SQLite

Check-in [55e7d65496]
Login

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

Overview
Comment:Double-quoted strings resolve to column names if possible. Single-quoted strings continue to be interpreted as string literals. (CVS 576)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 55e7d65496624c8e48673d8747f3123786bfedbc
User & Date: drh 2002-05-21 13:43:04.000
Context
2002-05-21
23:44
Fix for ticket #47: Use a cast to avoid a warning about discarding a "const" inside of hash.c. (CVS 577) (check-in: 0c90346153 user: drh tags: trunk)
13:43
Double-quoted strings resolve to column names if possible. Single-quoted strings continue to be interpreted as string literals. (CVS 576) (check-in: 55e7d65496 user: drh tags: trunk)
13:18
Clean up some compiler warnings. (CVS 575) (check-in: 3399b01219 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/expr.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.60 2002/05/19 23:43:14 danielk1977 Exp $
*/
#include "sqliteInt.h"


/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.61 2002/05/21 13:43:04 drh Exp $
*/
#include "sqliteInt.h"


/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function
281
282
283
284
285
286
287




288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
303
304
  sqliteFree(pList->a);
  sqliteFree(pList);
}

/*
** Walk an expression tree.  Return 1 if the expression is constant
** and 0 if it involves variables.




*/
int sqliteExprIsConstant(Expr *p){
  switch( p->op ){
    case TK_ID:
    case TK_COLUMN:
    case TK_DOT:
      return 0;
    case TK_INTEGER:

    case TK_FLOAT:
    case TK_STRING:
      return 1;
    default: {
      if( p->pLeft && !sqliteExprIsConstant(p->pLeft) ) return 0;
      if( p->pRight && !sqliteExprIsConstant(p->pRight) ) return 0;
      if( p->pList ){
        int i;
        for(i=0; i<p->pList->nExpr; i++){







>
>
>
>







|
>
|
|







281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
  sqliteFree(pList->a);
  sqliteFree(pList);
}

/*
** Walk an expression tree.  Return 1 if the expression is constant
** and 0 if it involves variables.
**
** For the purposes of this function, a double-quoted string (ex: "abc")
** is considered a variable but a single-quoted string (ex: 'abc') is
** a constant.
*/
int sqliteExprIsConstant(Expr *p){
  switch( p->op ){
    case TK_ID:
    case TK_COLUMN:
    case TK_DOT:
      return 0;
    case TK_STRING:
      return p->token.z[0]=='\'';
    case TK_INTEGER:
    case TK_FLOAT:
      return 1;
    default: {
      if( p->pLeft && !sqliteExprIsConstant(p->pLeft) ) return 0;
      if( p->pRight && !sqliteExprIsConstant(p->pRight) ) return 0;
      if( p->pList ){
        int i;
        for(i=0; i<p->pList->nExpr; i++){
358
359
360
361
362
363
364








365
366
367
368
369
370
371
  IdList *pTabList,  /* List of tables used to resolve column names */
  ExprList *pEList,  /* List of expressions used to resolve "AS" */
  Expr *pExpr        /* The expression to be analyzed. */
){
  if( pExpr==0 || pTabList==0 ) return 0;
  assert( base+pTabList->nId<=pParse->nTab );
  switch( pExpr->op ){








    /* A lone identifier.  Try and match it as follows:
    **
    **     1.  To the name of a column of one of the tables in pTabList
    **
    **     2.  To the right side of an AS keyword in the column list of
    **         a SELECT statement.  (For example, match against 'x' in
    **         "SELECT a+b AS 'x' FROM t1".)







>
>
>
>
>
>
>
>







363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
  IdList *pTabList,  /* List of tables used to resolve column names */
  ExprList *pEList,  /* List of expressions used to resolve "AS" */
  Expr *pExpr        /* The expression to be analyzed. */
){
  if( pExpr==0 || pTabList==0 ) return 0;
  assert( base+pTabList->nId<=pParse->nTab );
  switch( pExpr->op ){
    /* Double-quoted strings (ex: "abc") are used as identifiers if
    ** possible.  Otherwise they remain as strings.  Single-quoted
    ** strings (ex: 'abc') are always string literals.
    */
    case TK_STRING: {
      if( pExpr->token.z[0]=='\'' ) break;
      /* Fall thru into the TK_ID case if this is a double-quoted string */
    }
    /* A lone identifier.  Try and match it as follows:
    **
    **     1.  To the name of a column of one of the tables in pTabList
    **
    **     2.  To the right side of an AS keyword in the column list of
    **         a SELECT statement.  (For example, match against 'x' in
    **         "SELECT a+b AS 'x' FROM t1".)
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
      if( cnt==0 && sqliteIsRowid(z) ){
        pExpr->iColumn = -1;
        pExpr->iTable = base;
        cnt = 1 + (pTabList->nId>1);
        pExpr->op = TK_COLUMN;
      }
      sqliteFree(z);
      if( cnt==0 ){
        sqliteSetNString(&pParse->zErrMsg, "no such column: ", -1,  
          pExpr->token.z, pExpr->token.n, 0);
        pParse->nErr++;
        return 1;
      }else if( cnt>1 ){
        sqliteSetNString(&pParse->zErrMsg, "ambiguous column name: ", -1,  
          pExpr->token.z, pExpr->token.n, 0);







|







428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
      if( cnt==0 && sqliteIsRowid(z) ){
        pExpr->iColumn = -1;
        pExpr->iTable = base;
        cnt = 1 + (pTabList->nId>1);
        pExpr->op = TK_COLUMN;
      }
      sqliteFree(z);
      if( cnt==0 && pExpr->token.z[0]!='"' ){
        sqliteSetNString(&pParse->zErrMsg, "no such column: ", -1,  
          pExpr->token.z, pExpr->token.n, 0);
        pParse->nErr++;
        return 1;
      }else if( cnt>1 ){
        sqliteSetNString(&pParse->zErrMsg, "ambiguous column name: ", -1,  
          pExpr->token.z, pExpr->token.n, 0);
Changes to test/quote.test.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is the ability to specify table and column names
# as quoted strings.
#
# $Id: quote.test,v 1.2 2001/09/16 00:13:28 drh Exp $

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

# Create a table with a strange name and with strange column names.
#
do_test quote-1.0 {







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is the ability to specify table and column names
# as quoted strings.
#
# $Id: quote.test,v 1.3 2002/05/21 13:43:04 drh Exp $

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

# Create a table with a strange name and with strange column names.
#
do_test quote-1.0 {
36
37
38
39
40
41
42
















43
44
45
46
47
48
49
} {0 {}}
do_test quote-1.2 {
  set r [catch {
    execsql {SELECT * FROM '@abc'}
  } msg ]
  lappend r $msg
} {0 {5 hello}}
















do_test quote-1.3 {
  set r [catch {
    execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'}
  } msg ]
  lappend r $msg
} {0 {hello 10}}
do_test quote-1.4 {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
} {0 {}}
do_test quote-1.2 {
  set r [catch {
    execsql {SELECT * FROM '@abc'}
  } msg ]
  lappend r $msg
} {0 {5 hello}}
do_test quote-1.3 {
  set r [catch {
    execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'}
  } msg ]
  lappend r $msg
} {0 {hello 10}}
do_test quote-1.3.1 {
  catchsql {
    SELECT '!pqr', '#xyz'+5 FROM '@abc'
  }
} {0 {!pqr 5}}
do_test quote-1.3.2 {
  catchsql {
    SELECT "!pqr", "#xyz"+5 FROM '@abc'
  }
} {0 {hello 10}}
do_test quote-1.3 {
  set r [catch {
    execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'}
  } msg ]
  lappend r $msg
} {0 {hello 10}}
do_test quote-1.4 {