/ Check-in [ffbdd43f]
Login

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

Overview
Comment:Added the ability to say things like "SELECT rowid, * FROM table1;" (CVS 332)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:ffbdd43f5de62e7bf81631c83473aca29c3a6c98
User & Date: drh 2001-12-16 20:05:05
Context
2001-12-21
14:30
Added support for the INTEGER PRIMARY KEY column type. (CVS 333) check-in: 236a54d2 user: drh tags: trunk
2001-12-16
20:05
Added the ability to say things like "SELECT rowid, * FROM table1;" (CVS 332) check-in: ffbdd43f user: drh tags: trunk
2001-12-15
14:22
Comment and documentation changes. (CVS 331) check-in: e8595579 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to VERSION.

1
2.1.7
|
1
2.1.8

Changes to src/parse.y.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
194
195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
210
211
212



213
214
215
216
217
218
219
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.38 2001/11/06 04:00:18 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  sqliteSetString(&pParse->zErrMsg,"syntax error",0);
................................................................................
//
%type distinct {int}
distinct(A) ::= DISTINCT.   {A = 1;}
distinct(A) ::= ALL.        {A = 0;}
distinct(A) ::= .           {A = 0;}

// selcollist is a list of expressions that are to become the return
// values of the SELECT statement.  In the case of "SELECT * FROM ..."
// the selcollist value is NULL.  

//
%type selcollist {ExprList*}
%destructor selcollist {sqliteExprListDelete($$);}
%type sclp {ExprList*}
%destructor sclp {sqliteExprListDelete($$);}
sclp(A) ::= selcollist(X) COMMA.             {A = X;}
sclp(A) ::= .                                {A = 0;}
selcollist(A) ::= STAR.                      {A = 0;}
selcollist(A) ::= sclp(P) expr(X).           {A = sqliteExprListAppend(P,X,0);}
selcollist(A) ::= sclp(P) expr(X) as ids(Y). {A = sqliteExprListAppend(P,X,&Y);}



as ::= .
as ::= AS.


%type seltablist {IdList*}
%destructor seltablist {sqliteIdListDelete($$);}
%type stl_prefix {IdList*}







|







 







|
|
>







<


>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

211
212
213
214
215
216
217
218
219
220
221
222
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.39 2001/12/16 20:05:06 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  sqliteSetString(&pParse->zErrMsg,"syntax error",0);
................................................................................
//
%type distinct {int}
distinct(A) ::= DISTINCT.   {A = 1;}
distinct(A) ::= ALL.        {A = 0;}
distinct(A) ::= .           {A = 0;}

// selcollist is a list of expressions that are to become the return
// values of the SELECT statement.  The "*" in statements like
// "SELECT * FROM ..." is encoded as a special expression with an
// opcode of TK_ALL.
//
%type selcollist {ExprList*}
%destructor selcollist {sqliteExprListDelete($$);}
%type sclp {ExprList*}
%destructor sclp {sqliteExprListDelete($$);}
sclp(A) ::= selcollist(X) COMMA.             {A = X;}
sclp(A) ::= .                                {A = 0;}

selcollist(A) ::= sclp(P) expr(X).           {A = sqliteExprListAppend(P,X,0);}
selcollist(A) ::= sclp(P) expr(X) as ids(Y). {A = sqliteExprListAppend(P,X,&Y);}
selcollist(A) ::= sclp(P) STAR. {
  A = sqliteExprListAppend(P, sqliteExpr(TK_ALL, 0, 0, 0), 0);
}
as ::= .
as ::= AS.


%type seltablist {IdList*}
%destructor seltablist {sqliteIdListDelete($$);}
%type stl_prefix {IdList*}

Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
...
349
350
351
352
353
354
355
356



357
358
359













360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382



383
384
385
386
387
388
389
390
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.49 2001/11/07 16:48:27 drh Exp $
*/
#include "sqliteInt.h"

