Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Improve the error messages emitted by RENAME TABLE. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | alter-table-rename-column |
Files: | files | file ages | folders |
SHA3-256: |
6805b5900df5e6d3329cbad2660875eb |
User & Date: | dan 2018-09-03 20:05:15.294 |
Context
2018-09-04
| ||
18:23 | Merge latest trunk changes into this branch. (check-in: ef9e088290 user: dan tags: alter-table-rename-column) | |
2018-09-03
| ||
20:05 | Improve the error messages emitted by RENAME TABLE. (check-in: 6805b5900d user: dan tags: alter-table-rename-column) | |
2018-09-01
| ||
20:38 | Add another test case to altertab.test. (check-in: 828e8849fa user: dan tags: alter-table-rename-column) | |
Changes
Changes to src/alter.c.
︙ | ︙ | |||
187 188 189 190 191 192 193 | zTabName = pTab->zName; nTabName = sqlite3Utf8CharLen(zTabName, -1); /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in ** the schema to use the new table name. */ sqlite3NestedParse(pParse, "UPDATE \"%w\".%s SET " | | | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | zTabName = pTab->zName; nTabName = sqlite3Utf8CharLen(zTabName, -1); /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in ** the schema to use the new table name. */ sqlite3NestedParse(pParse, "UPDATE \"%w\".%s SET " "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, %d) " "WHERE (type!='index' OR tbl_name=%Q COLLATE nocase)" "AND name NOT LIKE 'sqlite_%%'" , zDb, MASTER_NAME, zDb, zTabName, zName, (iDb==1), zTabName ); /* Update the tbl_name and name columns of the sqlite_master table ** as required. */ |
︙ | ︙ | |||
227 228 229 230 231 232 233 | /* If the table being renamed is not itself part of the temp database, ** edit view and trigger definitions within the temp database ** as required. */ if( iDb!=1 ){ sqlite3NestedParse(pParse, "UPDATE sqlite_temp_master SET " | | | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | /* If the table being renamed is not itself part of the temp database, ** 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); |
︙ | ︙ | |||
1271 1272 1273 1274 1275 1276 1277 | /* ** This C function implements an SQL user function that is used by SQL code ** generated by the ALTER TABLE ... RENAME command to modify the definition ** of any foreign key constraints that use the table being renamed as the ** parent table. It is passed three arguments: ** ** 0: The database containing the table being renamed. | > > | | | | | | | | | 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 | /* ** This C function implements an SQL user function that is used by SQL code ** generated by the ALTER TABLE ... RENAME command to modify the definition ** of any foreign key constraints that use the table being renamed as the ** parent table. It is passed three arguments: ** ** 0: The database containing the table being renamed. ** 1. type: Type of object ("table", "view" etc.) ** 2. object: Name of object ** 3: The complete text of the schema statement being modified, ** 4: The old name of the table being renamed, and ** 5: The new name of the table being renamed. ** 6: True if the schema statement comes from the temp db. ** ** It returns the new schema statement. For example: ** ** sqlite_rename_table('main', 'CREATE TABLE t1(a REFERENCES t2)','t2','t3',0) ** -> 'CREATE TABLE t1(a REFERENCES t3)' */ static void renameTableFunc( sqlite3_context *context, int NotUsed, sqlite3_value **argv ){ sqlite3 *db = sqlite3_context_db_handle(context); const char *zDb = (const char*)sqlite3_value_text(argv[0]); const char *zInput = (const char*)sqlite3_value_text(argv[3]); const char *zOld = (const char*)sqlite3_value_text(argv[4]); const char *zNew = (const char*)sqlite3_value_text(argv[5]); int bTemp = sqlite3_value_int(argv[6]); UNUSED_PARAMETER(NotUsed); if( zInput && zOld && zNew ){ Parse sParse; int rc; int bQuote = 1; RenameCtx sCtx; |
︙ | ︙ | |||
1384 1385 1386 1387 1388 1389 1390 | #endif } if( rc==SQLITE_OK ){ rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote); } if( rc!=SQLITE_OK ){ | > > > | > | 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 | #endif } if( rc==SQLITE_OK ){ rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote); } if( rc!=SQLITE_OK ){ if( sParse.zErrMsg ){ renameColumnParseError(context, 0, argv[1], argv[2], &sParse); }else{ sqlite3_result_error_code(context, rc); } } renameParseCleanup(&sParse); renameTokenFree(db, sCtx.pList); sqlite3BtreeLeaveAll(db); #ifndef SQLITE_OMIT_AUTHORIZATION db->xAuth = xAuth; |
︙ | ︙ | |||
1449 1450 1451 1452 1453 1454 1455 | /* ** Register built-in functions used to help implement ALTER TABLE */ void sqlite3AlterFunctions(void){ static FuncDef aAlterTableFuncs[] = { FUNCTION(sqlite_rename_column, 9, 0, 0, renameColumnFunc), | | | 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 | /* ** Register built-in functions used to help implement ALTER TABLE */ void sqlite3AlterFunctions(void){ static FuncDef aAlterTableFuncs[] = { FUNCTION(sqlite_rename_column, 9, 0, 0, renameColumnFunc), FUNCTION(sqlite_rename_table, 7, 0, 0, renameTableFunc), FUNCTION(sqlite_rename_test, 5, 0, 0, renameTableTest), }; sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); } #endif /* SQLITE_ALTER_TABLE */ |
Changes to test/alter.test.
︙ | ︙ | |||
684 685 686 687 688 689 690 | # alter-9.X - Special test: Make sure the sqlite_rename_column() and # rename_table() functions do not crash when handed bad input. # do_test alter-9.1 { execsql {SELECT SQLITE_RENAME_COLUMN(0,0,0,0,0,0,0,0,0)} } {{}} foreach {tn sql} { | | | | | > > | 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 | # alter-9.X - Special test: Make sure the sqlite_rename_column() and # rename_table() functions do not crash when handed bad input. # do_test alter-9.1 { execsql {SELECT SQLITE_RENAME_COLUMN(0,0,0,0,0,0,0,0,0)} } {{}} foreach {tn sql} { 1 { SELECT SQLITE_RENAME_TABLE(0,0,0,0,0,0,0) } 2 { SELECT SQLITE_RENAME_TABLE(10,20,30,40,50,60,70) } 3 { SELECT SQLITE_RENAME_TABLE('foo','foo','foo','foo','foo','foo','foo') } } { do_test alter-9.2.$tn { catch { execsql $sql } } 1 } #------------------------------------------------------------------------ # alter-10.X - Make sure ALTER TABLE works with multi-byte UTF-8 characters # in the names. # do_test alter-10.1 { |
︙ | ︙ |
Changes to test/altertab.test.
︙ | ︙ | |||
235 236 237 238 239 240 241 | ), ( 'main', NULL, 'ddd', 'eee', 0 ); } {} do_execsql_test 7.2 { SELECT | | | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | ), ( 'main', NULL, 'ddd', 'eee', 0 ); } {} do_execsql_test 7.2 { SELECT sqlite_rename_table(db, 0, 0, sql, zOld, zNew, bTemp) FROM ddd; } {{} {} {}} #------------------------------------------------------------------------- # reset_db forcedelete test.db2 |
︙ | ︙ | |||
262 263 264 265 266 267 268 269 270 271 272 | ALTER TABLE aux.p1 RENAME TO ppp; } do_execsql_test 8.2 { INSERT INTO aux.c1 VALUES(NULL, 1); SELECT sql FROM aux.sqlite_master WHERE name = 'c1'; } {{CREATE TABLE c1(x INTEGER PRIMARY KEY, y REFERENCES "ppp"(a))}} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | ALTER TABLE aux.p1 RENAME TO ppp; } do_execsql_test 8.2 { INSERT INTO aux.c1 VALUES(NULL, 1); SELECT sql FROM aux.sqlite_master WHERE name = 'c1'; } {{CREATE TABLE c1(x INTEGER PRIMARY KEY, y REFERENCES "ppp"(a))}} reset_db do_execsql_test 9.0 { CREATE TABLE t1(a, b, c); CREATE VIEW v1 AS SELECT * FROM t2; } do_catchsql_test 9.1 { ALTER TABLE t1 RENAME TO t3; } {1 {error in view v1: no such table: main.t2}} do_execsql_test 9.2 { DROP VIEW v1; CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(new.a); END; } do_catchsql_test 9.3 { ALTER TABLE t1 RENAME TO t3; } {1 {error in trigger tr: no such table: main.t2}} forcedelete test.db2 do_execsql_test 9.4 { DROP TRIGGER tr; ATTACH 'test.db2' AS aux; CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN SELECT 1, 2, 3; END; CREATE TABLE aux.t1(x); CREATE TEMP TRIGGER tr AFTER INSERT ON aux.t1 BEGIN SELECT 1, 2, 3; END; } do_execsql_test 9.5 { ALTER TABLE main.t1 RENAME TO t3; } do_execsql_test 9.6 { SELECT sql FROM sqlite_temp_master; SELECT sql FROM sqlite_master WHERE type='trigger'; } { {CREATE TRIGGER tr AFTER INSERT ON aux.t1 BEGIN SELECT 1, 2, 3; END} {CREATE TRIGGER tr AFTER INSERT ON "t3" BEGIN SELECT 1, 2, 3; END} } finish_test |