summaryrefslogtreecommitdiffstats
path: root/third_party/sqlite/patches/0018-backport-Fix-collation-dequoting.patch
blob: f8f1597bbc2561f8bb1cfeefbd3fee685f888006 (plain)
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
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