]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the ability to group FROM terms using parentheses. Names of columns in
authordrh <drh@noemail.net>
Sat, 24 Jan 2004 20:18:12 +0000 (20:18 +0000)
committerdrh <drh@noemail.net>
Sat, 24 Jan 2004 20:18:12 +0000 (20:18 +0000)
a join no longer include the table name. (CVS 1197)

FossilOrigin-Name: 3626f6d4a1adb4209d5bd9e6477343b52bddbdf2

manifest
manifest.uuid
src/parse.y
src/select.c
test/join2.test [new file with mode: 0644]
test/select6.test

index 521ec18235f4e68dd6ec9a49e48ab3e1926f11fe..c6d822a639ec0d9e1a07a233bf91a2ad193e05f2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\stypo.\s\sTicket\s#577.\s(CVS\s1196)
-D 2004-01-22T23:38:22
+C Add\sthe\sability\sto\sgroup\sFROM\sterms\susing\sparentheses.\s\sNames\sof\scolumns\sin\na\sjoin\sno\slonger\sinclude\sthe\stable\sname.\s(CVS\s1197)
+D 2004-01-24T20:18:13
 F Makefile.in 0515ff9218ad8d5a8f6220f0494b8ef94c67013b
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -42,11 +42,11 @@ F src/os.c 681ec36217bc7c795d55d9a63ff79a8614ddee8c
 F src/os.h 8d02b622153d2df442da1ec37cdd6b1bd9804a25
 F src/pager.c 289328d8efba620eae99f6c2f6062710838a3eb4
 F src/pager.h 5da62c83443f26b1792cfd72c96c422f91aadd31
-F src/parse.y e41722d11148f34f034716652c1668ffb0ef2905
+F src/parse.y 7a121554c0c0c0150a77ab05417b01fa44813ac4
 F src/pragma.c 89d62c31c6f0a43376fe8d20549b87a6d30c467a
 F src/printf.c 292a7bfc5a815cb6465e32b2d5c9fe9bd43b27f0
 F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
-F src/select.c 131b1af582c48a72f92eee9f3dfc669687faa1c8
+F src/select.c b5bc89a56d3d9162559bc173b7d5110f20249057
 F src/shell.c 3b067edc098c45caca164bcad1fa79192c3ec5ae
 F src/sqlite.h.in c70d8533cd5a5ae8af580597dbc726693ef82de9
 F src/sqliteInt.h c5b727d5d07b88654c204c0fc1ae79c9f635a008
@@ -96,6 +96,7 @@ F test/insert2.test c288375a64dad3295044714f0dfed4a193cf067f
 F test/intpkey.test 9320af48415c594afd4e15f8ef0daa272e05502e
 F test/ioerr.test 5dbaf09f96b56ee01cf3edd762b96eb4ad2c9ca4
 F test/join.test 9ef6aabaac9de51d5fc41e68d1f4355da05a84cd
+F test/join2.test c97e4c5aa65dea462145529e58212a709b4722b8
 F test/limit.test fa2a8b3fe377ebe60e0bc9a6a35af9ac4eb3d2b3
 F test/lock.test 3d1855ba930732566f569d680e828656bd5b7f5c
 F test/main.test 6a851b5992c4881a725a3d9647e629199df8de9d
@@ -121,7 +122,7 @@ F test/select2.test aceea74fd895b9d007512f72499db589735bd8e4
 F test/select3.test 445a1a3dde4e2fd32541b311f55da5e2f8079d76
 F test/select4.test e7e9a32fa745246cb99fadbeb63af4843a17925b
 F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac
-F test/select6.test 670026a06c358cc867ace7b1de6020e43adc7245
+F test/select6.test a9e31906e700e7c7592c4d0acfc022808f718baf
 F test/sort.test ba07b107c16070208e6aab3cadea66ba079d85ba
 F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f
 F test/table.test 371a1fc1c470982b2f68f9732f903a5d96f949c4
@@ -180,7 +181,7 @@ F www/speed.tcl 2f6b1155b99d39adb185f900456d1d592c4832b3
 F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
 F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
-P df3509e13dc05751b7a5af07b57bca449fe5244c
-R a1c0ec9ce95261bea04d82449f802c30
+P 3dc951951947a9188ecba1b84e48c65e34c4df16
+R c11f9dd26aca5e351dec881862f5d549
 U drh
