Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Allow collation sequence names to be quoted. Ticket #2744. (CVS 4537) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
06749ac7afeea4adbdeb9315f3819d52 |
User & Date: | danielk1977 2007-11-12 09:50:26.000 |
Context
2007-11-12
| ||
15:29 | Where possible, transform the DISTINCT qualifier to a GROUP BY clause. GROUP BY clauses may be optimized by indices, DISTINCT qualifiers cannot. (CVS 4538) (check-in: e563312347 user: danielk1977 tags: trunk) | |
09:50 | Allow collation sequence names to be quoted. Ticket #2744. (CVS 4537) (check-in: 06749ac7af user: danielk1977 tags: trunk) | |
08:09 | Modify the order of assert() macros in vdbe.c as per the suggestion in #2768. (CVS 4536) (check-in: af5af5dc26 user: danielk1977 tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.448 2007/11/12 09:50:26 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. |
︙ | ︙ | |||
1179 1180 1181 1182 1183 1184 1185 | sqlite3ExprDelete(pCheckExpr); } /* ** Set the collation function of the most recently parsed table column ** to the CollSeq given. */ | | > > > > | | > > | 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 | sqlite3ExprDelete(pCheckExpr); } /* ** Set the collation function of the most recently parsed table column ** to the CollSeq given. */ 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; zColl = sqlite3NameFromToken(pParse->db, pToken); if( !zColl ) return; if( sqlite3LocateCollSeq(pParse, zColl, -1) ){ Index *pIdx; 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 ** collation type was added. Correct this if it is the case. */ for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->nColumn==1 ); if( pIdx->aiColumn[0]==i ){ pIdx->azColl[0] = p->aCol[i].zColl; } } }else{ sqlite3_free(zColl); } } /* ** This function returns the collation sequence for database native text ** encoding identified by the string zName, length nName. ** |
︙ | ︙ | |||
3347 3348 3349 3350 3351 3352 3353 3354 | return; } if( pName1==0 || pName1->z==0 ){ reindexDatabases(pParse, 0); return; }else if( pName2==0 || pName2->z==0 ){ assert( pName1->z ); | > > > | < > | 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 | return; } if( pName1==0 || pName1->z==0 ){ reindexDatabases(pParse, 0); return; }else if( pName2==0 || pName2->z==0 ){ char *zColl; assert( pName1->z ); zColl = sqlite3NameFromToken(pParse->db, pName1); if( !zColl ) return; pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0); if( pColl ){ if( zColl ){ reindexDatabases(pParse, zColl); sqlite3_free(zColl); } return; } sqlite3_free(zColl); } iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); if( iDb<0 ) return; z = sqlite3NameFromToken(db, pObjName); if( z==0 ) return; zDb = db->aDb[iDb].zName; pTab = sqlite3FindTable(db, z, zDb); |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** 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. ** | | | 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.316 2007/11/12 09:50:26 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
50 51 52 53 54 55 56 57 | ** Set the collating sequence for expression pExpr to be the collating ** sequence named by pToken. Return a pointer to the revised expression. ** The collating sequence is marked as "explicit" using the EP_ExpCollate ** flag. An explicit collating sequence will override implicit ** collating sequences. */ Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){ CollSeq *pColl; | > > | | | | | | > > | 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 | ** Set the collating sequence for expression pExpr to be the collating ** sequence named by pToken. Return a pointer to the revised expression. ** The collating sequence is marked as "explicit" using the EP_ExpCollate ** flag. An explicit collating sequence will override implicit ** collating sequences. */ Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){ char *zColl = 0; /* Dequoted name of collation sequence */ CollSeq *pColl; 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; } /* ** Return the default collation sequence for the expression pExpr. If ** there is no default collation type, return 0. */ |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $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_" %token_prefix TK_ // The type of the data attached to each token is Token. This is also the // default type for non-terminals. |
︙ | ︙ | |||
268 269 270 271 272 273 274 | ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I). {sqlite3AddPrimaryKey(pParse,0,R,I,Z);} ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);} 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);} | | | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I). {sqlite3AddPrimaryKey(pParse,0,R,I,Z);} ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);} 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 ids(C). {sqlite3AddCollateType(pParse, &C);} // The optional AUTOINCREMENT keyword %type autoinc {int} autoinc(X) ::= . {X = 0;} autoinc(X) ::= AUTOINCR. {X = 1;} // The next group of rules parses the arguments to a REFERENCES clause |
︙ | ︙ | |||
653 654 655 656 657 658 659 | term(A) ::= STRING(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);} expr(A) ::= REGISTER(X). {A = sqlite3RegisterExpr(pParse, &X);} expr(A) ::= VARIABLE(X). { Token *pToken = &X; Expr *pExpr = A = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken); sqlite3ExprAssignVarNumber(pParse, pExpr); } | | | 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 | term(A) ::= STRING(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);} expr(A) ::= REGISTER(X). {A = sqlite3RegisterExpr(pParse, &X);} expr(A) ::= VARIABLE(X). { Token *pToken = &X; Expr *pExpr = A = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken); sqlite3ExprAssignVarNumber(pParse, pExpr); } expr(A) ::= expr(E) COLLATE ids(C). { A = sqlite3ExprSetColl(pParse, E, &C); } %ifndef SQLITE_OMIT_CAST expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). { A = sqlite3PExpr(pParse, TK_CAST, E, 0, &T); sqlite3ExprSpan(A,&X,&Y); } |
︙ | ︙ | |||
889 890 891 892 893 894 895 | idxlist_opt(A) ::= . {A = 0;} idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;} 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); | | | | | 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 | idxlist_opt(A) ::= . {A = 0;} idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;} 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); sqlite3ExprSetColl(pParse, p, &C); } A = sqlite3ExprListAppend(pParse,X, p, &Y); sqlite3ExprListCheckLength(pParse, A, SQLITE_MAX_COLUMN, "index"); if( A ) A->a[A->nExpr-1].sortOrder = Z; } idxlist(A) ::= idxitem(Y) collate(C) sortorder(Z). { Expr *p = 0; if( C.n>0 ){ p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); sqlite3ExprSetColl(pParse, p, &C); } A = sqlite3ExprListAppend(pParse,0, p, &Y); sqlite3ExprListCheckLength(pParse, A, SQLITE_MAX_COLUMN, "index"); if( A ) A->a[A->nExpr-1].sortOrder = Z; } idxitem(A) ::= nm(X). {A = X;} %type collate {Token} collate(C) ::= . {C.z = 0; C.n = 0;} collate(C) ::= COLLATE ids(X). {C = X;} ///////////////////////////// The DROP INDEX command ///////////////////////// // cmd ::= DROP INDEX ifexists(E) fullname(X). {sqlite3DropIndex(pParse, X, E);} ///////////////////////////// The VACUUM command ///////////////////////////// |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.618 2007/11/12 09:50:26 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** These #defines should enable >2GB file support on Posix if the ** underlying operating system supports it. If the OS lacks |
︙ | ︙ | |||
1644 1645 1646 1647 1648 1649 1650 | void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); void sqlite3AddColumn(Parse*,Token*); void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); void sqlite3AddCheckConstraint(Parse*, Expr*); void sqlite3AddColumnType(Parse*,Token*); void sqlite3AddDefaultValue(Parse*,Expr*); | | | 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 | void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); void sqlite3AddColumn(Parse*,Token*); void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); void sqlite3AddCheckConstraint(Parse*, Expr*); void sqlite3AddColumnType(Parse*,Token*); void sqlite3AddDefaultValue(Parse*,Expr*); void sqlite3AddCollateType(Parse*, Token*); void sqlite3EndTable(Parse*,Token*,Token*,Select*); void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int); #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) int sqlite3ViewGetColumnNames(Parse*,Table*); #else |
︙ | ︙ |
Added test/collate9.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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 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 |