Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Have "ALTER TABLE ADD COLUMN" reload the entire db schema, as "RENAME COLUMN" and "RENAME TABLE" do. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | alter-table-rename-table |
Files: | files | file ages | folders |
SHA3-256: |
8d89ddc1a628e983b0fbd929c9c9daac |
User & Date: | dan 2018-09-01 16:05:50.207 |
Context
2018-09-01
| ||
16:13 | Merge alter-table-rename-table back into this branch. (check-in: ad704a7c86 user: dan tags: alter-table-rename-column) | |
16:05 | Have "ALTER TABLE ADD COLUMN" reload the entire db schema, as "RENAME COLUMN" and "RENAME TABLE" do. (Closed-Leaf check-in: 8d89ddc1a6 user: dan tags: alter-table-rename-table) | |
15:55 | Merge fixes from the alter-table-rename-column branch that occurred after this branch separated from that one. (check-in: 22e785aa2b user: drh tags: alter-table-rename-table) | |
Changes
Changes to src/alter.c.
︙ | ︙ | |||
16 17 18 19 20 21 22 | /* ** The code in this file only exists if we are not omitting the ** ALTER TABLE logic from the build. */ #ifndef SQLITE_OMIT_ALTERTABLE | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > > > > > > | 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 | /* ** The code in this file only exists if we are not omitting the ** ALTER TABLE logic from the build. */ #ifndef SQLITE_OMIT_ALTERTABLE /* ** Parameter zName is the name of a table that is about to be altered ** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN). ** If the table is a system table, this function leaves an error message ** in pParse->zErr (system tables may not be altered) and returns non-zero. ** ** Or, if zName is not a system table, zero is returned. */ static int isSystemTable(Parse *pParse, const char *zName){ if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ sqlite3ErrorMsg(pParse, "table %s may not be altered", zName); return 1; } return 0; } /* ** Generate code to verify that the schemas of database zDb and, if ** bTemp is not true, database "temp", can still be parsed. This is ** called at the end of the generation of an ALTER TABLE ... RENAME ... ** statement to ensure that the operation has not rendered any schema ** objects unusable. */ 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 ", |
︙ | ︙ | |||
179 180 181 182 183 184 185 186 187 188 189 190 191 192 | "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 implement the "ALTER TABLE xxx RENAME TO yyy" ** command. */ void sqlite3AlterRenameTable( Parse *pParse, /* Parser context. */ | > > > > > > > > > > > > > | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | "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 ** the temp database as well. */ void renameReloadSchema(Parse *pParse, int iDb){ Vdbe *v = pParse->pVdbe; if( v ){ sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0); if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0); } } /* ** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" ** command. */ void sqlite3AlterRenameTable( Parse *pParse, /* Parser context. */ |
︙ | ︙ | |||
269 270 271 272 273 274 275 | ** schema). Open a statement transaction if the table is a virtual ** table. */ v = sqlite3GetVdbe(pParse); if( v==0 ){ goto exit_rename_table; } | < < | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | ** schema). Open a statement transaction if the table is a virtual ** table. */ v = sqlite3GetVdbe(pParse); if( v==0 ){ goto exit_rename_table; } /* If this is a virtual table, invoke the xRename() function if ** one is defined. The xRename() callback will modify the names ** of any resources used by the v-table implementation (including other ** SQLite tables) that are identified by the name of the virtual table. */ #ifndef SQLITE_OMIT_VIRTUALTABLE |
︙ | ︙ | |||
341 342 343 344 345 346 347 | "sql = sqlite_rename_table(%Q, 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); } | < < | | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | "sql = sqlite_rename_table(%Q, 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); sqlite3DbFree(db, zName); db->mDbFlags = savedDbFlags; } |
︙ | ︙ | |||
370 371 372 373 374 375 376 | int iDb; /* Database number */ const char *zDb; /* Database name */ const char *zTab; /* Table name */ char *zCol; /* Null-terminated column definition */ Column *pCol; /* The new column */ Expr *pDflt; /* Default value for the new column */ sqlite3 *db; /* The database connection; */ | | > < | 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | int iDb; /* Database number */ const char *zDb; /* Database name */ const char *zTab; /* Table name */ char *zCol; /* Null-terminated column definition */ Column *pCol; /* The new column */ Expr *pDflt; /* Default value for the new column */ sqlite3 *db; /* The database connection; */ Vdbe *v; /* The prepared statement under construction */ int r1; /* Temporary registers */ char *zWhere; /* WHERE clause for reloading schema */ db = pParse->db; if( pParse->nErr || db->mallocFailed ) return; pNew = pParse->pNewTable; assert( pNew ); assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pNew->pSchema); zDb = db->aDb[iDb].zDbSName; zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ |
︙ | ︙ | |||
470 471 472 473 474 475 476 | db->mDbFlags = savedDbFlags; } /* Make sure the schema version is at least 3. But do not upgrade ** from less than 3 to 4, as that will corrupt any preexisting DESC ** index. */ | > > | | | | | | | | | > | | | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 | db->mDbFlags = savedDbFlags; } /* Make sure the schema version is at least 3. But do not upgrade ** from less than 3 to 4, as that will corrupt any preexisting DESC ** index. */ v = sqlite3GetVdbe(pParse); if( v ){ r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2); sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3); sqlite3ReleaseTempReg(pParse, r1); } /* Reload the table definition */ renameReloadSchema(pParse, iDb); } /* ** This function is called by the parser after the table-name in ** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument ** pSrc is the full-name of the table being altered. ** |
︙ | ︙ | |||
565 566 567 568 569 570 571 | pCol->zColl = 0; pCol->pDflt = 0; } pNew->pSchema = db->aDb[iDb].pSchema; pNew->addColOffset = pTab->addColOffset; pNew->nTabRef = 1; | < < < < < < | 459 460 461 462 463 464 465 466 467 468 469 470 471 472 | pCol->zColl = 0; pCol->pDflt = 0; } pNew->pSchema = db->aDb[iDb].pSchema; pNew->addColOffset = pTab->addColOffset; pNew->nTabRef = 1; exit_begin_add_column: sqlite3SrcListDelete(db, pSrc); return; } /* ** Parameter pTab is the subject of an ALTER TABLE ... RENAME COLUMN |
︙ | ︙ | |||
688 689 690 691 692 693 694 | "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d) " "WHERE type IN ('trigger', 'view')", MASTER_NAME, zDb, pTab->zName, iCol, zNew, bQuote ); /* Drop and reload the database schema. */ | < | < < < < | 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 | "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d) " "WHERE type IN ('trigger', 'view')", MASTER_NAME, zDb, pTab->zName, iCol, zNew, bQuote ); /* Drop and reload the database schema. */ renameReloadSchema(pParse, iSchema); renameTestSchema(pParse, zDb, iSchema==1); exit_rename_column: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zOld); sqlite3DbFree(db, zNew); return; |
︙ | ︙ | |||
741 742 743 744 745 746 747 | int iCol; /* Index of column being renamed */ Table *pTab; /* Table being ALTERed */ const char *zOld; /* Old column name */ }; void renameTokenClear(Parse *pParse, void *pPtr){ RenameToken *p; | | | 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 | int iCol; /* Index of column being renamed */ Table *pTab; /* Table being ALTERed */ const char *zOld; /* Old column name */ }; void renameTokenClear(Parse *pParse, void *pPtr){ RenameToken *p; assert( pPtr || pParse->db->mallocFailed ); for(p=pParse->pRename; p; p=p->pNext){ if( p->p==pPtr ){ p->p = 0; } } } |
︙ | ︙ | |||
1534 1535 1536 1537 1538 1539 1540 | int NotUsed, sqlite3_value **argv ){ sqlite3 *db = sqlite3_context_db_handle(context); unsigned char const *zDb = sqlite3_value_text(argv[0]); unsigned char const *zInput = sqlite3_value_text(argv[1]); int bTemp = sqlite3_value_int(argv[4]); | < < > > > | | | | | | | | | | | | | | | | | > | 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 | int NotUsed, sqlite3_value **argv ){ sqlite3 *db = sqlite3_context_db_handle(context); unsigned char const *zDb = sqlite3_value_text(argv[0]); unsigned char const *zInput = sqlite3_value_text(argv[1]); int bTemp = sqlite3_value_int(argv[4]); #ifndef SQLITE_OMIT_AUTHORIZATION sqlite3_xauth xAuth = db->xAuth; db->xAuth = 0; #endif if( zDb && zInput ){ int rc; Parse sParse; rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp); if( rc==SQLITE_OK ){ if( sParse.pNewTable && sParse.pNewTable->pSelect ){ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); 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); } #ifndef SQLITE_OMIT_AUTHORIZATION db->xAuth = xAuth; #endif } /* |
︙ | ︙ |