-Z 57b555ec3a70e65302149e827f2f3589
+Z 2a2e36c650f4fa8bf25792ffa5a54e26
index 09ac4c5902a8c58a0efe963465e14601fd2ed8a1..a96c152005464c8b1c8ddd56e0c25dec3e8367f8 100644 (file)
@@ -1 +1 @@
-3dc951951947a9188ecba1b84e48c65e34c4df16
\ No newline at end of file
+3626f6d4a1adb4209d5bd9e6477343b52bddbdf2
\ No newline at end of file
index 05f9dff8d5029270d55e702c7833558b166fdb18..736d8dfc1b7a466fdcef59c756316c5f7cf11027 100644 (file)
@@ -14,7 +14,7 @@
 ** the parser.  Lemon will also generate a header file containing
 ** numeric codes for all of the tokens.
 **
-** @(#) $Id: parse.y,v 1.106 2004/01/15 03:30:25 drh Exp $
+** @(#) $Id: parse.y,v 1.107 2004/01/24 20:18:13 drh Exp $
 */
 %token_prefix TK_
 %token_type {Token}
@@ -366,7 +366,8 @@ seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) on_opt(N) using_opt(U). {
     else { sqliteIdListDelete(U); }
   }
 }
-seltablist(A) ::= stl_prefix(X) LP select(S) RP as(Z) on_opt(N) using_opt(U). {
+seltablist(A) ::= stl_prefix(X) LP seltablist_paren(S) RP
+                  as(Z) on_opt(N) using_opt(U). {
   A = sqliteSrcListAppend(X,0,0);
   A->a[A->nSrc-1].pSelect = S;
   if( Z.n ) sqliteSrcListAddAlias(A,&Z);
@@ -380,6 +381,17 @@ seltablist(A) ::= stl_prefix(X) LP select(S) RP as(Z) on_opt(N) using_opt(U). {
   }
 }
 
+// A seltablist_paren nonterminal represents anything in a FROM that
+// is contained inside parentheses.  This can be either a subquery or
+// a grouping of table and subqueries.
+//
+%type seltablist_paren {Select*}
+%destructor seltablist_paren {sqliteSelectDelete($$);}
+seltablist_paren(A) ::= select(S).      {A = S;}
+seltablist_paren(A) ::= seltablist(F).  {
+   A = sqliteSelectNew(0,F,0,0,0,0,0,-1,0);
+}
+
 %type dbnm {Token}
 dbnm(A) ::= .          {A.z=0; A.n=0;}
 dbnm(A) ::= DOT nm(X). {A = X;}
@@ -666,16 +678,14 @@ expr(A) ::= expr(X) NOT IN LP select(Y) RP(E).  {
 }
 expr(A) ::= expr(X) IN nm(Y) dbnm(D). {
   SrcList *pSrc = sqliteSrcListAppend(0, &Y, &D);
-  ExprList *pList = sqliteExprListAppend(0, sqliteExpr(TK_ALL,0,0,0), 0);
   A = sqliteExpr(TK_IN, X, 0, 0);
-  if( A ) A->pSelect = sqliteSelectNew(pList,pSrc,0,0,0,0,0,-1,0);
+  if( A ) A->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0);
   sqliteExprSpan(A,&X->span,D.z?&D:&Y);
 }
 expr(A) ::= expr(X) NOT IN nm(Y) dbnm(D). {
   SrcList *pSrc = sqliteSrcListAppend(0, &Y, &D);
-  ExprList *pList = sqliteExprListAppend(0, sqliteExpr(TK_ALL,0,0,0), 0);
   A = sqliteExpr(TK_IN, X, 0, 0);
-  if( A ) A->pSelect = sqliteSelectNew(pList,pSrc,0,0,0,0,0,-1,0);
+  if( A ) A->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0);
   A = sqliteExpr(TK_NOT, A, 0, 0);
   sqliteExprSpan(A,&X->span,D.z?&D:&Y);
 }
index fde9270cab851a73f9f84ea9893d28f9fc5b24d7..735e16122f9534abdcbb13b0cf5565c106c3953b 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements in SQLite.
 **
-** $Id: select.c,v 1.148 2004/01/19 04:57:53 jplyon Exp $
+** $Id: select.c,v 1.149 2004/01/24 20:18:13 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -42,6 +42,9 @@ Select *sqliteSelectNew(
     sqliteExprDelete(pHaving);
     sqliteExprListDelete(pOrderBy);
   }else{
+    if( pEList==0 ){
+      pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL,0,0,0), 0);
+    }
     pNew->pEList = pEList;
     pNew->pSrc = pSrc;
     pNew->pWhere = pWhere;
@@ -777,8 +780,9 @@ static int fillInColumnList(Parse*, Select*);
 */
 Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
   Table *pTab;
-  int i;
+  int i, j;
   ExprList *pEList;
