Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch tkt9b78184b-alt Excluding Merge-Ins
This is equivalent to a diff from eab42975 to b0629132
2019-07-08
| ||
12:44 | Comment improvements. No changes to code. (Leaf check-in: b0629132 user: drh tags: tkt9b78184b-alt) | |
2019-07-02
| ||
20:10 | Have ALTER TABLE detect and error out for the case where renaming a column changes a the interpretation of a double-quoted identifier in the database schema from an SQL literal to a column reference. (check-in: 5dbb0734 user: dan tags: tkt9b78184b-alt) | |
12:23 | Restore the legacy behavior of enabling double-quoted string literals in all contexts. But also provide a new compile-time option (SQLITE_DQS) to change the default to something more restrictive. (check-in: 97a94446 user: drh tags: trunk) | |
11:56 | Experimental implementation of FILTER clause for aggregate functions. (check-in: 1f1ae2d6 user: dan tags: filter-clause) | |
2019-06-28
| ||
07:08 | Use the OP_Sequence opcode for generating unique rowid values for an autoindex on a co-routine implementation of a subquery. (check-in: eab42975 user: drh tags: trunk) | |
2019-06-26
| ||
21:04 | Ensure that when an ephemeral cursor is reopened with a second invocation of to OP_OpenEphemeral, the sequence counter is reset and the cache marked as stale. Fix for [9cdc5c46]. (check-in: 5fd20e09 user: dan tags: trunk) | |
Changes to src/alter.c.
︙ | ︙ | |||
523 524 525 526 527 528 529 530 531 532 533 534 535 536 | Table *pTab; /* Table being updated */ int iCol; /* Index of column being renamed */ char *zOld = 0; /* Old column name */ char *zNew = 0; /* New column name */ const char *zDb; /* Name of schema containing the table */ int iSchema; /* Index of the schema */ int bQuote; /* True to quote the new name */ /* Locate the table to be altered */ pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_rename_column; /* Cannot alter a system table */ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column; | > > | 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 | Table *pTab; /* Table being updated */ int iCol; /* Index of column being renamed */ char *zOld = 0; /* Old column name */ char *zNew = 0; /* New column name */ const char *zDb; /* Name of schema containing the table */ int iSchema; /* Index of the schema */ int bQuote; /* True to quote the new name */ Vdbe *v; /* VDBE handle */ int regRefCnt; /* Register for number of refs to column */ /* Locate the table to be altered */ pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_rename_column; /* Cannot alter a system table */ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column; |
︙ | ︙ | |||
556 557 558 559 560 561 562 | if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break; } if( iCol==pTab->nCol ){ sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld); goto exit_rename_column; } | > > > > > > | | | < | | > | | | | | | | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 | if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break; } if( iCol==pTab->nCol ){ sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld); goto exit_rename_column; } /* Allocate a register to count the number of rewritten column refs. */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto exit_rename_column; regRefCnt = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRefCnt); /* Do the rename operation using an UPDATE statement that uses the ** sqlite_rename_column() SQL function to compute the new CREATE ** statement text for the sqlite_master table. */ sqlite3MayAbort(pParse); zNew = sqlite3NameFromToken(db, pNew); if( !zNew ) goto exit_rename_column; assert( pNew->n>0 ); bQuote = sqlite3Isquote(pNew->z[0]); sqlite3NestedParse(pParse, "UPDATE \"%w\".%s SET " "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d, %d) " "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X' " " AND (type != 'index' OR tbl_name = %Q)" " AND sql NOT LIKE 'create virtual%%'", zDb, MASTER_NAME, zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1, regRefCnt, pTab->zName ); if( iSchema!=1 ){ sqlite3NestedParse(pParse, "UPDATE temp.%s SET " "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1, %d)" "WHERE type IN ('trigger', 'view')", MASTER_NAME, zDb, pTab->zName, iCol, zNew, bQuote, regRefCnt ); } /* Drop and reload the database schema. */ renameReloadSchema(pParse, iSchema); /* Now arrange for the sqlite_rename_column() function to be called a ** second time on the already rewritten schema. This serves two purposes: ** (a) to check that the schema can still be parsed, and (b) to decrement ** register regRefCnt once for each reference to the renamed column in the ** schema (the calls above incremented regRefCnt once for each such reference ** prior to renaming). If register regRefCnt is not left set to 0, then ** renaming the column has left the schema with either more or fewer ** references to the column than there was at the beginning of the ** operation. This is an error, so return an error message and SQLITE_ABORT ** the statement. */ sqlite3NestedParse(pParse, "SELECT 1 " "FROM \"%w\".%s " "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" " AND sql NOT LIKE 'create virtual%%'" " AND (type != 'index' OR tbl_name = %Q)" " AND sqlite_rename_column(sql,type,name,%Q,%Q,%d,%Q,%d,%d,%d)=NULL", zDb, MASTER_NAME, pTab->zName, zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1, regRefCnt*-1 ); if( iSchema!=1 ){ sqlite3NestedParse(pParse, "SELECT 1 " "FROM temp.%s " "WHERE type IN ('trigger', 'view')" " AND sqlite_rename_column(sql,type,name,%Q,%Q,%d,%Q,%d,1,%d)=NULL", MASTER_NAME, zDb, pTab->zName, iCol, zNew, bQuote, regRefCnt*-1 ); } sqlite3VdbeAddOp2(v, OP_IfNot, regRefCnt, sqlite3VdbeCurrentAddr(v)+2); sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort); sqlite3VdbeChangeP4(v, -1, "schema contains ambiguous double-quoted string", P4_STATIC ); exit_rename_column: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zOld); sqlite3DbFree(db, zNew); return; } |
︙ | ︙ | |||
1221 1222 1223 1224 1225 1226 1227 | renameTokenFree(db, pParse->pRename); sqlite3ParserReset(pParse); } /* ** SQL function: ** | | > > > > > | > > > | 1267 1268 1269 1270 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 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 | renameTokenFree(db, pParse->pRename); sqlite3ParserReset(pParse); } /* ** SQL function: ** ** sqlite_rename_column(...) ** ** The function requires exactly 10 arguments: ** ** 0. zSql: SQL statement to rewrite ** 1. type: Type of object ("table", "view" etc.) ** 2. object: Name of object ** 3. Database: Database name (e.g. "main") ** 4. Table: Table name ** 5. iCol: Index of column to rename ** 6. zNew: New column name ** 7. bQuote: Non-zero if the new column name should be quoted. ** 8. bTemp: True if zSql comes from temp schema ** 9. iReg: Register to increment for each rewritten column ref. Or, ** if this parameter is negative, -1 times the id of a register ** to decrement for each rewritten column ref. ** ** Do a column rename operation on the CREATE statement given in zSql. ** The iCol-th column (left-most is 0) of table zTable is renamed from zCol ** into zNew. The name should be quoted if bQuote is true. ** ** This function is used internally by the ALTER TABLE RENAME COLUMN command. ** It is only accessible to SQL created using sqlite3NestedParse(). It is ** not reachable from ordinary SQL passed into sqlite3_prepare(). Except, ** this function is reachable for testing purposes if the ** SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control is engaged. */ static void renameColumnFunc( sqlite3_context *context, int NotUsed, sqlite3_value **argv ){ sqlite3 *db = sqlite3_context_db_handle(context); RenameCtx sCtx; const char *zSql = (const char*)sqlite3_value_text(argv[0]); const char *zDb = (const char*)sqlite3_value_text(argv[3]); const char *zTable = (const char*)sqlite3_value_text(argv[4]); int iCol = sqlite3_value_int(argv[5]); const char *zNew = (const char*)sqlite3_value_text(argv[6]); int bQuote = sqlite3_value_int(argv[7]); int bTemp = sqlite3_value_int(argv[8]); int regRefCnt = sqlite3_value_int(argv[9]); const char *zOld; int rc; Parse sParse; Walker sWalker; Index *pIdx; int i; Table *pTab; |
︙ | ︙ | |||
1363 1364 1365 1366 1367 1368 1369 | } renameColumnIdlistNames(&sParse, &sCtx, pStep->pIdList, zOld); renameColumnElistNames(&sParse, &sCtx, pStep->pExprList, zOld); } } } | < > > > > | | 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 | } renameColumnIdlistNames(&sParse, &sCtx, pStep->pIdList, zOld); renameColumnElistNames(&sParse, &sCtx, pStep->pExprList, zOld); } } } /* Find tokens to edit in UPDATE OF clause */ if( sParse.pTriggerTab==pTab ){ renameColumnIdlistNames(&sParse, &sCtx,sParse.pNewTrigger->pColumns,zOld); } /* Find tokens to edit in various expressions and selects */ renameWalkTrigger(&sWalker, sParse.pNewTrigger); } assert( rc==SQLITE_OK ); if( regRefCnt!=0 ){ int mul = (regRefCnt<0 ? -1 : 1); sqlite3VdbeIncrReg(context, regRefCnt*mul, sCtx.nList*mul); } rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote); renameColumnFunc_done: if( rc!=SQLITE_OK ){ if( sParse.zErrMsg ){ renameColumnParseError(context, regRefCnt<0, argv[1], argv[2], &sParse); }else{ sqlite3_result_error_code(context, rc); } } renameParseCleanup(&sParse); renameTokenFree(db, sCtx.pList); |
︙ | ︙ | |||
1655 1656 1657 1658 1659 1660 1661 | } /* ** Register built-in functions used to help implement ALTER TABLE */ void sqlite3AlterFunctions(void){ static FuncDef aAlterTableFuncs[] = { | | | 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 | } /* ** Register built-in functions used to help implement ALTER TABLE */ void sqlite3AlterFunctions(void){ static FuncDef aAlterTableFuncs[] = { INTERNAL_FUNCTION(sqlite_rename_column, 10, renameColumnFunc), INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc), INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest), }; sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); } #endif /* SQLITE_ALTER_TABLE */ |
Changes to src/resolve.c.
︙ | ︙ | |||
814 815 816 817 818 819 820 | NC_IdxExpr|NC_PartIdx); } if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 && pParse->nested==0 && sqlite3Config.bInternalFunctions==0 ){ /* Internal-use-only functions are disallowed unless the | | > > | 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 | NC_IdxExpr|NC_PartIdx); } if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 && pParse->nested==0 && sqlite3Config.bInternalFunctions==0 ){ /* Internal-use-only functions are disallowed unless the ** SQL is being compiled using sqlite3NestedParse(). The ** SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control will override ** this restriction for testing purposes. */ no_such_func = 1; pDef = 0; } } if( 0==IN_RENAME_OBJECT ){ #ifndef SQLITE_OMIT_WINDOWFUNC |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
279 280 281 282 283 284 285 286 287 288 289 290 291 292 | RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); #ifndef SQLITE_OMIT_TRIGGER void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); #endif int sqlite3NotPureFunc(sqlite3_context*); /* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on ** each VDBE opcode. ** ** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op ** comments in VDBE programs that show key decision points in the code ** generator. | > | 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); #ifndef SQLITE_OMIT_TRIGGER void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); #endif int sqlite3NotPureFunc(sqlite3_context*); void sqlite3VdbeIncrReg(sqlite3_context*, int, int); /* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on ** each VDBE opcode. ** ** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op ** comments in VDBE programs that show key decision points in the code ** generator. |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 | sqlite3_result_error(pCtx, "non-deterministic function in index expression or CHECK constraint", -1); return 0; } return 1; } #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored ** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored ** in memory obtained from sqlite3DbMalloc). */ | > > > > > > > > > > | 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 | sqlite3_result_error(pCtx, "non-deterministic function in index expression or CHECK constraint", -1); return 0; } return 1; } /* ** Increment the value of register iReg, which is guaranteed to be an ** integer, in the VM associated with context object pCtx by iVal. */ void sqlite3VdbeIncrReg(sqlite3_context *pCtx, int iReg, int iVal){ Mem *pMem = &pCtx->pVdbe->aMem[iReg]; assert( pMem->flags==MEM_Int ); pMem->u.i += iVal; } #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored ** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored ** in memory obtained from sqlite3DbMalloc). */ |
︙ | ︙ |
Changes to test/alter.test.
︙ | ︙ | |||
682 683 684 685 686 687 688 | #-------------------------------------------------------------------------- # alter-9.X - Special test: Make sure the sqlite_rename_column() and # rename_table() functions do not crash when handed bad input. # sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test alter-9.1 { | | | 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 | #-------------------------------------------------------------------------- # alter-9.X - Special test: Make sure the sqlite_rename_column() and # rename_table() functions do not crash when handed bad input. # sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test alter-9.1 { execsql {SELECT SQLITE_RENAME_COLUMN(0,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 { |
︙ | ︙ |
Changes to test/alterauth2.test.
︙ | ︙ | |||
78 79 80 81 82 83 84 | do_auth_test 1.2 { ALTER TABLE t2 RENAME a TO aaa; } { {SQLITE_ALTER_TABLE main t2 {} {}} {SQLITE_FUNCTION {} like {} {}} {SQLITE_FUNCTION {} sqlite_rename_column {} {}} | < | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | do_auth_test 1.2 { ALTER TABLE t2 RENAME a TO aaa; } { {SQLITE_ALTER_TABLE main t2 {} {}} {SQLITE_FUNCTION {} like {} {}} {SQLITE_FUNCTION {} sqlite_rename_column {} {}} {SQLITE_READ sqlite_master name main {}} {SQLITE_READ sqlite_master sql main {}} {SQLITE_READ sqlite_master tbl_name main {}} {SQLITE_READ sqlite_master type main {}} {SQLITE_READ sqlite_temp_master name temp {}} {SQLITE_READ sqlite_temp_master sql temp {}} {SQLITE_READ sqlite_temp_master type temp {}} |
︙ | ︙ |
Changes to test/altercol.test.
︙ | ︙ | |||
634 635 636 637 638 639 640 | 'CREATE TABLE x1(i INTEGER, t TEXT)', 'table', 'x1', 'main', 'ddd', -1, 'zzz', 0 ); } {} do_execsql_test 14.2 { SELECT | | | | 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 | 'CREATE TABLE x1(i INTEGER, t TEXT)', 'table', 'x1', 'main', 'ddd', -1, 'zzz', 0 ); } {} do_execsql_test 14.2 { SELECT sqlite_rename_column(sql, type, object, db, tbl, icol, znew, bquote, 0, 0) FROM ddd; } {{} {} {} {}} sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 # If the INTERNAL_FUNCTIONS test-control is disabled (which is the default) # then the sqlite_rename_table() SQL function is not accessible to # ordinary SQL. # do_catchsql_test 14.3 { SELECT sqlite_rename_column(0,0,0,0,0,0,0,0,0,0); } {1 {no such function: sqlite_rename_column}} #------------------------------------------------------------------------- # reset_db do_execsql_test 15.0 { CREATE TABLE xxx(a, b, c); |
︙ | ︙ |
Added test/altercol2.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 | # 2019 July 3 # # 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. # #************************************************************************* # This file implements regression tests for SQLite library. The # focus of this script is testing that SQLite can handle a subtle # file format change that may be used in the future to implement # "ALTER TABLE ... RENAME COLUMN ... TO". # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix altercol2 # If SQLITE_OMIT_ALTERTABLE is defined, omit this file. ifcapable !altertable { finish_test return } sqlite3_db_config db DQS_DDL 1 #------------------------------------------------------------------------- # Check that the ALTER TABLE statement used in bug [9b78184b] is now # an error (because it effectively transforms a constant string into a # column ref). # do_execsql_test 1.0 { CREATE TABLE t0(c1, c2); INSERT INTO t0(c1, c2) VALUES ('a', 1); CREATE INDEX i0 ON t0("C3"); } do_catchsql_test 1.1 { ALTER TABLE t0 RENAME COLUMN c1 TO c3; } {1 {schema contains ambiguous double-quoted string}} do_execsql_test 1.2 { ALTER TABLE t0 RENAME COLUMN c1 TO c4; SELECT DISTINCT * FROM t0; } {a 1} finish_test |