Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix legacy comments on Token. Begin commenting the new ALTER TABLE RENAME COLUMN code. Fix a memory leak in the sqlite_rename_column() SQL function. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | alter-table-rename-column |
Files: | files | file ages | folders |
SHA3-256: |
32edc8920376aabb84ebe1900eaa9512 |
User & Date: | drh 2018-08-13 15:09:48.567 |
Context
2018-08-13
| ||
17:14 | Edit the WHEN and UPDATE OF clauses of trigger programs as part of ALTER TABLE RENAME COLUMN. (check-in: 5fdb6b0aaf user: dan tags: edit-trigger-wrapper) | |
17:02 | Make the sqlite_rename_column() SQL function resistant to problems caused by OOMs and/or malformed parameters submitted by hostile application code. Also add additional comments to the RENAME COLUMN logic. (check-in: 87743ddef1 user: drh tags: alter-table-rename-column) | |
15:09 | Fix legacy comments on Token. Begin commenting the new ALTER TABLE RENAME COLUMN code. Fix a memory leak in the sqlite_rename_column() SQL function. (check-in: 32edc89203 user: drh tags: alter-table-rename-column) | |
13:43 | Fix issues with ALTER TABLE RENAME COLUMN associated with OOM errors. (check-in: 0b28dd5c2e user: drh tags: alter-table-rename-column) | |
Changes
Changes to src/alter.c.
︙ | ︙ | |||
786 787 788 789 790 791 792 793 | sqlite3ChangeCookie(pParse, iDb); exit_begin_add_column: sqlite3SrcListDelete(db, pSrc); return; } void sqlite3AlterRenameColumn( | > > > > > | | | | | | | | | | > > > | > > > > > > > | 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 | sqlite3ChangeCookie(pParse, iDb); exit_begin_add_column: sqlite3SrcListDelete(db, pSrc); return; } /* ** Handles the following parser reduction: ** ** cmd ::= ALTER TABLE pSrc RENAME COLUMN pOld TO pNew */ void sqlite3AlterRenameColumn( Parse *pParse, /* Parsing context */ SrcList *pSrc, /* Table being altered. pSrc->nSrc==1 */ Token *pOld, /* Name of column being changed */ Token *pNew /* New column name */ ){ sqlite3 *db = pParse->db; /* Database connection */ Table *pTab; /* Table being updated */ int iCol; /* Index of column being renamed */ char *zOld = 0; /* Old column name */ char *zNew = 0; /* New column name */ const char *zDb; /* Name of schema containing the table */ int iSchema; /* Index of the schema */ int bQuote; /* True to quote the new name */ /* Locate the table to be altered */ pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_rename_column; /* Cannot alter a system table */ if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ) 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; /* Make sure the old name really is a column name in the table to be ** altered. Set iCol to be the index of the column being renamed */ zOld = sqlite3NameFromToken(db, pOld); if( !zOld ) goto exit_rename_column; for(iCol=0; iCol<pTab->nCol; iCol++){ if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break; } if( iCol==pTab->nCol ){ sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld); goto exit_rename_column; } /* Do the rename operation using a recursive UPDATE statement that ** uses the sqlite_rename_column() SQL function to compute the new ** CREATE statement text for the sqlite_master table. */ zNew = sqlite3NameFromToken(db, pNew); if( !zNew ) goto exit_rename_column; assert( pNew->n>0 ); bQuote = sqlite3Isquote(pNew->z[0]); sqlite3NestedParse(pParse, "UPDATE \"%w\".%s SET " "sql = sqlite_rename_column(sql, %d, %d, %Q, %Q, %Q) " |
︙ | ︙ | |||
845 846 847 848 849 850 851 852 | exit_rename_column: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zOld); sqlite3DbFree(db, zNew); return; } struct RenameToken { | > > > > > > > > > > > > > > > > > | | | > > > > > > > > > > > > > > > > | 860 861 862 863 864 865 866 867 868 869 870 871 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 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 | exit_rename_column: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zOld); sqlite3DbFree(db, zNew); return; } /* ** Each RenameToken object maps an element of the parse tree into ** the token that generated that element. The parse tree element ** might be one of: ** ** * A pointer to an Expr that represents an ID ** * The name of a table column in Column.zName ** ** A list of RenameToken objects can be constructed during parsing. ** Each new object is created by sqlite3RenameToken(). ** As the parse tree is transformed, the sqlite3MoveRenameToken() ** routine is used to keep the mapping current. ** ** After the parse finishes, renameTokenFind() routine can be used ** to look up the actual token value that created some element in ** the parse tree. */ struct RenameToken { void *p; /* Parse tree element created by token t */ Token t; /* The token that created parse tree element p */ RenameToken *pNext; /* Next is a list of all RenameToken objects */ }; /* ** The context of an ALTER TABLE RENAME COLUMN operation that gets passed ** down into the Walker. */ struct RenameCtx { RenameToken *pList; /* List of tokens to overwrite */ int nList; /* Number of tokens in pList */ int iCol; /* Index of column being renamed */ }; /* ** Add a new RenameToken object mapping parse tree element pPtr into ** token *pToken to the Parse object currently under construction. */ void sqlite3RenameToken(Parse *pParse, void *pPtr, Token *pToken){ RenameToken *pNew; pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken)); if( pNew ){ pNew->p = pPtr; pNew->t = *pToken; pNew->pNext = pParse->pRename; pParse->pRename = pNew; } } /* ** If there is a RenameToken object associated with parse tree element ** pFrom, then remap that object over to pTo due to a transformation ** in the parse tree. */ void sqlite3MoveRenameToken(Parse *pParse, void *pTo, void *pFrom){ RenameToken *p; for(p=pParse->pRename; p; p=p->pNext){ if( p->p==pFrom ){ p->p = pTo; break; } } assert( p ); } /* ** Free the list of RenameToken objects given in the second argument */ static void renameTokenFree(sqlite3 *db, RenameToken *pToken){ RenameToken *pNext; RenameToken *p; for(p=pToken; p; p=pNext){ pNext = p->pNext; sqlite3DbFree(db, p); } |
︙ | ︙ | |||
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 | renameColumnFunc_done: if( sParse.pVdbe ){ sqlite3VdbeFinalize(sParse.pVdbe); } sqlite3DeleteTable(db, sParse.pNewTable); if( sParse.pNewIndex ) sqlite3FreeIndex(db, sParse.pNewIndex); renameTokenFree(db, sParse.pRename); sqlite3ParserReset(&sParse); sqlite3_free(zQuot); } /* ** Register built-in functions used to help implement ALTER TABLE */ | > | 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 | renameColumnFunc_done: if( sParse.pVdbe ){ sqlite3VdbeFinalize(sParse.pVdbe); } sqlite3DeleteTable(db, sParse.pNewTable); if( sParse.pNewIndex ) sqlite3FreeIndex(db, sParse.pNewIndex); renameTokenFree(db, sParse.pRename); renameTokenFree(db, sCtx.pList); sqlite3ParserReset(&sParse); sqlite3_free(zQuot); } /* ** Register built-in functions used to help implement ALTER TABLE */ |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2277 2278 2279 2280 2281 2282 2283 | tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */ }; /* ** Each token coming out of the lexer is an instance of ** this structure. Tokens are also used as part of an expression. ** | | | > > | | 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 | tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */ }; /* ** Each token coming out of the lexer is an instance of ** this structure. Tokens are also used as part of an expression. ** ** The memory that "z" points to is owned by other objects. Take care ** that the owner of the "z" string does not deallocate the string before ** the Token goes out of scope! Very often, the "z" points to some place ** in the middle of the Parse.zSql text. But it might also point to a ** static string. */ struct Token { const char *z; /* Text of the token. Not NULL-terminated! */ unsigned int n; /* Number of characters in this token */ }; /* |
︙ | ︙ | |||
3110 3111 3112 3113 3114 3115 3116 | Table **apVtabLock; /* Pointer to virtual tables needing locking */ #endif Table *pZombieTab; /* List of Table objects to delete after code gen */ TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ With *pWith; /* Current WITH clause, or NULL */ With *pWithToFree; /* Free this WITH object at the end of the parse */ #ifndef SQLITE_OMIT_ALTERTABLE | | | 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 | Table **apVtabLock; /* Pointer to virtual tables needing locking */ #endif Table *pZombieTab; /* List of Table objects to delete after code gen */ TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ With *pWith; /* Current WITH clause, or NULL */ With *pWithToFree; /* Free this WITH object at the end of the parse */ #ifndef SQLITE_OMIT_ALTERTABLE RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */ #endif }; #define PARSE_MODE_NORMAL 0 #define PARSE_MODE_DECLARE_VTAB 1 #define PARSE_MODE_RENAME_COLUMN 2 |
︙ | ︙ |