/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
................................................................................
**         create a fake pEList containing the names of all columns
**         of all tables.
**
** Return 0 on success.  If there are problems, leave an error message
** in pParse and return non-zero.
*/
static int fillInColumnList(Parse *pParse, Select *p){
  int i, j;
  IdList *pTabList;
  ExprList *pEList;

  if( p==0 || p->pSrc==0 ) return 1;
  pTabList = p->pSrc;
  pEList = p->pEList;

................................................................................
      sqliteSetString(&pParse->zErrMsg, "no such table: ", 
         pTabList->a[i].zName, 0);
      pParse->nErr++;
      return 1;
    }
  }

  /* If the list of columns to retrieve is "*" then replace it with



  ** a list of all columns from all tables.
  */
  if( pEList==0 ){













    for(i=0; i<pTabList->nId; i++){
      Table *pTab = pTabList->a[i].pTab;
      for(j=0; j<pTab->nCol; j++){
        Expr *pExpr = sqliteExpr(TK_DOT, 0, 0, 0);
        if( pExpr==0 ) break;
        pExpr->pLeft = sqliteExpr(TK_ID, 0, 0, 0);
        if( pExpr->pLeft==0 ){ sqliteExprDelete(pExpr); break; }
        if( pTabList->a[i].zAlias && pTabList->a[i].zAlias[0] ){
          pExpr->pLeft->token.z = pTabList->a[i].zAlias;
          pExpr->pLeft->token.n = strlen(pTabList->a[i].zAlias);
        }else{
          pExpr->pLeft->token.z = pTab->zName;
          pExpr->pLeft->token.n = strlen(pTab->zName);
        }
        pExpr->pRight = sqliteExpr(TK_ID, 0, 0, 0);
        if( pExpr->pRight==0 ){ sqliteExprDelete(pExpr); break; }
        pExpr->pRight->token.z = pTab->aCol[j].zName;
        pExpr->pRight->token.n = strlen(pTab->aCol[j].zName);
        pExpr->span.z = "";
        pExpr->span.n = 0;
        pEList = sqliteExprListAppend(pEList, pExpr, 0);
      }
    }



    p->pEList = pEList;
  }
  return 0;
}

/*
** This routine associates entries in an ORDER BY expression list with
** columns in a result.  For each ORDER BY expression, the opcode of







|







 







|







 







|
>
>
>
|

<
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
...
349
350
351
352
353
354
355
356
357
358
359
360
361

362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.50 2001/12/16 20:05:06 drh Exp $
*/
#include "sqliteInt.h"

/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
................................................................................
**         create a fake pEList containing the names of all columns
**         of all tables.
**
** Return 0 on success.  If there are problems, leave an error message
** in pParse and return non-zero.
*/
static int fillInColumnList(Parse *pParse, Select *p){
  int i, j, k;
  IdList *pTabList;
  ExprList *pEList;

  if( p==0 || p->pSrc==0 ) return 1;
  pTabList = p->pSrc;
  pEList = p->pEList;

................................................................................
      sqliteSetString(&pParse->zErrMsg, "no such table: ", 
         pTabList->a[i].zName, 0);
      pParse->nErr++;
      return 1;
    }
  }

  /* For every "*" that occurs in the column list, insert the names of
  ** all columns in all tables.  The parser inserted a special expression
  ** with the TK_ALL operator for each "*" that it found in the column list.
  ** The following code just has to locate the TK_ALL expressions and expand
  ** each one to the list of all columns in all tables.
  */

  for(k=0; k<pEList->nExpr; k++){
    if( pEList->a[k].pExpr->op==TK_ALL ) break;
  }
  if( k<pEList->nExpr ){
    struct ExprList_item *a = pEList->a;
    ExprList *pNew = 0;
    for(k=0; k<pEList->nExpr; k++){
      if( a[k].pExpr->op!=TK_ALL ){
        pNew = sqliteExprListAppend(pNew, a[k].pExpr, 0);
        pNew->a[pNew->nExpr-1].zName = a[k].zName;
        a[k].pExpr = 0;
        a[k].zName = 0;
      }else{
        for(i=0; i<pTabList->nId; i++){
          Table *pTab = pTabList->a[i].pTab;
          for(j=0; j<pTab->nCol; j++){
            Expr *pExpr = sqliteExpr(TK_DOT, 0, 0, 0);
            if( pExpr==0 ) break;
            pExpr->pLeft = sqliteExpr(TK_ID, 0, 0, 0);
            if( pExpr->pLeft==0 ){ sqliteExprDelete(pExpr); break; }
            if( pTabList->a[i].zAlias && pTabList->a[i].zAlias[0] ){
              pExpr->pLeft->token.z = pTabList->a[i].zAlias;
              pExpr->pLeft->token.n = strlen(pTabList->a[i].zAlias);
            }else{
              pExpr->pLeft->token.z = pTab->zName;
              pExpr->pLeft->token.n = strlen(pTab->zName);
            }
            pExpr->pRight = sqliteExpr(TK_ID, 0, 0, 0);
            if( pExpr->pRight==0 ){ sqliteExprDelete(pExpr); break; }
            pExpr->pRight->token.z = pTab->aCol[j].zName;
            pExpr->pRight->token.n = strlen(pTab->aCol[j].zName);
            pExpr->span.z = "";
            pExpr->span.n = 0;
            pNew = sqliteExprListAppend(pNew, pExpr, 0);
          }
        }
      }
    }
    sqliteExprListDelete(pEList);
    p->pEList = pNew;
  }
  return 0;
}

