]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Allow collation sequence names to be quoted. Ticket #2744. (CVS 4537)
authordanielk1977 <danielk1977@noemail.net>
Mon, 12 Nov 2007 09:50:26 +0000 (09:50 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Mon, 12 Nov 2007 09:50:26 +0000 (09:50 +0000)
FossilOrigin-Name: 06749ac7afeea4adbdeb9315f3819d5224534c66

manifest
manifest.uuid
src/build.c
src/expr.c
src/parse.y
src/sqliteInt.h
test/collate9.test [new file with mode: 0644]

index cbd70eb016e70cf1c1b222f8d03da7f2194b5aae..6a753742d1a5b4531a0ff5f34a83b92901844e2d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Modify\sthe\sorder\sof\sassert()\smacros\sin\svdbe.c\sas\sper\sthe\ssuggestion\sin\s#2768.\s(CVS\s4536)
-D 2007-11-12T08:09:35
+C Allow\scollation\ssequence\snames\sto\sbe\squoted.\sTicket\s#2744.\s(CVS\s4537)
+D 2007-11-12T09:50:26
 F Makefile.in 30c7e3ba426ddb253b8ef037d1873425da6009a8
 F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -84,13 +84,13 @@ F src/btmutex.c 442be6f068d77ca9ffd69899cf0a3943c244548c
 F src/btree.c 008ce6b6bbcf00dfa3b1eca41bd3560fb287fd52
 F src/btree.h d0736ebca4b6eafbdd823c46a8de574cea078211
 F src/btreeInt.h 4330c19b8314545fdb209cc77e2a57f6a5290e9c
-F src/build.c d4ace66c2612d8973a17afdfe34b2a62f1a80178
+F src/build.c b58dd7c7a763a228196022ec0d51781ed6995cde
 F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
 F src/delete.c 034b87768c4135a22038a86a205f9d2d5f68a143
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c 23fac3749024deeaaa6c25b6b5c521e8d140a2c5
+F src/expr.c 7977bb9680ebeeabfa3214d936778baaa26dcc0c
 F src/func.c 73b4974e5ff03cc71345cc3a33b0022f7b99974a
 F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
@@ -123,7 +123,7 @@ F src/os_win.c 81690a858b90a1e0b83e7afbce6b6498bb3d3a1d
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
 F src/pager.c c5ffa55c299663b579fbcb430752c1e79d302c5b
 F src/pager.h d783e7f184afdc33adff37ba58d4e029bd8793b3
-F src/parse.y 2d2ce439dc6184621fb0b86f4fc5aca7f391a590
+F src/parse.y 9640f5b930b1d0bfd05d7428da6f762305567cbb
 F src/pragma.c 363e548dafb52327face8d99757ab56a7b1c1b26
 F src/prepare.c 663284f62a73a48b89f5f4e769e155fefba60384
 F src/printf.c 96c8d55315a13fc53cb3754cb15046f3ff891ea2
@@ -133,7 +133,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c 0b9dd90afc34f28b8786638155d32f6248d0bf0a
 F src/sqlite.h.in 3844177d389d58bd4a8be4ee81eefb01a084ed72
 F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
-F src/sqliteInt.h 7fd5cfa357d7aefe22cd2bcdfabcca4e7d5ab5b2
+F src/sqliteInt.h 4e6fdeb5630ead97bcec60b941e7a72203c64b9e
 F src/sqliteLimit.h 15ffe2116746c27ace2b428a26a4fcd6dba6fa65
 F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
 F src/tclsqlite.c 29bb44a88e02ca4d2017113b7b1acc839582d57a
@@ -229,6 +229,7 @@ F test/collate5.test 8fb4e7e0241839356bd8710f437c32efb47bfff8
 F test/collate6.test 8be65a182abaac8011a622131486dafb8076e907
 F test/collate7.test e23677b1fd271505302643a98178952bb65b6f21
 F test/collate8.test 7ed2461305ac959886a064dc1e3cf15e155a183f
+F test/collate9.test 0867eabc1222ab0bc308fc09a7fb30770334c3cd
 F test/colmeta.test 6505c73ab58796afcb7c89ba9f429d573fbc6e53
 F test/conflict.test 79b5214ef7a52f3e58a50ae5c60c37e7594d04e9
 F test/corrupt.test 18c7a995b1af76a8c8600b996257f2c7b7bff083
@@ -585,7 +586,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 3391f4139ccfe62cc27739a06567c422ddae9c69
-R 9bae5c8582864d5a42b9bca9b6ebf6ec
+P af5af5dc2608f369f0f4274ca06974b365424e72
+R 6609950e4e33ca146fe5280a3d429455
 U danielk1977
-Z eedea99e32136cad94caf09bae94e010
+Z 68349a41f440456331fc2acbb07fcff1
index 2d8c1e668bf314e94cc4cbeac015a1e93d7556bc..dee1e4d2893b295312ae70815511b172d7c83e8a 100644 (file)
@@ -1 +1 @@
-af5af5dc2608f369f0f4274ca06974b365424e72
\ No newline at end of file
+06749ac7afeea4adbdeb9315f3819d5224534c66
\ No newline at end of file
index ef6384b05b07ce6c06966865068bccbb5222e1b8..fcaa6024669c6e923954d09322ed9030c0b29cf1 100644 (file)
@@ -22,7 +22,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.447 2007/10/15 07:08:44 danielk1977 Exp $
+** $Id: build.c,v 1.448 2007/11/12 09:50:26 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1183,16 +1183,20 @@ void sqlite3AddCheckConstraint(
 ** Set the collation function of the most recently parsed table column
 ** to the CollSeq given.
 */
-void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){
+void sqlite3AddCollateType(Parse *pParse, Token *pToken){
   Table *p;
   int i;
+  char *zColl;              /* Dequoted name of collation sequence */
 
   if( (p = pParse->pNewTable)==0 ) return;
   i = p->nCol-1;
 
-  if( sqlite3LocateCollSeq(pParse, zType, nType) ){
+  zColl = sqlite3NameFromToken(pParse->db, pToken);
+  if( !zColl ) return;
+
+  if( sqlite3LocateCollSeq(pParse, zColl, -1) ){
     Index *pIdx;
-    p->aCol[i].zColl = sqlite3DbStrNDup(pParse->db, zType, nType);
+    p->aCol[i].zColl = zColl;
   
     /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
     ** then an index may have been created on this column before the
@@ -1204,6 +1208,8 @@ void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){
         pIdx->azColl[0] = p->aCol[i].zColl;
       }
     }
+  }else{
+    sqlite3_free(zColl);
   }
 }
 
@@ -3351,16 +3357,19 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
     reindexDatabases(pParse, 0);
     return;
   }else if( pName2==0 || pName2->z==0 ){
+    char *zColl;
     assert( pName1->z );
-    pColl = sqlite3FindCollSeq(db, ENC(db), (char*)pName1->z, pName1->n, 0);
+    zColl = sqlite3NameFromToken(pParse->db, pName1);
+    if( !zColl ) return;
+    pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0);
     if( pColl ){
-      char *zColl = sqlite3DbStrNDup(db, (const char *)pName1->z, pName1->n);
       if( zColl ){
         reindexDatabases(pParse, zColl);
         sqlite3_free(zColl);
       }
       return;
     }
