/ Check-in [ffecfca5]
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: 8a28a326 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: ffecfca5 user: dan tags: alter-table-rename-column
2018-09-05
17:52
Merge latest trunk changes into this branch. check-in: 6f4f707f user: dan tags: alter-table-rename-column
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/alter.c.

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
...
229
230
231
232
233
234
235
236


237
238
239
240
241
242
243
244
245
....
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498






1499
1500
1501
1502
1503
1504
1505
....
1524
1525
1526
1527
1528
1529
1530





1531
1532
1533
1534
1535
1536
1537
*/
void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
  sqlite3NestedParse(pParse, 
      "SELECT 1 "
      "FROM \"%w\".%s "
      "WHERE name NOT LIKE 'sqlite_%%'"
      " AND sql NOT LIKE 'create virtual%%'"
      " AND sqlite_rename_test(%Q, sql, type, name, %d)=0 ",
      zDb, MASTER_NAME, 
      zDb, bTemp
  );

  if( bTemp==0 ){
    sqlite3NestedParse(pParse, 
        "SELECT 1 "
        "FROM temp.%s "
        "WHERE name NOT LIKE 'sqlite_%%'"
        " AND sql NOT LIKE 'create virtual%%'"
        " AND sqlite_rename_test(%Q, sql, type, name, 1)=0 ",
        MASTER_NAME, zDb 
    );
  }
}

/*
** Generate code to reload the schema for database iDb. And, if iDb!=1, for
................................................................................
  ** edit view and trigger definitions within the temp database 
  ** as required.  */
  if( iDb!=1 ){
    sqlite3NestedParse(pParse, 
        "UPDATE sqlite_temp_master SET "
            "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
            "tbl_name = "
              "CASE WHEN tbl_name=%Q COLLATE nocase THEN %Q ELSE tbl_name END "


            "WHERE type IN ('view', 'trigger')"
        , zDb, zTabName, zName, zTabName, zTabName, zName);
  }

  renameReloadSchema(pParse, iDb);
  renameTestSchema(pParse, zDb, iDb==1);

exit_rename_table:
  sqlite3SrcListDelete(db, pSrc);
................................................................................
}

/*
** An SQL user function that checks that there are no parse or symbol
** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
** After an ALTER TABLE .. RENAME operation is performed and the schema
** reloaded, this function is called on each SQL statement in the schema
** to ensure that it are still usable.
**
**   0: Database name ("main", "temp" etc.).
**   1: SQL statement.
**   2: Object type ("view", "table", "trigger" or "index").
**   3: Object name.
**   4: True if object is from temp schema.






*/
static void renameTableTest(
  sqlite3_context *context,
  int NotUsed,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
................................................................................
        sNC.pParse = &sParse;
        sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC);
        if( sParse.nErr ) rc = sParse.rc;
      }

      else if( sParse.pNewTrigger ){
        rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);





      }
    }

    if( rc!=SQLITE_OK ){
      renameColumnParseError(context, 1, argv[2], argv[3], &sParse);
    }
    renameParseCleanup(&sParse);







|










|







 







|
>
>

|







 







|






>
>
>
>
>
>







 







>
>
>
>
>







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
...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
....
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
....
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
*/
void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
  sqlite3NestedParse(pParse, 
      "SELECT 1 "
      "FROM \"%w\".%s "
      "WHERE name NOT LIKE 'sqlite_%%'"
      " AND sql NOT LIKE 'create virtual%%'"
      " AND sqlite_rename_test(%Q, sql, type, name, %d)=NULL ",
      zDb, MASTER_NAME, 
      zDb, bTemp
  );

  if( bTemp==0 ){
    sqlite3NestedParse(pParse, 
        "SELECT 1 "
        "FROM temp.%s "
        "WHERE name NOT LIKE 'sqlite_%%'"
        " AND sql NOT LIKE 'create virtual%%'"
        " AND sqlite_rename_test(%Q, sql, type, name, 1)=NULL ",
        MASTER_NAME, zDb 
    );
  }
}

