engine/sqlite/src/select.cpp
author Sebastian Brannstrom <sebastianb@symbian.org>
Sat, 23 Oct 2010 17:11:38 +0100
branch3rded
changeset 278 e6aa20533d01
parent 2 29cda98b007e
permissions -rw-r--r--
Merged fix for 3843
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 file contains C code routines that are called by the parser
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    13
** to handle SELECT statements in SQLite.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    14
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    15
** $Id: select.cpp 1282 2008-11-13 09:31:33Z LarsPson $
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    16
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    17
#include "sqliteInt.h"
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
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
** Delete all the content of a Select structure but do not deallocate
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    22
** the select structure itself.
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
static void clearSelect(Select *p){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    25
  sqlite3ExprListDelete(p->pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    26
  sqlite3SrcListDelete(p->pSrc);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    27
  sqlite3ExprDelete(p->pWhere);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    28
  sqlite3ExprListDelete(p->pGroupBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    29
  sqlite3ExprDelete(p->pHaving);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    30
  sqlite3ExprListDelete(p->pOrderBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    31
  sqlite3SelectDelete(p->pPrior);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    32
  sqlite3ExprDelete(p->pLimit);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    33
  sqlite3ExprDelete(p->pOffset);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    34
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    35
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    36
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
** Allocate a new Select structure and return a pointer to that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    39
** structure.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    40
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    41
Select *sqlite3SelectNew(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    42
  Parse *pParse,        /* Parsing context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    43
  ExprList *pEList,     /* which columns to include in the result */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    44
  SrcList *pSrc,        /* the FROM clause -- which tables to scan */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    45
  Expr *pWhere,         /* the WHERE clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    46
  ExprList *pGroupBy,   /* the GROUP BY clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    47
  Expr *pHaving,        /* the HAVING clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    48
  ExprList *pOrderBy,   /* the ORDER BY clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    49
  int isDistinct,       /* true if the DISTINCT keyword is present */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    50
  Expr *pLimit,         /* LIMIT value.  NULL means not used */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    51
  Expr *pOffset         /* OFFSET value.  NULL means no offset */
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
  Select *pNew;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    54
  Select standin;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    55
  sqlite3 *db = pParse->db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    56
  pNew = (Select*)sqlite3DbMallocZero(db, sizeof(*pNew) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    57
  assert( !pOffset || pLimit );   /* Can't have OFFSET without LIMIT. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    58
  if( pNew==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    59
    pNew = &standin;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    60
    memset(pNew, 0, sizeof(*pNew));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    61
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    62
  if( pEList==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    63
    pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0,0,0), 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    64
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    65
  pNew->pEList = pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    66
  pNew->pSrc = pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    67
  pNew->pWhere = pWhere;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    68
  pNew->pGroupBy = pGroupBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    69
  pNew->pHaving = pHaving;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    70
  pNew->pOrderBy = pOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    71
  pNew->isDistinct = isDistinct;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    72
  pNew->op = TK_SELECT;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    73
  assert( pOffset==0 || pLimit!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    74
  pNew->pLimit = pLimit;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    75
  pNew->pOffset = pOffset;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    76
  pNew->iLimit = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    77
  pNew->iOffset = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    78
  pNew->addrOpenEphm[0] = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    79
  pNew->addrOpenEphm[1] = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    80
  pNew->addrOpenEphm[2] = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    81
  if( pNew==&standin) {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    82
    clearSelect(pNew);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    83
    pNew = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    84
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    85
  return pNew;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    86
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    87
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
** Delete the given Select structure and all of its substructures.
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
void sqlite3SelectDelete(Select *p){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    92
  if( p ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    93
    clearSelect(p);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    94
    sqlite3_free(p);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    95
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    96
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    97
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
** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   100
** type of join.  Return an integer constant that expresses that type
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   101
** in terms of the following bit values:
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
**     JT_INNER
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   104
**     JT_CROSS
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   105
**     JT_OUTER
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   106
**     JT_NATURAL
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   107
**     JT_LEFT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   108
**     JT_RIGHT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   109
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   110
** A full outer join is the combination of JT_LEFT and JT_RIGHT.
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
** If an illegal or unsupported join type is seen, then still return
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   113
** a join type, but put an error in the pParse structure.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   114
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   115
int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   116
  int jointype = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   117
  Token *apAll[3];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   118
  Token *p;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   119
  static const struct {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   120
    const char zKeyword[8];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   121
    u8 nChar;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   122
    u8 code;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   123
  } keywords[] = {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   124
    { "natural", 7, JT_NATURAL },
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   125
    { "left",    4, JT_LEFT|JT_OUTER },
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   126
    { "right",   5, JT_RIGHT|JT_OUTER },
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   127
    { "full",    4, JT_LEFT|JT_RIGHT|JT_OUTER },
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   128
    { "outer",   5, JT_OUTER },
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   129
    { "inner",   5, JT_INNER },
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   130
    { "cross",   5, JT_INNER|JT_CROSS },
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   131
  };
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   132
  int i, j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   133
  apAll[0] = pA;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   134
  apAll[1] = pB;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   135
  apAll[2] = pC;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   136
  for(i=0; i<3 && apAll[i]; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   137
    p = apAll[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   138
    for(j=0; j<sizeof(keywords)/sizeof(keywords[0]); j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   139
      if( p->n==keywords[j].nChar 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   140
          && sqlite3StrNICmp((char*)p->z, keywords[j].zKeyword, p->n)==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   141
        jointype |= keywords[j].code;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   142
        break;
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
    if( j>=sizeof(keywords)/sizeof(keywords[0]) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   146
      jointype |= JT_ERROR;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   147
      break;
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
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   150
  if(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   151
     (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) ||
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   152
     (jointype & JT_ERROR)!=0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   153
  ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   154
    const char *zSp1 = " ";
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   155
    const char *zSp2 = " ";
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   156
    if( pB==0 ){ zSp1++; }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   157
    if( pC==0 ){ zSp2++; }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   158
    sqlite3ErrorMsg(pParse, "unknown or unsupported join type: "
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   159
       "%T%s%T%s%T", pA, zSp1, pB, zSp2, pC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   160
    jointype = JT_INNER;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   161
  }else if( jointype & JT_RIGHT ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   162
    sqlite3ErrorMsg(pParse, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   163
      "RIGHT and FULL OUTER JOINs are not currently supported");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   164
    jointype = JT_INNER;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   165
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   166
  return jointype;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   167
}
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
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   170
** Return the index of a column in a table.  Return -1 if the column
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   171
** is not contained in the table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   172
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   173
static int columnIndex(Table *pTab, const char *zCol){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   174
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   175
  for(i=0; i<pTab->nCol; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   176
    if( sqlite3StrICmp(pTab->aCol[i].zName, zCol)==0 ) return i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   177
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   178
  return -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   179
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   180
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
** Set the value of a token to a '\000'-terminated string.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   183
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   184
static void setToken(Token *p, const char *z){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   185
  p->z = (u8*)z;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   186
  p->n = z ? strlen(z) : 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   187
  p->dyn = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   188
}
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
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   191
** Set the token to the double-quoted and escaped version of the string pointed
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   192
** to by z. For example;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   193
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   194
**    {a"bc}  ->  {"a""bc"}
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
static void setQuotedToken(Parse *pParse, Token *p, const char *z){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   197
  p->z = (u8 *)sqlite3MPrintf(0, "\"%w\"", z);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   198
  p->dyn = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   199
  if( p->z ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   200
    p->n = strlen((char *)p->z);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   201
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   202
    pParse->db->mallocFailed = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   203
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   204
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   205
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   206
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   207
** Create an expression node for an identifier with the name of zName
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
Expr *sqlite3CreateIdExpr(Parse *pParse, const char *zName){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   210
  Token dummy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   211
  setToken(&dummy, zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   212
  return sqlite3PExpr(pParse, TK_ID, 0, 0, &dummy);
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   216
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   217
** Add a term to the WHERE expression in *ppExpr that requires the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   218
** zCol column to be equal in the two tables pTab1 and pTab2.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   219
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   220
static void addWhereTerm(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   221
  Parse *pParse,           /* Parsing context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   222
  const char *zCol,        /* Name of the column */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   223
  const Table *pTab1,      /* First table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   224
  const char *zAlias1,     /* Alias for first table.  May be NULL */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   225
  const Table *pTab2,      /* Second table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   226
  const char *zAlias2,     /* Alias for second table.  May be NULL */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   227
  int iRightJoinTable,     /* VDBE cursor for the right table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   228
  Expr **ppExpr            /* Add the equality term to this expression */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   229
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   230
  Expr *pE1a, *pE1b, *pE1c;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   231
  Expr *pE2a, *pE2b, *pE2c;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   232
  Expr *pE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   233
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   234
  pE1a = sqlite3CreateIdExpr(pParse, zCol);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   235
  pE2a = sqlite3CreateIdExpr(pParse, zCol);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   236
  if( zAlias1==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   237
    zAlias1 = pTab1->zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   238
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   239
  pE1b = sqlite3CreateIdExpr(pParse, zAlias1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   240
  if( zAlias2==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   241
    zAlias2 = pTab2->zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   242
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   243
  pE2b = sqlite3CreateIdExpr(pParse, zAlias2);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   244
  pE1c = sqlite3PExpr(pParse, TK_DOT, pE1b, pE1a, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   245
  pE2c = sqlite3PExpr(pParse, TK_DOT, pE2b, pE2a, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   246
  pE = sqlite3PExpr(pParse, TK_EQ, pE1c, pE2c, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   247
  if( pE ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   248
    ExprSetProperty(pE, EP_FromJoin);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   249
    pE->iRightJoinTable = iRightJoinTable;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   250
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   251
  *ppExpr = sqlite3ExprAnd(pParse->db,*ppExpr, pE);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   252
}
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
** Set the EP_FromJoin property on all terms of the given expression.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   256
** And set the Expr.iRightJoinTable to iTable for every term in the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   257
** expression.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   258
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   259
** The EP_FromJoin property is used on terms of an expression to tell
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   260
** the LEFT OUTER JOIN processing logic that this term is part of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   261
** join restriction specified in the ON or USING clause and not a part
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   262
** of the more general WHERE clause.  These terms are moved over to the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   263
** WHERE clause during join processing but we need to remember that they
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   264
** originated in the ON or USING clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   265
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   266
** The Expr.iRightJoinTable tells the WHERE clause processing that the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   267
** expression depends on table iRightJoinTable even if that table is not
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   268
** explicitly mentioned in the expression.  That information is needed
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   269
** for cases like this:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   270
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   271
**    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   272
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   273
** The where clause needs to defer the handling of the t1.x=5
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   274
** term until after the t2 loop of the join.  In that way, a
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   275
** NULL t2 row will be inserted whenever t1.x!=5.  If we do not
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   276
** defer the handling of t1.x=5, it will be processed immediately
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   277
** after the t1 loop and rows with t1.x!=5 will never appear in
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   278
** the output, which is incorrect.
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
static void setJoinExpr(Expr *p, int iTable){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   281
  while( p ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   282
    ExprSetProperty(p, EP_FromJoin);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   283
    p->iRightJoinTable = iTable;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   284
    setJoinExpr(p->pLeft, iTable);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   285
    p = p->pRight;
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   289
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   290
** This routine processes the join information for a SELECT statement.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   291
** ON and USING clauses are converted into extra terms of the WHERE clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   292
** NATURAL joins also create extra WHERE clause terms.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   293
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   294
** The terms of a FROM clause are contained in the Select.pSrc structure.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   295
** The left most table is the first entry in Select.pSrc.  The right-most
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   296
** table is the last entry.  The join operator is held in the entry to
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   297
** the left.  Thus entry 0 contains the join operator for the join between
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   298
** entries 0 and 1.  Any ON or USING clauses associated with the join are
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   299
** also attached to the left entry.
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
** This routine returns the number of errors encountered.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   302
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   303
static int sqliteProcessJoin(Parse *pParse, Select *p){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   304
  SrcList *pSrc;                  /* All tables in the FROM clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   305
  int i, j;                       /* Loop counters */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   306
  SrcList::SrcList_item *pLeft;     /* Left table being joined */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   307
  SrcList::SrcList_item *pRight;    /* Right table being joined */
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
  pSrc = p->pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   310
  pLeft = &pSrc->a[0];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   311
  pRight = &pLeft[1];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   312
  for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   313
    Table *pLeftTab = pLeft->pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   314
    Table *pRightTab = pRight->pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   315
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   316
    if( pLeftTab==0 || pRightTab==0 ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   317
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   318
    /* When the NATURAL keyword is present, add WHERE clause terms for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   319
    ** every column that the two tables have in common.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   320
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   321
    if( pRight->jointype & JT_NATURAL ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   322
      if( pRight->pOn || pRight->pUsing ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   323
        sqlite3ErrorMsg(pParse, "a NATURAL join may not have "
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   324
           "an ON or USING clause", 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   325
        return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   326
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   327
      for(j=0; j<pLeftTab->nCol; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   328
        char *zName = pLeftTab->aCol[j].zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   329
        if( columnIndex(pRightTab, zName)>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   330
          addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   331
                              pRightTab, pRight->zAlias,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   332
                              pRight->iCursor, &p->pWhere);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   333
          
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   334
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   335
      }
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   338
    /* Disallow both ON and USING clauses in the same join
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   339
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   340
    if( pRight->pOn && pRight->pUsing ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   341
      sqlite3ErrorMsg(pParse, "cannot have both ON and USING "
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   342
        "clauses in the same join");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   343
      return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   344
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   345
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   346
    /* Add the ON clause to the end of the WHERE clause, connected by
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   347
    ** an AND operator.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   348
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   349
    if( pRight->pOn ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   350
      setJoinExpr(pRight->pOn, pRight->iCursor);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   351
      p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   352
      pRight->pOn = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   353
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   354
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   355
    /* Create extra terms on the WHERE clause for each column named
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   356
    ** in the USING clause.  Example: If the two tables to be joined are 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   357
    ** A and B and the USING clause names X, Y, and Z, then add this
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   358
    ** to the WHERE clause:    A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   359
    ** Report an error if any column mentioned in the USING clause is
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   360
    ** not contained in both tables to be joined.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   361
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   362
    if( pRight->pUsing ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   363
      IdList *pList = pRight->pUsing;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   364
      for(j=0; j<pList->nId; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   365
        char *zName = pList->a[j].zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   366
        if( columnIndex(pLeftTab, zName)<0 || columnIndex(pRightTab, zName)<0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   367
          sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   368
            "not present in both tables", zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   369
          return 1;
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
        addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   372
                            pRightTab, pRight->zAlias,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   373
                            pRight->iCursor, &p->pWhere);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   374
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   375
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   376
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   377
  return 0;
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
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   381
** Insert code into "v" that will push the record on the top of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   382
** stack into the sorter.
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
static void pushOntoSorter(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   385
  Parse *pParse,         /* Parser context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   386
  ExprList *pOrderBy,    /* The ORDER BY clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   387
  Select *pSelect        /* The whole SELECT statement */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   388
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   389
  Vdbe *v = pParse->pVdbe;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   390
  sqlite3ExprCodeExprList(pParse, pOrderBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   391
  sqlite3VdbeAddOp(v, OP_Sequence, pOrderBy->iECursor, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   392
  sqlite3VdbeAddOp(v, OP_Pull, pOrderBy->nExpr + 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   393
  sqlite3VdbeAddOp(v, OP_MakeRecord, pOrderBy->nExpr + 2, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   394
  sqlite3VdbeAddOp(v, OP_IdxInsert, pOrderBy->iECursor, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   395
  if( pSelect->iLimit>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   396
    int addr1, addr2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   397
    addr1 = sqlite3VdbeAddOp(v, OP_IfMemZero, pSelect->iLimit+1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   398
    sqlite3VdbeAddOp(v, OP_MemIncr, -1, pSelect->iLimit+1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   399
    addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   400
    sqlite3VdbeJumpHere(v, addr1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   401
    sqlite3VdbeAddOp(v, OP_Last, pOrderBy->iECursor, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   402
    sqlite3VdbeAddOp(v, OP_Delete, pOrderBy->iECursor, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   403
    sqlite3VdbeJumpHere(v, addr2);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   404
    pSelect->iLimit = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   405
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   406
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   407
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   408
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   409
** Add code to implement the OFFSET
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   410
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   411
static void codeOffset(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   412
  Vdbe *v,          /* Generate code into this VM */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   413
  Select *p,        /* The SELECT statement being coded */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   414
  int iContinue,    /* Jump here to skip the current record */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   415
  int nPop          /* Number of times to pop stack when jumping */
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
  if( p->iOffset>=0 && iContinue!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   418
    int addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   419
    sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iOffset);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   420
    addr = sqlite3VdbeAddOp(v, OP_IfMemNeg, p->iOffset, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   421
    if( nPop>0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   422
      sqlite3VdbeAddOp(v, OP_Pop, nPop, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   423
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   424
    sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   425
    VdbeComment((v, "# skip OFFSET records"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   426
    sqlite3VdbeJumpHere(v, addr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   427
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   428
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   429
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   430
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   431
** Add code that will check to make sure the top N elements of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   432
** stack are distinct.  iTab is a sorting index that holds previously
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   433
** seen combinations of the N values.  A new entry is made in iTab
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   434
** if the current N values are new.
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
** A jump to addrRepeat is made and the N+1 values are popped from the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   437
** stack if the top N elements are not distinct.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   438
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   439
static void codeDistinct(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   440
  Vdbe *v,           /* Generate code into this VM */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   441
  int iTab,          /* A sorting index used to test for distinctness */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   442
  int addrRepeat,    /* Jump to here if not distinct */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   443
  int N              /* The top N elements of the stack must be distinct */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   444
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   445
  sqlite3VdbeAddOp(v, OP_MakeRecord, -N, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   446
  sqlite3VdbeAddOp(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   447
  sqlite3VdbeAddOp(v, OP_Pop, N+1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   448
  sqlite3VdbeAddOp(v, OP_Goto, 0, addrRepeat);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   449
  VdbeComment((v, "# skip indistinct records"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   450
  sqlite3VdbeAddOp(v, OP_IdxInsert, iTab, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   451
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   452
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   453
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   454
** Generate an error message when a SELECT is used within a subexpression
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   455
** (example:  "a IN (SELECT * FROM table)") but it has more than 1 result
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   456
** column.  We do this in a subroutine because the error occurs in multiple
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   457
** places.
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
static int checkForMultiColumnSelectError(Parse *pParse, int eDest, int nExpr){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   460
  if( nExpr>1 && (eDest==SRT_Mem || eDest==SRT_Set) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   461
    sqlite3ErrorMsg(pParse, "only a single result allowed for "
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   462
       "a SELECT that is part of an expression");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   463
    return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   464
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   465
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   466
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   467
}
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
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   470
** This routine generates the code for the inside of the inner loop
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   471
** of a SELECT.
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
** If srcTab and nColumn are both zero, then the pEList expressions
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   474
** are evaluated in order to get the data for this row.  If nColumn>0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   475
** then data is pulled from srcTab and pEList is used only to get the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   476
** datatypes for each column.
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
static int selectInnerLoop(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   479
  Parse *pParse,          /* The parser context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   480
  Select *p,              /* The complete select statement being coded */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   481
  ExprList *pEList,       /* List of values being extracted */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   482
  int srcTab,             /* Pull data from this table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   483
  int nColumn,            /* Number of columns in the source table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   484
  ExprList *pOrderBy,     /* If not NULL, sort results using this key */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   485
  int distinct,           /* If >=0, make sure results are distinct */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   486
  int eDest,              /* How to dispose of the results */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   487
  int iParm,              /* An argument to the disposal method */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   488
  int iContinue,          /* Jump here to continue with next row */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   489
  int iBreak,             /* Jump here to break out of the inner loop */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   490
  char *aff               /* affinity string if eDest is SRT_Union */
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
  Vdbe *v = pParse->pVdbe;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   493
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   494
  int hasDistinct;        /* True if the DISTINCT keyword is present */
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
  if( v==0 ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   497
  assert( pEList!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   498
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   499
  /* If there was a LIMIT clause on the SELECT statement, then do the check
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   500
  ** to see if this row should be output.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   501
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   502
  hasDistinct = distinct>=0 && pEList->nExpr>0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   503
  if( pOrderBy==0 && !hasDistinct ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   504
    codeOffset(v, p, iContinue, 0);
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
  /* Pull the requested columns.
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
  if( nColumn>0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   510
    for(i=0; i<nColumn; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   511
      sqlite3VdbeAddOp(v, OP_Column, srcTab, i);
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
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   514
    nColumn = pEList->nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   515
    sqlite3ExprCodeExprList(pParse, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   516
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   517
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   518
  /* If the DISTINCT keyword was present on the SELECT statement
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   519
  ** and this row has been seen before, then do not make this row
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   520
  ** part of the result.
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
  if( hasDistinct ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   523
    assert( pEList!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   524
    assert( pEList->nExpr==nColumn );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   525
    codeDistinct(v, distinct, iContinue, nColumn);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   526
    if( pOrderBy==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   527
      codeOffset(v, p, iContinue, nColumn);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   528
    }
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   531
  if( checkForMultiColumnSelectError(pParse, eDest, pEList->nExpr) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   532
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   533
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   534
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   535
  switch( eDest ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   536
    /* In this mode, write each query result to the key of the temporary
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   537
    ** table iParm.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   538
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   539
#ifndef SQLITE_OMIT_COMPOUND_SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   540
    case SRT_Union: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   541
      sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   542
      if( aff ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   543
        sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   544
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   545
      sqlite3VdbeAddOp(v, OP_IdxInsert, iParm, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   546
      break;
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   549
    /* Construct a record from the query result, but instead of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   550
    ** saving that record, use it as a key to delete elements from
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   551
    ** the temporary table iParm.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   552
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   553
    case SRT_Except: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   554
      int addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   555
      addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   556
      sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   557
      sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   558
      sqlite3VdbeAddOp(v, OP_Delete, iParm, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   559
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   560
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   561
#endif
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
    /* Store the result as data using a unique key.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   564
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   565
    case SRT_Table:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   566
    case SRT_EphemTab: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   567
      sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   568
      if( pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   569
        pushOntoSorter(pParse, pOrderBy, p);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   570
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   571
        sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   572
        sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   573
        sqlite3VdbeAddOp(v, OP_Insert, iParm, OPFLAG_APPEND);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   574
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   575
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   576
    }
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
#ifndef SQLITE_OMIT_SUBQUERY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   579
    /* If we are creating a set for an "expr IN (SELECT ...)" construct,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   580
    ** then there should be a single item on the stack.  Write this
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   581
    ** item into the set table with bogus data.
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
    case SRT_Set: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   584
      int addr1 = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   585
      int addr2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   586
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   587
      assert( nColumn==1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   588
      sqlite3VdbeAddOp(v, OP_NotNull, -1, addr1+3);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   589
      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   590
      addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   591
      p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr,(iParm>>16)&0xff);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   592
      if( pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   593
        /* At first glance you would think we could optimize out the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   594
        ** ORDER BY in this case since the order of entries in the set
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   595
        ** does not matter.  But there might be a LIMIT clause, in which
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   596
        ** case the order does matter */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   597
        pushOntoSorter(pParse, pOrderBy, p);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   598
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   599
        sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &p->affinity, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   600
        sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
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
      sqlite3VdbeJumpHere(v, addr2);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   603
      break;
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   606
    /* If any row exist in the result set, record that fact and abort.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   607
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   608
    case SRT_Exists: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   609
      sqlite3VdbeAddOp(v, OP_MemInt, 1, iParm);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   610
      sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   611
      /* The LIMIT clause will terminate the loop for us */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   612
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   613
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   614
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   615
    /* If this is a scalar select that is part of an expression, then
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   616
    ** store the results in the appropriate memory cell and break out
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   617
    ** of the scan loop.
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
    case SRT_Mem: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   620
      assert( nColumn==1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   621
      if( pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   622
        pushOntoSorter(pParse, pOrderBy, p);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   623
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   624
        sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   625
        /* The LIMIT clause will jump out of the loop for us */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   626
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   627
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   628
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   629
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   630
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   631
    /* Send the data to the callback function or to a subroutine.  In the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   632
    ** case of a subroutine, the subroutine itself is responsible for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   633
    ** popping the data from the stack.
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
    case SRT_Subroutine:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   636
    case SRT_Callback: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   637
      if( pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   638
        sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   639
        pushOntoSorter(pParse, pOrderBy, p);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   640
      }else if( eDest==SRT_Subroutine ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   641
        sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   642
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   643
        sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   644
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   645
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   646
    }
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
#if !defined(SQLITE_OMIT_TRIGGER)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   649
    /* Discard the results.  This is used for SELECT statements inside
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   650
    ** the body of a TRIGGER.  The purpose of such selects is to call
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   651
    ** user-defined functions that have side effects.  We do not care
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   652
    ** about the actual results of the select.
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
    default: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   655
      assert( eDest==SRT_Discard );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   656
      sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   657
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   658
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   659
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   660
  }
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
  /* Jump to the end of the loop if the LIMIT is reached.
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
  if( p->iLimit>=0 && pOrderBy==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   665
    sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   666
    sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, iBreak);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   667
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   668
  return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   669
}
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
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   672
** Given an expression list, generate a KeyInfo structure that records
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   673
** the collating sequence for each expression in that expression list.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   674
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   675
** If the ExprList is an ORDER BY or GROUP BY clause then the resulting
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   676
** KeyInfo structure is appropriate for initializing a virtual index to
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   677
** implement that clause.  If the ExprList is the result set of a SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   678
** then the KeyInfo structure is appropriate for initializing a virtual
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   679
** index to implement a DISTINCT test.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   680
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   681
** Space to hold the KeyInfo structure is obtain from malloc.  The calling
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   682
** function is responsible for seeing that this structure is eventually
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   683
** freed.  Add the KeyInfo structure to the P3 field of an opcode using
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   684
** P3_KEYINFO_HANDOFF is the usual way of dealing with this.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   685
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   686
static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   687
  sqlite3 *db = pParse->db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   688
  int nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   689
  KeyInfo *pInfo;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   690
  ExprList::ExprList_item *pItem;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   691
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   692
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   693
  nExpr = pList->nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   694
  pInfo = (KeyInfo*)sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   695
  if( pInfo ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   696
    pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   697
    pInfo->nField = nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   698
    pInfo->enc = ENC(db);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   699
    for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   700
      CollSeq *pColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   701
      pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   702
      if( !pColl ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   703
        pColl = db->pDfltColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   704
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   705
      pInfo->aColl[i] = pColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   706
      pInfo->aSortOrder[i] = pItem->sortOrder;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   707
    }
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
  return pInfo;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   710
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   711
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   712
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
** If the inner loop was generated using a non-null pOrderBy argument,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   715
** then the results were placed in a sorter.  After the loop is terminated
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   716
** we need to run the sorter and output the results.  The following
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   717
** routine generates the code needed to do that.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   718
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   719
static void generateSortTail(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   720
  Parse *pParse,   /* Parsing context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   721
  Select *p,       /* The SELECT statement */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   722
  Vdbe *v,         /* Generate code into this VDBE */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   723
  int nColumn,     /* Number of columns of data */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   724
  int eDest,       /* Write the sorted results here */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   725
  int iParm        /* Optional parameter associated with eDest */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   726
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   727
  int brk = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   728
  int cont = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   729
  int addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   730
  int iTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   731
  int pseudoTab = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   732
  ExprList *pOrderBy = p->pOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   733
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   734
  iTab = pOrderBy->iECursor;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   735
  if( eDest==SRT_Callback || eDest==SRT_Subroutine ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   736
    pseudoTab = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   737
    sqlite3VdbeAddOp(v, OP_OpenPseudo, pseudoTab, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   738
    sqlite3VdbeAddOp(v, OP_SetNumColumns, pseudoTab, nColumn);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   739
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   740
  addr = 1 + sqlite3VdbeAddOp(v, OP_Sort, iTab, brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   741
  codeOffset(v, p, cont, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   742
  if( eDest==SRT_Callback || eDest==SRT_Subroutine ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   743
    sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   744
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   745
  sqlite3VdbeAddOp(v, OP_Column, iTab, pOrderBy->nExpr + 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   746
  switch( eDest ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   747
    case SRT_Table:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   748
    case SRT_EphemTab: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   749
      sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   750
      sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   751
      sqlite3VdbeAddOp(v, OP_Insert, iParm, OPFLAG_APPEND);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   752
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   753
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   754
#ifndef SQLITE_OMIT_SUBQUERY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   755
    case SRT_Set: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   756
      assert( nColumn==1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   757
      sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   758
      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   759
      sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   760
      sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &p->affinity, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   761
      sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   762
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   763
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   764
    case SRT_Mem: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   765
      assert( nColumn==1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   766
      sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   767
      /* The LIMIT clause will terminate the loop for us */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   768
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   769
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   770
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   771
    case SRT_Callback:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   772
    case SRT_Subroutine: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   773
      int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   774
      sqlite3VdbeAddOp(v, OP_Insert, pseudoTab, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   775
      for(i=0; i<nColumn; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   776
        sqlite3VdbeAddOp(v, OP_Column, pseudoTab, i);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   777
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   778
      if( eDest==SRT_Callback ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   779
        sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   780
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   781
        sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   782
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   783
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   784
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   785
    default: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   786
      /* Do nothing */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   787
      break;
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
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   790
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   791
  /* Jump to the end of the loop when the LIMIT is reached
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
  if( p->iLimit>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   794
    sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   795
    sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   796
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   797
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   798
  /* The bottom of the loop
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   799
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   800
  sqlite3VdbeResolveLabel(v, cont);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   801
  sqlite3VdbeAddOp(v, OP_Next, iTab, addr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   802
  sqlite3VdbeResolveLabel(v, brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   803
  if( eDest==SRT_Callback || eDest==SRT_Subroutine ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   804
    sqlite3VdbeAddOp(v, OP_Close, pseudoTab, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   805
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   806
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   807
}
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
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   810
** Return a pointer to a string containing the 'declaration type' of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   811
** expression pExpr. The string may be treated as static by the caller.
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
** The declaration type is the exact datatype definition extracted from the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   814
** original CREATE TABLE statement if the expression is a column. The
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   815
** declaration type for a ROWID field is INTEGER. Exactly when an expression
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   816
** is considered a column can be complex in the presence of subqueries. The
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   817
** result-set expression in all of the following SELECT statements is 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   818
** considered a column by this function.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   819
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   820
**   SELECT col FROM tbl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   821
**   SELECT (SELECT col FROM tbl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   822
**   SELECT (SELECT col FROM tbl);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   823
**   SELECT abc FROM (SELECT col AS abc FROM tbl);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   824
** 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   825
** The declaration type for any expression other than a column is NULL.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   826
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   827
static const char *columnType(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   828
  NameContext *pNC, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   829
  Expr *pExpr,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   830
  const char **pzOriginDb,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   831
  const char **pzOriginTab,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   832
  const char **pzOriginCol
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   833
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   834
  char const *zType = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   835
  char const *zOriginDb = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   836
  char const *zOriginTab = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   837
  char const *zOriginCol = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   838
  int j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   839
  if( pExpr==0 || pNC->pSrcList==0 ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   840
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   841
  switch( pExpr->op ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   842
    case TK_AGG_COLUMN:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   843
    case TK_COLUMN: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   844
      /* The expression is a column. Locate the table the column is being
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   845
      ** extracted from in NameContext.pSrcList. This table may be real
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   846
      ** database table or a subquery.
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
      Table *pTab = 0;            /* Table structure column is extracted from */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   849
      Select *pS = 0;             /* Select the column is extracted from */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   850
      int iCol = pExpr->iColumn;  /* Index of column in pTab */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   851
      while( pNC && !pTab ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   852
        SrcList *pTabList = pNC->pSrcList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   853
        for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   854
        if( j<pTabList->nSrc ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   855
          pTab = pTabList->a[j].pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   856
          pS = pTabList->a[j].pSelect;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   857
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   858
          pNC = pNC->pNext;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   859
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   860
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   861
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   862
      if( pTab==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   863
        /* FIX ME:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   864
        ** This can occurs if you have something like "SELECT new.x;" inside
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   865
        ** a trigger.  In other words, if you reference the special "new"
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   866
        ** table in the result set of a select.  We do not have a good way
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   867
        ** to find the actual table type, so call it "TEXT".  This is really
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   868
        ** something of a bug, but I do not know how to fix it.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   869
        **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   870
        ** This code does not produce the correct answer - it just prevents
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   871
        ** a segfault.  See ticket #1229.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   872
        */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   873
        zType = "TEXT";
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   874
        break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   875
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   876
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   877
      assert( pTab );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   878
      if( pS ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   879
        /* The "table" is actually a sub-select or a view in the FROM clause
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   880
        ** of the SELECT statement. Return the declaration type and origin
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   881
        ** data for the result-set column of the sub-select.
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
        if( iCol>=0 && iCol<pS->pEList->nExpr ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   884
          /* If iCol is less than zero, then the expression requests the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   885
          ** rowid of the sub-select or view. This expression is legal (see 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   886
          ** test case misc2.2.2) - it always evaluates to NULL.
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
          NameContext sNC;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   889
          Expr *p = pS->pEList->a[iCol].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   890
          sNC.pSrcList = pS->pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   891
          sNC.pNext = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   892
          sNC.pParse = pNC->pParse;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   893
          zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   894
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   895
      }else if( pTab->pSchema ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   896
        /* A real table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   897
        assert( !pS );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   898
        if( iCol<0 ) iCol = pTab->iPKey;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   899
        assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   900
        if( iCol<0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   901
          zType = "INTEGER";
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   902
          zOriginCol = "rowid";
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   903
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   904
          zType = pTab->aCol[iCol].zType;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   905
          zOriginCol = pTab->aCol[iCol].zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   906
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   907
        zOriginTab = pTab->zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   908
        if( pNC->pParse ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   909
          int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   910
          zOriginDb = pNC->pParse->db->aDb[iDb].zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   911
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   912
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   913
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   914
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   915
#ifndef SQLITE_OMIT_SUBQUERY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   916
    case TK_SELECT: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   917
      /* The expression is a sub-select. Return the declaration type and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   918
      ** origin info for the single column in the result set of the SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   919
      ** statement.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   920
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   921
      NameContext sNC;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   922
      Select *pS = pExpr->pSelect;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   923
      Expr *p = pS->pEList->a[0].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   924
      sNC.pSrcList = pS->pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   925
      sNC.pNext = pNC;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   926
      sNC.pParse = pNC->pParse;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   927
      zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   928
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   929
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   930
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   931
  }
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( pzOriginDb ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   934
    assert( pzOriginTab && pzOriginCol );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   935
    *pzOriginDb = zOriginDb;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   936
    *pzOriginTab = zOriginTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   937
    *pzOriginCol = zOriginCol;
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
  return zType;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   940
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   941
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   942
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   943
** Generate code that will tell the VDBE the declaration types of columns
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   944
** in the result set.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   945
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   946
static void generateColumnTypes(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   947
  Parse *pParse,      /* Parser context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   948
  SrcList *pTabList,  /* List of tables */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   949
  ExprList *pEList    /* Expressions defining the result set */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   950
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   951
  Vdbe *v = pParse->pVdbe;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   952
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   953
  NameContext sNC;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   954
  sNC.pSrcList = pTabList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   955
  sNC.pParse = pParse;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   956
  for(i=0; i<pEList->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   957
    Expr *p = pEList->a[i].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   958
    const char *zOrigDb = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   959
    const char *zOrigTab = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   960
    const char *zOrigCol = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   961
    const char *zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
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
    /* The vdbe must make its own copy of the column-type and other 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   964
    ** column specific strings, in case the schema is reset before this
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   965
    ** virtual machine is deleted.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   966
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   967
    sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P3_TRANSIENT);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   968
    sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, P3_TRANSIENT);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   969
    sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, P3_TRANSIENT);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   970
    sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, P3_TRANSIENT);
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
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   973
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   974
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   975
** Generate code that will tell the VDBE the names of columns
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   976
** in the result set.  This information is used to provide the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   977
** azCol[] values in the callback.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   978
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   979
static void generateColumnNames(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   980
  Parse *pParse,      /* Parser context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   981
  SrcList *pTabList,  /* List of tables */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   982
  ExprList *pEList    /* Expressions defining the result set */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   983
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   984
  Vdbe *v = pParse->pVdbe;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   985
  int i, j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   986
  sqlite3 *db = pParse->db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   987
  int fullNames, shortNames;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   988
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   989
#ifndef SQLITE_OMIT_EXPLAIN
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   990
  /* If this is an EXPLAIN, skip this step */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   991
  if( pParse->explain ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   992
    return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   993
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   994
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   995
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   996
  assert( v!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   997
  if( pParse->colNamesSet || v==0 || db->mallocFailed ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   998
  pParse->colNamesSet = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   999
  fullNames = (db->flags & SQLITE_FullColNames)!=0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1000
  shortNames = (db->flags & SQLITE_ShortColNames)!=0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1001
  sqlite3VdbeSetNumCols(v, pEList->nExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1002
  for(i=0; i<pEList->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1003
    Expr *p;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1004
    p = pEList->a[i].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1005
    if( p==0 ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1006
    if( pEList->a[i].zName ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1007
      char *zName = pEList->a[i].zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1008
      sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, strlen(zName));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1009
      continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1010
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1011
    if( p->op==TK_COLUMN && pTabList ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1012
      Table *pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1013
      char *zCol;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1014
      int iCol = p->iColumn;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1015
      for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1016
      assert( j<pTabList->nSrc );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1017
      pTab = pTabList->a[j].pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1018
      if( iCol<0 ) iCol = pTab->iPKey;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1019
      assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1020
      if( iCol<0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1021
        zCol = "rowid";
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1022
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1023
        zCol = pTab->aCol[iCol].zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1024
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1025
      if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1026
        sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1027
      }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1028
        char *zName = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1029
        char *zTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1030
 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1031
        zTab = pTabList->a[j].zAlias;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1032
        if( fullNames || zTab==0 ) zTab = pTab->zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1033
        sqlite3SetString(&zName, zTab, ".", zCol, (char*)0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1034
        sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, P3_DYNAMIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1035
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1036
        sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, strlen(zCol));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1037
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1038
    }else if( p->span.z && p->span.z[0] ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1039
      sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1040
      /* sqlite3VdbeCompressSpace(v, addr); */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1041
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1042
      char zName[30];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1043
      assert( p->op!=TK_COLUMN || pTabList==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1044
      sqlite3_snprintf(sizeof(zName), zName, "column%d", i+1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1045
      sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1046
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1047
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1048
  generateColumnTypes(pParse, pTabList, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1049
}
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
#ifndef SQLITE_OMIT_COMPOUND_SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1052
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1053
** Name of the connection operator, used for error messages.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1054
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1055
static const char *selectOpName(int id){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1056
  char *z;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1057
  switch( id ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1058
    case TK_ALL:       z = "UNION ALL";   break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1059
    case TK_INTERSECT: z = "INTERSECT";   break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1060
    case TK_EXCEPT:    z = "EXCEPT";      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1061
    default:           z = "UNION";       break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1062
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1063
  return z;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1064
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1065
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1066
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1067
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1068
** Forward declaration
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1069
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1070
static int prepSelectStmt(Parse*, Select*);
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
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1073
** Given a SELECT statement, generate a Table structure that describes
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1074
** the result set of that SELECT.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1075
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1076
Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1077
  Table *pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1078
  int i, j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1079
  ExprList *pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1080
  Column *aCol, *pCol;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1081
  sqlite3 *db = pParse->db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1082
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1083
  while( pSelect->pPrior ) pSelect = pSelect->pPrior;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1084
  if( prepSelectStmt(pParse, pSelect) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1085
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1086
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1087
  if( sqlite3SelectResolve(pParse, pSelect, 0) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1088
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1089
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1090
  pTab = (Table*)sqlite3DbMallocZero(db, sizeof(Table) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1091
  if( pTab==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1092
    return 0;
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
  pTab->nRef = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1095
  pTab->zName = zTabName ? sqlite3DbStrDup(db, zTabName) : 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1096
  pEList = pSelect->pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1097
  pTab->nCol = pEList->nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1098
  assert( pTab->nCol>0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1099
  pTab->aCol = aCol = (Column*)sqlite3DbMallocZero(db, sizeof(pTab->aCol[0])*pTab->nCol);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1100
  for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1101
    Expr *p, *pR;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1102
    char *zType;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1103
    char *zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1104
    int nName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1105
    CollSeq *pColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1106
    int cnt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1107
    NameContext sNC;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1108
    
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1109
    /* Get an appropriate name for the column
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1110
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1111
    p = pEList->a[i].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1112
    assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1113
    if( (zName = pEList->a[i].zName)!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1114
      /* If the column contains an "AS <name>" phrase, use <name> as the name */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1115
      zName = sqlite3DbStrDup(db, zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1116
    }else if( p->op==TK_DOT 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1117
              && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1118
      /* For columns of the from A.B use B as the name */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1119
      zName = sqlite3MPrintf(db, "%T", &pR->token);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1120
    }else if( p->span.z && p->span.z[0] ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1121
      /* Use the original text of the column expression as its name */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1122
      zName = sqlite3MPrintf(db, "%T", &p->span);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1123
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1124
      /* If all else fails, make up a name */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1125
      zName = sqlite3MPrintf(db, "column%d", i+1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1126
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1127
    if( !zName || db->mallocFailed ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1128
      db->mallocFailed = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1129
      sqlite3_free(zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1130
      sqlite3DeleteTable(pTab);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1131
      return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1132
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1133
    sqlite3Dequote(zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1134
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1135
    /* Make sure the column name is unique.  If the name is not unique,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1136
    ** append a integer to the name so that it becomes unique.
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
    nName = strlen(zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1139
    for(j=cnt=0; j<i; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1140
      if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1141
        zName[nName] = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1142
        zName = sqlite3MPrintf(db, "%z:%d", zName, ++cnt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1143
        j = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1144
        if( zName==0 ) break;
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
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1147
    pCol->zName = zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1148
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1149
    /* Get the typename, type affinity, and collating sequence for the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1150
    ** column.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1151
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1152
    memset(&sNC, 0, sizeof(sNC));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1153
    sNC.pSrcList = pSelect->pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1154
    zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1155
    pCol->zType = zType;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1156
    pCol->affinity = sqlite3ExprAffinity(p);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1157
    pColl = sqlite3ExprCollSeq(pParse, p);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1158
    if( pColl ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1159
      pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1160
    }
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
  pTab->iPKey = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1163
  return pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1164
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1165
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1166
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1167
** Prepare a SELECT statement for processing by doing the following
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1168
** things:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1169
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1170
**    (1)  Make sure VDBE cursor numbers have been assigned to every
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1171
**         element of the FROM clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1172
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1173
**    (2)  Fill in the pTabList->a[].pTab fields in the SrcList that 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1174
**         defines FROM clause.  When views appear in the FROM clause,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1175
**         fill pTabList->a[].pSelect with a copy of the SELECT statement
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1176
**         that implements the view.  A copy is made of the view's SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1177
**         statement so that we can freely modify or delete that statement
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1178
**         without worrying about messing up the presistent representation
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1179
**         of the view.
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
**    (3)  Add terms to the WHERE clause to accomodate the NATURAL keyword
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1182
**         on joins and the ON and USING clause of joins.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1183
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1184
**    (4)  Scan the list of columns in the result set (pEList) looking
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1185
**         for instances of the "*" operator or the TABLE.* operator.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1186
**         If found, expand each "*" to be every column in every table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1187
**         and TABLE.* to be every column in TABLE.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1188
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1189
** Return 0 on success.  If there are problems, leave an error message
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1190
** in pParse and return non-zero.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1191
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1192
static int prepSelectStmt(Parse *pParse, Select *p){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1193
  int i, j, k, rc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1194
  SrcList *pTabList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1195
  ExprList *pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1196
  SrcList::SrcList_item *pFrom;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1197
  sqlite3 *db = pParse->db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1198
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1199
  if( p==0 || p->pSrc==0 || db->mallocFailed ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1200
    return 1;
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
  pTabList = p->pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1203
  pEList = p->pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1204
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1205
  /* Make sure cursor numbers have been assigned to all entries in
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1206
  ** the FROM clause of the SELECT statement.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1207
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1208
  sqlite3SrcListAssignCursors(pParse, p->pSrc);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1209
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1210
  /* Look up every table named in the FROM clause of the select.  If
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1211
  ** an entry of the FROM clause is a subquery instead of a table or view,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1212
  ** then create a transient table structure to describe the subquery.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1213
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1214
     Table *pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1215
 for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1216
    if( pFrom->pTab!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1217
      /* This statement has already been prepared.  There is no need
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1218
      ** to go further. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1219
      assert( i==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1220
      return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1221
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1222
    if( pFrom->zName==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1223
#ifndef SQLITE_OMIT_SUBQUERY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1224
      /* A sub-query in the FROM clause of a SELECT */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1225
      assert( pFrom->pSelect!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1226
      if( pFrom->zAlias==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1227
        pFrom->zAlias =
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1228
          sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pFrom->pSelect);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1229
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1230
      assert( pFrom->pTab==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1231
      pFrom->pTab = pTab = 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1232
        sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1233
      if( pTab==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1234
        return 1;
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
      /* The isEphem flag indicates that the Table structure has been
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1237
      ** dynamically allocated and may be freed at any time.  In other words,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1238
      ** pTab is not pointing to a persistent table structure that defines
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1239
      ** part of the schema. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1240
      pTab->isEphem = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1241
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1242
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1243
      /* An ordinary table or view name in the FROM clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1244
      assert( pFrom->pTab==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1245
      pFrom->pTab = pTab = 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1246
        sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1247
      if( pTab==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1248
        return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1249
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1250
      pTab->nRef++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1251
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1252
      if( pTab->pSelect || IsVirtual(pTab) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1253
        /* We reach here if the named table is a really a view */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1254
        if( sqlite3ViewGetColumnNames(pParse, pTab) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1255
          return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1256
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1257
        /* If pFrom->pSelect!=0 it means we are dealing with a
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1258
        ** view within a view.  The SELECT structure has already been
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1259
        ** copied by the outer view so we can skip the copy step here
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1260
        ** in the inner view.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1261
        */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1262
        if( pFrom->pSelect==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1263
          pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect);
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
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1266
#endif
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
  /* Process NATURAL keywords, and ON and USING clauses of joins.
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
  if( sqliteProcessJoin(pParse, p) ) return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1273
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1274
  /* For every "*" that occurs in the column list, insert the names of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1275
  ** all columns in all tables.  And for every TABLE.* insert the names
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1276
  ** of all columns in TABLE.  The parser inserted a special expression
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1277
  ** with the TK_ALL operator for each "*" that it found in the column list.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1278
  ** The following code just has to locate the TK_ALL expressions and expand
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1279
  ** each one to the list of all columns in all tables.
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
  ** The first loop just checks to see if there are any "*" operators
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1282
  ** that need expanding.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1283
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1284
  for(k=0; k<pEList->nExpr; k++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1285
    Expr *pE = pEList->a[k].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1286
    if( pE->op==TK_ALL ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1287
    if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1288
         && pE->pLeft && pE->pLeft->op==TK_ID ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1289
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1290
  rc = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1291
  if( k<pEList->nExpr ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1292
    /*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1293
    ** If we get here it means the result set contains one or more "*"
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1294
    ** operators that need to be expanded.  Loop through each expression
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1295
    ** in the result set and expand them one by one.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1296
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1297
	  ExprList::ExprList_item *a = pEList->a;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1298
    ExprList *pNew = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1299
    int flags = pParse->db->flags;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1300
    int longNames = (flags & SQLITE_FullColNames)!=0 &&
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1301
                      (flags & SQLITE_ShortColNames)==0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1302
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1303
    for(k=0; k<pEList->nExpr; k++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1304
      Expr *pE = a[k].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1305
      if( pE->op!=TK_ALL &&
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1306
           (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1307
        /* This particular expression does not need to be expanded.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1308
        */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1309
        pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1310
        if( pNew ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1311
          pNew->a[pNew->nExpr-1].zName = a[k].zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1312
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1313
          rc = 1;
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
        a[k].pExpr = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1316
        a[k].zName = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1317
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1318
        /* This expression is a "*" or a "TABLE.*" and needs to be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1319
        ** expanded. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1320
        int tableSeen = 0;      /* Set to 1 when TABLE matches */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1321
        char *zTName;            /* text of name of TABLE */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1322
        if( pE->op==TK_DOT && pE->pLeft ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1323
          zTName = sqlite3NameFromToken(db, &pE->pLeft->token);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1324
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1325
          zTName = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1326
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1327
        for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1328
          Table *pTab = pFrom->pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1329
          char *zTabName = pFrom->zAlias;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1330
          if( zTabName==0 || zTabName[0]==0 ){ 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1331
            zTabName = pTab->zName;
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
          if( zTName && (zTabName==0 || zTabName[0]==0 || 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1334
                 sqlite3StrICmp(zTName, zTabName)!=0) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1335
            continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1336
          }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1337
          tableSeen = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1338
          for(j=0; j<pTab->nCol; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1339
            Expr *pExpr, *pRight;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1340
            char *zName = pTab->aCol[j].zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1341
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1342
            /* If a column is marked as 'hidden' (currently only possible
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1343
            ** for virtual tables), do not include it in the expanded
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1344
            ** result-set list.
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
            if( IsHiddenColumn(&pTab->aCol[j]) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1347
              assert(IsVirtual(pTab));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1348
              continue;
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1351
            if( i>0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1352
				SrcList::SrcList_item *pLeft = &pTabList->a[i-1];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1353
              if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1354
                        columnIndex(pLeft->pTab, zName)>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1355
                /* In a NATURAL join, omit the join columns from the 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1356
                ** table on the right */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1357
                continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1358
              }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1359
              if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1360
                /* In a join with a USING clause, omit columns in the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1361
                ** using clause from the table on the right. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1362
                continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1363
              }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1364
            }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1365
            pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1366
            if( pRight==0 ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1367
            setQuotedToken(pParse, &pRight->token, zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1368
            if( zTabName && (longNames || pTabList->nSrc>1) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1369
              Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1370
              pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1371
              if( pExpr==0 ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1372
              setQuotedToken(pParse, &pLeft->token, zTabName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1373
              setToken(&pExpr->span, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1374
                  sqlite3MPrintf(db, "%s.%s", zTabName, zName));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1375
              pExpr->span.dyn = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1376
              pExpr->token.z = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1377
              pExpr->token.n = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1378
              pExpr->token.dyn = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1379
            }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1380
              pExpr = pRight;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1381
              pExpr->span = pExpr->token;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1382
              pExpr->span.dyn = 0;
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
            if( longNames ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1385
              pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1386
            }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1387
              pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1388
            }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1389
          }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1390
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1391
        if( !tableSeen ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1392
          if( zTName ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1393
            sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1394
          }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1395
            sqlite3ErrorMsg(pParse, "no tables specified");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1396
          }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1397
          rc = 1;
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
        sqlite3_free(zTName);
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
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1402
    sqlite3ExprListDelete(pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1403
    p->pEList = pNew;
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
  if( p->pEList && p->pEList->nExpr>SQLITE_MAX_COLUMN ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1406
    sqlite3ErrorMsg(pParse, "too many columns in result set");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1407
    rc = SQLITE_ERROR;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1408
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1409
  if( db->mallocFailed ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1410
    rc = SQLITE_NOMEM;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1411
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1412
  return rc;
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1415
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1416
** pE is a pointer to an expression which is a single term in
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1417
** ORDER BY or GROUP BY clause.
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
** If pE evaluates to an integer constant i, then return i.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1420
** This is an indication to the caller that it should sort
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1421
** by the i-th column of the result set.
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
** If pE is a well-formed expression and the SELECT statement
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1424
** is not compound, then return 0.  This indicates to the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1425
** caller that it should sort by the value of the ORDER BY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1426
** expression.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1427
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1428
** If the SELECT is compound, then attempt to match pE against
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1429
** result set columns in the left-most SELECT statement.  Return
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1430
** the index i of the matching column, as an indication to the 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1431
** caller that it should sort by the i-th column.  If there is
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1432
** no match, return -1 and leave an error message in pParse.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1433
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1434
static int matchOrderByTermToExprList(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1435
  Parse *pParse,     /* Parsing context for error messages */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1436
  Select *pSelect,   /* The SELECT statement with the ORDER BY clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1437
  Expr *pE,          /* The specific ORDER BY term */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1438
  int idx,           /* When ORDER BY term is this */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1439
  int isCompound,    /* True if this is a compound SELECT */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1440
  u8 *pHasAgg        /* True if expression contains aggregate functions */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1441
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1442
  int i;             /* Loop counter */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1443
  ExprList *pEList;  /* The columns of the result set */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1444
  NameContext nc;    /* Name context for resolving pE */
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1447
  /* If the term is an integer constant, return the value of that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1448
  ** constant */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1449
  pEList = pSelect->pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1450
  if( sqlite3ExprIsInteger(pE, &i) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1451
    if( i<=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1452
      /* If i is too small, make it too big.  That way the calling
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1453
      ** function still sees a value that is out of range, but does
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1454
      ** not confuse the column number with 0 or -1 result code.
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
      i = pEList->nExpr+1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1457
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1458
    return i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1459
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1460
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1461
  /* If the term is a simple identifier that try to match that identifier
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1462
  ** against a column name in the result set.
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
  if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1465
    sqlite3 *db = pParse->db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1466
    char *zCol = sqlite3NameFromToken(db, &pE->token);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1467
    if( zCol==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1468
      return -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1469
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1470
    for(i=0; i<pEList->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1471
      char *zAs = pEList->a[i].zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1472
      if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1473
        sqlite3_free(zCol);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1474
        return i+1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1475
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1476
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1477
    sqlite3_free(zCol);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1478
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1479
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1480
  /* Resolve all names in the ORDER BY term expression
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1481
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1482
  memset(&nc, 0, sizeof(nc));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1483
  nc.pParse = pParse;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1484
  nc.pSrcList = pSelect->pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1485
  nc.pEList = pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1486
  nc.allowAgg = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1487
  nc.nErr = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1488
  if( sqlite3ExprResolveNames(&nc, pE) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1489
    if( isCompound ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1490
      sqlite3ErrorClear(pParse);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1491
      return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1492
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1493
      return -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1494
    }
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
  if( nc.hasAgg && pHasAgg ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1497
    *pHasAgg = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1498
  }
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
  /* For a compound SELECT, we need to try to match the ORDER BY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1501
  ** expression against an expression in the result set
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1502
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1503
  if( isCompound ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1504
    for(i=0; i<pEList->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1505
      if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1506
        return i+1;
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
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1509
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1510
  return 0;
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1513
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1514
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1515
** Analyze and ORDER BY or GROUP BY clause in a simple SELECT statement.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1516
** Return the number of errors seen.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1517
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1518
** Every term of the ORDER BY or GROUP BY clause needs to be an
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1519
** expression.  If any expression is an integer constant, then
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1520
** that expression is replaced by the corresponding 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1521
** expression from the result set.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1522
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1523
static int processOrderGroupBy(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1524
  Parse *pParse,        /* Parsing context.  Leave error messages here */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1525
  Select *pSelect,      /* The SELECT statement containing the clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1526
  ExprList *pOrderBy,   /* The ORDER BY or GROUP BY clause to be processed */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1527
  int isOrder,          /* 1 for ORDER BY.  0 for GROUP BY */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1528
  u8 *pHasAgg           /* Set to TRUE if any term contains an aggregate */
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
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1531
  sqlite3 *db = pParse->db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1532
  ExprList *pEList;
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
  if( pOrderBy==0 ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1535
  if( pOrderBy->nExpr>SQLITE_MAX_COLUMN ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1536
    const char *zType = isOrder ? "ORDER" : "GROUP";
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1537
    sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1538
    return 1;
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
  pEList = pSelect->pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1541
  if( pEList==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1542
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1543
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1544
  for(i=0; i<pOrderBy->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1545
    int iCol;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1546
    Expr *pE = pOrderBy->a[i].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1547
    iCol = matchOrderByTermToExprList(pParse, pSelect, pE, i+1, 0, pHasAgg);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1548
    if( iCol<0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1549
      return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1550
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1551
    if( iCol>pEList->nExpr ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1552
      const char *zType = isOrder ? "ORDER" : "GROUP";
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1553
      sqlite3ErrorMsg(pParse, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1554
         "%r %s BY term out of range - should be "
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1555
         "between 1 and %d", i+1, zType, pEList->nExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1556
      return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1557
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1558
    if( iCol>0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1559
      CollSeq *pColl = pE->pColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1560
      int flags = pE->flags & EP_ExpCollate;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1561
      sqlite3ExprDelete(pE);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1562
      pE = sqlite3ExprDup(db, pEList->a[iCol-1].pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1563
      pOrderBy->a[i].pExpr = pE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1564
      if( pColl && flags ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1565
        pE->pColl = pColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1566
        pE->flags |= flags;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1567
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1568
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1569
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1570
  return 0;
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
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1574
** Analyze and ORDER BY or GROUP BY clause in a SELECT statement.  Return
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1575
** the number of errors seen.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1576
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1577
** The processing depends on whether the SELECT is simple or compound.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1578
** For a simple SELECT statement, evry term of the ORDER BY or GROUP BY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1579
** clause needs to be an expression.  If any expression is an integer
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1580
** constant, then that expression is replaced by the corresponding 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1581
** expression from the result set.
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
** For compound SELECT statements, every expression needs to be of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1584
** type TK_COLUMN with a iTable value as given in the 4th parameter.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1585
** If any expression is an integer, that becomes the column number.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1586
** Otherwise, match the expression against result set columns from
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1587
** the left-most SELECT.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1588
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1589
static int processCompoundOrderBy(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1590
  Parse *pParse,        /* Parsing context.  Leave error messages here */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1591
  Select *pSelect,      /* The SELECT statement containing the ORDER BY */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1592
  int iTable            /* Output table for compound SELECT statements */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1593
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1594
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1595
  ExprList *pOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1596
  ExprList *pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1597
  sqlite3 *db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1598
  int moreToDo = 1;
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
  pOrderBy = pSelect->pOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1601
  if( pOrderBy==0 ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1602
  if( pOrderBy->nExpr>SQLITE_MAX_COLUMN ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1603
    sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1604
    return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1605
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1606
  db = pParse->db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1607
  for(i=0; i<pOrderBy->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1608
    pOrderBy->a[i].done = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1609
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1610
  while( pSelect->pPrior ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1611
    pSelect = pSelect->pPrior;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1612
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1613
  while( pSelect && moreToDo ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1614
    moreToDo = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1615
    for(i=0; i<pOrderBy->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1616
      int iCol;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1617
      Expr *pE, *pDup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1618
      if( pOrderBy->a[i].done ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1619
      pE = pOrderBy->a[i].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1620
      pDup = sqlite3ExprDup(db, pE);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1621
      if( pDup==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1622
        return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1623
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1624
      iCol = matchOrderByTermToExprList(pParse, pSelect, pDup, i+1, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1625
      sqlite3ExprDelete(pDup);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1626
      if( iCol<0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1627
        return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1628
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1629
      pEList = pSelect->pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1630
      if( pEList==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1631
        return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1632
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1633
      if( iCol>pEList->nExpr ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1634
        sqlite3ErrorMsg(pParse, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1635
           "%r ORDER BY term out of range - should be "
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1636
           "between 1 and %d", i+1, pEList->nExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1637
        return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1638
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1639
      if( iCol>0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1640
        pE->op = TK_COLUMN;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1641
        pE->iTable = iTable;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1642
        pE->iAgg = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1643
        pE->iColumn = iCol-1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1644
        pE->pTab = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1645
        pOrderBy->a[i].done = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1646
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1647
        moreToDo = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1648
      }
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
    pSelect = pSelect->pNext;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1651
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1652
  for(i=0; i<pOrderBy->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1653
    if( pOrderBy->a[i].done==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1654
      sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1655
            "column in the result set", i+1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1656
      return 1;
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
  return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1660
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1661
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1662
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1663
** Get a VDBE for the given parser context.  Create a new one if necessary.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1664
** If an error occurs, return NULL and leave a message in pParse.
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
Vdbe *sqlite3GetVdbe(Parse *pParse){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1667
  Vdbe *v = pParse->pVdbe;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1668
  if( v==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1669
    v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1670
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1671
  return v;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1672
}
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1675
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1676
** Compute the iLimit and iOffset fields of the SELECT based on the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1677
** pLimit and pOffset expressions.  pLimit and pOffset hold the expressions
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1678
** that appear in the original SQL statement after the LIMIT and OFFSET
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1679
** keywords.  Or NULL if those keywords are omitted. iLimit and iOffset 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1680
** are the integer memory register numbers for counters used to compute 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1681
** the limit and offset.  If there is no limit and/or offset, then 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1682
** iLimit and iOffset are negative.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1683
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1684
** This routine changes the values of iLimit and iOffset only if
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1685
** a limit or offset is defined by pLimit and pOffset.  iLimit and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1686
** iOffset should have been preset to appropriate default values
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1687
** (usually but not always -1) prior to calling this routine.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1688
** Only if pLimit!=0 or pOffset!=0 do the limit registers get
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1689
** redefined.  The UNION ALL operator uses this property to force
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1690
** the reuse of the same limit and offset registers across multiple
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1691
** SELECT statements.
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
static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1694
  Vdbe *v = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1695
  int iLimit = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1696
  int iOffset;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1697
  int addr1, addr2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1698
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
  ** "LIMIT -1" always shows all rows.  There is some
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1701
  ** contraversy about what the correct behavior should be.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1702
  ** The current implementation interprets "LIMIT 0" to mean
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1703
  ** no rows.
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
  if( p->pLimit ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1706
    p->iLimit = iLimit = pParse->nMem;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1707
    pParse->nMem += 2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1708
    v = sqlite3GetVdbe(pParse);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1709
    if( v==0 ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1710
    sqlite3ExprCode(pParse, p->pLimit);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1711
    sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1712
    sqlite3VdbeAddOp(v, OP_MemStore, iLimit, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1713
    VdbeComment((v, "# LIMIT counter"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1714
    sqlite3VdbeAddOp(v, OP_IfMemZero, iLimit, iBreak);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1715
    sqlite3VdbeAddOp(v, OP_MemLoad, iLimit, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1716
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1717
  if( p->pOffset ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1718
    p->iOffset = iOffset = pParse->nMem++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1719
    v = sqlite3GetVdbe(pParse);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1720
    if( v==0 ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1721
    sqlite3ExprCode(pParse, p->pOffset);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1722
    sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1723
    sqlite3VdbeAddOp(v, OP_MemStore, iOffset, p->pLimit==0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1724
    VdbeComment((v, "# OFFSET counter"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1725
    addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iOffset, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1726
    sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1727
    sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1728
    sqlite3VdbeJumpHere(v, addr1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1729
    if( p->pLimit ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1730
      sqlite3VdbeAddOp(v, OP_Add, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1731
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1732
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1733
  if( p->pLimit ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1734
    addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iLimit, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1735
    sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1736
    sqlite3VdbeAddOp(v, OP_MemInt, -1, iLimit+1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1737
    addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1738
    sqlite3VdbeJumpHere(v, addr1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1739
    sqlite3VdbeAddOp(v, OP_MemStore, iLimit+1, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1740
    VdbeComment((v, "# LIMIT+OFFSET"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1741
    sqlite3VdbeJumpHere(v, addr2);
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
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1744
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1745
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1746
** Allocate a virtual index to use for sorting.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1747
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1748
static void createSortingIndex(Parse *pParse, Select *p, ExprList *pOrderBy){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1749
  if( pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1750
    int addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1751
    assert( pOrderBy->iECursor==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1752
    pOrderBy->iECursor = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1753
    addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenEphemeral,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1754
                            pOrderBy->iECursor, pOrderBy->nExpr+1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1755
    assert( p->addrOpenEphm[2] == -1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1756
    p->addrOpenEphm[2] = addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1757
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1758
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1759
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1760
#ifndef SQLITE_OMIT_COMPOUND_SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1761
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1762
** Return the appropriate collating sequence for the iCol-th column of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1763
** the result set for the compound-select statement "p".  Return NULL if
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1764
** the column has no default collating sequence.
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
** The collating sequence for the compound select is taken from the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1767
** left-most term of the select that has a collating sequence.
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
static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1770
  CollSeq *pRet;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1771
  if( p->pPrior ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1772
    pRet = multiSelectCollSeq(pParse, p->pPrior, iCol);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1773
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1774
    pRet = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1775
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1776
  if( pRet==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1777
    pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1778
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1779
  return pRet;
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
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1782
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1783
#ifndef SQLITE_OMIT_COMPOUND_SELECT
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 is called to process a query that is really the union
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1786
** or intersection of two or more separate queries.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1787
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1788
** "p" points to the right-most of the two queries.  the query on the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1789
** left is p->pPrior.  The left query could also be a compound query
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1790
** in which case this routine will be called recursively. 
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
** The results of the total query are to be written into a destination
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1793
** of type eDest with parameter iParm.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1794
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1795
** Example 1:  Consider a three-way compound SQL statement.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1796
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1797
**     SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1798
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1799
** This statement is parsed up as follows:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1800
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1801
**     SELECT c FROM t3
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1802
**      |
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1803
**      `----->  SELECT b FROM t2
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1804
**                |
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1805
**                `------>  SELECT a FROM t1
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1806
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1807
** The arrows in the diagram above represent the Select.pPrior pointer.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1808
** So if this routine is called with p equal to the t3 query, then
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1809
** pPrior will be the t2 query.  p->op will be TK_UNION in this case.
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
** Notice that because of the way SQLite parses compound SELECTs, the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1812
** individual selects always group from left to right.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1813
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1814
static int multiSelect(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1815
  Parse *pParse,        /* Parsing context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1816
  Select *p,            /* The right-most of SELECTs to be coded */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1817
  int eDest,            /* \___  Store query results as specified */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1818
  int iParm,            /* /     by these two parameters.         */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1819
  char *aff             /* If eDest is SRT_Union, the affinity string */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1820
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1821
  int rc = SQLITE_OK;   /* Success code from a subroutine */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1822
  Select *pPrior;       /* Another SELECT immediately to our left */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1823
  Vdbe *v;              /* Generate code to this VDBE */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1824
  int nCol;             /* Number of columns in the result set */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1825
  ExprList *pOrderBy;   /* The ORDER BY clause on p */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1826
  int aSetP2[2];        /* Set P2 value of these op to number of columns */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1827
  int nSetP2 = 0;       /* Number of slots in aSetP2[] used */
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
  /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1830
  ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
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
  if( p==0 || p->pPrior==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1833
    rc = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1834
    goto multi_select_end;
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
  pPrior = p->pPrior;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1837
  assert( pPrior->pRightmost!=pPrior );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1838
  assert( pPrior->pRightmost==p->pRightmost );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1839
  if( pPrior->pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1840
    sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1841
      selectOpName(p->op));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1842
    rc = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1843
    goto multi_select_end;
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
  if( pPrior->pLimit ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1846
    sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before",
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1847
      selectOpName(p->op));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1848
    rc = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1849
    goto multi_select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1850
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1851
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1852
  /* Make sure we have a valid query engine.  If not, create a new one.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1853
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1854
  v = sqlite3GetVdbe(pParse);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1855
  if( v==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1856
    rc = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1857
    goto multi_select_end;
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1860
  /* Create the destination temporary table if necessary
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1861
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1862
  if( eDest==SRT_EphemTab ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1863
    assert( p->pEList );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1864
    assert( nSetP2<sizeof(aSetP2)/sizeof(aSetP2[0]) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1865
    aSetP2[nSetP2++] = sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1866
    eDest = SRT_Table;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1867
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1868
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1869
  /* Generate code for the left and right SELECT statements.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1870
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1871
  pOrderBy = p->pOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1872
  switch( p->op ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1873
    case TK_ALL: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1874
      if( pOrderBy==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1875
        int addr = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1876
        assert( !pPrior->pLimit );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1877
        pPrior->pLimit = p->pLimit;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1878
        pPrior->pOffset = p->pOffset;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1879
        rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1880
        p->pLimit = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1881
        p->pOffset = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1882
        if( rc ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1883
          goto multi_select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1884
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1885
        p->pPrior = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1886
        p->iLimit = pPrior->iLimit;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1887
        p->iOffset = pPrior->iOffset;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1888
        if( p->iLimit>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1889
          addr = sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1890
          VdbeComment((v, "# Jump ahead if LIMIT reached"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1891
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1892
        rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1893
        p->pPrior = pPrior;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1894
        if( rc ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1895
          goto multi_select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1896
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1897
        if( addr ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1898
          sqlite3VdbeJumpHere(v, addr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1899
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1900
        break;
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
      /* For UNION ALL ... ORDER BY fall through to the next case */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1903
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1904
    case TK_EXCEPT:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1905
    case TK_UNION: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1906
      int unionTab;    /* Cursor number of the temporary table holding result */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1907
      int op = 0;      /* One of the SRT_ operations to apply to self */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1908
      int priorOp;     /* The SRT_ operation to apply to prior selects */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1909
      Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1910
      int addr;
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
      priorOp = p->op==TK_ALL ? SRT_Table : SRT_Union;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1913
      if( eDest==priorOp && pOrderBy==0 && !p->pLimit && !p->pOffset ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1914
        /* We can reuse a temporary table generated by a SELECT to our
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1915
        ** right.
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
        unionTab = iParm;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1918
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1919
        /* We will need to create our own temporary table to hold the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1920
        ** intermediate results.
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
        unionTab = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1923
        if( processCompoundOrderBy(pParse, p, unionTab) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1924
          rc = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1925
          goto multi_select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1926
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1927
        addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, unionTab, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1928
        if( priorOp==SRT_Table ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1929
          assert( nSetP2<sizeof(aSetP2)/sizeof(aSetP2[0]) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1930
          aSetP2[nSetP2++] = addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1931
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1932
          assert( p->addrOpenEphm[0] == -1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1933
          p->addrOpenEphm[0] = addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1934
          p->pRightmost->usesEphm = 1;
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
        createSortingIndex(pParse, p, pOrderBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1937
        assert( p->pEList );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1938
      }
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
      /* Code the SELECT statements to our left
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1941
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1942
      assert( !pPrior->pOrderBy );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1943
      rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0, aff);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1944
      if( rc ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1945
        goto multi_select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1946
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1947
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1948
      /* Code the current SELECT statement
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1949
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1950
      switch( p->op ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1951
         case TK_EXCEPT:  op = SRT_Except;   break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1952
         case TK_UNION:   op = SRT_Union;    break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1953
         case TK_ALL:     op = SRT_Table;    break;
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
      p->pPrior = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1956
      p->pOrderBy = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1957
      p->disallowOrderBy = pOrderBy!=0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1958
      pLimit = p->pLimit;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1959
      p->pLimit = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1960
      pOffset = p->pOffset;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1961
      p->pOffset = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1962
      rc = sqlite3Select(pParse, p, op, unionTab, 0, 0, 0, aff);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1963
      /* Query flattening in sqlite3Select() might refill p->pOrderBy.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1964
      ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1965
      sqlite3ExprListDelete(p->pOrderBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1966
      p->pPrior = pPrior;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1967
      p->pOrderBy = pOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1968
      sqlite3ExprDelete(p->pLimit);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1969
      p->pLimit = pLimit;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1970
      p->pOffset = pOffset;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1971
      p->iLimit = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1972
      p->iOffset = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1973
      if( rc ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1974
        goto multi_select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1975
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1976
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1977
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1978
      /* Convert the data in the temporary table into whatever form
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1979
      ** it is that we currently need.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1980
      */      
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1981
      if( eDest!=priorOp || unionTab!=iParm ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1982
        int iCont, iBreak, iStart;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1983
        assert( p->pEList );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1984
        if( eDest==SRT_Callback ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1985
          Select *pFirst = p;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1986
          while( pFirst->pPrior ) pFirst = pFirst->pPrior;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1987
          generateColumnNames(pParse, 0, pFirst->pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1988
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1989
        iBreak = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1990
        iCont = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1991
        computeLimitRegisters(pParse, p, iBreak);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1992
        sqlite3VdbeAddOp(v, OP_Rewind, unionTab, iBreak);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1993
        iStart = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1994
        rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1995
                             pOrderBy, -1, eDest, iParm, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1996
                             iCont, iBreak, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1997
        if( rc ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1998
          rc = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1999
          goto multi_select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2000
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2001
        sqlite3VdbeResolveLabel(v, iCont);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2002
        sqlite3VdbeAddOp(v, OP_Next, unionTab, iStart);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2003
        sqlite3VdbeResolveLabel(v, iBreak);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2004
        sqlite3VdbeAddOp(v, OP_Close, unionTab, 0);
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
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2007
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2008
    case TK_INTERSECT: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2009
      int tab1, tab2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2010
      int iCont, iBreak, iStart;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2011
      Expr *pLimit, *pOffset;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2012
      int addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2013
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2014
      /* INTERSECT is different from the others since it requires
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2015
      ** two temporary tables.  Hence it has its own case.  Begin
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2016
      ** by allocating the tables we will need.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2017
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2018
      tab1 = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2019
      tab2 = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2020
      if( processCompoundOrderBy(pParse, p, tab1) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2021
        rc = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2022
        goto multi_select_end;
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
      createSortingIndex(pParse, p, pOrderBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2025
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2026
      addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, tab1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2027
      assert( p->addrOpenEphm[0] == -1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2028
      p->addrOpenEphm[0] = addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2029
      p->pRightmost->usesEphm = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2030
      assert( p->pEList );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2031
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2032
      /* Code the SELECTs to our left into temporary table "tab1".
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2033
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2034
      rc = sqlite3Select(pParse, pPrior, SRT_Union, tab1, 0, 0, 0, aff);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2035
      if( rc ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2036
        goto multi_select_end;
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2039
      /* Code the current SELECT into temporary table "tab2"
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2040
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2041
      addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, tab2, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2042
      assert( p->addrOpenEphm[1] == -1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2043
      p->addrOpenEphm[1] = addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2044
      p->pPrior = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2045
      pLimit = p->pLimit;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2046
      p->pLimit = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2047
      pOffset = p->pOffset;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2048
      p->pOffset = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2049
      rc = sqlite3Select(pParse, p, SRT_Union, tab2, 0, 0, 0, aff);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2050
      p->pPrior = pPrior;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2051
      sqlite3ExprDelete(p->pLimit);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2052
      p->pLimit = pLimit;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2053
      p->pOffset = pOffset;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2054
      if( rc ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2055
        goto multi_select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2056
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2057
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2058
      /* Generate code to take the intersection of the two temporary
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2059
      ** tables.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2060
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2061
      assert( p->pEList );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2062
      if( eDest==SRT_Callback ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2063
        Select *pFirst = p;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2064
        while( pFirst->pPrior ) pFirst = pFirst->pPrior;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2065
        generateColumnNames(pParse, 0, pFirst->pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2066
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2067
      iBreak = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2068
      iCont = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2069
      computeLimitRegisters(pParse, p, iBreak);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2070
      sqlite3VdbeAddOp(v, OP_Rewind, tab1, iBreak);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2071
      iStart = sqlite3VdbeAddOp(v, OP_RowKey, tab1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2072
      sqlite3VdbeAddOp(v, OP_NotFound, tab2, iCont);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2073
      rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2074
                             pOrderBy, -1, eDest, iParm, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2075
                             iCont, iBreak, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2076
      if( rc ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2077
        rc = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2078
        goto multi_select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2079
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2080
      sqlite3VdbeResolveLabel(v, iCont);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2081
      sqlite3VdbeAddOp(v, OP_Next, tab1, iStart);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2082
      sqlite3VdbeResolveLabel(v, iBreak);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2083
      sqlite3VdbeAddOp(v, OP_Close, tab2, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2084
      sqlite3VdbeAddOp(v, OP_Close, tab1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2085
      break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2086
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2087
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2088
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2089
  /* Make sure all SELECTs in the statement have the same number of elements
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2090
  ** in their result sets.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2091
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2092
  assert( p->pEList && pPrior->pEList );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2093
  if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2094
    sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2095
      " do not have the same number of result columns", selectOpName(p->op));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2096
    rc = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2097
    goto multi_select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2098
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2099
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2100
  /* Set the number of columns in temporary tables
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2101
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2102
  nCol = p->pEList->nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2103
  while( nSetP2 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2104
    sqlite3VdbeChangeP2(v, aSetP2[--nSetP2], nCol);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2105
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2106
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2107
  /* Compute collating sequences used by either the ORDER BY clause or
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2108
  ** by any temporary tables needed to implement the compound select.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2109
  ** Attach the KeyInfo structure to all temporary tables.  Invoke the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2110
  ** ORDER BY processing if there is an ORDER BY clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2111
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2112
  ** This section is run by the right-most SELECT statement only.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2113
  ** SELECT statements to the left always skip this part.  The right-most
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2114
  ** SELECT might also skip this part if it has no ORDER BY clause and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2115
  ** no temp tables are required.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2116
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2117
  if( pOrderBy || p->usesEphm ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2118
    int i;                        /* Loop counter */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2119
    KeyInfo *pKeyInfo;            /* Collating sequence for the result set */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2120
    Select *pLoop;                /* For looping through SELECT statements */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2121
    int nKeyCol;                  /* Number of entries in pKeyInfo->aCol[] */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2122
    CollSeq **apColl;             /* For looping through pKeyInfo->aColl[] */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2123
    CollSeq **aCopy;              /* A copy of pKeyInfo->aColl[] */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2124
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2125
    assert( p->pRightmost==p );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2126
    nKeyCol = nCol + (pOrderBy ? pOrderBy->nExpr : 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2127
    pKeyInfo = (KeyInfo*)sqlite3DbMallocZero(pParse->db,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2128
                       sizeof(*pKeyInfo)+nKeyCol*(sizeof(CollSeq*) + 1));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2129
    if( !pKeyInfo ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2130
      rc = SQLITE_NOMEM;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2131
      goto multi_select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2132
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2133
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2134
    pKeyInfo->enc = ENC(pParse->db);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2135
    pKeyInfo->nField = nCol;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2136
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2137
    for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2138
      *apColl = multiSelectCollSeq(pParse, p, i);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2139
      if( 0==*apColl ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2140
        *apColl = pParse->db->pDfltColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2141
      }
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2144
    for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2145
      for(i=0; i<2; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2146
        int addr = pLoop->addrOpenEphm[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2147
        if( addr<0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2148
          /* If [0] is unused then [1] is also unused.  So we can
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2149
          ** always safely abort as soon as the first unused slot is found */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2150
          assert( pLoop->addrOpenEphm[1]<0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2151
          break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2152
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2153
        sqlite3VdbeChangeP2(v, addr, nCol);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2154
        sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2155
        pLoop->addrOpenEphm[i] = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2156
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2157
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2158
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2159
    if( pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2160
		ExprList::ExprList_item *pOTerm = pOrderBy->a;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2161
      int nOrderByExpr = pOrderBy->nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2162
      int addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2163
      u8 *pSortOrder;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2164
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2165
      /* Reuse the same pKeyInfo for the ORDER BY as was used above for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2166
      ** the compound select statements.  Except we have to change out the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2167
      ** pKeyInfo->aColl[] values.  Some of the aColl[] values will be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2168
      ** reused when constructing the pKeyInfo for the ORDER BY, so make
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2169
      ** a copy.  Sufficient space to hold both the nCol entries for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2170
      ** the compound select and the nOrderbyExpr entries for the ORDER BY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2171
      ** was allocated above.  But we need to move the compound select
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2172
      ** entries out of the way before constructing the ORDER BY entries.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2173
      ** Move the compound select entries into aCopy[] where they can be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2174
      ** accessed and reused when constructing the ORDER BY entries.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2175
      ** Because nCol might be greater than or less than nOrderByExpr
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2176
      ** we have to use memmove() when doing the copy.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2177
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2178
      aCopy = &pKeyInfo->aColl[nOrderByExpr];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2179
      pSortOrder = pKeyInfo->aSortOrder = (u8*)&aCopy[nCol];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2180
      memmove(aCopy, pKeyInfo->aColl, nCol*sizeof(CollSeq*));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2181
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2182
      apColl = pKeyInfo->aColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2183
      for(i=0; i<nOrderByExpr; i++, pOTerm++, apColl++, pSortOrder++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2184
        Expr *pExpr = pOTerm->pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2185
        if( (pExpr->flags & EP_ExpCollate) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2186
          assert( pExpr->pColl!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2187
          *apColl = pExpr->pColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2188
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2189
          *apColl = aCopy[pExpr->iColumn];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2190
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2191
        *pSortOrder = pOTerm->sortOrder;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2192
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2193
      assert( p->pRightmost==p );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2194
      assert( p->addrOpenEphm[2]>=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2195
      addr = p->addrOpenEphm[2];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2196
      sqlite3VdbeChangeP2(v, addr, p->pOrderBy->nExpr+2);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2197
      pKeyInfo->nField = nOrderByExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2198
      sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2199
      pKeyInfo = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2200
      generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2201
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2202
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2203
    sqlite3_free(pKeyInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2204
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2205
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2206
multi_select_end:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2207
  return rc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2208
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2209
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2210
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2211
#ifndef SQLITE_OMIT_VIEW
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2212
/* Forward Declarations */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2213
static void substExprList(sqlite3*, ExprList*, int, ExprList*);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2214
static void substSelect(sqlite3*, Select *, int, ExprList *);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2215
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2216
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2217
** Scan through the expression pExpr.  Replace every reference to
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2218
** a column in table number iTable with a copy of the iColumn-th
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2219
** entry in pEList.  (But leave references to the ROWID column 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2220
** unchanged.)
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
** This routine is part of the flattening procedure.  A subquery
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2223
** whose result set is defined by pEList appears as entry in the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2224
** FROM clause of a SELECT such that the VDBE cursor assigned to that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2225
** FORM clause entry is iTable.  This routine make the necessary 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2226
** changes to pExpr so that it refers directly to the source table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2227
** of the subquery rather the result set of the subquery.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2228
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2229
static void substExpr(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2230
  sqlite3 *db,        /* Report malloc errors to this connection */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2231
  Expr *pExpr,        /* Expr in which substitution occurs */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2232
  int iTable,         /* Table to be substituted */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2233
  ExprList *pEList    /* Substitute expressions */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2234
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2235
  if( pExpr==0 ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2236
  if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2237
    if( pExpr->iColumn<0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2238
      pExpr->op = TK_NULL;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2239
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2240
      Expr *pNew;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2241
      assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2242
      assert( pExpr->pLeft==0 && pExpr->pRight==0 && pExpr->pList==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2243
      pNew = pEList->a[pExpr->iColumn].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2244
      assert( pNew!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2245
      pExpr->op = pNew->op;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2246
      assert( pExpr->pLeft==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2247
      pExpr->pLeft = sqlite3ExprDup(db, pNew->pLeft);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2248
      assert( pExpr->pRight==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2249
      pExpr->pRight = sqlite3ExprDup(db, pNew->pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2250
      assert( pExpr->pList==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2251
      pExpr->pList = sqlite3ExprListDup(db, pNew->pList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2252
      pExpr->iTable = pNew->iTable;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2253
      pExpr->pTab = pNew->pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2254
      pExpr->iColumn = pNew->iColumn;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2255
      pExpr->iAgg = pNew->iAgg;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2256
      sqlite3TokenCopy(db, &pExpr->token, &pNew->token);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2257
      sqlite3TokenCopy(db, &pExpr->span, &pNew->span);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2258
      pExpr->pSelect = sqlite3SelectDup(db, pNew->pSelect);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2259
      pExpr->flags = pNew->flags;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2260
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2261
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2262
    substExpr(db, pExpr->pLeft, iTable, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2263
    substExpr(db, pExpr->pRight, iTable, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2264
    substSelect(db, pExpr->pSelect, iTable, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2265
    substExprList(db, pExpr->pList, iTable, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2266
  }
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
static void substExprList(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2269
  sqlite3 *db,         /* Report malloc errors here */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2270
  ExprList *pList,     /* List to scan and in which to make substitutes */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2271
  int iTable,          /* Table to be substituted */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2272
  ExprList *pEList     /* Substitute values */
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 i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2275
  if( pList==0 ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2276
  for(i=0; i<pList->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2277
    substExpr(db, pList->a[i].pExpr, iTable, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2278
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2279
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2280
static void substSelect(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2281
  sqlite3 *db,         /* Report malloc errors here */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2282
  Select *p,           /* SELECT statement in which to make substitutions */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2283
  int iTable,          /* Table to be replaced */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2284
  ExprList *pEList     /* Substitute values */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2285
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2286
  if( !p ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2287
  substExprList(db, p->pEList, iTable, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2288
  substExprList(db, p->pGroupBy, iTable, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2289
  substExprList(db, p->pOrderBy, iTable, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2290
  substExpr(db, p->pHaving, iTable, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2291
  substExpr(db, p->pWhere, iTable, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2292
  substSelect(db, p->pPrior, iTable, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2293
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2294
#endif /* !defined(SQLITE_OMIT_VIEW) */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2295
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2296
#ifndef SQLITE_OMIT_VIEW
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2297
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2298
** This routine attempts to flatten subqueries in order to speed
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2299
** execution.  It returns 1 if it makes changes and 0 if no flattening
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2300
** occurs.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2301
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2302
** To understand the concept of flattening, consider the following
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2303
** query:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2304
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2305
**     SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2306
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2307
** The default way of implementing this query is to execute the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2308
** subquery first and store the results in a temporary table, then
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2309
** run the outer query on that temporary table.  This requires two
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2310
** passes over the data.  Furthermore, because the temporary table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2311
** has no indices, the WHERE clause on the outer query cannot be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2312
** optimized.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2313
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2314
** This routine attempts to rewrite queries such as the above into
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2315
** a single flat select, like this:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2316
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2317
**     SELECT x+y AS a FROM t1 WHERE z<100 AND a>5
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2318
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2319
** The code generated for this simpification gives the same result
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2320
** but only has to scan the data once.  And because indices might 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2321
** exist on the table t1, a complete scan of the data might be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2322
** avoided.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2323
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2324
** Flattening is only attempted if all of the following are true:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2325
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2326
**   (1)  The subquery and the outer query do not both use aggregates.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2327
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2328
**   (2)  The subquery is not an aggregate or the outer query is not a join.
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
**   (3)  The subquery is not the right operand of a left outer join, or
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2331
**        the subquery is not itself a join.  (Ticket #306)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2332
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2333
**   (4)  The subquery is not DISTINCT or the outer query is not a join.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2334
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2335
**   (5)  The subquery is not DISTINCT or the outer query does not use
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2336
**        aggregates.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2337
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2338
**   (6)  The subquery does not use aggregates or the outer query is not
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2339
**        DISTINCT.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2340
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2341
**   (7)  The subquery has a FROM clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2342
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2343
**   (8)  The subquery does not use LIMIT or the outer query is not a join.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2344
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2345
**   (9)  The subquery does not use LIMIT or the outer query does not use
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2346
**        aggregates.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2347
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2348
**  (10)  The subquery does not use aggregates or the outer query does not
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2349
**        use LIMIT.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2350
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2351
**  (11)  The subquery and the outer query do not both have ORDER BY clauses.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2352
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2353
**  (12)  The subquery is not the right term of a LEFT OUTER JOIN or the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2354
**        subquery has no WHERE clause.  (added by ticket #350)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2355
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2356
**  (13)  The subquery and outer query do not both use LIMIT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2357
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2358
**  (14)  The subquery does not use OFFSET
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2359
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2360
**  (15)  The outer query is not part of a compound select or the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2361
**        subquery does not have both an ORDER BY and a LIMIT clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2362
**        (See ticket #2339)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2363
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2364
** In this routine, the "p" parameter is a pointer to the outer query.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2365
** The subquery is p->pSrc->a[iFrom].  isAgg is true if the outer query
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2366
** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
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
** If flattening is not attempted, this routine is a no-op and returns 0.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2369
** If flattening is attempted this routine returns 1.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2370
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2371
** All of the expression analysis must occur on both the outer query and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2372
** the subquery before this routine runs.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2373
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2374
static int flattenSubquery(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2375
  sqlite3 *db,         /* Database connection */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2376
  Select *p,           /* The parent or outer SELECT statement */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2377
  int iFrom,           /* Index in p->pSrc->a[] of the inner subquery */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2378
  int isAgg,           /* True if outer SELECT uses aggregate functions */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2379
  int subqueryIsAgg    /* True if the subquery uses aggregate functions */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2380
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2381
  Select *pSub;       /* The inner query or "subquery" */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2382
  SrcList *pSrc;      /* The FROM clause of the outer query */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2383
  SrcList *pSubSrc;   /* The FROM clause of the subquery */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2384
  ExprList *pList;    /* The result set of the outer query */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2385
  int iParent;        /* VDBE cursor number of the pSub result set temp table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2386
  int i;              /* Loop counter */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2387
  Expr *pWhere;                    /* The WHERE clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2388
  SrcList::SrcList_item *pSubitem;   /* The subquery */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2389
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2390
  /* Check to see if flattening is permitted.  Return 0 if not.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2391
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2392
  if( p==0 ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2393
  pSrc = p->pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2394
  assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2395
  pSubitem = &pSrc->a[iFrom];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2396
  pSub = pSubitem->pSelect;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2397
  assert( pSub!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2398
  if( isAgg && subqueryIsAgg ) return 0;                 /* Restriction (1)  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2399
  if( subqueryIsAgg && pSrc->nSrc>1 ) return 0;          /* Restriction (2)  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2400
  pSubSrc = pSub->pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2401
  assert( pSubSrc );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2402
  /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2403
  ** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2404
  ** because they could be computed at compile-time.  But when LIMIT and OFFSET
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2405
  ** became arbitrary expressions, we were forced to add restrictions (13)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2406
  ** and (14). */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2407
  if( pSub->pLimit && p->pLimit ) return 0;              /* Restriction (13) */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2408
  if( pSub->pOffset ) return 0;                          /* Restriction (14) */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2409
  if( p->pRightmost && pSub->pLimit && pSub->pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2410
    return 0;                                            /* Restriction (15) */
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
  if( pSubSrc->nSrc==0 ) return 0;                       /* Restriction (7)  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2413
  if( (pSub->isDistinct || pSub->pLimit) 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2414
         && (pSrc->nSrc>1 || isAgg) ){          /* Restrictions (4)(5)(8)(9) */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2415
     return 0;       
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2416
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2417
  if( p->isDistinct && subqueryIsAgg ) return 0;         /* Restriction (6)  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2418
  if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2419
     return 0;                                           /* Restriction (11) */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2420
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2421
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2422
  /* Restriction 3:  If the subquery is a join, make sure the subquery is 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2423
  ** not used as the right operand of an outer join.  Examples of why this
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2424
  ** is not allowed:
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
  **         t1 LEFT OUTER JOIN (t2 JOIN t3)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2427
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2428
  ** If we flatten the above, we would get
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2429
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2430
  **         (t1 LEFT OUTER JOIN t2) JOIN t3
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2431
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2432
  ** which is not at all the same thing.
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
  if( pSubSrc->nSrc>1 && (pSubitem->jointype & JT_OUTER)!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2435
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2436
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2437
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2438
  /* Restriction 12:  If the subquery is the right operand of a left outer
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2439
  ** join, make sure the subquery has no WHERE clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2440
  ** An examples of why this is not allowed:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2441
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2442
  **         t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2443
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2444
  ** If we flatten the above, we would get
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2445
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2446
  **         (t1 LEFT OUTER JOIN t2) WHERE t2.x>0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2447
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2448
  ** But the t2.x>0 test will always fail on a NULL row of t2, which
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2449
  ** effectively converts the OUTER JOIN into an INNER JOIN.
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( (pSubitem->jointype & JT_OUTER)!=0 && pSub->pWhere!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2452
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2453
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2454
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2455
  /* If we reach this point, it means flattening is permitted for the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2456
  ** iFrom-th entry of the FROM clause in the outer query.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2457
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2458
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2459
  /* Move all of the FROM elements of the subquery into the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2460
  ** the FROM clause of the outer query.  Before doing this, remember
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2461
  ** the cursor number for the original outer query FROM element in
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2462
  ** iParent.  The iParent cursor will never be used.  Subsequent code
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2463
  ** will scan expressions looking for iParent references and replace
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2464
  ** those references with expressions that resolve to the subquery FROM
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2465
  ** elements we are now copying in.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2466
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2467
  iParent = pSubitem->iCursor;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2468
  {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2469
    int nSubSrc = pSubSrc->nSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2470
    int jointype = pSubitem->jointype;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2471
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2472
    sqlite3DeleteTable(pSubitem->pTab);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2473
    sqlite3_free(pSubitem->zDatabase);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2474
    sqlite3_free(pSubitem->zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2475
    sqlite3_free(pSubitem->zAlias);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2476
    pSubitem->pTab = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2477
    pSubitem->zDatabase = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2478
    pSubitem->zName = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2479
    pSubitem->zAlias = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2480
    if( nSubSrc>1 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2481
      int extra = nSubSrc - 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2482
      for(i=1; i<nSubSrc; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2483
        pSrc = sqlite3SrcListAppend(db, pSrc, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2484
        if( pSrc==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2485
          p->pSrc = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2486
          return 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
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2489
      p->pSrc = pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2490
      for(i=pSrc->nSrc-1; i-extra>=iFrom; i--){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2491
        pSrc->a[i] = pSrc->a[i-extra];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2492
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2493
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2494
    for(i=0; i<nSubSrc; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2495
      pSrc->a[i+iFrom] = pSubSrc->a[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2496
      memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2497
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2498
    pSrc->a[iFrom].jointype = jointype;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2499
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2500
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2501
  /* Now begin substituting subquery result set expressions for 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2502
  ** references to the iParent in the outer query.
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
  ** Example:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2505
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2506
  **   SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2507
  **   \                     \_____________ subquery __________/          /
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2508
  **    \_____________________ outer query ______________________________/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2509
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2510
  ** We look at every expression in the outer query and every place we see
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2511
  ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2512
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2513
  pList = p->pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2514
  for(i=0; i<pList->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2515
    Expr *pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2516
    if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2517
      pList->a[i].zName = 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2518
             sqlite3DbStrNDup(db, (char*)pExpr->span.z, pExpr->span.n);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2519
    }
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
  substExprList(db, p->pEList, iParent, pSub->pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2522
  if( isAgg ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2523
    substExprList(db, p->pGroupBy, iParent, pSub->pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2524
    substExpr(db, p->pHaving, iParent, pSub->pEList);
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
  if( pSub->pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2527
    assert( p->pOrderBy==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2528
    p->pOrderBy = pSub->pOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2529
    pSub->pOrderBy = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2530
  }else if( p->pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2531
    substExprList(db, p->pOrderBy, iParent, pSub->pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2532
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2533
  if( pSub->pWhere ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2534
    pWhere = sqlite3ExprDup(db, pSub->pWhere);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2535
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2536
    pWhere = 0;
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
  if( subqueryIsAgg ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2539
    assert( p->pHaving==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2540
    p->pHaving = p->pWhere;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2541
    p->pWhere = pWhere;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2542
    substExpr(db, p->pHaving, iParent, pSub->pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2543
    p->pHaving = sqlite3ExprAnd(db, p->pHaving, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2544
                                sqlite3ExprDup(db, pSub->pHaving));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2545
    assert( p->pGroupBy==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2546
    p->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2547
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2548
    substExpr(db, p->pWhere, iParent, pSub->pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2549
    p->pWhere = sqlite3ExprAnd(db, p->pWhere, pWhere);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2550
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2551
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2552
  /* The flattened query is distinct if either the inner or the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2553
  ** outer query is distinct. 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2554
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2555
  p->isDistinct = p->isDistinct || pSub->isDistinct;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2556
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2557
  /*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2558
  ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2559
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2560
  ** One is tempted to try to add a and b to combine the limits.  But this
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2561
  ** does not work if either limit is negative.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2562
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2563
  if( pSub->pLimit ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2564
    p->pLimit = pSub->pLimit;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2565
    pSub->pLimit = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2566
  }
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
  /* Finially, delete what is left of the subquery and return
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2569
  ** success.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2570
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2571
  sqlite3SelectDelete(pSub);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2572
  return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2573
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2574
#endif /* SQLITE_OMIT_VIEW */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2575
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2576
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2577
** Analyze the SELECT statement passed in as an argument to see if it
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2578
** is a simple min() or max() query.  If it is and this query can be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2579
** satisfied using a single seek to the beginning or end of an index,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2580
** then generate the code for this SELECT and return 1.  If this is not a 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2581
** simple min() or max() query, then return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2582
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2583
** A simply min() or max() query looks like this:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2584
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2585
**    SELECT min(a) FROM table;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2586
**    SELECT max(a) FROM table;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2587
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2588
** The query may have only a single table in its FROM argument.  There
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2589
** can be no GROUP BY or HAVING or WHERE clauses.  The result set must
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2590
** be the min() or max() of a single column of the table.  The column
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2591
** in the min() or max() function must be indexed.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2592
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2593
** The parameters to this routine are the same as for sqlite3Select().
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2594
** See the header comment on that routine for additional information.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2595
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2596
static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2597
  Expr *pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2598
  int iCol;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2599
  Table *pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2600
  Index *pIdx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2601
  int base;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2602
  Vdbe *v;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2603
  int seekOp;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2604
  ExprList *pEList, *pList, eList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2605
  ExprList::ExprList_item eListItem;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2606
  SrcList *pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2607
  int brk;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2608
  int iDb;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2609
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2610
  /* Check to see if this query is a simple min() or max() query.  Return
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2611
  ** zero if it is  not.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2612
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2613
  if( p->pGroupBy || p->pHaving || p->pWhere ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2614
  pSrc = p->pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2615
  if( pSrc->nSrc!=1 ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2616
  pEList = p->pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2617
  if( pEList->nExpr!=1 ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2618
  pExpr = pEList->a[0].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2619
  if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2620
  pList = pExpr->pList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2621
  if( pList==0 || pList->nExpr!=1 ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2622
  if( pExpr->token.n!=3 ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2623
  if( sqlite3StrNICmp((char*)pExpr->token.z,"min",3)==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2624
    seekOp = OP_Rewind;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2625
  }else if( sqlite3StrNICmp((char*)pExpr->token.z,"max",3)==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2626
    seekOp = OP_Last;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2627
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2628
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2629
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2630
  pExpr = pList->a[0].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2631
  if( pExpr->op!=TK_COLUMN ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2632
  iCol = pExpr->iColumn;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2633
  pTab = pSrc->a[0].pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2634
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2635
  /* This optimization cannot be used with virtual tables. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2636
  if( IsVirtual(pTab) ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2637
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2638
  /* If we get to here, it means the query is of the correct form.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2639
  ** Check to make sure we have an index and make pIdx point to the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2640
  ** appropriate index.  If the min() or max() is on an INTEGER PRIMARY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2641
  ** key column, no index is necessary so set pIdx to NULL.  If no
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2642
  ** usable index is found, return 0.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2643
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2644
  if( iCol<0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2645
    pIdx = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2646
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2647
    CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2648
    if( pColl==0 ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2649
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2650
      assert( pIdx->nColumn>=1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2651
      if( pIdx->aiColumn[0]==iCol && 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2652
          0==sqlite3StrICmp(pIdx->azColl[0], pColl->zName) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2653
        break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2654
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2655
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2656
    if( pIdx==0 ) return 0;
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
  /* Identify column types if we will be using the callback.  This
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2660
  ** step is skipped if the output is going to a table or a memory cell.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2661
  ** The column names have already been generated in the calling function.
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
  v = sqlite3GetVdbe(pParse);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2664
  if( v==0 ) return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2665
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2666
  /* If the output is destined for a temporary table, open that table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2667
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2668
  if( eDest==SRT_EphemTab ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2669
    sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2670
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2671
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2672
  /* Generating code to find the min or the max.  Basically all we have
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2673
  ** to do is find the first or the last entry in the chosen index.  If
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2674
  ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2675
  ** or last entry in the main table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2676
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2677
  iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2678
  assert( iDb>=0 || pTab->isEphem );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2679
  sqlite3CodeVerifySchema(pParse, iDb);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2680
  sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2681
  base = pSrc->a[0].iCursor;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2682
  brk = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2683
  computeLimitRegisters(pParse, p, brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2684
  if( pSrc->a[0].pSelect==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2685
    sqlite3OpenTable(pParse, base, iDb, pTab, OP_OpenRead);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2686
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2687
  if( pIdx==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2688
    sqlite3VdbeAddOp(v, seekOp, base, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2689
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2690
    /* Even though the cursor used to open the index here is closed
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2691
    ** as soon as a single value has been read from it, allocate it
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2692
    ** using (pParse->nTab++) to prevent the cursor id from being 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2693
    ** reused. This is important for statements of the form 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2694
    ** "INSERT INTO x SELECT max() FROM x".
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2695
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2696
    int iIdx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2697
    KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2698
    iIdx = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2699
    assert( pIdx->pSchema==pTab->pSchema );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2700
    sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2701
    sqlite3VdbeOp3(v, OP_OpenRead, iIdx, pIdx->tnum, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2702
        (char*)pKey, P3_KEYINFO_HANDOFF);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2703
    if( seekOp==OP_Rewind ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2704
      sqlite3VdbeAddOp(v, OP_Null, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2705
      sqlite3VdbeAddOp(v, OP_MakeRecord, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2706
      seekOp = OP_MoveGt;
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
    if( pIdx->aSortOrder[0]==SQLITE_SO_DESC ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2709
      /* Ticket #2514: invert the seek operator if we are using
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2710
      ** a descending index. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2711
      if( seekOp==OP_Last ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2712
        seekOp = OP_Rewind;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2713
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2714
        assert( seekOp==OP_MoveGt );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2715
        seekOp = OP_MoveLt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2716
      }
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, seekOp, iIdx, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2719
    sqlite3VdbeAddOp(v, OP_IdxRowid, iIdx, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2720
    sqlite3VdbeAddOp(v, OP_Close, iIdx, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2721
    sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
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
  eList.nExpr = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2724
  memset(&eListItem, 0, sizeof(eListItem));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2725
  eList.a = &eListItem;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2726
  eList.a[0].pExpr = pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2727
  selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, brk, brk, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2728
  sqlite3VdbeResolveLabel(v, brk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2729
  sqlite3VdbeAddOp(v, OP_Close, base, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2730
  
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2731
  return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2732
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2733
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2734
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2735
** This routine resolves any names used in the result set of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2736
** supplied SELECT statement. If the SELECT statement being resolved
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2737
** is a sub-select, then pOuterNC is a pointer to the NameContext 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2738
** of the parent SELECT.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2739
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2740
int sqlite3SelectResolve(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2741
  Parse *pParse,         /* The parser context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2742
  Select *p,             /* The SELECT statement being coded. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2743
  NameContext *pOuterNC  /* The outer name context. May be NULL. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2744
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2745
  ExprList *pEList;          /* Result set. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2746
  int i;                     /* For-loop variable used in multiple places */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2747
  NameContext sNC;           /* Local name-context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2748
  ExprList *pGroupBy;        /* The group by clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2749
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2750
  /* If this routine has run before, return immediately. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2751
  if( p->isResolved ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2752
    assert( !pOuterNC );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2753
    return SQLITE_OK;
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
  p->isResolved = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2756
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2757
  /* If there have already been errors, do nothing. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2758
  if( pParse->nErr>0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2759
    return SQLITE_ERROR;
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
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2762
  /* Prepare the select statement. This call will allocate all cursors
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2763
  ** required to handle the tables and subqueries in the FROM clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2764
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2765
  if( prepSelectStmt(pParse, p) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2766
    return SQLITE_ERROR;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2767
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2768
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2769
  /* Resolve the expressions in the LIMIT and OFFSET clauses. These
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2770
  ** are not allowed to refer to any names, so pass an empty NameContext.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2771
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2772
  memset(&sNC, 0, sizeof(sNC));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2773
  sNC.pParse = pParse;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2774
  if( sqlite3ExprResolveNames(&sNC, p->pLimit) ||
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2775
      sqlite3ExprResolveNames(&sNC, p->pOffset) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2776
    return SQLITE_ERROR;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2777
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2778
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2779
  /* Set up the local name-context to pass to ExprResolveNames() to
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2780
  ** resolve the expression-list.
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
  sNC.allowAgg = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2783
  sNC.pSrcList = p->pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2784
  sNC.pNext = pOuterNC;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2785
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2786
  /* Resolve names in the result set. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2787
  pEList = p->pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2788
  if( !pEList ) return SQLITE_ERROR;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2789
  for(i=0; i<pEList->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2790
    Expr *pX = pEList->a[i].pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2791
    if( sqlite3ExprResolveNames(&sNC, pX) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2792
      return SQLITE_ERROR;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2793
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2794
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2795
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2796
  /* If there are no aggregate functions in the result-set, and no GROUP BY 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2797
  ** expression, do not allow aggregates in any of the other expressions.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2798
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2799
  assert( !p->isAgg );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2800
  pGroupBy = p->pGroupBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2801
  if( pGroupBy || sNC.hasAgg ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2802
    p->isAgg = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2803
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2804
    sNC.allowAgg = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2805
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2806
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2807
  /* If a HAVING clause is present, then there must be a GROUP BY clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2808
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2809
  if( p->pHaving && !pGroupBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2810
    sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2811
    return SQLITE_ERROR;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2812
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2813
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2814
  /* Add the expression list to the name-context before parsing the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2815
  ** other expressions in the SELECT statement. This is so that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2816
  ** expressions in the WHERE clause (etc.) can refer to expressions by
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2817
  ** aliases in the result set.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2818
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2819
  ** Minor point: If this is the case, then the expression will be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2820
  ** re-evaluated for each reference to it.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2821
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2822
  sNC.pEList = p->pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2823
  if( sqlite3ExprResolveNames(&sNC, p->pWhere) ||
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2824
     sqlite3ExprResolveNames(&sNC, p->pHaving) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2825
    return SQLITE_ERROR;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2826
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2827
  if( p->pPrior==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2828
    if( processOrderGroupBy(pParse, p, p->pOrderBy, 1, &sNC.hasAgg) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2829
      return SQLITE_ERROR;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2830
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2831
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2832
  if( processOrderGroupBy(pParse, p, pGroupBy, 0, &sNC.hasAgg) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2833
    return SQLITE_ERROR;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2834
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2835
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2836
  if( pParse->db->mallocFailed ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2837
    return SQLITE_NOMEM;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2838
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2839
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2840
  /* Make sure the GROUP BY clause does not contain aggregate functions.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2841
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2842
  if( pGroupBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2843
	  ExprList::ExprList_item *pItem;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2844
  
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2845
    for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2846
      if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2847
        sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2848
            "the GROUP BY clause");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2849
        return SQLITE_ERROR;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2850
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2851
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2852
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2853
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2854
  /* If this is one SELECT of a compound, be sure to resolve names
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2855
  ** in the other SELECTs.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2856
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2857
  if( p->pPrior ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2858
    return sqlite3SelectResolve(pParse, p->pPrior, pOuterNC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2859
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2860
    return SQLITE_OK;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2861
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2862
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2863
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2864
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2865
** Reset the aggregate accumulator.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2866
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2867
** The aggregate accumulator is a set of memory cells that hold
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2868
** intermediate results while calculating an aggregate.  This
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2869
** routine simply stores NULLs in all of those memory cells.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2870
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2871
static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2872
  Vdbe *v = pParse->pVdbe;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2873
  int i=0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2874
  AggInfo::AggInfo_func *pFunc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2875
  if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2876
    return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2877
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2878
  for(i=0; i<pAggInfo->nColumn; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2879
    sqlite3VdbeAddOp(v, OP_MemNull, pAggInfo->aCol[i].iMem, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2880
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2881
  for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2882
    sqlite3VdbeAddOp(v, OP_MemNull, pFunc->iMem, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2883
    if( pFunc->iDistinct>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2884
      Expr *pE = pFunc->pExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2885
      if( pE->pList==0 || pE->pList->nExpr!=1 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2886
        sqlite3ErrorMsg(pParse, "DISTINCT in aggregate must be followed "
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2887
           "by an expression");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2888
        pFunc->iDistinct = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2889
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2890
        KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->pList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2891
        sqlite3VdbeOp3(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2892
                          (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2893
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2894
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2895
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2896
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2897
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2898
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2899
** Invoke the OP_AggFinalize opcode for every aggregate function
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2900
** in the AggInfo structure.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2901
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2902
static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2903
  Vdbe *v = pParse->pVdbe;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2904
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2905
  AggInfo::AggInfo_func *pF;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2906
  for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2907
    ExprList *pList = pF->pExpr->pList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2908
    sqlite3VdbeOp3(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2909
                      (const char*)pF->pFunc, P3_FUNCDEF);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2910
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2911
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2912
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2913
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2914
** Update the accumulator memory cells for an aggregate based on
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2915
** the current cursor position.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2916
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2917
static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2918
  Vdbe *v = pParse->pVdbe;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2919
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2920
  AggInfo::AggInfo_func *pF;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2921
  AggInfo::AggInfo_col *pC;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2922
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2923
  pAggInfo->directMode = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2924
  for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2925
    int nArg;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2926
    int addrNext = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2927
    ExprList *pList = pF->pExpr->pList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2928
    if( pList ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2929
      nArg = pList->nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2930
      sqlite3ExprCodeExprList(pParse, pList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2931
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2932
      nArg = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2933
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2934
    if( pF->iDistinct>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2935
      addrNext = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2936
      assert( nArg==1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2937
      codeDistinct(v, pF->iDistinct, addrNext, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2938
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2939
    if( pF->pFunc->needCollSeq ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2940
      CollSeq *pColl = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2941
	  ExprList::ExprList_item *pItem;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2942
      int j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2943
      assert( pList!=0 );  /* pList!=0 if pF->pFunc->needCollSeq is true */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2944
      for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2945
        pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2946
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2947
      if( !pColl ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2948
        pColl = pParse->db->pDfltColl;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2949
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2950
      sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2951
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2952
    sqlite3VdbeOp3(v, OP_AggStep, pF->iMem, nArg, (const char*)pF->pFunc, P3_FUNCDEF);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2953
    if( addrNext ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2954
      sqlite3VdbeResolveLabel(v, addrNext);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2955
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2956
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2957
  for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2958
    sqlite3ExprCode(pParse, pC->pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2959
    sqlite3VdbeAddOp(v, OP_MemStore, pC->iMem, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2960
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2961
  pAggInfo->directMode = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2962
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2963
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2964
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2965
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2966
** Generate code for the given SELECT statement.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2967
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2968
** The results are distributed in various ways depending on the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2969
** value of eDest and iParm.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2970
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2971
**     eDest Value       Result
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2972
**     ------------    -------------------------------------------
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2973
**     SRT_Callback    Invoke the callback for each row of the result.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2974
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2975
**     SRT_Mem         Store first result in memory cell iParm
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2976
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2977
**     SRT_Set         Store results as keys of table iParm.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2978
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2979
**     SRT_Union       Store results as a key in a temporary table iParm
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2980
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2981
**     SRT_Except      Remove results from the temporary table iParm.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2982
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2983
**     SRT_Table       Store results in temporary table iParm
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2984
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2985
** The table above is incomplete.  Additional eDist value have be added
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2986
** since this comment was written.  See the selectInnerLoop() function for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2987
** a complete listing of the allowed values of eDest and their meanings.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2988
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2989
** This routine returns the number of errors.  If any errors are
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2990
** encountered, then an appropriate error message is left in
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2991
** pParse->zErrMsg.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2992
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2993
** This routine does NOT free the Select structure passed in.  The
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2994
** calling function needs to do that.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2995
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2996
** The pParent, parentTab, and *pParentAgg fields are filled in if this
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2997
** SELECT is a subquery.  This routine may try to combine this SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2998
** with its parent to form a single flat query.  In so doing, it might
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  2999
** change the parent query from a non-aggregate to an aggregate query.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3000
** For that reason, the pParentAgg flag is passed as a pointer, so it
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3001
** can be changed.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3002
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3003
** Example 1:   The meaning of the pParent parameter.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3004
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3005
**    SELECT * FROM t1 JOIN (SELECT x, count(*) FROM t2) JOIN t3;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3006
**    \                      \_______ subquery _______/        /
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3007
**     \                                                      /
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3008
**      \____________________ outer query ___________________/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3009
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3010
** This routine is called for the outer query first.   For that call,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3011
** pParent will be NULL.  During the processing of the outer query, this 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3012
** routine is called recursively to handle the subquery.  For the recursive
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3013
** call, pParent will point to the outer query.  Because the subquery is
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3014
** the second element in a three-way join, the parentTab parameter will
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3015
** be 1 (the 2nd value of a 0-indexed array.)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3016
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3017
int sqlite3Select(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3018
  Parse *pParse,         /* The parser context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3019
  Select *p,             /* The SELECT statement being coded. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3020
  int eDest,             /* How to dispose of the results */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3021
  int iParm,             /* A parameter used by the eDest disposal method */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3022
  Select *pParent,       /* Another SELECT for which this is a sub-query */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3023
  int parentTab,         /* Index in pParent->pSrc of this query */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3024
  int *pParentAgg,       /* True if pParent uses aggregate functions */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3025
  char *aff              /* If eDest is SRT_Union, the affinity string */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3026
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3027
  int i, j;              /* Loop counters */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3028
  WhereInfo *pWInfo;     /* Return from sqlite3WhereBegin() */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3029
  Vdbe *v;               /* The virtual machine under construction */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3030
  int isAgg;             /* True for select lists like "count(*)" */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3031
  ExprList *pEList;      /* List of columns to extract. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3032
  SrcList *pTabList;     /* List of tables to select from */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3033
  Expr *pWhere;          /* The WHERE clause.  May be NULL */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3034
  ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3035
  ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3036
  Expr *pHaving;         /* The HAVING clause.  May be NULL */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3037
  int isDistinct;        /* True if the DISTINCT keyword is present */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3038
  int distinct;          /* Table to use for the distinct set */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3039
  int rc = 1;            /* Value to return from this function */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3040
  int addrSortIndex;     /* Address of an OP_OpenEphemeral instruction */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3041
  AggInfo sAggInfo;      /* Information used by aggregate queries */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3042
  int iEnd;              /* Address of the end of the query */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3043
  sqlite3 *db;           /* The database connection */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3044
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3045
  db = pParse->db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3046
  if( p==0 || db->mallocFailed || pParse->nErr ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3047
    return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3048
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3049
  if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3050
  memset(&sAggInfo, 0, sizeof(sAggInfo));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3051
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3052
  pOrderBy = p->pOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3053
  if( IgnorableOrderby(eDest) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3054
    p->pOrderBy = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3055
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3056
  if( sqlite3SelectResolve(pParse, p, 0) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3057
    goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3058
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3059
  p->pOrderBy = pOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3060
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3061
#ifndef SQLITE_OMIT_COMPOUND_SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3062
  /* If there is are a sequence of queries, do the earlier ones first.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3063
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3064
  if( p->pPrior ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3065
    if( p->pRightmost==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3066
      Select *pLoop, *pRight = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3067
      int cnt = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3068
      for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3069
        pLoop->pRightmost = p;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3070
        pLoop->pNext = pRight;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3071
        pRight = pLoop;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3072
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3073
      if( SQLITE_MAX_COMPOUND_SELECT>0 && cnt>SQLITE_MAX_COMPOUND_SELECT ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3074
        sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3075
        return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3076
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3077
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3078
    return multiSelect(pParse, p, eDest, iParm, aff);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3079
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3080
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3081
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3082
  /* Make local copies of the parameters for this query.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3083
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3084
  pTabList = p->pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3085
  pWhere = p->pWhere;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3086
  pGroupBy = p->pGroupBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3087
  pHaving = p->pHaving;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3088
  isAgg = p->isAgg;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3089
  isDistinct = p->isDistinct;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3090
  pEList = p->pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3091
  if( pEList==0 ) goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3092
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3093
  /* 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3094
  ** Do not even attempt to generate any code if we have already seen
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3095
  ** errors before this routine starts.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3096
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3097
  if( pParse->nErr>0 ) goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3098
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3099
  /* If writing to memory or generating a set
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3100
  ** only a single column may be output.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3101
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3102
#ifndef SQLITE_OMIT_SUBQUERY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3103
  if( checkForMultiColumnSelectError(pParse, eDest, pEList->nExpr) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3104
    goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3105
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3106
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3107
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3108
  /* ORDER BY is ignored for some destinations.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3109
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3110
  if( IgnorableOrderby(eDest) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3111
    pOrderBy = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3112
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3113
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3114
  /* Begin generating code.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3115
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3116
  v = sqlite3GetVdbe(pParse);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3117
  if( v==0 ) goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3118
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3119
  /* Generate code for all sub-queries in the FROM clause
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3120
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3121
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3122
  for(i=0; i<pTabList->nSrc; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3123
    const char *zSavedAuthContext = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3124
    int needRestoreContext;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3125
	SrcList::SrcList_item *pItem = &pTabList->a[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3126
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3127
    if( pItem->pSelect==0 || pItem->isPopulated ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3128
    if( pItem->zName!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3129
      zSavedAuthContext = pParse->zAuthContext;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3130
      pParse->zAuthContext = pItem->zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3131
      needRestoreContext = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3132
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3133
      needRestoreContext = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3134
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3135
#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3136
    /* Increment Parse.nHeight by the height of the largest expression
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3137
    ** tree refered to by this, the parent select. The child select
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3138
    ** may contain expression trees of at most
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3139
    ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3140
    ** more conservative than necessary, but much easier than enforcing
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3141
    ** an exact limit.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3142
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3143
    pParse->nHeight += sqlite3SelectExprHeight(p);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3144
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3145
    sqlite3Select(pParse, pItem->pSelect, SRT_EphemTab, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3146
                 pItem->iCursor, p, i, &isAgg, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3147
    if( db->mallocFailed ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3148
      goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3149
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3150
#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3151
    pParse->nHeight -= sqlite3SelectExprHeight(p);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3152
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3153
    if( needRestoreContext ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3154
      pParse->zAuthContext = zSavedAuthContext;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3155
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3156
    pTabList = p->pSrc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3157
    pWhere = p->pWhere;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3158
    if( !IgnorableOrderby(eDest) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3159
      pOrderBy = p->pOrderBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3160
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3161
    pGroupBy = p->pGroupBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3162
    pHaving = p->pHaving;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3163
    isDistinct = p->isDistinct;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3164
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3165
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3166
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3167
  /* Check for the special case of a min() or max() function by itself
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3168
  ** in the result set.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3169
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3170
  if( simpleMinMaxQuery(pParse, p, eDest, iParm) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3171
    rc = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3172
    goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3173
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3174
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3175
  /* Check to see if this is a subquery that can be "flattened" into its parent.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3176
  ** If flattening is a possiblity, do so and return immediately.  
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3177
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3178
#ifndef SQLITE_OMIT_VIEW
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3179
  if( pParent && pParentAgg &&
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3180
      flattenSubquery(db, pParent, parentTab, *pParentAgg, isAgg) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3181
    if( isAgg ) *pParentAgg = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3182
    goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3183
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3184
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3185
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3186
  /* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3187
  ** GROUP BY may use an index, DISTINCT never does.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3188
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3189
  if( p->isDistinct && !p->isAgg && !p->pGroupBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3190
    p->pGroupBy = sqlite3ExprListDup(db, p->pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3191
    pGroupBy = p->pGroupBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3192
    p->isDistinct = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3193
    isDistinct = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3194
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3195
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3196
  /* If there is an ORDER BY clause, then this sorting
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3197
  ** index might end up being unused if the data can be 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3198
  ** extracted in pre-sorted order.  If that is the case, then the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3199
  ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3200
  ** we figure out that the sorting index is not needed.  The addrSortIndex
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3201
  ** variable is used to facilitate that change.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3202
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3203
  if( pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3204
    KeyInfo *pKeyInfo;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3205
    if( pParse->nErr ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3206
      goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3207
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3208
    pKeyInfo = keyInfoFromExprList(pParse, pOrderBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3209
    pOrderBy->iECursor = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3210
    p->addrOpenEphm[2] = addrSortIndex =
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3211
      sqlite3VdbeOp3(v, OP_OpenEphemeral, pOrderBy->iECursor, pOrderBy->nExpr+2,                     (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3212
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3213
    addrSortIndex = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3214
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3215
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3216
  /* If the output is destined for a temporary table, open that table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3217
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3218
  if( eDest==SRT_EphemTab ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3219
    sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, pEList->nExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3220
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3221
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3222
  /* Set the limiter.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3223
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3224
  iEnd = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3225
  computeLimitRegisters(pParse, p, iEnd);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3226
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3227
  /* Open a virtual index to use for the distinct set.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3228
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3229
  if( isDistinct ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3230
    KeyInfo *pKeyInfo;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3231
    assert( isAgg || pGroupBy );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3232
    distinct = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3233
    pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3234
    sqlite3VdbeOp3(v, OP_OpenEphemeral, distinct, 0, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3235
                        (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3236
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3237
    distinct = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3238
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3239
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3240
  /* Aggregate and non-aggregate queries are handled differently */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3241
  if( !isAgg && pGroupBy==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3242
    /* This case is for non-aggregate queries
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3243
    ** Begin the database scan
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3244
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3245
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3246
    if( pWInfo==0 ) goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3247
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3248
    /* If sorting index that was created by a prior OP_OpenEphemeral 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3249
    ** instruction ended up not being needed, then change the OP_OpenEphemeral
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3250
    ** into an OP_Noop.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3251
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3252
    if( addrSortIndex>=0 && pOrderBy==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3253
      sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3254
      p->addrOpenEphm[2] = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3255
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3256
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3257
    /* Use the standard inner loop
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3258
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3259
    assert(!isDistinct);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3260
    if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, eDest,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3261
                    iParm, pWInfo->iContinue, pWInfo->iBreak, aff) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3262
       goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3263
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3264
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3265
    /* End the database scan loop.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3266
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3267
    sqlite3WhereEnd(pWInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3268
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3269
    /* This is the processing for aggregate queries */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3270
    NameContext sNC;    /* Name context for processing aggregate information */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3271
    int iAMem;          /* First Mem address for storing current GROUP BY */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3272
    int iBMem;          /* First Mem address for previous GROUP BY */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3273
    int iUseFlag;       /* Mem address holding flag indicating that at least
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3274
                        ** one row of the input to the aggregator has been
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3275
                        ** processed */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3276
    int iAbortFlag;     /* Mem address which causes query abort if positive */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3277
    int groupBySort;    /* Rows come from source in GROUP BY order */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3278
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3279
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3280
    /* The following variables hold addresses or labels for parts of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3281
    ** virtual machine program we are putting together */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3282
    int addrOutputRow;      /* Start of subroutine that outputs a result row */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3283
    int addrSetAbort;       /* Set the abort flag and return */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3284
    int addrInitializeLoop; /* Start of code that initializes the input loop */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3285
    int addrTopOfLoop;      /* Top of the input loop */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3286
    int addrGroupByChange;  /* Code that runs when any GROUP BY term changes */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3287
    int addrProcessRow;     /* Code to process a single input row */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3288
    int addrEnd;            /* End of all processing */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3289
    int addrSortingIdx;     /* The OP_OpenEphemeral for the sorting index */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3290
    int addrReset;          /* Subroutine for resetting the accumulator */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3291
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3292
    addrEnd = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3293
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3294
    /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3295
    ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3296
    ** SELECT statement.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3297
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3298
    memset(&sNC, 0, sizeof(sNC));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3299
    sNC.pParse = pParse;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3300
    sNC.pSrcList = pTabList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3301
    sNC.pAggInfo = &sAggInfo;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3302
    sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3303
    sAggInfo.pGroupBy = pGroupBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3304
    if( sqlite3ExprAnalyzeAggList(&sNC, pEList) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3305
      goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3306
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3307
    if( sqlite3ExprAnalyzeAggList(&sNC, pOrderBy) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3308
      goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3309
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3310
    if( pHaving && sqlite3ExprAnalyzeAggregates(&sNC, pHaving) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3311
      goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3312
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3313
    sAggInfo.nAccumulator = sAggInfo.nColumn;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3314
    for(i=0; i<sAggInfo.nFunc; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3315
      if( sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->pList) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3316
        goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3317
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3318
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3319
    if( db->mallocFailed ) goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3320
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3321
    /* Processing for aggregates with GROUP BY is very different and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3322
    ** much more complex than aggregates without a GROUP BY.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3323
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3324
    if( pGroupBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3325
      KeyInfo *pKeyInfo;  /* Keying information for the group by clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3326
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3327
      /* Create labels that we will be needing
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3328
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3329
     
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3330
      addrInitializeLoop = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3331
      addrGroupByChange = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3332
      addrProcessRow = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3333
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3334
      /* If there is a GROUP BY clause we might need a sorting index to
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3335
      ** implement it.  Allocate that sorting index now.  If it turns out
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3336
      ** that we do not need it after all, the OpenEphemeral instruction
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3337
      ** will be converted into a Noop.  
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3338
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3339
      sAggInfo.sortingIdx = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3340
      pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3341
      addrSortingIdx =
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3342
          sqlite3VdbeOp3(v, OP_OpenEphemeral, sAggInfo.sortingIdx,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3343
                         sAggInfo.nSortingColumn,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3344
                         (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3345
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3346
      /* Initialize memory locations used by GROUP BY aggregate processing
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3347
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3348
      iUseFlag = pParse->nMem++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3349
      iAbortFlag = pParse->nMem++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3350
      iAMem = pParse->nMem;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3351
      pParse->nMem += pGroupBy->nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3352
      iBMem = pParse->nMem;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3353
      pParse->nMem += pGroupBy->nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3354
      sqlite3VdbeAddOp(v, OP_MemInt, 0, iAbortFlag);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3355
      VdbeComment((v, "# clear abort flag"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3356
      sqlite3VdbeAddOp(v, OP_MemInt, 0, iUseFlag);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3357
      VdbeComment((v, "# indicate accumulator empty"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3358
      sqlite3VdbeAddOp(v, OP_Goto, 0, addrInitializeLoop);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3359
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3360
      /* Generate a subroutine that outputs a single row of the result
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3361
      ** set.  This subroutine first looks at the iUseFlag.  If iUseFlag
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3362
      ** is less than or equal to zero, the subroutine is a no-op.  If
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3363
      ** the processing calls for the query to abort, this subroutine
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3364
      ** increments the iAbortFlag memory location before returning in
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3365
      ** order to signal the caller to abort.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3366
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3367
      addrSetAbort = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3368
      sqlite3VdbeAddOp(v, OP_MemInt, 1, iAbortFlag);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3369
      VdbeComment((v, "# set abort flag"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3370
      sqlite3VdbeAddOp(v, OP_Return, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3371
      addrOutputRow = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3372
      sqlite3VdbeAddOp(v, OP_IfMemPos, iUseFlag, addrOutputRow+2);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3373
      VdbeComment((v, "# Groupby result generator entry point"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3374
      sqlite3VdbeAddOp(v, OP_Return, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3375
      finalizeAggFunctions(pParse, &sAggInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3376
      if( pHaving ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3377
        sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3378
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3379
      rc = selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3380
                           distinct, eDest, iParm, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3381
                           addrOutputRow+1, addrSetAbort, aff);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3382
      if( rc ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3383
        goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3384
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3385
      sqlite3VdbeAddOp(v, OP_Return, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3386
      VdbeComment((v, "# end groupby result generator"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3387
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3388
      /* Generate a subroutine that will reset the group-by accumulator
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3389
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3390
      addrReset = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3391
      resetAccumulator(pParse, &sAggInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3392
      sqlite3VdbeAddOp(v, OP_Return, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3393
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3394
      /* Begin a loop that will extract all source rows in GROUP BY order.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3395
      ** This might involve two separate loops with an OP_Sort in between, or
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3396
      ** it might be a single loop that uses an index to extract information
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3397
      ** in the right order to begin with.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3398
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3399
      sqlite3VdbeResolveLabel(v, addrInitializeLoop);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3400
      sqlite3VdbeAddOp(v, OP_Gosub, 0, addrReset);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3401
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3402
      if( pWInfo==0 ) goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3403
      if( pGroupBy==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3404
        /* The optimizer is able to deliver rows in group by order so
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3405
        ** we do not have to sort.  The OP_OpenEphemeral table will be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3406
        ** cancelled later because we still need to use the pKeyInfo
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3407
        */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3408
        pGroupBy = p->pGroupBy;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3409
        groupBySort = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3410
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3411
        /* Rows are coming out in undetermined order.  We have to push
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3412
        ** each row into a sorting index, terminate the first loop,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3413
        ** then loop over the sorting index in order to get the output
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3414
        ** in sorted order
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3415
        */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3416
        groupBySort = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3417
        sqlite3ExprCodeExprList(pParse, pGroupBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3418
        sqlite3VdbeAddOp(v, OP_Sequence, sAggInfo.sortingIdx, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3419
        j = pGroupBy->nExpr+1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3420
        for(i=0; i<sAggInfo.nColumn; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3421
			AggInfo::AggInfo_col *pCol = &sAggInfo.aCol[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3422
          if( pCol->iSorterColumn<j ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3423
          sqlite3ExprCodeGetColumn(v, pCol->pTab, pCol->iColumn, pCol->iTable);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3424
          j++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3425
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3426
        sqlite3VdbeAddOp(v, OP_MakeRecord, j, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3427
        sqlite3VdbeAddOp(v, OP_IdxInsert, sAggInfo.sortingIdx, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3428
        sqlite3WhereEnd(pWInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3429
        sqlite3VdbeAddOp(v, OP_Sort, sAggInfo.sortingIdx, addrEnd);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3430
        VdbeComment((v, "# GROUP BY sort"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3431
        sAggInfo.useSortingIdx = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3432
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3433
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3434
      /* Evaluate the current GROUP BY terms and store in b0, b1, b2...
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3435
      ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3436
      ** Then compare the current GROUP BY terms against the GROUP BY terms
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3437
      ** from the previous row currently stored in a0, a1, a2...
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3438
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3439
      addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3440
      for(j=0; j<pGroupBy->nExpr; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3441
        if( groupBySort ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3442
          sqlite3VdbeAddOp(v, OP_Column, sAggInfo.sortingIdx, j);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3443
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3444
          sAggInfo.directMode = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3445
          sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3446
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3447
        sqlite3VdbeAddOp(v, OP_MemStore, iBMem+j, j<pGroupBy->nExpr-1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3448
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3449
      for(j=pGroupBy->nExpr-1; j>=0; j--){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3450
        if( j<pGroupBy->nExpr-1 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3451
          sqlite3VdbeAddOp(v, OP_MemLoad, iBMem+j, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3452
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3453
        sqlite3VdbeAddOp(v, OP_MemLoad, iAMem+j, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3454
        if( j==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3455
          sqlite3VdbeAddOp(v, OP_Eq, 0x200, addrProcessRow);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3456
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3457
          sqlite3VdbeAddOp(v, OP_Ne, 0x200, addrGroupByChange);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3458
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3459
        sqlite3VdbeChangeP3(v, -1, (const char*)pKeyInfo->aColl[j], P3_COLLSEQ);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3460
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3461
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3462
      /* Generate code that runs whenever the GROUP BY changes.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3463
      ** Change in the GROUP BY are detected by the previous code
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3464
      ** block.  If there were no changes, this block is skipped.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3465
      **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3466
      ** This code copies current group by terms in b0,b1,b2,...
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3467
      ** over to a0,a1,a2.  It then calls the output subroutine
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3468
      ** and resets the aggregate accumulator registers in preparation
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3469
      ** for the next GROUP BY batch.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3470
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3471
      sqlite3VdbeResolveLabel(v, addrGroupByChange);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3472
      for(j=0; j<pGroupBy->nExpr; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3473
        sqlite3VdbeAddOp(v, OP_MemMove, iAMem+j, iBMem+j);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3474
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3475
      sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3476
      VdbeComment((v, "# output one row"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3477
      sqlite3VdbeAddOp(v, OP_IfMemPos, iAbortFlag, addrEnd);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3478
      VdbeComment((v, "# check abort flag"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3479
      sqlite3VdbeAddOp(v, OP_Gosub, 0, addrReset);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3480
      VdbeComment((v, "# reset accumulator"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3481
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3482
      /* Update the aggregate accumulators based on the content of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3483
      ** the current row
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3484
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3485
      sqlite3VdbeResolveLabel(v, addrProcessRow);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3486
      updateAccumulator(pParse, &sAggInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3487
      sqlite3VdbeAddOp(v, OP_MemInt, 1, iUseFlag);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3488
      VdbeComment((v, "# indicate data in accumulator"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3489
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3490
      /* End of the loop
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3491
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3492
      if( groupBySort ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3493
        sqlite3VdbeAddOp(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3494
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3495
        sqlite3WhereEnd(pWInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3496
        sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3497
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3498
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3499
      /* Output the final row of result
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3500
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3501
      sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3502
      VdbeComment((v, "# output final row"));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3503
      
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3504
    } /* endif pGroupBy */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3505
    else {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3506
      /* This case runs if the aggregate has no GROUP BY clause.  The
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3507
      ** processing is much simpler since there is only a single row
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3508
      ** of output.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3509
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3510
      resetAccumulator(pParse, &sAggInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3511
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3512
      if( pWInfo==0 ) goto select_end;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3513
      updateAccumulator(pParse, &sAggInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3514
      sqlite3WhereEnd(pWInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3515
      finalizeAggFunctions(pParse, &sAggInfo);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3516
      pOrderBy = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3517
      if( pHaving ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3518
        sqlite3ExprIfFalse(pParse, pHaving, addrEnd, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3519
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3520
      selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3521
                      eDest, iParm, addrEnd, addrEnd, aff);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3522
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3523
    sqlite3VdbeResolveLabel(v, addrEnd);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3524
    
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3525
  } /* endif aggregate query */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3526
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3527
  /* If there is an ORDER BY clause, then we need to sort the results
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3528
  ** and send them to the callback one by one.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3529
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3530
  if( pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3531
    generateSortTail(pParse, p, v, pEList->nExpr, eDest, iParm);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3532
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3533
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3534
#ifndef SQLITE_OMIT_SUBQUERY
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3535
  /* If this was a subquery, we have now converted the subquery into a
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3536
  ** temporary table.  So set the SrcList_item.isPopulated flag to prevent
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3537
  ** this subquery from being evaluated again and to force the use of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3538
  ** the temporary table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3539
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3540
  if( pParent ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3541
    assert( pParent->pSrc->nSrc>parentTab );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3542
    assert( pParent->pSrc->a[parentTab].pSelect==p );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3543
    pParent->pSrc->a[parentTab].isPopulated = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3544
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3545
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3546
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3547
  /* Jump here to skip this query
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3548
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3549
  sqlite3VdbeResolveLabel(v, iEnd);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3550
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3551
  /* The SELECT was successfully coded.   Set the return code to 0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3552
  ** to indicate no errors.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3553
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3554
  rc = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3555
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3556
  /* Control jumps to here if an error is encountered above, or upon
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3557
  ** successful coding of the SELECT.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3558
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3559
select_end:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3560
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3561
  /* Identify column names if we will be using them in a callback.  This
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3562
  ** step is skipped if the output is going to some other destination.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3563
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3564
  if( rc==SQLITE_OK && eDest==SRT_Callback ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3565
    generateColumnNames(pParse, pTabList, pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3566
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3567
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3568
  sqlite3_free(sAggInfo.aCol);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3569
  sqlite3_free(sAggInfo.aFunc);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3570
  return rc;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3571
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3572
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3573
#if defined(SQLITE_DEBUG)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3574
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3575
*******************************************************************************
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3576
** The following code is used for testing and debugging only.  The code
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3577
** that follows does not appear in normal builds.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3578
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3579
** These routines are used to print out the content of all or part of a 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3580
** parse structures such as Select or Expr.  Such printouts are useful
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3581
** for helping to understand what is happening inside the code generator
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3582
** during the execution of complex SELECT statements.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3583
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3584
** These routine are not called anywhere from within the normal
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3585
** code base.  Then are intended to be called from within the debugger
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3586
** or from temporary "printf" statements inserted for debugging.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3587
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3588
void sqlite3PrintExpr(Expr *p){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3589
  if( p->token.z && p->token.n>0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3590
    sqlite3DebugPrintf("(%.*s", p->token.n, p->token.z);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3591
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3592
    sqlite3DebugPrintf("(%d", p->op);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3593
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3594
  if( p->pLeft ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3595
    sqlite3DebugPrintf(" ");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3596
    sqlite3PrintExpr(p->pLeft);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3597
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3598
  if( p->pRight ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3599
    sqlite3DebugPrintf(" ");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3600
    sqlite3PrintExpr(p->pRight);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3601
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3602
  sqlite3DebugPrintf(")");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3603
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3604
void sqlite3PrintExprList(ExprList *pList){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3605
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3606
  for(i=0; i<pList->nExpr; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3607
    sqlite3PrintExpr(pList->a[i].pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3608
    if( i<pList->nExpr-1 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3609
      sqlite3DebugPrintf(", ");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3610
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3611
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3612
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3613
void sqlite3PrintSelect(Select *p, int indent){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3614
  sqlite3DebugPrintf("%*sSELECT(%p) ", indent, "", p);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3615
  sqlite3PrintExprList(p->pEList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3616
  sqlite3DebugPrintf("\n");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3617
  if( p->pSrc ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3618
    char *zPrefix;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3619
    int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3620
    zPrefix = "FROM";
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3621
    for(i=0; i<p->pSrc->nSrc; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3622
      struct SrcList_item *pItem = &p->pSrc->a[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3623
      sqlite3DebugPrintf("%*s ", indent+6, zPrefix);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3624
      zPrefix = "";
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3625
      if( pItem->pSelect ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3626
        sqlite3DebugPrintf("(\n");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3627
        sqlite3PrintSelect(pItem->pSelect, indent+10);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3628
        sqlite3DebugPrintf("%*s)", indent+8, "");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3629
      }else if( pItem->zName ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3630
        sqlite3DebugPrintf("%s", pItem->zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3631
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3632
      if( pItem->pTab ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3633
        sqlite3DebugPrintf("(table: %s)", pItem->pTab->zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3634
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3635
      if( pItem->zAlias ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3636
        sqlite3DebugPrintf(" AS %s", pItem->zAlias);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3637
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3638
      if( i<p->pSrc->nSrc-1 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3639
        sqlite3DebugPrintf(",");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3640
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3641
      sqlite3DebugPrintf("\n");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3642
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3643
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3644
  if( p->pWhere ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3645
    sqlite3DebugPrintf("%*s WHERE ", indent, "");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3646
    sqlite3PrintExpr(p->pWhere);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3647
    sqlite3DebugPrintf("\n");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3648
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3649
  if( p->pGroupBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3650
    sqlite3DebugPrintf("%*s GROUP BY ", indent, "");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3651
    sqlite3PrintExprList(p->pGroupBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3652
    sqlite3DebugPrintf("\n");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3653
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3654
  if( p->pHaving ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3655
    sqlite3DebugPrintf("%*s HAVING ", indent, "");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3656
    sqlite3PrintExpr(p->pHaving);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3657
    sqlite3DebugPrintf("\n");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3658
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3659
  if( p->pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3660
    sqlite3DebugPrintf("%*s ORDER BY ", indent, "");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3661
    sqlite3PrintExprList(p->pOrderBy);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3662
    sqlite3DebugPrintf("\n");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3663
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3664
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3665
/* End of the structure debug printing code
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3666
*****************************************************************************/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  3667
#endif /* defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */