line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
/* |
2
|
|
|
|
|
|
|
** 2001 September 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 are called by the SQLite parser |
13
|
|
|
|
|
|
|
** when syntax rules are reduced. The routines in this file handle the |
14
|
|
|
|
|
|
|
** following kinds of SQL syntax: |
15
|
|
|
|
|
|
|
** |
16
|
|
|
|
|
|
|
** CREATE TABLE |
17
|
|
|
|
|
|
|
** DROP TABLE |
18
|
|
|
|
|
|
|
** CREATE INDEX |
19
|
|
|
|
|
|
|
** DROP INDEX |
20
|
|
|
|
|
|
|
** creating ID lists |
21
|
|
|
|
|
|
|
** BEGIN TRANSACTION |
22
|
|
|
|
|
|
|
** COMMIT |
23
|
|
|
|
|
|
|
** ROLLBACK |
24
|
|
|
|
|
|
|
** PRAGMA |
25
|
|
|
|
|
|
|
** |
26
|
|
|
|
|
|
|
** $Id: build.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ |
27
|
|
|
|
|
|
|
*/ |
28
|
|
|
|
|
|
|
#include "sqliteInt.h" |
29
|
|
|
|
|
|
|
#include |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
/* |
32
|
|
|
|
|
|
|
** This routine is called when a new SQL statement is beginning to |
33
|
|
|
|
|
|
|
** be parsed. Check to see if the schema for the database needs |
34
|
|
|
|
|
|
|
** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables. |
35
|
|
|
|
|
|
|
** If it does, then read it. |
36
|
|
|
|
|
|
|
*/ |
37
|
353
|
|
|
|
|
|
void sqliteBeginParse(Parse *pParse, int explainFlag){ |
38
|
353
|
|
|
|
|
|
sqlite *db = pParse->db; |
39
|
|
|
|
|
|
|
int i; |
40
|
353
|
|
|
|
|
|
pParse->explain = explainFlag; |
41
|
353
|
100
|
|
|
|
|
if((db->flags & SQLITE_Initialized)==0 && db->init.busy==0 ){ |
|
|
50
|
|
|
|
|
|
42
|
0
|
|
|
|
|
|
int rc = sqliteInit(db, &pParse->zErrMsg); |
43
|
0
|
0
|
|
|
|
|
if( rc!=SQLITE_OK ){ |
44
|
0
|
|
|
|
|
|
pParse->rc = rc; |
45
|
0
|
|
|
|
|
|
pParse->nErr++; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
} |
48
|
1059
|
100
|
|
|
|
|
for(i=0; inDb; i++){ |
49
|
706
|
|
|
|
|
|
DbClearProperty(db, i, DB_Locked); |
50
|
706
|
100
|
|
|
|
|
if( !db->aDb[i].inTrans ){ |
51
|
658
|
|
|
|
|
|
DbClearProperty(db, i, DB_Cookie); |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
} |
54
|
353
|
|
|
|
|
|
pParse->nVar = 0; |
55
|
353
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
/* |
58
|
|
|
|
|
|
|
** This routine is called after a single SQL statement has been |
59
|
|
|
|
|
|
|
** parsed and we want to execute the VDBE code to implement |
60
|
|
|
|
|
|
|
** that statement. Prior action routines should have already |
61
|
|
|
|
|
|
|
** constructed VDBE code to do the work of the SQL statement. |
62
|
|
|
|
|
|
|
** This routine just has to execute the VDBE code. |
63
|
|
|
|
|
|
|
** |
64
|
|
|
|
|
|
|
** Note that if an error occurred, it might be the case that |
65
|
|
|
|
|
|
|
** no VDBE code was generated. |
66
|
|
|
|
|
|
|
*/ |
67
|
348
|
|
|
|
|
|
void sqliteExec(Parse *pParse){ |
68
|
348
|
|
|
|
|
|
sqlite *db = pParse->db; |
69
|
348
|
|
|
|
|
|
Vdbe *v = pParse->pVdbe; |
70
|
|
|
|
|
|
|
|
71
|
348
|
100
|
|
|
|
|
if( v==0 && (v = sqliteGetVdbe(pParse))!=0 ){ |
|
|
50
|
|
|
|
|
|
72
|
79
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Halt, 0, 0); |
73
|
|
|
|
|
|
|
} |
74
|
348
|
50
|
|
|
|
|
if( sqlite_malloc_failed ) return; |
75
|
690
|
50
|
|
|
|
|
if( v && pParse->nErr==0 ){ |
|
|
100
|
|
|
|
|
|
76
|
342
|
50
|
|
|
|
|
FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; |
77
|
342
|
|
|
|
|
|
sqliteVdbeTrace(v, trace); |
78
|
342
|
|
|
|
|
|
sqliteVdbeMakeReady(v, pParse->nVar, pParse->explain); |
79
|
342
|
50
|
|
|
|
|
pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE; |
80
|
342
|
|
|
|
|
|
pParse->colNamesSet = 0; |
81
|
6
|
50
|
|
|
|
|
}else if( pParse->rc==SQLITE_OK ){ |
82
|
6
|
|
|
|
|
|
pParse->rc = SQLITE_ERROR; |
83
|
|
|
|
|
|
|
} |
84
|
348
|
|
|
|
|
|
pParse->nTab = 0; |
85
|
348
|
|
|
|
|
|
pParse->nMem = 0; |
86
|
348
|
|
|
|
|
|
pParse->nSet = 0; |
87
|
348
|
|
|
|
|
|
pParse->nAgg = 0; |
88
|
348
|
|
|
|
|
|
pParse->nVar = 0; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
/* |
92
|
|
|
|
|
|
|
** Locate the in-memory structure that describes |
93
|
|
|
|
|
|
|
** a particular database table given the name |
94
|
|
|
|
|
|
|
** of that table and (optionally) the name of the database |
95
|
|
|
|
|
|
|
** containing the table. Return NULL if not found. |
96
|
|
|
|
|
|
|
** |
97
|
|
|
|
|
|
|
** If zDatabase is 0, all databases are searched for the |
98
|
|
|
|
|
|
|
** table and the first matching table is returned. (No checking |
99
|
|
|
|
|
|
|
** for duplicate table names is done.) The search order is |
100
|
|
|
|
|
|
|
** TEMP first, then MAIN, then any auxiliary databases added |
101
|
|
|
|
|
|
|
** using the ATTACH command. |
102
|
|
|
|
|
|
|
** |
103
|
|
|
|
|
|
|
** See also sqliteLocateTable(). |
104
|
|
|
|
|
|
|
*/ |
105
|
328
|
|
|
|
|
|
Table *sqliteFindTable(sqlite *db, const char *zName, const char *zDatabase){ |
106
|
328
|
|
|
|
|
|
Table *p = 0; |
107
|
|
|
|
|
|
|
int i; |
108
|
695
|
100
|
|
|
|
|
for(i=0; inDb; i++){ |
109
|
596
|
50
|
|
|
|
|
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ |
110
|
596
|
100
|
|
|
|
|
if( zDatabase!=0 && sqliteStrICmp(zDatabase, db->aDb[j].zName) ) continue; |
|
|
100
|
|
|
|
|
|
111
|
539
|
|
|
|
|
|
p = sqliteHashFind(&db->aDb[j].tblHash, zName, strlen(zName)+1); |
112
|
539
|
100
|
|
|
|
|
if( p ) break; |
113
|
|
|
|
|
|
|
} |
114
|
328
|
|
|
|
|
|
return p; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
/* |
118
|
|
|
|
|
|
|
** Locate the in-memory structure that describes |
119
|
|
|
|
|
|
|
** a particular database table given the name |
120
|
|
|
|
|
|
|
** of that table and (optionally) the name of the database |
121
|
|
|
|
|
|
|
** containing the table. Return NULL if not found. |
122
|
|
|
|
|
|
|
** Also leave an error message in pParse->zErrMsg. |
123
|
|
|
|
|
|
|
** |
124
|
|
|
|
|
|
|
** The difference between this routine and sqliteFindTable() |
125
|
|
|
|
|
|
|
** is that this routine leaves an error message in pParse->zErrMsg |
126
|
|
|
|
|
|
|
** where sqliteFindTable() does not. |
127
|
|
|
|
|
|
|
*/ |
128
|
164
|
|
|
|
|
|
Table *sqliteLocateTable(Parse *pParse, const char *zName, const char *zDbase){ |
129
|
|
|
|
|
|
|
Table *p; |
130
|
|
|
|
|
|
|
|
131
|
164
|
|
|
|
|
|
p = sqliteFindTable(pParse->db, zName, zDbase); |
132
|
164
|
50
|
|
|
|
|
if( p==0 ){ |
133
|
0
|
0
|
|
|
|
|
if( zDbase ){ |
134
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "no such table: %s.%s", zDbase, zName); |
135
|
0
|
0
|
|
|
|
|
}else if( sqliteFindTable(pParse->db, zName, 0)!=0 ){ |
136
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "table \"%s\" is not in database \"%s\"", |
137
|
|
|
|
|
|
|
zName, zDbase); |
138
|
|
|
|
|
|
|
}else{ |
139
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "no such table: %s", zName); |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
} |
142
|
164
|
|
|
|
|
|
return p; |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
/* |
146
|
|
|
|
|
|
|
** Locate the in-memory structure that describes |
147
|
|
|
|
|
|
|
** a particular index given the name of that index |
148
|
|
|
|
|
|
|
** and the name of the database that contains the index. |
149
|
|
|
|
|
|
|
** Return NULL if not found. |
150
|
|
|
|
|
|
|
** |
151
|
|
|
|
|
|
|
** If zDatabase is 0, all databases are searched for the |
152
|
|
|
|
|
|
|
** table and the first matching index is returned. (No checking |
153
|
|
|
|
|
|
|
** for duplicate index names is done.) The search order is |
154
|
|
|
|
|
|
|
** TEMP first, then MAIN, then any auxiliary databases added |
155
|
|
|
|
|
|
|
** using the ATTACH command. |
156
|
|
|
|
|
|
|
*/ |
157
|
93
|
|
|
|
|
|
Index *sqliteFindIndex(sqlite *db, const char *zName, const char *zDb){ |
158
|
93
|
|
|
|
|
|
Index *p = 0; |
159
|
|
|
|
|
|
|
int i; |
160
|
279
|
100
|
|
|
|
|
for(i=0; inDb; i++){ |
161
|
186
|
50
|
|
|
|
|
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ |
162
|
186
|
50
|
|
|
|
|
if( zDb && sqliteStrICmp(zDb, db->aDb[j].zName) ) continue; |
|
|
0
|
|
|
|
|
|
163
|
186
|
|
|
|
|
|
p = sqliteHashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1); |
164
|
186
|
50
|
|
|
|
|
if( p ) break; |
165
|
|
|
|
|
|
|
} |
166
|
93
|
|
|
|
|
|
return p; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
/* |
170
|
|
|
|
|
|
|
** Remove the given index from the index hash table, and free |
171
|
|
|
|
|
|
|
** its memory structures. |
172
|
|
|
|
|
|
|
** |
173
|
|
|
|
|
|
|
** The index is removed from the database hash tables but |
174
|
|
|
|
|
|
|
** it is not unlinked from the Table that it indexes. |
175
|
|
|
|
|
|
|
** Unlinking from the Table must be done by the calling function. |
176
|
|
|
|
|
|
|
*/ |
177
|
8
|
|
|
|
|
|
static void sqliteDeleteIndex(sqlite *db, Index *p){ |
178
|
|
|
|
|
|
|
Index *pOld; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
assert( db!=0 && p->zName!=0 ); |
181
|
8
|
|
|
|
|
|
pOld = sqliteHashInsert(&db->aDb[p->iDb].idxHash, p->zName, |
182
|
8
|
|
|
|
|
|
strlen(p->zName)+1, 0); |
183
|
8
|
50
|
|
|
|
|
if( pOld!=0 && pOld!=p ){ |
|
|
0
|
|
|
|
|
|
184
|
0
|
|
|
|
|
|
sqliteHashInsert(&db->aDb[p->iDb].idxHash, pOld->zName, |
185
|
0
|
|
|
|
|
|
strlen(pOld->zName)+1, pOld); |
186
|
|
|
|
|
|
|
} |
187
|
8
|
|
|
|
|
|
sqliteFree(p); |
188
|
8
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
/* |
191
|
|
|
|
|
|
|
** Unlink the given index from its table, then remove |
192
|
|
|
|
|
|
|
** the index from the index hash table and free its memory |
193
|
|
|
|
|
|
|
** structures. |
194
|
|
|
|
|
|
|
*/ |
195
|
0
|
|
|
|
|
|
void sqliteUnlinkAndDeleteIndex(sqlite *db, Index *pIndex){ |
196
|
0
|
0
|
|
|
|
|
if( pIndex->pTable->pIndex==pIndex ){ |
197
|
0
|
|
|
|
|
|
pIndex->pTable->pIndex = pIndex->pNext; |
198
|
|
|
|
|
|
|
}else{ |
199
|
|
|
|
|
|
|
Index *p; |
200
|
0
|
0
|
|
|
|
|
for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){} |
|
|
0
|
|
|
|
|
|
201
|
0
|
0
|
|
|
|
|
if( p && p->pNext==pIndex ){ |
|
|
0
|
|
|
|
|
|
202
|
0
|
|
|
|
|
|
p->pNext = pIndex->pNext; |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
} |
205
|
0
|
|
|
|
|
|
sqliteDeleteIndex(db, pIndex); |
206
|
0
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
/* |
209
|
|
|
|
|
|
|
** Erase all schema information from the in-memory hash tables of |
210
|
|
|
|
|
|
|
** database connection. This routine is called to reclaim memory |
211
|
|
|
|
|
|
|
** before the connection closes. It is also called during a rollback |
212
|
|
|
|
|
|
|
** if there were schema changes during the transaction. |
213
|
|
|
|
|
|
|
** |
214
|
|
|
|
|
|
|
** If iDb<=0 then reset the internal schema tables for all database |
215
|
|
|
|
|
|
|
** files. If iDb>=2 then reset the internal schema for only the |
216
|
|
|
|
|
|
|
** single file indicated. |
217
|
|
|
|
|
|
|
*/ |
218
|
30
|
|
|
|
|
|
void sqliteResetInternalSchema(sqlite *db, int iDb){ |
219
|
|
|
|
|
|
|
HashElem *pElem; |
220
|
|
|
|
|
|
|
Hash temp1; |
221
|
|
|
|
|
|
|
Hash temp2; |
222
|
|
|
|
|
|
|
int i, j; |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
assert( iDb>=0 && iDbnDb ); |
225
|
30
|
|
|
|
|
|
db->flags &= ~SQLITE_Initialized; |
226
|
90
|
100
|
|
|
|
|
for(i=iDb; inDb; i++){ |
227
|
60
|
|
|
|
|
|
Db *pDb = &db->aDb[i]; |
228
|
60
|
|
|
|
|
|
temp1 = pDb->tblHash; |
229
|
60
|
|
|
|
|
|
temp2 = pDb->trigHash; |
230
|
60
|
|
|
|
|
|
sqliteHashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0); |
231
|
60
|
|
|
|
|
|
sqliteHashClear(&pDb->aFKey); |
232
|
60
|
|
|
|
|
|
sqliteHashClear(&pDb->idxHash); |
233
|
60
|
50
|
|
|
|
|
for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ |
234
|
0
|
|
|
|
|
|
Trigger *pTrigger = sqliteHashData(pElem); |
235
|
0
|
|
|
|
|
|
sqliteDeleteTrigger(pTrigger); |
236
|
|
|
|
|
|
|
} |
237
|
60
|
|
|
|
|
|
sqliteHashClear(&temp2); |
238
|
60
|
|
|
|
|
|
sqliteHashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0); |
239
|
141
|
100
|
|
|
|
|
for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ |
240
|
81
|
|
|
|
|
|
Table *pTab = sqliteHashData(pElem); |
241
|
81
|
|
|
|
|
|
sqliteDeleteTable(db, pTab); |
242
|
|
|
|
|
|
|
} |
243
|
60
|
|
|
|
|
|
sqliteHashClear(&temp1); |
244
|
60
|
|
|
|
|
|
DbClearProperty(db, i, DB_SchemaLoaded); |
245
|
60
|
50
|
|
|
|
|
if( iDb>0 ) return; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
assert( iDb==0 ); |
248
|
30
|
|
|
|
|
|
db->flags &= ~SQLITE_InternChanges; |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
/* If one or more of the auxiliary database files has been closed, |
251
|
|
|
|
|
|
|
** then remove then from the auxiliary database list. We take the |
252
|
|
|
|
|
|
|
** opportunity to do this here since we have just deleted all of the |
253
|
|
|
|
|
|
|
** schema hash tables and therefore do not have to make any changes |
254
|
|
|
|
|
|
|
** to any of those tables. |
255
|
|
|
|
|
|
|
*/ |
256
|
90
|
100
|
|
|
|
|
for(i=0; inDb; i++){ |
257
|
60
|
|
|
|
|
|
struct Db *pDb = &db->aDb[i]; |
258
|
60
|
100
|
|
|
|
|
if( pDb->pBt==0 ){ |
259
|
50
|
50
|
|
|
|
|
if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux); |
|
|
0
|
|
|
|
|
|
260
|
50
|
|
|
|
|
|
pDb->pAux = 0; |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
} |
263
|
30
|
50
|
|
|
|
|
for(i=j=2; inDb; i++){ |
264
|
0
|
|
|
|
|
|
struct Db *pDb = &db->aDb[i]; |
265
|
0
|
0
|
|
|
|
|
if( pDb->pBt==0 ){ |
266
|
0
|
|
|
|
|
|
sqliteFree(pDb->zName); |
267
|
0
|
|
|
|
|
|
pDb->zName = 0; |
268
|
0
|
|
|
|
|
|
continue; |
269
|
|
|
|
|
|
|
} |
270
|
0
|
0
|
|
|
|
|
if( j
|
271
|
0
|
|
|
|
|
|
db->aDb[j] = db->aDb[i]; |
272
|
|
|
|
|
|
|
} |
273
|
0
|
|
|
|
|
|
j++; |
274
|
|
|
|
|
|
|
} |
275
|
30
|
|
|
|
|
|
memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j])); |
276
|
30
|
|
|
|
|
|
db->nDb = j; |
277
|
30
|
50
|
|
|
|
|
if( db->nDb<=2 && db->aDb!=db->aDbStatic ){ |
|
|
50
|
|
|
|
|
|
278
|
0
|
|
|
|
|
|
memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0])); |
279
|
0
|
|
|
|
|
|
sqliteFree(db->aDb); |
280
|
30
|
|
|
|
|
|
db->aDb = db->aDbStatic; |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
/* |
285
|
|
|
|
|
|
|
** This routine is called whenever a rollback occurs. If there were |
286
|
|
|
|
|
|
|
** schema changes during the transaction, then we have to reset the |
287
|
|
|
|
|
|
|
** internal hash tables and reload them from disk. |
288
|
|
|
|
|
|
|
*/ |
289
|
2
|
|
|
|
|
|
void sqliteRollbackInternalChanges(sqlite *db){ |
290
|
2
|
50
|
|
|
|
|
if( db->flags & SQLITE_InternChanges ){ |
291
|
0
|
|
|
|
|
|
sqliteResetInternalSchema(db, 0); |
292
|
|
|
|
|
|
|
} |
293
|
2
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
/* |
296
|
|
|
|
|
|
|
** This routine is called when a commit occurs. |
297
|
|
|
|
|
|
|
*/ |
298
|
100
|
|
|
|
|
|
void sqliteCommitInternalChanges(sqlite *db){ |
299
|
100
|
|
|
|
|
|
db->aDb[0].schema_cookie = db->next_cookie; |
300
|
100
|
|
|
|
|
|
db->flags &= ~SQLITE_InternChanges; |
301
|
100
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
/* |
304
|
|
|
|
|
|
|
** Remove the memory data structures associated with the given |
305
|
|
|
|
|
|
|
** Table. No changes are made to disk by this routine. |
306
|
|
|
|
|
|
|
** |
307
|
|
|
|
|
|
|
** This routine just deletes the data structure. It does not unlink |
308
|
|
|
|
|
|
|
** the table data structure from the hash table. Nor does it remove |
309
|
|
|
|
|
|
|
** foreign keys from the sqlite.aFKey hash table. But it does destroy |
310
|
|
|
|
|
|
|
** memory structures of the indices and foreign keys associated with |
311
|
|
|
|
|
|
|
** the table. |
312
|
|
|
|
|
|
|
** |
313
|
|
|
|
|
|
|
** Indices associated with the table are unlinked from the "db" |
314
|
|
|
|
|
|
|
** data structure if db!=NULL. If db==NULL, indices attached to |
315
|
|
|
|
|
|
|
** the table are deleted, but it is assumed they have already been |
316
|
|
|
|
|
|
|
** unlinked. |
317
|
|
|
|
|
|
|
*/ |
318
|
98
|
|
|
|
|
|
void sqliteDeleteTable(sqlite *db, Table *pTable){ |
319
|
|
|
|
|
|
|
int i; |
320
|
|
|
|
|
|
|
Index *pIndex, *pNext; |
321
|
|
|
|
|
|
|
FKey *pFKey, *pNextFKey; |
322
|
|
|
|
|
|
|
|
323
|
98
|
50
|
|
|
|
|
if( pTable==0 ) return; |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
/* Delete all indices associated with this table |
326
|
|
|
|
|
|
|
*/ |
327
|
106
|
100
|
|
|
|
|
for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ |
328
|
8
|
|
|
|
|
|
pNext = pIndex->pNext; |
329
|
|
|
|
|
|
|
assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) ); |
330
|
8
|
|
|
|
|
|
sqliteDeleteIndex(db, pIndex); |
331
|
|
|
|
|
|
|
} |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
/* Delete all foreign keys associated with this table. The keys |
334
|
|
|
|
|
|
|
** should have already been unlinked from the db->aFKey hash table |
335
|
|
|
|
|
|
|
*/ |
336
|
98
|
50
|
|
|
|
|
for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){ |
337
|
0
|
|
|
|
|
|
pNextFKey = pFKey->pNextFrom; |
338
|
|
|
|
|
|
|
assert( pTable->iDbnDb ); |
339
|
|
|
|
|
|
|
assert( sqliteHashFind(&db->aDb[pTable->iDb].aFKey, |
340
|
|
|
|
|
|
|
pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey ); |
341
|
0
|
|
|
|
|
|
sqliteFree(pFKey); |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
/* Delete the Table structure itself. |
345
|
|
|
|
|
|
|
*/ |
346
|
476
|
100
|
|
|
|
|
for(i=0; inCol; i++){ |
347
|
378
|
|
|
|
|
|
sqliteFree(pTable->aCol[i].zName); |
348
|
378
|
|
|
|
|
|
sqliteFree(pTable->aCol[i].zDflt); |
349
|
378
|
|
|
|
|
|
sqliteFree(pTable->aCol[i].zType); |
350
|
|
|
|
|
|
|
} |
351
|
98
|
|
|
|
|
|
sqliteFree(pTable->zName); |
352
|
98
|
|
|
|
|
|
sqliteFree(pTable->aCol); |
353
|
98
|
|
|
|
|
|
sqliteSelectDelete(pTable->pSelect); |
354
|
98
|
|
|
|
|
|
sqliteFree(pTable); |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
/* |
358
|
|
|
|
|
|
|
** Unlink the given table from the hash tables and the delete the |
359
|
|
|
|
|
|
|
** table structure with all its indices and foreign keys. |
360
|
|
|
|
|
|
|
*/ |
361
|
11
|
|
|
|
|
|
static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){ |
362
|
|
|
|
|
|
|
Table *pOld; |
363
|
|
|
|
|
|
|
FKey *pF1, *pF2; |
364
|
11
|
|
|
|
|
|
int i = p->iDb; |
365
|
|
|
|
|
|
|
assert( db!=0 ); |
366
|
11
|
|
|
|
|
|
pOld = sqliteHashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1, 0); |
367
|
|
|
|
|
|
|
assert( pOld==0 || pOld==p ); |
368
|
11
|
50
|
|
|
|
|
for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){ |
369
|
0
|
|
|
|
|
|
int nTo = strlen(pF1->zTo) + 1; |
370
|
0
|
|
|
|
|
|
pF2 = sqliteHashFind(&db->aDb[i].aFKey, pF1->zTo, nTo); |
371
|
0
|
0
|
|
|
|
|
if( pF2==pF1 ){ |
372
|
0
|
|
|
|
|
|
sqliteHashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo); |
373
|
|
|
|
|
|
|
}else{ |
374
|
0
|
0
|
|
|
|
|
while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; } |
|
|
0
|
|
|
|
|
|
375
|
0
|
0
|
|
|
|
|
if( pF2 ){ |
376
|
0
|
|
|
|
|
|
pF2->pNextTo = pF1->pNextTo; |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
} |
379
|
|
|
|
|
|
|
} |
380
|
11
|
|
|
|
|
|
sqliteDeleteTable(db, p); |
381
|
11
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
/* |
384
|
|
|
|
|
|
|
** Construct the name of a user table or index from a token. |
385
|
|
|
|
|
|
|
** |
386
|
|
|
|
|
|
|
** Space to hold the name is obtained from sqliteMalloc() and must |
387
|
|
|
|
|
|
|
** be freed by the calling function. |
388
|
|
|
|
|
|
|
*/ |
389
|
111
|
|
|
|
|
|
char *sqliteTableNameFromToken(Token *pName){ |
390
|
111
|
|
|
|
|
|
char *zName = sqliteStrNDup(pName->z, pName->n); |
391
|
111
|
|
|
|
|
|
sqliteDequote(zName); |
392
|
111
|
|
|
|
|
|
return zName; |
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
/* |
396
|
|
|
|
|
|
|
** Generate code to open the appropriate master table. The table |
397
|
|
|
|
|
|
|
** opened will be SQLITE_MASTER for persistent tables and |
398
|
|
|
|
|
|
|
** SQLITE_TEMP_MASTER for temporary tables. The table is opened |
399
|
|
|
|
|
|
|
** on cursor 0. |
400
|
|
|
|
|
|
|
*/ |
401
|
45
|
|
|
|
|
|
void sqliteOpenMasterTable(Vdbe *v, int isTemp){ |
402
|
45
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Integer, isTemp, 0); |
403
|
45
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2); |
404
|
45
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
/* |
407
|
|
|
|
|
|
|
** Begin constructing a new table representation in memory. This is |
408
|
|
|
|
|
|
|
** the first of several action routines that get called in response |
409
|
|
|
|
|
|
|
** to a CREATE TABLE statement. In particular, this routine is called |
410
|
|
|
|
|
|
|
** after seeing tokens "CREATE" and "TABLE" and the table name. The |
411
|
|
|
|
|
|
|
** pStart token is the CREATE and pName is the table name. The isTemp |
412
|
|
|
|
|
|
|
** flag is true if the table should be stored in the auxiliary database |
413
|
|
|
|
|
|
|
** file instead of in the main database file. This is normally the case |
414
|
|
|
|
|
|
|
** when the "TEMP" or "TEMPORARY" keyword occurs in between |
415
|
|
|
|
|
|
|
** CREATE and TABLE. |
416
|
|
|
|
|
|
|
** |
417
|
|
|
|
|
|
|
** The new table record is initialized and put in pParse->pNewTable. |
418
|
|
|
|
|
|
|
** As more of the CREATE TABLE statement is parsed, additional action |
419
|
|
|
|
|
|
|
** routines will be called to add more information to this record. |
420
|
|
|
|
|
|
|
** At the end of the CREATE TABLE statement, the sqliteEndTable() routine |
421
|
|
|
|
|
|
|
** is called to complete the construction of the new table record. |
422
|
|
|
|
|
|
|
*/ |
423
|
92
|
|
|
|
|
|
void sqliteStartTable( |
424
|
|
|
|
|
|
|
Parse *pParse, /* Parser context */ |
425
|
|
|
|
|
|
|
Token *pStart, /* The "CREATE" token */ |
426
|
|
|
|
|
|
|
Token *pName, /* Name of table or view to create */ |
427
|
|
|
|
|
|
|
int isTemp, /* True if this is a TEMP table */ |
428
|
|
|
|
|
|
|
int isView /* True if this is a VIEW */ |
429
|
|
|
|
|
|
|
){ |
430
|
|
|
|
|
|
|
Table *pTable; |
431
|
|
|
|
|
|
|
Index *pIdx; |
432
|
|
|
|
|
|
|
char *zName; |
433
|
92
|
|
|
|
|
|
sqlite *db = pParse->db; |
434
|
|
|
|
|
|
|
Vdbe *v; |
435
|
|
|
|
|
|
|
int iDb; |
436
|
|
|
|
|
|
|
|
437
|
92
|
|
|
|
|
|
pParse->sFirstToken = *pStart; |
438
|
92
|
|
|
|
|
|
zName = sqliteTableNameFromToken(pName); |
439
|
92
|
50
|
|
|
|
|
if( zName==0 ) return; |
440
|
92
|
100
|
|
|
|
|
if( db->init.iDb==1 ) isTemp = 1; |
441
|
|
|
|
|
|
|
#ifndef SQLITE_OMIT_AUTHORIZATION |
442
|
|
|
|
|
|
|
assert( (isTemp & 1)==isTemp ); |
443
|
|
|
|
|
|
|
{ |
444
|
|
|
|
|
|
|
int code; |
445
|
92
|
100
|
|
|
|
|
char *zDb = isTemp ? "temp" : "main"; |
446
|
92
|
100
|
|
|
|
|
if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ |
|
|
50
|
|
|
|
|
|
447
|
0
|
|
|
|
|
|
sqliteFree(zName); |
448
|
0
|
|
|
|
|
|
return; |
449
|
|
|
|
|
|
|
} |
450
|
92
|
50
|
|
|
|
|
if( isView ){ |
451
|
0
|
0
|
|
|
|
|
if( isTemp ){ |
452
|
0
|
|
|
|
|
|
code = SQLITE_CREATE_TEMP_VIEW; |
453
|
|
|
|
|
|
|
}else{ |
454
|
0
|
|
|
|
|
|
code = SQLITE_CREATE_VIEW; |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
}else{ |
457
|
92
|
100
|
|
|
|
|
if( isTemp ){ |
458
|
28
|
|
|
|
|
|
code = SQLITE_CREATE_TEMP_TABLE; |
459
|
|
|
|
|
|
|
}else{ |
460
|
64
|
|
|
|
|
|
code = SQLITE_CREATE_TABLE; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
} |
463
|
92
|
50
|
|
|
|
|
if( sqliteAuthCheck(pParse, code, zName, 0, zDb) ){ |
464
|
0
|
|
|
|
|
|
sqliteFree(zName); |
465
|
0
|
|
|
|
|
|
return; |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
} |
468
|
|
|
|
|
|
|
#endif |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
/* Before trying to create a temporary table, make sure the Btree for |
472
|
|
|
|
|
|
|
** holding temporary tables is open. |
473
|
|
|
|
|
|
|
*/ |
474
|
92
|
100
|
|
|
|
|
if( isTemp && db->aDb[1].pBt==0 && !pParse->explain ){ |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
475
|
25
|
|
|
|
|
|
int rc = sqliteBtreeFactory(db, 0, 0, MAX_PAGES, &db->aDb[1].pBt); |
476
|
25
|
50
|
|
|
|
|
if( rc!=SQLITE_OK ){ |
477
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "unable to open a temporary database " |
478
|
|
|
|
|
|
|
"file for storing temporary tables"); |
479
|
0
|
|
|
|
|
|
pParse->nErr++; |
480
|
0
|
|
|
|
|
|
return; |
481
|
|
|
|
|
|
|
} |
482
|
25
|
50
|
|
|
|
|
if( db->flags & SQLITE_InTrans ){ |
483
|
0
|
|
|
|
|
|
rc = sqliteBtreeBeginTrans(db->aDb[1].pBt); |
484
|
0
|
0
|
|
|
|
|
if( rc!=SQLITE_OK ){ |
485
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "unable to get a write lock on " |
486
|
|
|
|
|
|
|
"the temporary database file"); |
487
|
0
|
|
|
|
|
|
return; |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
/* Make sure the new table name does not collide with an existing |
493
|
|
|
|
|
|
|
** index or table name. Issue an error message if it does. |
494
|
|
|
|
|
|
|
** |
495
|
|
|
|
|
|
|
** If we are re-reading the sqlite_master table because of a schema |
496
|
|
|
|
|
|
|
** change and a new permanent table is found whose name collides with |
497
|
|
|
|
|
|
|
** an existing temporary table, that is not an error. |
498
|
|
|
|
|
|
|
*/ |
499
|
92
|
|
|
|
|
|
pTable = sqliteFindTable(db, zName, 0); |
500
|
92
|
100
|
|
|
|
|
iDb = isTemp ? 1 : db->init.iDb; |
501
|
92
|
50
|
|
|
|
|
if( pTable!=0 && (pTable->iDb==iDb || !db->init.busy) ){ |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
502
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "table %T already exists", pName); |
503
|
0
|
|
|
|
|
|
sqliteFree(zName); |
504
|
0
|
|
|
|
|
|
return; |
505
|
|
|
|
|
|
|
} |
506
|
92
|
50
|
|
|
|
|
if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 && |
|
|
0
|
|
|
|
|
|
507
|
0
|
0
|
|
|
|
|
(pIdx->iDb==0 || !db->init.busy) ){ |
508
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "there is already an index named %s", zName); |
509
|
0
|
|
|
|
|
|
sqliteFree(zName); |
510
|
0
|
|
|
|
|
|
return; |
511
|
|
|
|
|
|
|
} |
512
|
92
|
|
|
|
|
|
pTable = sqliteMalloc( sizeof(Table) ); |
513
|
92
|
50
|
|
|
|
|
if( pTable==0 ){ |
514
|
0
|
|
|
|
|
|
sqliteFree(zName); |
515
|
0
|
|
|
|
|
|
return; |
516
|
|
|
|
|
|
|
} |
517
|
92
|
|
|
|
|
|
pTable->zName = zName; |
518
|
92
|
|
|
|
|
|
pTable->nCol = 0; |
519
|
92
|
|
|
|
|
|
pTable->aCol = 0; |
520
|
92
|
|
|
|
|
|
pTable->iPKey = -1; |
521
|
92
|
|
|
|
|
|
pTable->pIndex = 0; |
522
|
92
|
|
|
|
|
|
pTable->iDb = iDb; |
523
|
92
|
50
|
|
|
|
|
if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable); |
524
|
92
|
|
|
|
|
|
pParse->pNewTable = pTable; |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
/* Begin generating the code that will insert the table record into |
527
|
|
|
|
|
|
|
** the SQLITE_MASTER table. Note in particular that we must go ahead |
528
|
|
|
|
|
|
|
** and allocate the record number for the table entry now. Before any |
529
|
|
|
|
|
|
|
** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause |
530
|
|
|
|
|
|
|
** indices to be created and the table record must come before the |
531
|
|
|
|
|
|
|
** indices. Hence, the record number for the table must be allocated |
532
|
|
|
|
|
|
|
** now. |
533
|
|
|
|
|
|
|
*/ |
534
|
92
|
100
|
|
|
|
|
if( !db->init.busy && (v = sqliteGetVdbe(pParse))!=0 ){ |
|
|
50
|
|
|
|
|
|
535
|
22
|
|
|
|
|
|
sqliteBeginWriteOperation(pParse, 0, isTemp); |
536
|
22
|
100
|
|
|
|
|
if( !isTemp ){ |
537
|
21
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0); |
538
|
21
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_SetCookie, 0, 1); |
539
|
|
|
|
|
|
|
} |
540
|
22
|
|
|
|
|
|
sqliteOpenMasterTable(v, isTemp); |
541
|
22
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_NewRecno, 0, 0); |
542
|
22
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Dup, 0, 0); |
543
|
22
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_String, 0, 0); |
544
|
22
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
/* |
549
|
|
|
|
|
|
|
** Add a new column to the table currently being constructed. |
550
|
|
|
|
|
|
|
** |
551
|
|
|
|
|
|
|
** The parser calls this routine once for each column declaration |
552
|
|
|
|
|
|
|
** in a CREATE TABLE statement. sqliteStartTable() gets called |
553
|
|
|
|
|
|
|
** first to get things going. Then this routine is called for each |
554
|
|
|
|
|
|
|
** column. |
555
|
|
|
|
|
|
|
*/ |
556
|
351
|
|
|
|
|
|
void sqliteAddColumn(Parse *pParse, Token *pName){ |
557
|
|
|
|
|
|
|
Table *p; |
558
|
|
|
|
|
|
|
int i; |
559
|
351
|
|
|
|
|
|
char *z = 0; |
560
|
|
|
|
|
|
|
Column *pCol; |
561
|
351
|
50
|
|
|
|
|
if( (p = pParse->pNewTable)==0 ) return; |
562
|
351
|
|
|
|
|
|
sqliteSetNString(&z, pName->z, pName->n, 0); |
563
|
351
|
50
|
|
|
|
|
if( z==0 ) return; |
564
|
351
|
|
|
|
|
|
sqliteDequote(z); |
565
|
944
|
100
|
|
|
|
|
for(i=0; inCol; i++){ |
566
|
593
|
50
|
|
|
|
|
if( sqliteStrICmp(z, p->aCol[i].zName)==0 ){ |
567
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "duplicate column name: %s", z); |
568
|
0
|
|
|
|
|
|
sqliteFree(z); |
569
|
0
|
|
|
|
|
|
return; |
570
|
|
|
|
|
|
|
} |
571
|
|
|
|
|
|
|
} |
572
|
351
|
100
|
|
|
|
|
if( (p->nCol & 0x7)==0 ){ |
573
|
|
|
|
|
|
|
Column *aNew; |
574
|
92
|
|
|
|
|
|
aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0])); |
575
|
92
|
50
|
|
|
|
|
if( aNew==0 ) return; |
576
|
92
|
|
|
|
|
|
p->aCol = aNew; |
577
|
|
|
|
|
|
|
} |
578
|
351
|
|
|
|
|
|
pCol = &p->aCol[p->nCol]; |
579
|
351
|
|
|
|
|
|
memset(pCol, 0, sizeof(p->aCol[0])); |
580
|
351
|
|
|
|
|
|
pCol->zName = z; |
581
|
351
|
|
|
|
|
|
pCol->sortOrder = SQLITE_SO_NUM; |
582
|
351
|
|
|
|
|
|
p->nCol++; |
583
|
|
|
|
|
|
|
} |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
/* |
586
|
|
|
|
|
|
|
** This routine is called by the parser while in the middle of |
587
|
|
|
|
|
|
|
** parsing a CREATE TABLE statement. A "NOT NULL" constraint has |
588
|
|
|
|
|
|
|
** been seen on a column. This routine sets the notNull flag on |
589
|
|
|
|
|
|
|
** the column currently under construction. |
590
|
|
|
|
|
|
|
*/ |
591
|
22
|
|
|
|
|
|
void sqliteAddNotNull(Parse *pParse, int onError){ |
592
|
|
|
|
|
|
|
Table *p; |
593
|
|
|
|
|
|
|
int i; |
594
|
22
|
50
|
|
|
|
|
if( (p = pParse->pNewTable)==0 ) return; |
595
|
22
|
|
|
|
|
|
i = p->nCol-1; |
596
|
22
|
50
|
|
|
|
|
if( i>=0 ) p->aCol[i].notNull = onError; |
597
|
|
|
|
|
|
|
} |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
/* |
600
|
|
|
|
|
|
|
** This routine is called by the parser while in the middle of |
601
|
|
|
|
|
|
|
** parsing a CREATE TABLE statement. The pFirst token is the first |
602
|
|
|
|
|
|
|
** token in the sequence of tokens that describe the type of the |
603
|
|
|
|
|
|
|
** column currently under construction. pLast is the last token |
604
|
|
|
|
|
|
|
** in the sequence. Use this information to construct a string |
605
|
|
|
|
|
|
|
** that contains the typename of the column and store that string |
606
|
|
|
|
|
|
|
** in zType. |
607
|
|
|
|
|
|
|
*/ |
608
|
312
|
|
|
|
|
|
void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){ |
609
|
|
|
|
|
|
|
Table *p; |
610
|
|
|
|
|
|
|
int i, j; |
611
|
|
|
|
|
|
|
int n; |
612
|
|
|
|
|
|
|
char *z, **pz; |
613
|
|
|
|
|
|
|
Column *pCol; |
614
|
312
|
50
|
|
|
|
|
if( (p = pParse->pNewTable)==0 ) return; |
615
|
312
|
|
|
|
|
|
i = p->nCol-1; |
616
|
312
|
50
|
|
|
|
|
if( i<0 ) return; |
617
|
312
|
|
|
|
|
|
pCol = &p->aCol[i]; |
618
|
312
|
|
|
|
|
|
pz = &pCol->zType; |
619
|
312
|
|
|
|
|
|
n = pLast->n + Addr(pLast->z) - Addr(pFirst->z); |
620
|
312
|
|
|
|
|
|
sqliteSetNString(pz, pFirst->z, n, 0); |
621
|
312
|
|
|
|
|
|
z = *pz; |
622
|
312
|
50
|
|
|
|
|
if( z==0 ) return; |
623
|
1889
|
100
|
|
|
|
|
for(i=j=0; z[i]; i++){ |
624
|
1577
|
|
|
|
|
|
int c = z[i]; |
625
|
1577
|
100
|
|
|
|
|
if( isspace(c) ) continue; |
626
|
1561
|
|
|
|
|
|
z[j++] = c; |
627
|
|
|
|
|
|
|
} |
628
|
312
|
|
|
|
|
|
z[j] = 0; |
629
|
312
|
100
|
|
|
|
|
if( pParse->db->file_format>=4 ){ |
630
|
187
|
|
|
|
|
|
pCol->sortOrder = sqliteCollateType(z, n); |
631
|
|
|
|
|
|
|
}else{ |
632
|
125
|
|
|
|
|
|
pCol->sortOrder = SQLITE_SO_NUM; |
633
|
|
|
|
|
|
|
} |
634
|
|
|
|
|
|
|
} |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
/* |
637
|
|
|
|
|
|
|
** The given token is the default value for the last column added to |
638
|
|
|
|
|
|
|
** the table currently under construction. If "minusFlag" is true, it |
639
|
|
|
|
|
|
|
** means the value token was preceded by a minus sign. |
640
|
|
|
|
|
|
|
** |
641
|
|
|
|
|
|
|
** This routine is called by the parser while in the middle of |
642
|
|
|
|
|
|
|
** parsing a CREATE TABLE statement. |
643
|
|
|
|
|
|
|
*/ |
644
|
0
|
|
|
|
|
|
void sqliteAddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){ |
645
|
|
|
|
|
|
|
Table *p; |
646
|
|
|
|
|
|
|
int i; |
647
|
|
|
|
|
|
|
char **pz; |
648
|
0
|
0
|
|
|
|
|
if( (p = pParse->pNewTable)==0 ) return; |
649
|
0
|
|
|
|
|
|
i = p->nCol-1; |
650
|
0
|
0
|
|
|
|
|
if( i<0 ) return; |
651
|
0
|
|
|
|
|
|
pz = &p->aCol[i].zDflt; |
652
|
0
|
0
|
|
|
|
|
if( minusFlag ){ |
653
|
0
|
|
|
|
|
|
sqliteSetNString(pz, "-", 1, pVal->z, pVal->n, 0); |
654
|
|
|
|
|
|
|
}else{ |
655
|
0
|
|
|
|
|
|
sqliteSetNString(pz, pVal->z, pVal->n, 0); |
656
|
|
|
|
|
|
|
} |
657
|
0
|
|
|
|
|
|
sqliteDequote(*pz); |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
/* |
661
|
|
|
|
|
|
|
** Designate the PRIMARY KEY for the table. pList is a list of names |
662
|
|
|
|
|
|
|
** of columns that form the primary key. If pList is NULL, then the |
663
|
|
|
|
|
|
|
** most recently added column of the table is the primary key. |
664
|
|
|
|
|
|
|
** |
665
|
|
|
|
|
|
|
** A table can have at most one primary key. If the table already has |
666
|
|
|
|
|
|
|
** a primary key (and this is the second primary key) then create an |
667
|
|
|
|
|
|
|
** error. |
668
|
|
|
|
|
|
|
** |
669
|
|
|
|
|
|
|
** If the PRIMARY KEY is on a single column whose datatype is INTEGER, |
670
|
|
|
|
|
|
|
** then we will try to use that column as the row id. (Exception: |
671
|
|
|
|
|
|
|
** For backwards compatibility with older databases, do not do this |
672
|
|
|
|
|
|
|
** if the file format version number is less than 1.) Set the Table.iPKey |
673
|
|
|
|
|
|
|
** field of the table under construction to be the index of the |
674
|
|
|
|
|
|
|
** INTEGER PRIMARY KEY column. Table.iPKey is set to -1 if there is |
675
|
|
|
|
|
|
|
** no INTEGER PRIMARY KEY. |
676
|
|
|
|
|
|
|
** |
677
|
|
|
|
|
|
|
** If the key is not an INTEGER PRIMARY KEY, then create a unique |
678
|
|
|
|
|
|
|
** index for the key. No index is created for INTEGER PRIMARY KEYs. |
679
|
|
|
|
|
|
|
*/ |
680
|
4
|
|
|
|
|
|
void sqliteAddPrimaryKey(Parse *pParse, IdList *pList, int onError){ |
681
|
4
|
|
|
|
|
|
Table *pTab = pParse->pNewTable; |
682
|
4
|
|
|
|
|
|
char *zType = 0; |
683
|
4
|
|
|
|
|
|
int iCol = -1, i; |
684
|
4
|
50
|
|
|
|
|
if( pTab==0 ) goto primary_key_exit; |
685
|
4
|
50
|
|
|
|
|
if( pTab->hasPrimKey ){ |
686
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, |
687
|
|
|
|
|
|
|
"table \"%s\" has more than one primary key", pTab->zName); |
688
|
0
|
|
|
|
|
|
goto primary_key_exit; |
689
|
|
|
|
|
|
|
} |
690
|
4
|
|
|
|
|
|
pTab->hasPrimKey = 1; |
691
|
4
|
100
|
|
|
|
|
if( pList==0 ){ |
692
|
2
|
|
|
|
|
|
iCol = pTab->nCol - 1; |
693
|
2
|
|
|
|
|
|
pTab->aCol[iCol].isPrimKey = 1; |
694
|
|
|
|
|
|
|
}else{ |
695
|
5
|
100
|
|
|
|
|
for(i=0; inId; i++){ |
696
|
4
|
50
|
|
|
|
|
for(iCol=0; iColnCol; iCol++){ |
697
|
4
|
100
|
|
|
|
|
if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ) break; |
698
|
|
|
|
|
|
|
} |
699
|
3
|
50
|
|
|
|
|
if( iColnCol ) pTab->aCol[iCol].isPrimKey = 1; |
700
|
|
|
|
|
|
|
} |
701
|
2
|
100
|
|
|
|
|
if( pList->nId>1 ) iCol = -1; |
702
|
|
|
|
|
|
|
} |
703
|
4
|
100
|
|
|
|
|
if( iCol>=0 && iColnCol ){ |
|
|
50
|
|
|
|
|
|
704
|
3
|
|
|
|
|
|
zType = pTab->aCol[iCol].zType; |
705
|
|
|
|
|
|
|
} |
706
|
4
|
50
|
|
|
|
|
if( pParse->db->file_format>=1 && |
|
|
100
|
|
|
|
|
|
707
|
3
|
50
|
|
|
|
|
zType && sqliteStrICmp(zType, "INTEGER")==0 ){ |
708
|
0
|
|
|
|
|
|
pTab->iPKey = iCol; |
709
|
0
|
|
|
|
|
|
pTab->keyConf = onError; |
710
|
|
|
|
|
|
|
}else{ |
711
|
4
|
|
|
|
|
|
sqliteCreateIndex(pParse, 0, 0, pList, onError, 0, 0); |
712
|
4
|
|
|
|
|
|
pList = 0; |
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
primary_key_exit: |
716
|
4
|
|
|
|
|
|
sqliteIdListDelete(pList); |
717
|
4
|
|
|
|
|
|
return; |
718
|
|
|
|
|
|
|
} |
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
/* |
721
|
|
|
|
|
|
|
** Return the appropriate collating type given a type name. |
722
|
|
|
|
|
|
|
** |
723
|
|
|
|
|
|
|
** The collation type is text (SQLITE_SO_TEXT) if the type |
724
|
|
|
|
|
|
|
** name contains the character stream "text" or "blob" or |
725
|
|
|
|
|
|
|
** "clob". Any other type name is collated as numeric |
726
|
|
|
|
|
|
|
** (SQLITE_SO_NUM). |
727
|
|
|
|
|
|
|
*/ |
728
|
187
|
|
|
|
|
|
int sqliteCollateType(const char *zType, int nType){ |
729
|
|
|
|
|
|
|
int i; |
730
|
383
|
100
|
|
|
|
|
for(i=0; i
|
731
|
337
|
|
|
|
|
|
int c = *(zType++) | 0x60; |
732
|
337
|
100
|
|
|
|
|
if( (c=='b' || c=='c') && sqliteStrNICmp(zType, "lob", 3)==0 ){ |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
733
|
1
|
|
|
|
|
|
return SQLITE_SO_TEXT; |
734
|
|
|
|
|
|
|
} |
735
|
336
|
100
|
|
|
|
|
if( c=='c' && sqliteStrNICmp(zType, "har", 3)==0 ){ |
|
|
50
|
|
|
|
|
|
736
|
24
|
|
|
|
|
|
return SQLITE_SO_TEXT; |
737
|
|
|
|
|
|
|
} |
738
|
312
|
100
|
|
|
|
|
if( c=='t' && sqliteStrNICmp(zType, "ext", 3)==0 ){ |
|
|
100
|
|
|
|
|
|
739
|
116
|
|
|
|
|
|
return SQLITE_SO_TEXT; |
740
|
|
|
|
|
|
|
} |
741
|
|
|
|
|
|
|
} |
742
|
46
|
|
|
|
|
|
return SQLITE_SO_NUM; |
743
|
|
|
|
|
|
|
} |
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
/* |
746
|
|
|
|
|
|
|
** This routine is called by the parser while in the middle of |
747
|
|
|
|
|
|
|
** parsing a CREATE TABLE statement. A "COLLATE" clause has |
748
|
|
|
|
|
|
|
** been seen on a column. This routine sets the Column.sortOrder on |
749
|
|
|
|
|
|
|
** the column currently under construction. |
750
|
|
|
|
|
|
|
*/ |
751
|
0
|
|
|
|
|
|
void sqliteAddCollateType(Parse *pParse, int collType){ |
752
|
|
|
|
|
|
|
Table *p; |
753
|
|
|
|
|
|
|
int i; |
754
|
0
|
0
|
|
|
|
|
if( (p = pParse->pNewTable)==0 ) return; |
755
|
0
|
|
|
|
|
|
i = p->nCol-1; |
756
|
0
|
0
|
|
|
|
|
if( i>=0 ) p->aCol[i].sortOrder = collType; |
757
|
|
|
|
|
|
|
} |
758
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
/* |
760
|
|
|
|
|
|
|
** Come up with a new random value for the schema cookie. Make sure |
761
|
|
|
|
|
|
|
** the new value is different from the old. |
762
|
|
|
|
|
|
|
** |
763
|
|
|
|
|
|
|
** The schema cookie is used to determine when the schema for the |
764
|
|
|
|
|
|
|
** database changes. After each schema change, the cookie value |
765
|
|
|
|
|
|
|
** changes. When a process first reads the schema it records the |
766
|
|
|
|
|
|
|
** cookie. Thereafter, whenever it goes to access the database, |
767
|
|
|
|
|
|
|
** it checks the cookie to make sure the schema has not changed |
768
|
|
|
|
|
|
|
** since it was last read. |
769
|
|
|
|
|
|
|
** |
770
|
|
|
|
|
|
|
** This plan is not completely bullet-proof. It is possible for |
771
|
|
|
|
|
|
|
** the schema to change multiple times and for the cookie to be |
772
|
|
|
|
|
|
|
** set back to prior value. But schema changes are infrequent |
773
|
|
|
|
|
|
|
** and the probability of hitting the same cookie value is only |
774
|
|
|
|
|
|
|
** 1 chance in 2^32. So we're safe enough. |
775
|
|
|
|
|
|
|
*/ |
776
|
33
|
|
|
|
|
|
void sqliteChangeCookie(sqlite *db, Vdbe *v){ |
777
|
33
|
100
|
|
|
|
|
if( db->next_cookie==db->aDb[0].schema_cookie ){ |
778
|
|
|
|
|
|
|
unsigned char r; |
779
|
32
|
|
|
|
|
|
sqliteRandomness(1, &r); |
780
|
32
|
|
|
|
|
|
db->next_cookie = db->aDb[0].schema_cookie + r + 1; |
781
|
32
|
|
|
|
|
|
db->flags |= SQLITE_InternChanges; |
782
|
32
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0); |
783
|
32
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_SetCookie, 0, 0); |
784
|
|
|
|
|
|
|
} |
785
|
33
|
|
|
|
|
|
} |
786
|
|
|
|
|
|
|
|
787
|
|
|
|
|
|
|
/* |
788
|
|
|
|
|
|
|
** Measure the number of characters needed to output the given |
789
|
|
|
|
|
|
|
** identifier. The number returned includes any quotes used |
790
|
|
|
|
|
|
|
** but does not include the null terminator. |
791
|
|
|
|
|
|
|
*/ |
792
|
0
|
|
|
|
|
|
static int identLength(const char *z){ |
793
|
|
|
|
|
|
|
int n; |
794
|
0
|
|
|
|
|
|
int needQuote = 0; |
795
|
0
|
0
|
|
|
|
|
for(n=0; *z; n++, z++){ |
796
|
0
|
0
|
|
|
|
|
if( *z=='\'' ){ n++; needQuote=1; } |
797
|
|
|
|
|
|
|
} |
798
|
0
|
|
|
|
|
|
return n + needQuote*2; |
799
|
|
|
|
|
|
|
} |
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
/* |
802
|
|
|
|
|
|
|
** Write an identifier onto the end of the given string. Add |
803
|
|
|
|
|
|
|
** quote characters as needed. |
804
|
|
|
|
|
|
|
*/ |
805
|
0
|
|
|
|
|
|
static void identPut(char *z, int *pIdx, char *zIdent){ |
806
|
|
|
|
|
|
|
int i, j, needQuote; |
807
|
0
|
|
|
|
|
|
i = *pIdx; |
808
|
0
|
0
|
|
|
|
|
for(j=0; zIdent[j]; j++){ |
809
|
0
|
0
|
|
|
|
|
if( !isalnum(zIdent[j]) && zIdent[j]!='_' ) break; |
|
|
0
|
|
|
|
|
|
810
|
|
|
|
|
|
|
} |
811
|
0
|
0
|
|
|
|
|
needQuote = zIdent[j]!=0 || isdigit(zIdent[0]) |
812
|
0
|
0
|
|
|
|
|
|| sqliteKeywordCode(zIdent, j)!=TK_ID; |
|
|
0
|
|
|
|
|
|
813
|
0
|
0
|
|
|
|
|
if( needQuote ) z[i++] = '\''; |
814
|
0
|
0
|
|
|
|
|
for(j=0; zIdent[j]; j++){ |
815
|
0
|
|
|
|
|
|
z[i++] = zIdent[j]; |
816
|
0
|
0
|
|
|
|
|
if( zIdent[j]=='\'' ) z[i++] = '\''; |
817
|
|
|
|
|
|
|
} |
818
|
0
|
0
|
|
|
|
|
if( needQuote ) z[i++] = '\''; |
819
|
0
|
|
|
|
|
|
z[i] = 0; |
820
|
0
|
|
|
|
|
|
*pIdx = i; |
821
|
0
|
|
|
|
|
|
} |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
/* |
824
|
|
|
|
|
|
|
** Generate a CREATE TABLE statement appropriate for the given |
825
|
|
|
|
|
|
|
** table. Memory to hold the text of the statement is obtained |
826
|
|
|
|
|
|
|
** from sqliteMalloc() and must be freed by the calling function. |
827
|
|
|
|
|
|
|
*/ |
828
|
0
|
|
|
|
|
|
static char *createTableStmt(Table *p){ |
829
|
|
|
|
|
|
|
int i, k, n; |
830
|
|
|
|
|
|
|
char *zStmt; |
831
|
|
|
|
|
|
|
char *zSep, *zSep2, *zEnd; |
832
|
0
|
|
|
|
|
|
n = 0; |
833
|
0
|
0
|
|
|
|
|
for(i=0; inCol; i++){ |
834
|
0
|
|
|
|
|
|
n += identLength(p->aCol[i].zName); |
835
|
|
|
|
|
|
|
} |
836
|
0
|
|
|
|
|
|
n += identLength(p->zName); |
837
|
0
|
0
|
|
|
|
|
if( n<40 ){ |
838
|
0
|
|
|
|
|
|
zSep = ""; |
839
|
0
|
|
|
|
|
|
zSep2 = ","; |
840
|
0
|
|
|
|
|
|
zEnd = ")"; |
841
|
|
|
|
|
|
|
}else{ |
842
|
0
|
|
|
|
|
|
zSep = "\n "; |
843
|
0
|
|
|
|
|
|
zSep2 = ",\n "; |
844
|
0
|
|
|
|
|
|
zEnd = "\n)"; |
845
|
|
|
|
|
|
|
} |
846
|
0
|
|
|
|
|
|
n += 35 + 6*p->nCol; |
847
|
0
|
|
|
|
|
|
zStmt = sqliteMallocRaw( n ); |
848
|
0
|
0
|
|
|
|
|
if( zStmt==0 ) return 0; |
849
|
0
|
0
|
|
|
|
|
strcpy(zStmt, p->iDb==1 ? "CREATE TEMP TABLE " : "CREATE TABLE "); |
850
|
0
|
|
|
|
|
|
k = strlen(zStmt); |
851
|
0
|
|
|
|
|
|
identPut(zStmt, &k, p->zName); |
852
|
0
|
|
|
|
|
|
zStmt[k++] = '('; |
853
|
0
|
0
|
|
|
|
|
for(i=0; inCol; i++){ |
854
|
0
|
|
|
|
|
|
strcpy(&zStmt[k], zSep); |
855
|
0
|
|
|
|
|
|
k += strlen(&zStmt[k]); |
856
|
0
|
|
|
|
|
|
zSep = zSep2; |
857
|
0
|
|
|
|
|
|
identPut(zStmt, &k, p->aCol[i].zName); |
858
|
|
|
|
|
|
|
} |
859
|
0
|
|
|
|
|
|
strcpy(&zStmt[k], zEnd); |
860
|
0
|
|
|
|
|
|
return zStmt; |
861
|
|
|
|
|
|
|
} |
862
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
/* |
864
|
|
|
|
|
|
|
** This routine is called to report the final ")" that terminates |
865
|
|
|
|
|
|
|
** a CREATE TABLE statement. |
866
|
|
|
|
|
|
|
** |
867
|
|
|
|
|
|
|
** The table structure that other action routines have been building |
868
|
|
|
|
|
|
|
** is added to the internal hash tables, assuming no errors have |
869
|
|
|
|
|
|
|
** occurred. |
870
|
|
|
|
|
|
|
** |
871
|
|
|
|
|
|
|
** An entry for the table is made in the master table on disk, unless |
872
|
|
|
|
|
|
|
** this is a temporary table or db->init.busy==1. When db->init.busy==1 |
873
|
|
|
|
|
|
|
** it means we are reading the sqlite_master table because we just |
874
|
|
|
|
|
|
|
** connected to the database or because the sqlite_master table has |
875
|
|
|
|
|
|
|
** recently changes, so the entry for this table already exists in |
876
|
|
|
|
|
|
|
** the sqlite_master table. We do not want to create it again. |
877
|
|
|
|
|
|
|
** |
878
|
|
|
|
|
|
|
** If the pSelect argument is not NULL, it means that this routine |
879
|
|
|
|
|
|
|
** was called to create a table generated from a |
880
|
|
|
|
|
|
|
** "CREATE TABLE ... AS SELECT ..." statement. The column names of |
881
|
|
|
|
|
|
|
** the new table will match the result set of the SELECT. |
882
|
|
|
|
|
|
|
*/ |
883
|
92
|
|
|
|
|
|
void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){ |
884
|
|
|
|
|
|
|
Table *p; |
885
|
92
|
|
|
|
|
|
sqlite *db = pParse->db; |
886
|
|
|
|
|
|
|
|
887
|
92
|
50
|
|
|
|
|
if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite_malloc_failed ) return; |
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
888
|
92
|
|
|
|
|
|
p = pParse->pNewTable; |
889
|
92
|
50
|
|
|
|
|
if( p==0 ) return; |
890
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
/* If the table is generated from a SELECT, then construct the |
892
|
|
|
|
|
|
|
** list of columns and the text of the table. |
893
|
|
|
|
|
|
|
*/ |
894
|
92
|
50
|
|
|
|
|
if( pSelect ){ |
895
|
0
|
|
|
|
|
|
Table *pSelTab = sqliteResultSetOfSelect(pParse, 0, pSelect); |
896
|
0
|
0
|
|
|
|
|
if( pSelTab==0 ) return; |
897
|
|
|
|
|
|
|
assert( p->aCol==0 ); |
898
|
0
|
|
|
|
|
|
p->nCol = pSelTab->nCol; |
899
|
0
|
|
|
|
|
|
p->aCol = pSelTab->aCol; |
900
|
0
|
|
|
|
|
|
pSelTab->nCol = 0; |
901
|
0
|
|
|
|
|
|
pSelTab->aCol = 0; |
902
|
0
|
|
|
|
|
|
sqliteDeleteTable(0, pSelTab); |
903
|
|
|
|
|
|
|
} |
904
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
/* If the db->init.busy is 1 it means we are reading the SQL off the |
906
|
|
|
|
|
|
|
** "sqlite_master" or "sqlite_temp_master" table on the disk. |
907
|
|
|
|
|
|
|
** So do not write to the disk again. Extract the root page number |
908
|
|
|
|
|
|
|
** for the table from the db->init.newTnum field. (The page number |
909
|
|
|
|
|
|
|
** should have been put there by the sqliteOpenCb routine.) |
910
|
|
|
|
|
|
|
*/ |
911
|
92
|
100
|
|
|
|
|
if( db->init.busy ){ |
912
|
70
|
|
|
|
|
|
p->tnum = db->init.newTnum; |
913
|
|
|
|
|
|
|
} |
914
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
/* If not initializing, then create a record for the new table |
916
|
|
|
|
|
|
|
** in the SQLITE_MASTER table of the database. The record number |
917
|
|
|
|
|
|
|
** for the new table entry should already be on the stack. |
918
|
|
|
|
|
|
|
** |
919
|
|
|
|
|
|
|
** If this is a TEMPORARY table, write the entry into the auxiliary |
920
|
|
|
|
|
|
|
** file instead of into the main database file. |
921
|
|
|
|
|
|
|
*/ |
922
|
92
|
100
|
|
|
|
|
if( !db->init.busy ){ |
923
|
|
|
|
|
|
|
int n; |
924
|
|
|
|
|
|
|
Vdbe *v; |
925
|
|
|
|
|
|
|
|
926
|
22
|
|
|
|
|
|
v = sqliteGetVdbe(pParse); |
927
|
22
|
50
|
|
|
|
|
if( v==0 ) return; |
928
|
22
|
50
|
|
|
|
|
if( p->pSelect==0 ){ |
929
|
|
|
|
|
|
|
/* A regular table */ |
930
|
22
|
|
|
|
|
|
sqliteVdbeOp3(v, OP_CreateTable, 0, p->iDb, (char*)&p->tnum, P3_POINTER); |
931
|
|
|
|
|
|
|
}else{ |
932
|
|
|
|
|
|
|
/* A view */ |
933
|
0
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Integer, 0, 0); |
934
|
|
|
|
|
|
|
} |
935
|
22
|
|
|
|
|
|
p->tnum = 0; |
936
|
22
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Pull, 1, 0); |
937
|
22
|
50
|
|
|
|
|
sqliteVdbeOp3(v, OP_String, 0, 0, p->pSelect==0?"table":"view", P3_STATIC); |
938
|
22
|
|
|
|
|
|
sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0); |
939
|
22
|
|
|
|
|
|
sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0); |
940
|
22
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Dup, 4, 0); |
941
|
22
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_String, 0, 0); |
942
|
22
|
50
|
|
|
|
|
if( pSelect ){ |
943
|
0
|
|
|
|
|
|
char *z = createTableStmt(p); |
944
|
0
|
0
|
|
|
|
|
n = z ? strlen(z) : 0; |
945
|
0
|
|
|
|
|
|
sqliteVdbeChangeP3(v, -1, z, n); |
946
|
0
|
|
|
|
|
|
sqliteFree(z); |
947
|
|
|
|
|
|
|
}else{ |
948
|
|
|
|
|
|
|
assert( pEnd!=0 ); |
949
|
22
|
|
|
|
|
|
n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1; |
950
|
22
|
|
|
|
|
|
sqliteVdbeChangeP3(v, -1, pParse->sFirstToken.z, n); |
951
|
|
|
|
|
|
|
} |
952
|
22
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); |
953
|
22
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); |
954
|
22
|
100
|
|
|
|
|
if( !p->iDb ){ |
955
|
21
|
|
|
|
|
|
sqliteChangeCookie(db, v); |
956
|
|
|
|
|
|
|
} |
957
|
22
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Close, 0, 0); |
958
|
22
|
50
|
|
|
|
|
if( pSelect ){ |
959
|
0
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Integer, p->iDb, 0); |
960
|
0
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0); |
961
|
0
|
|
|
|
|
|
pParse->nTab = 2; |
962
|
0
|
|
|
|
|
|
sqliteSelect(pParse, pSelect, SRT_Table, 1, 0, 0, 0); |
963
|
|
|
|
|
|
|
} |
964
|
22
|
|
|
|
|
|
sqliteEndWriteOperation(pParse); |
965
|
|
|
|
|
|
|
} |
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
/* Add the table to the in-memory representation of the database. |
968
|
|
|
|
|
|
|
*/ |
969
|
92
|
50
|
|
|
|
|
if( pParse->explain==0 && pParse->nErr==0 ){ |
|
|
50
|
|
|
|
|
|
970
|
|
|
|
|
|
|
Table *pOld; |
971
|
|
|
|
|
|
|
FKey *pFKey; |
972
|
92
|
|
|
|
|
|
pOld = sqliteHashInsert(&db->aDb[p->iDb].tblHash, |
973
|
184
|
|
|
|
|
|
p->zName, strlen(p->zName)+1, p); |
974
|
92
|
50
|
|
|
|
|
if( pOld ){ |
975
|
|
|
|
|
|
|
assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ |
976
|
0
|
|
|
|
|
|
return; |
977
|
|
|
|
|
|
|
} |
978
|
92
|
50
|
|
|
|
|
for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){ |
979
|
0
|
|
|
|
|
|
int nTo = strlen(pFKey->zTo) + 1; |
980
|
0
|
|
|
|
|
|
pFKey->pNextTo = sqliteHashFind(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo); |
981
|
0
|
|
|
|
|
|
sqliteHashInsert(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo, pFKey); |
982
|
|
|
|
|
|
|
} |
983
|
92
|
|
|
|
|
|
pParse->pNewTable = 0; |
984
|
92
|
|
|
|
|
|
db->nTable++; |
985
|
92
|
|
|
|
|
|
db->flags |= SQLITE_InternChanges; |
986
|
|
|
|
|
|
|
} |
987
|
|
|
|
|
|
|
} |
988
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
/* |
990
|
|
|
|
|
|
|
** The parser calls this routine in order to create a new VIEW |
991
|
|
|
|
|
|
|
*/ |
992
|
0
|
|
|
|
|
|
void sqliteCreateView( |
993
|
|
|
|
|
|
|
Parse *pParse, /* The parsing context */ |
994
|
|
|
|
|
|
|
Token *pBegin, /* The CREATE token that begins the statement */ |
995
|
|
|
|
|
|
|
Token *pName, /* The token that holds the name of the view */ |
996
|
|
|
|
|
|
|
Select *pSelect, /* A SELECT statement that will become the new view */ |
997
|
|
|
|
|
|
|
int isTemp /* TRUE for a TEMPORARY view */ |
998
|
|
|
|
|
|
|
){ |
999
|
|
|
|
|
|
|
Table *p; |
1000
|
|
|
|
|
|
|
int n; |
1001
|
|
|
|
|
|
|
const char *z; |
1002
|
|
|
|
|
|
|
Token sEnd; |
1003
|
|
|
|
|
|
|
DbFixer sFix; |
1004
|
|
|
|
|
|
|
|
1005
|
0
|
|
|
|
|
|
sqliteStartTable(pParse, pBegin, pName, isTemp, 1); |
1006
|
0
|
|
|
|
|
|
p = pParse->pNewTable; |
1007
|
0
|
0
|
|
|
|
|
if( p==0 || pParse->nErr ){ |
|
|
0
|
|
|
|
|
|
1008
|
0
|
|
|
|
|
|
sqliteSelectDelete(pSelect); |
1009
|
0
|
|
|
|
|
|
return; |
1010
|
|
|
|
|
|
|
} |
1011
|
0
|
0
|
|
|
|
|
if( sqliteFixInit(&sFix, pParse, p->iDb, "view", pName) |
1012
|
0
|
0
|
|
|
|
|
&& sqliteFixSelect(&sFix, pSelect) |
1013
|
|
|
|
|
|
|
){ |
1014
|
0
|
|
|
|
|
|
sqliteSelectDelete(pSelect); |
1015
|
0
|
|
|
|
|
|
return; |
1016
|
|
|
|
|
|
|
} |
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
/* Make a copy of the entire SELECT statement that defines the view. |
1019
|
|
|
|
|
|
|
** This will force all the Expr.token.z values to be dynamically |
1020
|
|
|
|
|
|
|
** allocated rather than point to the input string - which means that |
1021
|
|
|
|
|
|
|
** they will persist after the current sqlite_exec() call returns. |
1022
|
|
|
|
|
|
|
*/ |
1023
|
0
|
|
|
|
|
|
p->pSelect = sqliteSelectDup(pSelect); |
1024
|
0
|
|
|
|
|
|
sqliteSelectDelete(pSelect); |
1025
|
0
|
0
|
|
|
|
|
if( !pParse->db->init.busy ){ |
1026
|
0
|
|
|
|
|
|
sqliteViewGetColumnNames(pParse, p); |
1027
|
|
|
|
|
|
|
} |
1028
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
/* Locate the end of the CREATE VIEW statement. Make sEnd point to |
1030
|
|
|
|
|
|
|
** the end. |
1031
|
|
|
|
|
|
|
*/ |
1032
|
0
|
|
|
|
|
|
sEnd = pParse->sLastToken; |
1033
|
0
|
0
|
|
|
|
|
if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){ |
|
|
0
|
|
|
|
|
|
1034
|
0
|
|
|
|
|
|
sEnd.z += sEnd.n; |
1035
|
|
|
|
|
|
|
} |
1036
|
0
|
|
|
|
|
|
sEnd.n = 0; |
1037
|
0
|
|
|
|
|
|
n = sEnd.z - pBegin->z; |
1038
|
0
|
|
|
|
|
|
z = pBegin->z; |
1039
|
0
|
0
|
|
|
|
|
while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; } |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
1040
|
0
|
|
|
|
|
|
sEnd.z = &z[n-1]; |
1041
|
0
|
|
|
|
|
|
sEnd.n = 1; |
1042
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
/* Use sqliteEndTable() to add the view to the SQLITE_MASTER table */ |
1044
|
0
|
|
|
|
|
|
sqliteEndTable(pParse, &sEnd, 0); |
1045
|
0
|
|
|
|
|
|
return; |
1046
|
|
|
|
|
|
|
} |
1047
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
/* |
1049
|
|
|
|
|
|
|
** The Table structure pTable is really a VIEW. Fill in the names of |
1050
|
|
|
|
|
|
|
** the columns of the view in the pTable structure. Return the number |
1051
|
|
|
|
|
|
|
** of errors. If an error is seen leave an error message in pParse->zErrMsg. |
1052
|
|
|
|
|
|
|
*/ |
1053
|
0
|
|
|
|
|
|
int sqliteViewGetColumnNames(Parse *pParse, Table *pTable){ |
1054
|
|
|
|
|
|
|
ExprList *pEList; |
1055
|
|
|
|
|
|
|
Select *pSel; |
1056
|
|
|
|
|
|
|
Table *pSelTab; |
1057
|
0
|
|
|
|
|
|
int nErr = 0; |
1058
|
|
|
|
|
|
|
|
1059
|
|
|
|
|
|
|
assert( pTable ); |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
/* A positive nCol means the columns names for this view are |
1062
|
|
|
|
|
|
|
** already known. |
1063
|
|
|
|
|
|
|
*/ |
1064
|
0
|
0
|
|
|
|
|
if( pTable->nCol>0 ) return 0; |
1065
|
|
|
|
|
|
|
|
1066
|
|
|
|
|
|
|
/* A negative nCol is a special marker meaning that we are currently |
1067
|
|
|
|
|
|
|
** trying to compute the column names. If we enter this routine with |
1068
|
|
|
|
|
|
|
** a negative nCol, it means two or more views form a loop, like this: |
1069
|
|
|
|
|
|
|
** |
1070
|
|
|
|
|
|
|
** CREATE VIEW one AS SELECT * FROM two; |
1071
|
|
|
|
|
|
|
** CREATE VIEW two AS SELECT * FROM one; |
1072
|
|
|
|
|
|
|
** |
1073
|
|
|
|
|
|
|
** Actually, this error is caught previously and so the following test |
1074
|
|
|
|
|
|
|
** should always fail. But we will leave it in place just to be safe. |
1075
|
|
|
|
|
|
|
*/ |
1076
|
0
|
0
|
|
|
|
|
if( pTable->nCol<0 ){ |
1077
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "view %s is circularly defined", pTable->zName); |
1078
|
0
|
|
|
|
|
|
return 1; |
1079
|
|
|
|
|
|
|
} |
1080
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
/* If we get this far, it means we need to compute the table names. |
1082
|
|
|
|
|
|
|
*/ |
1083
|
|
|
|
|
|
|
assert( pTable->pSelect ); /* If nCol==0, then pTable must be a VIEW */ |
1084
|
0
|
|
|
|
|
|
pSel = pTable->pSelect; |
1085
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
/* Note that the call to sqliteResultSetOfSelect() will expand any |
1087
|
|
|
|
|
|
|
** "*" elements in this list. But we will need to restore the list |
1088
|
|
|
|
|
|
|
** back to its original configuration afterwards, so we save a copy of |
1089
|
|
|
|
|
|
|
** the original in pEList. |
1090
|
|
|
|
|
|
|
*/ |
1091
|
0
|
|
|
|
|
|
pEList = pSel->pEList; |
1092
|
0
|
|
|
|
|
|
pSel->pEList = sqliteExprListDup(pEList); |
1093
|
0
|
0
|
|
|
|
|
if( pSel->pEList==0 ){ |
1094
|
0
|
|
|
|
|
|
pSel->pEList = pEList; |
1095
|
0
|
|
|
|
|
|
return 1; /* Malloc failed */ |
1096
|
|
|
|
|
|
|
} |
1097
|
0
|
|
|
|
|
|
pTable->nCol = -1; |
1098
|
0
|
|
|
|
|
|
pSelTab = sqliteResultSetOfSelect(pParse, 0, pSel); |
1099
|
0
|
0
|
|
|
|
|
if( pSelTab ){ |
1100
|
|
|
|
|
|
|
assert( pTable->aCol==0 ); |
1101
|
0
|
|
|
|
|
|
pTable->nCol = pSelTab->nCol; |
1102
|
0
|
|
|
|
|
|
pTable->aCol = pSelTab->aCol; |
1103
|
0
|
|
|
|
|
|
pSelTab->nCol = 0; |
1104
|
0
|
|
|
|
|
|
pSelTab->aCol = 0; |
1105
|
0
|
|
|
|
|
|
sqliteDeleteTable(0, pSelTab); |
1106
|
0
|
|
|
|
|
|
DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews); |
1107
|
|
|
|
|
|
|
}else{ |
1108
|
0
|
|
|
|
|
|
pTable->nCol = 0; |
1109
|
0
|
|
|
|
|
|
nErr++; |
1110
|
|
|
|
|
|
|
} |
1111
|
0
|
|
|
|
|
|
sqliteSelectUnbind(pSel); |
1112
|
0
|
|
|
|
|
|
sqliteExprListDelete(pSel->pEList); |
1113
|
0
|
|
|
|
|
|
pSel->pEList = pEList; |
1114
|
0
|
|
|
|
|
|
return nErr; |
1115
|
|
|
|
|
|
|
} |
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
/* |
1118
|
|
|
|
|
|
|
** Clear the column names from the VIEW pTable. |
1119
|
|
|
|
|
|
|
** |
1120
|
|
|
|
|
|
|
** This routine is called whenever any other table or view is modified. |
1121
|
|
|
|
|
|
|
** The view passed into this routine might depend directly or indirectly |
1122
|
|
|
|
|
|
|
** on the modified or deleted table so we need to clear the old column |
1123
|
|
|
|
|
|
|
** names so that they will be recomputed. |
1124
|
|
|
|
|
|
|
*/ |
1125
|
0
|
|
|
|
|
|
static void sqliteViewResetColumnNames(Table *pTable){ |
1126
|
|
|
|
|
|
|
int i; |
1127
|
|
|
|
|
|
|
Column *pCol; |
1128
|
|
|
|
|
|
|
assert( pTable!=0 && pTable->pSelect!=0 ); |
1129
|
0
|
0
|
|
|
|
|
for(i=0, pCol=pTable->aCol; inCol; i++, pCol++){ |
1130
|
0
|
|
|
|
|
|
sqliteFree(pCol->zName); |
1131
|
0
|
|
|
|
|
|
sqliteFree(pCol->zDflt); |
1132
|
0
|
|
|
|
|
|
sqliteFree(pCol->zType); |
1133
|
|
|
|
|
|
|
} |
1134
|
0
|
|
|
|
|
|
sqliteFree(pTable->aCol); |
1135
|
0
|
|
|
|
|
|
pTable->aCol = 0; |
1136
|
0
|
|
|
|
|
|
pTable->nCol = 0; |
1137
|
0
|
|
|
|
|
|
} |
1138
|
|
|
|
|
|
|
|
1139
|
|
|
|
|
|
|
/* |
1140
|
|
|
|
|
|
|
** Clear the column names from every VIEW in database idx. |
1141
|
|
|
|
|
|
|
*/ |
1142
|
11
|
|
|
|
|
|
static void sqliteViewResetAll(sqlite *db, int idx){ |
1143
|
|
|
|
|
|
|
HashElem *i; |
1144
|
11
|
50
|
|
|
|
|
if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; |
1145
|
0
|
0
|
|
|
|
|
for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){ |
1146
|
0
|
|
|
|
|
|
Table *pTab = sqliteHashData(i); |
1147
|
0
|
0
|
|
|
|
|
if( pTab->pSelect ){ |
1148
|
0
|
|
|
|
|
|
sqliteViewResetColumnNames(pTab); |
1149
|
|
|
|
|
|
|
} |
1150
|
|
|
|
|
|
|
} |
1151
|
0
|
|
|
|
|
|
DbClearProperty(db, idx, DB_UnresetViews); |
1152
|
|
|
|
|
|
|
} |
1153
|
|
|
|
|
|
|
|
1154
|
|
|
|
|
|
|
/* |
1155
|
|
|
|
|
|
|
** Given a token, look up a table with that name. If not found, leave |
1156
|
|
|
|
|
|
|
** an error for the parser to find and return NULL. |
1157
|
|
|
|
|
|
|
*/ |
1158
|
17
|
|
|
|
|
|
Table *sqliteTableFromToken(Parse *pParse, Token *pTok){ |
1159
|
|
|
|
|
|
|
char *zName; |
1160
|
|
|
|
|
|
|
Table *pTab; |
1161
|
17
|
|
|
|
|
|
zName = sqliteTableNameFromToken(pTok); |
1162
|
17
|
50
|
|
|
|
|
if( zName==0 ) return 0; |
1163
|
17
|
|
|
|
|
|
pTab = sqliteFindTable(pParse->db, zName, 0); |
1164
|
17
|
|
|
|
|
|
sqliteFree(zName); |
1165
|
17
|
100
|
|
|
|
|
if( pTab==0 ){ |
1166
|
6
|
|
|
|
|
|
sqliteErrorMsg(pParse, "no such table: %T", pTok); |
1167
|
|
|
|
|
|
|
} |
1168
|
17
|
|
|
|
|
|
return pTab; |
1169
|
|
|
|
|
|
|
} |
1170
|
|
|
|
|
|
|
|
1171
|
|
|
|
|
|
|
/* |
1172
|
|
|
|
|
|
|
** This routine is called to do the work of a DROP TABLE statement. |
1173
|
|
|
|
|
|
|
** pName is the name of the table to be dropped. |
1174
|
|
|
|
|
|
|
*/ |
1175
|
17
|
|
|
|
|
|
void sqliteDropTable(Parse *pParse, Token *pName, int isView){ |
1176
|
|
|
|
|
|
|
Table *pTable; |
1177
|
|
|
|
|
|
|
Vdbe *v; |
1178
|
|
|
|
|
|
|
int base; |
1179
|
17
|
|
|
|
|
|
sqlite *db = pParse->db; |
1180
|
|
|
|
|
|
|
int iDb; |
1181
|
|
|
|
|
|
|
|
1182
|
17
|
50
|
|
|
|
|
if( pParse->nErr || sqlite_malloc_failed ) return; |
|
|
50
|
|
|
|
|
|
1183
|
17
|
|
|
|
|
|
pTable = sqliteTableFromToken(pParse, pName); |
1184
|
17
|
100
|
|
|
|
|
if( pTable==0 ) return; |
1185
|
11
|
|
|
|
|
|
iDb = pTable->iDb; |
1186
|
|
|
|
|
|
|
assert( iDb>=0 && iDbnDb ); |
1187
|
|
|
|
|
|
|
#ifndef SQLITE_OMIT_AUTHORIZATION |
1188
|
|
|
|
|
|
|
{ |
1189
|
|
|
|
|
|
|
int code; |
1190
|
11
|
50
|
|
|
|
|
const char *zTab = SCHEMA_TABLE(pTable->iDb); |
1191
|
11
|
|
|
|
|
|
const char *zDb = db->aDb[pTable->iDb].zName; |
1192
|
11
|
50
|
|
|
|
|
if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ |
1193
|
0
|
|
|
|
|
|
return; |
1194
|
|
|
|
|
|
|
} |
1195
|
11
|
50
|
|
|
|
|
if( isView ){ |
1196
|
0
|
0
|
|
|
|
|
if( iDb==1 ){ |
1197
|
0
|
|
|
|
|
|
code = SQLITE_DROP_TEMP_VIEW; |
1198
|
|
|
|
|
|
|
}else{ |
1199
|
0
|
|
|
|
|
|
code = SQLITE_DROP_VIEW; |
1200
|
|
|
|
|
|
|
} |
1201
|
|
|
|
|
|
|
}else{ |
1202
|
11
|
50
|
|
|
|
|
if( iDb==1 ){ |
1203
|
0
|
|
|
|
|
|
code = SQLITE_DROP_TEMP_TABLE; |
1204
|
|
|
|
|
|
|
}else{ |
1205
|
11
|
|
|
|
|
|
code = SQLITE_DROP_TABLE; |
1206
|
|
|
|
|
|
|
} |
1207
|
|
|
|
|
|
|
} |
1208
|
11
|
50
|
|
|
|
|
if( sqliteAuthCheck(pParse, code, pTable->zName, 0, zDb) ){ |
1209
|
0
|
|
|
|
|
|
return; |
1210
|
|
|
|
|
|
|
} |
1211
|
11
|
50
|
|
|
|
|
if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTable->zName, 0, zDb) ){ |
1212
|
0
|
|
|
|
|
|
return; |
1213
|
|
|
|
|
|
|
} |
1214
|
|
|
|
|
|
|
} |
1215
|
|
|
|
|
|
|
#endif |
1216
|
11
|
50
|
|
|
|
|
if( pTable->readOnly ){ |
1217
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "table %s may not be dropped", pTable->zName); |
1218
|
0
|
|
|
|
|
|
pParse->nErr++; |
1219
|
0
|
|
|
|
|
|
return; |
1220
|
|
|
|
|
|
|
} |
1221
|
11
|
50
|
|
|
|
|
if( isView && pTable->pSelect==0 ){ |
|
|
0
|
|
|
|
|
|
1222
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "use DROP TABLE to delete table %s", pTable->zName); |
1223
|
0
|
|
|
|
|
|
return; |
1224
|
|
|
|
|
|
|
} |
1225
|
11
|
50
|
|
|
|
|
if( !isView && pTable->pSelect ){ |
|
|
50
|
|
|
|
|
|
1226
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "use DROP VIEW to delete view %s", pTable->zName); |
1227
|
0
|
|
|
|
|
|
return; |
1228
|
|
|
|
|
|
|
} |
1229
|
|
|
|
|
|
|
|
1230
|
|
|
|
|
|
|
/* Generate code to remove the table from the master table |
1231
|
|
|
|
|
|
|
** on disk. |
1232
|
|
|
|
|
|
|
*/ |
1233
|
11
|
|
|
|
|
|
v = sqliteGetVdbe(pParse); |
1234
|
11
|
50
|
|
|
|
|
if( v ){ |
1235
|
|
|
|
|
|
|
static VdbeOpList dropTable[] = { |
1236
|
|
|
|
|
|
|
{ OP_Rewind, 0, ADDR(8), 0}, |
1237
|
|
|
|
|
|
|
{ OP_String, 0, 0, 0}, /* 1 */ |
1238
|
|
|
|
|
|
|
{ OP_MemStore, 1, 1, 0}, |
1239
|
|
|
|
|
|
|
{ OP_MemLoad, 1, 0, 0}, /* 3 */ |
1240
|
|
|
|
|
|
|
{ OP_Column, 0, 2, 0}, |
1241
|
|
|
|
|
|
|
{ OP_Ne, 0, ADDR(7), 0}, |
1242
|
|
|
|
|
|
|
{ OP_Delete, 0, 0, 0}, |
1243
|
|
|
|
|
|
|
{ OP_Next, 0, ADDR(3), 0}, /* 7 */ |
1244
|
|
|
|
|
|
|
}; |
1245
|
|
|
|
|
|
|
Index *pIdx; |
1246
|
|
|
|
|
|
|
Trigger *pTrigger; |
1247
|
11
|
|
|
|
|
|
sqliteBeginWriteOperation(pParse, 0, pTable->iDb); |
1248
|
|
|
|
|
|
|
|
1249
|
|
|
|
|
|
|
/* Drop all triggers associated with the table being dropped */ |
1250
|
11
|
|
|
|
|
|
pTrigger = pTable->pTrigger; |
1251
|
11
|
50
|
|
|
|
|
while( pTrigger ){ |
1252
|
|
|
|
|
|
|
assert( pTrigger->iDb==pTable->iDb || pTrigger->iDb==1 ); |
1253
|
0
|
|
|
|
|
|
sqliteDropTriggerPtr(pParse, pTrigger, 1); |
1254
|
0
|
0
|
|
|
|
|
if( pParse->explain ){ |
1255
|
0
|
|
|
|
|
|
pTrigger = pTrigger->pNext; |
1256
|
|
|
|
|
|
|
}else{ |
1257
|
0
|
|
|
|
|
|
pTrigger = pTable->pTrigger; |
1258
|
|
|
|
|
|
|
} |
1259
|
|
|
|
|
|
|
} |
1260
|
|
|
|
|
|
|
|
1261
|
|
|
|
|
|
|
/* Drop all SQLITE_MASTER entries that refer to the table */ |
1262
|
11
|
|
|
|
|
|
sqliteOpenMasterTable(v, pTable->iDb); |
1263
|
11
|
|
|
|
|
|
base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable); |
1264
|
11
|
|
|
|
|
|
sqliteVdbeChangeP3(v, base+1, pTable->zName, 0); |
1265
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
/* Drop all SQLITE_TEMP_MASTER entries that refer to the table */ |
1267
|
11
|
50
|
|
|
|
|
if( pTable->iDb!=1 ){ |
1268
|
11
|
|
|
|
|
|
sqliteOpenMasterTable(v, 1); |
1269
|
11
|
|
|
|
|
|
base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable); |
1270
|
11
|
|
|
|
|
|
sqliteVdbeChangeP3(v, base+1, pTable->zName, 0); |
1271
|
|
|
|
|
|
|
} |
1272
|
|
|
|
|
|
|
|
1273
|
11
|
50
|
|
|
|
|
if( pTable->iDb==0 ){ |
1274
|
11
|
|
|
|
|
|
sqliteChangeCookie(db, v); |
1275
|
|
|
|
|
|
|
} |
1276
|
11
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Close, 0, 0); |
1277
|
11
|
50
|
|
|
|
|
if( !isView ){ |
1278
|
11
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->iDb); |
1279
|
11
|
50
|
|
|
|
|
for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){ |
1280
|
0
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb); |
1281
|
|
|
|
|
|
|
} |
1282
|
|
|
|
|
|
|
} |
1283
|
11
|
|
|
|
|
|
sqliteEndWriteOperation(pParse); |
1284
|
|
|
|
|
|
|
} |
1285
|
|
|
|
|
|
|
|
1286
|
|
|
|
|
|
|
/* Delete the in-memory description of the table. |
1287
|
|
|
|
|
|
|
** |
1288
|
|
|
|
|
|
|
** Exception: if the SQL statement began with the EXPLAIN keyword, |
1289
|
|
|
|
|
|
|
** then no changes should be made. |
1290
|
|
|
|
|
|
|
*/ |
1291
|
11
|
50
|
|
|
|
|
if( !pParse->explain ){ |
1292
|
11
|
|
|
|
|
|
sqliteUnlinkAndDeleteTable(db, pTable); |
1293
|
11
|
|
|
|
|
|
db->flags |= SQLITE_InternChanges; |
1294
|
|
|
|
|
|
|
} |
1295
|
11
|
|
|
|
|
|
sqliteViewResetAll(db, iDb); |
1296
|
|
|
|
|
|
|
} |
1297
|
|
|
|
|
|
|
|
1298
|
|
|
|
|
|
|
/* |
1299
|
|
|
|
|
|
|
** This routine constructs a P3 string suitable for an OP_MakeIdxKey |
1300
|
|
|
|
|
|
|
** opcode and adds that P3 string to the most recently inserted instruction |
1301
|
|
|
|
|
|
|
** in the virtual machine. The P3 string consists of a single character |
1302
|
|
|
|
|
|
|
** for each column in the index pIdx of table pTab. If the column uses |
1303
|
|
|
|
|
|
|
** a numeric sort order, then the P3 string character corresponding to |
1304
|
|
|
|
|
|
|
** that column is 'n'. If the column uses a text sort order, then the |
1305
|
|
|
|
|
|
|
** P3 string is 't'. See the OP_MakeIdxKey opcode documentation for |
1306
|
|
|
|
|
|
|
** additional information. See also the sqliteAddKeyType() routine. |
1307
|
|
|
|
|
|
|
*/ |
1308
|
3
|
|
|
|
|
|
void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){ |
1309
|
|
|
|
|
|
|
char *zType; |
1310
|
|
|
|
|
|
|
Table *pTab; |
1311
|
|
|
|
|
|
|
int i, n; |
1312
|
|
|
|
|
|
|
assert( pIdx!=0 && pIdx->pTable!=0 ); |
1313
|
3
|
|
|
|
|
|
pTab = pIdx->pTable; |
1314
|
3
|
|
|
|
|
|
n = pIdx->nColumn; |
1315
|
3
|
|
|
|
|
|
zType = sqliteMallocRaw( n+1 ); |
1316
|
3
|
50
|
|
|
|
|
if( zType==0 ) return; |
1317
|
7
|
100
|
|
|
|
|
for(i=0; i
|
1318
|
4
|
|
|
|
|
|
int iCol = pIdx->aiColumn[i]; |
1319
|
|
|
|
|
|
|
assert( iCol>=0 && iColnCol ); |
1320
|
4
|
100
|
|
|
|
|
if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){ |
1321
|
2
|
|
|
|
|
|
zType[i] = 't'; |
1322
|
|
|
|
|
|
|
}else{ |
1323
|
2
|
|
|
|
|
|
zType[i] = 'n'; |
1324
|
|
|
|
|
|
|
} |
1325
|
|
|
|
|
|
|
} |
1326
|
3
|
|
|
|
|
|
zType[n] = 0; |
1327
|
3
|
|
|
|
|
|
sqliteVdbeChangeP3(v, -1, zType, n); |
1328
|
3
|
|
|
|
|
|
sqliteFree(zType); |
1329
|
|
|
|
|
|
|
} |
1330
|
|
|
|
|
|
|
|
1331
|
|
|
|
|
|
|
/* |
1332
|
|
|
|
|
|
|
** This routine is called to create a new foreign key on the table |
1333
|
|
|
|
|
|
|
** currently under construction. pFromCol determines which columns |
1334
|
|
|
|
|
|
|
** in the current table point to the foreign key. If pFromCol==0 then |
1335
|
|
|
|
|
|
|
** connect the key to the last column inserted. pTo is the name of |
1336
|
|
|
|
|
|
|
** the table referred to. pToCol is a list of tables in the other |
1337
|
|
|
|
|
|
|
** pTo table that the foreign key points to. flags contains all |
1338
|
|
|
|
|
|
|
** information about the conflict resolution algorithms specified |
1339
|
|
|
|
|
|
|
** in the ON DELETE, ON UPDATE and ON INSERT clauses. |
1340
|
|
|
|
|
|
|
** |
1341
|
|
|
|
|
|
|
** An FKey structure is created and added to the table currently |
1342
|
|
|
|
|
|
|
** under construction in the pParse->pNewTable field. The new FKey |
1343
|
|
|
|
|
|
|
** is not linked into db->aFKey at this point - that does not happen |
1344
|
|
|
|
|
|
|
** until sqliteEndTable(). |
1345
|
|
|
|
|
|
|
** |
1346
|
|
|
|
|
|
|
** The foreign key is set for IMMEDIATE processing. A subsequent call |
1347
|
|
|
|
|
|
|
** to sqliteDeferForeignKey() might change this to DEFERRED. |
1348
|
|
|
|
|
|
|
*/ |
1349
|
0
|
|
|
|
|
|
void sqliteCreateForeignKey( |
1350
|
|
|
|
|
|
|
Parse *pParse, /* Parsing context */ |
1351
|
|
|
|
|
|
|
IdList *pFromCol, /* Columns in this table that point to other table */ |
1352
|
|
|
|
|
|
|
Token *pTo, /* Name of the other table */ |
1353
|
|
|
|
|
|
|
IdList *pToCol, /* Columns in the other table */ |
1354
|
|
|
|
|
|
|
int flags /* Conflict resolution algorithms. */ |
1355
|
|
|
|
|
|
|
){ |
1356
|
0
|
|
|
|
|
|
Table *p = pParse->pNewTable; |
1357
|
|
|
|
|
|
|
int nByte; |
1358
|
|
|
|
|
|
|
int i; |
1359
|
|
|
|
|
|
|
int nCol; |
1360
|
|
|
|
|
|
|
char *z; |
1361
|
0
|
|
|
|
|
|
FKey *pFKey = 0; |
1362
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
assert( pTo!=0 ); |
1364
|
0
|
0
|
|
|
|
|
if( p==0 || pParse->nErr ) goto fk_end; |
|
|
0
|
|
|
|
|
|
1365
|
0
|
0
|
|
|
|
|
if( pFromCol==0 ){ |
1366
|
0
|
|
|
|
|
|
int iCol = p->nCol-1; |
1367
|
0
|
0
|
|
|
|
|
if( iCol<0 ) goto fk_end; |
1368
|
0
|
0
|
|
|
|
|
if( pToCol && pToCol->nId!=1 ){ |
|
|
0
|
|
|
|
|
|
1369
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "foreign key on %s" |
1370
|
|
|
|
|
|
|
" should reference only one column of table %T", |
1371
|
0
|
|
|
|
|
|
p->aCol[iCol].zName, pTo); |
1372
|
0
|
|
|
|
|
|
goto fk_end; |
1373
|
|
|
|
|
|
|
} |
1374
|
0
|
|
|
|
|
|
nCol = 1; |
1375
|
0
|
0
|
|
|
|
|
}else if( pToCol && pToCol->nId!=pFromCol->nId ){ |
|
|
0
|
|
|
|
|
|
1376
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, |
1377
|
|
|
|
|
|
|
"number of columns in foreign key does not match the number of " |
1378
|
|
|
|
|
|
|
"columns in the referenced table"); |
1379
|
0
|
|
|
|
|
|
goto fk_end; |
1380
|
|
|
|
|
|
|
}else{ |
1381
|
0
|
|
|
|
|
|
nCol = pFromCol->nId; |
1382
|
|
|
|
|
|
|
} |
1383
|
0
|
|
|
|
|
|
nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1; |
1384
|
0
|
0
|
|
|
|
|
if( pToCol ){ |
1385
|
0
|
0
|
|
|
|
|
for(i=0; inId; i++){ |
1386
|
0
|
|
|
|
|
|
nByte += strlen(pToCol->a[i].zName) + 1; |
1387
|
|
|
|
|
|
|
} |
1388
|
|
|
|
|
|
|
} |
1389
|
0
|
|
|
|
|
|
pFKey = sqliteMalloc( nByte ); |
1390
|
0
|
0
|
|
|
|
|
if( pFKey==0 ) goto fk_end; |
1391
|
0
|
|
|
|
|
|
pFKey->pFrom = p; |
1392
|
0
|
|
|
|
|
|
pFKey->pNextFrom = p->pFKey; |
1393
|
0
|
|
|
|
|
|
z = (char*)&pFKey[1]; |
1394
|
0
|
|
|
|
|
|
pFKey->aCol = (struct sColMap*)z; |
1395
|
0
|
|
|
|
|
|
z += sizeof(struct sColMap)*nCol; |
1396
|
0
|
|
|
|
|
|
pFKey->zTo = z; |
1397
|
0
|
|
|
|
|
|
memcpy(z, pTo->z, pTo->n); |
1398
|
0
|
|
|
|
|
|
z[pTo->n] = 0; |
1399
|
0
|
|
|
|
|
|
z += pTo->n+1; |
1400
|
0
|
|
|
|
|
|
pFKey->pNextTo = 0; |
1401
|
0
|
|
|
|
|
|
pFKey->nCol = nCol; |
1402
|
0
|
0
|
|
|
|
|
if( pFromCol==0 ){ |
1403
|
0
|
|
|
|
|
|
pFKey->aCol[0].iFrom = p->nCol-1; |
1404
|
|
|
|
|
|
|
}else{ |
1405
|
0
|
0
|
|
|
|
|
for(i=0; i
|
1406
|
|
|
|
|
|
|
int j; |
1407
|
0
|
0
|
|
|
|
|
for(j=0; jnCol; j++){ |
1408
|
0
|
0
|
|
|
|
|
if( sqliteStrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){ |
1409
|
0
|
|
|
|
|
|
pFKey->aCol[i].iFrom = j; |
1410
|
0
|
|
|
|
|
|
break; |
1411
|
|
|
|
|
|
|
} |
1412
|
|
|
|
|
|
|
} |
1413
|
0
|
0
|
|
|
|
|
if( j>=p->nCol ){ |
1414
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, |
1415
|
|
|
|
|
|
|
"unknown column \"%s\" in foreign key definition", |
1416
|
0
|
|
|
|
|
|
pFromCol->a[i].zName); |
1417
|
0
|
|
|
|
|
|
goto fk_end; |
1418
|
|
|
|
|
|
|
} |
1419
|
|
|
|
|
|
|
} |
1420
|
|
|
|
|
|
|
} |
1421
|
0
|
0
|
|
|
|
|
if( pToCol ){ |
1422
|
0
|
0
|
|
|
|
|
for(i=0; i
|
1423
|
0
|
|
|
|
|
|
int n = strlen(pToCol->a[i].zName); |
1424
|
0
|
|
|
|
|
|
pFKey->aCol[i].zCol = z; |
1425
|
0
|
|
|
|
|
|
memcpy(z, pToCol->a[i].zName, n); |
1426
|
0
|
|
|
|
|
|
z[n] = 0; |
1427
|
0
|
|
|
|
|
|
z += n+1; |
1428
|
|
|
|
|
|
|
} |
1429
|
|
|
|
|
|
|
} |
1430
|
0
|
|
|
|
|
|
pFKey->isDeferred = 0; |
1431
|
0
|
|
|
|
|
|
pFKey->deleteConf = flags & 0xff; |
1432
|
0
|
|
|
|
|
|
pFKey->updateConf = (flags >> 8 ) & 0xff; |
1433
|
0
|
|
|
|
|
|
pFKey->insertConf = (flags >> 16 ) & 0xff; |
1434
|
|
|
|
|
|
|
|
1435
|
|
|
|
|
|
|
/* Link the foreign key to the table as the last step. |
1436
|
|
|
|
|
|
|
*/ |
1437
|
0
|
|
|
|
|
|
p->pFKey = pFKey; |
1438
|
0
|
|
|
|
|
|
pFKey = 0; |
1439
|
|
|
|
|
|
|
|
1440
|
|
|
|
|
|
|
fk_end: |
1441
|
0
|
|
|
|
|
|
sqliteFree(pFKey); |
1442
|
0
|
|
|
|
|
|
sqliteIdListDelete(pFromCol); |
1443
|
0
|
|
|
|
|
|
sqliteIdListDelete(pToCol); |
1444
|
0
|
|
|
|
|
|
} |
1445
|
|
|
|
|
|
|
|
1446
|
|
|
|
|
|
|
/* |
1447
|
|
|
|
|
|
|
** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED |
1448
|
|
|
|
|
|
|
** clause is seen as part of a foreign key definition. The isDeferred |
1449
|
|
|
|
|
|
|
** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE. |
1450
|
|
|
|
|
|
|
** The behavior of the most recently created foreign key is adjusted |
1451
|
|
|
|
|
|
|
** accordingly. |
1452
|
|
|
|
|
|
|
*/ |
1453
|
0
|
|
|
|
|
|
void sqliteDeferForeignKey(Parse *pParse, int isDeferred){ |
1454
|
|
|
|
|
|
|
Table *pTab; |
1455
|
|
|
|
|
|
|
FKey *pFKey; |
1456
|
0
|
0
|
|
|
|
|
if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return; |
|
|
0
|
|
|
|
|
|
1457
|
0
|
|
|
|
|
|
pFKey->isDeferred = isDeferred; |
1458
|
|
|
|
|
|
|
} |
1459
|
|
|
|
|
|
|
|
1460
|
|
|
|
|
|
|
/* |
1461
|
|
|
|
|
|
|
** Create a new index for an SQL table. pIndex is the name of the index |
1462
|
|
|
|
|
|
|
** and pTable is the name of the table that is to be indexed. Both will |
1463
|
|
|
|
|
|
|
** be NULL for a primary key or an index that is created to satisfy a |
1464
|
|
|
|
|
|
|
** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable |
1465
|
|
|
|
|
|
|
** as the table to be indexed. pParse->pNewTable is a table that is |
1466
|
|
|
|
|
|
|
** currently being constructed by a CREATE TABLE statement. |
1467
|
|
|
|
|
|
|
** |
1468
|
|
|
|
|
|
|
** pList is a list of columns to be indexed. pList will be NULL if this |
1469
|
|
|
|
|
|
|
** is a primary key or unique-constraint on the most recent column added |
1470
|
|
|
|
|
|
|
** to the table currently under construction. |
1471
|
|
|
|
|
|
|
*/ |
1472
|
8
|
|
|
|
|
|
void sqliteCreateIndex( |
1473
|
|
|
|
|
|
|
Parse *pParse, /* All information about this parse */ |
1474
|
|
|
|
|
|
|
Token *pName, /* Name of the index. May be NULL */ |
1475
|
|
|
|
|
|
|
SrcList *pTable, /* Name of the table to index. Use pParse->pNewTable if 0 */ |
1476
|
|
|
|
|
|
|
IdList *pList, /* A list of columns to be indexed */ |
1477
|
|
|
|
|
|
|
int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ |
1478
|
|
|
|
|
|
|
Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */ |
1479
|
|
|
|
|
|
|
Token *pEnd /* The ")" that closes the CREATE INDEX statement */ |
1480
|
|
|
|
|
|
|
){ |
1481
|
|
|
|
|
|
|
Table *pTab; /* Table to be indexed */ |
1482
|
|
|
|
|
|
|
Index *pIndex; /* The index to be created */ |
1483
|
8
|
|
|
|
|
|
char *zName = 0; |
1484
|
|
|
|
|
|
|
int i, j; |
1485
|
|
|
|
|
|
|
Token nullId; /* Fake token for an empty ID list */ |
1486
|
|
|
|
|
|
|
DbFixer sFix; /* For assigning database names to pTable */ |
1487
|
|
|
|
|
|
|
int isTemp; /* True for a temporary index */ |
1488
|
8
|
|
|
|
|
|
sqlite *db = pParse->db; |
1489
|
|
|
|
|
|
|
|
1490
|
8
|
50
|
|
|
|
|
if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index; |
|
|
50
|
|
|
|
|
|
1491
|
8
|
100
|
|
|
|
|
if( db->init.busy |
1492
|
3
|
50
|
|
|
|
|
&& sqliteFixInit(&sFix, pParse, db->init.iDb, "index", pName) |
1493
|
3
|
50
|
|
|
|
|
&& sqliteFixSrcList(&sFix, pTable) |
1494
|
|
|
|
|
|
|
){ |
1495
|
0
|
|
|
|
|
|
goto exit_create_index; |
1496
|
|
|
|
|
|
|
} |
1497
|
|
|
|
|
|
|
|
1498
|
|
|
|
|
|
|
/* |
1499
|
|
|
|
|
|
|
** Find the table that is to be indexed. Return early if not found. |
1500
|
|
|
|
|
|
|
*/ |
1501
|
8
|
100
|
|
|
|
|
if( pTable!=0 ){ |
1502
|
|
|
|
|
|
|
assert( pName!=0 ); |
1503
|
|
|
|
|
|
|
assert( pTable->nSrc==1 ); |
1504
|
4
|
|
|
|
|
|
pTab = sqliteSrcListLookup(pParse, pTable); |
1505
|
|
|
|
|
|
|
}else{ |
1506
|
|
|
|
|
|
|
assert( pName==0 ); |
1507
|
4
|
|
|
|
|
|
pTab = pParse->pNewTable; |
1508
|
|
|
|
|
|
|
} |
1509
|
8
|
50
|
|
|
|
|
if( pTab==0 || pParse->nErr ) goto exit_create_index; |
|
|
50
|
|
|
|
|
|
1510
|
8
|
50
|
|
|
|
|
if( pTab->readOnly ){ |
1511
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "table %s may not be indexed", pTab->zName); |
1512
|
0
|
|
|
|
|
|
goto exit_create_index; |
1513
|
|
|
|
|
|
|
} |
1514
|
8
|
50
|
|
|
|
|
if( pTab->iDb>=2 && db->init.busy==0 ){ |
|
|
0
|
|
|
|
|
|
1515
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "table %s may not have indices added", pTab->zName); |
1516
|
0
|
|
|
|
|
|
goto exit_create_index; |
1517
|
|
|
|
|
|
|
} |
1518
|
8
|
50
|
|
|
|
|
if( pTab->pSelect ){ |
1519
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "views may not be indexed"); |
1520
|
0
|
|
|
|
|
|
goto exit_create_index; |
1521
|
|
|
|
|
|
|
} |
1522
|
8
|
|
|
|
|
|
isTemp = pTab->iDb==1; |
1523
|
|
|
|
|
|
|
|
1524
|
|
|
|
|
|
|
/* |
1525
|
|
|
|
|
|
|
** Find the name of the index. Make sure there is not already another |
1526
|
|
|
|
|
|
|
** index or table with the same name. |
1527
|
|
|
|
|
|
|
** |
1528
|
|
|
|
|
|
|
** Exception: If we are reading the names of permanent indices from the |
1529
|
|
|
|
|
|
|
** sqlite_master table (because some other process changed the schema) and |
1530
|
|
|
|
|
|
|
** one of the index names collides with the name of a temporary table or |
1531
|
|
|
|
|
|
|
** index, then we will continue to process this index. |
1532
|
|
|
|
|
|
|
** |
1533
|
|
|
|
|
|
|
** If pName==0 it means that we are |
1534
|
|
|
|
|
|
|
** dealing with a primary key or UNIQUE constraint. We have to invent our |
1535
|
|
|
|
|
|
|
** own name. |
1536
|
|
|
|
|
|
|
*/ |
1537
|
9
|
100
|
|
|
|
|
if( pName && !db->init.busy ){ |
|
|
100
|
|
|
|
|
|
1538
|
|
|
|
|
|
|
Index *pISameName; /* Another index with the same name */ |
1539
|
|
|
|
|
|
|
Table *pTSameName; /* A table with same name as the index */ |
1540
|
1
|
|
|
|
|
|
zName = sqliteTableNameFromToken(pName); |
1541
|
1
|
50
|
|
|
|
|
if( zName==0 ) goto exit_create_index; |
1542
|
1
|
50
|
|
|
|
|
if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){ |
1543
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "index %s already exists", zName); |
1544
|
0
|
|
|
|
|
|
goto exit_create_index; |
1545
|
|
|
|
|
|
|
} |
1546
|
1
|
50
|
|
|
|
|
if( (pTSameName = sqliteFindTable(db, zName, 0))!=0 ){ |
1547
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "there is already a table named %s", zName); |
1548
|
0
|
|
|
|
|
|
goto exit_create_index; |
1549
|
|
|
|
|
|
|
} |
1550
|
7
|
100
|
|
|
|
|
}else if( pName==0 ){ |
1551
|
|
|
|
|
|
|
char zBuf[30]; |
1552
|
|
|
|
|
|
|
int n; |
1553
|
|
|
|
|
|
|
Index *pLoop; |
1554
|
4
|
50
|
|
|
|
|
for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){} |
1555
|
4
|
|
|
|
|
|
sprintf(zBuf,"%d)",n); |
1556
|
4
|
|
|
|
|
|
zName = 0; |
1557
|
4
|
|
|
|
|
|
sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0); |
1558
|
4
|
50
|
|
|
|
|
if( zName==0 ) goto exit_create_index; |
1559
|
|
|
|
|
|
|
}else{ |
1560
|
3
|
|
|
|
|
|
zName = sqliteStrNDup(pName->z, pName->n); |
1561
|
|
|
|
|
|
|
} |
1562
|
|
|
|
|
|
|
|
1563
|
|
|
|
|
|
|
/* Check for authorization to create an index. |
1564
|
|
|
|
|
|
|
*/ |
1565
|
|
|
|
|
|
|
#ifndef SQLITE_OMIT_AUTHORIZATION |
1566
|
|
|
|
|
|
|
{ |
1567
|
8
|
|
|
|
|
|
const char *zDb = db->aDb[pTab->iDb].zName; |
1568
|
|
|
|
|
|
|
|
1569
|
|
|
|
|
|
|
assert( pTab->iDb==db->init.iDb || isTemp ); |
1570
|
8
|
50
|
|
|
|
|
if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ |
|
|
50
|
|
|
|
|
|
1571
|
0
|
|
|
|
|
|
goto exit_create_index; |
1572
|
|
|
|
|
|
|
} |
1573
|
8
|
|
|
|
|
|
i = SQLITE_CREATE_INDEX; |
1574
|
8
|
50
|
|
|
|
|
if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX; |
1575
|
8
|
50
|
|
|
|
|
if( sqliteAuthCheck(pParse, i, zName, pTab->zName, zDb) ){ |
1576
|
0
|
|
|
|
|
|
goto exit_create_index; |
1577
|
|
|
|
|
|
|
} |
1578
|
|
|
|
|
|
|
} |
1579
|
|
|
|
|
|
|
#endif |
1580
|
|
|
|
|
|
|
|
1581
|
|
|
|
|
|
|
/* If pList==0, it means this routine was called to make a primary |
1582
|
|
|
|
|
|
|
** key out of the last column added to the table under construction. |
1583
|
|
|
|
|
|
|
** So create a fake list to simulate this. |
1584
|
|
|
|
|
|
|
*/ |
1585
|
8
|
100
|
|
|
|
|
if( pList==0 ){ |
1586
|
2
|
|
|
|
|
|
nullId.z = pTab->aCol[pTab->nCol-1].zName; |
1587
|
2
|
|
|
|
|
|
nullId.n = strlen(nullId.z); |
1588
|
2
|
|
|
|
|
|
pList = sqliteIdListAppend(0, &nullId); |
1589
|
2
|
50
|
|
|
|
|
if( pList==0 ) goto exit_create_index; |
1590
|
|
|
|
|
|
|
} |
1591
|
|
|
|
|
|
|
|
1592
|
|
|
|
|
|
|
/* |
1593
|
|
|
|
|
|
|
** Allocate the index structure. |
1594
|
|
|
|
|
|
|
*/ |
1595
|
8
|
|
|
|
|
|
pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 + |
1596
|
8
|
|
|
|
|
|
sizeof(int)*pList->nId ); |
1597
|
8
|
50
|
|
|
|
|
if( pIndex==0 ) goto exit_create_index; |
1598
|
8
|
|
|
|
|
|
pIndex->aiColumn = (int*)&pIndex[1]; |
1599
|
8
|
|
|
|
|
|
pIndex->zName = (char*)&pIndex->aiColumn[pList->nId]; |
1600
|
8
|
|
|
|
|
|
strcpy(pIndex->zName, zName); |
1601
|
8
|
|
|
|
|
|
pIndex->pTable = pTab; |
1602
|
8
|
|
|
|
|
|
pIndex->nColumn = pList->nId; |
1603
|
8
|
|
|
|
|
|
pIndex->onError = onError; |
1604
|
8
|
|
|
|
|
|
pIndex->autoIndex = pName==0; |
1605
|
8
|
50
|
|
|
|
|
pIndex->iDb = isTemp ? 1 : db->init.iDb; |
1606
|
|
|
|
|
|
|
|
1607
|
|
|
|
|
|
|
/* Scan the names of the columns of the table to be indexed and |
1608
|
|
|
|
|
|
|
** load the column indices into the Index structure. Report an error |
1609
|
|
|
|
|
|
|
** if any column is not found. |
1610
|
|
|
|
|
|
|
*/ |
1611
|
17
|
100
|
|
|
|
|
for(i=0; inId; i++){ |
1612
|
11
|
50
|
|
|
|
|
for(j=0; jnCol; j++){ |
1613
|
11
|
100
|
|
|
|
|
if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break; |
1614
|
|
|
|
|
|
|
} |
1615
|
9
|
50
|
|
|
|
|
if( j>=pTab->nCol ){ |
1616
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "table %s has no column named %s", |
1617
|
0
|
|
|
|
|
|
pTab->zName, pList->a[i].zName); |
1618
|
0
|
|
|
|
|
|
sqliteFree(pIndex); |
1619
|
0
|
|
|
|
|
|
goto exit_create_index; |
1620
|
|
|
|
|
|
|
} |
1621
|
9
|
|
|
|
|
|
pIndex->aiColumn[i] = j; |
1622
|
|
|
|
|
|
|
} |
1623
|
|
|
|
|
|
|
|
1624
|
|
|
|
|
|
|
/* Link the new Index structure to its table and to the other |
1625
|
|
|
|
|
|
|
** in-memory database structures. |
1626
|
|
|
|
|
|
|
*/ |
1627
|
8
|
50
|
|
|
|
|
if( !pParse->explain ){ |
1628
|
|
|
|
|
|
|
Index *p; |
1629
|
8
|
|
|
|
|
|
p = sqliteHashInsert(&db->aDb[pIndex->iDb].idxHash, |
1630
|
16
|
|
|
|
|
|
pIndex->zName, strlen(pIndex->zName)+1, pIndex); |
1631
|
8
|
50
|
|
|
|
|
if( p ){ |
1632
|
|
|
|
|
|
|
assert( p==pIndex ); /* Malloc must have failed */ |
1633
|
0
|
|
|
|
|
|
sqliteFree(pIndex); |
1634
|
0
|
|
|
|
|
|
goto exit_create_index; |
1635
|
|
|
|
|
|
|
} |
1636
|
8
|
|
|
|
|
|
db->flags |= SQLITE_InternChanges; |
1637
|
|
|
|
|
|
|
} |
1638
|
|
|
|
|
|
|
|
1639
|
|
|
|
|
|
|
/* When adding an index to the list of indices for a table, make |
1640
|
|
|
|
|
|
|
** sure all indices labeled OE_Replace come after all those labeled |
1641
|
|
|
|
|
|
|
** OE_Ignore. This is necessary for the correct operation of UPDATE |
1642
|
|
|
|
|
|
|
** and INSERT. |
1643
|
|
|
|
|
|
|
*/ |
1644
|
8
|
50
|
|
|
|
|
if( onError!=OE_Replace || pTab->pIndex==0 |
|
|
0
|
|
|
|
|
|
1645
|
0
|
0
|
|
|
|
|
|| pTab->pIndex->onError==OE_Replace){ |
1646
|
8
|
|
|
|
|
|
pIndex->pNext = pTab->pIndex; |
1647
|
8
|
|
|
|
|
|
pTab->pIndex = pIndex; |
1648
|
|
|
|
|
|
|
}else{ |
1649
|
0
|
|
|
|
|
|
Index *pOther = pTab->pIndex; |
1650
|
0
|
0
|
|
|
|
|
while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){ |
|
|
0
|
|
|
|
|
|
1651
|
0
|
|
|
|
|
|
pOther = pOther->pNext; |
1652
|
|
|
|
|
|
|
} |
1653
|
0
|
|
|
|
|
|
pIndex->pNext = pOther->pNext; |
1654
|
0
|
|
|
|
|
|
pOther->pNext = pIndex; |
1655
|
|
|
|
|
|
|
} |
1656
|
|
|
|
|
|
|
|
1657
|
|
|
|
|
|
|
/* If the db->init.busy is 1 it means we are reading the SQL off the |
1658
|
|
|
|
|
|
|
** "sqlite_master" table on the disk. So do not write to the disk |
1659
|
|
|
|
|
|
|
** again. Extract the table number from the db->init.newTnum field. |
1660
|
|
|
|
|
|
|
*/ |
1661
|
8
|
100
|
|
|
|
|
if( db->init.busy && pTable!=0 ){ |
|
|
50
|
|
|
|
|
|
1662
|
3
|
|
|
|
|
|
pIndex->tnum = db->init.newTnum; |
1663
|
|
|
|
|
|
|
} |
1664
|
|
|
|
|
|
|
|
1665
|
|
|
|
|
|
|
/* If the db->init.busy is 0 then create the index on disk. This |
1666
|
|
|
|
|
|
|
** involves writing the index into the master table and filling in the |
1667
|
|
|
|
|
|
|
** index with the current table contents. |
1668
|
|
|
|
|
|
|
** |
1669
|
|
|
|
|
|
|
** The db->init.busy is 0 when the user first enters a CREATE INDEX |
1670
|
|
|
|
|
|
|
** command. db->init.busy is 1 when a database is opened and |
1671
|
|
|
|
|
|
|
** CREATE INDEX statements are read out of the master table. In |
1672
|
|
|
|
|
|
|
** the latter case the index already exists on disk, which is why |
1673
|
|
|
|
|
|
|
** we don't want to recreate it. |
1674
|
|
|
|
|
|
|
** |
1675
|
|
|
|
|
|
|
** If pTable==0 it means this index is generated as a primary key |
1676
|
|
|
|
|
|
|
** or UNIQUE constraint of a CREATE TABLE statement. Since the table |
1677
|
|
|
|
|
|
|
** has just been created, it contains no data and the index initialization |
1678
|
|
|
|
|
|
|
** step can be skipped. |
1679
|
|
|
|
|
|
|
*/ |
1680
|
5
|
50
|
|
|
|
|
else if( db->init.busy==0 ){ |
1681
|
|
|
|
|
|
|
int n; |
1682
|
|
|
|
|
|
|
Vdbe *v; |
1683
|
|
|
|
|
|
|
int lbl1, lbl2; |
1684
|
|
|
|
|
|
|
int i; |
1685
|
|
|
|
|
|
|
int addr; |
1686
|
|
|
|
|
|
|
|
1687
|
5
|
|
|
|
|
|
v = sqliteGetVdbe(pParse); |
1688
|
5
|
50
|
|
|
|
|
if( v==0 ) goto exit_create_index; |
1689
|
5
|
100
|
|
|
|
|
if( pTable!=0 ){ |
1690
|
1
|
|
|
|
|
|
sqliteBeginWriteOperation(pParse, 0, isTemp); |
1691
|
1
|
|
|
|
|
|
sqliteOpenMasterTable(v, isTemp); |
1692
|
|
|
|
|
|
|
} |
1693
|
5
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_NewRecno, 0, 0); |
1694
|
5
|
|
|
|
|
|
sqliteVdbeOp3(v, OP_String, 0, 0, "index", P3_STATIC); |
1695
|
5
|
|
|
|
|
|
sqliteVdbeOp3(v, OP_String, 0, 0, pIndex->zName, 0); |
1696
|
5
|
|
|
|
|
|
sqliteVdbeOp3(v, OP_String, 0, 0, pTab->zName, 0); |
1697
|
5
|
|
|
|
|
|
sqliteVdbeOp3(v, OP_CreateIndex, 0, isTemp,(char*)&pIndex->tnum,P3_POINTER); |
1698
|
5
|
|
|
|
|
|
pIndex->tnum = 0; |
1699
|
5
|
100
|
|
|
|
|
if( pTable ){ |
1700
|
1
|
|
|
|
|
|
sqliteVdbeCode(v, |
1701
|
|
|
|
|
|
|
OP_Dup, 0, 0, |
1702
|
|
|
|
|
|
|
OP_Integer, isTemp, 0, |
1703
|
|
|
|
|
|
|
OP_OpenWrite, 1, 0, |
1704
|
|
|
|
|
|
|
0); |
1705
|
|
|
|
|
|
|
} |
1706
|
5
|
|
|
|
|
|
addr = sqliteVdbeAddOp(v, OP_String, 0, 0); |
1707
|
5
|
100
|
|
|
|
|
if( pStart && pEnd ){ |
|
|
50
|
|
|
|
|
|
1708
|
1
|
|
|
|
|
|
n = Addr(pEnd->z) - Addr(pStart->z) + 1; |
1709
|
1
|
|
|
|
|
|
sqliteVdbeChangeP3(v, addr, pStart->z, n); |
1710
|
|
|
|
|
|
|
} |
1711
|
5
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); |
1712
|
5
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); |
1713
|
5
|
100
|
|
|
|
|
if( pTable ){ |
1714
|
1
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); |
1715
|
1
|
|
|
|
|
|
sqliteVdbeOp3(v, OP_OpenRead, 2, pTab->tnum, pTab->zName, 0); |
1716
|
1
|
|
|
|
|
|
lbl2 = sqliteVdbeMakeLabel(v); |
1717
|
1
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2); |
1718
|
1
|
|
|
|
|
|
lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0); |
1719
|
2
|
100
|
|
|
|
|
for(i=0; inColumn; i++){ |
1720
|
1
|
|
|
|
|
|
int iCol = pIndex->aiColumn[i]; |
1721
|
1
|
50
|
|
|
|
|
if( pTab->iPKey==iCol ){ |
1722
|
0
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Dup, i, 0); |
1723
|
|
|
|
|
|
|
}else{ |
1724
|
1
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Column, 2, iCol); |
1725
|
|
|
|
|
|
|
} |
1726
|
|
|
|
|
|
|
} |
1727
|
1
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0); |
1728
|
1
|
50
|
|
|
|
|
if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIndex); |
1729
|
1
|
|
|
|
|
|
sqliteVdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None, |
1730
|
|
|
|
|
|
|
"indexed columns are not unique", P3_STATIC); |
1731
|
1
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Next, 2, lbl1); |
1732
|
1
|
|
|
|
|
|
sqliteVdbeResolveLabel(v, lbl2); |
1733
|
1
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Close, 2, 0); |
1734
|
1
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Close, 1, 0); |
1735
|
|
|
|
|
|
|
} |
1736
|
5
|
100
|
|
|
|
|
if( pTable!=0 ){ |
1737
|
1
|
50
|
|
|
|
|
if( !isTemp ){ |
1738
|
1
|
|
|
|
|
|
sqliteChangeCookie(db, v); |
1739
|
|
|
|
|
|
|
} |
1740
|
1
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Close, 0, 0); |
1741
|
1
|
|
|
|
|
|
sqliteEndWriteOperation(pParse); |
1742
|
|
|
|
|
|
|
} |
1743
|
|
|
|
|
|
|
} |
1744
|
|
|
|
|
|
|
|
1745
|
|
|
|
|
|
|
/* Clean up before exiting */ |
1746
|
|
|
|
|
|
|
exit_create_index: |
1747
|
8
|
|
|
|
|
|
sqliteIdListDelete(pList); |
1748
|
8
|
|
|
|
|
|
sqliteSrcListDelete(pTable); |
1749
|
8
|
|
|
|
|
|
sqliteFree(zName); |
1750
|
8
|
|
|
|
|
|
return; |
1751
|
|
|
|
|
|
|
} |
1752
|
|
|
|
|
|
|
|
1753
|
|
|
|
|
|
|
/* |
1754
|
|
|
|
|
|
|
** This routine will drop an existing named index. This routine |
1755
|
|
|
|
|
|
|
** implements the DROP INDEX statement. |
1756
|
|
|
|
|
|
|
*/ |
1757
|
0
|
|
|
|
|
|
void sqliteDropIndex(Parse *pParse, SrcList *pName){ |
1758
|
|
|
|
|
|
|
Index *pIndex; |
1759
|
|
|
|
|
|
|
Vdbe *v; |
1760
|
0
|
|
|
|
|
|
sqlite *db = pParse->db; |
1761
|
|
|
|
|
|
|
|
1762
|
0
|
0
|
|
|
|
|
if( pParse->nErr || sqlite_malloc_failed ) return; |
|
|
0
|
|
|
|
|
|
1763
|
|
|
|
|
|
|
assert( pName->nSrc==1 ); |
1764
|
0
|
|
|
|
|
|
pIndex = sqliteFindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); |
1765
|
0
|
0
|
|
|
|
|
if( pIndex==0 ){ |
1766
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "no such index: %S", pName, 0); |
1767
|
0
|
|
|
|
|
|
goto exit_drop_index; |
1768
|
|
|
|
|
|
|
} |
1769
|
0
|
0
|
|
|
|
|
if( pIndex->autoIndex ){ |
1770
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "index associated with UNIQUE " |
1771
|
|
|
|
|
|
|
"or PRIMARY KEY constraint cannot be dropped", 0); |
1772
|
0
|
|
|
|
|
|
goto exit_drop_index; |
1773
|
|
|
|
|
|
|
} |
1774
|
0
|
0
|
|
|
|
|
if( pIndex->iDb>1 ){ |
1775
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "cannot alter schema of attached " |
1776
|
|
|
|
|
|
|
"databases", 0); |
1777
|
0
|
|
|
|
|
|
goto exit_drop_index; |
1778
|
|
|
|
|
|
|
} |
1779
|
|
|
|
|
|
|
#ifndef SQLITE_OMIT_AUTHORIZATION |
1780
|
|
|
|
|
|
|
{ |
1781
|
0
|
|
|
|
|
|
int code = SQLITE_DROP_INDEX; |
1782
|
0
|
|
|
|
|
|
Table *pTab = pIndex->pTable; |
1783
|
0
|
|
|
|
|
|
const char *zDb = db->aDb[pIndex->iDb].zName; |
1784
|
0
|
0
|
|
|
|
|
const char *zTab = SCHEMA_TABLE(pIndex->iDb); |
1785
|
0
|
0
|
|
|
|
|
if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ |
1786
|
0
|
|
|
|
|
|
goto exit_drop_index; |
1787
|
|
|
|
|
|
|
} |
1788
|
0
|
0
|
|
|
|
|
if( pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX; |
1789
|
0
|
0
|
|
|
|
|
if( sqliteAuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ |
1790
|
0
|
|
|
|
|
|
goto exit_drop_index; |
1791
|
|
|
|
|
|
|
} |
1792
|
|
|
|
|
|
|
} |
1793
|
|
|
|
|
|
|
#endif |
1794
|
|
|
|
|
|
|
|
1795
|
|
|
|
|
|
|
/* Generate code to remove the index and from the master table */ |
1796
|
0
|
|
|
|
|
|
v = sqliteGetVdbe(pParse); |
1797
|
0
|
0
|
|
|
|
|
if( v ){ |
1798
|
|
|
|
|
|
|
static VdbeOpList dropIndex[] = { |
1799
|
|
|
|
|
|
|
{ OP_Rewind, 0, ADDR(9), 0}, |
1800
|
|
|
|
|
|
|
{ OP_String, 0, 0, 0}, /* 1 */ |
1801
|
|
|
|
|
|
|
{ OP_MemStore, 1, 1, 0}, |
1802
|
|
|
|
|
|
|
{ OP_MemLoad, 1, 0, 0}, /* 3 */ |
1803
|
|
|
|
|
|
|
{ OP_Column, 0, 1, 0}, |
1804
|
|
|
|
|
|
|
{ OP_Eq, 0, ADDR(8), 0}, |
1805
|
|
|
|
|
|
|
{ OP_Next, 0, ADDR(3), 0}, |
1806
|
|
|
|
|
|
|
{ OP_Goto, 0, ADDR(9), 0}, |
1807
|
|
|
|
|
|
|
{ OP_Delete, 0, 0, 0}, /* 8 */ |
1808
|
|
|
|
|
|
|
}; |
1809
|
|
|
|
|
|
|
int base; |
1810
|
|
|
|
|
|
|
|
1811
|
0
|
|
|
|
|
|
sqliteBeginWriteOperation(pParse, 0, pIndex->iDb); |
1812
|
0
|
|
|
|
|
|
sqliteOpenMasterTable(v, pIndex->iDb); |
1813
|
0
|
|
|
|
|
|
base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex); |
1814
|
0
|
|
|
|
|
|
sqliteVdbeChangeP3(v, base+1, pIndex->zName, 0); |
1815
|
0
|
0
|
|
|
|
|
if( pIndex->iDb==0 ){ |
1816
|
0
|
|
|
|
|
|
sqliteChangeCookie(db, v); |
1817
|
|
|
|
|
|
|
} |
1818
|
0
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Close, 0, 0); |
1819
|
0
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb); |
1820
|
0
|
|
|
|
|
|
sqliteEndWriteOperation(pParse); |
1821
|
|
|
|
|
|
|
} |
1822
|
|
|
|
|
|
|
|
1823
|
|
|
|
|
|
|
/* Delete the in-memory description of this index. |
1824
|
|
|
|
|
|
|
*/ |
1825
|
0
|
0
|
|
|
|
|
if( !pParse->explain ){ |
1826
|
0
|
|
|
|
|
|
sqliteUnlinkAndDeleteIndex(db, pIndex); |
1827
|
0
|
|
|
|
|
|
db->flags |= SQLITE_InternChanges; |
1828
|
|
|
|
|
|
|
} |
1829
|
|
|
|
|
|
|
|
1830
|
|
|
|
|
|
|
exit_drop_index: |
1831
|
0
|
|
|
|
|
|
sqliteSrcListDelete(pName); |
1832
|
|
|
|
|
|
|
} |
1833
|
|
|
|
|
|
|
|
1834
|
|
|
|
|
|
|
/* |
1835
|
|
|
|
|
|
|
** Append a new element to the given IdList. Create a new IdList if |
1836
|
|
|
|
|
|
|
** need be. |
1837
|
|
|
|
|
|
|
** |
1838
|
|
|
|
|
|
|
** A new IdList is returned, or NULL if malloc() fails. |
1839
|
|
|
|
|
|
|
*/ |
1840
|
15
|
|
|
|
|
|
IdList *sqliteIdListAppend(IdList *pList, Token *pToken){ |
1841
|
15
|
100
|
|
|
|
|
if( pList==0 ){ |
1842
|
11
|
|
|
|
|
|
pList = sqliteMalloc( sizeof(IdList) ); |
1843
|
11
|
50
|
|
|
|
|
if( pList==0 ) return 0; |
1844
|
11
|
|
|
|
|
|
pList->nAlloc = 0; |
1845
|
|
|
|
|
|
|
} |
1846
|
15
|
100
|
|
|
|
|
if( pList->nId>=pList->nAlloc ){ |
1847
|
|
|
|
|
|
|
struct IdList_item *a; |
1848
|
11
|
|
|
|
|
|
pList->nAlloc = pList->nAlloc*2 + 5; |
1849
|
11
|
|
|
|
|
|
a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) ); |
1850
|
11
|
50
|
|
|
|
|
if( a==0 ){ |
1851
|
0
|
|
|
|
|
|
sqliteIdListDelete(pList); |
1852
|
0
|
|
|
|
|
|
return 0; |
1853
|
|
|
|
|
|
|
} |
1854
|
11
|
|
|
|
|
|
pList->a = a; |
1855
|
|
|
|
|
|
|
} |
1856
|
15
|
|
|
|
|
|
memset(&pList->a[pList->nId], 0, sizeof(pList->a[0])); |
1857
|
15
|
50
|
|
|
|
|
if( pToken ){ |
1858
|
15
|
|
|
|
|
|
char **pz = &pList->a[pList->nId].zName; |
1859
|
15
|
|
|
|
|
|
sqliteSetNString(pz, pToken->z, pToken->n, 0); |
1860
|
15
|
50
|
|
|
|
|
if( *pz==0 ){ |
1861
|
0
|
|
|
|
|
|
sqliteIdListDelete(pList); |
1862
|
0
|
|
|
|
|
|
return 0; |
1863
|
|
|
|
|
|
|
}else{ |
1864
|
15
|
|
|
|
|
|
sqliteDequote(*pz); |
1865
|
|
|
|
|
|
|
} |
1866
|
|
|
|
|
|
|
} |
1867
|
15
|
|
|
|
|
|
pList->nId++; |
1868
|
15
|
|
|
|
|
|
return pList; |
1869
|
|
|
|
|
|
|
} |
1870
|
|
|
|
|
|
|
|
1871
|
|
|
|
|
|
|
/* |
1872
|
|
|
|
|
|
|
** Append a new table name to the given SrcList. Create a new SrcList if |
1873
|
|
|
|
|
|
|
** need be. A new entry is created in the SrcList even if pToken is NULL. |
1874
|
|
|
|
|
|
|
** |
1875
|
|
|
|
|
|
|
** A new SrcList is returned, or NULL if malloc() fails. |
1876
|
|
|
|
|
|
|
** |
1877
|
|
|
|
|
|
|
** If pDatabase is not null, it means that the table has an optional |
1878
|
|
|
|
|
|
|
** database name prefix. Like this: "database.table". The pDatabase |
1879
|
|
|
|
|
|
|
** points to the table name and the pTable points to the database name. |
1880
|
|
|
|
|
|
|
** The SrcList.a[].zName field is filled with the table name which might |
1881
|
|
|
|
|
|
|
** come from pTable (if pDatabase is NULL) or from pDatabase. |
1882
|
|
|
|
|
|
|
** SrcList.a[].zDatabase is filled with the database name from pTable, |
1883
|
|
|
|
|
|
|
** or with NULL if no database is specified. |
1884
|
|
|
|
|
|
|
** |
1885
|
|
|
|
|
|
|
** In other words, if call like this: |
1886
|
|
|
|
|
|
|
** |
1887
|
|
|
|
|
|
|
** sqliteSrcListAppend(A,B,0); |
1888
|
|
|
|
|
|
|
** |
1889
|
|
|
|
|
|
|
** Then B is a table name and the database name is unspecified. If called |
1890
|
|
|
|
|
|
|
** like this: |
1891
|
|
|
|
|
|
|
** |
1892
|
|
|
|
|
|
|
** sqliteSrcListAppend(A,B,C); |
1893
|
|
|
|
|
|
|
** |
1894
|
|
|
|
|
|
|
** Then C is the table name and B is the database name. |
1895
|
|
|
|
|
|
|
*/ |
1896
|
170
|
|
|
|
|
|
SrcList *sqliteSrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){ |
1897
|
170
|
100
|
|
|
|
|
if( pList==0 ){ |
1898
|
169
|
|
|
|
|
|
pList = sqliteMalloc( sizeof(SrcList) ); |
1899
|
169
|
50
|
|
|
|
|
if( pList==0 ) return 0; |
1900
|
169
|
|
|
|
|
|
pList->nAlloc = 1; |
1901
|
|
|
|
|
|
|
} |
1902
|
170
|
100
|
|
|
|
|
if( pList->nSrc>=pList->nAlloc ){ |
1903
|
|
|
|
|
|
|
SrcList *pNew; |
1904
|
1
|
|
|
|
|
|
pList->nAlloc *= 2; |
1905
|
1
|
|
|
|
|
|
pNew = sqliteRealloc(pList, |
1906
|
1
|
|
|
|
|
|
sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) ); |
1907
|
1
|
50
|
|
|
|
|
if( pNew==0 ){ |
1908
|
0
|
|
|
|
|
|
sqliteSrcListDelete(pList); |
1909
|
0
|
|
|
|
|
|
return 0; |
1910
|
|
|
|
|
|
|
} |
1911
|
1
|
|
|
|
|
|
pList = pNew; |
1912
|
|
|
|
|
|
|
} |
1913
|
170
|
|
|
|
|
|
memset(&pList->a[pList->nSrc], 0, sizeof(pList->a[0])); |
1914
|
170
|
100
|
|
|
|
|
if( pDatabase && pDatabase->z==0 ){ |
|
|
100
|
|
|
|
|
|
1915
|
110
|
|
|
|
|
|
pDatabase = 0; |
1916
|
|
|
|
|
|
|
} |
1917
|
170
|
100
|
|
|
|
|
if( pDatabase && pTable ){ |
|
|
50
|
|
|
|
|
|
1918
|
54
|
|
|
|
|
|
Token *pTemp = pDatabase; |
1919
|
54
|
|
|
|
|
|
pDatabase = pTable; |
1920
|
54
|
|
|
|
|
|
pTable = pTemp; |
1921
|
|
|
|
|
|
|
} |
1922
|
170
|
100
|
|
|
|
|
if( pTable ){ |
1923
|
164
|
|
|
|
|
|
char **pz = &pList->a[pList->nSrc].zName; |
1924
|
164
|
|
|
|
|
|
sqliteSetNString(pz, pTable->z, pTable->n, 0); |
1925
|
164
|
50
|
|
|
|
|
if( *pz==0 ){ |
1926
|
0
|
|
|
|
|
|
sqliteSrcListDelete(pList); |
1927
|
0
|
|
|
|
|
|
return 0; |
1928
|
|
|
|
|
|
|
}else{ |
1929
|
164
|
|
|
|
|
|
sqliteDequote(*pz); |
1930
|
|
|
|
|
|
|
} |
1931
|
|
|
|
|
|
|
} |
1932
|
170
|
100
|
|
|
|
|
if( pDatabase ){ |
1933
|
54
|
|
|
|
|
|
char **pz = &pList->a[pList->nSrc].zDatabase; |
1934
|
54
|
|
|
|
|
|
sqliteSetNString(pz, pDatabase->z, pDatabase->n, 0); |
1935
|
54
|
50
|
|
|
|
|
if( *pz==0 ){ |
1936
|
0
|
|
|
|
|
|
sqliteSrcListDelete(pList); |
1937
|
0
|
|
|
|
|
|
return 0; |
1938
|
|
|
|
|
|
|
}else{ |
1939
|
54
|
|
|
|
|
|
sqliteDequote(*pz); |
1940
|
|
|
|
|
|
|
} |
1941
|
|
|
|
|
|
|
} |
1942
|
170
|
|
|
|
|
|
pList->a[pList->nSrc].iCursor = -1; |
1943
|
170
|
|
|
|
|
|
pList->nSrc++; |
1944
|
170
|
|
|
|
|
|
return pList; |
1945
|
|
|
|
|
|
|
} |
1946
|
|
|
|
|
|
|
|
1947
|
|
|
|
|
|
|
/* |
1948
|
|
|
|
|
|
|
** Assign cursors to all tables in a SrcList |
1949
|
|
|
|
|
|
|
*/ |
1950
|
138
|
|
|
|
|
|
void sqliteSrcListAssignCursors(Parse *pParse, SrcList *pList){ |
1951
|
|
|
|
|
|
|
int i; |
1952
|
254
|
100
|
|
|
|
|
for(i=0; inSrc; i++){ |
1953
|
116
|
50
|
|
|
|
|
if( pList->a[i].iCursor<0 ){ |
1954
|
116
|
|
|
|
|
|
pList->a[i].iCursor = pParse->nTab++; |
1955
|
|
|
|
|
|
|
} |
1956
|
|
|
|
|
|
|
} |
1957
|
138
|
|
|
|
|
|
} |
1958
|
|
|
|
|
|
|
|
1959
|
|
|
|
|
|
|
/* |
1960
|
|
|
|
|
|
|
** Add an alias to the last identifier on the given identifier list. |
1961
|
|
|
|
|
|
|
*/ |
1962
|
0
|
|
|
|
|
|
void sqliteSrcListAddAlias(SrcList *pList, Token *pToken){ |
1963
|
0
|
0
|
|
|
|
|
if( pList && pList->nSrc>0 ){ |
|
|
0
|
|
|
|
|
|
1964
|
0
|
|
|
|
|
|
int i = pList->nSrc - 1; |
1965
|
0
|
|
|
|
|
|
sqliteSetNString(&pList->a[i].zAlias, pToken->z, pToken->n, 0); |
1966
|
0
|
|
|
|
|
|
sqliteDequote(pList->a[i].zAlias); |
1967
|
|
|
|
|
|
|
} |
1968
|
0
|
|
|
|
|
|
} |
1969
|
|
|
|
|
|
|
|
1970
|
|
|
|
|
|
|
/* |
1971
|
|
|
|
|
|
|
** Delete an IdList. |
1972
|
|
|
|
|
|
|
*/ |
1973
|
226
|
|
|
|
|
|
void sqliteIdListDelete(IdList *pList){ |
1974
|
|
|
|
|
|
|
int i; |
1975
|
226
|
100
|
|
|
|
|
if( pList==0 ) return; |
1976
|
26
|
100
|
|
|
|
|
for(i=0; inId; i++){ |
1977
|
15
|
|
|
|
|
|
sqliteFree(pList->a[i].zName); |
1978
|
|
|
|
|
|
|
} |
1979
|
11
|
|
|
|
|
|
sqliteFree(pList->a); |
1980
|
11
|
|
|
|
|
|
sqliteFree(pList); |
1981
|
|
|
|
|
|
|
} |
1982
|
|
|
|
|
|
|
|
1983
|
|
|
|
|
|
|
/* |
1984
|
|
|
|
|
|
|
** Return the index in pList of the identifier named zId. Return -1 |
1985
|
|
|
|
|
|
|
** if not found. |
1986
|
|
|
|
|
|
|
*/ |
1987
|
0
|
|
|
|
|
|
int sqliteIdListIndex(IdList *pList, const char *zName){ |
1988
|
|
|
|
|
|
|
int i; |
1989
|
0
|
0
|
|
|
|
|
if( pList==0 ) return -1; |
1990
|
0
|
0
|
|
|
|
|
for(i=0; inId; i++){ |
1991
|
0
|
0
|
|
|
|
|
if( sqliteStrICmp(pList->a[i].zName, zName)==0 ) return i; |
1992
|
|
|
|
|
|
|
} |
1993
|
0
|
|
|
|
|
|
return -1; |
1994
|
|
|
|
|
|
|
} |
1995
|
|
|
|
|
|
|
|
1996
|
|
|
|
|
|
|
/* |
1997
|
|
|
|
|
|
|
** Delete an entire SrcList including all its substructure. |
1998
|
|
|
|
|
|
|
*/ |
1999
|
196
|
|
|
|
|
|
void sqliteSrcListDelete(SrcList *pList){ |
2000
|
|
|
|
|
|
|
int i; |
2001
|
196
|
100
|
|
|
|
|
if( pList==0 ) return; |
2002
|
362
|
100
|
|
|
|
|
for(i=0; inSrc; i++){ |
2003
|
170
|
|
|
|
|
|
sqliteFree(pList->a[i].zDatabase); |
2004
|
170
|
|
|
|
|
|
sqliteFree(pList->a[i].zName); |
2005
|
170
|
|
|
|
|
|
sqliteFree(pList->a[i].zAlias); |
2006
|
170
|
100
|
|
|
|
|
if( pList->a[i].pTab && pList->a[i].pTab->isTransient ){ |
|
|
100
|
|
|
|
|
|
2007
|
3
|
|
|
|
|
|
sqliteDeleteTable(0, pList->a[i].pTab); |
2008
|
|
|
|
|
|
|
} |
2009
|
170
|
|
|
|
|
|
sqliteSelectDelete(pList->a[i].pSelect); |
2010
|
170
|
|
|
|
|
|
sqliteExprDelete(pList->a[i].pOn); |
2011
|
170
|
|
|
|
|
|
sqliteIdListDelete(pList->a[i].pUsing); |
2012
|
|
|
|
|
|
|
} |
2013
|
192
|
|
|
|
|
|
sqliteFree(pList); |
2014
|
|
|
|
|
|
|
} |
2015
|
|
|
|
|
|
|
|
2016
|
|
|
|
|
|
|
/* |
2017
|
|
|
|
|
|
|
** Begin a transaction |
2018
|
|
|
|
|
|
|
*/ |
2019
|
6
|
|
|
|
|
|
void sqliteBeginTransaction(Parse *pParse, int onError){ |
2020
|
|
|
|
|
|
|
sqlite *db; |
2021
|
|
|
|
|
|
|
|
2022
|
6
|
50
|
|
|
|
|
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
2023
|
6
|
50
|
|
|
|
|
if( pParse->nErr || sqlite_malloc_failed ) return; |
|
|
50
|
|
|
|
|
|
2024
|
6
|
50
|
|
|
|
|
if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; |
2025
|
6
|
50
|
|
|
|
|
if( db->flags & SQLITE_InTrans ){ |
2026
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "cannot start a transaction within a transaction"); |
2027
|
0
|
|
|
|
|
|
return; |
2028
|
|
|
|
|
|
|
} |
2029
|
6
|
|
|
|
|
|
sqliteBeginWriteOperation(pParse, 0, 0); |
2030
|
6
|
50
|
|
|
|
|
if( !pParse->explain ){ |
2031
|
6
|
|
|
|
|
|
db->flags |= SQLITE_InTrans; |
2032
|
6
|
|
|
|
|
|
db->onError = onError; |
2033
|
|
|
|
|
|
|
} |
2034
|
|
|
|
|
|
|
} |
2035
|
|
|
|
|
|
|
|
2036
|
|
|
|
|
|
|
/* |
2037
|
|
|
|
|
|
|
** Commit a transaction |
2038
|
|
|
|
|
|
|
*/ |
2039
|
2
|
|
|
|
|
|
void sqliteCommitTransaction(Parse *pParse){ |
2040
|
|
|
|
|
|
|
sqlite *db; |
2041
|
|
|
|
|
|
|
|
2042
|
2
|
50
|
|
|
|
|
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
2043
|
2
|
50
|
|
|
|
|
if( pParse->nErr || sqlite_malloc_failed ) return; |
|
|
50
|
|
|
|
|
|
2044
|
2
|
50
|
|
|
|
|
if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; |
2045
|
2
|
50
|
|
|
|
|
if( (db->flags & SQLITE_InTrans)==0 ){ |
2046
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "cannot commit - no transaction is active"); |
2047
|
0
|
|
|
|
|
|
return; |
2048
|
|
|
|
|
|
|
} |
2049
|
2
|
50
|
|
|
|
|
if( !pParse->explain ){ |
2050
|
2
|
|
|
|
|
|
db->flags &= ~SQLITE_InTrans; |
2051
|
|
|
|
|
|
|
} |
2052
|
2
|
|
|
|
|
|
sqliteEndWriteOperation(pParse); |
2053
|
2
|
50
|
|
|
|
|
if( !pParse->explain ){ |
2054
|
2
|
|
|
|
|
|
db->onError = OE_Default; |
2055
|
|
|
|
|
|
|
} |
2056
|
|
|
|
|
|
|
} |
2057
|
|
|
|
|
|
|
|
2058
|
|
|
|
|
|
|
/* |
2059
|
|
|
|
|
|
|
** Rollback a transaction |
2060
|
|
|
|
|
|
|
*/ |
2061
|
4
|
|
|
|
|
|
void sqliteRollbackTransaction(Parse *pParse){ |
2062
|
|
|
|
|
|
|
sqlite *db; |
2063
|
|
|
|
|
|
|
Vdbe *v; |
2064
|
|
|
|
|
|
|
|
2065
|
4
|
50
|
|
|
|
|
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
2066
|
4
|
50
|
|
|
|
|
if( pParse->nErr || sqlite_malloc_failed ) return; |
|
|
50
|
|
|
|
|
|
2067
|
4
|
50
|
|
|
|
|
if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; |
2068
|
4
|
50
|
|
|
|
|
if( (db->flags & SQLITE_InTrans)==0 ){ |
2069
|
0
|
|
|
|
|
|
sqliteErrorMsg(pParse, "cannot rollback - no transaction is active"); |
2070
|
0
|
|
|
|
|
|
return; |
2071
|
|
|
|
|
|
|
} |
2072
|
4
|
|
|
|
|
|
v = sqliteGetVdbe(pParse); |
2073
|
4
|
50
|
|
|
|
|
if( v ){ |
2074
|
4
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Rollback, 0, 0); |
2075
|
|
|
|
|
|
|
} |
2076
|
4
|
50
|
|
|
|
|
if( !pParse->explain ){ |
2077
|
4
|
|
|
|
|
|
db->flags &= ~SQLITE_InTrans; |
2078
|
4
|
|
|
|
|
|
db->onError = OE_Default; |
2079
|
|
|
|
|
|
|
} |
2080
|
|
|
|
|
|
|
} |
2081
|
|
|
|
|
|
|
|
2082
|
|
|
|
|
|
|
/* |
2083
|
|
|
|
|
|
|
** Generate VDBE code that will verify the schema cookie for all |
2084
|
|
|
|
|
|
|
** named database files. |
2085
|
|
|
|
|
|
|
*/ |
2086
|
269
|
|
|
|
|
|
void sqliteCodeVerifySchema(Parse *pParse, int iDb){ |
2087
|
269
|
|
|
|
|
|
sqlite *db = pParse->db; |
2088
|
269
|
|
|
|
|
|
Vdbe *v = sqliteGetVdbe(pParse); |
2089
|
|
|
|
|
|
|
assert( iDb>=0 && iDbnDb ); |
2090
|
|
|
|
|
|
|
assert( db->aDb[iDb].pBt!=0 ); |
2091
|
269
|
100
|
|
|
|
|
if( iDb!=1 && !DbHasProperty(db, iDb, DB_Cookie) ){ |
|
|
100
|
|
|
|
|
|
2092
|
147
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_VerifyCookie, iDb, db->aDb[iDb].schema_cookie); |
2093
|
147
|
|
|
|
|
|
DbSetProperty(db, iDb, DB_Cookie); |
2094
|
|
|
|
|
|
|
} |
2095
|
269
|
|
|
|
|
|
} |
2096
|
|
|
|
|
|
|
|
2097
|
|
|
|
|
|
|
/* |
2098
|
|
|
|
|
|
|
** Generate VDBE code that prepares for doing an operation that |
2099
|
|
|
|
|
|
|
** might change the database. |
2100
|
|
|
|
|
|
|
** |
2101
|
|
|
|
|
|
|
** This routine starts a new transaction if we are not already within |
2102
|
|
|
|
|
|
|
** a transaction. If we are already within a transaction, then a checkpoint |
2103
|
|
|
|
|
|
|
** is set if the setCheckpoint parameter is true. A checkpoint should |
2104
|
|
|
|
|
|
|
** be set for operations that might fail (due to a constraint) part of |
2105
|
|
|
|
|
|
|
** the way through and which will need to undo some writes without having to |
2106
|
|
|
|
|
|
|
** rollback the whole transaction. For operations where all constraints |
2107
|
|
|
|
|
|
|
** can be checked before any changes are made to the database, it is never |
2108
|
|
|
|
|
|
|
** necessary to undo a write and the checkpoint should not be set. |
2109
|
|
|
|
|
|
|
** |
2110
|
|
|
|
|
|
|
** Only database iDb and the temp database are made writable by this call. |
2111
|
|
|
|
|
|
|
** If iDb==0, then the main and temp databases are made writable. If |
2112
|
|
|
|
|
|
|
** iDb==1 then only the temp database is made writable. If iDb>1 then the |
2113
|
|
|
|
|
|
|
** specified auxiliary database and the temp database are made writable. |
2114
|
|
|
|
|
|
|
*/ |
2115
|
165
|
|
|
|
|
|
void sqliteBeginWriteOperation(Parse *pParse, int setCheckpoint, int iDb){ |
2116
|
|
|
|
|
|
|
Vdbe *v; |
2117
|
165
|
|
|
|
|
|
sqlite *db = pParse->db; |
2118
|
165
|
50
|
|
|
|
|
if( DbHasProperty(db, iDb, DB_Locked) ) return; |
2119
|
165
|
|
|
|
|
|
v = sqliteGetVdbe(pParse); |
2120
|
165
|
50
|
|
|
|
|
if( v==0 ) return; |
2121
|
165
|
100
|
|
|
|
|
if( !db->aDb[iDb].inTrans ){ |
2122
|
153
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Transaction, iDb, 0); |
2123
|
153
|
|
|
|
|
|
DbSetProperty(db, iDb, DB_Locked); |
2124
|
153
|
|
|
|
|
|
sqliteCodeVerifySchema(pParse, iDb); |
2125
|
153
|
100
|
|
|
|
|
if( iDb!=1 ){ |
2126
|
153
|
|
|
|
|
|
sqliteBeginWriteOperation(pParse, setCheckpoint, 1); |
2127
|
|
|
|
|
|
|
} |
2128
|
12
|
50
|
|
|
|
|
}else if( setCheckpoint ){ |
2129
|
0
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Checkpoint, iDb, 0); |
2130
|
0
|
|
|
|
|
|
DbSetProperty(db, iDb, DB_Locked); |
2131
|
|
|
|
|
|
|
} |
2132
|
|
|
|
|
|
|
} |
2133
|
|
|
|
|
|
|
|
2134
|
|
|
|
|
|
|
/* |
2135
|
|
|
|
|
|
|
** Generate code that concludes an operation that may have changed |
2136
|
|
|
|
|
|
|
** the database. If a statement transaction was started, then emit |
2137
|
|
|
|
|
|
|
** an OP_Commit that will cause the changes to be committed to disk. |
2138
|
|
|
|
|
|
|
** |
2139
|
|
|
|
|
|
|
** Note that checkpoints are automatically committed at the end of |
2140
|
|
|
|
|
|
|
** a statement. Note also that there can be multiple calls to |
2141
|
|
|
|
|
|
|
** sqliteBeginWriteOperation() but there should only be a single |
2142
|
|
|
|
|
|
|
** call to sqliteEndWriteOperation() at the conclusion of the statement. |
2143
|
|
|
|
|
|
|
*/ |
2144
|
86
|
|
|
|
|
|
void sqliteEndWriteOperation(Parse *pParse){ |
2145
|
|
|
|
|
|
|
Vdbe *v; |
2146
|
86
|
|
|
|
|
|
sqlite *db = pParse->db; |
2147
|
86
|
50
|
|
|
|
|
if( pParse->trigStack ) return; /* if this is in a trigger */ |
2148
|
86
|
|
|
|
|
|
v = sqliteGetVdbe(pParse); |
2149
|
86
|
50
|
|
|
|
|
if( v==0 ) return; |
2150
|
86
|
100
|
|
|
|
|
if( db->flags & SQLITE_InTrans ){ |
2151
|
|
|
|
|
|
|
/* A BEGIN has executed. Do not commit until we see an explicit |
2152
|
|
|
|
|
|
|
** COMMIT statement. */ |
2153
|
|
|
|
|
|
|
}else{ |
2154
|
74
|
|
|
|
|
|
sqliteVdbeAddOp(v, OP_Commit, 0, 0); |
2155
|
|
|
|
|
|
|
} |
2156
|
|
|
|
|
|
|
} |