SQLite

Check-in [eb4f452e35]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix an RBU problem causing errors when updating tables with default collation sequences that require quoting (e.g. COLLATE "ICU_root-u-kn-on").
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: eb4f452e354065d610ff57a6a9312ad119b6b0cc467f9dff105f0718bc27ef01
User & Date: dan 2018-03-22 17:13:44.592
References
2018-03-22
17:17
Fix an RBU problem causing errors when updating tables with default collation sequences that require quoting (e.g. COLLATE "ICU_root-u-kn-on"). Cherrypick of [eb4f452e]. (check-in: 5dd61e1cbd user: dan tags: branch-3.22)
Context
2018-03-22
20:35
Add APIs to the sessions module for "rebasing" changesets. (check-in: 509506c76b user: dan tags: trunk)
17:17
Fix an RBU problem causing errors when updating tables with default collation sequences that require quoting (e.g. COLLATE "ICU_root-u-kn-on"). Cherrypick of [eb4f452e]. (check-in: 5dd61e1cbd user: dan tags: branch-3.22)
17:13
Fix an RBU problem causing errors when updating tables with default collation sequences that require quoting (e.g. COLLATE "ICU_root-u-kn-on"). (check-in: eb4f452e35 user: dan tags: trunk)
17:02
Fix a test script problem causing rbuvacuum.test to fail when run along with other tests. (check-in: 901cb3b6a2 user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Added ext/rbu/rbucollate.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
# 2018 March 22
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] rbu_common.tcl]
set ::testprefix rbucollate

ifcapable !icu_collations {
  finish_test
  return
}

db close
sqlite3_shutdown
sqlite3_config_uri 1
reset_db
 
# Create a simple RBU database. That expects to write to a table:
#
#   CREATE TABLE t1(a PRIMARY KEY, b, c);
#
proc create_rbu1 {filename} {
  forcedelete $filename
  sqlite3 rbu1 $filename  
  rbu1 eval {
    CREATE TABLE data_t1(a, b, c, rbu_control);
    INSERT INTO data_t1 VALUES('a', 'one', 1, 0);
    INSERT INTO data_t1 VALUES('b', 'two', 2, 0);
    INSERT INTO data_t1 VALUES('c', 'three', 3, 0);
  }
  rbu1 close
  return $filename
}

do_execsql_test 1.0 {
  SELECT icu_load_collation('en_US', 'my-collate');
  CREATE TABLE t1(a COLLATE "my-collate" PRIMARY KEY, b, c);
} {{}}

do_test 1.2 {
  create_rbu1 testrbu.db
  sqlite3rbu rbu test.db testrbu.db
  rbu dbMain_eval { SELECT icu_load_collation('en_US', 'my-collate') }
  rbu dbRbu_eval { SELECT icu_load_collation('en_US', 'my-collate') }
  while 1 {
    set rc [rbu step]
    if {$rc!="SQLITE_OK"} break
  }
  rbu close
  db eval { SELECT * FROM t1 }
} {a one 1 b two 2 c three 3}

#forcedelete testrbu.db
finish_test

Changes to ext/rbu/sqlite3rbu.c.
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816

    while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
      int bKey = sqlite3_column_int(pXInfo, 5);
      if( bKey ){
        int iCid = sqlite3_column_int(pXInfo, 1);
        int bDesc = sqlite3_column_int(pXInfo, 3);
        const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4);
        zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %s", zCols, zComma, 
            iCid, pIter->azTblType[iCid], zCollate
        );
        zPk = rbuMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":"");
        zComma = ", ";
      }
    }
    zCols = rbuMPrintf(p, "%z, id INTEGER", zCols);







|







1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816

    while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
      int bKey = sqlite3_column_int(pXInfo, 5);
      if( bKey ){
        int iCid = sqlite3_column_int(pXInfo, 1);
        int bDesc = sqlite3_column_int(pXInfo, 3);
        const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4);
        zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %Q", zCols, zComma, 
            iCid, pIter->azTblType[iCid], zCollate
        );
        zPk = rbuMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":"");
        zComma = ", ";
      }
    }
    zCols = rbuMPrintf(p, "%z, id INTEGER", zCols);
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
      );

      if( pIter->eType==RBU_PK_IPK && pIter->abTblPk[iCol] ){
        /* If the target table column is an "INTEGER PRIMARY KEY", add
        ** "PRIMARY KEY" to the imposter table column declaration. */
        zPk = "PRIMARY KEY ";
      }
      zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %s%s", 
          zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl,
          (pIter->abNotNull[iCol] ? " NOT NULL" : "")
      );
      zComma = ", ";
    }

    if( pIter->eType==RBU_PK_WITHOUT_ROWID ){







|







1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
      );

      if( pIter->eType==RBU_PK_IPK && pIter->abTblPk[iCol] ){
        /* If the target table column is an "INTEGER PRIMARY KEY", add
        ** "PRIMARY KEY" to the imposter table column declaration. */
        zPk = "PRIMARY KEY ";
      }
      zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %Q%s", 
          zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl,
          (pIter->abNotNull[iCol] ? " NOT NULL" : "")
      );
      zComma = ", ";
    }

    if( pIter->eType==RBU_PK_WITHOUT_ROWID ){
Changes to ext/rbu/test_rbu.c.
77
78
79
80
81
82
83

84
85
86
87
88
89
90
    {"bp_progress", 2, ""},          /* 5 */
    {"db", 3, "RBU"},                /* 6 */
    {"state", 2, ""},                /* 7 */
    {"progress", 2, ""},             /* 8 */
    {"close_no_error", 2, ""},       /* 9 */
    {"temp_size_limit", 3, "LIMIT"}, /* 10 */
    {"temp_size", 2, ""},            /* 11 */

    {0,0,0}
  };
  int iCmd;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "METHOD");
    return TCL_ERROR;







>







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    {"bp_progress", 2, ""},          /* 5 */
    {"db", 3, "RBU"},                /* 6 */
    {"state", 2, ""},                /* 7 */
    {"progress", 2, ""},             /* 8 */
    {"close_no_error", 2, ""},       /* 9 */
    {"temp_size_limit", 3, "LIMIT"}, /* 10 */
    {"temp_size", 2, ""},            /* 11 */
    {"dbRbu_eval", 3, "SQL"},        /* 12 */
    {0,0,0}
  };
  int iCmd;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "METHOD");
    return TCL_ERROR;
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156
157
    case 3: /* savestate */ {
      int rc = sqlite3rbu_savestate(pRbu);
      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
      ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
      break;
    }


    case 4: /* dbMain_eval */ {
      sqlite3 *db = sqlite3rbu_db(pRbu, 0);
      int rc = sqlite3_exec(db, Tcl_GetString(objv[2]), 0, 0, 0);
      if( rc!=SQLITE_OK ){
        Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(db), -1));
        ret = TCL_ERROR;
      }
      break;
    }







>
|
|







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
    case 3: /* savestate */ {
      int rc = sqlite3rbu_savestate(pRbu);
      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
      ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
      break;
    }

    case 12: /* dbRbu_eval */ 
    case 4:  /* dbMain_eval */ {
      sqlite3 *db = sqlite3rbu_db(pRbu, (iCmd==12));
      int rc = sqlite3_exec(db, Tcl_GetString(objv[2]), 0, 0, 0);
      if( rc!=SQLITE_OK ){
        Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(db), -1));
        ret = TCL_ERROR;
      }
      break;
    }