+    sqlite3_free(zColl);
   }
   iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName);
   if( iDb<0 ) return;
index 4f3d52779831dce35bb6ec4909b609cef51cd29e..a2ba3f8ba63623ecf42430621bfe7a58ddb80052 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.315 2007/10/23 18:55:49 drh Exp $
+** $Id: expr.c,v 1.316 2007/11/12 09:50:26 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -54,13 +54,17 @@ char sqlite3ExprAffinity(Expr *pExpr){
 ** collating sequences.
 */
 Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){
+  char *zColl = 0;            /* Dequoted name of collation sequence */
   CollSeq *pColl;
-  if( pExpr==0 ) return 0;
-  pColl = sqlite3LocateCollSeq(pParse, (char*)pName->z, pName->n);
-  if( pColl ){
-    pExpr->pColl = pColl;
-    pExpr->flags |= EP_ExpCollate;
+  zColl = sqlite3NameFromToken(pParse->db, pName);
+  if( pExpr && zColl ){
+    pColl = sqlite3LocateCollSeq(pParse, zColl, -1);
+    if( pColl ){
+      pExpr->pColl = pColl;
+      pExpr->flags |= EP_ExpCollate;
+    }
   }
+  sqlite3_free(zColl);
   return pExpr;
 }
 
index 5077daf31b87ed7700dc7bc5d4e7004288f5f6f8..9b41a716606e693c7aecaf3485a141bbae7adb5c 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.234 2007/08/21 10:44:16 drh Exp $
+** @(#) $Id: parse.y,v 1.235 2007/11/12 09:50:26 danielk1977 Exp $
 */
 
 // All token codes are small integers with #defines that begin with "TK_"
@@ -272,7 +272,7 @@ ccons ::= CHECK LP expr(X) RP.       {sqlite3AddCheckConstraint(pParse,X);}
 ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
                                 {sqlite3CreateForeignKey(pParse,0,&T,TA,R);}
 ccons ::= defer_subclause(D).   {sqlite3DeferForeignKey(pParse,D);}
-ccons ::= COLLATE id(C).  {sqlite3AddCollateType(pParse, (char*)C.z, C.n);}
+ccons ::= COLLATE ids(C).  {sqlite3AddCollateType(pParse, &C);}
 
 // The optional AUTOINCREMENT keyword
 %type autoinc {int}
@@ -657,7 +657,7 @@ expr(A) ::= VARIABLE(X).     {
   Expr *pExpr = A = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken);
   sqlite3ExprAssignVarNumber(pParse, pExpr);
 }
-expr(A) ::= expr(E) COLLATE id(C). {
+expr(A) ::= expr(E) COLLATE ids(C). {
   A = sqlite3ExprSetColl(pParse, E, &C);
 }
 %ifndef SQLITE_OMIT_CAST
@@ -893,7 +893,7 @@ idxlist(A) ::= idxlist(X) COMMA idxitem(Y) collate(C) sortorder(Z).  {
   Expr *p = 0;
   if( C.n>0 ){
     p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
-    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)C.z, C.n);
+    sqlite3ExprSetColl(pParse, p, &C);
   }
   A = sqlite3ExprListAppend(pParse,X, p, &Y);
   sqlite3ExprListCheckLength(pParse, A, SQLITE_MAX_COLUMN, "index");
@@ -903,7 +903,7 @@ idxlist(A) ::= idxitem(Y) collate(C) sortorder(Z). {
   Expr *p = 0;
   if( C.n>0 ){
     p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
-    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)C.z, C.n);
+    sqlite3ExprSetColl(pParse, p, &C);
   }
   A = sqlite3ExprListAppend(pParse,0, p, &Y);
   sqlite3ExprListCheckLength(pParse, A, SQLITE_MAX_COLUMN, "index");
