c0e712
# Fix a problem causing collation sequence names to be dequoted multiple times
c0e712
# under some circumstances.
c0e712
# Upstream original patch: https://www.sqlite.org/src/info/eddc05e7bb31fae7
c0e712
c0e712
diff -up sqlite-src-3071700/src/expr.c.old sqlite-src-3071700/src/expr.c
c0e712
--- sqlite-src-3071700/src/expr.c.old	2015-07-23 10:26:11.220420294 +0200
c0e712
+++ sqlite-src-3071700/src/expr.c	2015-07-23 10:26:47.468601833 +0200
c0e712
@@ -65,9 +65,9 @@ char sqlite3ExprAffinity(Expr *pExpr){
c0e712
 ** If a memory allocation error occurs, that fact is recorded in pParse->db
c0e712
 ** and the pExpr parameter is returned unchanged.
c0e712
 */
c0e712
-Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
c0e712
+Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName, int dequote){
c0e712
   if( pCollName->n>0 ){
c0e712
-    Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
c0e712
+    Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
c0e712
     if( pNew ){
c0e712
       pNew->pLeft = pExpr;
c0e712
       pNew->flags |= EP_Collate;
c0e712
@@ -81,7 +81,7 @@ Expr *sqlite3ExprAddCollateString(Parse
c0e712
   assert( zC!=0 );
c0e712
   s.z = zC;
c0e712
   s.n = sqlite3Strlen30(s.z);
c0e712
-  return sqlite3ExprAddCollateToken(pParse, pExpr, &s);
c0e712
+  return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0);
c0e712
 }
c0e712
 
c0e712
 /*
c0e712
diff -up sqlite-src-3071700/src/parse.y.old sqlite-src-3071700/src/parse.y
c0e712
--- sqlite-src-3071700/src/parse.y.old	2015-07-23 10:27:00.595682612 +0200
c0e712
+++ sqlite-src-3071700/src/parse.y	2015-07-23 10:27:47.850973405 +0200
c0e712
@@ -818,7 +818,7 @@ expr(A) ::= VARIABLE(X).     {
c0e712
   spanSet(&A, &X, &X);
c0e712
 }
c0e712
 expr(A) ::= expr(E) COLLATE ids(C). {
c0e712
-  A.pExpr = sqlite3ExprAddCollateToken(pParse, E.pExpr, &C);
c0e712
+  A.pExpr = sqlite3ExprAddCollateToken(pParse, E.pExpr, &C, 1);
c0e712
   A.zStart = E.zStart;
c0e712
   A.zEnd = &C.z[C.n];
c0e712
 }
c0e712
@@ -1143,14 +1143,14 @@ uniqueflag(A) ::= .        {A = OE_None;
c0e712
 idxlist_opt(A) ::= .                         {A = 0;}
c0e712
 idxlist_opt(A) ::= LP idxlist(X) RP.         {A = X;}
c0e712
 idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z).  {
c0e712
-  Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C);
c0e712
+  Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C, 1);
c0e712
   A = sqlite3ExprListAppend(pParse,X, p);
c0e712
   sqlite3ExprListSetName(pParse,A,&Y,1);
c0e712
   sqlite3ExprListCheckLength(pParse, A, "index");
c0e712
   if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z;
c0e712
 }
c0e712
 idxlist(A) ::= nm(Y) collate(C) sortorder(Z). {
c0e712
-  Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C);
c0e712
+  Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C, 1);
c0e712
   A = sqlite3ExprListAppend(pParse,0, p);
c0e712
   sqlite3ExprListSetName(pParse, A, &Y, 1);
c0e712
   sqlite3ExprListCheckLength(pParse, A, "index");
c0e712
diff -up sqlite-src-3071700/src/sqliteInt.h.old sqlite-src-3071700/src/sqliteInt.h
c0e712
--- sqlite-src-3071700/src/sqliteInt.h.old	2015-07-23 10:34:54.516598956 +0200
c0e712
+++ sqlite-src-3071700/src/sqliteInt.h	2015-07-23 10:35:12.908712134 +0200
c0e712
@@ -3103,7 +3103,7 @@ int sqlite3ReadSchema(Parse *pParse);
c0e712
 CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
c0e712
 CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
c0e712
 CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
c0e712
-Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*);
c0e712
+Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*, int);
c0e712
 Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
c0e712
 Expr *sqlite3ExprSkipCollate(Expr*);
c0e712
 int sqlite3CheckCollSeq(Parse *, CollSeq *);
c0e712
diff -up sqlite-src-3071700/src/where.c.old sqlite-src-3071700/src/where.c
c0e712
--- sqlite-src-3071700/src/where.c.old	2015-07-23 10:35:22.365770330 +0200
c0e712
+++ sqlite-src-3071700/src/where.c	2015-07-23 10:38:03.460761652 +0200
c0e712
@@ -1389,7 +1389,7 @@ static void exprAnalyze(
c0e712
     Expr *pNewExpr2;
c0e712
     int idxNew1;
c0e712
     int idxNew2;
c0e712
-    Token sCollSeqName;  /* Name of collating sequence */
c0e712
+    const char *zCollSeqName;  /* Name of collating sequence */
c0e712
 
c0e712
     pLeft = pExpr->x.pList->a[1].pExpr;
c0e712
     pStr2 = sqlite3ExprDup(db, pStr1, 0);
c0e712
@@ -1411,11 +1411,10 @@ static void exprAnalyze(
c0e712
       }
c0e712
       *pC = c + 1;
c0e712
     }
c0e712
-    sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
c0e712
-    sCollSeqName.n = 6;
c0e712
+    zCollSeqName = noCase ? "NOCASE" : "BINARY";
c0e712
     pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
c0e712
     pNewExpr1 = sqlite3PExpr(pParse, TK_GE, 
c0e712
-           sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
c0e712
+           sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName),
c0e712
            pStr1, 0);
