/ Check-in [ffecfca511]
Login

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

Overview
Comment:Ensure that the tbl_name column in the sqlite_temp_master table is updated correctly as part of a RENAME TABLE operation.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | alter-table-rename-column
Files: files | file ages | folders
SHA3-256: ffecfca511718e39e0003b380d5113755b8a11405a5bd80cc04503d9557f0842
User & Date: dan 2018-09-06 16:01:37
Context
2018-09-06
16:17
Merge latest trunk changes into this branch. Closed-Leaf check-in: 8a28a326d7 user: dan tags: alter-table-rename-column
16:01
Ensure that the tbl_name column in the sqlite_temp_master table is updated correctly as part of a RENAME TABLE operation. check-in: ffecfca511 user: dan tags: alter-table-rename-column
2018-09-05
17:52
Merge latest trunk changes into this branch. check-in: 6f4f707f9c user: dan tags: alter-table-rename-column
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/alter.c.

    45     45   */
    46     46   void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
    47     47     sqlite3NestedParse(pParse, 
    48     48         "SELECT 1 "
    49     49         "FROM \"%w\".%s "
    50     50         "WHERE name NOT LIKE 'sqlite_%%'"
    51     51         " AND sql NOT LIKE 'create virtual%%'"
    52         -      " AND sqlite_rename_test(%Q, sql, type, name, %d)=0 ",
           52  +      " AND sqlite_rename_test(%Q, sql, type, name, %d)=NULL ",
    53     53         zDb, MASTER_NAME, 
    54     54         zDb, bTemp
    55     55     );
    56     56   
    57     57     if( bTemp==0 ){
    58     58       sqlite3NestedParse(pParse, 
    59     59           "SELECT 1 "
    60     60           "FROM temp.%s "
    61     61           "WHERE name NOT LIKE 'sqlite_%%'"
    62     62           " AND sql NOT LIKE 'create virtual%%'"
    63         -        " AND sqlite_rename_test(%Q, sql, type, name, 1)=0 ",
           63  +        " AND sqlite_rename_test(%Q, sql, type, name, 1)=NULL ",
    64     64           MASTER_NAME, zDb 
    65     65       );
    66     66     }
    67     67   }
    68     68   
    69     69   /*
    70     70   ** Generate code to reload the schema for database iDb. And, if iDb!=1, for
................................................................................
   229    229     ** edit view and trigger definitions within the temp database 
   230    230     ** as required.  */
   231    231     if( iDb!=1 ){
   232    232       sqlite3NestedParse(pParse, 
   233    233           "UPDATE sqlite_temp_master SET "
   234    234               "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
   235    235               "tbl_name = "
   236         -              "CASE WHEN tbl_name=%Q COLLATE nocase THEN %Q ELSE tbl_name END "
          236  +              "CASE WHEN tbl_name=%Q COLLATE nocase AND "
          237  +              "          sqlite_rename_test(%Q, sql, type, name, 1) "
          238  +              "THEN %Q ELSE tbl_name END "
   237    239               "WHERE type IN ('view', 'trigger')"
   238         -        , zDb, zTabName, zName, zTabName, zTabName, zName);
          240  +        , zDb, zTabName, zName, zTabName, zDb, zName);
   239    241     }
   240    242   
   241    243     renameReloadSchema(pParse, iDb);
   242    244     renameTestSchema(pParse, zDb, iDb==1);
   243    245   
   244    246   exit_rename_table:
   245    247     sqlite3SrcListDelete(db, pSrc);