/*
** Generate code to reload the schema for database iDb. And, if iDb!=1, for
................................................................................
  ** edit view and trigger definitions within the temp database 
  ** as required.  */
  if( iDb!=1 ){
    sqlite3NestedParse(pParse, 
        "UPDATE sqlite_temp_master SET "
            "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
            "tbl_name = "
              "CASE WHEN tbl_name=%Q COLLATE nocase AND "
              "          sqlite_rename_test(%Q, sql, type, name, 1) "
              "THEN %Q ELSE tbl_name END "
            "WHERE type IN ('view', 'trigger')"
        , zDb, zTabName, zName, zTabName, zDb, zName);
  }

  renameReloadSchema(pParse, iDb);
  renameTestSchema(pParse, zDb, iDb==1);

exit_rename_table:
  sqlite3SrcListDelete(db, pSrc);
................................................................................
}

/*
** An SQL user function that checks that there are no parse or symbol
** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
** After an ALTER TABLE .. RENAME operation is performed and the schema
** reloaded, this function is called on each SQL statement in the schema
** to ensure that it is still usable.
**
**   0: Database name ("main", "temp" etc.).
**   1: SQL statement.
**   2: Object type ("view", "table", "trigger" or "index").
**   3: Object name.
**   4: True if object is from temp schema.
**
** Unless it finds an error, this function normally returns NULL. However, it
** returns integer value 1 if:
**
**   * the SQL argument creates a trigger, and
**   * the table that the trigger is attached to is in database zDb.
*/
static void renameTableTest(
  sqlite3_context *context,
  int NotUsed,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
................................................................................
        sNC.pParse = &sParse;
        sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC);
        if( sParse.nErr ) rc = sParse.rc;
      }

      else if( sParse.pNewTrigger ){
        rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
        if( rc==SQLITE_OK ){
          int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema);
          int i2 = sqlite3FindDbName(db, zDb);
          if( i1==i2 ) sqlite3_result_int(context, 1);
        }
      }
    }

    if( rc!=SQLITE_OK ){
      renameColumnParseError(context, 1, argv[2], argv[3], &sParse);
    }
    renameParseCleanup(&sParse);

Changes to test/altertab.test.

321
322
323
324
325
326
327
328







329







330




























  }

  do_execsql_test 10.2 {
    SELECT * FROM ggg;
  } {a b c}
}

finish_test



















































<
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
321
322
323
324
325
326
327

328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
  }

  do_execsql_test 10.2 {
    SELECT * FROM ggg;
  } {a b c}
}


#-------------------------------------------------------------------------
reset_db
forcedelete test.db2
db func trigger trigger
set ::trigger [list]
proc trigger {args} {
  lappend ::trigger $args
}
do_execsql_test 11.0 {
  ATTACH 'test.db2' AS aux;
  CREATE TABLE aux.t1(a, b, c);
  CREATE TABLE main.t1(a, b, c);
  CREATE TEMP TRIGGER tr AFTER INSERT ON aux.t1 BEGIN
    SELECT trigger(new.a, new.b, new.c);
  END;
}

do_execsql_test 11.1 {
  INSERT INTO main.t1 VALUES(1, 2, 3);
  INSERT INTO aux.t1 VALUES(4, 5, 6);
}
do_test 11.2 { set ::trigger } {{4 5 6}}

do_execsql_test 11.3 {
  SELECT name, tbl_name FROM sqlite_temp_master;
} {tr t1}

do_execsql_test 11.4 {
  ALTER TABLE main.t1 RENAME TO t2;
  SELECT name, tbl_name FROM sqlite_temp_master;
} {tr t1}

do_execsql_test 11.5 {
  ALTER TABLE aux.t1 RENAME TO t2;
  SELECT name, tbl_name FROM sqlite_temp_master;
} {tr t2}

do_execsql_test 11.6 {
  INSERT INTO aux.t2 VALUES(7, 8, 9);
}
do_test 11.7 { set ::trigger } {{4 5 6} {7 8 9}}

finish_test