SQLite

Check-in [3e7d84db78]
Login

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

Overview
Comment:Add commentary to the ExprList object to explain how zSpan is overloaded. Add test cases for the new name resolution functionality.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | name-resolution-fix
Files: files | file ages | folders
SHA1: 3e7d84db7861911c9b2c7dcdabe0b213bf483d79
User & Date: drh 2012-12-19 13:41:03.688
Context
2013-01-02
12:29
Merge all the latest trunk changes into the name-resolution enhancement branch. (check-in: a5f4d2b641 user: drh tags: name-resolution-fix)
2012-12-19
13:41
Add commentary to the ExprList object to explain how zSpan is overloaded. Add test cases for the new name resolution functionality. (check-in: 3e7d84db78 user: drh tags: name-resolution-fix)
02:36
Better resolution of table and column names in joins where some of the terms of the FROM clause are parenthesized. (check-in: 7344e791b9 user: drh tags: name-resolution-fix)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/sqliteInt.h.
1767
1768
1769
1770
1771
1772
1773







1774
1775
1776
1777
1778
1779
1780
1781
1782
1783

1784
1785
1786
1787
1788
1789
1790
1791
1792
/*
** A list of expressions.  Each expression may optionally have a
** name.  An expr/name combination can be used in several ways, such
** as the list of "expr AS ID" fields following a "SELECT" or in the
** list of "ID = expr" items in an UPDATE.  A list of expressions can
** also be used as the argument to a function, in which case the a.zName
** field is not used.







*/
struct ExprList {
  int nExpr;             /* Number of expressions on the list */
  int iECursor;          /* VDBE Cursor associated with this ExprList */
  struct ExprList_item { /* For each expression in the list */
    Expr *pExpr;           /* The list of expressions */
    char *zName;           /* Token associated with this expression */
    char *zSpan;           /* Original text of the expression */
    u8 sortOrder;          /* 1 for DESC or 0 for ASC */
    u8 done;               /* A flag to indicate when processing is finished */

    u16 iOrderByCol;       /* For ORDER BY, column number in result set */
    u16 iAlias;            /* Index into Parse.aAlias[] for zName */
  } *a;                  /* Alloc a power of two greater or equal to nExpr */
};

/*
** An instance of this structure is used by the parser to record both
** the parse tree for an expression and the span of input text for an
** expression.







>
>
>
>
>
>
>





|
|
|
|
|
>
|
|







1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
/*
** A list of expressions.  Each expression may optionally have a
** name.  An expr/name combination can be used in several ways, such
** as the list of "expr AS ID" fields following a "SELECT" or in the
** list of "ID = expr" items in an UPDATE.  A list of expressions can
** also be used as the argument to a function, in which case the a.zName
** field is not used.
**
** By default the Expr.zSpan field holds a human-readable description of
** the expression that is used in the generation of error messages and
** column labels.  In this case, Expr.zSpan is typically the text of a
** column expression as it exists in a SELECT statement.  However, if
** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
** of the table to which the column of a FROM-clause subquery refers.
*/
struct ExprList {
  int nExpr;             /* Number of expressions on the list */
  int iECursor;          /* VDBE Cursor associated with this ExprList */
  struct ExprList_item { /* For each expression in the list */
    Expr *pExpr;            /* The list of expressions */
    char *zName;            /* Token associated with this expression */
    char *zSpan;            /* Original text of the expression */
    u8 sortOrder;           /* 1 for DESC or 0 for ASC */
    unsigned done :1;       /* A flag to indicate when processing is finished */
    unsigned bSpanIsTab :1; /* zSpan holds table name, not the span */
    u16 iOrderByCol;        /* For ORDER BY, column number in result set */
    u16 iAlias;             /* Index into Parse.aAlias[] for zName */
  } *a;                  /* Alloc a power of two greater or equal to nExpr */
};

/*
** An instance of this structure is used by the parser to record both
** the parse tree for an expression and the span of input text for an
** expression.
Added test/selectD.test.




























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
66
67
68
69
70
71
72
73
74
75
76
77
78
# 2012 December 19
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    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 name resolution in SELECT
# statements that have parenthesized FROM clauses.
#

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

do_test selectD-1.1 {
  db eval {
    CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(111,'x1');
    CREATE TABLE t2(a,b); INSERT INTO t2 VALUES(222,'x2');
    CREATE TABLE t3(a,b); INSERT INTO t3 VALUES(333,'x3');
    CREATE TABLE t4(a,b); INSERT INTO t4 VALUES(444,'x4');

    SELECT *
      FROM (t1), (t2), (t3), (t4)
     WHERE t4.a=t3.a+111 
       AND t3.a=t2.a+111
       AND t2.a=t1.a+111;
  }
} {111 x1 222 x2 333 x3 444 x4}
do_test selectD-1.2 {
  db eval {
    SELECT *
      FROM t1 JOIN (t2 JOIN (t3 JOIN t4 ON t4.a=t3.a+111)
                            ON t3.a=t2.a+111)
                   ON t2.a=t1.a+111;
  }
} {111 x1 222 x2 333 x3 444 x4}
do_test selectD-1.3 {
  db eval {
    UPDATE t2 SET a=111;
    UPDATE t3 SET a=111;
    UPDATE t4 SET a=111;
    SELECT *
      FROM t1 JOIN (t2 JOIN (t3 JOIN t4 USING(a)) USING (a)) USING (a);
  }
} {111 x1 x2 x3 x4}
do_test selectD-1.4 {
  db eval {
    UPDATE t2 SET a=111;
    UPDATE t3 SET a=111;
    UPDATE t4 SET a=111;
    SELECT *
      FROM t1 LEFT JOIN (t2 LEFT JOIN (t3 LEFT JOIN t4 USING(a))
                                      USING (a))
                         USING (a);
  }
} {111 x1 x2 x3 x4}
do_test selectD-1.5 {
  db eval {
    UPDATE t3 SET a=222;
    UPDATE t4 SET a=222;
    SELECT *
      FROM (t1 LEFT JOIN t2 USING(a)) JOIN (t3 LEFT JOIN t4 USING(a))
           ON t1.a=t3.a-111;
  }
} {111 x1 x2 222 x3 x4}
do_test selectD-1.6 {
  db eval {
    UPDATE t4 SET a=333;
    SELECT *
      FROM (t1 LEFT JOIN t2 USING(a)) JOIN (t3 LEFT JOIN t4 USING(a))
           ON t1.a=t3.a-111;
  }
} {111 x1 x2 222 x3 {}}

finish_test