Blob Blame History Raw
# Fix a problem causing collation sequence names to be dequoted multiple times
# under some circumstances.
# Upstream original patch: https://www.sqlite.org/src/info/eddc05e7bb31fae7

diff -up sqlite-src-3071700/src/expr.c.old sqlite-src-3071700/src/expr.c
--- sqlite-src-3071700/src/expr.c.old	2015-07-23 10:26:11.220420294 +0200
+++ sqlite-src-3071700/src/expr.c	2015-07-23 10:26:47.468601833 +0200
@@ -65,9 +65,9 @@ char sqlite3ExprAffinity(Expr *pExpr){
 ** If a memory allocation error occurs, that fact is recorded in pParse->db
 ** and the pExpr parameter is returned unchanged.
 */
-Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
+Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName, int dequote){
   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;
@@ -81,7 +81,7 @@ Expr *sqlite3ExprAddCollateString(Parse
   assert( zC!=0 );
   s.z = zC;
   s.n = sqlite3Strlen30(s.z);
-  return sqlite3ExprAddCollateToken(pParse, pExpr, &s);
+  return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0);
 }
 
 /*
diff -up sqlite-src-3071700/src/parse.y.old sqlite-src-3071700/src/parse.y
--- sqlite-src-3071700/src/parse.y.old	2015-07-23 10:27:00.595682612 +0200
+++ sqlite-src-3071700/src/parse.y	2015-07-23 10:27:47.850973405 +0200
@@ -818,7 +818,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];
 }
@@ -1143,14 +1143,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 -up sqlite-src-3071700/src/sqliteInt.h.old sqlite-src-3071700/src/sqliteInt.h
--- sqlite-src-3071700/src/sqliteInt.h.old	2015-07-23 10:34:54.516598956 +0200
+++ sqlite-src-3071700/src/sqliteInt.h	2015-07-23 10:35:12.908712134 +0200
@@ -3103,7 +3103,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*, Token*);
+Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*, int);
 Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
 Expr *sqlite3ExprSkipCollate(Expr*);
 int sqlite3CheckCollSeq(Parse *, CollSeq *);
diff -up sqlite-src-3071700/src/where.c.old sqlite-src-3071700/src/where.c
--- sqlite-src-3071700/src/where.c.old	2015-07-23 10:35:22.365770330 +0200
+++ sqlite-src-3071700/src/where.c	2015-07-23 10:38:03.460761652 +0200
@@ -1389,7 +1389,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);
@@ -1411,11 +1411,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);
     idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
     testcase( idxNew1==0 );
@@ -1421,7 +1421,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);
     idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
     testcase( idxNew2==0 );
diff -up sqlite-src-3071700/test/collate1.test.old sqlite-src-3071700/test/collate1.test
--- sqlite-src-3071700/test/collate1.test.old	2015-07-23 10:38:58.858102547 +0200
+++ sqlite-src-3071700/test/collate1.test	2015-07-23 10:40:30.474666325 +0200
@@ -10,12 +10,13 @@
 #
 #***********************************************************************
 # 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:
@@ -305,4 +306,54 @@ do_test collate1-4.5 {
   }
 } {}
 
+#-------------------------------------------------------------------------
+# 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