diff options
author | dan miller | 2007-10-21 08:36:32 +0000 |
---|---|---|
committer | dan miller | 2007-10-21 08:36:32 +0000 |
commit | 2f8d7092bc2c9609fa98d6888106b96f38b22828 (patch) | |
tree | da6c37579258cc965b52a75aee6135fe44237698 /libraries/sqlite/win32/alter.c | |
parent | * Committing new PolicyManager based on an ACL system. (diff) | |
download | opensim-SC-2f8d7092bc2c9609fa98d6888106b96f38b22828.zip opensim-SC-2f8d7092bc2c9609fa98d6888106b96f38b22828.tar.gz opensim-SC-2f8d7092bc2c9609fa98d6888106b96f38b22828.tar.bz2 opensim-SC-2f8d7092bc2c9609fa98d6888106b96f38b22828.tar.xz |
libraries moved to opensim-libs, a new repository
Diffstat (limited to '')
-rwxr-xr-x | libraries/sqlite/win32/alter.c | 622 |
1 files changed, 0 insertions, 622 deletions
diff --git a/libraries/sqlite/win32/alter.c b/libraries/sqlite/win32/alter.c deleted file mode 100755 index 9d1ebd2..0000000 --- a/libraries/sqlite/win32/alter.c +++ /dev/null | |||
@@ -1,622 +0,0 @@ | |||
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 | ** $Id: alter.c,v 1.32 2007/08/29 14:06:23 danielk1977 Exp $ | ||
16 | */ | ||
17 | #include "sqliteInt.h" | ||
18 | #include <ctype.h> | ||
19 | |||
20 | /* | ||
21 | ** The code in this file only exists if we are not omitting the | ||
22 | ** ALTER TABLE logic from the build. | ||
23 | */ | ||
24 | #ifndef SQLITE_OMIT_ALTERTABLE | ||
25 | |||
26 | |||
27 | /* | ||
28 | ** This function is used by SQL generated to implement the | ||
29 | ** ALTER TABLE command. The first argument is the text of a CREATE TABLE or | ||
30 | ** CREATE INDEX command. The second is a table name. The table name in | ||
31 | ** the CREATE TABLE or CREATE INDEX statement is replaced with the third | ||
32 | ** argument and the result returned. Examples: | ||
33 | ** | ||
34 | ** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def') | ||
35 | ** -> 'CREATE TABLE def(a, b, c)' | ||
36 | ** | ||
37 | ** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def') | ||
38 | ** -> 'CREATE INDEX i ON def(a, b, c)' | ||
39 | */ | ||
40 | static void renameTableFunc( | ||
41 | sqlite3_context *context, | ||
42 | int argc, | ||
43 | sqlite3_value **argv | ||
44 | ){ | ||
45 | unsigned char const *zSql = sqlite3_value_text(argv[0]); | ||
46 | unsigned char const *zTableName = sqlite3_value_text(argv[1]); | ||
47 | |||
48 | int token; | ||
49 | Token tname; | ||
50 | unsigned char const *zCsr = zSql; | ||
51 | int len = 0; | ||
52 | char *zRet; | ||
53 | |||
54 | sqlite3 *db = sqlite3_user_data(context); | ||
55 | |||
56 | /* The principle used to locate the table name in the CREATE TABLE | ||
57 | ** statement is that the table name is the first token that is immediatedly | ||
58 | ** followed by a left parenthesis - TK_LP - or "USING" TK_USING. | ||
59 | */ | ||
60 | if( zSql ){ | ||
61 | do { | ||
62 | if( !*zCsr ){ | ||
63 | /* Ran out of input before finding an opening bracket. Return NULL. */ | ||
64 | return; | ||
65 | } | ||
66 | |||
67 | /* Store the token that zCsr points to in tname. */ | ||
68 | tname.z = zCsr; | ||
69 | tname.n = len; | ||
70 | |||
71 | /* Advance zCsr to the next token. Store that token type in 'token', | ||
72 | ** and it's length in 'len' (to be used next iteration of this loop). | ||
73 | */ | ||
74 | do { | ||
75 | zCsr += len; | ||
76 | len = sqlite3GetToken(zCsr, &token); | ||
77 | } while( token==TK_SPACE ); | ||
78 | assert( len>0 ); | ||
79 | } while( token!=TK_LP && token!=TK_USING ); | ||
80 | |||
81 | zRet = sqlite3MPrintf(db, "%.*s%Q%s", tname.z - zSql, zSql, | ||
82 | zTableName, tname.z+tname.n); | ||
83 | sqlite3_result_text(context, zRet, -1, sqlite3_free); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | #ifndef SQLITE_OMIT_TRIGGER | ||
88 | /* This function is used by SQL generated to implement the | ||
89 | ** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER | ||
90 | ** statement. The second is a table name. The table name in the CREATE | ||
91 | ** TRIGGER statement is replaced with the third argument and the result | ||
92 | ** returned. This is analagous to renameTableFunc() above, except for CREATE | ||
93 | ** TRIGGER, not CREATE INDEX and CREATE TABLE. | ||
94 | */ | ||
95 | static void renameTriggerFunc( | ||
96 | sqlite3_context *context, | ||
97 | int argc, | ||
98 | sqlite3_value **argv | ||
99 | ){ | ||
100 | unsigned char const *zSql = sqlite3_value_text(argv[0]); | ||
101 | unsigned char const *zTableName = sqlite3_value_text(argv[1]); | ||
102 | |||
103 | int token; | ||
104 | Token tname; | ||
105 | int dist = 3; | ||
106 | unsigned char const *zCsr = zSql; | ||
107 | int len = 0; | ||
108 | char *zRet; | ||
109 | |||
110 | sqlite3 *db = sqlite3_user_data(context); | ||
111 | |||
112 | /* The principle used to locate the table name in the CREATE TRIGGER | ||
113 | ** statement is that the table name is the first token that is immediatedly | ||
114 | ** preceded by either TK_ON or TK_DOT and immediatedly followed by one | ||
115 | ** of TK_WHEN, TK_BEGIN or TK_FOR. | ||
116 | */ | ||
117 | if( zSql ){ | ||
118 | do { | ||
119 | |||
120 | if( !*zCsr ){ | ||
121 | /* Ran out of input before finding the table name. Return NULL. */ | ||
122 | return; | ||
123 | } | ||
124 | |||
125 | /* Store the token that zCsr points to in tname. */ | ||
126 | tname.z = zCsr; | ||
127 | tname.n = len; | ||
128 | |||
129 | /* Advance zCsr to the next token. Store that token type in 'token', | ||
130 | ** and it's length in 'len' (to be used next iteration of this loop). | ||
131 | */ | ||
132 | do { | ||
133 | zCsr += len; | ||
134 | len = sqlite3GetToken(zCsr, &token); | ||
135 | }while( token==TK_SPACE ); | ||
136 | assert( len>0 ); | ||
137 | |||
138 | /* Variable 'dist' stores the number of tokens read since the most | ||
139 | ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN | ||
140 | ** token is read and 'dist' equals 2, the condition stated above | ||
141 | ** to be met. | ||
142 | ** | ||
143 | ** Note that ON cannot be a database, table or column name, so | ||
144 | ** there is no need to worry about syntax like | ||
145 | ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc. | ||
146 | */ | ||
147 | dist++; | ||
148 | if( token==TK_DOT || token==TK_ON ){ | ||
149 | dist = 0; | ||
150 | } | ||
151 | } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) ); | ||
152 | |||
153 | /* Variable tname now contains the token that is the old table-name | ||
154 | ** in the CREATE TRIGGER statement. | ||
155 | */ | ||
156 | zRet = sqlite3MPrintf(db, "%.*s%Q%s", tname.z - zSql, zSql, | ||
157 | zTableName, tname.z+tname.n); | ||
158 | sqlite3_result_text(context, zRet, -1, sqlite3_free); | ||
159 | } | ||
160 | } | ||
161 | #endif /* !SQLITE_OMIT_TRIGGER */ | ||
162 | |||
163 | /* | ||
164 | ** Register built-in functions used to help implement ALTER TABLE | ||
165 | */ | ||
166 | void sqlite3AlterFunctions(sqlite3 *db){ | ||
167 | static const struct { | ||
168 | char *zName; | ||
169 | signed char nArg; | ||
170 | void (*xFunc)(sqlite3_context*,int,sqlite3_value **); | ||
171 | } aFuncs[] = { | ||
172 | { "sqlite_rename_table", 2, renameTableFunc}, | ||
173 | #ifndef SQLITE_OMIT_TRIGGER | ||
174 | { "sqlite_rename_trigger", 2, renameTriggerFunc}, | ||
175 | #endif | ||
176 | }; | ||
177 | int i; | ||
178 | |||
179 | for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ | ||
180 | sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg, | ||
181 | SQLITE_UTF8, (void *)db, aFuncs[i].xFunc, 0, 0); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | ** Generate the text of a WHERE expression which can be used to select all | ||
187 | ** temporary triggers on table pTab from the sqlite_temp_master table. If | ||
188 | ** table pTab has no temporary triggers, or is itself stored in the | ||
189 | ** temporary database, NULL is returned. | ||
190 | */ | ||
191 | static char *whereTempTriggers(Parse *pParse, Table *pTab){ | ||
192 | Trigger *pTrig; | ||
193 | char *zWhere = 0; | ||
194 | char *tmp = 0; | ||
195 | const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */ | ||
196 | |||
197 | /* If the table is not located in the temp-db (in which case NULL is | ||
198 | ** returned, loop through the tables list of triggers. For each trigger | ||
199 | ** that is not part of the temp-db schema, add a clause to the WHERE | ||
200 | ** expression being built up in zWhere. | ||
201 | */ | ||
202 | if( pTab->pSchema!=pTempSchema ){ | ||
203 | sqlite3 *db = pParse->db; | ||
204 | for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){ | ||
205 | if( pTrig->pSchema==pTempSchema ){ | ||
206 | if( !zWhere ){ | ||
207 | zWhere = sqlite3MPrintf(db, "name=%Q", pTrig->name); | ||
208 | }else{ | ||
209 | tmp = zWhere; | ||
210 | zWhere = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, pTrig->name); | ||
211 | sqlite3_free(tmp); | ||
212 | } | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | return zWhere; | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | ** Generate code to drop and reload the internal representation of table | ||
221 | ** pTab from the database, including triggers and temporary triggers. | ||
222 | ** Argument zName is the name of the table in the database schema at | ||
223 | ** the time the generated code is executed. This can be different from | ||
224 | ** pTab->zName if this function is being called to code part of an | ||
225 | ** "ALTER TABLE RENAME TO" statement. | ||
226 | */ | ||
227 | static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ | ||
228 | Vdbe *v; | ||
229 | char *zWhere; | ||
230 | int iDb; /* Index of database containing pTab */ | ||
231 | #ifndef SQLITE_OMIT_TRIGGER | ||
232 | Trigger *pTrig; | ||
233 | #endif | ||
234 | |||
235 | v = sqlite3GetVdbe(pParse); | ||
236 | if( !v ) return; | ||
237 | assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); | ||
238 | iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); | ||
239 | assert( iDb>=0 ); | ||
240 | |||
241 | #ifndef SQLITE_OMIT_TRIGGER | ||
242 | /* Drop any table triggers from the internal schema. */ | ||
243 | for(pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext){ | ||
244 | int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); | ||
245 | assert( iTrigDb==iDb || iTrigDb==1 ); | ||
246 | sqlite3VdbeOp3(v, OP_DropTrigger, iTrigDb, 0, pTrig->name, 0); | ||
247 | } | ||
248 | #endif | ||
249 | |||
250 | /* Drop the table and index from the internal schema */ | ||
251 | sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0); | ||
252 | |||
253 | /* Reload the table, index and permanent trigger schemas. */ | ||
254 | zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName); | ||
255 | if( !zWhere ) return; | ||
256 | sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC); | ||
257 | |||
258 | #ifndef SQLITE_OMIT_TRIGGER | ||
259 | /* Now, if the table is not stored in the temp database, reload any temp | ||
260 | ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined. | ||
261 | */ | ||
262 | if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ | ||
263 | sqlite3VdbeOp3(v, OP_ParseSchema, 1, 0, zWhere, P3_DYNAMIC); | ||
264 | } | ||
265 | #endif | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | ** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" | ||
270 | ** command. | ||
271 | */ | ||
272 | void sqlite3AlterRenameTable( | ||
273 | Parse *pParse, /* Parser context. */ | ||
274 | SrcList *pSrc, /* The table to rename. */ | ||
275 | Token *pName /* The new table name. */ | ||
276 | ){ | ||
277 | int iDb; /* Database that contains the table */ | ||
278 | char *zDb; /* Name of database iDb */ | ||
279 | Table *pTab; /* Table being renamed */ | ||
280 | char *zName = 0; /* NULL-terminated version of pName */ | ||
281 | sqlite3 *db = pParse->db; /* Database connection */ | ||
282 | int nTabName; /* Number of UTF-8 characters in zTabName */ | ||
283 | const char *zTabName; /* Original name of the table */ | ||
284 | Vdbe *v; | ||
285 | #ifndef SQLITE_OMIT_TRIGGER | ||
286 | char *zWhere = 0; /* Where clause to locate temp triggers */ | ||
287 | #endif | ||
288 | int isVirtualRename = 0; /* True if this is a v-table with an xRename() */ | ||
289 | |||
290 | if( db->mallocFailed ) goto exit_rename_table; | ||
291 | assert( pSrc->nSrc==1 ); | ||
292 | assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); | ||
293 | |||
294 | pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase); | ||
295 | if( !pTab ) goto exit_rename_table; | ||
296 | iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); | ||
297 | zDb = db->aDb[iDb].zName; | ||
298 | |||
299 | /* Get a NULL terminated version of the new table name. */ | ||
300 | zName = sqlite3NameFromToken(db, pName); | ||
301 | if( !zName ) goto exit_rename_table; | ||
302 | |||
303 | /* Check that a table or index named 'zName' does not already exist | ||
304 | ** in database iDb. If so, this is an error. | ||
305 | */ | ||
306 | if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){ | ||
307 | sqlite3ErrorMsg(pParse, | ||
308 | "there is already another table or index with this name: %s", zName); | ||
309 | goto exit_rename_table; | ||
310 | } | ||
311 | |||
312 | /* Make sure it is not a system table being altered, or a reserved name | ||
313 | ** that the table is being renamed to. | ||
314 | */ | ||
315 | if( strlen(pTab->zName)>6 && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ){ | ||
316 | sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName); | ||
317 | goto exit_rename_table; | ||
318 | } | ||
319 | if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ | ||
320 | goto exit_rename_table; | ||
321 | } | ||
322 | |||
323 | #ifndef SQLITE_OMIT_AUTHORIZATION | ||
324 | /* Invoke the authorization callback. */ | ||
325 | if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ | ||
326 | goto exit_rename_table; | ||
327 | } | ||
328 | #endif | ||
329 | |||
330 | #ifndef SQLITE_OMIT_VIRTUALTABLE | ||
331 | if( sqlite3ViewGetColumnNames(pParse, pTab) ){ | ||
332 | goto exit_rename_table; | ||
333 | } | ||
334 | if( IsVirtual(pTab) && pTab->pMod->pModule->xRename ){ | ||
335 | isVirtualRename = 1; | ||
336 | } | ||
337 | #endif | ||
338 | |||
339 | /* Begin a transaction and code the VerifyCookie for database iDb. | ||
340 | ** Then modify the schema cookie (since the ALTER TABLE modifies the | ||
341 | ** schema). Open a statement transaction if the table is a virtual | ||
342 | ** table. | ||
343 | */ | ||
344 | v = sqlite3GetVdbe(pParse); | ||
345 | if( v==0 ){ | ||
346 | goto exit_rename_table; | ||
347 | } | ||
348 | sqlite3BeginWriteOperation(pParse, isVirtualRename, iDb); | ||
349 | sqlite3ChangeCookie(db, v, iDb); | ||
350 | |||
351 | /* If this is a virtual table, invoke the xRename() function if | ||
352 | ** one is defined. The xRename() callback will modify the names | ||
353 | ** of any resources used by the v-table implementation (including other | ||
354 | ** SQLite tables) that are identified by the name of the virtual table. | ||
355 | */ | ||
356 | #ifndef SQLITE_OMIT_VIRTUALTABLE | ||
357 | if( isVirtualRename ){ | ||
358 | sqlite3VdbeOp3(v, OP_String8, 0, 0, zName, 0); | ||
359 | sqlite3VdbeOp3(v, OP_VRename, 0, 0, (const char*)pTab->pVtab, P3_VTAB); | ||
360 | } | ||
361 | #endif | ||
362 | |||
363 | /* figure out how many UTF-8 characters are in zName */ | ||
364 | zTabName = pTab->zName; | ||
365 | nTabName = sqlite3Utf8CharLen(zTabName, -1); | ||
366 | |||
367 | /* Modify the sqlite_master table to use the new table name. */ | ||
368 | sqlite3NestedParse(pParse, | ||
369 | "UPDATE %Q.%s SET " | ||
370 | #ifdef SQLITE_OMIT_TRIGGER | ||
371 | "sql = sqlite_rename_table(sql, %Q), " | ||
372 | #else | ||
373 | "sql = CASE " | ||
374 | "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)" | ||
375 | "ELSE sqlite_rename_table(sql, %Q) END, " | ||
376 | #endif | ||
377 | "tbl_name = %Q, " | ||
378 | "name = CASE " | ||
379 | "WHEN type='table' THEN %Q " | ||
380 | "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " | ||
381 | "'sqlite_autoindex_' || %Q || substr(name,%d+18,10) " | ||
382 | "ELSE name END " | ||
383 | "WHERE tbl_name=%Q AND " | ||
384 | "(type='table' OR type='index' OR type='trigger');", | ||
385 | zDb, SCHEMA_TABLE(iDb), zName, zName, zName, | ||
386 | #ifndef SQLITE_OMIT_TRIGGER | ||
387 | zName, | ||
388 | #endif | ||
389 | zName, nTabName, zTabName | ||
390 | ); | ||
391 | |||
392 | #ifndef SQLITE_OMIT_AUTOINCREMENT | ||
393 | /* If the sqlite_sequence table exists in this database, then update | ||
394 | ** it with the new table name. | ||
395 | */ | ||
396 | if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){ | ||
397 | sqlite3NestedParse(pParse, | ||
398 | "UPDATE %Q.sqlite_sequence set name = %Q WHERE name = %Q", | ||
399 | zDb, zName, pTab->zName); | ||
400 | } | ||
401 | #endif | ||
402 | |||
403 | #ifndef SQLITE_OMIT_TRIGGER | ||
404 | /* If there are TEMP triggers on this table, modify the sqlite_temp_master | ||
405 | ** table. Don't do this if the table being ALTERed is itself located in | ||
406 | ** the temp database. | ||
407 | */ | ||
408 | if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ | ||
409 | sqlite3NestedParse(pParse, | ||
410 | "UPDATE sqlite_temp_master SET " | ||
411 | "sql = sqlite_rename_trigger(sql, %Q), " | ||
412 | "tbl_name = %Q " | ||
413 | "WHERE %s;", zName, zName, zWhere); | ||
414 | sqlite3_free(zWhere); | ||
415 | } | ||
416 | #endif | ||
417 | |||
418 | /* Drop and reload the internal table schema. */ | ||
419 | reloadTableSchema(pParse, pTab, zName); | ||
420 | |||
421 | exit_rename_table: | ||
422 | sqlite3SrcListDelete(pSrc); | ||
423 | sqlite3_free(zName); | ||
424 | } | ||
425 | |||
426 | |||
427 | /* | ||
428 | ** This function is called after an "ALTER TABLE ... ADD" statement | ||
429 | ** has been parsed. Argument pColDef contains the text of the new | ||
430 | ** column definition. | ||
431 | ** | ||
432 | ** The Table structure pParse->pNewTable was extended to include | ||
433 | ** the new column during parsing. | ||
434 | */ | ||
435 | void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ | ||
436 | Table *pNew; /* Copy of pParse->pNewTable */ | ||
437 | Table *pTab; /* Table being altered */ | ||
438 | int iDb; /* Database number */ | ||
439 | const char *zDb; /* Database name */ | ||
440 | const char *zTab; /* Table name */ | ||
441 | char *zCol; /* Null-terminated column definition */ | ||
442 | Column *pCol; /* The new column */ | ||
443 | Expr *pDflt; /* Default value for the new column */ | ||
444 | sqlite3 *db; /* The database connection; */ | ||
445 | |||
446 | if( pParse->nErr ) return; | ||
447 | pNew = pParse->pNewTable; | ||
448 | assert( pNew ); | ||
449 | |||
450 | db = pParse->db; | ||
451 | assert( sqlite3BtreeHoldsAllMutexes(db) ); | ||
452 | iDb = sqlite3SchemaToIndex(db, pNew->pSchema); | ||
453 | zDb = db->aDb[iDb].zName; | ||
454 | zTab = pNew->zName; | ||
455 | pCol = &pNew->aCol[pNew->nCol-1]; | ||
456 | pDflt = pCol->pDflt; | ||
457 | pTab = sqlite3FindTable(db, zTab, zDb); | ||
458 | assert( pTab ); | ||
459 | |||
460 | #ifndef SQLITE_OMIT_AUTHORIZATION | ||
461 | /* Invoke the authorization callback. */ | ||
462 | if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ | ||
463 | return; | ||
464 | } | ||
465 | #endif | ||
466 | |||
467 | /* If the default value for the new column was specified with a | ||
468 | ** literal NULL, then set pDflt to 0. This simplifies checking | ||
469 | ** for an SQL NULL default below. | ||
470 | */ | ||
471 | if( pDflt && pDflt->op==TK_NULL ){ | ||
472 | pDflt = 0; | ||
473 | } | ||
474 | |||
475 | /* Check that the new column is not specified as PRIMARY KEY or UNIQUE. | ||
476 | ** If there is a NOT NULL constraint, then the default value for the | ||
477 | ** column must not be NULL. | ||
478 | */ | ||
479 | if( pCol->isPrimKey ){ | ||
480 | sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column"); | ||
481 | return; | ||
482 | } | ||
483 | if( pNew->pIndex ){ | ||
484 | sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column"); | ||
485 | return; | ||
486 | } | ||
487 | if( pCol->notNull && !pDflt ){ | ||
488 | sqlite3ErrorMsg(pParse, | ||
489 | "Cannot add a NOT NULL column with default value NULL"); | ||
490 | return; | ||
491 | } | ||
492 | |||
493 | /* Ensure the default expression is something that sqlite3ValueFromExpr() | ||
494 | ** can handle (i.e. not CURRENT_TIME etc.) | ||
495 | */ | ||
496 | if( pDflt ){ | ||
497 | sqlite3_value *pVal; | ||
498 | if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){ | ||
499 | db->mallocFailed = 1; | ||
500 | return; | ||
501 | } | ||
502 | if( !pVal ){ | ||
503 | sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default"); | ||
504 | return; | ||
505 | } | ||
506 | sqlite3ValueFree(pVal); | ||
507 | } | ||
508 | |||
509 | /* Modify the CREATE TABLE statement. */ | ||
510 | zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); | ||
511 | if( zCol ){ | ||
512 | char *zEnd = &zCol[pColDef->n-1]; | ||
513 | while( (zEnd>zCol && *zEnd==';') || isspace(*(unsigned char *)zEnd) ){ | ||
514 | *zEnd-- = '\0'; | ||
515 | } | ||
516 | sqlite3NestedParse(pParse, | ||
517 | "UPDATE %Q.%s SET " | ||
518 | "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d,length(sql)) " | ||
519 | "WHERE type = 'table' AND name = %Q", | ||
520 | zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1, | ||
521 | zTab | ||
522 | ); | ||
523 | sqlite3_free(zCol); | ||
524 | } | ||
525 | |||
526 | /* If the default value of the new column is NULL, then set the file | ||
527 | ** format to 2. If the default value of the new column is not NULL, | ||
528 | ** the file format becomes 3. | ||
529 | */ | ||
530 | sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2); | ||
531 | |||
532 | /* Reload the schema of the modified table. */ | ||
533 | reloadTableSchema(pParse, pTab, pTab->zName); | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | ** This function is called by the parser after the table-name in | ||
538 | ** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument | ||
539 | ** pSrc is the full-name of the table being altered. | ||
540 | ** | ||
541 | ** This routine makes a (partial) copy of the Table structure | ||
542 | ** for the table being altered and sets Parse.pNewTable to point | ||
543 | ** to it. Routines called by the parser as the column definition | ||
544 | ** is parsed (i.e. sqlite3AddColumn()) add the new Column data to | ||
545 | ** the copy. The copy of the Table structure is deleted by tokenize.c | ||
546 | ** after parsing is finished. | ||
547 | ** | ||
548 | ** Routine sqlite3AlterFinishAddColumn() will be called to complete | ||
549 | ** coding the "ALTER TABLE ... ADD" statement. | ||
550 | */ | ||
551 | void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ | ||
552 | Table *pNew; | ||
553 | Table *pTab; | ||
554 | Vdbe *v; | ||
555 | int iDb; | ||
556 | int i; | ||
557 | int nAlloc; | ||
558 | sqlite3 *db = pParse->db; | ||
559 | |||
560 | /* Look up the table being altered. */ | ||
561 | assert( pParse->pNewTable==0 ); | ||
562 | assert( sqlite3BtreeHoldsAllMutexes(db) ); | ||
563 | if( db->mallocFailed ) goto exit_begin_add_column; | ||
564 | pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase); | ||
565 | if( !pTab ) goto exit_begin_add_column; | ||
566 | |||
567 | #ifndef SQLITE_OMIT_VIRTUALTABLE | ||
568 | if( IsVirtual(pTab) ){ | ||
569 | sqlite3ErrorMsg(pParse, "virtual tables may not be altered"); | ||
570 | goto exit_begin_add_column; | ||
571 | } | ||
572 | #endif | ||
573 | |||
574 | /* Make sure this is not an attempt to ALTER a view. */ | ||
575 | if( pTab->pSelect ){ | ||
576 | sqlite3ErrorMsg(pParse, "Cannot add a column to a view"); | ||
577 | goto exit_begin_add_column; | ||
578 | } | ||
579 | |||
580 | assert( pTab->addColOffset>0 ); | ||
581 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); | ||
582 | |||
583 | /* Put a copy of the Table struct in Parse.pNewTable for the | ||
584 | ** sqlite3AddColumn() function and friends to modify. | ||
585 | */ | ||
586 | pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table)); | ||
587 | if( !pNew ) goto exit_begin_add_column; | ||
588 | pParse->pNewTable = pNew; | ||
589 | pNew->nRef = 1; | ||
590 | pNew->nCol = pTab->nCol; | ||
591 | assert( pNew->nCol>0 ); | ||
592 | nAlloc = (((pNew->nCol-1)/8)*8)+8; | ||
593 | assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); | ||
594 | pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); | ||
595 | pNew->zName = sqlite3DbStrDup(db, pTab->zName); | ||
596 | if( !pNew->aCol || !pNew->zName ){ | ||
597 | db->mallocFailed = 1; | ||
598 | goto exit_begin_add_column; | ||
599 | } | ||
600 | memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); | ||
601 | for(i=0; i<pNew->nCol; i++){ | ||
602 | Column *pCol = &pNew->aCol[i]; | ||
603 | pCol->zName = sqlite3DbStrDup(db, pCol->zName); | ||
604 | pCol->zColl = 0; | ||
605 | pCol->zType = 0; | ||
606 | pCol->pDflt = 0; | ||
607 | } | ||
608 | pNew->pSchema = db->aDb[iDb].pSchema; | ||
609 | pNew->addColOffset = pTab->addColOffset; | ||
610 | pNew->nRef = 1; | ||
611 | |||
612 | /* Begin a transaction and increment the schema cookie. */ | ||
613 | sqlite3BeginWriteOperation(pParse, 0, iDb); | ||
614 | v = sqlite3GetVdbe(pParse); | ||
615 | if( !v ) goto exit_begin_add_column; | ||
616 | sqlite3ChangeCookie(db, v, iDb); | ||
617 | |||
618 | exit_begin_add_column: | ||
619 | sqlite3SrcListDelete(pSrc); | ||
620 | return; | ||
621 | } | ||
622 | #endif /* SQLITE_ALTER_TABLE */ | ||