c0e712
     idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
c0e712
     testcase( idxNew1==0 );
c0e712
@@ -1421,7 +1421,7 @@ static void exprAnalyze(
c0e712
     exprAnalyze(pSrc, pWC, idxNew1);
c0e712
     pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
c0e712
     pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
c0e712
-           sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
c0e712
+           sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName),
c0e712
            pStr2, 0);
c0e712
     idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
c0e712
     testcase( idxNew2==0 );
c0e712
diff -up sqlite-src-3071700/test/collate1.test.old sqlite-src-3071700/test/collate1.test
c0e712
--- sqlite-src-3071700/test/collate1.test.old	2015-07-23 10:38:58.858102547 +0200
c0e712
+++ sqlite-src-3071700/test/collate1.test	2015-07-23 10:40:30.474666325 +0200
c0e712
@@ -10,12 +10,13 @@
c0e712
 #
c0e712
 #***********************************************************************
c0e712
 # This file implements regression tests for SQLite library.  The
c0e712
-# focus of this script is page cache subsystem.
c0e712
+# focus of this script is testing collation sequences.
c0e712
 #
c0e712
 # $Id: collate1.test,v 1.5 2007/02/01 23:02:46 drh Exp $
c0e712
 
c0e712
 set testdir [file dirname $argv0]
c0e712
 source $testdir/tester.tcl
c0e712
+set testprefix collate1
c0e712
 
c0e712
 #
c0e712
 # Tests are roughly organised as follows:
c0e712
@@ -305,4 +306,54 @@ do_test collate1-4.5 {
c0e712
   }
c0e712
 } {}
c0e712
 
c0e712
+#-------------------------------------------------------------------------
c0e712
+# Fix problems with handling collation sequences named '"""'.
c0e712
+#
c0e712
+do_execsql_test 6.1 {
c0e712
+  SELECT """""""";
c0e712
+} {\"\"\"}
c0e712
+
c0e712
+do_catchsql_test 6.2 {
c0e712
+  CREATE TABLE x1(a);
c0e712
+  SELECT a FROM x1 ORDER BY a COLLATE """""""";
c0e712
+} {1 {no such collation sequence: """}}
c0e712
+
c0e712
+do_catchsql_test 6.3 {
c0e712
+  SELECT a FROM x1 ORDER BY 1 COLLATE """""""";
c0e712
+} {1 {no such collation sequence: """}}
c0e712
+
c0e712
+do_catchsql_test 6.4 {
c0e712
+  SELECT 0 UNION SELECT 0 ORDER BY 1 COLLATE """""""";
c0e712
+} {1 {no such collation sequence: """}}
c0e712
+
c0e712
+db collate {"""} [list string compare -nocase]
c0e712
+
c0e712
+do_execsql_test 6.5 {
c0e712
+  PRAGMA foreign_keys = ON;
c0e712
+  CREATE TABLE p1(a PRIMARY KEY COLLATE '"""');
c0e712
+  CREATE TABLE c1(x, y REFERENCES p1);
c0e712
+} {}
c0e712
+
c0e712
+do_execsql_test 6.6 { 
c0e712
+  INSERT INTO p1 VALUES('abc'); 
c0e712
+  INSERT INTO c1 VALUES(1, 'ABC'); 
c0e712
+}
c0e712
+
c0e712
+ifcapable foreignkey {
c0e712
+  do_catchsql_test 6.7 { 
c0e712
+    DELETE FROM p1 WHERE rowid = 1 
c0e712
+  } {1 {foreign key constraint failed}}
c0e712
+}
c0e712
+
c0e712
+do_execsql_test 6.8 { 
c0e712
+  INSERT INTO p1 VALUES('abb');
c0e712
+  INSERT INTO p1 VALUES('wxz');
c0e712
+  INSERT INTO p1 VALUES('wxy');
c0e712
+
c0e712
+  INSERT INTO c1 VALUES(2, 'abb');
c0e712
+  INSERT INTO c1 VALUES(3, 'wxz');
c0e712
+  INSERT INTO c1 VALUES(4, 'WXY');
c0e712
+  SELECT x, y FROM c1 ORDER BY y COLLATE """""""";
c0e712
+} {2 abb 1 ABC 4 WXY 3 wxz}
c0e712
+
c0e712
 finish_test