/*
** This routine associates entries in an ORDER BY expression list with
** columns in a result.  For each ORDER BY expression, the opcode of

Changes to test/select1.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
50
51
52
53
54
55
56









57
58
59
60
61
62
63






64
65
66
67
68
69
70
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the SELECT statement.
#
# $Id: select1.test,v 1.15 2001/11/06 14:10:42 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to select on a non-existant table.
#
do_test select1-1.1 {
................................................................................
} {22 11}
do_test select1-1.7 {
  execsql {SELECT f1, f2 FROM test1}
} {11 22}
do_test select1-1.8 {
  execsql {SELECT * FROM test1}
} {11 22}










execsql {CREATE TABLE test2(r1 real, r2 real)}
execsql {INSERT INTO test2(r1,r2) VALUES(1.1,2.2)}

do_test select1-1.9 {
  execsql {SELECT * FROM test1, test2}
} {11 22 1.1 2.2}






do_test select1-1.10 {
  execsql {SELECT test1.f1, test2.r1 FROM test1, test2}
} {11 1.1}
do_test select1-1.11 {
  execsql {SELECT test1.f1, test2.r1 FROM test2, test1}
} {11 1.1}
do_test select1-1.11.1 {







|







 







>
>
>
>
>
>
>
>
>







>
>
>
>
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the SELECT statement.
#
# $Id: select1.test,v 1.16 2001/12/16 20:05:06 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to select on a non-existant table.
#
do_test select1-1.1 {
................................................................................
} {22 11}
do_test select1-1.7 {
  execsql {SELECT f1, f2 FROM test1}
} {11 22}
do_test select1-1.8 {
  execsql {SELECT * FROM test1}
} {11 22}
do_test select1-1.8.1 {
  execsql {SELECT *, * FROM test1}
} {11 22 11 22}
do_test select1-1.8.2 {
  execsql {SELECT *, min(f1,f2), max(f1,f2) FROM test1}
} {11 22 11 22}
do_test select1-1.8.3 {
  execsql {SELECT 'one', *, 'two', * FROM test1}
} {one 11 22 two 11 22}

execsql {CREATE TABLE test2(r1 real, r2 real)}
execsql {INSERT INTO test2(r1,r2) VALUES(1.1,2.2)}

do_test select1-1.9 {
  execsql {SELECT * FROM test1, test2}
} {11 22 1.1 2.2}
do_test select1-1.9.1 {
  execsql {SELECT *, 'hi' FROM test1, test2}
} {11 22 1.1 2.2 hi}
do_test select1-1.9.2 {
  execsql {SELECT 'one', *, 'two', * FROM test1, test2}
} {one 11 22 1.1 2.2 two 11 22 1.1 2.2}
do_test select1-1.10 {
  execsql {SELECT test1.f1, test2.r1 FROM test1, test2}
} {11 1.1}
do_test select1-1.11 {
  execsql {SELECT test1.f1, test2.r1 FROM test2, test1}
} {11 1.1}
do_test select1-1.11.1 {

Changes to www/changes.tcl.

12
13
14
15
16
17
18







19
20
21
22
23
24
25
}


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}








chng {2001 Dec 14 (2.1.7)} {
<li>Fix a bug in <b>CREATE TEMPORARY TABLE</b> which was causing the
    table to be initially allocated in the main database file instead
    of in the separate temporary file.  This bug could cause the library
    to suffer an assertion failure and it could cause "page leaks" in the
    main database file.







>
>
>
>
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
}


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}

chng {2001 Dec 16 (2.1.8)} {
<li>Added the ability to specify "*" as part of a larger column list in
    the result section of a SELECT statement.  For example:
    <nobr>"<b>SELECT rowid, * FROM table1;</b>"</nobr>.</li>
<li>Updates to comments and documentation.</li>
}

chng {2001 Dec 14 (2.1.7)} {
<li>Fix a bug in <b>CREATE TEMPORARY TABLE</b> which was causing the
    table to be initially allocated in the main database file instead
    of in the separate temporary file.  This bug could cause the library
    to suffer an assertion failure and it could cause "page leaks" in the
    main database file.