@@ -913,7 +913,7 @@ idxitem(A) ::= nm(X).              {A = X;}
 
 %type collate {Token}
 collate(C) ::= .                {C.z = 0; C.n = 0;}
-collate(C) ::= COLLATE id(X).   {C = X;}
+collate(C) ::= COLLATE ids(X).   {C = X;}
 
 
 ///////////////////////////// The DROP INDEX command /////////////////////////
index 14e108361d85182ba4cf93ee7bb39b1ff6b29836..702c94cb1db7de1edd02a93ead6b773e56108bbd 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.617 2007/10/23 15:59:18 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.618 2007/11/12 09:50:26 danielk1977 Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1648,7 +1648,7 @@ void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
 void sqlite3AddCheckConstraint(Parse*, Expr*);
 void sqlite3AddColumnType(Parse*,Token*);
 void sqlite3AddDefaultValue(Parse*,Expr*);
-void sqlite3AddCollateType(Parse*, const char*, int);
+void sqlite3AddCollateType(Parse*, Token*);
 void sqlite3EndTable(Parse*,Token*,Token*,Select*);
 
 void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
diff --git a/test/collate9.test b/test/collate9.test
new file mode 100644 (file)
index 0000000..d676f80
--- /dev/null
@@ -0,0 +1,164 @@
+#
+# 2007 November 12
+#
+# 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.  The
+# focus of this script is making sure that the names of collation
+# sequences may be quoted using double quotes in SQL statements.
+#
+# $Id: collate9.test,v 1.1 2007/11/12 09:50:26 danielk1977 Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+proc reverse_sort {lhs rhs} {
+  return [string compare $rhs $lhs]
+}
+db collate "reverse sort" reverse_sort
+
+# This procedure executes the SQL.  Then it checks to see if the OP_Sort
+# opcode was executed.  If an OP_Sort did occur, then "sort" is appended
+# to the result.  If no OP_Sort happened, then "nosort" is appended.
+#
+# This procedure is used to check to make sure sorting is or is not
+# occurring as expected.
+#
+proc cksort {sql} {
+  set ::sqlite_sort_count 0
+  set data [execsql $sql]
+  if {$::sqlite_sort_count} {set x sort} {set x nosort}
+  lappend data $x
+  return $data
+}
+
+# Test plan:
+#
+#     collate9-1.* - Test collation sequences attached to table columns
+#     collate9-2.* - Test collation sequences attached to expressions
+#     collate9-3.* - Test collation sequences attached to an index
+#     collate9-4.* - Test collation sequences as an argument to REINDEX
+#
+
+do_test collate9-1.1 {
+  execsql {
+    CREATE TABLE xy(x COLLATE "reverse sort", y COLLATE binary);
+    INSERT INTO xy VALUES('one', 'one');
+    INSERT INTO xy VALUES('two', 'two');
+    INSERT INTO xy VALUES('three', 'three');
+  }
+} {}
+do_test collate9-1.2 {
+  execsql { 
+    SELECT x FROM xy ORDER BY x
+  }
+} {two three one}
+do_test collate9-1.3 {
+  execsql { 
+    SELECT y FROM xy ORDER BY y
+  }
+} {one three two}
+do_test collate9-1.4 {
+  cksort { 
+    SELECT x FROM xy ORDER BY x
+  }
+} {two three one sort}
+do_test collate9-1.5 {
+  execsql { 
+    CREATE INDEX xy_i ON xy(x)
+  }
+} {}
+do_test collate9-1.6 {
+  cksort { 
+    SELECT x FROM xy ORDER BY x
+  }
+} {two three one nosort}
+
+do_test collate9-2.1 {
+  execsql { 
+    SELECT x, x < 'seven' FROM xy ORDER BY x
+  }
+} {two 1 three 1 one 0}
+do_test collate9-2.2 {
+  execsql { 
+    SELECT y, y < 'seven' FROM xy ORDER BY x
+  }
+} {two 0 three 0 one 1}
+do_test collate9-2.3 {
+  execsql { 
+    SELECT y, y COLLATE "reverse sort" < 'seven' FROM xy ORDER BY x
+  }
+} {two 1 three 1 one 0}
+do_test collate9-2.4 {
+  execsql {
+    SELECT y FROM xy ORDER BY y
+  }
+} {one three two}
+do_test collate9-2.5 {
+  execsql {
+    SELECT y FROM xy ORDER BY y COLLATE "reverse sort"
+  }
+} {two three one}
+
+do_test collate9-3.1 {
+  execsql {
+    CREATE INDEX xy_i2 ON xy(y COLLATE "reverse sort");
+  }
+} {}
+do_test collate9-3.2 {
+  cksort { 
+    SELECT y FROM xy ORDER BY y 
+  }
+} {one three two sort}
+do_test collate9-3.3 {
+  cksort { 
+    SELECT y FROM xy ORDER BY y COLLATE "reverse sort"
+  }
+} {two three one nosort}
+
+ifcapable reindex {
+  do_test collate9-4.1 {
+    execsql {
+      REINDEX "reverse sort"
+    }
+  } {}
+
+  # Modify the "reverse sort" collation so that it now sorts in the same
+  # order as binary.
+  proc reverse_sort {lhs rhs} {
+    return [string compare $lhs $rhs]
+  }
+
+  # The integrity check should now fail because the indexes created using
+  # "reverse sort" are no longer in sync with the collation sequence
+  # implementation.
+  do_test collate9-4.2 {
+    expr {"ok" eq [execsql { PRAGMA integrity_check }]}
+  } {0}
+
+  do_test collate9-4.3 {
+    execsql {
+      REINDEX "reverse sort"
+    }
+  } {}
+
+  # Integrity check should now pass.
+  do_test collate9-4.4 {
+    expr {"ok" eq [execsql { PRAGMA integrity_check }]}
+  } {1}
+
+  do_test collate9-4.5 {
+    cksort {
+      SELECT x FROM xy ORDER BY x COLLATE "reverse sort"
+    }
+  } {one three two nosort}
+}
+
+finish_test
+