From: danielk1977 Date: Mon, 12 Nov 2007 09:50:26 +0000 (+0000) Subject: Allow collation sequence names to be quoted. Ticket #2744. (CVS 4537) X-Git-Tag: version-3.6.10~1640 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=390025053e0b4660e83db4b206bd97d594179bf0;p=thirdparty%2Fsqlite.git Allow collation sequence names to be quoted. Ticket #2744. (CVS 4537) FossilOrigin-Name: 06749ac7afeea4adbdeb9315f3819d5224534c66 --- diff --git a/manifest b/manifest index cbd70eb016..6a753742d1 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 2d8c1e668b..dee1e4d289 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -af5af5dc2608f369f0f4274ca06974b365424e72 \ No newline at end of file +06749ac7afeea4adbdeb9315f3819d5224534c66 \ No newline at end of file diff --git a/src/build.c b/src/build.c index ef6384b05b..fcaa602466 100644 --- a/src/build.c +++ b/src/build.c @@ -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 @@ -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 " PRIMARY KEY COLLATE ", ** 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; diff --git a/src/expr.c b/src/expr.c index 4f3d527798..a2ba3f8ba6 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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 @@ -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; } diff --git a/src/parse.y b/src/parse.y index 5077daf31b..9b41a71660 100644 --- a/src/parse.y +++ b/src/parse.y @@ -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 ///////////////////////// diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 14e108361d..702c94cb1d 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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 index 0000000000..d676f80f05 --- /dev/null +++ b/test/collate9.test @@ -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 +