1 | /* |
2 | ** 2005 February 15 |
3 | ** |
4 | ** The author disclaims copyright to this source code. In place of |
5 | ** a legal notice, here is a blessing: |
6 | ** |
7 | ** May you do good and not evil. |
8 | ** May you find forgiveness for yourself and forgive others. |
9 | ** May you share freely, never taking more than you give. |
10 | ** |
11 | ************************************************************************* |
12 | ** This file contains C code routines that used to generate VDBE code |
13 | ** that implements the ALTER TABLE command. |
14 | */ |
15 | #include "sqliteInt.h" |
16 | |
17 | /* |
18 | ** The code in this file only exists if we are not omitting the |
19 | ** ALTER TABLE logic from the build. |
20 | */ |
21 | #ifndef SQLITE_OMIT_ALTERTABLE |
22 | |
23 | /* |
24 | ** Parameter zName is the name of a table that is about to be altered |
25 | ** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN). |
26 | ** If the table is a system table, this function leaves an error message |
27 | ** in pParse->zErr (system tables may not be altered) and returns non-zero. |
28 | ** |
29 | ** Or, if zName is not a system table, zero is returned. |
30 | */ |
31 | static int isAlterableTable(Parse *pParse, Table *pTab){ |
32 | if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_" , 7) |
33 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
34 | || (pTab->tabFlags & TF_Eponymous)!=0 |
35 | || ( (pTab->tabFlags & TF_Shadow)!=0 |
36 | && sqlite3ReadOnlyShadowTables(pParse->db) |
37 | ) |
38 | #endif |
39 | ){ |
40 | sqlite3ErrorMsg(pParse, "table %s may not be altered" , pTab->zName); |
41 | return 1; |
42 | } |
43 | return 0; |
44 | } |
45 | |
46 | /* |
47 | ** Generate code to verify that the schemas of database zDb and, if |
48 | ** bTemp is not true, database "temp", can still be parsed. This is |
49 | ** called at the end of the generation of an ALTER TABLE ... RENAME ... |
50 | ** statement to ensure that the operation has not rendered any schema |
51 | ** objects unusable. |
52 | */ |
53 | static void renameTestSchema( |
54 | Parse *pParse, /* Parse context */ |
55 | const char *zDb, /* Name of db to verify schema of */ |
56 | int bTemp, /* True if this is the temp db */ |
57 | const char *zWhen, /* "when" part of error message */ |
58 | int bNoDQS /* Do not allow DQS in the schema */ |
59 | ){ |
60 | pParse->colNamesSet = 1; |
61 | sqlite3NestedParse(pParse, |
62 | "SELECT 1 " |
63 | "FROM \"%w\"." LEGACY_SCHEMA_TABLE " " |
64 | "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" |
65 | " AND sql NOT LIKE 'create virtual%%'" |
66 | " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %d)=NULL " , |
67 | zDb, |
68 | zDb, bTemp, zWhen, bNoDQS |
69 | ); |
70 | |
71 | if( bTemp==0 ){ |
72 | sqlite3NestedParse(pParse, |
73 | "SELECT 1 " |
74 | "FROM temp." LEGACY_SCHEMA_TABLE " " |
75 | "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" |
76 | " AND sql NOT LIKE 'create virtual%%'" |
77 | " AND sqlite_rename_test(%Q, sql, type, name, 1, %Q, %d)=NULL " , |
78 | zDb, zWhen, bNoDQS |
79 | ); |
80 | } |
81 | } |
82 | |
83 | /* |
84 | ** Generate VM code to replace any double-quoted strings (but not double-quoted |
85 | ** identifiers) within the "sql" column of the sqlite_schema table in |
86 | ** database zDb with their single-quoted equivalents. If argument bTemp is |
87 | ** not true, similarly update all SQL statements in the sqlite_schema table |
88 | ** of the temp db. |
89 | */ |
90 | static void renameFixQuotes(Parse *pParse, const char *zDb, int bTemp){ |
91 | sqlite3NestedParse(pParse, |
92 | "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE |
93 | " SET sql = sqlite_rename_quotefix(%Q, sql)" |
94 | "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" |
95 | " AND sql NOT LIKE 'create virtual%%'" , zDb, zDb |
96 | ); |
97 | if( bTemp==0 ){ |
98 | sqlite3NestedParse(pParse, |
99 | "UPDATE temp." LEGACY_SCHEMA_TABLE |
100 | " SET sql = sqlite_rename_quotefix('temp', sql)" |
101 | "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" |
102 | " AND sql NOT LIKE 'create virtual%%'" |
103 | ); |
104 | } |
105 | } |
106 | |
107 | /* |
108 | ** Generate code to reload the schema for database iDb. And, if iDb!=1, for |
109 | ** the temp database as well. |
110 | */ |
111 | static void renameReloadSchema(Parse *pParse, int iDb, u16 p5){ |
112 | Vdbe *v = pParse->pVdbe; |
113 | if( v ){ |
114 | sqlite3ChangeCookie(pParse, iDb); |
115 | sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0, p5); |
116 | if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0, p5); |
117 | } |
118 | } |
119 | |
120 | /* |
121 | ** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" |
122 | ** command. |
123 | */ |
124 | void sqlite3AlterRenameTable( |
125 | Parse *pParse, /* Parser context. */ |
126 | SrcList *pSrc, /* The table to rename. */ |
127 | Token *pName /* The new table name. */ |
128 | ){ |
129 | int iDb; /* Database that contains the table */ |
130 | char *zDb; /* Name of database iDb */ |
131 | Table *pTab; /* Table being renamed */ |
132 | char *zName = 0; /* NULL-terminated version of pName */ |
133 | sqlite3 *db = pParse->db; /* Database connection */ |
134 | int nTabName; /* Number of UTF-8 characters in zTabName */ |
135 | const char *zTabName; /* Original name of the table */ |
136 | Vdbe *v; |
137 | VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ |
138 | |
139 | if( NEVER(db->mallocFailed) ) goto exit_rename_table; |
140 | assert( pSrc->nSrc==1 ); |
141 | assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); |
142 | |
143 | pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); |
144 | if( !pTab ) goto exit_rename_table; |
145 | iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); |
146 | zDb = db->aDb[iDb].zDbSName; |
147 | |
148 | /* Get a NULL terminated version of the new table name. */ |
149 | zName = sqlite3NameFromToken(db, pName); |
150 | if( !zName ) goto exit_rename_table; |
151 | |
152 | /* Check that a table or index named 'zName' does not already exist |
153 | ** in database iDb. If so, this is an error. |
154 | */ |
155 | if( sqlite3FindTable(db, zName, zDb) |
156 | || sqlite3FindIndex(db, zName, zDb) |
157 | || sqlite3IsShadowTableOf(db, pTab, zName) |
158 | ){ |
159 | sqlite3ErrorMsg(pParse, |
160 | "there is already another table or index with this name: %s" , zName); |
161 | goto exit_rename_table; |
162 | } |
163 | |
164 | /* Make sure it is not a system table being altered, or a reserved name |
165 | ** that the table is being renamed to. |
166 | */ |
167 | if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){ |
168 | goto exit_rename_table; |
169 | } |
170 | if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table" ,zName) ){ |
171 | goto exit_rename_table; |
172 | } |
173 | |
174 | #ifndef SQLITE_OMIT_VIEW |
175 | if( IsView(pTab) ){ |
176 | sqlite3ErrorMsg(pParse, "view %s may not be altered" , pTab->zName); |
177 | goto exit_rename_table; |
178 | } |
179 | #endif |
180 | |
181 | #ifndef SQLITE_OMIT_AUTHORIZATION |
182 | /* Invoke the authorization callback. */ |
183 | if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ |
184 | goto exit_rename_table; |
185 | } |
186 | #endif |
187 | |
188 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
189 | if( sqlite3ViewGetColumnNames(pParse, pTab) ){ |
190 | goto exit_rename_table; |
191 | } |
192 | if( IsVirtual(pTab) ){ |
193 | pVTab = sqlite3GetVTable(db, pTab); |
194 | if( pVTab->pVtab->pModule->xRename==0 ){ |
195 | pVTab = 0; |
196 | } |
197 | } |
198 | #endif |
199 | |
200 | /* Begin a transaction for database iDb. Then modify the schema cookie |
201 | ** (since the ALTER TABLE modifies the schema). Call sqlite3MayAbort(), |
202 | ** as the scalar functions (e.g. sqlite_rename_table()) invoked by the |
203 | ** nested SQL may raise an exception. */ |
204 | v = sqlite3GetVdbe(pParse); |
205 | if( v==0 ){ |
206 | goto exit_rename_table; |
207 | } |
208 | sqlite3MayAbort(pParse); |
209 | |
210 | /* figure out how many UTF-8 characters are in zName */ |
211 | zTabName = pTab->zName; |
212 | nTabName = sqlite3Utf8CharLen(zTabName, -1); |
213 | |
214 | /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in |
215 | ** the schema to use the new table name. */ |
216 | sqlite3NestedParse(pParse, |
217 | "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " |
218 | "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, %d) " |
219 | "WHERE (type!='index' OR tbl_name=%Q COLLATE nocase)" |
220 | "AND name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" |
221 | , zDb, zDb, zTabName, zName, (iDb==1), zTabName |
222 | ); |
223 | |
224 | /* Update the tbl_name and name columns of the sqlite_schema table |
225 | ** as required. */ |
226 | sqlite3NestedParse(pParse, |
227 | "UPDATE %Q." LEGACY_SCHEMA_TABLE " SET " |
228 | "tbl_name = %Q, " |
229 | "name = CASE " |
230 | "WHEN type='table' THEN %Q " |
231 | "WHEN name LIKE 'sqliteX_autoindex%%' ESCAPE 'X' " |
232 | " AND type='index' THEN " |
233 | "'sqlite_autoindex_' || %Q || substr(name,%d+18) " |
234 | "ELSE name END " |
235 | "WHERE tbl_name=%Q COLLATE nocase AND " |
236 | "(type='table' OR type='index' OR type='trigger');" , |
237 | zDb, |
238 | zName, zName, zName, |
239 | nTabName, zTabName |
240 | ); |
241 | |
242 | #ifndef SQLITE_OMIT_AUTOINCREMENT |
243 | /* If the sqlite_sequence table exists in this database, then update |
244 | ** it with the new table name. |
245 | */ |
246 | if( sqlite3FindTable(db, "sqlite_sequence" , zDb) ){ |
247 | sqlite3NestedParse(pParse, |
248 | "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q" , |
249 | zDb, zName, pTab->zName); |
250 | } |
251 | #endif |
252 | |
253 | /* If the table being renamed is not itself part of the temp database, |
254 | ** edit view and trigger definitions within the temp database |
255 | ** as required. */ |
256 | if( iDb!=1 ){ |
257 | sqlite3NestedParse(pParse, |
258 | "UPDATE sqlite_temp_schema SET " |
259 | "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), " |
260 | "tbl_name = " |
261 | "CASE WHEN tbl_name=%Q COLLATE nocase AND " |
262 | " sqlite_rename_test(%Q, sql, type, name, 1, 'after rename', 0) " |
263 | "THEN %Q ELSE tbl_name END " |
264 | "WHERE type IN ('view', 'trigger')" |
265 | , zDb, zTabName, zName, zTabName, zDb, zName); |
266 | } |
267 | |
268 | /* If this is a virtual table, invoke the xRename() function if |
269 | ** one is defined. The xRename() callback will modify the names |
270 | ** of any resources used by the v-table implementation (including other |
271 | ** SQLite tables) that are identified by the name of the virtual table. |
272 | */ |
273 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
274 | if( pVTab ){ |
275 | int i = ++pParse->nMem; |
276 | sqlite3VdbeLoadString(v, i, zName); |
277 | sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); |
278 | } |
279 | #endif |
280 | |
281 | renameReloadSchema(pParse, iDb, INITFLAG_AlterRename); |
282 | renameTestSchema(pParse, zDb, iDb==1, "after rename" , 0); |
283 | |
284 | exit_rename_table: |
285 | sqlite3SrcListDelete(db, pSrc); |
286 | sqlite3DbFree(db, zName); |
287 | } |
288 | |
289 | /* |
290 | ** Write code that will raise an error if the table described by |
291 | ** zDb and zTab is not empty. |
292 | */ |
293 | static void sqlite3ErrorIfNotEmpty( |
294 | Parse *pParse, /* Parsing context */ |
295 | const char *zDb, /* Schema holding the table */ |
296 | const char *zTab, /* Table to check for empty */ |
297 | const char *zErr /* Error message text */ |
298 | ){ |
299 | sqlite3NestedParse(pParse, |
300 | "SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"" , |
301 | zErr, zDb, zTab |
302 | ); |
303 | } |
304 | |
305 | /* |
306 | ** This function is called after an "ALTER TABLE ... ADD" statement |
307 | ** has been parsed. Argument pColDef contains the text of the new |
308 | ** column definition. |
309 | ** |
310 | ** The Table structure pParse->pNewTable was extended to include |
311 | ** the new column during parsing. |
312 | */ |
313 | void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ |
314 | Table *pNew; /* Copy of pParse->pNewTable */ |
315 | Table *pTab; /* Table being altered */ |
316 | int iDb; /* Database number */ |
317 | const char *zDb; /* Database name */ |
318 | const char *zTab; /* Table name */ |
319 | char *zCol; /* Null-terminated column definition */ |
320 | Column *pCol; /* The new column */ |
321 | Expr *pDflt; /* Default value for the new column */ |
322 | sqlite3 *db; /* The database connection; */ |
323 | Vdbe *v; /* The prepared statement under construction */ |
324 | int r1; /* Temporary registers */ |
325 | |
326 | db = pParse->db; |
327 | assert( db->pParse==pParse ); |
328 | if( pParse->nErr ) return; |
329 | assert( db->mallocFailed==0 ); |
330 | pNew = pParse->pNewTable; |
331 | assert( pNew ); |
332 | |
333 | assert( sqlite3BtreeHoldsAllMutexes(db) ); |
334 | iDb = sqlite3SchemaToIndex(db, pNew->pSchema); |
335 | zDb = db->aDb[iDb].zDbSName; |
336 | zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ |
337 | pCol = &pNew->aCol[pNew->nCol-1]; |
338 | pDflt = sqlite3ColumnExpr(pNew, pCol); |
339 | pTab = sqlite3FindTable(db, zTab, zDb); |
340 | assert( pTab ); |
341 | |
342 | #ifndef SQLITE_OMIT_AUTHORIZATION |
343 | /* Invoke the authorization callback. */ |
344 | if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ |
345 | return; |
346 | } |
347 | #endif |
348 | |
349 | |
350 | /* Check that the new column is not specified as PRIMARY KEY or UNIQUE. |
351 | ** If there is a NOT NULL constraint, then the default value for the |
352 | ** column must not be NULL. |
353 | */ |
354 | if( pCol->colFlags & COLFLAG_PRIMKEY ){ |
355 | sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column" ); |
356 | return; |
357 | } |
358 | if( pNew->pIndex ){ |
359 | sqlite3ErrorMsg(pParse, |
360 | "Cannot add a UNIQUE column" ); |
361 | return; |
362 | } |
363 | if( (pCol->colFlags & COLFLAG_GENERATED)==0 ){ |
364 | /* If the default value for the new column was specified with a |
365 | ** literal NULL, then set pDflt to 0. This simplifies checking |
366 | ** for an SQL NULL default below. |
367 | */ |
368 | assert( pDflt==0 || pDflt->op==TK_SPAN ); |
369 | if( pDflt && pDflt->pLeft->op==TK_NULL ){ |
370 | pDflt = 0; |
371 | } |
372 | assert( IsOrdinaryTable(pNew) ); |
373 | if( (db->flags&SQLITE_ForeignKeys) && pNew->u.tab.pFKey && pDflt ){ |
374 | sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, |
375 | "Cannot add a REFERENCES column with non-NULL default value" ); |
376 | } |
377 | if( pCol->notNull && !pDflt ){ |
378 | sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, |
379 | "Cannot add a NOT NULL column with default value NULL" ); |
380 | } |
381 | |
382 | |
383 | /* Ensure the default expression is something that sqlite3ValueFromExpr() |
384 | ** can handle (i.e. not CURRENT_TIME etc.) |
385 | */ |
386 | if( pDflt ){ |
387 | sqlite3_value *pVal = 0; |
388 | int rc; |
389 | rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal); |
390 | assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); |
391 | if( rc!=SQLITE_OK ){ |
392 | assert( db->mallocFailed == 1 ); |
393 | return; |
394 | } |
395 | if( !pVal ){ |
396 | sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, |
397 | "Cannot add a column with non-constant default" ); |
398 | } |
399 | sqlite3ValueFree(pVal); |
400 | } |
401 | }else if( pCol->colFlags & COLFLAG_STORED ){ |
402 | sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, "cannot add a STORED column" ); |
403 | } |
404 | |
405 | |
406 | /* Modify the CREATE TABLE statement. */ |
407 | zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); |
408 | if( zCol ){ |
409 | char *zEnd = &zCol[pColDef->n-1]; |
410 | while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){ |
411 | *zEnd-- = '\0'; |
412 | } |
413 | /* substr() operations on characters, but addColOffset is in bytes. So we |
414 | ** have to use printf() to translate between these units: */ |
415 | assert( IsOrdinaryTable(pTab) ); |
416 | assert( IsOrdinaryTable(pNew) ); |
417 | sqlite3NestedParse(pParse, |
418 | "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " |
419 | "sql = printf('%%.%ds, ',sql) || %Q" |
420 | " || substr(sql,1+length(printf('%%.%ds',sql))) " |
421 | "WHERE type = 'table' AND name = %Q" , |
422 | zDb, pNew->u.tab.addColOffset, zCol, pNew->u.tab.addColOffset, |
423 | zTab |
424 | ); |
425 | sqlite3DbFree(db, zCol); |
426 | } |
427 | |
428 | v = sqlite3GetVdbe(pParse); |
429 | if( v ){ |
430 | /* Make sure the schema version is at least 3. But do not upgrade |
431 | ** from less than 3 to 4, as that will corrupt any preexisting DESC |
432 | ** index. |
433 | */ |
434 | r1 = sqlite3GetTempReg(pParse); |
435 | sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); |
436 | sqlite3VdbeUsesBtree(v, iDb); |
437 | sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2); |
438 | sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2); |
439 | VdbeCoverage(v); |
440 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3); |
441 | sqlite3ReleaseTempReg(pParse, r1); |
442 | |
443 | /* Reload the table definition */ |
444 | renameReloadSchema(pParse, iDb, INITFLAG_AlterAdd); |
445 | |
446 | /* Verify that constraints are still satisfied */ |
447 | if( pNew->pCheck!=0 |
448 | || (pCol->notNull && (pCol->colFlags & COLFLAG_GENERATED)!=0) |
449 | ){ |
450 | sqlite3NestedParse(pParse, |
451 | "SELECT CASE WHEN quick_check GLOB 'CHECK*'" |
452 | " THEN raise(ABORT,'CHECK constraint failed')" |
453 | " ELSE raise(ABORT,'NOT NULL constraint failed')" |
454 | " END" |
455 | " FROM pragma_quick_check(%Q,%Q)" |
456 | " WHERE quick_check GLOB 'CHECK*' OR quick_check GLOB 'NULL*'" , |
457 | zTab, zDb |
458 | ); |
459 | } |
460 | } |
461 | } |
462 | |
463 | /* |
464 | ** This function is called by the parser after the table-name in |
465 | ** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument |
466 | ** pSrc is the full-name of the table being altered. |
467 | ** |
468 | ** This routine makes a (partial) copy of the Table structure |
469 | ** for the table being altered and sets Parse.pNewTable to point |
470 | ** to it. Routines called by the parser as the column definition |
471 | ** is parsed (i.e. sqlite3AddColumn()) add the new Column data to |
472 | ** the copy. The copy of the Table structure is deleted by tokenize.c |
473 | ** after parsing is finished. |
474 | ** |
475 | ** Routine sqlite3AlterFinishAddColumn() will be called to complete |
476 | ** coding the "ALTER TABLE ... ADD" statement. |
477 | */ |
478 | void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ |
479 | Table *pNew; |
480 | Table *pTab; |
481 | int iDb; |
482 | int i; |
483 | int nAlloc; |
484 | sqlite3 *db = pParse->db; |
485 | |
486 | /* Look up the table being altered. */ |
487 | assert( pParse->pNewTable==0 ); |
488 | assert( sqlite3BtreeHoldsAllMutexes(db) ); |
489 | if( db->mallocFailed ) goto exit_begin_add_column; |
490 | pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); |
491 | if( !pTab ) goto exit_begin_add_column; |
492 | |
493 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
494 | if( IsVirtual(pTab) ){ |
495 | sqlite3ErrorMsg(pParse, "virtual tables may not be altered" ); |
496 | goto exit_begin_add_column; |
497 | } |
498 | #endif |
499 | |
500 | /* Make sure this is not an attempt to ALTER a view. */ |
501 | if( IsView(pTab) ){ |
502 | sqlite3ErrorMsg(pParse, "Cannot add a column to a view" ); |
503 | goto exit_begin_add_column; |
504 | } |
505 | if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){ |
506 | goto exit_begin_add_column; |
507 | } |
508 | |
509 | sqlite3MayAbort(pParse); |
510 | assert( IsOrdinaryTable(pTab) ); |
511 | assert( pTab->u.tab.addColOffset>0 ); |
512 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
513 | |
514 | /* Put a copy of the Table struct in Parse.pNewTable for the |
515 | ** sqlite3AddColumn() function and friends to modify. But modify |
516 | ** the name by adding an "sqlite_altertab_" prefix. By adding this |
517 | ** prefix, we insure that the name will not collide with an existing |
518 | ** table because user table are not allowed to have the "sqlite_" |
519 | ** prefix on their name. |
520 | */ |
521 | pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table)); |
522 | if( !pNew ) goto exit_begin_add_column; |
523 | pParse->pNewTable = pNew; |
524 | pNew->nTabRef = 1; |
525 | pNew->nCol = pTab->nCol; |
526 | assert( pNew->nCol>0 ); |
527 | nAlloc = (((pNew->nCol-1)/8)*8)+8; |
528 | assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); |
529 | pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); |
530 | pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s" , pTab->zName); |
531 | if( !pNew->aCol || !pNew->zName ){ |
532 | assert( db->mallocFailed ); |
533 | goto exit_begin_add_column; |
534 | } |
535 | memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); |
536 | for(i=0; i<pNew->nCol; i++){ |
537 | Column *pCol = &pNew->aCol[i]; |
538 | pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName); |
539 | pCol->hName = sqlite3StrIHash(pCol->zCnName); |
540 | } |
541 | assert( IsOrdinaryTable(pNew) ); |
542 | pNew->u.tab.pDfltList = sqlite3ExprListDup(db, pTab->u.tab.pDfltList, 0); |
543 | pNew->pSchema = db->aDb[iDb].pSchema; |
544 | pNew->u.tab.addColOffset = pTab->u.tab.addColOffset; |
545 | pNew->nTabRef = 1; |
546 | |
547 | exit_begin_add_column: |
548 | sqlite3SrcListDelete(db, pSrc); |
549 | return; |
550 | } |
551 | |
552 | /* |
553 | ** Parameter pTab is the subject of an ALTER TABLE ... RENAME COLUMN |
554 | ** command. This function checks if the table is a view or virtual |
555 | ** table (columns of views or virtual tables may not be renamed). If so, |
556 | ** it loads an error message into pParse and returns non-zero. |
557 | ** |
558 | ** Or, if pTab is not a view or virtual table, zero is returned. |
559 | */ |
560 | #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) |
561 | static int isRealTable(Parse *pParse, Table *pTab, int bDrop){ |
562 | const char *zType = 0; |
563 | #ifndef SQLITE_OMIT_VIEW |
564 | if( IsView(pTab) ){ |
565 | zType = "view" ; |
566 | } |
567 | #endif |
568 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
569 | if( IsVirtual(pTab) ){ |
570 | zType = "virtual table" ; |
571 | } |
572 | #endif |
573 | if( zType ){ |
574 | sqlite3ErrorMsg(pParse, "cannot %s %s \"%s\"" , |
575 | (bDrop ? "drop column from" : "rename columns of" ), |
576 | zType, pTab->zName |
577 | ); |
578 | return 1; |
579 | } |
580 | return 0; |
581 | } |
582 | #else /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ |
583 | # define isRealTable(x,y,z) (0) |
584 | #endif |
585 | |
586 | /* |
587 | ** Handles the following parser reduction: |
588 | ** |
589 | ** cmd ::= ALTER TABLE pSrc RENAME COLUMN pOld TO pNew |
590 | */ |
591 | void sqlite3AlterRenameColumn( |
592 | Parse *pParse, /* Parsing context */ |
593 | SrcList *pSrc, /* Table being altered. pSrc->nSrc==1 */ |
594 | Token *pOld, /* Name of column being changed */ |
595 | Token *pNew /* New column name */ |
596 | ){ |
597 | sqlite3 *db = pParse->db; /* Database connection */ |
598 | Table *pTab; /* Table being updated */ |
599 | int iCol; /* Index of column being renamed */ |
600 | char *zOld = 0; /* Old column name */ |
601 | char *zNew = 0; /* New column name */ |
602 | const char *zDb; /* Name of schema containing the table */ |
603 | int iSchema; /* Index of the schema */ |
604 | int bQuote; /* True to quote the new name */ |
605 | |
606 | /* Locate the table to be altered */ |
607 | pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); |
608 | if( !pTab ) goto exit_rename_column; |
609 | |
610 | /* Cannot alter a system table */ |
611 | if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column; |
612 | if( SQLITE_OK!=isRealTable(pParse, pTab, 0) ) goto exit_rename_column; |
613 | |
614 | /* Which schema holds the table to be altered */ |
615 | iSchema = sqlite3SchemaToIndex(db, pTab->pSchema); |
616 | assert( iSchema>=0 ); |
617 | zDb = db->aDb[iSchema].zDbSName; |
618 | |
619 | #ifndef SQLITE_OMIT_AUTHORIZATION |
620 | /* Invoke the authorization callback. */ |
621 | if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ |
622 | goto exit_rename_column; |
623 | } |
624 | #endif |
625 | |
626 | /* Make sure the old name really is a column name in the table to be |
627 | ** altered. Set iCol to be the index of the column being renamed */ |
628 | zOld = sqlite3NameFromToken(db, pOld); |
629 | if( !zOld ) goto exit_rename_column; |
630 | for(iCol=0; iCol<pTab->nCol; iCol++){ |
631 | if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break; |
632 | } |
633 | if( iCol==pTab->nCol ){ |
634 | sqlite3ErrorMsg(pParse, "no such column: \"%T\"" , pOld); |
635 | goto exit_rename_column; |
636 | } |
637 | |
638 | /* Ensure the schema contains no double-quoted strings */ |
639 | renameTestSchema(pParse, zDb, iSchema==1, "" , 0); |
640 | renameFixQuotes(pParse, zDb, iSchema==1); |
641 | |
642 | /* Do the rename operation using a recursive UPDATE statement that |
643 | ** uses the sqlite_rename_column() SQL function to compute the new |
644 | ** CREATE statement text for the sqlite_schema table. |
645 | */ |
646 | sqlite3MayAbort(pParse); |
647 | zNew = sqlite3NameFromToken(db, pNew); |
648 | if( !zNew ) goto exit_rename_column; |
649 | assert( pNew->n>0 ); |
650 | bQuote = sqlite3Isquote(pNew->z[0]); |
651 | sqlite3NestedParse(pParse, |
652 | "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " |
653 | "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) " |
654 | "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X' " |
655 | " AND (type != 'index' OR tbl_name = %Q)" , |
656 | zDb, |
657 | zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1, |
658 | pTab->zName |
659 | ); |
660 | |
661 | sqlite3NestedParse(pParse, |
662 | "UPDATE temp." LEGACY_SCHEMA_TABLE " SET " |
663 | "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) " |
664 | "WHERE type IN ('trigger', 'view')" , |
665 | zDb, pTab->zName, iCol, zNew, bQuote |
666 | ); |
667 | |
668 | /* Drop and reload the database schema. */ |
669 | renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename); |
670 | renameTestSchema(pParse, zDb, iSchema==1, "after rename" , 1); |
671 | |
672 | exit_rename_column: |
673 | sqlite3SrcListDelete(db, pSrc); |
674 | sqlite3DbFree(db, zOld); |
675 | sqlite3DbFree(db, zNew); |
676 | return; |
677 | } |
678 | |
679 | /* |
680 | ** Each RenameToken object maps an element of the parse tree into |
681 | ** the token that generated that element. The parse tree element |
682 | ** might be one of: |
683 | ** |
684 | ** * A pointer to an Expr that represents an ID |
685 | ** * The name of a table column in Column.zName |
686 | ** |
687 | ** A list of RenameToken objects can be constructed during parsing. |
688 | ** Each new object is created by sqlite3RenameTokenMap(). |
689 | ** As the parse tree is transformed, the sqlite3RenameTokenRemap() |
690 | ** routine is used to keep the mapping current. |
691 | ** |
692 | ** After the parse finishes, renameTokenFind() routine can be used |
693 | ** to look up the actual token value that created some element in |
694 | ** the parse tree. |
695 | */ |
696 | struct RenameToken { |
697 | const void *p; /* Parse tree element created by token t */ |
698 | Token t; /* The token that created parse tree element p */ |
699 | RenameToken *pNext; /* Next is a list of all RenameToken objects */ |
700 | }; |
701 | |
702 | /* |
703 | ** The context of an ALTER TABLE RENAME COLUMN operation that gets passed |
704 | ** down into the Walker. |
705 | */ |
706 | typedef struct RenameCtx RenameCtx; |
707 | struct RenameCtx { |
708 | RenameToken *pList; /* List of tokens to overwrite */ |
709 | int nList; /* Number of tokens in pList */ |
710 | int iCol; /* Index of column being renamed */ |
711 | Table *pTab; /* Table being ALTERed */ |
712 | const char *zOld; /* Old column name */ |
713 | }; |
714 | |
715 | #ifdef SQLITE_DEBUG |
716 | /* |
717 | ** This function is only for debugging. It performs two tasks: |
718 | ** |
719 | ** 1. Checks that pointer pPtr does not already appear in the |
720 | ** rename-token list. |
721 | ** |
722 | ** 2. Dereferences each pointer in the rename-token list. |
723 | ** |
724 | ** The second is most effective when debugging under valgrind or |
725 | ** address-sanitizer or similar. If any of these pointers no longer |
726 | ** point to valid objects, an exception is raised by the memory-checking |
727 | ** tool. |
728 | ** |
729 | ** The point of this is to prevent comparisons of invalid pointer values. |
730 | ** Even though this always seems to work, it is undefined according to the |
731 | ** C standard. Example of undefined comparison: |
732 | ** |
733 | ** sqlite3_free(x); |
734 | ** if( x==y ) ... |
735 | ** |
736 | ** Technically, as x no longer points into a valid object or to the byte |
737 | ** following a valid object, it may not be used in comparison operations. |
738 | */ |
739 | static void renameTokenCheckAll(Parse *pParse, const void *pPtr){ |
740 | assert( pParse==pParse->db->pParse ); |
741 | assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); |
742 | if( pParse->nErr==0 ){ |
743 | const RenameToken *p; |
744 | u8 i = 0; |
745 | for(p=pParse->pRename; p; p=p->pNext){ |
746 | if( p->p ){ |
747 | assert( p->p!=pPtr ); |
748 | i += *(u8*)(p->p); |
749 | } |
750 | } |
751 | } |
752 | } |
753 | #else |
754 | # define renameTokenCheckAll(x,y) |
755 | #endif |
756 | |
757 | /* |
758 | ** Remember that the parser tree element pPtr was created using |
759 | ** the token pToken. |
760 | ** |
761 | ** In other words, construct a new RenameToken object and add it |
762 | ** to the list of RenameToken objects currently being built up |
763 | ** in pParse->pRename. |
764 | ** |
765 | ** The pPtr argument is returned so that this routine can be used |
766 | ** with tail recursion in tokenExpr() routine, for a small performance |
767 | ** improvement. |
768 | */ |
769 | const void *sqlite3RenameTokenMap( |
770 | Parse *pParse, |
771 | const void *pPtr, |
772 | const Token *pToken |
773 | ){ |
774 | RenameToken *pNew; |
775 | assert( pPtr || pParse->db->mallocFailed ); |
776 | renameTokenCheckAll(pParse, pPtr); |
777 | if( ALWAYS(pParse->eParseMode!=PARSE_MODE_UNMAP) ){ |
778 | pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken)); |
779 | if( pNew ){ |
780 | pNew->p = pPtr; |
781 | pNew->t = *pToken; |
782 | pNew->pNext = pParse->pRename; |
783 | pParse->pRename = pNew; |
784 | } |
785 | } |
786 | |
787 | return pPtr; |
788 | } |
789 | |
790 | /* |
791 | ** It is assumed that there is already a RenameToken object associated |
792 | ** with parse tree element pFrom. This function remaps the associated token |
793 | ** to parse tree element pTo. |
794 | */ |
795 | void sqlite3RenameTokenRemap(Parse *pParse, const void *pTo, const void *pFrom){ |
796 | RenameToken *p; |
797 | renameTokenCheckAll(pParse, pTo); |
798 | for(p=pParse->pRename; p; p=p->pNext){ |
799 | if( p->p==pFrom ){ |
800 | p->p = pTo; |
801 | break; |
802 | } |
803 | } |
804 | } |
805 | |
806 | /* |
807 | ** Walker callback used by sqlite3RenameExprUnmap(). |
808 | */ |
809 | static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){ |
810 | Parse *pParse = pWalker->pParse; |
811 | sqlite3RenameTokenRemap(pParse, 0, (const void*)pExpr); |
812 | if( ExprUseYTab(pExpr) ){ |
813 | sqlite3RenameTokenRemap(pParse, 0, (const void*)&pExpr->y.pTab); |
814 | } |
815 | return WRC_Continue; |
816 | } |
817 | |
818 | /* |
819 | ** Iterate through the Select objects that are part of WITH clauses attached |
820 | ** to select statement pSelect. |
821 | */ |
822 | static void renameWalkWith(Walker *pWalker, Select *pSelect){ |
823 | With *pWith = pSelect->pWith; |
824 | if( pWith ){ |
825 | Parse *pParse = pWalker->pParse; |
826 | int i; |
827 | With *pCopy = 0; |
828 | assert( pWith->nCte>0 ); |
829 | if( (pWith->a[0].pSelect->selFlags & SF_Expanded)==0 ){ |
830 | /* Push a copy of the With object onto the with-stack. We use a copy |
831 | ** here as the original will be expanded and resolved (flags SF_Expanded |
832 | ** and SF_Resolved) below. And the parser code that uses the with-stack |
833 | ** fails if the Select objects on it have already been expanded and |
834 | ** resolved. */ |
835 | pCopy = sqlite3WithDup(pParse->db, pWith); |
836 | pCopy = sqlite3WithPush(pParse, pCopy, 1); |
837 | } |
838 | for(i=0; i<pWith->nCte; i++){ |
839 | Select *p = pWith->a[i].pSelect; |
840 | NameContext sNC; |
841 | memset(&sNC, 0, sizeof(sNC)); |
842 | sNC.pParse = pParse; |
843 | if( pCopy ) sqlite3SelectPrep(sNC.pParse, p, &sNC); |
844 | if( sNC.pParse->db->mallocFailed ) return; |
845 | sqlite3WalkSelect(pWalker, p); |
846 | sqlite3RenameExprlistUnmap(pParse, pWith->a[i].pCols); |
847 | } |
848 | if( pCopy && pParse->pWith==pCopy ){ |
849 | pParse->pWith = pCopy->pOuter; |
850 | } |
851 | } |
852 | } |
853 | |
854 | /* |
855 | ** Unmap all tokens in the IdList object passed as the second argument. |
856 | */ |
857 | static void unmapColumnIdlistNames( |
858 | Parse *pParse, |
859 | const IdList *pIdList |
860 | ){ |
861 | int ii; |
862 | assert( pIdList!=0 ); |
863 | for(ii=0; ii<pIdList->nId; ii++){ |
864 | sqlite3RenameTokenRemap(pParse, 0, (const void*)pIdList->a[ii].zName); |
865 | } |
866 | } |
867 | |
868 | /* |
869 | ** Walker callback used by sqlite3RenameExprUnmap(). |
870 | */ |
871 | static int renameUnmapSelectCb(Walker *pWalker, Select *p){ |
872 | Parse *pParse = pWalker->pParse; |
873 | int i; |
874 | if( pParse->nErr ) return WRC_Abort; |
875 | testcase( p->selFlags & SF_View ); |
876 | testcase( p->selFlags & SF_CopyCte ); |
877 | if( p->selFlags & (SF_View|SF_CopyCte) ){ |
878 | return WRC_Prune; |
879 | } |
880 | if( ALWAYS(p->pEList) ){ |
881 | ExprList *pList = p->pEList; |
882 | for(i=0; i<pList->nExpr; i++){ |
883 | if( pList->a[i].zEName && pList->a[i].fg.eEName==ENAME_NAME ){ |
884 | sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName); |
885 | } |
886 | } |
887 | } |
888 | if( ALWAYS(p->pSrc) ){ /* Every Select as a SrcList, even if it is empty */ |
889 | SrcList *pSrc = p->pSrc; |
890 | for(i=0; i<pSrc->nSrc; i++){ |
891 | sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName); |
892 | if( pSrc->a[i].fg.isUsing==0 ){ |
893 | sqlite3WalkExpr(pWalker, pSrc->a[i].u3.pOn); |
894 | }else{ |
895 | unmapColumnIdlistNames(pParse, pSrc->a[i].u3.pUsing); |
896 | } |
897 | } |
898 | } |
899 | |
900 | renameWalkWith(pWalker, p); |
901 | return WRC_Continue; |
902 | } |
903 | |
904 | /* |
905 | ** Remove all nodes that are part of expression pExpr from the rename list. |
906 | */ |
907 | void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){ |
908 | u8 eMode = pParse->eParseMode; |
909 | Walker sWalker; |
910 | memset(&sWalker, 0, sizeof(Walker)); |
911 | sWalker.pParse = pParse; |
912 | sWalker.xExprCallback = renameUnmapExprCb; |
913 | sWalker.xSelectCallback = renameUnmapSelectCb; |
914 | pParse->eParseMode = PARSE_MODE_UNMAP; |
915 | sqlite3WalkExpr(&sWalker, pExpr); |
916 | pParse->eParseMode = eMode; |
917 | } |
918 | |
919 | /* |
920 | ** Remove all nodes that are part of expression-list pEList from the |
921 | ** rename list. |
922 | */ |
923 | void sqlite3RenameExprlistUnmap(Parse *pParse, ExprList *pEList){ |
924 | if( pEList ){ |
925 | int i; |
926 | Walker sWalker; |
927 | memset(&sWalker, 0, sizeof(Walker)); |
928 | sWalker.pParse = pParse; |
929 | sWalker.xExprCallback = renameUnmapExprCb; |
930 | sqlite3WalkExprList(&sWalker, pEList); |
931 | for(i=0; i<pEList->nExpr; i++){ |
932 | if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME) ){ |
933 | sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zEName); |
934 | } |
935 | } |
936 | } |
937 | } |
938 | |
939 | /* |
940 | ** Free the list of RenameToken objects given in the second argument |
941 | */ |
942 | static void renameTokenFree(sqlite3 *db, RenameToken *pToken){ |
943 | RenameToken *pNext; |
944 | RenameToken *p; |
945 | for(p=pToken; p; p=pNext){ |
946 | pNext = p->pNext; |
947 | sqlite3DbFree(db, p); |
948 | } |
949 | } |
950 | |
951 | /* |
952 | ** Search the Parse object passed as the first argument for a RenameToken |
953 | ** object associated with parse tree element pPtr. If found, return a pointer |
954 | ** to it. Otherwise, return NULL. |
955 | ** |
956 | ** If the second argument passed to this function is not NULL and a matching |
957 | ** RenameToken object is found, remove it from the Parse object and add it to |
958 | ** the list maintained by the RenameCtx object. |
959 | */ |
960 | static RenameToken *renameTokenFind( |
961 | Parse *pParse, |
962 | struct RenameCtx *pCtx, |
963 | const void *pPtr |
964 | ){ |
965 | RenameToken **pp; |
966 | if( NEVER(pPtr==0) ){ |
967 | return 0; |
968 | } |
969 | for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){ |
970 | if( (*pp)->p==pPtr ){ |
971 | RenameToken *pToken = *pp; |
972 | if( pCtx ){ |
973 | *pp = pToken->pNext; |
974 | pToken->pNext = pCtx->pList; |
975 | pCtx->pList = pToken; |
976 | pCtx->nList++; |
977 | } |
978 | return pToken; |
979 | } |
980 | } |
981 | return 0; |
982 | } |
983 | |
984 | /* |
985 | ** This is a Walker select callback. It does nothing. It is only required |
986 | ** because without a dummy callback, sqlite3WalkExpr() and similar do not |
987 | ** descend into sub-select statements. |
988 | */ |
989 | static int renameColumnSelectCb(Walker *pWalker, Select *p){ |
990 | if( p->selFlags & (SF_View|SF_CopyCte) ){ |
991 | testcase( p->selFlags & SF_View ); |
992 | testcase( p->selFlags & SF_CopyCte ); |
993 | return WRC_Prune; |
994 | } |
995 | renameWalkWith(pWalker, p); |
996 | return WRC_Continue; |
997 | } |
998 | |
999 | /* |
1000 | ** This is a Walker expression callback. |
1001 | ** |
1002 | ** For every TK_COLUMN node in the expression tree, search to see |
1003 | ** if the column being references is the column being renamed by an |
1004 | ** ALTER TABLE statement. If it is, then attach its associated |
1005 | ** RenameToken object to the list of RenameToken objects being |
1006 | ** constructed in RenameCtx object at pWalker->u.pRename. |
1007 | */ |
1008 | static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){ |
1009 | RenameCtx *p = pWalker->u.pRename; |
1010 | if( pExpr->op==TK_TRIGGER |
1011 | && pExpr->iColumn==p->iCol |
1012 | && pWalker->pParse->pTriggerTab==p->pTab |
1013 | ){ |
1014 | renameTokenFind(pWalker->pParse, p, (void*)pExpr); |
1015 | }else if( pExpr->op==TK_COLUMN |
1016 | && pExpr->iColumn==p->iCol |
1017 | && ALWAYS(ExprUseYTab(pExpr)) |
1018 | && p->pTab==pExpr->y.pTab |
1019 | ){ |
1020 | renameTokenFind(pWalker->pParse, p, (void*)pExpr); |
1021 | } |
1022 | return WRC_Continue; |
1023 | } |
1024 | |
1025 | /* |
1026 | ** The RenameCtx contains a list of tokens that reference a column that |
1027 | ** is being renamed by an ALTER TABLE statement. Return the "last" |
1028 | ** RenameToken in the RenameCtx and remove that RenameToken from the |
1029 | ** RenameContext. "Last" means the last RenameToken encountered when |
1030 | ** the input SQL is parsed from left to right. Repeated calls to this routine |
1031 | ** return all column name tokens in the order that they are encountered |
1032 | ** in the SQL statement. |
1033 | */ |
1034 | static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){ |
1035 | RenameToken *pBest = pCtx->pList; |
1036 | RenameToken *pToken; |
1037 | RenameToken **pp; |
1038 | |
1039 | for(pToken=pBest->pNext; pToken; pToken=pToken->pNext){ |
1040 | if( pToken->t.z>pBest->t.z ) pBest = pToken; |
1041 | } |
1042 | for(pp=&pCtx->pList; *pp!=pBest; pp=&(*pp)->pNext); |
1043 | *pp = pBest->pNext; |
1044 | |
1045 | return pBest; |
1046 | } |
1047 | |
1048 | /* |
1049 | ** An error occured while parsing or otherwise processing a database |
1050 | ** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an |
1051 | ** ALTER TABLE RENAME COLUMN program. The error message emitted by the |
1052 | ** sub-routine is currently stored in pParse->zErrMsg. This function |
1053 | ** adds context to the error message and then stores it in pCtx. |
1054 | */ |
1055 | static void renameColumnParseError( |
1056 | sqlite3_context *pCtx, |
1057 | const char *zWhen, |
1058 | sqlite3_value *pType, |
1059 | sqlite3_value *pObject, |
1060 | Parse *pParse |
1061 | ){ |
1062 | const char *zT = (const char*)sqlite3_value_text(pType); |
1063 | const char *zN = (const char*)sqlite3_value_text(pObject); |
1064 | char *zErr; |
1065 | |
1066 | zErr = sqlite3MPrintf(pParse->db, "error in %s %s%s%s: %s" , |
1067 | zT, zN, (zWhen[0] ? " " : "" ), zWhen, |
1068 | pParse->zErrMsg |
1069 | ); |
1070 | sqlite3_result_error(pCtx, zErr, -1); |
1071 | sqlite3DbFree(pParse->db, zErr); |
1072 | } |
1073 | |
1074 | /* |
1075 | ** For each name in the the expression-list pEList (i.e. each |
1076 | ** pEList->a[i].zName) that matches the string in zOld, extract the |
1077 | ** corresponding rename-token from Parse object pParse and add it |
1078 | ** to the RenameCtx pCtx. |
1079 | */ |
1080 | static void renameColumnElistNames( |
1081 | Parse *pParse, |
1082 | RenameCtx *pCtx, |
1083 | const ExprList *pEList, |
1084 | const char *zOld |
1085 | ){ |
1086 | if( pEList ){ |
1087 | int i; |
1088 | for(i=0; i<pEList->nExpr; i++){ |
1089 | const char *zName = pEList->a[i].zEName; |
1090 | if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME) |
1091 | && ALWAYS(zName!=0) |
1092 | && 0==sqlite3_stricmp(zName, zOld) |
1093 | ){ |
1094 | renameTokenFind(pParse, pCtx, (const void*)zName); |
1095 | } |
1096 | } |
1097 | } |
1098 | } |
1099 | |
1100 | /* |
1101 | ** For each name in the the id-list pIdList (i.e. each pIdList->a[i].zName) |
1102 | ** that matches the string in zOld, extract the corresponding rename-token |
1103 | ** from Parse object pParse and add it to the RenameCtx pCtx. |
1104 | */ |
1105 | static void renameColumnIdlistNames( |
1106 | Parse *pParse, |
1107 | RenameCtx *pCtx, |
1108 | const IdList *pIdList, |
1109 | const char *zOld |
1110 | ){ |
1111 | if( pIdList ){ |
1112 | int i; |
1113 | for(i=0; i<pIdList->nId; i++){ |
1114 | const char *zName = pIdList->a[i].zName; |
1115 | if( 0==sqlite3_stricmp(zName, zOld) ){ |
1116 | renameTokenFind(pParse, pCtx, (const void*)zName); |
1117 | } |
1118 | } |
1119 | } |
1120 | } |
1121 | |
1122 | |
1123 | /* |
1124 | ** Parse the SQL statement zSql using Parse object (*p). The Parse object |
1125 | ** is initialized by this function before it is used. |
1126 | */ |
1127 | static int renameParseSql( |
1128 | Parse *p, /* Memory to use for Parse object */ |
1129 | const char *zDb, /* Name of schema SQL belongs to */ |
1130 | sqlite3 *db, /* Database handle */ |
1131 | const char *zSql, /* SQL to parse */ |
1132 | int bTemp /* True if SQL is from temp schema */ |
1133 | ){ |
1134 | int rc; |
1135 | |
1136 | sqlite3ParseObjectInit(p, db); |
1137 | if( zSql==0 ){ |
1138 | return SQLITE_NOMEM; |
1139 | } |
1140 | if( sqlite3StrNICmp(zSql,"CREATE " ,7)!=0 ){ |
1141 | return SQLITE_CORRUPT_BKPT; |
1142 | } |
1143 | db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb); |
1144 | p->eParseMode = PARSE_MODE_RENAME; |
1145 | p->db = db; |
1146 | p->nQueryLoop = 1; |
1147 | rc = sqlite3RunParser(p, zSql); |
1148 | if( db->mallocFailed ) rc = SQLITE_NOMEM; |
1149 | if( rc==SQLITE_OK |
1150 | && NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0) |
1151 | ){ |
1152 | rc = SQLITE_CORRUPT_BKPT; |
1153 | } |
1154 | |
1155 | #ifdef SQLITE_DEBUG |
1156 | /* Ensure that all mappings in the Parse.pRename list really do map to |
1157 | ** a part of the input string. */ |
1158 | if( rc==SQLITE_OK ){ |
1159 | int nSql = sqlite3Strlen30(zSql); |
1160 | RenameToken *pToken; |
1161 | for(pToken=p->pRename; pToken; pToken=pToken->pNext){ |
1162 | assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] ); |
1163 | } |
1164 | } |
1165 | #endif |
1166 | |
1167 | db->init.iDb = 0; |
1168 | return rc; |
1169 | } |
1170 | |
1171 | /* |
1172 | ** This function edits SQL statement zSql, replacing each token identified |
1173 | ** by the linked list pRename with the text of zNew. If argument bQuote is |
1174 | ** true, then zNew is always quoted first. If no error occurs, the result |
1175 | ** is loaded into context object pCtx as the result. |
1176 | ** |
1177 | ** Or, if an error occurs (i.e. an OOM condition), an error is left in |
1178 | ** pCtx and an SQLite error code returned. |
1179 | */ |
1180 | static int renameEditSql( |
1181 | sqlite3_context *pCtx, /* Return result here */ |
1182 | RenameCtx *pRename, /* Rename context */ |
1183 | const char *zSql, /* SQL statement to edit */ |
1184 | const char *zNew, /* New token text */ |
1185 | int bQuote /* True to always quote token */ |
1186 | ){ |
1187 | i64 nNew = sqlite3Strlen30(zNew); |
1188 | i64 nSql = sqlite3Strlen30(zSql); |
1189 | sqlite3 *db = sqlite3_context_db_handle(pCtx); |
1190 | int rc = SQLITE_OK; |
1191 | char *zQuot = 0; |
1192 | char *zOut; |
1193 | i64 nQuot = 0; |
1194 | char *zBuf1 = 0; |
1195 | char *zBuf2 = 0; |
1196 | |
1197 | if( zNew ){ |
1198 | /* Set zQuot to point to a buffer containing a quoted copy of the |
1199 | ** identifier zNew. If the corresponding identifier in the original |
1200 | ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to |
1201 | ** point to zQuot so that all substitutions are made using the |
1202 | ** quoted version of the new column name. */ |
1203 | zQuot = sqlite3MPrintf(db, "\"%w\" " , zNew); |
1204 | if( zQuot==0 ){ |
1205 | return SQLITE_NOMEM; |
1206 | }else{ |
1207 | nQuot = sqlite3Strlen30(zQuot)-1; |
1208 | } |
1209 | |
1210 | assert( nQuot>=nNew ); |
1211 | zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1); |
1212 | }else{ |
1213 | zOut = (char*)sqlite3DbMallocZero(db, (nSql*2+1) * 3); |
1214 | if( zOut ){ |
1215 | zBuf1 = &zOut[nSql*2+1]; |
1216 | zBuf2 = &zOut[nSql*4+2]; |
1217 | } |
1218 | } |
1219 | |
1220 | /* At this point pRename->pList contains a list of RenameToken objects |
1221 | ** corresponding to all tokens in the input SQL that must be replaced |
1222 | ** with the new column name, or with single-quoted versions of themselves. |
1223 | ** All that remains is to construct and return the edited SQL string. */ |
1224 | if( zOut ){ |
1225 | int nOut = nSql; |
1226 | memcpy(zOut, zSql, nSql); |
1227 | while( pRename->pList ){ |
1228 | int iOff; /* Offset of token to replace in zOut */ |
1229 | u32 nReplace; |
1230 | const char *zReplace; |
1231 | RenameToken *pBest = renameColumnTokenNext(pRename); |
1232 | |
1233 | if( zNew ){ |
1234 | if( bQuote==0 && sqlite3IsIdChar(*pBest->t.z) ){ |
1235 | nReplace = nNew; |
1236 | zReplace = zNew; |
1237 | }else{ |
1238 | nReplace = nQuot; |
1239 | zReplace = zQuot; |
1240 | if( pBest->t.z[pBest->t.n]=='"' ) nReplace++; |
1241 | } |
1242 | }else{ |
1243 | /* Dequote the double-quoted token. Then requote it again, this time |
1244 | ** using single quotes. If the character immediately following the |
1245 | ** original token within the input SQL was a single quote ('), then |
1246 | ** add another space after the new, single-quoted version of the |
1247 | ** token. This is so that (SELECT "string"'alias') maps to |
1248 | ** (SELECT 'string' 'alias'), and not (SELECT 'string''alias'). */ |
1249 | memcpy(zBuf1, pBest->t.z, pBest->t.n); |
1250 | zBuf1[pBest->t.n] = 0; |
1251 | sqlite3Dequote(zBuf1); |
1252 | sqlite3_snprintf(nSql*2, zBuf2, "%Q%s" , zBuf1, |
1253 | pBest->t.z[pBest->t.n]=='\'' ? " " : "" |
1254 | ); |
1255 | zReplace = zBuf2; |
1256 | nReplace = sqlite3Strlen30(zReplace); |
1257 | } |
1258 | |
1259 | iOff = pBest->t.z - zSql; |
1260 | if( pBest->t.n!=nReplace ){ |
1261 | memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n], |
1262 | nOut - (iOff + pBest->t.n) |
1263 | ); |
1264 | nOut += nReplace - pBest->t.n; |
1265 | zOut[nOut] = '\0'; |
1266 | } |
1267 | memcpy(&zOut[iOff], zReplace, nReplace); |
1268 | sqlite3DbFree(db, pBest); |
1269 | } |
1270 | |
1271 | sqlite3_result_text(pCtx, zOut, -1, SQLITE_TRANSIENT); |
1272 | sqlite3DbFree(db, zOut); |
1273 | }else{ |
1274 | rc = SQLITE_NOMEM; |
1275 | } |
1276 | |
1277 | sqlite3_free(zQuot); |
1278 | return rc; |
1279 | } |
1280 | |
1281 | /* |
1282 | ** Resolve all symbols in the trigger at pParse->pNewTrigger, assuming |
1283 | ** it was read from the schema of database zDb. Return SQLITE_OK if |
1284 | ** successful. Otherwise, return an SQLite error code and leave an error |
1285 | ** message in the Parse object. |
1286 | */ |
1287 | static int renameResolveTrigger(Parse *pParse){ |
1288 | sqlite3 *db = pParse->db; |
1289 | Trigger *pNew = pParse->pNewTrigger; |
1290 | TriggerStep *pStep; |
1291 | NameContext sNC; |
1292 | int rc = SQLITE_OK; |
1293 | |
1294 | memset(&sNC, 0, sizeof(sNC)); |
1295 | sNC.pParse = pParse; |
1296 | assert( pNew->pTabSchema ); |
1297 | pParse->pTriggerTab = sqlite3FindTable(db, pNew->table, |
1298 | db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema)].zDbSName |
1299 | ); |
1300 | pParse->eTriggerOp = pNew->op; |
1301 | /* ALWAYS() because if the table of the trigger does not exist, the |
1302 | ** error would have been hit before this point */ |
1303 | if( ALWAYS(pParse->pTriggerTab) ){ |
1304 | rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab); |
1305 | } |
1306 | |
1307 | /* Resolve symbols in WHEN clause */ |
1308 | if( rc==SQLITE_OK && pNew->pWhen ){ |
1309 | rc = sqlite3ResolveExprNames(&sNC, pNew->pWhen); |
1310 | } |
1311 | |
1312 | for(pStep=pNew->step_list; rc==SQLITE_OK && pStep; pStep=pStep->pNext){ |
1313 | if( pStep->pSelect ){ |
1314 | sqlite3SelectPrep(pParse, pStep->pSelect, &sNC); |
1315 | if( pParse->nErr ) rc = pParse->rc; |
1316 | } |
1317 | if( rc==SQLITE_OK && pStep->zTarget ){ |
1318 | SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep); |
1319 | if( pSrc ){ |
1320 | Select *pSel = sqlite3SelectNew( |
1321 | pParse, pStep->pExprList, pSrc, 0, 0, 0, 0, 0, 0 |
1322 | ); |
1323 | if( pSel==0 ){ |
1324 | pStep->pExprList = 0; |
1325 | pSrc = 0; |
1326 | rc = SQLITE_NOMEM; |
1327 | }else{ |
1328 | sqlite3SelectPrep(pParse, pSel, 0); |
1329 | rc = pParse->nErr ? SQLITE_ERROR : SQLITE_OK; |
1330 | assert( pStep->pExprList==0 || pStep->pExprList==pSel->pEList ); |
1331 | assert( pSrc==pSel->pSrc ); |
1332 | if( pStep->pExprList ) pSel->pEList = 0; |
1333 | pSel->pSrc = 0; |
1334 | sqlite3SelectDelete(db, pSel); |
1335 | } |
1336 | if( pStep->pFrom ){ |
1337 | int i; |
1338 | for(i=0; i<pStep->pFrom->nSrc && rc==SQLITE_OK; i++){ |
1339 | SrcItem *p = &pStep->pFrom->a[i]; |
1340 | if( p->pSelect ){ |
1341 | sqlite3SelectPrep(pParse, p->pSelect, 0); |
1342 | } |
1343 | } |
1344 | } |
1345 | |
1346 | if( db->mallocFailed ){ |
1347 | rc = SQLITE_NOMEM; |
1348 | } |
1349 | sNC.pSrcList = pSrc; |
1350 | if( rc==SQLITE_OK && pStep->pWhere ){ |
1351 | rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere); |
1352 | } |
1353 | if( rc==SQLITE_OK ){ |
1354 | rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList); |
1355 | } |
1356 | assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) ); |
1357 | if( pStep->pUpsert && rc==SQLITE_OK ){ |
1358 | Upsert *pUpsert = pStep->pUpsert; |
1359 | pUpsert->pUpsertSrc = pSrc; |
1360 | sNC.uNC.pUpsert = pUpsert; |
1361 | sNC.ncFlags = NC_UUpsert; |
1362 | rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget); |
1363 | if( rc==SQLITE_OK ){ |
1364 | ExprList *pUpsertSet = pUpsert->pUpsertSet; |
1365 | rc = sqlite3ResolveExprListNames(&sNC, pUpsertSet); |
1366 | } |
1367 | if( rc==SQLITE_OK ){ |
1368 | rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertWhere); |
1369 | } |
1370 | if( rc==SQLITE_OK ){ |
1371 | rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere); |
1372 | } |
1373 | sNC.ncFlags = 0; |
1374 | } |
1375 | sNC.pSrcList = 0; |
1376 | sqlite3SrcListDelete(db, pSrc); |
1377 | }else{ |
1378 | rc = SQLITE_NOMEM; |
1379 | } |
1380 | } |
1381 | } |
1382 | return rc; |
1383 | } |
1384 | |
1385 | /* |
1386 | ** Invoke sqlite3WalkExpr() or sqlite3WalkSelect() on all Select or Expr |
1387 | ** objects that are part of the trigger passed as the second argument. |
1388 | */ |
1389 | static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){ |
1390 | TriggerStep *pStep; |
1391 | |
1392 | /* Find tokens to edit in WHEN clause */ |
1393 | sqlite3WalkExpr(pWalker, pTrigger->pWhen); |
1394 | |
1395 | /* Find tokens to edit in trigger steps */ |
1396 | for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ |
1397 | sqlite3WalkSelect(pWalker, pStep->pSelect); |
1398 | sqlite3WalkExpr(pWalker, pStep->pWhere); |
1399 | sqlite3WalkExprList(pWalker, pStep->pExprList); |
1400 | if( pStep->pUpsert ){ |
1401 | Upsert *pUpsert = pStep->pUpsert; |
1402 | sqlite3WalkExprList(pWalker, pUpsert->pUpsertTarget); |
1403 | sqlite3WalkExprList(pWalker, pUpsert->pUpsertSet); |
1404 | sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere); |
1405 | sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere); |
1406 | } |
1407 | if( pStep->pFrom ){ |
1408 | int i; |
1409 | for(i=0; i<pStep->pFrom->nSrc; i++){ |
1410 | sqlite3WalkSelect(pWalker, pStep->pFrom->a[i].pSelect); |
1411 | } |
1412 | } |
1413 | } |
1414 | } |
1415 | |
1416 | /* |
1417 | ** Free the contents of Parse object (*pParse). Do not free the memory |
1418 | ** occupied by the Parse object itself. |
1419 | */ |
1420 | static void renameParseCleanup(Parse *pParse){ |
1421 | sqlite3 *db = pParse->db; |
1422 | Index *pIdx; |
1423 | if( pParse->pVdbe ){ |
1424 | sqlite3VdbeFinalize(pParse->pVdbe); |
1425 | } |
1426 | sqlite3DeleteTable(db, pParse->pNewTable); |
1427 | while( (pIdx = pParse->pNewIndex)!=0 ){ |
1428 | pParse->pNewIndex = pIdx->pNext; |
1429 | sqlite3FreeIndex(db, pIdx); |
1430 | } |
1431 | sqlite3DeleteTrigger(db, pParse->pNewTrigger); |
1432 | sqlite3DbFree(db, pParse->zErrMsg); |
1433 | renameTokenFree(db, pParse->pRename); |
1434 | sqlite3ParseObjectReset(pParse); |
1435 | } |
1436 | |
1437 | /* |
1438 | ** SQL function: |
1439 | ** |
1440 | ** sqlite_rename_column(SQL,TYPE,OBJ,DB,TABLE,COL,NEWNAME,QUOTE,TEMP) |
1441 | ** |
1442 | ** 0. zSql: SQL statement to rewrite |
1443 | ** 1. type: Type of object ("table", "view" etc.) |
1444 | ** 2. object: Name of object |
1445 | ** 3. Database: Database name (e.g. "main") |
1446 | ** 4. Table: Table name |
1447 | ** 5. iCol: Index of column to rename |
1448 | ** 6. zNew: New column name |
1449 | ** 7. bQuote: Non-zero if the new column name should be quoted. |
1450 | ** 8. bTemp: True if zSql comes from temp schema |
1451 | ** |
1452 | ** Do a column rename operation on the CREATE statement given in zSql. |
1453 | ** The iCol-th column (left-most is 0) of table zTable is renamed from zCol |
1454 | ** into zNew. The name should be quoted if bQuote is true. |
1455 | ** |
1456 | ** This function is used internally by the ALTER TABLE RENAME COLUMN command. |
1457 | ** It is only accessible to SQL created using sqlite3NestedParse(). It is |
1458 | ** not reachable from ordinary SQL passed into sqlite3_prepare() unless the |
1459 | ** SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test setting is enabled. |
1460 | */ |
1461 | static void renameColumnFunc( |
1462 | sqlite3_context *context, |
1463 | int NotUsed, |
1464 | sqlite3_value **argv |
1465 | ){ |
1466 | sqlite3 *db = sqlite3_context_db_handle(context); |
1467 | RenameCtx sCtx; |
1468 | const char *zSql = (const char*)sqlite3_value_text(argv[0]); |
1469 | const char *zDb = (const char*)sqlite3_value_text(argv[3]); |
1470 | const char *zTable = (const char*)sqlite3_value_text(argv[4]); |
1471 | int iCol = sqlite3_value_int(argv[5]); |
1472 | const char *zNew = (const char*)sqlite3_value_text(argv[6]); |
1473 | int bQuote = sqlite3_value_int(argv[7]); |
1474 | int bTemp = sqlite3_value_int(argv[8]); |
1475 | const char *zOld; |
1476 | int rc; |
1477 | Parse sParse; |
1478 | Walker sWalker; |
1479 | Index *pIdx; |
1480 | int i; |
1481 | Table *pTab; |
1482 | #ifndef SQLITE_OMIT_AUTHORIZATION |
1483 | sqlite3_xauth xAuth = db->xAuth; |
1484 | #endif |
1485 | |
1486 | UNUSED_PARAMETER(NotUsed); |
1487 | if( zSql==0 ) return; |
1488 | if( zTable==0 ) return; |
1489 | if( zNew==0 ) return; |
1490 | if( iCol<0 ) return; |
1491 | sqlite3BtreeEnterAll(db); |
1492 | pTab = sqlite3FindTable(db, zTable, zDb); |
1493 | if( pTab==0 || iCol>=pTab->nCol ){ |
1494 | sqlite3BtreeLeaveAll(db); |
1495 | return; |
1496 | } |
1497 | zOld = pTab->aCol[iCol].zCnName; |
1498 | memset(&sCtx, 0, sizeof(sCtx)); |
1499 | sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol); |
1500 | |
1501 | #ifndef SQLITE_OMIT_AUTHORIZATION |
1502 | db->xAuth = 0; |
1503 | #endif |
1504 | rc = renameParseSql(&sParse, zDb, db, zSql, bTemp); |
1505 | |
1506 | /* Find tokens that need to be replaced. */ |
1507 | memset(&sWalker, 0, sizeof(Walker)); |
1508 | sWalker.pParse = &sParse; |
1509 | sWalker.xExprCallback = renameColumnExprCb; |
1510 | sWalker.xSelectCallback = renameColumnSelectCb; |
1511 | sWalker.u.pRename = &sCtx; |
1512 | |
1513 | sCtx.pTab = pTab; |
1514 | if( rc!=SQLITE_OK ) goto renameColumnFunc_done; |
1515 | if( sParse.pNewTable ){ |
1516 | if( IsView(sParse.pNewTable) ){ |
1517 | Select *pSelect = sParse.pNewTable->u.view.pSelect; |
1518 | pSelect->selFlags &= ~SF_View; |
1519 | sParse.rc = SQLITE_OK; |
1520 | sqlite3SelectPrep(&sParse, pSelect, 0); |
1521 | rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc); |
1522 | if( rc==SQLITE_OK ){ |
1523 | sqlite3WalkSelect(&sWalker, pSelect); |
1524 | } |
1525 | if( rc!=SQLITE_OK ) goto renameColumnFunc_done; |
1526 | }else if( IsOrdinaryTable(sParse.pNewTable) ){ |
1527 | /* A regular table */ |
1528 | int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName); |
1529 | FKey *pFKey; |
1530 | sCtx.pTab = sParse.pNewTable; |
1531 | if( bFKOnly==0 ){ |
1532 | if( iCol<sParse.pNewTable->nCol ){ |
1533 | renameTokenFind( |
1534 | &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zCnName |
1535 | ); |
1536 | } |
1537 | if( sCtx.iCol<0 ){ |
1538 | renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey); |
1539 | } |
1540 | sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck); |
1541 | for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){ |
1542 | sqlite3WalkExprList(&sWalker, pIdx->aColExpr); |
1543 | } |
1544 | for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){ |
1545 | sqlite3WalkExprList(&sWalker, pIdx->aColExpr); |
1546 | } |
1547 | #ifndef SQLITE_OMIT_GENERATED_COLUMNS |
1548 | for(i=0; i<sParse.pNewTable->nCol; i++){ |
1549 | Expr *pExpr = sqlite3ColumnExpr(sParse.pNewTable, |
1550 | &sParse.pNewTable->aCol[i]); |
1551 | sqlite3WalkExpr(&sWalker, pExpr); |
1552 | } |
1553 | #endif |
1554 | } |
1555 | |
1556 | assert( IsOrdinaryTable(sParse.pNewTable) ); |
1557 | for(pFKey=sParse.pNewTable->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ |
1558 | for(i=0; i<pFKey->nCol; i++){ |
1559 | if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){ |
1560 | renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]); |
1561 | } |
1562 | if( 0==sqlite3_stricmp(pFKey->zTo, zTable) |
1563 | && 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld) |
1564 | ){ |
1565 | renameTokenFind(&sParse, &sCtx, (void*)pFKey->aCol[i].zCol); |
1566 | } |
1567 | } |
1568 | } |
1569 | } |
1570 | }else if( sParse.pNewIndex ){ |
1571 | sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr); |
1572 | sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); |
1573 | }else{ |
1574 | /* A trigger */ |
1575 | TriggerStep *pStep; |
1576 | rc = renameResolveTrigger(&sParse); |
1577 | if( rc!=SQLITE_OK ) goto renameColumnFunc_done; |
1578 | |
1579 | for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){ |
1580 | if( pStep->zTarget ){ |
1581 | Table *pTarget = sqlite3LocateTable(&sParse, 0, pStep->zTarget, zDb); |
1582 | if( pTarget==pTab ){ |
1583 | if( pStep->pUpsert ){ |
1584 | ExprList *pUpsertSet = pStep->pUpsert->pUpsertSet; |
1585 | renameColumnElistNames(&sParse, &sCtx, pUpsertSet, zOld); |
1586 | } |
1587 | renameColumnIdlistNames(&sParse, &sCtx, pStep->pIdList, zOld); |
1588 | renameColumnElistNames(&sParse, &sCtx, pStep->pExprList, zOld); |
1589 | } |
1590 | } |
1591 | } |
1592 | |
1593 | |
1594 | /* Find tokens to edit in UPDATE OF clause */ |
1595 | if( sParse.pTriggerTab==pTab ){ |
1596 | renameColumnIdlistNames(&sParse, &sCtx,sParse.pNewTrigger->pColumns,zOld); |
1597 | } |
1598 | |
1599 | /* Find tokens to edit in various expressions and selects */ |
1600 | renameWalkTrigger(&sWalker, sParse.pNewTrigger); |
1601 | } |
1602 | |
1603 | assert( rc==SQLITE_OK ); |
1604 | rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote); |
1605 | |
1606 | renameColumnFunc_done: |
1607 | if( rc!=SQLITE_OK ){ |
1608 | if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){ |
1609 | sqlite3_result_value(context, argv[0]); |
1610 | }else if( sParse.zErrMsg ){ |
1611 | renameColumnParseError(context, "" , argv[1], argv[2], &sParse); |
1612 | }else{ |
1613 | sqlite3_result_error_code(context, rc); |
1614 | } |
1615 | } |
1616 | |
1617 | renameParseCleanup(&sParse); |
1618 | renameTokenFree(db, sCtx.pList); |
1619 | #ifndef SQLITE_OMIT_AUTHORIZATION |
1620 | db->xAuth = xAuth; |
1621 | #endif |
1622 | sqlite3BtreeLeaveAll(db); |
1623 | } |
1624 | |
1625 | /* |
1626 | ** Walker expression callback used by "RENAME TABLE". |
1627 | */ |
1628 | static int renameTableExprCb(Walker *pWalker, Expr *pExpr){ |
1629 | RenameCtx *p = pWalker->u.pRename; |
1630 | if( pExpr->op==TK_COLUMN |
1631 | && ALWAYS(ExprUseYTab(pExpr)) |
1632 | && p->pTab==pExpr->y.pTab |
1633 | ){ |
1634 | renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab); |
1635 | } |
1636 | return WRC_Continue; |
1637 | } |
1638 | |
1639 | /* |
1640 | ** Walker select callback used by "RENAME TABLE". |
1641 | */ |
1642 | static int renameTableSelectCb(Walker *pWalker, Select *pSelect){ |
1643 | int i; |
1644 | RenameCtx *p = pWalker->u.pRename; |
1645 | SrcList *pSrc = pSelect->pSrc; |
1646 | if( pSelect->selFlags & (SF_View|SF_CopyCte) ){ |
1647 | testcase( pSelect->selFlags & SF_View ); |
1648 | testcase( pSelect->selFlags & SF_CopyCte ); |
1649 | return WRC_Prune; |
1650 | } |
1651 | if( NEVER(pSrc==0) ){ |
1652 | assert( pWalker->pParse->db->mallocFailed ); |
1653 | return WRC_Abort; |
1654 | } |
1655 | for(i=0; i<pSrc->nSrc; i++){ |
1656 | SrcItem *pItem = &pSrc->a[i]; |
1657 | if( pItem->pTab==p->pTab ){ |
1658 | renameTokenFind(pWalker->pParse, p, pItem->zName); |
1659 | } |
1660 | } |
1661 | renameWalkWith(pWalker, pSelect); |
1662 | |
1663 | return WRC_Continue; |
1664 | } |
1665 | |
1666 | |
1667 | /* |
1668 | ** This C function implements an SQL user function that is used by SQL code |
1669 | ** generated by the ALTER TABLE ... RENAME command to modify the definition |
1670 | ** of any foreign key constraints that use the table being renamed as the |
1671 | ** parent table. It is passed three arguments: |
1672 | ** |
1673 | ** 0: The database containing the table being renamed. |
1674 | ** 1. type: Type of object ("table", "view" etc.) |
1675 | ** 2. object: Name of object |
1676 | ** 3: The complete text of the schema statement being modified, |
1677 | ** 4: The old name of the table being renamed, and |
1678 | ** 5: The new name of the table being renamed. |
1679 | ** 6: True if the schema statement comes from the temp db. |
1680 | ** |
1681 | ** It returns the new schema statement. For example: |
1682 | ** |
1683 | ** sqlite_rename_table('main', 'CREATE TABLE t1(a REFERENCES t2)','t2','t3',0) |
1684 | ** -> 'CREATE TABLE t1(a REFERENCES t3)' |
1685 | */ |
1686 | static void renameTableFunc( |
1687 | sqlite3_context *context, |
1688 | int NotUsed, |
1689 | sqlite3_value **argv |
1690 | ){ |
1691 | sqlite3 *db = sqlite3_context_db_handle(context); |
1692 | const char *zDb = (const char*)sqlite3_value_text(argv[0]); |
1693 | const char *zInput = (const char*)sqlite3_value_text(argv[3]); |
1694 | const char *zOld = (const char*)sqlite3_value_text(argv[4]); |
1695 | const char *zNew = (const char*)sqlite3_value_text(argv[5]); |
1696 | int bTemp = sqlite3_value_int(argv[6]); |
1697 | UNUSED_PARAMETER(NotUsed); |
1698 | |
1699 | if( zInput && zOld && zNew ){ |
1700 | Parse sParse; |
1701 | int rc; |
1702 | int bQuote = 1; |
1703 | RenameCtx sCtx; |
1704 | Walker sWalker; |
1705 | |
1706 | #ifndef SQLITE_OMIT_AUTHORIZATION |
1707 | sqlite3_xauth xAuth = db->xAuth; |
1708 | db->xAuth = 0; |
1709 | #endif |
1710 | |
1711 | sqlite3BtreeEnterAll(db); |
1712 | |
1713 | memset(&sCtx, 0, sizeof(RenameCtx)); |
1714 | sCtx.pTab = sqlite3FindTable(db, zOld, zDb); |
1715 | memset(&sWalker, 0, sizeof(Walker)); |
1716 | sWalker.pParse = &sParse; |
1717 | sWalker.xExprCallback = renameTableExprCb; |
1718 | sWalker.xSelectCallback = renameTableSelectCb; |
1719 | sWalker.u.pRename = &sCtx; |
1720 | |
1721 | rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); |
1722 | |
1723 | if( rc==SQLITE_OK ){ |
1724 | int isLegacy = (db->flags & SQLITE_LegacyAlter); |
1725 | if( sParse.pNewTable ){ |
1726 | Table *pTab = sParse.pNewTable; |
1727 | |
1728 | if( IsView(pTab) ){ |
1729 | if( isLegacy==0 ){ |
1730 | Select *pSelect = pTab->u.view.pSelect; |
1731 | NameContext sNC; |
1732 | memset(&sNC, 0, sizeof(sNC)); |
1733 | sNC.pParse = &sParse; |
1734 | |
1735 | assert( pSelect->selFlags & SF_View ); |
1736 | pSelect->selFlags &= ~SF_View; |
1737 | sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC); |
1738 | if( sParse.nErr ){ |
1739 | rc = sParse.rc; |
1740 | }else{ |
1741 | sqlite3WalkSelect(&sWalker, pTab->u.view.pSelect); |
1742 | } |
1743 | } |
1744 | }else{ |
1745 | /* Modify any FK definitions to point to the new table. */ |
1746 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
1747 | if( (isLegacy==0 || (db->flags & SQLITE_ForeignKeys)) |
1748 | && !IsVirtual(pTab) |
1749 | ){ |
1750 | FKey *pFKey; |
1751 | assert( IsOrdinaryTable(pTab) ); |
1752 | for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ |
1753 | if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){ |
1754 | renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo); |
1755 | } |
1756 | } |
1757 | } |
1758 | #endif |
1759 | |
1760 | /* If this is the table being altered, fix any table refs in CHECK |
1761 | ** expressions. Also update the name that appears right after the |
1762 | ** "CREATE [VIRTUAL] TABLE" bit. */ |
1763 | if( sqlite3_stricmp(zOld, pTab->zName)==0 ){ |
1764 | sCtx.pTab = pTab; |
1765 | if( isLegacy==0 ){ |
1766 | sqlite3WalkExprList(&sWalker, pTab->pCheck); |
1767 | } |
1768 | renameTokenFind(&sParse, &sCtx, pTab->zName); |
1769 | } |
1770 | } |
1771 | } |
1772 | |
1773 | else if( sParse.pNewIndex ){ |
1774 | renameTokenFind(&sParse, &sCtx, sParse.pNewIndex->zName); |
1775 | if( isLegacy==0 ){ |
1776 | sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); |
1777 | } |
1778 | } |
1779 | |
1780 | #ifndef SQLITE_OMIT_TRIGGER |
1781 | else{ |
1782 | Trigger *pTrigger = sParse.pNewTrigger; |
1783 | TriggerStep *pStep; |
1784 | if( 0==sqlite3_stricmp(sParse.pNewTrigger->table, zOld) |
1785 | && sCtx.pTab->pSchema==pTrigger->pTabSchema |
1786 | ){ |
1787 | renameTokenFind(&sParse, &sCtx, sParse.pNewTrigger->table); |
1788 | } |
1789 | |
1790 | if( isLegacy==0 ){ |
1791 | rc = renameResolveTrigger(&sParse); |
1792 | if( rc==SQLITE_OK ){ |
1793 | renameWalkTrigger(&sWalker, pTrigger); |
1794 | for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ |
1795 | if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){ |
1796 | renameTokenFind(&sParse, &sCtx, pStep->zTarget); |
1797 | } |
1798 | if( pStep->pFrom ){ |
1799 | int i; |
1800 | for(i=0; i<pStep->pFrom->nSrc; i++){ |
1801 | SrcItem *pItem = &pStep->pFrom->a[i]; |
1802 | if( 0==sqlite3_stricmp(pItem->zName, zOld) ){ |
1803 | renameTokenFind(&sParse, &sCtx, pItem->zName); |
1804 | } |
1805 | } |
1806 | } |
1807 | } |
1808 | } |
1809 | } |
1810 | } |
1811 | #endif |
1812 | } |
1813 | |
1814 | if( rc==SQLITE_OK ){ |
1815 | rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote); |
1816 | } |
1817 | if( rc!=SQLITE_OK ){ |
1818 | if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){ |
1819 | sqlite3_result_value(context, argv[3]); |
1820 | }else if( sParse.zErrMsg ){ |
1821 | renameColumnParseError(context, "" , argv[1], argv[2], &sParse); |
1822 | }else{ |
1823 | sqlite3_result_error_code(context, rc); |
1824 | } |
1825 | } |
1826 | |
1827 | renameParseCleanup(&sParse); |
1828 | renameTokenFree(db, sCtx.pList); |
1829 | sqlite3BtreeLeaveAll(db); |
1830 | #ifndef SQLITE_OMIT_AUTHORIZATION |
1831 | db->xAuth = xAuth; |
1832 | #endif |
1833 | } |
1834 | |
1835 | return; |
1836 | } |
1837 | |
1838 | static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){ |
1839 | if( pExpr->op==TK_STRING && (pExpr->flags & EP_DblQuoted) ){ |
1840 | renameTokenFind(pWalker->pParse, pWalker->u.pRename, (const void*)pExpr); |
1841 | } |
1842 | return WRC_Continue; |
1843 | } |
1844 | |
1845 | /* SQL function: sqlite_rename_quotefix(DB,SQL) |
1846 | ** |
1847 | ** Rewrite the DDL statement "SQL" so that any string literals that use |
1848 | ** double-quotes use single quotes instead. |
1849 | ** |
1850 | ** Two arguments must be passed: |
1851 | ** |
1852 | ** 0: Database name ("main", "temp" etc.). |
1853 | ** 1: SQL statement to edit. |
1854 | ** |
1855 | ** The returned value is the modified SQL statement. For example, given |
1856 | ** the database schema: |
1857 | ** |
1858 | ** CREATE TABLE t1(a, b, c); |
1859 | ** |
1860 | ** SELECT sqlite_rename_quotefix('main', |
1861 | ** 'CREATE VIEW v1 AS SELECT "a", "string" FROM t1' |
1862 | ** ); |
1863 | ** |
1864 | ** returns the string: |
1865 | ** |
1866 | ** CREATE VIEW v1 AS SELECT "a", 'string' FROM t1 |
1867 | ** |
1868 | ** If there is a error in the input SQL, then raise an error, except |
1869 | ** if PRAGMA writable_schema=ON, then just return the input string |
1870 | ** unmodified following an error. |
1871 | */ |
1872 | static void renameQuotefixFunc( |
1873 | sqlite3_context *context, |
1874 | int NotUsed, |
1875 | sqlite3_value **argv |
1876 | ){ |
1877 | sqlite3 *db = sqlite3_context_db_handle(context); |
1878 | char const *zDb = (const char*)sqlite3_value_text(argv[0]); |
1879 | char const *zInput = (const char*)sqlite3_value_text(argv[1]); |
1880 | |
1881 | #ifndef SQLITE_OMIT_AUTHORIZATION |
1882 | sqlite3_xauth xAuth = db->xAuth; |
1883 | db->xAuth = 0; |
1884 | #endif |
1885 | |
1886 | sqlite3BtreeEnterAll(db); |
1887 | |
1888 | UNUSED_PARAMETER(NotUsed); |
1889 | if( zDb && zInput ){ |
1890 | int rc; |
1891 | Parse sParse; |
1892 | rc = renameParseSql(&sParse, zDb, db, zInput, 0); |
1893 | |
1894 | if( rc==SQLITE_OK ){ |
1895 | RenameCtx sCtx; |
1896 | Walker sWalker; |
1897 | |
1898 | /* Walker to find tokens that need to be replaced. */ |
1899 | memset(&sCtx, 0, sizeof(RenameCtx)); |
1900 | memset(&sWalker, 0, sizeof(Walker)); |
1901 | sWalker.pParse = &sParse; |
1902 | sWalker.xExprCallback = renameQuotefixExprCb; |
1903 | sWalker.xSelectCallback = renameColumnSelectCb; |
1904 | sWalker.u.pRename = &sCtx; |
1905 | |
1906 | if( sParse.pNewTable ){ |
1907 | if( IsView(sParse.pNewTable) ){ |
1908 | Select *pSelect = sParse.pNewTable->u.view.pSelect; |
1909 | pSelect->selFlags &= ~SF_View; |
1910 | sParse.rc = SQLITE_OK; |
1911 | sqlite3SelectPrep(&sParse, pSelect, 0); |
1912 | rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc); |
1913 | if( rc==SQLITE_OK ){ |
1914 | sqlite3WalkSelect(&sWalker, pSelect); |
1915 | } |
1916 | }else{ |
1917 | int i; |
1918 | sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck); |
1919 | #ifndef SQLITE_OMIT_GENERATED_COLUMNS |
1920 | for(i=0; i<sParse.pNewTable->nCol; i++){ |
1921 | sqlite3WalkExpr(&sWalker, |
1922 | sqlite3ColumnExpr(sParse.pNewTable, |
1923 | &sParse.pNewTable->aCol[i])); |
1924 | } |
1925 | #endif /* SQLITE_OMIT_GENERATED_COLUMNS */ |
1926 | } |
1927 | }else if( sParse.pNewIndex ){ |
1928 | sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr); |
1929 | sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); |
1930 | }else{ |
1931 | #ifndef SQLITE_OMIT_TRIGGER |
1932 | rc = renameResolveTrigger(&sParse); |
1933 | if( rc==SQLITE_OK ){ |
1934 | renameWalkTrigger(&sWalker, sParse.pNewTrigger); |
1935 | } |
1936 | #endif /* SQLITE_OMIT_TRIGGER */ |
1937 | } |
1938 | |
1939 | if( rc==SQLITE_OK ){ |
1940 | rc = renameEditSql(context, &sCtx, zInput, 0, 0); |
1941 | } |
1942 | renameTokenFree(db, sCtx.pList); |
1943 | } |
1944 | if( rc!=SQLITE_OK ){ |
1945 | if( sqlite3WritableSchema(db) && rc==SQLITE_ERROR ){ |
1946 | sqlite3_result_value(context, argv[1]); |
1947 | }else{ |
1948 | sqlite3_result_error_code(context, rc); |
1949 | } |
1950 | } |
1951 | renameParseCleanup(&sParse); |
1952 | } |
1953 | |
1954 | #ifndef SQLITE_OMIT_AUTHORIZATION |
1955 | db->xAuth = xAuth; |
1956 | #endif |
1957 | |
1958 | sqlite3BtreeLeaveAll(db); |
1959 | } |
1960 | |
1961 | /* Function: sqlite_rename_test(DB,SQL,TYPE,NAME,ISTEMP,WHEN,DQS) |
1962 | ** |
1963 | ** An SQL user function that checks that there are no parse or symbol |
1964 | ** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement. |
1965 | ** After an ALTER TABLE .. RENAME operation is performed and the schema |
1966 | ** reloaded, this function is called on each SQL statement in the schema |
1967 | ** to ensure that it is still usable. |
1968 | ** |
1969 | ** 0: Database name ("main", "temp" etc.). |
1970 | ** 1: SQL statement. |
1971 | ** 2: Object type ("view", "table", "trigger" or "index"). |
1972 | ** 3: Object name. |
1973 | ** 4: True if object is from temp schema. |
1974 | ** 5: "when" part of error message. |
1975 | ** 6: True to disable the DQS quirk when parsing SQL. |
1976 | ** |
1977 | ** The return value is computed as follows: |
1978 | ** |
1979 | ** A. If an error is seen and not in PRAGMA writable_schema=ON mode, |
1980 | ** then raise the error. |
1981 | ** B. Else if a trigger is created and the the table that the trigger is |
1982 | ** attached to is in database zDb, then return 1. |
1983 | ** C. Otherwise return NULL. |
1984 | */ |
1985 | static void renameTableTest( |
1986 | sqlite3_context *context, |
1987 | int NotUsed, |
1988 | sqlite3_value **argv |
1989 | ){ |
1990 | sqlite3 *db = sqlite3_context_db_handle(context); |
1991 | char const *zDb = (const char*)sqlite3_value_text(argv[0]); |
1992 | char const *zInput = (const char*)sqlite3_value_text(argv[1]); |
1993 | int bTemp = sqlite3_value_int(argv[4]); |
1994 | int isLegacy = (db->flags & SQLITE_LegacyAlter); |
1995 | char const *zWhen = (const char*)sqlite3_value_text(argv[5]); |
1996 | int bNoDQS = sqlite3_value_int(argv[6]); |
1997 | |
1998 | #ifndef SQLITE_OMIT_AUTHORIZATION |
1999 | sqlite3_xauth xAuth = db->xAuth; |
2000 | db->xAuth = 0; |
2001 | #endif |
2002 | |
2003 | UNUSED_PARAMETER(NotUsed); |
2004 | |
2005 | if( zDb && zInput ){ |
2006 | int rc; |
2007 | Parse sParse; |
2008 | int flags = db->flags; |
2009 | if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL); |
2010 | rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); |
2011 | db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL)); |
2012 | if( rc==SQLITE_OK ){ |
2013 | if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){ |
2014 | NameContext sNC; |
2015 | memset(&sNC, 0, sizeof(sNC)); |
2016 | sNC.pParse = &sParse; |
2017 | sqlite3SelectPrep(&sParse, sParse.pNewTable->u.view.pSelect, &sNC); |
2018 | if( sParse.nErr ) rc = sParse.rc; |
2019 | } |
2020 | |
2021 | else if( sParse.pNewTrigger ){ |
2022 | if( isLegacy==0 ){ |
2023 | rc = renameResolveTrigger(&sParse); |
2024 | } |
2025 | if( rc==SQLITE_OK ){ |
2026 | int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema); |
2027 | int i2 = sqlite3FindDbName(db, zDb); |
2028 | if( i1==i2 ){ |
2029 | /* Handle output case B */ |
2030 | sqlite3_result_int(context, 1); |
2031 | } |
2032 | } |
2033 | } |
2034 | } |
2035 | |
2036 | if( rc!=SQLITE_OK && zWhen && !sqlite3WritableSchema(db) ){ |
2037 | /* Output case A */ |
2038 | renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse); |
2039 | } |
2040 | renameParseCleanup(&sParse); |
2041 | } |
2042 | |
2043 | #ifndef SQLITE_OMIT_AUTHORIZATION |
2044 | db->xAuth = xAuth; |
2045 | #endif |
2046 | } |
2047 | |
2048 | /* |
2049 | ** The implementation of internal UDF sqlite_drop_column(). |
2050 | ** |
2051 | ** Arguments: |
2052 | ** |
2053 | ** argv[0]: An integer - the index of the schema containing the table |
2054 | ** argv[1]: CREATE TABLE statement to modify. |
2055 | ** argv[2]: An integer - the index of the column to remove. |
2056 | ** |
2057 | ** The value returned is a string containing the CREATE TABLE statement |
2058 | ** with column argv[2] removed. |
2059 | */ |
2060 | static void dropColumnFunc( |
2061 | sqlite3_context *context, |
2062 | int NotUsed, |
2063 | sqlite3_value **argv |
2064 | ){ |
2065 | sqlite3 *db = sqlite3_context_db_handle(context); |
2066 | int iSchema = sqlite3_value_int(argv[0]); |
2067 | const char *zSql = (const char*)sqlite3_value_text(argv[1]); |
2068 | int iCol = sqlite3_value_int(argv[2]); |
2069 | const char *zDb = db->aDb[iSchema].zDbSName; |
2070 | int rc; |
2071 | Parse sParse; |
2072 | RenameToken *pCol; |
2073 | Table *pTab; |
2074 | const char *zEnd; |
2075 | char *zNew = 0; |
2076 | |
2077 | #ifndef SQLITE_OMIT_AUTHORIZATION |
2078 | sqlite3_xauth xAuth = db->xAuth; |
2079 | db->xAuth = 0; |
2080 | #endif |
2081 | |
2082 | UNUSED_PARAMETER(NotUsed); |
2083 | rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1); |
2084 | if( rc!=SQLITE_OK ) goto drop_column_done; |
2085 | pTab = sParse.pNewTable; |
2086 | if( pTab==0 || pTab->nCol==1 || iCol>=pTab->nCol ){ |
2087 | /* This can happen if the sqlite_schema table is corrupt */ |
2088 | rc = SQLITE_CORRUPT_BKPT; |
2089 | goto drop_column_done; |
2090 | } |
2091 | |
2092 | pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName); |
2093 | if( iCol<pTab->nCol-1 ){ |
2094 | RenameToken *pEnd; |
2095 | pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zCnName); |
2096 | zEnd = (const char*)pEnd->t.z; |
2097 | }else{ |
2098 | assert( IsOrdinaryTable(pTab) ); |
2099 | zEnd = (const char*)&zSql[pTab->u.tab.addColOffset]; |
2100 | while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--; |
2101 | } |
2102 | |
2103 | zNew = sqlite3MPrintf(db, "%.*s%s" , pCol->t.z-zSql, zSql, zEnd); |
2104 | sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT); |
2105 | sqlite3_free(zNew); |
2106 | |
2107 | drop_column_done: |
2108 | renameParseCleanup(&sParse); |
2109 | #ifndef SQLITE_OMIT_AUTHORIZATION |
2110 | db->xAuth = xAuth; |
2111 | #endif |
2112 | if( rc!=SQLITE_OK ){ |
2113 | sqlite3_result_error_code(context, rc); |
2114 | } |
2115 | } |
2116 | |
2117 | /* |
2118 | ** This function is called by the parser upon parsing an |
2119 | ** |
2120 | ** ALTER TABLE pSrc DROP COLUMN pName |
2121 | ** |
2122 | ** statement. Argument pSrc contains the possibly qualified name of the |
2123 | ** table being edited, and token pName the name of the column to drop. |
2124 | */ |
2125 | void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const Token *pName){ |
2126 | sqlite3 *db = pParse->db; /* Database handle */ |
2127 | Table *pTab; /* Table to modify */ |
2128 | int iDb; /* Index of db containing pTab in aDb[] */ |
2129 | const char *zDb; /* Database containing pTab ("main" etc.) */ |
2130 | char *zCol = 0; /* Name of column to drop */ |
2131 | int iCol; /* Index of column zCol in pTab->aCol[] */ |
2132 | |
2133 | /* Look up the table being altered. */ |
2134 | assert( pParse->pNewTable==0 ); |
2135 | assert( sqlite3BtreeHoldsAllMutexes(db) ); |
2136 | if( NEVER(db->mallocFailed) ) goto exit_drop_column; |
2137 | pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); |
2138 | if( !pTab ) goto exit_drop_column; |
2139 | |
2140 | /* Make sure this is not an attempt to ALTER a view, virtual table or |
2141 | ** system table. */ |
2142 | if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_drop_column; |
2143 | if( SQLITE_OK!=isRealTable(pParse, pTab, 1) ) goto exit_drop_column; |
2144 | |
2145 | /* Find the index of the column being dropped. */ |
2146 | zCol = sqlite3NameFromToken(db, pName); |
2147 | if( zCol==0 ){ |
2148 | assert( db->mallocFailed ); |
2149 | goto exit_drop_column; |
2150 | } |
2151 | iCol = sqlite3ColumnIndex(pTab, zCol); |
2152 | if( iCol<0 ){ |
2153 | sqlite3ErrorMsg(pParse, "no such column: \"%T\"" , pName); |
2154 | goto exit_drop_column; |
2155 | } |
2156 | |
2157 | /* Do not allow the user to drop a PRIMARY KEY column or a column |
2158 | ** constrained by a UNIQUE constraint. */ |
2159 | if( pTab->aCol[iCol].colFlags & (COLFLAG_PRIMKEY|COLFLAG_UNIQUE) ){ |
2160 | sqlite3ErrorMsg(pParse, "cannot drop %s column: \"%s\"" , |
2161 | (pTab->aCol[iCol].colFlags&COLFLAG_PRIMKEY) ? "PRIMARY KEY" : "UNIQUE" , |
2162 | zCol |
2163 | ); |
2164 | goto exit_drop_column; |
2165 | } |
2166 | |
2167 | /* Do not allow the number of columns to go to zero */ |
2168 | if( pTab->nCol<=1 ){ |
2169 | sqlite3ErrorMsg(pParse, "cannot drop column \"%s\": no other columns exist" ,zCol); |
2170 | goto exit_drop_column; |
2171 | } |
2172 | |
2173 | /* Edit the sqlite_schema table */ |
2174 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
2175 | assert( iDb>=0 ); |
2176 | zDb = db->aDb[iDb].zDbSName; |
2177 | #ifndef SQLITE_OMIT_AUTHORIZATION |
2178 | /* Invoke the authorization callback. */ |
2179 | if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, zCol) ){ |
2180 | goto exit_drop_column; |
2181 | } |
2182 | #endif |
2183 | renameTestSchema(pParse, zDb, iDb==1, "" , 0); |
2184 | renameFixQuotes(pParse, zDb, iDb==1); |
2185 | sqlite3NestedParse(pParse, |
2186 | "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " |
2187 | "sql = sqlite_drop_column(%d, sql, %d) " |
2188 | "WHERE (type=='table' AND tbl_name=%Q COLLATE nocase)" |
2189 | , zDb, iDb, iCol, pTab->zName |
2190 | ); |
2191 | |
2192 | /* Drop and reload the database schema. */ |
2193 | renameReloadSchema(pParse, iDb, INITFLAG_AlterDrop); |
2194 | renameTestSchema(pParse, zDb, iDb==1, "after drop column" , 1); |
2195 | |
2196 | /* Edit rows of table on disk */ |
2197 | if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){ |
2198 | int i; |
2199 | int addr; |
2200 | int reg; |
2201 | int regRec; |
2202 | Index *pPk = 0; |
2203 | int nField = 0; /* Number of non-virtual columns after drop */ |
2204 | int iCur; |
2205 | Vdbe *v = sqlite3GetVdbe(pParse); |
2206 | iCur = pParse->nTab++; |
2207 | sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite); |
2208 | addr = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); |
2209 | reg = ++pParse->nMem; |
2210 | if( HasRowid(pTab) ){ |
2211 | sqlite3VdbeAddOp2(v, OP_Rowid, iCur, reg); |
2212 | pParse->nMem += pTab->nCol; |
2213 | }else{ |
2214 | pPk = sqlite3PrimaryKeyIndex(pTab); |
2215 | pParse->nMem += pPk->nColumn; |
2216 | for(i=0; i<pPk->nKeyCol; i++){ |
2217 | sqlite3VdbeAddOp3(v, OP_Column, iCur, i, reg+i+1); |
2218 | } |
2219 | nField = pPk->nKeyCol; |
2220 | } |
2221 | regRec = ++pParse->nMem; |
2222 | for(i=0; i<pTab->nCol; i++){ |
2223 | if( i!=iCol && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){ |
2224 | int regOut; |
2225 | if( pPk ){ |
2226 | int iPos = sqlite3TableColumnToIndex(pPk, i); |
2227 | int iColPos = sqlite3TableColumnToIndex(pPk, iCol); |
2228 | if( iPos<pPk->nKeyCol ) continue; |
2229 | regOut = reg+1+iPos-(iPos>iColPos); |
2230 | }else{ |
2231 | regOut = reg+1+nField; |
2232 | } |
2233 | if( i==pTab->iPKey ){ |
2234 | sqlite3VdbeAddOp2(v, OP_Null, 0, regOut); |
2235 | }else{ |
2236 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut); |
2237 | } |
2238 | nField++; |
2239 | } |
2240 | } |
2241 | if( nField==0 ){ |
2242 | /* dbsqlfuzz 5f09e7bcc78b4954d06bf9f2400d7715f48d1fef */ |
2243 | pParse->nMem++; |
2244 | sqlite3VdbeAddOp2(v, OP_Null, 0, reg+1); |
2245 | nField = 1; |
2246 | } |
2247 | sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec); |
2248 | if( pPk ){ |
2249 | sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol); |
2250 | }else{ |
2251 | sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg); |
2252 | } |
2253 | sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION); |
2254 | |
2255 | sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1); VdbeCoverage(v); |
2256 | sqlite3VdbeJumpHere(v, addr); |
2257 | } |
2258 | |
2259 | exit_drop_column: |
2260 | sqlite3DbFree(db, zCol); |
2261 | sqlite3SrcListDelete(db, pSrc); |
2262 | } |
2263 | |
2264 | /* |
2265 | ** Register built-in functions used to help implement ALTER TABLE |
2266 | */ |
2267 | void sqlite3AlterFunctions(void){ |
2268 | static FuncDef aAlterTableFuncs[] = { |
2269 | INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc), |
2270 | INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc), |
2271 | INTERNAL_FUNCTION(sqlite_rename_test, 7, renameTableTest), |
2272 | INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc), |
2273 | INTERNAL_FUNCTION(sqlite_rename_quotefix,2, renameQuotefixFunc), |
2274 | }; |
2275 | sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); |
2276 | } |
2277 | #endif /* SQLITE_ALTER_TABLE */ |
2278 | |