+  Column *aCol;
 
   if( fillInColumnList(pParse, pSelect) ){
     return 0;
@@ -791,17 +795,27 @@ Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
   pEList = pSelect->pEList;
   pTab->nCol = pEList->nExpr;
   assert( pTab->nCol>0 );
-  pTab->aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
+  pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
   for(i=0; i<pTab->nCol; i++){
-    Expr *p;
+    Expr *p, *pR;
     if( pEList->a[i].zName ){
-      pTab->aCol[i].zName = sqliteStrDup(pEList->a[i].zName);
-    }else if( (p=pEList->a[i].pExpr)->span.z && p->span.z[0] ){
+      aCol[i].zName = sqliteStrDup(pEList->a[i].zName);
+    }else if( (p=pEList->a[i].pExpr)->op==TK_DOT 
+               && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
+      int cnt;
+      sqliteSetNString(&aCol[i].zName, pR->token.z, pR->token.n, 0);
+      for(j=cnt=0; j<i; j++){
+        if( sqliteStrICmp(aCol[j].zName, aCol[i].zName)==0 ){
+          int n;
+          char zBuf[30];
+          sprintf(zBuf,"_%d",++cnt);
+          n = strlen(zBuf);
+          sqliteSetNString(&aCol[i].zName, pR->token.z, pR->token.n, zBuf, n,0);
+          j = -1;
+        }
+      }
+    }else if( p->span.z && p->span.z[0] ){
       sqliteSetNString(&pTab->aCol[i].zName, p->span.z, p->span.n, 0);
-    }else if( p->op==TK_DOT && p->pRight && p->pRight->token.z &&
-           p->pRight->token.z[0] ){
-      sqliteSetNString(&pTab->aCol[i].zName, 
-           p->pRight->token.z, p->pRight->token.n, 0);
     }else{
       char zBuf[30];
       sprintf(zBuf, "column%d", i+1);
diff --git a/test/join2.test b/test/join2.test
new file mode 100644 (file)
index 0000000..8829be3
--- /dev/null
@@ -0,0 +1,73 @@
+# 2002 May 24
+#
+# 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 SQLite library.
+#
+# This file implements tests for joins, including outer joins.
+#
+# $Id: join2.test,v 1.1 2004/01/24 20:18:13 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test join2-1.1 {
+  execsql {
+    CREATE TABLE t1(a,b);
+    INSERT INTO t1 VALUES(1,11);
+    INSERT INTO t1 VALUES(2,22);
+    INSERT INTO t1 VALUES(3,33);
+    SELECT * FROM t1;
+  }  
+} {1 11 2 22 3 33}
+do_test join2-1.2 {
+  execsql {
+    CREATE TABLE t2(b,c);
+    INSERT INTO t2 VALUES(11,111);
+    INSERT INTO t2 VALUES(33,333);
+    INSERT INTO t2 VALUES(44,444);
+    SELECT * FROM t2;
+  }  
+} {11 111 33 333 44 444};
+do_test join2-1.3 {
+  execsql {
+    CREATE TABLE t3(c,d);
+    INSERT INTO t3 VALUES(111,1111);
+    INSERT INTO t3 VALUES(444,4444);
+    INSERT INTO t3 VALUES(555,5555);
+    SELECT * FROM t3;
+  }  
+} {111 1111 444 4444 555 5555}
+
+do_test join2-1.4 {
+  execsql {
+    SELECT * FROM
+      t1 NATURAL JOIN t2 NATURAL JOIN t3
+  }
+} {1 11 111 1111}
+do_test join2-1.5 {
+  execsql {
+    SELECT * FROM
+      t1 NATURAL JOIN t2 NATURAL LEFT OUTER JOIN t3
+  }
+} {1 11 111 1111 3 33 333 {}}
+do_test join2-1.6 {
+  execsql {
+    SELECT * FROM
+      t1 NATURAL LEFT OUTER JOIN t2 NATURAL JOIN t3
+  }
+} {1 11 111 1111}
+do_test join2-1.6 {
+  execsql {
+    SELECT * FROM
+      t1 NATURAL LEFT OUTER JOIN (t2 NATURAL JOIN t3)
+  }
+} {1 11 111 1111 2 22 {} {} 3 33 {} {}}
+
+finish_test
index d47cdc65f096df35a2f9810e53ee6462facbe5ac..bb57b7c48d6682e93ed06e568083161f575d0d36 100644 (file)
@@ -12,7 +12,7 @@
 # focus of this file is testing SELECT statements that contain
 # subqueries in their FROM clause.
 #
-# $Id: select6.test,v 1.10 2003/05/02 16:44:25 drh Exp $
+# $Id: select6.test,v 1.11 2004/01/24 20:18:13 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -163,7 +163,7 @@ do_test sqlite6-3.2 {
        FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY q) AS a,
             (SELECT max(a) as r, b as s FROM t2 GROUP BY s) as b
        WHERE a.q=b.s ORDER BY a.q)
-    ORDER BY [a.q]
+    ORDER BY q
   }
 } {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}
 do_test select6-3.3 {