Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch as-materialize Excluding Merge-Ins
This is equivalent to a diff from 78dcddd969 to 7a90571e0a
2021-02-20
| ||
12:47 | Merge changes from trunk. (Later:) Abandon this line of development. See the as-materialize-redux branch. (Closed-Leaf check-in: 7a90571e0a user: drh tags: as-materialize) | |
2021-02-19
| ||
18:39 | Fix another problem handling corrupt database files in the ALTER TABLE DROP COLUMN code. (check-in: 9edf2ddc47 user: dan tags: trunk) | |
2021-02-16
| ||
19:29 | Remove unnecessarily complexity from sqlite3WithReleaseByParse(). Improved TreeView output for the enhanced CTE structures. This code still does not work 100%. I'm saving my place in order to (maybe) come back to it later. (check-in: 30bb18b450 user: drh tags: as-materialize) | |
16:32 | Trying to get the new AS MATERIALIZE syntax of CTEs to work. There are still performance and memory management issues. This is a WIP check-in. (check-in: bf0fd9b23a user: drh tags: as-materialize) | |
00:48 | Change the syntax from "GENERATED AS" to "AS MATERIALIZED" so as to match the syntax of PostgreSQL 12+. (Closed-Leaf check-in: 78dcddd969 user: drh tags: with-generated-as) | |
2021-02-15
| ||
17:51 | Merge the LIKE operator fix from trunk. (check-in: 8c8618780a user: drh tags: with-generated-as) | |
Changes to ext/session/sessionwor.test.
︙ | ︙ | |||
65 66 67 68 69 70 71 | foreach {tn wo} { 1 "" 2 "WITHOUT ROWID" } { reset_db | | > > | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | foreach {tn wo} { 1 "" 2 "WITHOUT ROWID" } { reset_db do_execsql_test 2.$tn.0.1 "CREATE TABLE t1(a INTEGER PRIMARY KEY, b) $wo ;" do_execsql_test 2.$tn.0.2 "CREATE TABLE t2(a INTEGER PRIMARY KEY, b) $wo ;" do_execsql_test 2.$tn.0.3 "CREATE TABLE t3(a INTEGER PRIMARY KEY, b) $wo ;" do_iterator_test 1.1 t1 { INSERT INTO t1 VALUES(1, 'two'); } { {INSERT t1 0 X. {} {i 1 t two}} } |
︙ | ︙ | |||
90 91 92 93 94 95 96 97 98 99 100 | } do_iterator_test 2.$tn.4 t1 { DELETE FROM t1; } { {DELETE t1 0 X. {i 1 t four} {}} } } finish_test | > > > > > > > > > > > > > > > > > > > > > | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | } do_iterator_test 2.$tn.4 t1 { DELETE FROM t1; } { {DELETE t1 0 X. {i 1 t four} {}} } do_execsql_test 2.$tn.5 { INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); INSERT INTO t1 VALUES(3, 'three'); } do_iterator_test 2.$tn.6 t2 { INSERT INTO t2 SELECT a, b FROM t1 } { {INSERT t2 0 X. {} {i 1 t one}} {INSERT t2 0 X. {} {i 2 t two}} {INSERT t2 0 X. {} {i 3 t three}} } do_iterator_test 2.$tn.7 t3 { INSERT INTO t3 SELECT * FROM t1 } { {INSERT t3 0 X. {} {i 1 t one}} {INSERT t3 0 X. {} {i 2 t two}} {INSERT t3 0 X. {} {i 3 t three}} } } finish_test |
Changes to src/alter.c.
︙ | ︙ | |||
45 46 47 48 49 50 51 | /* ** 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. */ | | > > > > > | | | | | | | | 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 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | /* ** 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. */ static void renameTestSchema( Parse *pParse, /* Parse context */ const char *zDb, /* Name of db to verify schema of */ int bTemp, /* True if this is the temp db */ const char *zWhen /* "when" part of error message */ ){ pParse->colNamesSet = 1; sqlite3NestedParse(pParse, "SELECT 1 " "FROM \"%w\"." DFLT_SCHEMA_TABLE " " "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" " AND sql NOT LIKE 'create virtual%%'" " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q)=NULL ", zDb, zDb, bTemp, zWhen ); if( bTemp==0 ){ sqlite3NestedParse(pParse, "SELECT 1 " "FROM temp." DFLT_SCHEMA_TABLE " " "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" " AND sql NOT LIKE 'create virtual%%'" " AND sqlite_rename_test(%Q, sql, type, name, 1, %Q)=NULL ", zDb, zWhen ); } } /* ** Generate code to reload the schema for database iDb. And, if iDb!=1, for ** the temp database as well. */ static void renameReloadSchema(Parse *pParse, int iDb, u16 p5){ Vdbe *v = pParse->pVdbe; if( v ){ sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0, p5); if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0, p5); } } /* ** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" ** command. */ |
︙ | ︙ | |||
227 228 229 230 231 232 233 | ** as required. */ if( iDb!=1 ){ sqlite3NestedParse(pParse, "UPDATE sqlite_temp_schema SET " "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), " "tbl_name = " "CASE WHEN tbl_name=%Q COLLATE nocase AND " | | | | | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 | ** as required. */ if( iDb!=1 ){ sqlite3NestedParse(pParse, "UPDATE sqlite_temp_schema 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, 'after rename') " "THEN %Q ELSE tbl_name END " "WHERE type IN ('view', 'trigger')" , zDb, zTabName, zName, zTabName, zDb, zName); } /* 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 if( pVTab ){ int i = ++pParse->nMem; sqlite3VdbeLoadString(v, i, zName); sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); } #endif renameReloadSchema(pParse, iDb, INITFLAG_AlterRename); renameTestSchema(pParse, zDb, iDb==1, "after rename"); exit_rename_table: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zName); db->mDbFlags = savedDbFlags; } |
︙ | ︙ | |||
409 410 411 412 413 414 415 | 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 */ | | | 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 | 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, INITFLAG_AlterRename); } /* ** 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. ** |
︙ | ︙ | |||
509 510 511 512 513 514 515 | ** command. This function checks if the table is a view or virtual ** table (columns of views or virtual tables may not be renamed). If so, ** it loads an error message into pParse and returns non-zero. ** ** Or, if pTab is not a view or virtual table, zero is returned. */ #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) | | | > | | | 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 | ** command. This function checks if the table is a view or virtual ** table (columns of views or virtual tables may not be renamed). If so, ** it loads an error message into pParse and returns non-zero. ** ** Or, if pTab is not a view or virtual table, zero is returned. */ #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) static int isRealTable(Parse *pParse, Table *pTab, int bDrop){ const char *zType = 0; #ifndef SQLITE_OMIT_VIEW if( pTab->pSelect ){ zType = "view"; } #endif #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ zType = "virtual table"; } #endif if( zType ){ sqlite3ErrorMsg(pParse, "cannot %s %s \"%s\"", (bDrop ? "drop column from" : "rename columns of"), zType, pTab->zName ); return 1; } return 0; } #else /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ # define isRealTable(x,y,z) (0) #endif /* ** Handles the following parser reduction: ** ** cmd ::= ALTER TABLE pSrc RENAME COLUMN pOld TO pNew */ |
︙ | ︙ | |||
559 560 561 562 563 564 565 | /* 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; | | | 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 | /* 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; if( SQLITE_OK!=isRealTable(pParse, pTab, 0) ) goto exit_rename_column; /* Which schema holds the table to be altered */ iSchema = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iSchema>=0 ); zDb = db->aDb[iSchema].zDbSName; #ifndef SQLITE_OMIT_AUTHORIZATION |
︙ | ︙ | |||
613 614 615 616 617 618 619 | "UPDATE temp." DFLT_SCHEMA_TABLE " SET " "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) " "WHERE type IN ('trigger', 'view')", zDb, pTab->zName, iCol, zNew, bQuote ); /* Drop and reload the database schema. */ | | | | 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 | "UPDATE temp." DFLT_SCHEMA_TABLE " SET " "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) " "WHERE type IN ('trigger', 'view')", zDb, pTab->zName, iCol, zNew, bQuote ); /* Drop and reload the database schema. */ renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename); renameTestSchema(pParse, zDb, iSchema==1, "after rename"); exit_rename_column: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zOld); sqlite3DbFree(db, zNew); return; } |
︙ | ︙ | |||
866 867 868 869 870 871 872 | pNext = p->pNext; sqlite3DbFree(db, p); } } /* ** Search the Parse object passed as the first argument for a RenameToken | | > > > | | > > | > > > | | | | > | > | 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | pNext = p->pNext; sqlite3DbFree(db, p); } } /* ** Search the Parse object passed as the first argument for a RenameToken ** object associated with parse tree element pPtr. If found, return a pointer ** to it. Otherwise, return NULL. ** ** If the second argument passed to this function is not NULL and a matching ** RenameToken object is found, remove it from the Parse object and add it to ** the list maintained by the RenameCtx object. */ static RenameToken *renameTokenFind( Parse *pParse, struct RenameCtx *pCtx, void *pPtr ){ RenameToken **pp; assert( pPtr!=0 ); for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){ if( (*pp)->p==pPtr ){ RenameToken *pToken = *pp; if( pCtx ){ *pp = pToken->pNext; pToken->pNext = pCtx->pList; pCtx->pList = pToken; pCtx->nList++; } return pToken; } } return 0; } /* ** This is a Walker select callback. It does nothing. It is only required ** because without a dummy callback, sqlite3WalkExpr() and similar do not ** descend into sub-select statements. */ |
︙ | ︙ | |||
953 954 955 956 957 958 959 | ** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an ** ALTER TABLE RENAME COLUMN program. The error message emitted by the ** sub-routine is currently stored in pParse->zErrMsg. This function ** adds context to the error message and then stores it in pCtx. */ static void renameColumnParseError( sqlite3_context *pCtx, | | | | | 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 | ** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an ** ALTER TABLE RENAME COLUMN program. The error message emitted by the ** sub-routine is currently stored in pParse->zErrMsg. This function ** adds context to the error message and then stores it in pCtx. */ static void renameColumnParseError( sqlite3_context *pCtx, const char *zWhen, sqlite3_value *pType, sqlite3_value *pObject, Parse *pParse ){ const char *zT = (const char*)sqlite3_value_text(pType); const char *zN = (const char*)sqlite3_value_text(pObject); char *zErr; zErr = sqlite3_mprintf("error in %s %s%s%s: %s", zT, zN, (zWhen[0] ? " " : ""), zWhen, pParse->zErrMsg ); sqlite3_result_error(pCtx, zErr, -1); sqlite3_free(zErr); } /* |
︙ | ︙ | |||
1042 1043 1044 1045 1046 1047 1048 | /* Parse the SQL statement passed as the first argument. If no error ** occurs and the parse does not result in a new table, index or ** trigger object, the database must be corrupt. */ memset(p, 0, sizeof(Parse)); p->eParseMode = PARSE_MODE_RENAME; p->db = db; p->nQueryLoop = 1; | | | 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 | /* Parse the SQL statement passed as the first argument. If no error ** occurs and the parse does not result in a new table, index or ** trigger object, the database must be corrupt. */ memset(p, 0, sizeof(Parse)); p->eParseMode = PARSE_MODE_RENAME; p->db = db; p->nQueryLoop = 1; rc = zSql ? sqlite3RunParser(p, zSql, &zErr) : SQLITE_NOMEM; assert( p->zErrMsg==0 ); assert( rc!=SQLITE_OK || zErr==0 ); p->zErrMsg = zErr; if( db->mallocFailed ) rc = SQLITE_NOMEM; if( rc==SQLITE_OK && p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0 ){ |
︙ | ︙ | |||
1469 1470 1471 1472 1473 1474 1475 | assert( rc==SQLITE_OK ); rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote); renameColumnFunc_done: if( rc!=SQLITE_OK ){ if( sParse.zErrMsg ){ | | | 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 | assert( rc==SQLITE_OK ); rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote); renameColumnFunc_done: if( rc!=SQLITE_OK ){ if( sParse.zErrMsg ){ renameColumnParseError(context, "", argv[1], argv[2], &sParse); }else{ sqlite3_result_error_code(context, rc); } } renameParseCleanup(&sParse); renameTokenFree(db, sCtx.pList); |
︙ | ︙ | |||
1658 1659 1660 1661 1662 1663 1664 | } if( rc==SQLITE_OK ){ rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote); } if( rc!=SQLITE_OK ){ if( sParse.zErrMsg ){ | | | 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 | } if( rc==SQLITE_OK ){ rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote); } if( rc!=SQLITE_OK ){ if( sParse.zErrMsg ){ renameColumnParseError(context, "", argv[1], argv[2], &sParse); }else{ sqlite3_result_error_code(context, rc); } } renameParseCleanup(&sParse); renameTokenFree(db, sCtx.pList); |
︙ | ︙ | |||
1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 | ** 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); char const *zDb = (const char*)sqlite3_value_text(argv[0]); char const *zInput = (const char*)sqlite3_value_text(argv[1]); int bTemp = sqlite3_value_int(argv[4]); int isLegacy = (db->flags & SQLITE_LegacyAlter); #ifndef SQLITE_OMIT_AUTHORIZATION sqlite3_xauth xAuth = db->xAuth; db->xAuth = 0; #endif UNUSED_PARAMETER(NotUsed); | > > | 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 | ** 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. ** 5: "when" part of error message. ** ** 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); char const *zDb = (const char*)sqlite3_value_text(argv[0]); char const *zInput = (const char*)sqlite3_value_text(argv[1]); int bTemp = sqlite3_value_int(argv[4]); int isLegacy = (db->flags & SQLITE_LegacyAlter); char const *zWhen = (const char*)sqlite3_value_text(argv[5]); #ifndef SQLITE_OMIT_AUTHORIZATION sqlite3_xauth xAuth = db->xAuth; db->xAuth = 0; #endif UNUSED_PARAMETER(NotUsed); |
︙ | ︙ | |||
1736 1737 1738 1739 1740 1741 1742 | int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema); int i2 = sqlite3FindDbName(db, zDb); if( i1==i2 ) sqlite3_result_int(context, 1); } } } | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > | 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 | int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema); int i2 = sqlite3FindDbName(db, zDb); if( i1==i2 ) sqlite3_result_int(context, 1); } } } if( rc!=SQLITE_OK && zWhen ){ renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse); } renameParseCleanup(&sParse); } #ifndef SQLITE_OMIT_AUTHORIZATION db->xAuth = xAuth; #endif } /* ** The implementation of internal UDF sqlite_drop_column(). ** ** Arguments: ** ** argv[0]: An integer - the index of the schema containing the table ** argv[1]: CREATE TABLE statement to modify. ** argv[2]: An integer - the index of the column to remove. ** ** The value returned is a string containing the CREATE TABLE statement ** with column argv[2] removed. */ static void dropColumnFunc( sqlite3_context *context, int NotUsed, sqlite3_value **argv ){ sqlite3 *db = sqlite3_context_db_handle(context); int iSchema = sqlite3_value_int(argv[0]); const char *zSql = (const char*)sqlite3_value_text(argv[1]); int iCol = sqlite3_value_int(argv[2]); const char *zDb = db->aDb[iSchema].zDbSName; int rc; Parse sParse; RenameToken *pCol; Table *pTab; const char *zEnd; char *zNew = 0; #ifndef SQLITE_OMIT_AUTHORIZATION sqlite3_xauth xAuth = db->xAuth; db->xAuth = 0; #endif rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1); if( rc!=SQLITE_OK ) goto drop_column_done; pTab = sParse.pNewTable; if( pTab->nCol==1 || iCol>=pTab->nCol ){ /* This can happen if the sqlite_schema table is corrupt */ rc = SQLITE_CORRUPT_BKPT; goto drop_column_done; } pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zName); if( iCol<pTab->nCol-1 ){ RenameToken *pEnd; pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zName); zEnd = (const char*)pEnd->t.z; }else{ zEnd = (const char*)&zSql[pTab->addColOffset]; while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--; } zNew = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd); sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT); sqlite3_free(zNew); drop_column_done: renameParseCleanup(&sParse); #ifndef SQLITE_OMIT_AUTHORIZATION db->xAuth = xAuth; #endif if( rc!=SQLITE_OK ){ sqlite3_result_error_code(context, rc); } } /* ** This function is called by the parser upon parsing an ** ** ALTER TABLE pSrc DROP COLUMN pName ** ** statement. Argument pSrc contains the possibly qualified name of the ** table being edited, and token pName the name of the column to drop. */ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, Token *pName){ sqlite3 *db = pParse->db; /* Database handle */ Table *pTab; /* Table to modify */ int iDb; /* Index of db containing pTab in aDb[] */ const char *zDb; /* Database containing pTab ("main" etc.) */ char *zCol = 0; /* Name of column to drop */ int iCol; /* Index of column zCol in pTab->aCol[] */ /* Look up the table being altered. */ assert( pParse->pNewTable==0 ); assert( sqlite3BtreeHoldsAllMutexes(db) ); if( NEVER(db->mallocFailed) ) goto exit_drop_column; pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_drop_column; /* Make sure this is not an attempt to ALTER a view, virtual table or ** system table. */ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_drop_column; if( SQLITE_OK!=isRealTable(pParse, pTab, 1) ) goto exit_drop_column; /* Find the index of the column being dropped. */ zCol = sqlite3NameFromToken(db, pName); if( zCol==0 ){ assert( db->mallocFailed ); goto exit_drop_column; } iCol = sqlite3ColumnIndex(pTab, zCol); if( iCol<0 ){ sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zCol); goto exit_drop_column; } /* Do not allow the user to drop a PRIMARY KEY column or a column ** constrained by a UNIQUE constraint. */ if( pTab->aCol[iCol].colFlags & (COLFLAG_PRIMKEY|COLFLAG_UNIQUE) ){ sqlite3ErrorMsg(pParse, "cannot drop %s column: \"%s\"", (pTab->aCol[iCol].colFlags&COLFLAG_PRIMKEY) ? "PRIMARY KEY" : "UNIQUE", zCol ); goto exit_drop_column; } /* Do not allow the number of columns to go to zero */ if( pTab->nCol<=1 ){ sqlite3ErrorMsg(pParse, "cannot drop column \"%s\": no other columns exist",zCol); goto exit_drop_column; } /* Edit the sqlite_schema table */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb>=0 ); zDb = db->aDb[iDb].zDbSName; renameTestSchema(pParse, zDb, iDb==1, ""); sqlite3NestedParse(pParse, "UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET " "sql = sqlite_drop_column(%d, sql, %d) " "WHERE (type=='table' AND tbl_name=%Q COLLATE nocase)" , zDb, iDb, iCol, pTab->zName ); /* Drop and reload the database schema. */ renameReloadSchema(pParse, iDb, INITFLAG_AlterDrop); renameTestSchema(pParse, zDb, iDb==1, "after drop column"); /* Edit rows of table on disk */ if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){ int i; int addr; int reg; int regRec; Index *pPk = 0; int nField = 0; /* Number of non-virtual columns after drop */ int iCur; Vdbe *v = sqlite3GetVdbe(pParse); iCur = pParse->nTab++; sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite); addr = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); reg = ++pParse->nMem; pParse->nMem += pTab->nCol; if( HasRowid(pTab) ){ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, reg); }else{ pPk = sqlite3PrimaryKeyIndex(pTab); } for(i=0; i<pTab->nCol; i++){ if( i!=iCol && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){ int regOut; if( pPk ){ int iPos = sqlite3TableColumnToIndex(pPk, i); int iColPos = sqlite3TableColumnToIndex(pPk, iCol); regOut = reg+1+iPos-(iPos>iColPos); }else{ regOut = reg+1+nField; } sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut); nField++; } } regRec = reg + pTab->nCol; sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec); if( pPk ){ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol); }else{ sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg); } sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr); } exit_drop_column: sqlite3DbFree(db, zCol); sqlite3SrcListDelete(db, pSrc); } /* ** Register built-in functions used to help implement ALTER TABLE */ void sqlite3AlterFunctions(void){ static FuncDef aAlterTableFuncs[] = { INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc), INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc), INTERNAL_FUNCTION(sqlite_rename_test, 6, renameTableTest), INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc), }; sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); } #endif /* SQLITE_ALTER_TABLE */ |
Changes to src/build.c.
︙ | ︙ | |||
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | Returning *pReturning = pParse->u1.pReturning; int addrRewind; int i; int reg; addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur); reg = pReturning->iRetReg; for(i=0; i<pReturning->nRetCol; i++){ sqlite3VdbeAddOp3(v, OP_Column, pReturning->iRetCur, i, reg+i); } sqlite3VdbeAddOp2(v, OP_ResultRow, reg, i); sqlite3VdbeAddOp2(v, OP_Next, pReturning->iRetCur, addrRewind+1); sqlite3VdbeJumpHere(v, addrRewind); } sqlite3VdbeAddOp0(v, OP_Halt); #if SQLITE_USER_AUTHENTICATION if( pParse->nTableLock>0 && db->init.busy==0 ){ sqlite3UserAuthInit(db); | > > | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | Returning *pReturning = pParse->u1.pReturning; int addrRewind; int i; int reg; addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur); VdbeCoverage(v); reg = pReturning->iRetReg; for(i=0; i<pReturning->nRetCol; i++){ sqlite3VdbeAddOp3(v, OP_Column, pReturning->iRetCur, i, reg+i); } sqlite3VdbeAddOp2(v, OP_ResultRow, reg, i); sqlite3VdbeAddOp2(v, OP_Next, pReturning->iRetCur, addrRewind+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrRewind); } sqlite3VdbeAddOp0(v, OP_Halt); #if SQLITE_USER_AUTHENTICATION if( pParse->nTableLock>0 && db->init.busy==0 ){ sqlite3UserAuthInit(db); |
︙ | ︙ | |||
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 | /* Set properties of a table column based on the (magical) ** name of the column. */ #if SQLITE_ENABLE_HIDDEN_COLUMNS void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){ if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){ pCol->colFlags |= COLFLAG_HIDDEN; }else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){ pTab->tabFlags |= TF_OOOHidden; } } #endif /* | > | 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 | /* Set properties of a table column based on the (magical) ** name of the column. */ #if SQLITE_ENABLE_HIDDEN_COLUMNS void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){ if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){ pCol->colFlags |= COLFLAG_HIDDEN; if( pTab ) pTab->tabFlags |= TF_HasHidden; }else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){ pTab->tabFlags |= TF_OOOHidden; } } #endif /* |
︙ | ︙ | |||
2634 2635 2636 2637 2638 2639 2640 | ); } } #endif /* Reparse everything to update our internal data structures */ sqlite3VdbeAddParseSchemaOp(v, iDb, | | | > | < < | | | | < | | < | 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 | ); } } #endif /* Reparse everything to update our internal data structures */ sqlite3VdbeAddParseSchemaOp(v, iDb, sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName),0); } /* Add the table to the in-memory representation of the database. */ if( db->init.busy ){ Table *pOld; Schema *pSchema = p->pSchema; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p); if( pOld ){ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ sqlite3OomFault(db); return; } pParse->pNewTable = 0; db->mDbFlags |= DBFLAG_SchemaChange; } #ifndef SQLITE_OMIT_ALTERTABLE if( !pSelect && !p->pSelect ){ assert( pCons && pEnd ); if( pCons->z==0 ){ pCons = pEnd; } p->addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z); } #endif } #ifndef SQLITE_OMIT_VIEW /* ** The parser calls this routine in order to create a new VIEW */ void sqlite3CreateView( |
︙ | ︙ | |||
4122 4123 4124 4125 4126 4127 4128 | /* Fill the index with data and reparse the schema. Code an OP_Expire ** to invalidate all pre-compiled statements. */ if( pTblName ){ sqlite3RefillIndex(pParse, pIndex, iMem); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(v, iDb, | | | 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 | /* Fill the index with data and reparse the schema. Code an OP_Expire ** to invalidate all pre-compiled statements. */ if( pTblName ){ sqlite3RefillIndex(pParse, pIndex, iMem); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(v, iDb, sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName), 0); sqlite3VdbeAddOp2(v, OP_Expire, 0, 1); } sqlite3VdbeJumpHere(v, (int)pIndex->tnum); } } if( db->init.busy || pTblName==0 ){ |
︙ | ︙ | |||
5208 5209 5210 5211 5212 5213 5214 | ** Create a new CTE object */ Cte *sqlite3CteNew( Parse *pParse, /* Parsing context */ Token *pName, /* Name of the common-table */ ExprList *pArglist, /* Optional column name list for the table */ Select *pQuery, /* Query used to initialize the table */ | | | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < | | > > > > > > > > > | 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 | ** Create a new CTE object */ Cte *sqlite3CteNew( Parse *pParse, /* Parsing context */ Token *pName, /* Name of the common-table */ ExprList *pArglist, /* Optional column name list for the table */ Select *pQuery, /* Query used to initialize the table */ int eMaterialize /* Force or prohibit materialization */ ){ Cte *pNew; sqlite3 *db = pParse->db; assert( eMaterialize==Materialize_Any || eMaterialize==Materialize_Yes || eMaterialize==Materialize_No ); pNew = sqlite3DbMallocZero(db, sizeof(*pNew)); assert( pNew!=0 || db->mallocFailed ); if( db->mallocFailed ){ sqlite3ExprListDelete(db, pArglist); sqlite3SelectDelete(db, pQuery); }else{ pNew->pSelect = pQuery; pNew->pCols = pArglist; pNew->zName = sqlite3NameFromToken(pParse->db, pName); pNew->zCteErr = 0; pNew->eMaterialize = (u8)eMaterialize; } return pNew; } #ifdef SQLITE_DEBUG /* ** Validate the back-reference from a SrcList_item back to its Cte object. ** Raise an assertion fault if anything is wrong. This routine is for ** sanity and design checking and does not appear in release builds. */ void sqlite3AssertValidCteBackRef(struct SrcList_item *pItem){ Cte *pCte; if( !pItem->fg.isCte ) return; /* Nothing to check here */ assert( pItem->pSelect!=0 ); pCte = pItem->u2.pCteSrc; if( pCte==0 ) return; assert( pCte->eCteMagic==CTE_MAGIC ); assert( pItem->pTab!=0 ); assert( sqlite3_stricmp(pCte->zName, pItem->pTab->zName)==0 ); assert( pCte->nRefCte>=1 ); } #endif /* SQLITE_DEBUG */ /* ** Clear information from a Cte object, but do not deallocate storage. */ static void cteClear(sqlite3 *db, Cte *pCte){ sqlite3ExprListDelete(db, pCte->pCols); sqlite3SelectDelete(db, pCte->pSelect); sqlite3DbFree(db, pCte->zName); #ifdef SQLITE_DEBUG if( db==0 || db->pnBytesFreed==0 ){ pCte->zName = 0; pCte->eCteMagic = 0; } #endif } /* ** Free the contents of the CTE object passed as the second argument. */ void sqlite3CteDelete(sqlite3 *db, Cte *pCte){ if( pCte ){ cteClear(db, pCte); sqlite3DbFree(db, pCte); } } /* ** This routine is invoked once per CTE by the parser while parsing a ** WITH clause. Construct a new Cte object and append it to the ** input With object, reallocating the With object as needed. If the ** pWith input is NULL, then create a new With object. ** ** The returned With object is unowned. The caller needs to assign ** ownership. Note, however, that ownership should not be assigned ** until the object stops growing. The input pWith parameter must be ** either NULL or a pointer to an unowned With object. */ With *sqlite3WithAdd( Parse *pParse, /* Parsing context */ With *pWith, /* Existing WITH clause, or NULL */ Cte *pCte /* The CTE to add to the WITH clause */ ){ sqlite3 *db = pParse->db; With *pNew; char *zName; /* The input WITH clause is yet unowned */ assert( pWith==0 || pWith->mOwner==0 ); if( pCte==0 ){ return pWith; } /* Check that the CTE name is unique within this WITH clause. If ** not, store an error in the Parse structure. */ |
︙ | ︙ | |||
5293 5294 5295 5296 5297 5298 5299 5300 5301 | pNew->nCte++; } return pNew; } /* ** Free the contents of the With object passed as the second argument. */ void sqlite3WithDelete(sqlite3 *db, With *pWith){ | > > > > > < | | | < < > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 | pNew->nCte++; } return pNew; } /* ** Free the contents of the With object passed as the second argument. ** ** The sqlite3WithReleaseBySelect() causes the Select-object ownership ** to be released, and sqlite3WithReleaseByParse() causes the Parse-object ** ownership to be released. The With object is only deallocated after ** both owners release it. */ void sqlite3WithDelete(sqlite3 *db, With *pWith){ int i; for(i=0; i<pWith->nCte; i++){ cteClear(db, &pWith->a[i]); } sqlite3DbFree(db, pWith); } void sqlite3WithReleaseBySelect(sqlite3 *db, With *pWith){ if( pWith==0 ) return; if( db && db->pnBytesFreed ){ if( pWith->mOwner==WithOwnedBySelect ) sqlite3WithDelete(db, pWith); }else{ pWith->mOwner &= ~WithOwnedBySelect; if( pWith->mOwner==0 ) sqlite3WithDelete(db, pWith); } } void sqlite3WithReleaseByParse(sqlite3 *db, With *pWith){ if( pWith==0 ) return; assert( db==0 || db->pnBytesFreed==0 ); pWith->mOwner &= ~WithOwnedByParse; if( pWith->mOwner==0 ) sqlite3WithDelete(db, pWith); } /* ** Add Select-object or Parse-object ownership to a With object. If ** the With object is already owned appropriately, then these routines ** are no-ops. ** ** The first time that a With becomes owned by a Parse-object, make ** arrangements to automatically release the ownership when the Parse ** object is destroyed using a call to sqlite3ParserAddCleanup(). ** This involves a memory allocation. If that memory allocation fails, ** the With object might be destroyed immediately. In that ** case, return a NULL pointer. But usually, return a copy of the pWith ** pointer. */ void sqlite3WithClaimedBySelect(With *pWith){ pWith->mOwner |= WithOwnedBySelect; } With *sqlite3WithClaimedByParse(Parse *pParse, With *pWith){ if( (pWith->mOwner & WithOwnedByParse)==0 ){ pWith->mOwner |= WithOwnedByParse; pWith = (With*)sqlite3ParserAddCleanup(pParse, (void(*)(sqlite3*,void*))sqlite3WithReleaseByParse, (void*)pWith); } return pWith; } #endif /* !defined(SQLITE_OMIT_CTE) */ |
Changes to src/delete.c.
︙ | ︙ | |||
205 206 207 208 209 210 211 | } /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree ** and the SELECT subtree. */ pSrc->a[0].pTab = 0; pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0); pSrc->a[0].pTab = pTab; | | | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | } /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree ** and the SELECT subtree. */ pSrc->a[0].pTab = 0; pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0); pSrc->a[0].pTab = pTab; pSrc->a[0].u2.pIBIndex = 0; assert( !pSrc->a[0].fg.isCte ); /* generate the SELECT expression tree. */ pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0, pOrderBy,0,pLimit ); /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 | With *pRet = 0; if( p ){ sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1); pRet = sqlite3DbMallocZero(db, nByte); if( pRet ){ int i; pRet->nCte = p->nCte; for(i=0; i<p->nCte; i++){ pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0); pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0); pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName); } } } | > | 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 | With *pRet = 0; if( p ){ sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1); pRet = sqlite3DbMallocZero(db, nByte); if( pRet ){ int i; pRet->nCte = p->nCte; pRet->mOwner = WithOwnedBySelect; for(i=0; i<p->nCte; i++){ pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0); pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0); pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName); } } } |
︙ | ︙ | |||
1540 1541 1542 1543 1544 1545 1546 | pNewItem->fg = pOldItem->fg; pNewItem->iCursor = pOldItem->iCursor; pNewItem->addrFillSub = pOldItem->addrFillSub; pNewItem->regReturn = pOldItem->regReturn; if( pNewItem->fg.isIndexedBy ){ pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy); } | | | 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 | pNewItem->fg = pOldItem->fg; pNewItem->iCursor = pOldItem->iCursor; pNewItem->addrFillSub = pOldItem->addrFillSub; pNewItem->regReturn = pOldItem->regReturn; if( pNewItem->fg.isIndexedBy ){ pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy); } pNewItem->u2 = pOldItem->u2; if( pNewItem->fg.isTabFunc ){ pNewItem->u1.pFuncArg = sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags); } pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ pTab->nTabRef++; |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
926 927 928 929 930 931 932 | testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ); testcase( pTab->aCol[i].colFlags & COLFLAG_STORED ); ipkColumn--; } } } #endif | | < | | | > > > > | | | > | | | | | > | 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 | testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ); testcase( pTab->aCol[i].colFlags & COLFLAG_STORED ); ipkColumn--; } } } #endif /* Make sure the number of columns in the source data matches the number ** of columns to be inserted into the table. */ assert( TF_HasHidden==COLFLAG_HIDDEN ); assert( TF_HasGenerated==COLFLAG_GENERATED ); assert( COLFLAG_NOINSERT==(COLFLAG_GENERATED|COLFLAG_HIDDEN) ); if( (pTab->tabFlags & (TF_HasGenerated|TF_HasHidden))!=0 ){ for(i=0; i<pTab->nCol; i++){ if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++; } } if( nColumn!=(pTab->nCol-nHidden) ){ sqlite3ErrorMsg(pParse, "table %S has %d columns but %d values were supplied", pTabList, 0, pTab->nCol-nHidden, nColumn); goto insert_cleanup; } } if( pColumn!=0 && nColumn!=pColumn->nId ){ sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); goto insert_cleanup; } /* Initialize the count of rows to be inserted |
︙ | ︙ | |||
2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 | if( pTab->aCol[i].pDflt!=0 ) break; if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break; } sqlite3VdbeChangeP5(v, i+1); } #endif /* ** This routine generates code to finish the INSERT or UPDATE operation ** that was started by a prior call to sqlite3GenerateConstraintChecks. ** A consecutive range of registers starting at regNewData contains the ** rowid and the content to be inserted. ** ** The arguments to this routine should be the same as the first six | > > > > > > > > > > > > > > > > > > > > > > > > > > | 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 | if( pTab->aCol[i].pDflt!=0 ) break; if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break; } sqlite3VdbeChangeP5(v, i+1); } #endif /* ** Table pTab is a WITHOUT ROWID table that is being written to. The cursor ** number is iCur, and register regData contains the new record for the ** PK index. This function adds code to invoke the pre-update hook, ** if one is registered. */ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK static void codeWithoutRowidPreupdate( Parse *pParse, /* Parse context */ Table *pTab, /* Table being updated */ int iCur, /* Cursor number for table */ int regData /* Data containing new record */ ){ Vdbe *v = pParse->pVdbe; int r = sqlite3GetTempReg(pParse); assert( !HasRowid(pTab) ); assert( 0==(pParse->db->mDbFlags & DBFLAG_Vacuum) ); sqlite3VdbeAddOp2(v, OP_Integer, 0, r); sqlite3VdbeAddOp4(v, OP_Insert, iCur, regData, r, (char*)pTab, P4_TABLE); sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP); sqlite3ReleaseTempReg(pParse, r); } #else # define codeWithoutRowidPreupdate(a,b,c,d) #endif /* ** This routine generates code to finish the INSERT or UPDATE operation ** that was started by a prior call to sqlite3GenerateConstraintChecks. ** A consecutive range of registers starting at regNewData contains the ** rowid and the content to be inserted. ** ** The arguments to this routine should be the same as the first six |
︙ | ︙ | |||
2449 2450 2451 2452 2453 2454 2455 | VdbeCoverage(v); } pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0); if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ assert( pParse->nested==0 ); pik_flags |= OPFLAG_NCHANGE; pik_flags |= (update_flags & OPFLAG_SAVEPOSITION); | < < < < | < < < < | 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 | VdbeCoverage(v); } pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0); if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ assert( pParse->nested==0 ); pik_flags |= OPFLAG_NCHANGE; pik_flags |= (update_flags & OPFLAG_SAVEPOSITION); if( update_flags==0 ){ codeWithoutRowidPreupdate(pParse, pTab, iIdxCur+i, aRegIdx[i]); } } sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i], aRegIdx[i]+1, pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn); sqlite3VdbeChangeP5(v, pik_flags); } if( !HasRowid(pTab) ) return; |
︙ | ︙ | |||
2932 2933 2934 2935 2936 2937 2938 | if( db->mDbFlags & DBFLAG_Vacuum ){ sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest); insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT; }else{ insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND|OPFLAG_PREFORMAT; } #ifdef SQLITE_ENABLE_PREUPDATE_HOOK | | | > | > | 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 | if( db->mDbFlags & DBFLAG_Vacuum ){ sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest); insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT; }else{ insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND|OPFLAG_PREFORMAT; } #ifdef SQLITE_ENABLE_PREUPDATE_HOOK if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); insFlags &= ~OPFLAG_PREFORMAT; }else #endif { sqlite3VdbeAddOp3(v, OP_RowCell, iDest, iSrc, regRowid); } sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid); if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){ sqlite3VdbeChangeP4(v, -1, (char*)pDest, P4_TABLE); } sqlite3VdbeChangeP5(v, insFlags); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); }else{ sqlite3TableLock(pParse, iDbDest, pDest->tnum, 1, pDest->zName); |
︙ | ︙ | |||
2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 | sqlite3VdbeAddOp2(v, OP_RowCell, iDest, iSrc); } }else if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){ idxInsFlags |= OPFLAG_NCHANGE; } if( idxInsFlags!=(OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT) ){ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); } sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData); sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); | > > > > > > | 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 | sqlite3VdbeAddOp2(v, OP_RowCell, iDest, iSrc); } }else if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){ idxInsFlags |= OPFLAG_NCHANGE; } if( idxInsFlags!=(OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT) ){ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); if( (db->mDbFlags & DBFLAG_Vacuum)==0 && !HasRowid(pDest) && IsPrimaryKeyIndex(pDestIdx) ){ codeWithoutRowidPreupdate(pParse, pDest, iDest, regData); } } sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData); sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
509 510 511 512 513 514 515 | (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 && cnt>mxSelect ){ sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); } } } | < < | | > > | > | | > | | | | | | < < | | < < < | < | > > > > | 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 && cnt>mxSelect ){ sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); } } } #ifndef SQLITE_OMIT_CTE /* Link a With object to a Select object. ** Both Select- and Parse-ownership is assigned to the With object */ static Select *linkWithToSelect(Parse *pParse, Select *pSelect, With *pWith){ assert( pWith->mOwner==0 ); if( pSelect ){ pSelect->pWith = pWith; sqlite3WithClaimedBySelect(pWith); parserDoubleLinkSelect(pParse, pSelect); }else{ sqlite3WithClaimedByParse(pParse,pWith); } return pSelect; } #endif /* SQLITE_OMIT_CTE */ } // end %include %ifndef SQLITE_OMIT_CTE select(A) ::= WITH wqlist(W) selectnowith(X). { A = linkWithToSelect(pParse,X,W); } select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X). { A = linkWithToSelect(pParse,X,W); } %endif /* SQLITE_OMIT_CTE */ select(A) ::= selectnowith(X). { Select *p = X; if( p ){ parserDoubleLinkSelect(pParse, p); } A = p; /*A-overwrites-X*/ |
︙ | ︙ | |||
1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 | sqlite3AlterRenameTable(pParse,X,&Z); } cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname(Y) carglist. { Y.n = (int)(pParse->sLastToken.z-Y.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &Y); } add_column_fullname ::= fullname(X). { disableLookaside(pParse); sqlite3AlterBeginAddColumn(pParse, X); } cmd ::= ALTER TABLE fullname(X) RENAME kwcolumn_opt nm(Y) TO nm(Z). { sqlite3AlterRenameColumn(pParse, X, &Y, &Z); } | > > > > | 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 | sqlite3AlterRenameTable(pParse,X,&Z); } cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname(Y) carglist. { Y.n = (int)(pParse->sLastToken.z-Y.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &Y); } cmd ::= ALTER TABLE fullname(X) DROP kwcolumn_opt nm(Y). { sqlite3AlterDropColumn(pParse, X, &Y); } add_column_fullname ::= fullname(X). { disableLookaside(pParse); sqlite3AlterBeginAddColumn(pParse, X); } cmd ::= ALTER TABLE fullname(X) RENAME kwcolumn_opt nm(Y) TO nm(Z). { sqlite3AlterRenameColumn(pParse, X, &Y, &Z); } |
︙ | ︙ | |||
1656 1657 1658 1659 1660 1661 1662 | anylist ::= anylist LP anylist RP. anylist ::= anylist ANY. %endif SQLITE_OMIT_VIRTUALTABLE //////////////////////// COMMON TABLE EXPRESSIONS //////////////////////////// %type wqlist {With*} | | | | | | | | 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 | anylist ::= anylist LP anylist RP. anylist ::= anylist ANY. %endif SQLITE_OMIT_VIRTUALTABLE //////////////////////// COMMON TABLE EXPRESSIONS //////////////////////////// %type wqlist {With*} %destructor wqlist {if($$)sqlite3WithDelete(pParse->db, $$);} %type wqitem {Cte*} %destructor wqitem {sqlite3CteDelete(pParse->db, $$);} %type wqas {int} with ::= . %ifndef SQLITE_OMIT_CTE with ::= WITH wqlist(W). { sqlite3WithPush(pParse, W); } with ::= WITH RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W); } wqas(A) ::= AS. {A = Materialize_Any;} wqas(A) ::= AS MATERIALIZED. {A = Materialize_Yes;} wqas(A) ::= AS NOT MATERIALIZED. {A = Materialize_No;} wqitem(A) ::= nm(X) eidlist_opt(Y) wqas(F) LP select(Z) RP. { A = sqlite3CteNew(pParse, &X, Y, Z, F); /*A-overwrites-X*/ } wqlist(A) ::= wqitem(X). { A = sqlite3WithAdd(pParse, 0, X); /*A-overwrites-X*/ } wqlist(A) ::= wqlist(A) COMMA wqitem(X). { |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
17 18 19 20 21 22 23 | /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. */ static void corruptSchema( InitData *pData, /* Initialization context */ | | | | > > > > | | 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 | /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. */ static void corruptSchema( InitData *pData, /* Initialization context */ char **azObj, /* Type and name of object being parsed */ const char *zExtra /* Error information */ ){ sqlite3 *db = pData->db; if( db->mallocFailed ){ pData->rc = SQLITE_NOMEM_BKPT; }else if( pData->pzErrMsg[0]!=0 ){ /* A error message has already been generated. Do not overwrite it */ }else if( pData->mInitFlags & (INITFLAG_AlterRename|INITFLAG_AlterDrop) ){ *pData->pzErrMsg = sqlite3MPrintf(db, "error in %s %s after %s: %s", azObj[0], azObj[1], (pData->mInitFlags & INITFLAG_AlterRename) ? "rename" : "drop column", zExtra ); pData->rc = SQLITE_ERROR; }else if( db->flags & SQLITE_WriteSchema ){ pData->rc = SQLITE_CORRUPT_BKPT; }else{ char *z; const char *zObj = azObj[1] ? azObj[1] : "?"; z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); *pData->pzErrMsg = z; pData->rc = SQLITE_CORRUPT_BKPT; } } |
︙ | ︙ | |||
90 91 92 93 94 95 96 | assert( argc==5 ); UNUSED_PARAMETER2(NotUsed, argc); assert( sqlite3_mutex_held(db->mutex) ); db->mDbFlags |= DBFLAG_EncodingFixed; pData->nInitRow++; if( db->mallocFailed ){ | | | | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | assert( argc==5 ); UNUSED_PARAMETER2(NotUsed, argc); assert( sqlite3_mutex_held(db->mutex) ); db->mDbFlags |= DBFLAG_EncodingFixed; pData->nInitRow++; if( db->mallocFailed ){ corruptSchema(pData, argv, 0); return 1; } assert( iDb>=0 && iDb<db->nDb ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[3]==0 ){ corruptSchema(pData, argv, 0); }else if( argv[4] && 'c'==sqlite3UpperToLower[(unsigned char)argv[4][0]] && 'r'==sqlite3UpperToLower[(unsigned char)argv[4][1]] ){ /* Call the parser to process a CREATE TABLE, INDEX or VIEW. ** But because db->init.busy is set to 1, no VDBE code is generated ** or executed. All the parser does is build the internal data ** structures that describe the table, index, or view. |
︙ | ︙ | |||
122 123 124 125 126 127 128 | assert( db->init.busy ); db->init.iDb = iDb; if( sqlite3GetUInt32(argv[3], &db->init.newTnum)==0 || (db->init.newTnum>pData->mxPage && pData->mxPage>0) ){ if( sqlite3Config.bExtraSchemaChecks ){ | | | | | | | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | assert( db->init.busy ); db->init.iDb = iDb; if( sqlite3GetUInt32(argv[3], &db->init.newTnum)==0 || (db->init.newTnum>pData->mxPage && pData->mxPage>0) ){ if( sqlite3Config.bExtraSchemaChecks ){ corruptSchema(pData, argv, "invalid rootpage"); } } db->init.orphanTrigger = 0; db->init.azInit = argv; pStmt = 0; TESTONLY(rcp = ) sqlite3Prepare(db, argv[4], -1, 0, 0, &pStmt, 0); rc = db->errCode; assert( (rc&0xFF)==(rcp&0xFF) ); db->init.iDb = saved_iDb; /* assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 ); */ if( SQLITE_OK!=rc ){ if( db->init.orphanTrigger ){ assert( iDb==1 ); }else{ if( rc > pData->rc ) pData->rc = rc; if( rc==SQLITE_NOMEM ){ sqlite3OomFault(db); }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){ corruptSchema(pData, argv, sqlite3_errmsg(db)); } } } sqlite3_finalize(pStmt); }else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=0) ){ corruptSchema(pData, argv, 0); }else{ /* If the SQL column is blank it means this is an index that ** was created to be the PRIMARY KEY or to fulfill a UNIQUE ** constraint for a CREATE TABLE. The index should have already ** been created when we processed the CREATE TABLE. All we have ** to do here is record the root page number for that index. */ Index *pIndex; pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName); if( pIndex==0 ){ corruptSchema(pData, argv, "orphan index"); }else if( sqlite3GetUInt32(argv[3],&pIndex->tnum)==0 || pIndex->tnum<2 || pIndex->tnum>pData->mxPage || sqlite3IndexHasDuplicateRootPage(pIndex) ){ if( sqlite3Config.bExtraSchemaChecks ){ corruptSchema(pData, argv, "invalid rootpage"); } } } return 0; } /* |
︙ | ︙ | |||
546 547 548 549 550 551 552 | } } assert( i>=0 && i<db->nDb ); } return i; } | < < < < < < < < < < < < < < < | | 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 | } } assert( i>=0 && i<db->nDb ); } return i; } /* ** Free all memory allocations in the pParse object */ void sqlite3ParserReset(Parse *pParse){ sqlite3 *db = pParse->db; while( pParse->pCleanup ){ ParseCleanup *pCleanup = pParse->pCleanup; pParse->pCleanup = pCleanup->pNext; pCleanup->xCleanup(db, pCleanup->pPtr); sqlite3DbFreeNN(db, pCleanup); } sqlite3DbFree(db, pParse->aLabel); if( pParse->pConstExpr ){ sqlite3ExprListDelete(db, pParse->pConstExpr); } if( db ){ assert( db->lookaside.bDisable >= pParse->disableLookaside ); |
︙ | ︙ | |||
604 605 606 607 608 609 610 | ** pParse->earlyCleanup flag is set in that case. Calling code show verify ** that test cases exist for which this happens, to guard against possible ** use-after-free errors following an OOM. The preferred way to do this is ** to immediately follow the call to this routine with: ** ** testcase( pParse->earlyCleanup ); */ | | > > | 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 | ** pParse->earlyCleanup flag is set in that case. Calling code show verify ** that test cases exist for which this happens, to guard against possible ** use-after-free errors following an OOM. The preferred way to do this is ** to immediately follow the call to this routine with: ** ** testcase( pParse->earlyCleanup ); */ void *sqlite3ParserAddCleanup( Parse *pParse, /* Destroy when this Parser finishes */ void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */ void *pPtr /* Pointer to object to be cleaned up */ ){ ParseCleanup *pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup)); if( pCleanup ){ pCleanup->pNext = pParse->pCleanup; pParse->pCleanup = pCleanup; pCleanup->pPtr = pPtr; pCleanup->xCleanup = xCleanup; }else{ xCleanup(pParse->db, pPtr); pPtr = 0; #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) pParse->earlyCleanup = 1; #endif } return pPtr; } /* ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. */ static int sqlite3Prepare( sqlite3 *db, /* Database handle. */ |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
66 67 68 69 70 71 72 | ** structures must be increased by the nSubquery amount. */ static void resolveAlias( Parse *pParse, /* Parsing context */ ExprList *pEList, /* A result set */ int iCol, /* A column in the result set. 0..pEList->nExpr-1 */ Expr *pExpr, /* Transform this into an alias to the result set */ | < | | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | ** structures must be increased by the nSubquery amount. */ static void resolveAlias( Parse *pParse, /* Parsing context */ ExprList *pEList, /* A result set */ int iCol, /* A column in the result set. 0..pEList->nExpr-1 */ Expr *pExpr, /* Transform this into an alias to the result set */ int nSubquery /* Number of subqueries that the label is moving */ ){ Expr *pOrig; /* The iCol-th column of the result set */ Expr *pDup; /* Copy of pOrig */ sqlite3 *db; /* The database connection */ assert( iCol>=0 && iCol<pEList->nExpr ); pOrig = pEList->a[iCol].pExpr; assert( pOrig!=0 ); db = pParse->db; pDup = sqlite3ExprDup(db, pOrig, 0); if( pDup!=0 ){ incrAggFunctionDepth(pDup, nSubquery); if( pExpr->op==TK_COLLATE ){ pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); } /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This ** prevents ExprDelete() from deleting the Expr structure itself, ** allowing it to be repopulated by the memcpy() on the following line. |
︙ | ︙ | |||
520 521 522 523 524 525 526 | sqlite3ErrorMsg(pParse, "misuse of aliased window function %s",zAs); return WRC_Abort; } if( sqlite3ExprVectorSize(pOrig)!=1 ){ sqlite3ErrorMsg(pParse, "row value misused"); return WRC_Abort; } | | | 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 | sqlite3ErrorMsg(pParse, "misuse of aliased window function %s",zAs); return WRC_Abort; } if( sqlite3ExprVectorSize(pOrig)!=1 ){ sqlite3ErrorMsg(pParse, "row value misused"); return WRC_Abort; } resolveAlias(pParse, pEList, j, pExpr, nSubquery); cnt = 1; pMatch = 0; assert( zTab==0 && zDb==0 ); if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr); } goto lookupname_end; |
︙ | ︙ | |||
622 623 624 625 626 627 628 | */ if( pExpr->iColumn>=0 && pMatch!=0 ){ pMatch->colUsed |= sqlite3ExprColUsed(pExpr); } /* Clean up and return */ | > | | | | > | 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 | */ if( pExpr->iColumn>=0 && pMatch!=0 ){ pMatch->colUsed |= sqlite3ExprColUsed(pExpr); } /* Clean up and return */ if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ sqlite3ExprDelete(db, pExpr->pLeft); pExpr->pLeft = 0; sqlite3ExprDelete(db, pExpr->pRight); pExpr->pRight = 0; } pExpr->op = eNewExprOp; ExprSetProperty(pExpr, EP_Leaf); lookupname_end: if( cnt==1 ){ assert( pNC!=0 ); if( pParse->db->xAuth && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER) |
︙ | ︙ | |||
1397 1398 1399 1400 1401 1402 1403 | assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */ for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ if( pItem->u.x.iOrderByCol ){ if( pItem->u.x.iOrderByCol>pEList->nExpr ){ resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr); return 1; } | | < | 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 | assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */ for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ if( pItem->u.x.iOrderByCol ){ if( pItem->u.x.iOrderByCol>pEList->nExpr ){ resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr); return 1; } resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,0); } } return 0; } #ifndef SQLITE_OMIT_WINDOWFUNC /* |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
86 87 88 89 90 91 92 | sqlite3ExprListDelete(db, p->pOrderBy); sqlite3ExprDelete(db, p->pLimit); #ifndef SQLITE_OMIT_WINDOWFUNC if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){ sqlite3WindowListDelete(db, p->pWinDefn); } #endif | | | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | sqlite3ExprListDelete(db, p->pOrderBy); sqlite3ExprDelete(db, p->pLimit); #ifndef SQLITE_OMIT_WINDOWFUNC if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){ sqlite3WindowListDelete(db, p->pWinDefn); } #endif if( p->pWith ) sqlite3WithReleaseBySelect(db, p->pWith); if( bFree ) sqlite3DbFreeNN(db, p); p = pPrior; bFree = 1; } } /* |
︙ | ︙ | |||
258 259 260 261 262 263 264 | return jointype; } /* ** Return the index of a column in a table. Return -1 if the column ** is not contained in the table. */ | | | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | return jointype; } /* ** Return the index of a column in a table. Return -1 if the column ** is not contained in the table. */ int sqlite3ColumnIndex(Table *pTab, const char *zCol){ int i; u8 h = sqlite3StrIHash(zCol); Column *pCol; for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){ if( pCol->hName==h && sqlite3StrICmp(pCol->zName, zCol)==0 ) return i; } return -1; |
︙ | ︙ | |||
290 291 292 293 294 295 296 | int bIgnoreHidden /* True to ignore hidden columns */ ){ int i; /* For looping over tables in pSrc */ int iCol; /* Index of column matching zCol */ assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */ for(i=0; i<N; i++){ | | | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | int bIgnoreHidden /* True to ignore hidden columns */ ){ int i; /* For looping over tables in pSrc */ int iCol; /* Index of column matching zCol */ assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */ for(i=0; i<N; i++){ iCol = sqlite3ColumnIndex(pSrc->a[i].pTab, zCol); if( iCol>=0 && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0) ){ if( piTab ){ *piTab = i; *piCol = iCol; } |
︙ | ︙ | |||
500 501 502 503 504 505 506 | for(j=0; j<pList->nId; j++){ char *zName; /* Name of the term in the USING clause */ int iLeft; /* Table on the left with matching column name */ int iLeftCol; /* Column number of matching column on the left */ int iRightCol; /* Column number of matching column on the right */ zName = pList->a[j].zName; | | | 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 | for(j=0; j<pList->nId; j++){ char *zName; /* Name of the term in the USING clause */ int iLeft; /* Table on the left with matching column name */ int iLeftCol; /* Column number of matching column on the left */ int iRightCol; /* Column number of matching column on the right */ zName = pList->a[j].zName; iRightCol = sqlite3ColumnIndex(pRightTab, zName); if( iRightCol<0 || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 0) ){ sqlite3ErrorMsg(pParse, "cannot join using column %s - column " "not present in both tables", zName); return 1; } |
︙ | ︙ | |||
2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 | if( db->mallocFailed ) return; memset(&sNC, 0, sizeof(sNC)); sNC.pSrcList = pSelect->pSrc; a = pSelect->pEList->a; for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ const char *zType; int n, m; p = a[i].pExpr; zType = columnType(&sNC, p, 0, 0, 0); /* pCol->szEst = ... // Column size est for SELECT tables never used */ pCol->affinity = sqlite3ExprAffinity(p); if( zType ){ m = sqlite3Strlen30(zType); n = sqlite3Strlen30(pCol->zName); | > | 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 | if( db->mallocFailed ) return; memset(&sNC, 0, sizeof(sNC)); sNC.pSrcList = pSelect->pSrc; a = pSelect->pEList->a; for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ const char *zType; int n, m; pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT); p = a[i].pExpr; zType = columnType(&sNC, p, 0, 0, 0); /* pCol->szEst = ... // Column size est for SELECT tables never used */ pCol->affinity = sqlite3ExprAffinity(p); if( zType ){ m = sqlite3Strlen30(zType); n = sqlite3Strlen30(pCol->zName); |
︙ | ︙ | |||
4719 4720 4721 4722 4723 4724 4725 | pIdx=pIdx->pNext ); if( !pIdx ){ sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0); pParse->checkSchema = 1; return SQLITE_ERROR; } | > > | | 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 | pIdx=pIdx->pNext ); if( !pIdx ){ sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0); pParse->checkSchema = 1; return SQLITE_ERROR; } assert( pFrom->fg.isCte==0 ); assert( pFrom->pSelect==0 ); pFrom->u2.pIBIndex = pIdx; } return SQLITE_OK; } /* ** Detect compound SELECT statements that use an ORDER BY clause with ** an alternative collating sequence. ** |
︙ | ︙ | |||
4851 4852 4853 4854 4855 4856 4857 | } } return 0; } /* The code generator maintains a stack of active WITH clauses ** with the inner-most WITH clause being at the top of the stack. | < < < < < < < | < < < | < < | 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 | } } return 0; } /* The code generator maintains a stack of active WITH clauses ** with the inner-most WITH clause being at the top of the stack. */ void sqlite3WithPush(Parse *pParse, With *pWith){ if( pWith ){ assert( pParse->pWith!=pWith ); pWith->pOuter = pParse->pWith; pParse->pWith = pWith; sqlite3WithClaimedByParse(pParse, pWith); } } /* ** This function checks if argument pFrom refers to a CTE declared by ** a WITH clause on the stack currently maintained by the parser. And, ** if currently processing a CTE expression, if it is a recursive |
︙ | ︙ | |||
4934 4935 4936 4937 4938 4939 4940 | pTab->zName = sqlite3DbStrDup(db, pCte->zName); pTab->iPKey = -1; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; assert( pFrom->pSelect ); | | > > > > > > > > | 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 | pTab->zName = sqlite3DbStrDup(db, pCte->zName); pTab->iPKey = -1; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; assert( pFrom->pSelect ); if( pCte->eMaterialize==Materialize_Yes ){ pFrom->pSelect->selFlags |= SF_OptBarrier; } assert( !pFrom->fg.isIndexedBy ); pFrom->fg.isCte = 1; assert( (pCte->eCteMagic==0 && pCte->nRefCte==0) || (pCte->eCteMagic==CTE_MAGIC && pCte->nRefCte>0) ); pFrom->u2.pCteSrc = pCte; sqlite3WithClaimedByParse(pParse, pWith); pCte->nRefCte++; VVA_ONLY( pCte->eCteMagic = CTE_MAGIC ); /* Check if this is a recursive CTE. */ pRecTerm = pSel = pFrom->pSelect; bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION ); while( bMayRecursive && pRecTerm->op==pSel->op ){ int i; SrcList *pSrc = pRecTerm->pSrc; |
︙ | ︙ | |||
5117 5118 5119 5120 5121 5122 5123 | } if( pWalker->eCode ){ /* Renumber selId because it has been copied from a view */ p->selId = ++pParse->nSelect; } pTabList = p->pSrc; pEList = p->pEList; | | | 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 | } if( pWalker->eCode ){ /* Renumber selId because it has been copied from a view */ p->selId = ++pParse->nSelect; } pTabList = p->pSrc; pEList = p->pEList; sqlite3WithPush(pParse, p->pWith); /* Make sure cursor numbers have been assigned to all entries in ** the FROM clause of the SELECT statement. */ sqlite3SrcListAssignCursors(pParse, pTabList); /* Look up every table named in the FROM clause of the select. If |
︙ | ︙ | |||
5756 5757 5758 5759 5760 5761 5762 | SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif } /* | | > | | > > > > > | 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 | SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif } /* ** Check to see if the pThis entry of pTabList is a self-join of a prior view, ** or any reuse of a CTE that is not necessarily a self-join. ** If it is, then return the SrcList_item for the prior view or CTE. ** If it is not, then return 0. */ static struct SrcList_item *isSelfJoinView( SrcList *pTabList, /* Search for self-joins in this FROM clause */ struct SrcList_item *pThis /* Search for prior reference to this subquery */ ){ struct SrcList_item *pItem; assert( pThis->pSelect!=0 ); if( pThis->pSelect->selFlags & SF_PushDown ) return 0; if( pThis->fg.isCte ){ Cte *pCte = pThis->u2.pCteSrc; sqlite3AssertValidCteBackRef(pThis); return pCte->pCteMat; } for(pItem = pTabList->a; pItem<pThis; pItem++){ Select *pS1; if( pItem->pSelect==0 ) continue; if( pItem->fg.viaCoroutine ) continue; if( pItem->zName==0 ) continue; assert( pItem->pTab!=0 ); assert( pThis->pTab!=0 ); |
︙ | ︙ | |||
5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 | ** pushDownWhereTerms() */ continue; } return pItem; } return 0; } #ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION /* ** Attempt to transform a query of the form ** ** SELECT count(*) FROM (SELECT x FROM t1 UNION ALL SELECT y FROM t2) ** | > > > > > > > > > | 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 | ** pushDownWhereTerms() */ continue; } return pItem; } return 0; } /* ** Deallocate a single AggInfo object */ static void agginfoFree(sqlite3 *db, AggInfo *p){ sqlite3DbFree(db, p->aCol); sqlite3DbFree(db, p->aFunc); sqlite3DbFreeNN(db, p); } #ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION /* ** Attempt to transform a query of the form ** ** SELECT count(*) FROM (SELECT x FROM t1 UNION ALL SELECT y FROM t2) ** |
︙ | ︙ | |||
6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 | /* For each term in the FROM clause, do two things: ** (1) Authorized unreferenced tables ** (2) Generate code for all sub-queries */ for(i=0; i<pTabList->nSrc; i++){ struct SrcList_item *pItem = &pTabList->a[i]; SelectDest dest; Select *pSub; #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) const char *zSavedAuthContext; #endif /* Issue SQLITE_READ authorizations with a fake column name for any | > | 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 | /* For each term in the FROM clause, do two things: ** (1) Authorized unreferenced tables ** (2) Generate code for all sub-queries */ for(i=0; i<pTabList->nSrc; i++){ struct SrcList_item *pItem = &pTabList->a[i]; struct SrcList_item *pPrior; SelectDest dest; Select *pSub; #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) const char *zSavedAuthContext; #endif /* Issue SQLITE_READ authorizations with a fake column name for any |
︙ | ︙ | |||
6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 | assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 ); }else{ SELECTTRACE(0x100,pParse,p,("Push-down not possible\n")); } zSavedAuthContext = pParse->zAuthContext; pParse->zAuthContext = pItem->zName; /* Generate code to implement the subquery ** ** The subquery is implemented as a co-routine if (1) the subquery is ** guaranteed to be the outer loop (so that it does not need to be | > > > | | | > > > > > > > > > < < < < < > < < < < < < < | | | > > > | 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 | assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 ); }else{ SELECTTRACE(0x100,pParse,p,("Push-down not possible\n")); } zSavedAuthContext = pParse->zAuthContext; pParse->zAuthContext = pItem->zName; /* Verify that the CTE back-reference information is valid */ sqlite3AssertValidCteBackRef(pItem); /* Generate code to implement the subquery ** ** The subquery is implemented as a co-routine if (1) the subquery is ** guaranteed to be the outer loop (so that it does not need to be ** computed more than once) and if (2) the subquery is a CTE that is ** used only this one time. ** ** TODO: Are there other reasons beside (1) and (2) to use a co-routine ** implementation? ** ** TODO: We might should allow a subquery that is an optimization barrier ** to be implemented as a co-routine as long as we know that it is the ** only use of the subquery. */ if( i==0 && (pTabList->nSrc==1 || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */ && (pItem->fg.isCte && pItem->u2.pCteSrc->nRefCte==1) /* (2) */ ){ /* Implement a co-routine that will return a single row of the result ** set on each invocation. */ int addrTop = sqlite3VdbeCurrentAddr(v)+1; pItem->regReturn = ++pParse->nMem; sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop); VdbeComment((v, "%s", pItem->pTab->zName)); pItem->addrFillSub = addrTop; sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); ExplainQueryPlan((pParse, 1, "CO-ROUTINE %u", pSub->selId)); sqlite3Select(pParse, pSub, &dest); pItem->pTab->nRowLogEst = pSub->nSelectRow; pItem->fg.viaCoroutine = 1; pItem->regResult = dest.iSdst; sqlite3VdbeEndCoroutine(v, pItem->regReturn); sqlite3VdbeJumpHere(v, addrTop-1); sqlite3ClearTempRegCache(pParse); }else if( (pPrior = isSelfJoinView(pTabList,pItem))!=0 ){ /* This view has been previously materialized. Use the ** prior materialization */ if( pPrior->addrFillSub ){ sqlite3VdbeAddOp2(v, OP_Gosub, pPrior->regReturn, pPrior->addrFillSub); } sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor); assert( pPrior->pSelect!=0 ); pSub->nSelectRow = pPrior->pSelect->nSelectRow; }else{ /* Materialize the view */ int topAddr; int onceAddr = 0; int retAddr; testcase( pItem->addrFillSub==0 ); /* Ticket c52b09c7f38903b1311 */ pItem->regReturn = ++pParse->nMem; topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn); pItem->addrFillSub = topAddr+1; if( pItem->fg.isCorrelated==0 ){ /* If the subquery is not correlated and if we are not inside of ** a trigger, then we only need to compute the value of the subquery ** once. */ onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName)); }else{ VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName)); } sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId)); sqlite3Select(pParse, pSub, &dest); if( pItem->fg.isCte ){ sqlite3AssertValidCteBackRef(pItem); pItem->u2.pCteSrc->pCteMat = pItem; } pItem->pTab->nRowLogEst = pSub->nSelectRow; if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn); VdbeComment((v, "end %s", pItem->pTab->zName)); sqlite3VdbeChangeP1(v, topAddr, retAddr); sqlite3ClearTempRegCache(pParse); |
︙ | ︙ | |||
6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 | if( sSort.pOrderBy ){ sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo); sSort.labelOBLopt = sqlite3WhereOrderByLimitOptLabel(pWInfo); if( sSort.nOBSat==sSort.pOrderBy->nExpr ){ sSort.pOrderBy = 0; } } /* If sorting index that was created by a prior OP_OpenEphemeral ** instruction ended up not being needed, then change the OP_OpenEphemeral ** into an OP_Noop. */ if( sSort.addrSortIndex>=0 && sSort.pOrderBy==0 ){ sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex); | > | 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 | if( sSort.pOrderBy ){ sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo); sSort.labelOBLopt = sqlite3WhereOrderByLimitOptLabel(pWInfo); if( sSort.nOBSat==sSort.pOrderBy->nExpr ){ sSort.pOrderBy = 0; } } SELECTTRACE(1,pParse,p,("WhereBegin returns\n")); /* If sorting index that was created by a prior OP_OpenEphemeral ** instruction ended up not being needed, then change the OP_OpenEphemeral ** into an OP_Noop. */ if( sSort.addrSortIndex>=0 && sSort.pOrderBy==0 ){ sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex); |
︙ | ︙ | |||
6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 | /* Use the standard inner loop. */ selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, sqlite3WhereContinueLabel(pWInfo), sqlite3WhereBreakLabel(pWInfo)); /* End the database scan loop. */ sqlite3WhereEnd(pWInfo); } }else{ /* This case when there exist aggregate functions or a GROUP BY clause ** or both */ NameContext sNC; /* Name context for processing aggregate information */ int iAMem; /* First Mem address for storing current GROUP BY */ | > | 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 | /* Use the standard inner loop. */ selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, sqlite3WhereContinueLabel(pWInfo), sqlite3WhereBreakLabel(pWInfo)); /* End the database scan loop. */ SELECTTRACE(1,pParse,p,("WhereEnd\n")); sqlite3WhereEnd(pWInfo); } }else{ /* This case when there exist aggregate functions or a GROUP BY clause ** or both */ NameContext sNC; /* Name context for processing aggregate information */ int iAMem; /* First Mem address for storing current GROUP BY */ |
︙ | ︙ | |||
6544 6545 6546 6547 6548 6549 6550 | addrEnd = sqlite3VdbeMakeLabel(pParse); /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the ** SELECT statement. */ pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) ); | | > > > > < < | 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 | addrEnd = sqlite3VdbeMakeLabel(pParse); /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the ** SELECT statement. */ pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) ); if( pAggInfo ){ sqlite3ParserAddCleanup(pParse, (void(*)(sqlite3*,void*))agginfoFree, pAggInfo); } if( db->mallocFailed ){ goto select_end; } pAggInfo->selId = p->selId; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; sNC.pSrcList = pTabList; sNC.uNC.pAggInfo = pAggInfo; VVA_ONLY( sNC.ncFlags = NC_UAggInfo; ) pAggInfo->mnReg = pParse->nMem+1; |
︙ | ︙ | |||
6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 | */ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0 ); if( pWInfo==0 ) goto select_end; if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){ /* The optimizer is able to deliver rows in group by order so ** we do not have to sort. The OP_OpenEphemeral table will be ** cancelled later because we still need to use the pKeyInfo */ groupBySort = 0; }else{ | > | 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 | */ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0 ); if( pWInfo==0 ) goto select_end; SELECTTRACE(1,pParse,p,("WhereBegin returns\n")); if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){ /* The optimizer is able to deliver rows in group by order so ** we do not have to sort. The OP_OpenEphemeral table will be ** cancelled later because we still need to use the pKeyInfo */ groupBySort = 0; }else{ |
︙ | ︙ | |||
6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 | } } regRecord = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord); sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempRange(pParse, regBase, nCol); sqlite3WhereEnd(pWInfo); pAggInfo->sortingIdxPTab = sortPTab = pParse->nTab++; sortOut = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); sqlite3VdbeAddOp2(v, OP_SorterSort, pAggInfo->sortingIdx, addrEnd); VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); pAggInfo->useSortingIdx = 1; | > | 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 | } } regRecord = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord); sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempRange(pParse, regBase, nCol); SELECTTRACE(1,pParse,p,("WhereEnd\n")); sqlite3WhereEnd(pWInfo); pAggInfo->sortingIdxPTab = sortPTab = pParse->nTab++; sortOut = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); sqlite3VdbeAddOp2(v, OP_SorterSort, pAggInfo->sortingIdx, addrEnd); VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); pAggInfo->useSortingIdx = 1; |
︙ | ︙ | |||
6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 | /* End of the loop */ if( groupBySort ){ sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop); VdbeCoverage(v); }else{ sqlite3WhereEnd(pWInfo); sqlite3VdbeChangeToNoop(v, addrSortingIdx); } /* Output the final row of result */ sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); | > | 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 | /* End of the loop */ if( groupBySort ){ sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop); VdbeCoverage(v); }else{ SELECTTRACE(1,pParse,p,("WhereEnd\n")); sqlite3WhereEnd(pWInfo); sqlite3VdbeChangeToNoop(v, addrSortingIdx); } /* Output the final row of result */ sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); |
︙ | ︙ | |||
6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 | SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy, 0, minMaxFlag, 0); if( pWInfo==0 ){ goto select_end; } updateAccumulator(pParse, regAcc, pAggInfo); if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc); if( minMaxFlag ){ sqlite3WhereMinMaxOptEarlyOut(v, pWInfo); } sqlite3WhereEnd(pWInfo); finalizeAggFunctions(pParse, pAggInfo); } sSort.pOrderBy = 0; sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); selectInnerLoop(pParse, p, -1, 0, 0, | > > | 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 | SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy, 0, minMaxFlag, 0); if( pWInfo==0 ){ goto select_end; } SELECTTRACE(1,pParse,p,("WhereBegin returns\n")); updateAccumulator(pParse, regAcc, pAggInfo); if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc); if( minMaxFlag ){ sqlite3WhereMinMaxOptEarlyOut(v, pWInfo); } SELECTTRACE(1,pParse,p,("WhereEnd\n")); sqlite3WhereEnd(pWInfo); finalizeAggFunctions(pParse, pAggInfo); } sSort.pOrderBy = 0; sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); selectInnerLoop(pParse, p, -1, 0, 0, |
︙ | ︙ |
Changes to src/shell.c.in.
︙ | ︙ | |||
8749 8750 8751 8752 8753 8754 8755 | } }else if( (c=='o' && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0)) || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0) ){ | | | 8749 8750 8751 8752 8753 8754 8755 8756 8757 8758 8759 8760 8761 8762 8763 | } }else if( (c=='o' && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0)) || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0) ){ char *zFile = 0; int bTxtMode = 0; int i; int eMode = 0; int bBOM = 0; int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */ if( c=='e' ){ |
︙ | ︙ | |||
8779 8780 8781 8782 8783 8784 8785 | }else{ utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", azArg[i]); showHelp(p->out, azArg[0]); rc = 1; goto meta_command_exit; } | | | > > > > > | | 8779 8780 8781 8782 8783 8784 8785 8786 8787 8788 8789 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 | }else{ utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", azArg[i]); showHelp(p->out, azArg[0]); rc = 1; goto meta_command_exit; } }else if( zFile==0 && eMode!='e' && eMode!='x' ){ zFile = sqlite3_mprintf("%s", z); if( zFile[0]=='|' ){ while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]); break; } }else{ utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n", azArg[i]); showHelp(p->out, azArg[0]); rc = 1; sqlite3_free(zFile); goto meta_command_exit; } } if( zFile==0 ) zFile = sqlite3_mprintf("stdout"); if( bOnce ){ p->outCount = 2; }else{ p->outCount = 0; } output_reset(p); #ifndef SQLITE_NOHAVE_SYSTEM |
︙ | ︙ | |||
8812 8813 8814 8815 8816 8817 8818 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); }else{ /* text editor mode */ newTempFile(p, "txt"); bTxtMode = 1; } | > | | 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); }else{ /* text editor mode */ newTempFile(p, "txt"); bTxtMode = 1; } sqlite3_free(zFile); zFile = sqlite3_mprintf("%s", p->zTempFile); } #endif /* SQLITE_NOHAVE_SYSTEM */ if( zFile[0]=='|' ){ #ifdef SQLITE_OMIT_POPEN raw_printf(stderr, "Error: pipes are not supported in this OS\n"); rc = 1; p->out = stdout; |
︙ | ︙ | |||
8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 | p->out = stdout; rc = 1; } else { if( bBOM ) fprintf(p->out,"\357\273\277"); sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); } } }else if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){ open_db(p,0); if( nArg<=1 ) goto parameter_syntax_error; /* .parameter clear | > | 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 | p->out = stdout; rc = 1; } else { if( bBOM ) fprintf(p->out,"\357\273\277"); sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); } } sqlite3_free(zFile); }else if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){ open_db(p,0); if( nArg<=1 ) goto parameter_syntax_error; /* .parameter clear |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2012 2013 2014 2015 2016 2017 2018 | u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ char affinity; /* One of the SQLITE_AFF_... values */ u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */ u8 hName; /* Column name hash for faster lookup */ u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */ }; | | > > > > > | 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 | u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ char affinity; /* One of the SQLITE_AFF_... values */ u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */ u8 hName; /* Column name hash for faster lookup */ u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */ }; /* Allowed values for Column.colFlags. ** ** Constraints: ** TF_HasVirtual == COLFLAG_VIRTUAL ** TF_HasStored == COLFLAG_STORED ** TF_HasHidden == COLFLAG_HIDDEN */ #define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */ #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ #define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */ #define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */ #define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */ #define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */ |
︙ | ︙ | |||
2201 2202 2203 2204 2205 2206 2207 | ** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING ** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, ** the TF_OOOHidden attribute would apply in this case. Such tables require ** special handling during INSERT processing. The "OOO" means "Out Of Order". ** ** Constraints: ** | | | > | > | 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 | ** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING ** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, ** the TF_OOOHidden attribute would apply in this case. Such tables require ** special handling during INSERT processing. The "OOO" means "Out Of Order". ** ** Constraints: ** ** TF_HasVirtual == COLFLAG_VIRTUAL ** TF_HasStored == COLFLAG_STORED ** TF_HasHidden == COLFLAG_HIDDEN */ #define TF_Readonly 0x0001 /* Read-only system table */ #define TF_HasHidden 0x0002 /* Has one or more hidden columns */ #define TF_HasPrimaryKey 0x0004 /* Table has a primary key */ #define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */ #define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */ #define TF_HasVirtual 0x0020 /* Has one or more VIRTUAL columns */ #define TF_HasStored 0x0040 /* Has one or more STORED columns */ #define TF_HasGenerated 0x0060 /* Combo: HasVirtual + HasStored */ #define TF_WithoutRowid 0x0080 /* No rowid. PRIMARY KEY is the key */ #define TF_StatsUsed 0x0100 /* Query planner decisions affected by ** Index.aiRowLogEst[] values */ #define TF_NoVisibleRowid 0x0200 /* No user-visible "rowid" column */ #define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */ #define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */ #define TF_Shadow 0x1000 /* True for a shadow table */ #define TF_HasStat4 0x2000 /* STAT4 info available for this table */ #define TF_Ephemeral 0x4000 /* An ephemeral table */ /* ** Test to see whether or not a table is a virtual table. This is ** done as a macro so that it will be optimized out when virtual ** table support is omitted from the build. */ #ifndef SQLITE_OMIT_VIRTUALTABLE |
︙ | ︙ | |||
2588 2589 2590 2591 2592 2593 2594 | Expr *pFExpr; /* Expression encoding the function */ FuncDef *pFunc; /* The aggregate function implementation */ int iMem; /* Memory location that acts as accumulator */ int iDistinct; /* Ephemeral table used to enforce DISTINCT */ } *aFunc; int nFunc; /* Number of entries in aFunc[] */ u32 selId; /* Select to which this AggInfo belongs */ | < | 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 | Expr *pFExpr; /* Expression encoding the function */ FuncDef *pFunc; /* The aggregate function implementation */ int iMem; /* Memory location that acts as accumulator */ int iDistinct; /* Ephemeral table used to enforce DISTINCT */ } *aFunc; int nFunc; /* Number of entries in aFunc[] */ u32 selId; /* Select to which this AggInfo belongs */ }; /* ** The datatype ynVar is a signed integer, either 16-bit or 32-bit. ** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater ** than 32767 we have to make it 32-bit. 16-bit is preferred because ** it uses less memory in the Expr object, which is a big memory user |
︙ | ︙ | |||
2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 | unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */ unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */ unsigned isTabFunc :1; /* True if table-valued-function syntax */ unsigned isCorrelated :1; /* True if sub-query is correlated */ unsigned viaCoroutine :1; /* Implemented as a co-routine */ unsigned isRecursive :1; /* True for recursive reference in WITH */ unsigned fromDDL :1; /* Comes from sqlite_schema */ } fg; int iCursor; /* The VDBE cursor number used to access this table */ Expr *pOn; /* The ON clause of a join */ IdList *pUsing; /* The USING clause of a join */ Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */ union { char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */ ExprList *pFuncArg; /* Arguments to table-valued-function */ } u1; | > > | > > | 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 | unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */ unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */ unsigned isTabFunc :1; /* True if table-valued-function syntax */ unsigned isCorrelated :1; /* True if sub-query is correlated */ unsigned viaCoroutine :1; /* Implemented as a co-routine */ unsigned isRecursive :1; /* True for recursive reference in WITH */ unsigned fromDDL :1; /* Comes from sqlite_schema */ unsigned isCte :1; /* True if table is a CTE */ } fg; int iCursor; /* The VDBE cursor number used to access this table */ Expr *pOn; /* The ON clause of a join */ IdList *pUsing; /* The USING clause of a join */ Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */ union { char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */ ExprList *pFuncArg; /* Arguments to table-valued-function */ } u1; union { Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */ Cte *pCteSrc; /* The original CTE, if fg.isCte is true */ } u2; } a[1]; /* One entry for each identifier on the list */ }; /* ** Permitted values of the SrcList.a.jointype field */ #define JT_INNER 0x0001 /* Any kind of inner or cross join */ |
︙ | ︙ | |||
3425 3426 3427 3428 3429 3430 3431 | int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ Parse *pParentParse; /* Parent parser if this parser is nested */ | < | 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 | int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ Parse *pParentParse; /* Parent parser if this parser is nested */ union { int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ Returning *pReturning; /* The RETURNING clause */ } u1; u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ u32 oldmask; /* Mask of old.* columns referenced */ u32 newmask; /* Mask of new.* columns referenced */ |
︙ | ︙ | |||
3709 3710 3711 3712 3713 3714 3715 | u32 nInitRow; /* Number of rows processed */ Pgno mxPage; /* Maximum page number. 0 for no limit. */ } InitData; /* ** Allowed values for mInitFlags */ | | > | 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 | u32 nInitRow; /* Number of rows processed */ Pgno mxPage; /* Maximum page number. 0 for no limit. */ } InitData; /* ** Allowed values for mInitFlags */ #define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */ #define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */ /* ** Structure containing global configuration data for the SQLite library. ** ** This structure also contains some state information. */ struct Sqlite3Config { |
︙ | ︙ | |||
3866 3867 3868 3869 3870 3871 3872 | ** callbacks. */ #define WRC_Continue 0 /* Continue down into children */ #define WRC_Prune 1 /* Omit children but continue walking siblings */ #define WRC_Abort 2 /* Abandon the tree walk */ /* | | | | | > > > > > > > > > > > > > | > > > > > > > > > > > > > | 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 | ** callbacks. */ #define WRC_Continue 0 /* Continue down into children */ #define WRC_Prune 1 /* Omit children but continue walking siblings */ #define WRC_Abort 2 /* Abandon the tree walk */ /* ** Allowed values for Cte.eMaterialize */ #define Materialize_Any 0 /* Not specified */ #define Materialize_Yes 1 /* AS MATERIALIZED ... */ #define Materialize_No 2 /* AS NOT MATERIALIZED. Not currently used */ /* ** An instance of this structure represents a set of one or more CTEs ** (common table expressions) created by a single WITH clause. ** ** A With object describes an entire WITH clause, which is composed of ** one or more Cte objects. During parsing, the Cte objects are created ** separately for each common-table-expression, then copied into the ** With object container. ** ** DUAL OWNERSHIP ** The With object can be owned by a Select object (via the Select.pWith ** field), or it can be owned by the Parse object of the current parse, ** or by both. The With.mOwner bitmask determines who owns each With object. ** The object is not deallocated until all owners have released it. */ struct Cte { char *zName; /* Name of this CTE */ ExprList *pCols; /* List of explicit column names, or NULL */ Select *pSelect; /* The definition of this CTE */ const char *zCteErr; /* Error message for circular references */ u8 eMaterialize; /* One of the Materialize_* options */ u16 eCteMagic; /* Magic number for sanity checking */ u32 nRefCte; /* Number of times used */ struct SrcList_item *pCteMat; /* The materialization of this CTE */ }; struct With { int nCte; /* Number of CTEs in the WITH clause */ int mOwner; /* Mask of bits to discribe ownership */ With *pOuter; /* Containing WITH clause, or NULL */ Cte a[1]; /* The CTEs of this WITH clause */ }; /* ** The correct value for Cte.eCteMagic if the Cte object is valid */ #define CTE_MAGIC 0x3f96 /* Magic number for valid Cte objects */ /* ** Ownership flags for With. */ #define WithOwnedBySelect 0x01 /* Owned by a Select object */ #define WithOwnedByParse 0x10 /* Owned by the Parse object */ #ifdef SQLITE_DEBUG /* ** An instance of the TreeView object is used for printing the content of ** data structures on sqlite3DebugPrintf() using a tree-like view. */ struct TreeView { int iLevel; /* Which level of the tree we are on */ |
︙ | ︙ | |||
4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 | # define sqlite3ParseToplevel(p) p # define sqlite3IsToplevel(p) 1 # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 # define sqlite3TriggerStepSrc(A,B) 0 #endif int sqlite3JoinType(Parse*, Token*, Token*, Token*); void sqlite3SetJoinExpr(Expr*,int); void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); void sqlite3DeferForeignKey(Parse*, int); #ifndef SQLITE_OMIT_AUTHORIZATION void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*); int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*); void sqlite3AuthContextPush(Parse*, AuthContext*, const char*); | > | 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 | # define sqlite3ParseToplevel(p) p # define sqlite3IsToplevel(p) 1 # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 # define sqlite3TriggerStepSrc(A,B) 0 #endif int sqlite3JoinType(Parse*, Token*, Token*, Token*); int sqlite3ColumnIndex(Table *pTab, const char *zCol); void sqlite3SetJoinExpr(Expr*,int); void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); void sqlite3DeferForeignKey(Parse*, int); #ifndef SQLITE_OMIT_AUTHORIZATION void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*); int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*); void sqlite3AuthContextPush(Parse*, AuthContext*, const char*); |
︙ | ︙ | |||
4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 | int sqlite3ResolveExprListNames(NameContext*, ExprList*); void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); int sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*); int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); void sqlite3ColumnDefault(Vdbe *, Table *, int, int); void sqlite3AlterFinishAddColumn(Parse *, Token *); void sqlite3AlterBeginAddColumn(Parse *, SrcList *); void *sqlite3RenameTokenMap(Parse*, void*, Token*); void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom); void sqlite3RenameExprUnmap(Parse*, Expr*); void sqlite3RenameExprlistUnmap(Parse*, ExprList*); CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); char sqlite3AffinityType(const char*, Column*); void sqlite3Analyze(Parse*, Token*, Token*); | > | 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 | int sqlite3ResolveExprListNames(NameContext*, ExprList*); void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); int sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*); int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); void sqlite3ColumnDefault(Vdbe *, Table *, int, int); void sqlite3AlterFinishAddColumn(Parse *, Token *); void sqlite3AlterBeginAddColumn(Parse *, SrcList *); void sqlite3AlterDropColumn(Parse*, SrcList*, Token*); void *sqlite3RenameTokenMap(Parse*, void*, Token*); void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom); void sqlite3RenameExprUnmap(Parse*, Expr*); void sqlite3RenameExprlistUnmap(Parse*, ExprList*); CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); char sqlite3AffinityType(const char*, Column*); void sqlite3Analyze(Parse*, Token*, Token*); |
︙ | ︙ | |||
4875 4876 4877 4878 4879 4880 4881 | int sqlite3VtabCallDestroy(sqlite3*, int, const char *); int sqlite3VtabBegin(sqlite3 *, VTable *); FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); void sqlite3ParserReset(Parse*); | | > > > > | > > | > > > | | > > > > > | | 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 | int sqlite3VtabCallDestroy(sqlite3*, int, const char *); int sqlite3VtabBegin(sqlite3 *, VTable *); FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); void sqlite3ParserReset(Parse*); void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*); #ifdef SQLITE_ENABLE_NORMALIZE char *sqlite3Normalize(Vdbe*, const char*); #endif int sqlite3Reprepare(Vdbe*); void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); CollSeq *sqlite3ExprCompareCollSeq(Parse*,const Expr*); CollSeq *sqlite3BinaryCompareCollSeq(Parse *, const Expr*, const Expr*); int sqlite3TempInMemory(const sqlite3*); const char *sqlite3JournalModename(int); #ifndef SQLITE_OMIT_WAL int sqlite3Checkpoint(sqlite3*, int, int, int*, int*); int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); #endif #ifndef SQLITE_OMIT_CTE Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,int); With *sqlite3WithAdd(Parse*,With*,Cte*); void sqlite3CteDelete(sqlite3*,Cte*); void sqlite3WithDelete(sqlite3*,With*); void sqlite3WithReleaseBySelect(sqlite3*,With*); void sqlite3WithReleaseByParse(sqlite3*,With*); void sqlite3WithClaimedBySelect(With*); With *sqlite3WithClaimedByParse(Parse*,With*); void sqlite3WithPush(Parse*, With*); # ifdef SQLITE_DEBUG void sqlite3AssertValidCteBackRef(struct SrcList_item*); # else # define sqlite3AssertValidCteBackRef(X) # endif #else /* if defined(SQLITE_OMIT_CTE) */ # define sqlite3WithPush(PARSE,W) # deifne sqlite3WithDelete(Db,W) # define sqlite3WithReleaseBySelect(DB,W) # define sqlite3WithReleaseByParse(DB,W) # define sqlite3WithClaimedBySelect(W) # define sqlite3WithClaimedByParse(PARSE,W); # define sqlite3AssertValidCteBackRef(X) #endif /* SQLITE_OMIT_CTE */ #ifndef SQLITE_OMIT_UPSERT Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*); void sqlite3UpsertDelete(sqlite3*,Upsert*); Upsert *sqlite3UpsertDup(sqlite3*,Upsert*); int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*); void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int); Upsert *sqlite3UpsertOfIndex(Upsert*,Index*); |
︙ | ︙ |
Changes to src/treeview.c.
︙ | ︙ | |||
86 87 88 89 90 91 92 | ** Generate a human-readable description of a WITH clause. */ void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){ int i; if( pWith==0 ) return; if( pWith->nCte==0 ) return; if( pWith->pOuter ){ | | > | > > > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | ** Generate a human-readable description of a WITH clause. */ void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){ int i; if( pWith==0 ) return; if( pWith->nCte==0 ) return; if( pWith->pOuter ){ sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)", pWith,pWith->pOuter); }else{ sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith); } if( pWith->nCte>0 ){ pView = sqlite3TreeViewPush(pView, 1); for(i=0; i<pWith->nCte; i++){ StrAccum x; char zLine[1000]; const struct Cte *pCte = &pWith->a[i]; sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); sqlite3_str_appendf(&x, "%s%s (0x%p, n=%d)", pCte->zName, pCte->eMaterialize==Materialize_Any ? "" : pCte->eMaterialize==Materialize_Yes ? " MATERIALIZED" : " NOT MATERIALIZED", pCte, pCte->nRefCte); if( pCte->pCols && pCte->pCols->nExpr>0 ){ char cSep = '('; int j; for(j=0; j<pCte->pCols->nExpr; j++){ sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zEName); cSep = ','; } |
︙ | ︙ | |||
146 147 148 149 150 151 152 153 154 155 156 157 158 159 | } if( pItem->fg.jointype & JT_LEFT ){ sqlite3_str_appendf(&x, " LEFT-JOIN"); } if( pItem->fg.fromDDL ){ sqlite3_str_appendf(&x, " DDL"); } sqlite3StrAccumFinish(&x); sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1); if( pItem->pSelect ){ sqlite3TreeViewSelect(pView, pItem->pSelect, 0); } if( pItem->fg.isTabFunc ){ sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); | > > > | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | } if( pItem->fg.jointype & JT_LEFT ){ sqlite3_str_appendf(&x, " LEFT-JOIN"); } if( pItem->fg.fromDDL ){ sqlite3_str_appendf(&x, " DDL"); } if( pItem->fg.isCte && pItem->u2.pCteSrc ){ sqlite3_str_appendf(&x, " CTE=0x%p", pItem->u2.pCteSrc); } sqlite3StrAccumFinish(&x); sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1); if( pItem->pSelect ){ sqlite3TreeViewSelect(pView, pItem->pSelect, 0); } if( pItem->fg.isTabFunc ){ sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
352 353 354 355 356 357 358 | "INSERT INTO %Q." DFLT_SCHEMA_TABLE " VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", db->aDb[iDb].zDbSName, zName, pTrig->table, z); sqlite3DbFree(db, z); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(v, iDb, | | | 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | "INSERT INTO %Q." DFLT_SCHEMA_TABLE " VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", db->aDb[iDb].zDbSName, zName, pTrig->table, z); sqlite3DbFree(db, z); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(v, iDb, sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName), 0); } if( db->init.busy ){ Trigger *pLink = pTrig; Hash *pHash = &db->aDb[iDb].pSchema->trigHash; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); assert( pLink!=0 ); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
6326 6327 6328 6329 6330 6331 6332 | assert( iDb>=0 && iDb<db->nDb ); assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); #ifndef SQLITE_OMIT_ALTERTABLE if( pOp->p4.z==0 ){ sqlite3SchemaClear(db->aDb[iDb].pSchema); db->mDbFlags &= ~DBFLAG_SchemaKnownOk; | | | 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 | assert( iDb>=0 && iDb<db->nDb ); assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); #ifndef SQLITE_OMIT_ALTERTABLE if( pOp->p4.z==0 ){ sqlite3SchemaClear(db->aDb[iDb].pSchema); db->mDbFlags &= ~DBFLAG_SchemaKnownOk; rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5); db->mDbFlags |= DBFLAG_SchemaChange; p->expired = 0; }else #endif { zSchema = DFLT_SCHEMA_TABLE; initData.db = db; |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
219 220 221 222 223 224 225 | # define sqlite3ExplainBreakpoint(A,B) /*no-op*/ #endif #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN) void sqlite3ExplainBreakpoint(const char*,const char*); #else # define sqlite3ExplainBreakpoint(A,B) /*no-op*/ #endif | | | 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | # define sqlite3ExplainBreakpoint(A,B) /*no-op*/ #endif #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN) void sqlite3ExplainBreakpoint(const char*,const char*); #else # define sqlite3ExplainBreakpoint(A,B) /*no-op*/ #endif void sqlite3VdbeAddParseSchemaOp(Vdbe*, int, char*, u16); void sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8); void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3); void sqlite3VdbeChangeP5(Vdbe*, u16 P5); void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeJumpHereOrPopInst(Vdbe*, int addr); |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
467 468 469 470 471 472 473 | ** Add an OP_ParseSchema opcode. This routine is broken out from ** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees ** as having been used. ** ** The zWhere string must have been obtained from sqlite3_malloc(). ** This routine will take ownership of the allocated memory. */ | | > | 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | ** Add an OP_ParseSchema opcode. This routine is broken out from ** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees ** as having been used. ** ** The zWhere string must have been obtained from sqlite3_malloc(). ** This routine will take ownership of the allocated memory. */ void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, u16 p5){ int j; sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC); sqlite3VdbeChangeP5(p, p5); for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j); sqlite3MayAbort(p->pParse); } /* ** Add an opcode that includes the p4 value as an integer. */ |
︙ | ︙ |
Changes to src/vtab.c.
︙ | ︙ | |||
485 486 487 488 489 490 491 | pParse->regRowid ); v = sqlite3GetVdbe(pParse); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp0(v, OP_Expire); zWhere = sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt); | | | 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | pParse->regRowid ); v = sqlite3GetVdbe(pParse); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp0(v, OP_Expire); zWhere = sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt); sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere, 0); sqlite3DbFree(db, zStmt); iReg = ++pParse->nMem; sqlite3VdbeLoadString(v, iReg, pTab->zName); sqlite3VdbeAddOp2(v, OP_VCreate, iDb, iReg); } |
︙ | ︙ | |||
656 657 658 659 660 661 662 663 664 665 666 667 668 669 | zType[j] = zType[j+nDel]; } if( zType[i]=='\0' && i>0 ){ assert(zType[i-1]==' '); zType[i-1] = '\0'; } pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN; oooHidden = TF_OOOHidden; }else{ pTab->tabFlags |= oooHidden; } } } } | > | 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 | zType[j] = zType[j+nDel]; } if( zType[i]=='\0' && i>0 ){ assert(zType[i-1]==' '); zType[i-1] = '\0'; } pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN; pTab->tabFlags |= TF_HasHidden; oooHidden = TF_OOOHidden; }else{ pTab->tabFlags |= oooHidden; } } } } |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
2950 2951 2952 2953 2954 2955 2956 | pWInfo = pBuilder->pWInfo; pTabList = pWInfo->pTabList; pSrc = pTabList->a + pNew->iTab; pTab = pSrc->pTab; pWC = pBuilder->pWC; assert( !IsVirtual(pSrc->pTab) ); | | | | 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 | pWInfo = pBuilder->pWInfo; pTabList = pWInfo->pTabList; pSrc = pTabList->a + pNew->iTab; pTab = pSrc->pTab; pWC = pBuilder->pWC; assert( !IsVirtual(pSrc->pTab) ); if( pSrc->fg.isIndexedBy ){ /* An INDEXED BY clause specifies a particular index to use */ pProbe = pSrc->u2.pIBIndex; }else if( !HasRowid(pTab) ){ pProbe = pTab->pIndex; }else{ /* There is no INDEXED BY clause. Create a fake Index object in local ** variable sPk to represent the rowid primary key index. Make this ** fake index the first in a chain of Index objects with all of the real ** indices to follow */ |
︙ | ︙ | |||
2988 2989 2990 2991 2992 2993 2994 | rLogSize = estLog(rSize); #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ if( !pBuilder->pOrSet /* Not part of an OR optimization */ && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 | | | 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 | rLogSize = estLog(rSize); #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ if( !pBuilder->pOrSet /* Not part of an OR optimization */ && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 && !pSrc->fg.isIndexedBy /* Has no INDEXED BY clause */ && !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */ && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */ && !pSrc->fg.isCorrelated /* Not a correlated subquery */ && !pSrc->fg.isRecursive /* Not a recursive common table expression. */ ){ /* Generate auto-index WhereLoops */ WhereTerm *pTerm; |
︙ | ︙ | |||
3038 3039 3040 3041 3042 3043 3044 | } } #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ /* Loop over all indices. If there was an INDEXED BY clause, then only ** consider index pProbe. */ for(; rc==SQLITE_OK && pProbe; | | | 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 | } } #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ /* Loop over all indices. If there was an INDEXED BY clause, then only ** consider index pProbe. */ for(; rc==SQLITE_OK && pProbe; pProbe=(pSrc->fg.isIndexedBy ? 0 : pProbe->pNext), iSortIdx++ ){ int isLeft = (pSrc->fg.jointype & JT_OUTER)!=0; if( pProbe->pPartIdxWhere!=0 && !whereUsablePartialIndex(pSrc->iCursor, isLeft, pWC, pProbe->pPartIdxWhere) ){ testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */ |
︙ | ︙ |
Changes to test/alterauth2.test.
︙ | ︙ | |||
90 91 92 93 94 95 96 97 98 | {SQLITE_READ sqlite_temp_master name temp {}} {SQLITE_READ sqlite_temp_master sql temp {}} {SQLITE_READ sqlite_temp_master type temp {}} {SQLITE_SELECT {} {} {} {}} {SQLITE_UPDATE sqlite_master sql main {}} {SQLITE_UPDATE sqlite_temp_master sql temp {}} } finish_test | > > > > > > > > > > > > > > > > > | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | {SQLITE_READ sqlite_temp_master name temp {}} {SQLITE_READ sqlite_temp_master sql temp {}} {SQLITE_READ sqlite_temp_master type temp {}} {SQLITE_SELECT {} {} {} {}} {SQLITE_UPDATE sqlite_master sql main {}} {SQLITE_UPDATE sqlite_temp_master sql temp {}} } do_auth_test 1.3 { ALTER TABLE t2 DROP COLUMN c; } { {SQLITE_FUNCTION {} like {} {}} {SQLITE_FUNCTION {} sqlite_drop_column {} {}} {SQLITE_FUNCTION {} sqlite_rename_test {} {}} {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 {}} {SQLITE_SELECT {} {} {} {}} {SQLITE_UPDATE sqlite_master sql main {}} } finish_test |
Added test/altercorrupt.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 50 51 52 53 54 55 56 57 58 59 60 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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | # 2019-01-11 # # 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. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix altercorrupt database_may_be_corrupt #-------------------------------------------------------------------------- reset_db do_test 1.0 { sqlite3 db {} db deserialize [decode_hexdb { .open --hexdb | size 24576 pagesize 4096 filename crash-685346d89b5e5f.db | page 1 offset 0 | 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3. | 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 06 .....@ ........ | 32: 00 00 63 00 00 05 f0 00 00 00 00 04 10 00 00 04 ..c............. | 48: 00 00 00 00 00 00 0f f0 00 00 00 01 00 00 00 00 ................ | 64: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | 96: 00 00 00 00 0d 0f f8 00 05 0e cf 00 0f 79 0f d3 .............y.. | 112: 0f 2e 0e f3 0e cf 00 00 00 00 00 00 00 00 00 00 ................ | 3776: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 ................ | 3792: 05 06 17 11 11 01 31 74 61 62 6c 65 74 34 74 34 ......1tablet4t4 | 3808: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 34 .CREATE TABLE t4 | 3824: 28 7a 29 39 04 06 17 11 11 01 5f 74 61 62 6c 65 (z)9......_table | 3840: 74 33 74 33 05 43 52 45 41 54 45 20 54 41 42 4c t3t3.CREATE TABL | 3856: 45 20 74 33 28 78 20 49 4e 54 45 47 45 52 20 50 E t3(x INTEGER P | 3872: 52 49 4d 41 52 59 20 4b 45 59 2c 20 79 29 49 03 RIMARY KEY, y)I. | 3888: 06 17 11 11 01 7f 74 61 62 6c 65 74 32 74 32 04 ......tablet2t2. | 3904: 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 32 28 CREATE TABLE t2( | 3920: 61 2c 62 2c 63 20 50 52 49 4d 41 52 59 20 4b 45 a,b,c PRIMARY KE | 3936: 59 2c 20 64 2c 20 65 2c 20 66 29 20 57 49 54 48 Y, d, e, f) WITH | 3952: 4f 55 54 20 52 4f 57 49 44 58 03 07 17 11 11 01 OUT ROWIDX...... | 3968: 81 1b 74 61 62 6c 65 74 31 74 31 02 43 52 45 41 ..tablet1t1.CREA | 3984: 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 2c TE TABLE t1(a,b, | 4000: 63 20 41 53 20 28 2d 62 29 20 56 49 52 54 55 41 c AS (-b) VIRTUA | 4016: 4c 2c 64 20 43 48 45 43 4b 28 64 3e 35 29 2c 65 L,d CHECK(d>5),e | 4032: 20 55 4e 49 51 55 45 2c 20 66 20 41 53 20 28 2b UNIQUE, f AS (+ | 4048: 62 29 29 23 02 06 17 37 11 01 00 69 6e 64 65 78 b))#...7...index | 4064: 73 71 6c 69 74 65 5f 61 75 74 6f 69 6e 64 65 78 sqlite_autoindex | 4080: 5f 74 31 5f 31 74 31 03 00 00 00 08 00 00 00 00 _t1_1t1......... | page 2 offset 4096 | 0: 0d 00 00 00 0a 0f 93 00 0f f6 0f eb 0f e0 0f d5 ................ | 16: 0f ca 0f 8f 0f b4 0f a9 0f 9e 0f 93 00 00 00 00 ................ | 3984: 00 00 00 09 0a 05 01 01 01 01 0a 64 6e 14 09 09 ...........dn... | 4000: 05 01 01 01 01 09 5a 6d 12 09 08 05 01 01 01 01 ......Zm........ | 4016: 08 50 6c 10 09 07 05 01 01 01 01 07 46 6b 0e 09 .Pl.........Fk.. | 4032: 06 05 01 01 01 01 06 3c 6a 0c 09 05 05 01 01 01 .......<j....... | 4048: 01 05 32 69 0a 09 04 05 01 01 01 01 04 28 68 08 ..2i.........(h. | 4064: 09 03 05 01 01 01 01 03 1e 67 06 09 02 05 01 01 .........g...... | 4080: 01 01 02 14 66 04 08 01 05 09 01 01 01 0a 65 02 ....f.........e. | page 3 offset 8192 | 0: 0a 00 00 00 0a 0f c5 00 0f fb 0f f5 0f ef 0f e9 ................ | 16: 0f e3 0f dd 0f d7 0f d1 0f cb 0f c5 00 00 00 00 ................ | 4032: 00 00 00 00 00 05 03 01 01 14 0a 05 03 01 01 12 ................ | 4048: 09 05 03 01 01 10 08 05 03 01 01 0e 07 05 03 01 ................ | 4064: 01 0c 06 05 03 01 01 0a 05 05 03 01 01 08 04 05 ................ | 4080: 03 01 01 06 03 05 03 01 01 04 02 04 03 01 09 02 ................ | page 4 offset 12288 | 0: 0a 00 00 00 0a 0f 75 00 0f 75 0f 83 0f 91 0f 9f ......u..u...... | 16: 0f ad 0f bb 0f 00 00 00 00 00 00 00 00 00 00 00 ................ | 3952: 00 00 00 00 00 0d 07 01 01 01 01 01 01 9c 0a 64 ...............d | 3968: 6e 14 64 0d 07 02 01 01 01 01 01 a6 09 5a 6d 12 n.d..........Zm. | 3984: 5a 0d 07 01 01 01 01 01 01 b0 08 50 6c 10 50 0d Z..........Pl.P. | 4000: 07 01 01 01 01 01 01 ba 07 46 6b 0e 46 0d 07 01 .........Fk.F... | 4016: 01 01 01 01 01 c4 06 3c 6a 0c 3c 0d 07 01 01 01 .......<j.<..... | 4032: 01 01 01 ce 05 32 69 0a 32 0d 07 01 01 01 01 01 .....2i.2....... | 4048: 01 d8 04 28 68 08 28 0d 07 01 01 01 01 01 01 e2 ...(h.(......... | 4064: 03 1e 67 06 1e 0d 07 01 01 01 01 01 01 ec 02 14 ..g............. | 4080: 66 04 14 0c 07 01 09 01 01 01 01 f6 0a 65 02 0a f............e.. | page 5 offset 16384 | 0: 0d 00 00 00 03 0f e9 00 0f e9 0f fb 0f f6 00 00 ................ | 16: 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | 4064: 00 00 00 00 00 00 00 00 00 03 ff ff ff ff ff ff ................ | 4080: ff ff 9c 03 00 00 03 64 03 00 00 03 01 03 00 00 .......d........ | page 6 offset 20480 | 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................ | end crash-685346d89b5e5f.db }]} {} do_execsql_test 1.1 { ALTER TABLE t2 DROP COLUMN e; } do_catchsql_test 1.2 { ALTER TABLE t1 DROP COLUMN f; } {1 {database disk image is malformed}} #-------------------------------------------------------------------------- reset_db do_test 2.0 { sqlite3 db {} db deserialize [decode_hexdb { .open --hexdb | size 24576 pagesize 4096 filename crash-0572db8f391431.db | page 1 offset 0 | 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3. | 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 06 .....@ ........ | 32: 00 00 63 00 10 05 f0 00 00 00 00 04 10 00 00 04 ..c............. | 48: 00 00 00 00 00 00 0f f0 00 00 00 00 00 00 00 00 ................ | 96: 00 00 00 00 0d 0f f8 00 05 0e cf 00 0f 79 0f d3 .............y.. | 112: 0f 2e 0e f3 0e cf 00 00 00 00 00 00 00 00 00 00 ................ | 3776: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 ................ | 3792: 05 06 17 11 11 01 31 74 61 62 6c 65 74 34 74 34 ......1tablet4t4 | 3808: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 34 .CREATE TABLE t4 | 3824: 28 7a 29 39 04 06 17 11 11 01 5f 74 61 62 6c 65 (z)9......_table | 3840: 74 33 74 33 05 43 52 45 41 54 45 20 54 41 42 4c t3t3.CREATE TABL | 3856: 45 20 74 33 28 78 20 49 4e 54 55 47 45 52 20 50 E t3(x INTUGER P | 3872: 52 49 4d 41 52 59 20 4b 45 59 2c 20 79 29 49 03 RIMARY KEY, y)I. | 3888: 06 17 11 11 01 7f 74 61 62 6c 65 74 32 74 32 04 ......tablet2t2. | 3904: 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 32 28 CREATE TABLE t2( | 3920: 61 2c 62 2c 63 20 50 52 49 4d 41 52 59 20 4b 45 a,b,c PRIMARY KE | 3936: 59 2c 20 64 2c 20 65 2c 20 66 29 20 57 49 54 48 Y, d, e, f) WITH | 3952: 4f 55 54 20 52 4f 57 49 44 58 05 07 17 11 11 01 OUT ROWIDX...... | 3968: 81 1b 74 61 62 6c 65 74 31 74 31 02 43 52 45 41 ..tablet1t1.CREA | 3984: 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 2c TE TABLE t1(a,b, | 4000: 63 20 41 53 20 28 2d 62 29 20 56 49 52 54 55 41 c AS (-b) VIRTUA | 4016: 4c 2c 64 20 43 48 45 43 4b 28 64 3e 35 29 2c 65 L,d CHECK(d>5),e | 4032: 20 55 4e 49 51 55 45 2c 20 66 20 41 53 20 28 2b UNIQUE, f AS (+ | 4048: 62 29 29 23 02 06 17 37 11 01 00 69 6e 64 65 78 b))#...7...index | 4064: 73 71 6c 69 74 65 5f 61 75 74 6f 69 6e 64 65 78 sqlite_autoindex | 4080: 5f 74 31 5f 31 84 31 03 01 00 00 08 00 00 00 00 _t1_1.1......... | page 2 offset 4096 | 0: 0d 00 00 00 0a 0f 93 00 0f f6 0f eb 0f e0 0f d5 ................ | 16: 0f ca 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | 3984: 00 00 00 09 0a 05 01 01 01 01 0a 64 6e 14 09 09 ...........dn... | 4000: 05 01 01 01 01 09 5a 6d 12 09 08 05 01 00 f1 01 ......Zm........ | 4016: 08 50 6c 10 09 07 05 01 01 01 01 07 46 6b 0e 09 .Pl.........Fk.. | 4032: 06 05 01 00 f1 01 06 3c 6a 0c 09 05 05 01 01 01 .......<j....... | 4048: 01 05 32 69 0a 09 04 05 01 01 01 01 04 28 68 08 ..2i.........(h. | 4064: 57 03 05 01 01 01 01 03 1e 67 06 09 02 05 01 01 W........g...... | 4080: 01 01 02 14 66 04 08 01 05 09 01 01 01 0a 65 02 ....f.........e. | page 3 offset 8192 | 0: 09 ff ff ff fa 0f c5 00 0f fb 0f f5 0f ef 0f e9 ................ | 16: 0f e3 0f dd 0f d7 00 00 00 00 00 00 00 00 00 00 ................ | 4032: 00 00 00 00 00 05 03 01 01 14 0a 05 03 01 01 12 ................ | 4048: 09 05 03 01 01 10 08 05 03 01 01 0e 07 05 03 01 ................ | 4064: 01 0c 06 05 03 01 01 0a 05 05 03 01 01 08 04 05 ................ | 4080: 03 01 01 06 03 05 03 01 01 04 02 04 03 01 09 02 ................ | page 4 offset 12288 | 0: 0a 00 00 00 0a 0f 75 00 0f 75 0f 83 0f 91 0f 9f ......u..u...... | 16: 0f ad 0f bb 0f 00 00 00 00 00 01 00 00 00 00 00 ................ | 3952: 00 00 00 00 00 0d 07 01 01 01 01 01 01 9c 0a 64 ...............d | 3968: 6e 14 64 0d 07 02 01 01 01 01 01 a6 09 5a 6d 12 n.d..........Zm. | 3984: 5a 0d 07 01 01 01 01 d4 01 b0 08 50 6c 10 50 0d Z..........Pl.P. | 4000: 07 01 01 01 01 01 01 ba 07 46 6b 0e 46 0d 07 00 .........Fk.F... | 4016: 01 01 01 01 01 c4 06 3c 6a 0c 3c 0d 07 01 01 01 .......<j.<..... | 4032: 01 01 01 ce 05 32 69 0a 32 0d 07 01 01 01 01 01 .....2i.2....... | 4048: 01 d8 04 28 68 08 28 0d 07 01 01 01 01 01 01 e2 ...(h.(......... | 4064: 03 1e 67 06 1e 0d 07 01 01 01 01 01 01 ec 02 14 ..g............. | 4080: 66 04 14 0c 07 01 09 01 01 00 f1 f6 0a 65 02 0a f............e.. | page 5 offset 16384 | 0: 0d 00 00 00 03 0f e9 00 0f e9 0f fb 0f f6 00 00 ................ | 4064: 00 00 00 00 00 00 00 00 00 03 ff ff ff ff ff ff ................ | 4080: ff ff 9c 03 00 00 03 64 03 00 01 03 01 03 00 00 .......d........ | page 6 offset 20480 | 0: 0d 00 10 00 00 10 01 00 00 00 00 00 00 00 00 00 ................ | end crash-0572db8f391431.db }]} {} do_catchsql_test 2.1 { ALTER TABLE t1 DROP COLUMN a; } {1 {database disk image is malformed}} finish_test |
Added test/alterdropcol.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 50 51 52 53 54 55 56 57 58 59 60 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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | # 2021 February 16 # # 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. # #************************************************************************* # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix alterdropcol # If SQLITE_OMIT_ALTERTABLE is defined, omit this file. ifcapable !altertable { finish_test return } do_execsql_test 1.0 { CREATE TABLE t1(a, b, c); CREATE VIEW v1 AS SELECT * FROM t1; CREATE TABLE t2(x INTEGER PRIMARY KEY, y, z UNIQUE); CREATE INDEX t2y ON t2(y); CREATE TABLE t3(q, r, s); CREATE INDEX t3rs ON t3(r+s); } do_catchsql_test 1.1 { ALTER TABLE nosuch DROP COLUMN z; } {1 {no such table: nosuch}} do_catchsql_test 1.2 { ALTER TABLE v1 DROP COLUMN c; } {1 {cannot drop column from view "v1"}} ifcapable fts5 { do_execsql_test 1.3.1 { CREATE VIRTUAL TABLE ft1 USING fts5(one, two); } do_catchsql_test 1.3.2 { ALTER TABLE ft1 DROP COLUMN two; } {1 {cannot drop column from virtual table "ft1"}} } do_catchsql_test 1.4 { ALTER TABLE sqlite_schema DROP COLUMN sql; } {1 {table sqlite_master may not be altered}} do_catchsql_test 1.5 { ALTER TABLE t1 DROP COLUMN d; } {1 {no such column: "d"}} do_execsql_test 1.6.1 { ALTER TABLE t1 DROP COLUMN b; } do_execsql_test 1.6.2 { SELECT sql FROM sqlite_schema WHERE name = 't1' } {{CREATE TABLE t1(a, c)}} do_execsql_test 1.7.1 { ALTER TABLE t1 DROP COLUMN c; } do_execsql_test 1.7.2 { SELECT sql FROM sqlite_schema WHERE name = 't1' } {{CREATE TABLE t1(a)}} do_catchsql_test 1.7.3 { ALTER TABLE t1 DROP COLUMN a; } {1 {cannot drop column "a": no other columns exist}} do_catchsql_test 1.8 { ALTER TABLE t2 DROP COLUMN z } {1 {cannot drop UNIQUE column: "z"}} do_catchsql_test 1.9 { ALTER TABLE t2 DROP COLUMN x } {1 {cannot drop PRIMARY KEY column: "x"}} do_catchsql_test 1.10 { ALTER TABLE t2 DROP COLUMN y } {1 {error in index t2y after drop column: no such column: y}} do_catchsql_test 1.11 { ALTER TABLE t3 DROP COLUMN s } {1 {error in index t3rs after drop column: no such column: s}} #------------------------------------------------------------------------- foreach {tn wo} { 1 {} 2 {WITHOUT ROWID} } { eval [string map [list %TN% $tn %WO% $wo] { reset_db do_execsql_test 2.%TN%.0 { CREATE TABLE t1(x, y INTEGER PRIMARY KEY, z) %WO% ; INSERT INTO t1 VALUES(1, 2, 3); INSERT INTO t1 VALUES(4, 5, 6); INSERT INTO t1 VALUES(7, 8, 9); } do_execsql_test 2.%TN%.1 { ALTER TABLE t1 DROP COLUMN x; SELECT * FROM t1; } { 2 3 5 6 8 9 } do_execsql_test 2.%TN%.2 { ALTER TABLE t1 DROP COLUMN z; SELECT * FROM t1; } { 2 5 8 } }]} #------------------------------------------------------------------------- reset_db do_execsql_test 3.0 { CREATE TABLE t12(a, b, c, CHECK(c>10)); CREATE TABLE t13(a, b, c CHECK(c>10)); } do_catchsql_test 3.1 { ALTER TABLE t12 DROP COLUMN c; } {1 {error in table t12 after drop column: no such column: c}} do_catchsql_test 3.2 { ALTER TABLE t13 DROP COLUMN c; } {0 {}} #------------------------------------------------------------------------- # Test that generated columns can be dropped. And that other columns from # tables that contain generated columns can be dropped. # foreach {tn wo vs} { 1 "" "" 2 "" VIRTUAL 3 "" STORED 4 "WITHOUT ROWID" STORED 5 "WITHOUT ROWID" VIRTUAL } { reset_db do_execsql_test 4.$tn.0 " CREATE TABLE 'my table'(a, b PRIMARY KEY, c AS (a+b) $vs, d) $wo " do_execsql_test 4.$tn.1 { INSERT INTO "my table"(a, b, d) VALUES(1, 2, 'hello'); INSERT INTO "my table"(a, b, d) VALUES(3, 4, 'world'); SELECT * FROM "my table" } { 1 2 3 hello 3 4 7 world } do_execsql_test 4.$tn.2 { ALTER TABLE "my table" DROP COLUMN c; } do_execsql_test 4.$tn.3 { SELECT * FROM "my table" } { 1 2 hello 3 4 world } do_execsql_test 4.$tn.4 " CREATE TABLE x1(a, b, c PRIMARY KEY, d AS (b+c) $vs, e) $wo " do_execsql_test 4.$tn.5 { INSERT INTO x1(a, b, c, e) VALUES(1, 2, 3, 4); INSERT INTO x1(a, b, c, e) VALUES(5, 6, 7, 8); INSERT INTO x1(a, b, c, e) VALUES(9, 10, 11, 12); SELECT * FROM x1; } { 1 2 3 5 4 5 6 7 13 8 9 10 11 21 12 } do_execsql_test 4.$tn.6 { ALTER TABLE x1 DROP COLUMN a } do_execsql_test 4.$tn.7 { SELECT * FROM x1 } { 2 3 5 4 6 7 13 8 10 11 21 12 } do_execsql_test 4.$tn.8 { ALTER TABLE x1 DROP COLUMN e } do_execsql_test 4.$tn.9 { SELECT * FROM x1 } { 2 3 5 6 7 13 10 11 21 } } #------------------------------------------------------------------------- reset_db do_execsql_test 5.0 { CREATE TABLE p1(a PRIMARY KEY, b UNIQUE); CREATE TABLE c1(x, y, z REFERENCES p1(c)); CREATE TABLE c2(x, y, z, w REFERENCES p1(b)); } do_execsql_test 5.1 { ALTER TABLE c1 DROP COLUMN z; ALTER TABLE c2 DROP COLUMN z; SELECT sql FROM sqlite_schema WHERE name IN ('c1', 'c2'); } { {CREATE TABLE c1(x, y)} {CREATE TABLE c2(x, y, w REFERENCES p1(b))} } do_execsql_test 5.2.1 { CREATE VIEW v1 AS SELECT d, e FROM p1 } do_catchsql_test 5.2.2 { ALTER TABLE c1 DROP COLUMN x } {1 {error in view v1: no such column: d}} do_execsql_test 5.3.1 { DROP VIEW v1; CREATE VIEW v1 AS SELECT x, y FROM c1; } do_catchsql_test 5.3.2 { ALTER TABLE c1 DROP COLUMN x } {1 {error in view v1 after drop column: no such column: x}} do_execsql_test 5.4.1 { CREATE TRIGGER tr AFTER INSERT ON c1 BEGIN INSERT INTO p1 VALUES(new.y, new.xyz); END; } do_catchsql_test 5.4.2 { ALTER TABLE c1 DROP COLUMN y } {1 {error in trigger tr: no such column: new.xyz}} do_execsql_test 5.5.1 { DROP TRIGGER tr; CREATE TRIGGER tr AFTER INSERT ON c1 BEGIN INSERT INTO p1 VALUES(new.y, new.z); END; } do_catchsql_test 5.5.2 { ALTER TABLE c1 DROP COLUMN y } {1 {error in trigger tr: no such column: new.z}} finish_test |
Added test/alterdropcol2.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 50 51 52 53 54 55 56 57 58 59 60 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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | # 2021 February 19 # # 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. # #************************************************************************* # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix alterdropcol2 # If SQLITE_OMIT_ALTERTABLE is defined, omit this file. ifcapable !altertable { finish_test return } # EVIDENCE-OF: R-58318-35349 The DROP COLUMN syntax is used to remove an # existing column from a table. do_execsql_test 1.0 { CREATE TABLE t1(c, b, a, PRIMARY KEY(b, a)) WITHOUT ROWID; INSERT INTO t1 VALUES(1, 2, 3), (4, 5, 6); } do_execsql_test 1.1 { ALTER TABLE t1 DROP c; } # EVIDENCE-OF: The DROP COLUMN command removes the named column from the table, # and also rewrites the entire table to purge the data associated with that # column. do_execsql_test 1.2.1 { SELECT * FROM t1; } {2 3 5 6} do_execsql_test 1.2.2 { SELECT sql FROM sqlite_schema; } { {CREATE TABLE t1(b, a, PRIMARY KEY(b, a)) WITHOUT ROWID} } proc do_atdc_error_test {tn schema atdc error} { reset_db execsql $schema uplevel [list do_catchsql_test $tn $atdc [list 1 [string trim $error]]] } #------------------------------------------------------------------------- # Test cases 2.* attempt to verify the following: # # EVIDENCE-OF: R-24098-10282 The DROP COLUMN command only works if the column # is not referenced by any other parts of the schema and is not a PRIMARY KEY # and does not have a UNIQUE constraint. # # EVIDENCE-OF: R-05184-13006 The column is a PRIMARY KEY. # do_atdc_error_test 2.1.1 { CREATE TABLE x1(a PRIMARY KEY, b, c); } { ALTER TABLE x1 DROP COLUMN a } { cannot drop PRIMARY KEY column: "a" } # EVIDENCE-OF: R-43412-16016 The column has a UNIQUE constraint. # do_atdc_error_test 2.2.1 { CREATE TABLE x1(a PRIMARY KEY, b, c UNIQUE); } { ALTER TABLE x1 DROP COLUMN c } { cannot drop UNIQUE column: "c" } do_atdc_error_test 2.2.2 { CREATE TABLE x1(a PRIMARY KEY, b, c, UNIQUE(b, c)); } { ALTER TABLE x1 DROP COLUMN c } { error in table x1 after drop column: no such column: c } # EVIDENCE-OF: R-46731-08965: The column is indexed. # do_atdc_error_test 2.3.1 { CREATE TABLE 'one two'('x y', 'z 1', 'a b'); CREATE INDEX idx ON 'one two'('z 1'); } { ALTER TABLE 'one two' DROP COLUMN 'z 1' } { error in index idx after drop column: no such column: z 1 } do_atdc_error_test 2.3.2 { CREATE TABLE x1(a, b, c); CREATE INDEX idx ON x1(a); } { ALTER TABLE x1 DROP COLUMN a; } { error in index idx after drop column: no such column: a } # EVIDENCE-OF: R-46731-08965: The column is indexed. # do_atdc_error_test 2.4.1 { CREATE TABLE x1234(a, b, c PRIMARY KEY) WITHOUT ROWID; CREATE INDEX i1 ON x1234(b) WHERE ((a+5) % 10)==0; } { ALTER TABLE x1234 DROP a } { error in index i1 after drop column: no such column: a } # EVIDENCE-OF: R-18825-17786 The column appears in a table CHECK constraint. # do_atdc_error_test 2.5.1 { CREATE TABLE x1234(a, b, c PRIMARY KEY, CHECK(((a+5)%10)!=0)) WITHOUT ROWID; } { ALTER TABLE x1234 DROP a } { error in table x1234 after drop column: no such column: a } # EVIDENCE-OF: R-55640-01652 The column is used in a foreign key constraint. # do_atdc_error_test 2.6.1 { CREATE TABLE p1(x, y UNIQUE); CREATE TABLE c1(u, v, FOREIGN KEY (v) REFERENCES p1(y)) } { ALTER TABLE c1 DROP v } { error in table c1 after drop column: unknown column "v" in foreign key definition } # EVIDENCE-OF: R-20795-39479 The column is used in the expression of a # generated column. do_atdc_error_test 2.7.1 { CREATE TABLE c1(u, v, w AS (u+v)); } { ALTER TABLE c1 DROP v } { error in table c1 after drop column: no such column: v } do_atdc_error_test 2.7.2 { CREATE TABLE c1(u, v, w AS (u+v) STORED); } { ALTER TABLE c1 DROP u } { error in table c1 after drop column: no such column: u } # EVIDENCE-OF: R-01515-49025 The column appears in a trigger or view. # do_atdc_error_test 2.8.1 { CREATE TABLE log(l); CREATE TABLE c1(u, v, w); CREATE TRIGGER tr1 AFTER INSERT ON c1 BEGIN INSERT INTO log VALUES(new.w); END; } { ALTER TABLE c1 DROP w } { error in trigger tr1 after drop column: no such column: new.w } do_atdc_error_test 2.8.2 { CREATE TABLE c1(u, v, w); CREATE VIEW v1 AS SELECT u, v, w FROM c1; } { ALTER TABLE c1 DROP w } { error in view v1 after drop column: no such column: w } do_atdc_error_test 2.8.3 { CREATE TABLE c1(u, v, w); CREATE VIEW v1 AS SELECT * FROM c1 WHERE w IS NOT NULL; } { ALTER TABLE c1 DROP w } { error in view v1 after drop column: no such column: w } #------------------------------------------------------------------------- # Verify that a column that is part of a CHECK constraint may be dropped # if the CHECK constraint was specified as part of the column definition. # # EVIDENCE-OF: R-60924-11170 However, the column being deleted can be used in a # column CHECK constraint because the column CHECK constraint is dropped # together with the column itself. do_execsql_test 3.0 { CREATE TABLE yyy(q, w, e CHECK (e > 0), r); INSERT INTO yyy VALUES(1,1,1,1), (2,2,2,2); CREATE TABLE zzz(q, w, e, r, CHECK (e > 0)); INSERT INTO zzz VALUES(1,1,1,1), (2,2,2,2); } do_catchsql_test 3.1.1 { INSERT INTO yyy VALUES(0,0,0,0); } {1 {CHECK constraint failed: e > 0}} do_catchsql_test 3.1.2 { INSERT INTO yyy VALUES(0,0,0,0); } {1 {CHECK constraint failed: e > 0}} do_execsql_test 3.2.1 { ALTER TABLE yyy DROP e; } do_catchsql_test 3.2.2 { ALTER TABLE zzz DROP e; } {1 {error in table zzz after drop column: no such column: e}} finish_test |
Changes to test/alterlegacy.test.
︙ | ︙ | |||
36 37 38 39 40 41 42 | } # Legacy behavior is to corrupt the schema in this case, as the table name in # the CHECK constraint is incorrect after "t1" is renamed. This version is # slightly different - it rejects the change and rolls back the transaction. do_catchsql_test 1.2 { ALTER TABLE t1 RENAME TO t1new; | | | | 36 37 38 39 40 41 42 43 44 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 | } # Legacy behavior is to corrupt the schema in this case, as the table name in # the CHECK constraint is incorrect after "t1" is renamed. This version is # slightly different - it rejects the change and rolls back the transaction. do_catchsql_test 1.2 { ALTER TABLE t1 RENAME TO t1new; } {1 {error in table t1new after rename: no such column: t1.a}} do_execsql_test 1.3 { CREATE TABLE t3(c, d); ALTER TABLE t3 RENAME TO t3new; DROP TABLE t3new; } do_execsql_test 1.4 { SELECT sql FROM sqlite_master } { {CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))} {CREATE TABLE t2(a, b)} {CREATE INDEX t2expr ON t2(a) WHERE t2.b>0} } do_catchsql_test 1.3 { ALTER TABLE t2 RENAME TO t2new; } {1 {error in index t2expr after rename: no such column: t2.b}} do_execsql_test 1.4 { SELECT sql FROM sqlite_master } { {CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))} {CREATE TABLE t2(a, b)} {CREATE INDEX t2expr ON t2(a) WHERE t2.b>0} } |
︙ | ︙ |
Added test/altermalloc3.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 | # 2021 February 18 # # 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. # #************************************************************************* # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl set testprefix altermalloc3 # If SQLITE_OMIT_ALTERTABLE is defined, omit this file. ifcapable !altertable { finish_test return } do_execsql_test 1.0 { CREATE TABLE t1(a, b, c, d, PRIMARY KEY(d, b)) WITHOUT ROWID; INSERT INTO t1 VALUES(1, 2, 3, 4); } faultsim_save_and_close do_faultsim_test 1 -prep { faultsim_restore_and_reopen } -body { execsql { ALTER TABLE t1 DROP COLUMN c } } -test { faultsim_test_result {0 {}} } finish_test |
Changes to test/fts4rename.test.
︙ | ︙ | |||
25 26 27 28 29 30 31 | CREATE VIRTUAL TABLE temp.t1 USING fts3(a); BEGIN; CREATE TABLE t2(x); } {} do_catchsql_test 1.1 { ALTER TABLE t1_content RENAME c0a TO docid; | | | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | CREATE VIRTUAL TABLE temp.t1 USING fts3(a); BEGIN; CREATE TABLE t2(x); } {} do_catchsql_test 1.1 { ALTER TABLE t1_content RENAME c0a TO docid; } {1 {error in table t1_content after rename: duplicate column name: docid}} do_catchsql_test 1.2 { UPDATE t1 SET Col0 = 1 ; } {1 {no such column: Col0}} do_catchsql_test 1.3 { ROLLBACK; |
︙ | ︙ |
Changes to test/hook.test.
︙ | ︙ | |||
952 953 954 955 956 957 958 | preupdate {DELETE main sqlite_stat1 1 1} preupdate {DELETE main sqlite_stat1 2 2} preupdate {INSERT main sqlite_stat1 1 1} preupdate {INSERT main sqlite_stat1 2 2} }] } | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 | preupdate {DELETE main sqlite_stat1 1 1} preupdate {DELETE main sqlite_stat1 2 2} preupdate {INSERT main sqlite_stat1 1 1} preupdate {INSERT main sqlite_stat1 2 2} }] } #------------------------------------------------------------------------- # Test that the pre-update hook is fired for INSERT statements that use # the xfer optimization on without rowid tables. # reset_db do_execsql_test 12.1 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b); CREATE TABLE t2(a INTEGER PRIMARY KEY, b) WITHOUT ROWID; INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t2 VALUES(5, 6); INSERT INTO t2 VALUES(7, 8); CREATE TABLE t3 (a INTEGER PRIMARY KEY, b) WITHOUT ROWID; } db preupdate hook preupdate_cb db update_hook update_cb proc preupdate_cb {args} { lappend ::res "preupdate" $args } proc update_cb {args} { lappend ::res "update" $args } set ::res [list] do_test 12.2 { execsql VACUUM set ::res } {} do_test 12.3 { set ::res [list] execsql { INSERT INTO t3 SELECT a, b FROM t2 } set ::res } {preupdate {INSERT main t3 0 0} preupdate {INSERT main t3 0 0}} do_test 12.4 { execsql { DELETE FROM t3 } set ::res [list] execsql { INSERT INTO t3 SELECT * FROM t2 } set ::res } {preupdate {INSERT main t3 0 0} preupdate {INSERT main t3 0 0}} do_execsql_test 12.5 { CREATE TABLE t4(a COLLATE nocase PRIMARY KEY, b) WITHOUT ROWID; INSERT INTO t4 VALUES('abc', 1); INSERT INTO t4 VALUES('DEF', 2); } set ::res [list] do_test 12.6 { execsql VACUUM set ::res } {} do_catchsql_test 12.6 { INSERT INTO t4 VALUES('def', 3); } {1 {UNIQUE constraint failed: t4.a}} finish_test |