................................................................................
  1485   1487   }
  1486   1488   
  1487   1489   /*
  1488   1490   ** An SQL user function that checks that there are no parse or symbol
  1489   1491   ** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
  1490   1492   ** After an ALTER TABLE .. RENAME operation is performed and the schema
  1491   1493   ** reloaded, this function is called on each SQL statement in the schema
  1492         -** to ensure that it are still usable.
         1494  +** to ensure that it is still usable.
  1493   1495   **
  1494   1496   **   0: Database name ("main", "temp" etc.).
  1495   1497   **   1: SQL statement.
  1496   1498   **   2: Object type ("view", "table", "trigger" or "index").
  1497   1499   **   3: Object name.
  1498   1500   **   4: True if object is from temp schema.
         1501  +**
         1502  +** Unless it finds an error, this function normally returns NULL. However, it
         1503  +** returns integer value 1 if:
         1504  +**
         1505  +**   * the SQL argument creates a trigger, and
         1506  +**   * the table that the trigger is attached to is in database zDb.
  1499   1507   */
  1500   1508   static void renameTableTest(
  1501   1509     sqlite3_context *context,
  1502   1510     int NotUsed,
  1503   1511     sqlite3_value **argv
  1504   1512   ){
  1505   1513     sqlite3 *db = sqlite3_context_db_handle(context);
................................................................................
  1524   1532           sNC.pParse = &sParse;
  1525   1533           sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC);
  1526   1534           if( sParse.nErr ) rc = sParse.rc;
  1527   1535         }
  1528   1536   
  1529   1537         else if( sParse.pNewTrigger ){
  1530   1538           rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
         1539  +        if( rc==SQLITE_OK ){
         1540  +          int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema);
         1541  +          int i2 = sqlite3FindDbName(db, zDb);
         1542  +          if( i1==i2 ) sqlite3_result_int(context, 1);
         1543  +        }
  1531   1544         }
  1532   1545       }
  1533   1546   
  1534   1547       if( rc!=SQLITE_OK ){
  1535   1548         renameColumnParseError(context, 1, argv[2], argv[3], &sParse);
  1536   1549       }
  1537   1550       renameParseCleanup(&sParse);

Changes to test/altertab.test.

   321    321     }
   322    322   
   323    323     do_execsql_test 10.2 {
   324    324       SELECT * FROM ggg;
   325    325     } {a b c}
   326    326   }
   327    327   
   328         -finish_test
          328  +#-------------------------------------------------------------------------
          329  +reset_db
          330  +forcedelete test.db2
          331  +db func trigger trigger
          332  +set ::trigger [list]
          333  +proc trigger {args} {
          334  +  lappend ::trigger $args
          335  +}
          336  +do_execsql_test 11.0 {
          337  +  ATTACH 'test.db2' AS aux;
          338  +  CREATE TABLE aux.t1(a, b, c);
          339  +  CREATE TABLE main.t1(a, b, c);
          340  +  CREATE TEMP TRIGGER tr AFTER INSERT ON aux.t1 BEGIN
          341  +    SELECT trigger(new.a, new.b, new.c);
          342  +  END;
          343  +}
          344  +
          345  +do_execsql_test 11.1 {
          346  +  INSERT INTO main.t1 VALUES(1, 2, 3);
          347  +  INSERT INTO aux.t1 VALUES(4, 5, 6);
          348  +}
          349  +do_test 11.2 { set ::trigger } {{4 5 6}}
          350  +
          351  +do_execsql_test 11.3 {
          352  +  SELECT name, tbl_name FROM sqlite_temp_master;
          353  +} {tr t1}
          354  +
          355  +do_execsql_test 11.4 {
          356  +  ALTER TABLE main.t1 RENAME TO t2;
          357  +  SELECT name, tbl_name FROM sqlite_temp_master;
          358  +} {tr t1}
          359  +
          360  +do_execsql_test 11.5 {
          361  +  ALTER TABLE aux.t1 RENAME TO t2;
          362  +  SELECT name, tbl_name FROM sqlite_temp_master;
          363  +} {tr t2}
          364  +
          365  +do_execsql_test 11.6 {
          366  +  INSERT INTO aux.t2 VALUES(7, 8, 9);
          367  +}
          368  +do_test 11.7 { set ::trigger } {{4 5 6} {7 8 9}}
   329    369   
          370  +finish_test
   330    371