| From f4b79cfaefb87fa2c37a860c5a64f320a5265f99 Mon Sep 17 00:00:00 2001 |
| From: Scott Hess <shess@chromium.org> |
| Date: Mon, 23 Mar 2015 11:24:11 -0700 |
| Subject: [PATCH] [backport] Fix collation dequoting. |
| |
| Backport https://www.sqlite.org/src/info/eddc05e7bb31fae7 |
| "Fix a problem causing collation sequence names to be dequoted |
| multiple times under some circumstances." |
| |
| BUG=469082 |
| --- |
| third_party/sqlite/src/src/expr.c | 7 ++-- |
| third_party/sqlite/src/src/parse.y | 6 ++-- |
| third_party/sqlite/src/src/sqliteInt.h | 2 +- |
| third_party/sqlite/src/src/where.c | 9 +++-- |
| third_party/sqlite/src/test/collate1.test | 58 +++++++++++++++++++++++++++++-- |
| 5 files changed, 68 insertions(+), 14 deletions(-) |
| |
| diff --git a/third_party/sqlite/src/src/expr.c b/third_party/sqlite/src/src/expr.c |
| index 65f211e..2d96c8d 100644 |
| --- a/third_party/sqlite/src/src/expr.c |
| +++ b/third_party/sqlite/src/src/expr.c |
| @@ -69,10 +69,11 @@ char sqlite3ExprAffinity(Expr *pExpr){ |
| Expr *sqlite3ExprAddCollateToken( |
| Parse *pParse, /* Parsing context */ |
| Expr *pExpr, /* Add the "COLLATE" clause to this expression */ |
| - const Token *pCollName /* Name of collating sequence */ |
| + const Token *pCollName, /* Name of collating sequence */ |
| + int dequote /* True to dequote pCollName */ |
| ){ |
| if( pCollName->n>0 ){ |
| - Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1); |
| + Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote); |
| if( pNew ){ |
| pNew->pLeft = pExpr; |
| pNew->flags |= EP_Collate|EP_Skip; |
| @@ -86,7 +87,7 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ |
| assert( zC!=0 ); |
| s.z = zC; |
| s.n = sqlite3Strlen30(s.z); |
| - return sqlite3ExprAddCollateToken(pParse, pExpr, &s); |
| + return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0); |
| } |
| |
| /* |
| diff --git a/third_party/sqlite/src/src/parse.y b/third_party/sqlite/src/src/parse.y |
| index 877827e..d888cff 100644 |
| --- a/third_party/sqlite/src/src/parse.y |
| +++ b/third_party/sqlite/src/src/parse.y |
| @@ -854,7 +854,7 @@ expr(A) ::= VARIABLE(X). { |
| spanSet(&A, &X, &X); |
| } |
| expr(A) ::= expr(E) COLLATE ids(C). { |
| - A.pExpr = sqlite3ExprAddCollateToken(pParse, E.pExpr, &C); |
| + A.pExpr = sqlite3ExprAddCollateToken(pParse, E.pExpr, &C, 1); |
| A.zStart = E.zStart; |
| A.zEnd = &C.z[C.n]; |
| } |
| @@ -1200,14 +1200,14 @@ uniqueflag(A) ::= . {A = OE_None;} |
| idxlist_opt(A) ::= . {A = 0;} |
| idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;} |
| idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z). { |
| - Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C); |
| + Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C, 1); |
| A = sqlite3ExprListAppend(pParse,X, p); |
| sqlite3ExprListSetName(pParse,A,&Y,1); |
| sqlite3ExprListCheckLength(pParse, A, "index"); |
| if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z; |
| } |
| idxlist(A) ::= nm(Y) collate(C) sortorder(Z). { |
| - Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C); |
| + Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C, 1); |
| A = sqlite3ExprListAppend(pParse,0, p); |
| sqlite3ExprListSetName(pParse, A, &Y, 1); |
| sqlite3ExprListCheckLength(pParse, A, "index"); |
| diff --git a/third_party/sqlite/src/src/sqliteInt.h b/third_party/sqlite/src/src/sqliteInt.h |
| index 9d6a7d8..264f4fe 100644 |
| --- a/third_party/sqlite/src/src/sqliteInt.h |
| +++ b/third_party/sqlite/src/src/sqliteInt.h |
| @@ -3462,7 +3462,7 @@ int sqlite3ReadSchema(Parse *pParse); |
| CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); |
| CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); |
| CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); |
| -Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*); |
| +Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int); |
| Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); |
| Expr *sqlite3ExprSkipCollate(Expr*); |
| int sqlite3CheckCollSeq(Parse *, CollSeq *); |
| diff --git a/third_party/sqlite/src/src/where.c b/third_party/sqlite/src/src/where.c |
| index bc01107..793b01d 100644 |
| --- a/third_party/sqlite/src/src/where.c |
| +++ b/third_party/sqlite/src/src/where.c |
| @@ -1252,7 +1252,7 @@ static void exprAnalyze( |
| Expr *pNewExpr2; |
| int idxNew1; |
| int idxNew2; |
| - Token sCollSeqName; /* Name of collating sequence */ |
| + const char *zCollSeqName; /* Name of collating sequence */ |
| |
| pLeft = pExpr->x.pList->a[1].pExpr; |
| pStr2 = sqlite3ExprDup(db, pStr1, 0); |
| @@ -1272,11 +1272,10 @@ static void exprAnalyze( |
| } |
| *pC = c + 1; |
| } |
| - sCollSeqName.z = noCase ? "NOCASE" : "BINARY"; |
| - sCollSeqName.n = 6; |
| + zCollSeqName = noCase ? "NOCASE" : "BINARY"; |
| pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); |
| pNewExpr1 = sqlite3PExpr(pParse, TK_GE, |
| - sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName), |
| + sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName), |
| pStr1, 0); |
| transferJoinMarkings(pNewExpr1, pExpr); |
| idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); |
| @@ -1284,7 +1283,7 @@ static void exprAnalyze( |
| exprAnalyze(pSrc, pWC, idxNew1); |
| pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); |
| pNewExpr2 = sqlite3PExpr(pParse, TK_LT, |
| - sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName), |
| + sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName), |
| pStr2, 0); |
| transferJoinMarkings(pNewExpr2, pExpr); |
| idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); |
| diff --git a/third_party/sqlite/src/test/collate1.test b/third_party/sqlite/src/test/collate1.test |
| index 2085415..0716ac7 100644 |
| --- a/third_party/sqlite/src/test/collate1.test |
| +++ b/third_party/sqlite/src/test/collate1.test |
| @@ -10,12 +10,12 @@ |
| # |
| #*********************************************************************** |
| # This file implements regression tests for SQLite library. The |
| -# focus of this script is page cache subsystem. |
| +# focus of this script is testing collation sequences. |
| # |
| -# $Id: collate1.test,v 1.5 2007/02/01 23:02:46 drh Exp $ |
| |
| set testdir [file dirname $argv0] |
| source $testdir/tester.tcl |
| +set testprefix collate1 |
| |
| # |
| # Tests are roughly organised as follows: |
| @@ -333,4 +333,58 @@ do_test collate1-5.3 { |
| } |
| } {1 2} |
| |
| + |
| + |
| +#------------------------------------------------------------------------- |
| +# Fix problems with handling collation sequences named '"""'. |
| +# |
| +do_execsql_test 6.1 { |
| + SELECT """"""""; |
| +} {\"\"\"} |
| + |
| +do_catchsql_test 6.2 { |
| + CREATE TABLE x1(a); |
| + SELECT a FROM x1 ORDER BY a COLLATE """"""""; |
| +} {1 {no such collation sequence: """}} |
| + |
| +do_catchsql_test 6.3 { |
| + SELECT a FROM x1 ORDER BY 1 COLLATE """"""""; |
| +} {1 {no such collation sequence: """}} |
| + |
| +do_catchsql_test 6.4 { |
| + SELECT 0 UNION SELECT 0 ORDER BY 1 COLLATE """"""""; |
| +} {1 {no such collation sequence: """}} |
| + |
| +db collate {"""} [list string compare -nocase] |
| + |
| +do_execsql_test 6.5 { |
| + PRAGMA foreign_keys = ON; |
| + CREATE TABLE p1(a PRIMARY KEY COLLATE '"""'); |
| + CREATE TABLE c1(x, y REFERENCES p1); |
| +} {} |
| + |
| +do_execsql_test 6.6 { |
| + INSERT INTO p1 VALUES('abc'); |
| + INSERT INTO c1 VALUES(1, 'ABC'); |
| +} |
| + |
| +ifcapable foreignkey { |
| + do_catchsql_test 6.7 { |
| + DELETE FROM p1 WHERE rowid = 1 |
| + } {1 {FOREIGN KEY constraint failed}} |
| +} |
| + |
| +do_execsql_test 6.8 { |
| + INSERT INTO p1 VALUES('abb'); |
| + INSERT INTO p1 VALUES('wxz'); |
| + INSERT INTO p1 VALUES('wxy'); |
| + |
| + INSERT INTO c1 VALUES(2, 'abb'); |
| + INSERT INTO c1 VALUES(3, 'wxz'); |
| + INSERT INTO c1 VALUES(4, 'WXY'); |
| + SELECT x, y FROM c1 ORDER BY y COLLATE """"""""; |
| +} {2 abb 1 ABC 4 WXY 3 wxz} |
| + |
| finish_test |
| + |
| + |
| -- |
| 2.2.1 |
| |