| 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
|
|
|
|
|
|
|
} |