xref: /illumos-gate/usr/src/lib/libsqlite/src/build.c (revision 1da57d55)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate ** 2001 September 15
37c478bd9Sstevel@tonic-gate **
47c478bd9Sstevel@tonic-gate ** The author disclaims copyright to this source code.  In place of
57c478bd9Sstevel@tonic-gate ** a legal notice, here is a blessing:
67c478bd9Sstevel@tonic-gate **
77c478bd9Sstevel@tonic-gate **    May you do good and not evil.
87c478bd9Sstevel@tonic-gate **    May you find forgiveness for yourself and forgive others.
97c478bd9Sstevel@tonic-gate **    May you share freely, never taking more than you give.
107c478bd9Sstevel@tonic-gate **
117c478bd9Sstevel@tonic-gate *************************************************************************
127c478bd9Sstevel@tonic-gate ** This file contains C code routines that are called by the SQLite parser
137c478bd9Sstevel@tonic-gate ** when syntax rules are reduced.  The routines in this file handle the
147c478bd9Sstevel@tonic-gate ** following kinds of SQL syntax:
157c478bd9Sstevel@tonic-gate **
167c478bd9Sstevel@tonic-gate **     CREATE TABLE
177c478bd9Sstevel@tonic-gate **     DROP TABLE
187c478bd9Sstevel@tonic-gate **     CREATE INDEX
197c478bd9Sstevel@tonic-gate **     DROP INDEX
207c478bd9Sstevel@tonic-gate **     creating ID lists
217c478bd9Sstevel@tonic-gate **     BEGIN TRANSACTION
227c478bd9Sstevel@tonic-gate **     COMMIT
237c478bd9Sstevel@tonic-gate **     ROLLBACK
247c478bd9Sstevel@tonic-gate **     PRAGMA
257c478bd9Sstevel@tonic-gate **
267c478bd9Sstevel@tonic-gate ** $Id: build.c,v 1.176.2.2 2004/07/20 00:50:30 drh Exp $
277c478bd9Sstevel@tonic-gate */
287c478bd9Sstevel@tonic-gate #include "sqliteInt.h"
297c478bd9Sstevel@tonic-gate #include <ctype.h>
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate ** This routine is called when a new SQL statement is beginning to
337c478bd9Sstevel@tonic-gate ** be parsed.  Check to see if the schema for the database needs
347c478bd9Sstevel@tonic-gate ** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables.
357c478bd9Sstevel@tonic-gate ** If it does, then read it.
367c478bd9Sstevel@tonic-gate */
sqliteBeginParse(Parse * pParse,int explainFlag)377c478bd9Sstevel@tonic-gate void sqliteBeginParse(Parse *pParse, int explainFlag){
387c478bd9Sstevel@tonic-gate   sqlite *db = pParse->db;
397c478bd9Sstevel@tonic-gate   int i;
407c478bd9Sstevel@tonic-gate   pParse->explain = explainFlag;
417c478bd9Sstevel@tonic-gate   if((db->flags & SQLITE_Initialized)==0 && db->init.busy==0 ){
427c478bd9Sstevel@tonic-gate     int rc = sqliteInit(db, &pParse->zErrMsg);
437c478bd9Sstevel@tonic-gate     if( rc!=SQLITE_OK ){
447c478bd9Sstevel@tonic-gate       pParse->rc = rc;
457c478bd9Sstevel@tonic-gate       pParse->nErr++;
467c478bd9Sstevel@tonic-gate     }
477c478bd9Sstevel@tonic-gate   }
487c478bd9Sstevel@tonic-gate   for(i=0; i<db->nDb; i++){
497c478bd9Sstevel@tonic-gate     DbClearProperty(db, i, DB_Locked);
507c478bd9Sstevel@tonic-gate     if( !db->aDb[i].inTrans ){
517c478bd9Sstevel@tonic-gate       DbClearProperty(db, i, DB_Cookie);
527c478bd9Sstevel@tonic-gate     }
537c478bd9Sstevel@tonic-gate   }
547c478bd9Sstevel@tonic-gate   pParse->nVar = 0;
557c478bd9Sstevel@tonic-gate }
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /*
587c478bd9Sstevel@tonic-gate ** This routine is called after a single SQL statement has been
59*1da57d55SToomas Soome ** parsed and we want to execute the VDBE code to implement
607c478bd9Sstevel@tonic-gate ** that statement.  Prior action routines should have already
617c478bd9Sstevel@tonic-gate ** constructed VDBE code to do the work of the SQL statement.
627c478bd9Sstevel@tonic-gate ** This routine just has to execute the VDBE code.
637c478bd9Sstevel@tonic-gate **
647c478bd9Sstevel@tonic-gate ** Note that if an error occurred, it might be the case that
657c478bd9Sstevel@tonic-gate ** no VDBE code was generated.
667c478bd9Sstevel@tonic-gate */
sqliteExec(Parse * pParse)677c478bd9Sstevel@tonic-gate void sqliteExec(Parse *pParse){
687c478bd9Sstevel@tonic-gate   sqlite *db = pParse->db;
697c478bd9Sstevel@tonic-gate   Vdbe *v = pParse->pVdbe;
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate   if( v==0 && (v = sqliteGetVdbe(pParse))!=0 ){
727c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_Halt, 0, 0);
737c478bd9Sstevel@tonic-gate   }
747c478bd9Sstevel@tonic-gate   if( sqlite_malloc_failed ) return;
757c478bd9Sstevel@tonic-gate   if( v && pParse->nErr==0 ){
767c478bd9Sstevel@tonic-gate     FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
777c478bd9Sstevel@tonic-gate     sqliteVdbeTrace(v, trace);
787c478bd9Sstevel@tonic-gate     sqliteVdbeMakeReady(v, pParse->nVar, pParse->explain);
797c478bd9Sstevel@tonic-gate     pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE;
807c478bd9Sstevel@tonic-gate     pParse->colNamesSet = 0;
817c478bd9Sstevel@tonic-gate   }else if( pParse->rc==SQLITE_OK ){
827c478bd9Sstevel@tonic-gate     pParse->rc = SQLITE_ERROR;
837c478bd9Sstevel@tonic-gate   }
847c478bd9Sstevel@tonic-gate   pParse->nTab = 0;
857c478bd9Sstevel@tonic-gate   pParse->nMem = 0;
867c478bd9Sstevel@tonic-gate   pParse->nSet = 0;
877c478bd9Sstevel@tonic-gate   pParse->nAgg = 0;
887c478bd9Sstevel@tonic-gate   pParse->nVar = 0;
897c478bd9Sstevel@tonic-gate }
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate /*
92*1da57d55SToomas Soome ** Locate the in-memory structure that describes
937c478bd9Sstevel@tonic-gate ** a particular database table given the name
947c478bd9Sstevel@tonic-gate ** of that table and (optionally) the name of the database
957c478bd9Sstevel@tonic-gate ** containing the table.  Return NULL if not found.
967c478bd9Sstevel@tonic-gate **
977c478bd9Sstevel@tonic-gate ** If zDatabase is 0, all databases are searched for the
987c478bd9Sstevel@tonic-gate ** table and the first matching table is returned.  (No checking
997c478bd9Sstevel@tonic-gate ** for duplicate table names is done.)  The search order is
1007c478bd9Sstevel@tonic-gate ** TEMP first, then MAIN, then any auxiliary databases added
1017c478bd9Sstevel@tonic-gate ** using the ATTACH command.
1027c478bd9Sstevel@tonic-gate **
1037c478bd9Sstevel@tonic-gate ** See also sqliteLocateTable().
1047c478bd9Sstevel@tonic-gate */
sqliteFindTable(sqlite * db,const char * zName,const char * zDatabase)1057c478bd9Sstevel@tonic-gate Table *sqliteFindTable(sqlite *db, const char *zName, const char *zDatabase){
1067c478bd9Sstevel@tonic-gate   Table *p = 0;
1077c478bd9Sstevel@tonic-gate   int i;
1087c478bd9Sstevel@tonic-gate   for(i=0; i<db->nDb; i++){
1097c478bd9Sstevel@tonic-gate     int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */
1107c478bd9Sstevel@tonic-gate     if( zDatabase!=0 && sqliteStrICmp(zDatabase, db->aDb[j].zName) ) continue;
1117c478bd9Sstevel@tonic-gate     p = sqliteHashFind(&db->aDb[j].tblHash, zName, strlen(zName)+1);
1127c478bd9Sstevel@tonic-gate     if( p ) break;
1137c478bd9Sstevel@tonic-gate   }
1147c478bd9Sstevel@tonic-gate   return p;
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate /*
118*1da57d55SToomas Soome ** Locate the in-memory structure that describes
1197c478bd9Sstevel@tonic-gate ** a particular database table given the name
1207c478bd9Sstevel@tonic-gate ** of that table and (optionally) the name of the database
1217c478bd9Sstevel@tonic-gate ** containing the table.  Return NULL if not found.
1227c478bd9Sstevel@tonic-gate ** Also leave an error message in pParse->zErrMsg.
1237c478bd9Sstevel@tonic-gate **
1247c478bd9Sstevel@tonic-gate ** The difference between this routine and sqliteFindTable()
1257c478bd9Sstevel@tonic-gate ** is that this routine leaves an error message in pParse->zErrMsg
1267c478bd9Sstevel@tonic-gate ** where sqliteFindTable() does not.
1277c478bd9Sstevel@tonic-gate */
sqliteLocateTable(Parse * pParse,const char * zName,const char * zDbase)1287c478bd9Sstevel@tonic-gate Table *sqliteLocateTable(Parse *pParse, const char *zName, const char *zDbase){
1297c478bd9Sstevel@tonic-gate   Table *p;
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate   p = sqliteFindTable(pParse->db, zName, zDbase);
1327c478bd9Sstevel@tonic-gate   if( p==0 ){
1337c478bd9Sstevel@tonic-gate     if( zDbase ){
1347c478bd9Sstevel@tonic-gate       sqliteErrorMsg(pParse, "no such table: %s.%s", zDbase, zName);
1357c478bd9Sstevel@tonic-gate     }else if( sqliteFindTable(pParse->db, zName, 0)!=0 ){
1367c478bd9Sstevel@tonic-gate       sqliteErrorMsg(pParse, "table \"%s\" is not in database \"%s\"",
1377c478bd9Sstevel@tonic-gate          zName, zDbase);
1387c478bd9Sstevel@tonic-gate     }else{
1397c478bd9Sstevel@tonic-gate       sqliteErrorMsg(pParse, "no such table: %s", zName);
1407c478bd9Sstevel@tonic-gate     }
1417c478bd9Sstevel@tonic-gate   }
1427c478bd9Sstevel@tonic-gate   return p;
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate /*
146*1da57d55SToomas Soome ** Locate the in-memory structure that describes
1477c478bd9Sstevel@tonic-gate ** a particular index given the name of that index
1487c478bd9Sstevel@tonic-gate ** and the name of the database that contains the index.
1497c478bd9Sstevel@tonic-gate ** Return NULL if not found.
1507c478bd9Sstevel@tonic-gate **
1517c478bd9Sstevel@tonic-gate ** If zDatabase is 0, all databases are searched for the
1527c478bd9Sstevel@tonic-gate ** table and the first matching index is returned.  (No checking
1537c478bd9Sstevel@tonic-gate ** for duplicate index names is done.)  The search order is
1547c478bd9Sstevel@tonic-gate ** TEMP first, then MAIN, then any auxiliary databases added
1557c478bd9Sstevel@tonic-gate ** using the ATTACH command.
1567c478bd9Sstevel@tonic-gate */
sqliteFindIndex(sqlite * db,const char * zName,const char * zDb)1577c478bd9Sstevel@tonic-gate Index *sqliteFindIndex(sqlite *db, const char *zName, const char *zDb){
1587c478bd9Sstevel@tonic-gate   Index *p = 0;
1597c478bd9Sstevel@tonic-gate   int i;
1607c478bd9Sstevel@tonic-gate   for(i=0; i<db->nDb; i++){
1617c478bd9Sstevel@tonic-gate     int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */
1627c478bd9Sstevel@tonic-gate     if( zDb && sqliteStrICmp(zDb, db->aDb[j].zName) ) continue;
1637c478bd9Sstevel@tonic-gate     p = sqliteHashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1);
1647c478bd9Sstevel@tonic-gate     if( p ) break;
1657c478bd9Sstevel@tonic-gate   }
1667c478bd9Sstevel@tonic-gate   return p;
1677c478bd9Sstevel@tonic-gate }
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate /*
1707c478bd9Sstevel@tonic-gate ** Remove the given index from the index hash table, and free
1717c478bd9Sstevel@tonic-gate ** its memory structures.
1727c478bd9Sstevel@tonic-gate **
1737c478bd9Sstevel@tonic-gate ** The index is removed from the database hash tables but
1747c478bd9Sstevel@tonic-gate ** it is not unlinked from the Table that it indexes.
1757c478bd9Sstevel@tonic-gate ** Unlinking from the Table must be done by the calling function.
1767c478bd9Sstevel@tonic-gate */
sqliteDeleteIndex(sqlite * db,Index * p)1777c478bd9Sstevel@tonic-gate static void sqliteDeleteIndex(sqlite *db, Index *p){
1787c478bd9Sstevel@tonic-gate   Index *pOld;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate   assert( db!=0 && p->zName!=0 );
1817c478bd9Sstevel@tonic-gate   pOld = sqliteHashInsert(&db->aDb[p->iDb].idxHash, p->zName,
1827c478bd9Sstevel@tonic-gate                           strlen(p->zName)+1, 0);
1837c478bd9Sstevel@tonic-gate   if( pOld!=0 && pOld!=p ){
1847c478bd9Sstevel@tonic-gate     sqliteHashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,
1857c478bd9Sstevel@tonic-gate                      strlen(pOld->zName)+1, pOld);
1867c478bd9Sstevel@tonic-gate   }
1877c478bd9Sstevel@tonic-gate   sqliteFree(p);
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate /*
1917c478bd9Sstevel@tonic-gate ** Unlink the given index from its table, then remove
1927c478bd9Sstevel@tonic-gate ** the index from the index hash table and free its memory
1937c478bd9Sstevel@tonic-gate ** structures.
1947c478bd9Sstevel@tonic-gate */
sqliteUnlinkAndDeleteIndex(sqlite * db,Index * pIndex)1957c478bd9Sstevel@tonic-gate void sqliteUnlinkAndDeleteIndex(sqlite *db, Index *pIndex){
1967c478bd9Sstevel@tonic-gate   if( pIndex->pTable->pIndex==pIndex ){
1977c478bd9Sstevel@tonic-gate     pIndex->pTable->pIndex = pIndex->pNext;
1987c478bd9Sstevel@tonic-gate   }else{
1997c478bd9Sstevel@tonic-gate     Index *p;
2007c478bd9Sstevel@tonic-gate     for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){}
2017c478bd9Sstevel@tonic-gate     if( p && p->pNext==pIndex ){
2027c478bd9Sstevel@tonic-gate       p->pNext = pIndex->pNext;
2037c478bd9Sstevel@tonic-gate     }
2047c478bd9Sstevel@tonic-gate   }
2057c478bd9Sstevel@tonic-gate   sqliteDeleteIndex(db, pIndex);
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate /*
2097c478bd9Sstevel@tonic-gate ** Erase all schema information from the in-memory hash tables of
2107c478bd9Sstevel@tonic-gate ** database connection.  This routine is called to reclaim memory
2117c478bd9Sstevel@tonic-gate ** before the connection closes.  It is also called during a rollback
2127c478bd9Sstevel@tonic-gate ** if there were schema changes during the transaction.
2137c478bd9Sstevel@tonic-gate **
2147c478bd9Sstevel@tonic-gate ** If iDb<=0 then reset the internal schema tables for all database
2157c478bd9Sstevel@tonic-gate ** files.  If iDb>=2 then reset the internal schema for only the
2167c478bd9Sstevel@tonic-gate ** single file indicated.
2177c478bd9Sstevel@tonic-gate */
sqliteResetInternalSchema(sqlite * db,int iDb)2187c478bd9Sstevel@tonic-gate void sqliteResetInternalSchema(sqlite *db, int iDb){
2197c478bd9Sstevel@tonic-gate   HashElem *pElem;
2207c478bd9Sstevel@tonic-gate   Hash temp1;
2217c478bd9Sstevel@tonic-gate   Hash temp2;
2227c478bd9Sstevel@tonic-gate   int i, j;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate   assert( iDb>=0 && iDb<db->nDb );
2257c478bd9Sstevel@tonic-gate   db->flags &= ~SQLITE_Initialized;
2267c478bd9Sstevel@tonic-gate   for(i=iDb; i<db->nDb; i++){
2277c478bd9Sstevel@tonic-gate     Db *pDb = &db->aDb[i];
2287c478bd9Sstevel@tonic-gate     temp1 = pDb->tblHash;
2297c478bd9Sstevel@tonic-gate     temp2 = pDb->trigHash;
2307c478bd9Sstevel@tonic-gate     sqliteHashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0);
2317c478bd9Sstevel@tonic-gate     sqliteHashClear(&pDb->aFKey);
2327c478bd9Sstevel@tonic-gate     sqliteHashClear(&pDb->idxHash);
2337c478bd9Sstevel@tonic-gate     for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
2347c478bd9Sstevel@tonic-gate       Trigger *pTrigger = sqliteHashData(pElem);
2357c478bd9Sstevel@tonic-gate       sqliteDeleteTrigger(pTrigger);
2367c478bd9Sstevel@tonic-gate     }
2377c478bd9Sstevel@tonic-gate     sqliteHashClear(&temp2);
2387c478bd9Sstevel@tonic-gate     sqliteHashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0);
2397c478bd9Sstevel@tonic-gate     for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
2407c478bd9Sstevel@tonic-gate       Table *pTab = sqliteHashData(pElem);
2417c478bd9Sstevel@tonic-gate       sqliteDeleteTable(db, pTab);
2427c478bd9Sstevel@tonic-gate     }
2437c478bd9Sstevel@tonic-gate     sqliteHashClear(&temp1);
2447c478bd9Sstevel@tonic-gate     DbClearProperty(db, i, DB_SchemaLoaded);
2457c478bd9Sstevel@tonic-gate     if( iDb>0 ) return;
2467c478bd9Sstevel@tonic-gate   }
2477c478bd9Sstevel@tonic-gate   assert( iDb==0 );
2487c478bd9Sstevel@tonic-gate   db->flags &= ~SQLITE_InternChanges;
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate   /* If one or more of the auxiliary database files has been closed,
2517c478bd9Sstevel@tonic-gate   ** then remove then from the auxiliary database list.  We take the
2527c478bd9Sstevel@tonic-gate   ** opportunity to do this here since we have just deleted all of the
2537c478bd9Sstevel@tonic-gate   ** schema hash tables and therefore do not have to make any changes
2547c478bd9Sstevel@tonic-gate   ** to any of those tables.
2557c478bd9Sstevel@tonic-gate   */
2567c478bd9Sstevel@tonic-gate   for(i=0; i<db->nDb; i++){
2577c478bd9Sstevel@tonic-gate     struct Db *pDb = &db->aDb[i];
2587c478bd9Sstevel@tonic-gate     if( pDb->pBt==0 ){
2597c478bd9Sstevel@tonic-gate       if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
2607c478bd9Sstevel@tonic-gate       pDb->pAux = 0;
2617c478bd9Sstevel@tonic-gate     }
2627c478bd9Sstevel@tonic-gate   }
2637c478bd9Sstevel@tonic-gate   for(i=j=2; i<db->nDb; i++){
2647c478bd9Sstevel@tonic-gate     struct Db *pDb = &db->aDb[i];
2657c478bd9Sstevel@tonic-gate     if( pDb->pBt==0 ){
2667c478bd9Sstevel@tonic-gate       sqliteFree(pDb->zName);
2677c478bd9Sstevel@tonic-gate       pDb->zName = 0;
2687c478bd9Sstevel@tonic-gate       continue;
2697c478bd9Sstevel@tonic-gate     }
2707c478bd9Sstevel@tonic-gate     if( j<i ){
2717c478bd9Sstevel@tonic-gate       db->aDb[j] = db->aDb[i];
2727c478bd9Sstevel@tonic-gate     }
2737c478bd9Sstevel@tonic-gate     j++;
2747c478bd9Sstevel@tonic-gate   }
2757c478bd9Sstevel@tonic-gate   memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j]));
2767c478bd9Sstevel@tonic-gate   db->nDb = j;
2777c478bd9Sstevel@tonic-gate   if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
2787c478bd9Sstevel@tonic-gate     memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
2797c478bd9Sstevel@tonic-gate     sqliteFree(db->aDb);
2807c478bd9Sstevel@tonic-gate     db->aDb = db->aDbStatic;
2817c478bd9Sstevel@tonic-gate   }
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate ** This routine is called whenever a rollback occurs.  If there were
2867c478bd9Sstevel@tonic-gate ** schema changes during the transaction, then we have to reset the
2877c478bd9Sstevel@tonic-gate ** internal hash tables and reload them from disk.
2887c478bd9Sstevel@tonic-gate */
sqliteRollbackInternalChanges(sqlite * db)2897c478bd9Sstevel@tonic-gate void sqliteRollbackInternalChanges(sqlite *db){
2907c478bd9Sstevel@tonic-gate   if( db->flags & SQLITE_InternChanges ){
2917c478bd9Sstevel@tonic-gate     sqliteResetInternalSchema(db, 0);
2927c478bd9Sstevel@tonic-gate   }
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate /*
2967c478bd9Sstevel@tonic-gate ** This routine is called when a commit occurs.
2977c478bd9Sstevel@tonic-gate */
sqliteCommitInternalChanges(sqlite * db)2987c478bd9Sstevel@tonic-gate void sqliteCommitInternalChanges(sqlite *db){
2997c478bd9Sstevel@tonic-gate   db->aDb[0].schema_cookie = db->next_cookie;
3007c478bd9Sstevel@tonic-gate   db->flags &= ~SQLITE_InternChanges;
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate /*
3047c478bd9Sstevel@tonic-gate ** Remove the memory data structures associated with the given
3057c478bd9Sstevel@tonic-gate ** Table.  No changes are made to disk by this routine.
3067c478bd9Sstevel@tonic-gate **
3077c478bd9Sstevel@tonic-gate ** This routine just deletes the data structure.  It does not unlink
3087c478bd9Sstevel@tonic-gate ** the table data structure from the hash table.  Nor does it remove
3097c478bd9Sstevel@tonic-gate ** foreign keys from the sqlite.aFKey hash table.  But it does destroy
310*1da57d55SToomas Soome ** memory structures of the indices and foreign keys associated with
3117c478bd9Sstevel@tonic-gate ** the table.
3127c478bd9Sstevel@tonic-gate **
3137c478bd9Sstevel@tonic-gate ** Indices associated with the table are unlinked from the "db"
3147c478bd9Sstevel@tonic-gate ** data structure if db!=NULL.  If db==NULL, indices attached to
3157c478bd9Sstevel@tonic-gate ** the table are deleted, but it is assumed they have already been
3167c478bd9Sstevel@tonic-gate ** unlinked.
3177c478bd9Sstevel@tonic-gate */
sqliteDeleteTable(sqlite * db,Table * pTable)3187c478bd9Sstevel@tonic-gate void sqliteDeleteTable(sqlite *db, Table *pTable){
3197c478bd9Sstevel@tonic-gate   int i;
3207c478bd9Sstevel@tonic-gate   Index *pIndex, *pNext;
3217c478bd9Sstevel@tonic-gate   FKey *pFKey, *pNextFKey;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate   if( pTable==0 ) return;
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate   /* Delete all indices associated with this table
3267c478bd9Sstevel@tonic-gate   */
3277c478bd9Sstevel@tonic-gate   for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
3287c478bd9Sstevel@tonic-gate     pNext = pIndex->pNext;
3297c478bd9Sstevel@tonic-gate     assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) );
3307c478bd9Sstevel@tonic-gate     sqliteDeleteIndex(db, pIndex);
3317c478bd9Sstevel@tonic-gate   }
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate   /* Delete all foreign keys associated with this table.  The keys
334*1da57d55SToomas Soome   ** should have already been unlinked from the db->aFKey hash table
3357c478bd9Sstevel@tonic-gate   */
3367c478bd9Sstevel@tonic-gate   for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){
3377c478bd9Sstevel@tonic-gate     pNextFKey = pFKey->pNextFrom;
3387c478bd9Sstevel@tonic-gate     assert( pTable->iDb<db->nDb );
3397c478bd9Sstevel@tonic-gate     assert( sqliteHashFind(&db->aDb[pTable->iDb].aFKey,
3407c478bd9Sstevel@tonic-gate                            pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
3417c478bd9Sstevel@tonic-gate     sqliteFree(pFKey);
3427c478bd9Sstevel@tonic-gate   }
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate   /* Delete the Table structure itself.
3457c478bd9Sstevel@tonic-gate   */
3467c478bd9Sstevel@tonic-gate   for(i=0; i<pTable->nCol; i++){
3477c478bd9Sstevel@tonic-gate     sqliteFree(pTable->aCol[i].zName);
3487c478bd9Sstevel@tonic-gate     sqliteFree(pTable->aCol[i].zDflt);
3497c478bd9Sstevel@tonic-gate     sqliteFree(pTable->aCol[i].zType);
3507c478bd9Sstevel@tonic-gate   }
3517c478bd9Sstevel@tonic-gate   sqliteFree(pTable->zName);
3527c478bd9Sstevel@tonic-gate   sqliteFree(pTable->aCol);
3537c478bd9Sstevel@tonic-gate   sqliteSelectDelete(pTable->pSelect);
3547c478bd9Sstevel@tonic-gate   sqliteFree(pTable);
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate /*
3587c478bd9Sstevel@tonic-gate ** Unlink the given table from the hash tables and the delete the
3597c478bd9Sstevel@tonic-gate ** table structure with all its indices and foreign keys.
3607c478bd9Sstevel@tonic-gate */
sqliteUnlinkAndDeleteTable(sqlite * db,Table * p)3617c478bd9Sstevel@tonic-gate static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){
3627c478bd9Sstevel@tonic-gate   Table *pOld;
3637c478bd9Sstevel@tonic-gate   FKey *pF1, *pF2;
3647c478bd9Sstevel@tonic-gate   int i = p->iDb;
3657c478bd9Sstevel@tonic-gate   assert( db!=0 );
3667c478bd9Sstevel@tonic-gate   pOld = sqliteHashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1, 0);
3677c478bd9Sstevel@tonic-gate   assert( pOld==0 || pOld==p );
3687c478bd9Sstevel@tonic-gate   for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
3697c478bd9Sstevel@tonic-gate     int nTo = strlen(pF1->zTo) + 1;
3707c478bd9Sstevel@tonic-gate     pF2 = sqliteHashFind(&db->aDb[i].aFKey, pF1->zTo, nTo);
3717c478bd9Sstevel@tonic-gate     if( pF2==pF1 ){
3727c478bd9Sstevel@tonic-gate       sqliteHashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo);
3737c478bd9Sstevel@tonic-gate     }else{
3747c478bd9Sstevel@tonic-gate       while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
3757c478bd9Sstevel@tonic-gate       if( pF2 ){
3767c478bd9Sstevel@tonic-gate         pF2->pNextTo = pF1->pNextTo;
3777c478bd9Sstevel@tonic-gate       }
3787c478bd9Sstevel@tonic-gate     }
3797c478bd9Sstevel@tonic-gate   }
3807c478bd9Sstevel@tonic-gate   sqliteDeleteTable(db, p);
3817c478bd9Sstevel@tonic-gate }
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate /*
3847c478bd9Sstevel@tonic-gate ** Construct the name of a user table or index from a token.
3857c478bd9Sstevel@tonic-gate **
3867c478bd9Sstevel@tonic-gate ** Space to hold the name is obtained from sqliteMalloc() and must
3877c478bd9Sstevel@tonic-gate ** be freed by the calling function.
3887c478bd9Sstevel@tonic-gate */
sqliteTableNameFromToken(Token * pName)3897c478bd9Sstevel@tonic-gate char *sqliteTableNameFromToken(Token *pName){
3907c478bd9Sstevel@tonic-gate   char *zName = sqliteStrNDup(pName->z, pName->n);
3917c478bd9Sstevel@tonic-gate   sqliteDequote(zName);
3927c478bd9Sstevel@tonic-gate   return zName;
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate /*
3967c478bd9Sstevel@tonic-gate ** Generate code to open the appropriate master table.  The table
397*1da57d55SToomas Soome ** opened will be SQLITE_MASTER for persistent tables and
3987c478bd9Sstevel@tonic-gate ** SQLITE_TEMP_MASTER for temporary tables.  The table is opened
3997c478bd9Sstevel@tonic-gate ** on cursor 0.
4007c478bd9Sstevel@tonic-gate */
sqliteOpenMasterTable(Vdbe * v,int isTemp)4017c478bd9Sstevel@tonic-gate void sqliteOpenMasterTable(Vdbe *v, int isTemp){
4027c478bd9Sstevel@tonic-gate   sqliteVdbeAddOp(v, OP_Integer, isTemp, 0);
4037c478bd9Sstevel@tonic-gate   sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate /*
4077c478bd9Sstevel@tonic-gate ** Begin constructing a new table representation in memory.  This is
4087c478bd9Sstevel@tonic-gate ** the first of several action routines that get called in response
4097c478bd9Sstevel@tonic-gate ** to a CREATE TABLE statement.  In particular, this routine is called
4107c478bd9Sstevel@tonic-gate ** after seeing tokens "CREATE" and "TABLE" and the table name.  The
4117c478bd9Sstevel@tonic-gate ** pStart token is the CREATE and pName is the table name.  The isTemp
4127c478bd9Sstevel@tonic-gate ** flag is true if the table should be stored in the auxiliary database
4137c478bd9Sstevel@tonic-gate ** file instead of in the main database file.  This is normally the case
4147c478bd9Sstevel@tonic-gate ** when the "TEMP" or "TEMPORARY" keyword occurs in between
4157c478bd9Sstevel@tonic-gate ** CREATE and TABLE.
4167c478bd9Sstevel@tonic-gate **
4177c478bd9Sstevel@tonic-gate ** The new table record is initialized and put in pParse->pNewTable.
4187c478bd9Sstevel@tonic-gate ** As more of the CREATE TABLE statement is parsed, additional action
4197c478bd9Sstevel@tonic-gate ** routines will be called to add more information to this record.
4207c478bd9Sstevel@tonic-gate ** At the end of the CREATE TABLE statement, the sqliteEndTable() routine
4217c478bd9Sstevel@tonic-gate ** is called to complete the construction of the new table record.
4227c478bd9Sstevel@tonic-gate */
sqliteStartTable(Parse * pParse,Token * pStart,Token * pName,int isTemp,int isView)4237c478bd9Sstevel@tonic-gate void sqliteStartTable(
4247c478bd9Sstevel@tonic-gate   Parse *pParse,   /* Parser context */
4257c478bd9Sstevel@tonic-gate   Token *pStart,   /* The "CREATE" token */
4267c478bd9Sstevel@tonic-gate   Token *pName,    /* Name of table or view to create */
4277c478bd9Sstevel@tonic-gate   int isTemp,      /* True if this is a TEMP table */
4287c478bd9Sstevel@tonic-gate   int isView       /* True if this is a VIEW */
4297c478bd9Sstevel@tonic-gate ){
4307c478bd9Sstevel@tonic-gate   Table *pTable;
4317c478bd9Sstevel@tonic-gate   Index *pIdx;
4327c478bd9Sstevel@tonic-gate   char *zName;
4337c478bd9Sstevel@tonic-gate   sqlite *db = pParse->db;
4347c478bd9Sstevel@tonic-gate   Vdbe *v;
4357c478bd9Sstevel@tonic-gate   int iDb;
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate   pParse->sFirstToken = *pStart;
4387c478bd9Sstevel@tonic-gate   zName = sqliteTableNameFromToken(pName);
4397c478bd9Sstevel@tonic-gate   if( zName==0 ) return;
4407c478bd9Sstevel@tonic-gate   if( db->init.iDb==1 ) isTemp = 1;
4417c478bd9Sstevel@tonic-gate #ifndef SQLITE_OMIT_AUTHORIZATION
4427c478bd9Sstevel@tonic-gate   assert( (isTemp & 1)==isTemp );
4437c478bd9Sstevel@tonic-gate   {
4447c478bd9Sstevel@tonic-gate     int code;
4457c478bd9Sstevel@tonic-gate     char *zDb = isTemp ? "temp" : "main";
4467c478bd9Sstevel@tonic-gate     if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
4477c478bd9Sstevel@tonic-gate       sqliteFree(zName);
4487c478bd9Sstevel@tonic-gate       return;
4497c478bd9Sstevel@tonic-gate     }
4507c478bd9Sstevel@tonic-gate     if( isView ){
4517c478bd9Sstevel@tonic-gate       if( isTemp ){
4527c478bd9Sstevel@tonic-gate         code = SQLITE_CREATE_TEMP_VIEW;
4537c478bd9Sstevel@tonic-gate       }else{
4547c478bd9Sstevel@tonic-gate         code = SQLITE_CREATE_VIEW;
4557c478bd9Sstevel@tonic-gate       }
4567c478bd9Sstevel@tonic-gate     }else{
4577c478bd9Sstevel@tonic-gate       if( isTemp ){
4587c478bd9Sstevel@tonic-gate         code = SQLITE_CREATE_TEMP_TABLE;
4597c478bd9Sstevel@tonic-gate       }else{
4607c478bd9Sstevel@tonic-gate         code = SQLITE_CREATE_TABLE;
4617c478bd9Sstevel@tonic-gate       }
4627c478bd9Sstevel@tonic-gate     }
4637c478bd9Sstevel@tonic-gate     if( sqliteAuthCheck(pParse, code, zName, 0, zDb) ){
4647c478bd9Sstevel@tonic-gate       sqliteFree(zName);
4657c478bd9Sstevel@tonic-gate       return;
4667c478bd9Sstevel@tonic-gate     }
4677c478bd9Sstevel@tonic-gate   }
4687c478bd9Sstevel@tonic-gate #endif
469*1da57d55SToomas Soome 
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate   /* Before trying to create a temporary table, make sure the Btree for
4727c478bd9Sstevel@tonic-gate   ** holding temporary tables is open.
4737c478bd9Sstevel@tonic-gate   */
4747c478bd9Sstevel@tonic-gate   if( isTemp && db->aDb[1].pBt==0 && !pParse->explain ){
4757c478bd9Sstevel@tonic-gate     int rc = sqliteBtreeFactory(db, 0, 0, MAX_PAGES, &db->aDb[1].pBt);
4767c478bd9Sstevel@tonic-gate     if( rc!=SQLITE_OK ){
4777c478bd9Sstevel@tonic-gate       sqliteErrorMsg(pParse, "unable to open a temporary database "
4787c478bd9Sstevel@tonic-gate         "file for storing temporary tables");
4797c478bd9Sstevel@tonic-gate       pParse->nErr++;
4807c478bd9Sstevel@tonic-gate       return;
4817c478bd9Sstevel@tonic-gate     }
4827c478bd9Sstevel@tonic-gate     if( db->flags & SQLITE_InTrans ){
4837c478bd9Sstevel@tonic-gate       rc = sqliteBtreeBeginTrans(db->aDb[1].pBt);
4847c478bd9Sstevel@tonic-gate       if( rc!=SQLITE_OK ){
4857c478bd9Sstevel@tonic-gate         sqliteErrorMsg(pParse, "unable to get a write lock on "
4867c478bd9Sstevel@tonic-gate           "the temporary database file");
4877c478bd9Sstevel@tonic-gate         return;
4887c478bd9Sstevel@tonic-gate       }
4897c478bd9Sstevel@tonic-gate     }
4907c478bd9Sstevel@tonic-gate   }
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate   /* Make sure the new table name does not collide with an existing
4937c478bd9Sstevel@tonic-gate   ** index or table name.  Issue an error message if it does.
4947c478bd9Sstevel@tonic-gate   **
4957c478bd9Sstevel@tonic-gate   ** If we are re-reading the sqlite_master table because of a schema
4967c478bd9Sstevel@tonic-gate   ** change and a new permanent table is found whose name collides with
4977c478bd9Sstevel@tonic-gate   ** an existing temporary table, that is not an error.
4987c478bd9Sstevel@tonic-gate   */
4997c478bd9Sstevel@tonic-gate   pTable = sqliteFindTable(db, zName, 0);
5007c478bd9Sstevel@tonic-gate   iDb = isTemp ? 1 : db->init.iDb;
5017c478bd9Sstevel@tonic-gate   if( pTable!=0 && (pTable->iDb==iDb || !db->init.busy) ){
5027c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "table %T already exists", pName);
5037c478bd9Sstevel@tonic-gate     sqliteFree(zName);
5047c478bd9Sstevel@tonic-gate     return;
5057c478bd9Sstevel@tonic-gate   }
5067c478bd9Sstevel@tonic-gate   if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 &&
5077c478bd9Sstevel@tonic-gate           (pIdx->iDb==0 || !db->init.busy) ){
5087c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "there is already an index named %s", zName);
5097c478bd9Sstevel@tonic-gate     sqliteFree(zName);
5107c478bd9Sstevel@tonic-gate     return;
5117c478bd9Sstevel@tonic-gate   }
5127c478bd9Sstevel@tonic-gate   pTable = sqliteMalloc( sizeof(Table) );
5137c478bd9Sstevel@tonic-gate   if( pTable==0 ){
5147c478bd9Sstevel@tonic-gate     sqliteFree(zName);
5157c478bd9Sstevel@tonic-gate     return;
5167c478bd9Sstevel@tonic-gate   }
5177c478bd9Sstevel@tonic-gate   pTable->zName = zName;
5187c478bd9Sstevel@tonic-gate   pTable->nCol = 0;
5197c478bd9Sstevel@tonic-gate   pTable->aCol = 0;
5207c478bd9Sstevel@tonic-gate   pTable->iPKey = -1;
5217c478bd9Sstevel@tonic-gate   pTable->pIndex = 0;
5227c478bd9Sstevel@tonic-gate   pTable->iDb = iDb;
5237c478bd9Sstevel@tonic-gate   if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
5247c478bd9Sstevel@tonic-gate   pParse->pNewTable = pTable;
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate   /* Begin generating the code that will insert the table record into
5277c478bd9Sstevel@tonic-gate   ** the SQLITE_MASTER table.  Note in particular that we must go ahead
5287c478bd9Sstevel@tonic-gate   ** and allocate the record number for the table entry now.  Before any
5297c478bd9Sstevel@tonic-gate   ** PRIMARY KEY or UNIQUE keywords are parsed.  Those keywords will cause
530*1da57d55SToomas Soome   ** indices to be created and the table record must come before the
5317c478bd9Sstevel@tonic-gate   ** indices.  Hence, the record number for the table must be allocated
5327c478bd9Sstevel@tonic-gate   ** now.
5337c478bd9Sstevel@tonic-gate   */
5347c478bd9Sstevel@tonic-gate   if( !db->init.busy && (v = sqliteGetVdbe(pParse))!=0 ){
5357c478bd9Sstevel@tonic-gate     sqliteBeginWriteOperation(pParse, 0, isTemp);
5367c478bd9Sstevel@tonic-gate     if( !isTemp ){
5377c478bd9Sstevel@tonic-gate       sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0);
5387c478bd9Sstevel@tonic-gate       sqliteVdbeAddOp(v, OP_SetCookie, 0, 1);
5397c478bd9Sstevel@tonic-gate     }
5407c478bd9Sstevel@tonic-gate     sqliteOpenMasterTable(v, isTemp);
5417c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
5427c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_Dup, 0, 0);
5437c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_String, 0, 0);
5447c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
5457c478bd9Sstevel@tonic-gate   }
5467c478bd9Sstevel@tonic-gate }
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate /*
5497c478bd9Sstevel@tonic-gate ** Add a new column to the table currently being constructed.
5507c478bd9Sstevel@tonic-gate **
5517c478bd9Sstevel@tonic-gate ** The parser calls this routine once for each column declaration
5527c478bd9Sstevel@tonic-gate ** in a CREATE TABLE statement.  sqliteStartTable() gets called
5537c478bd9Sstevel@tonic-gate ** first to get things going.  Then this routine is called for each
5547c478bd9Sstevel@tonic-gate ** column.
5557c478bd9Sstevel@tonic-gate */
sqliteAddColumn(Parse * pParse,Token * pName)5567c478bd9Sstevel@tonic-gate void sqliteAddColumn(Parse *pParse, Token *pName){
5577c478bd9Sstevel@tonic-gate   Table *p;
5587c478bd9Sstevel@tonic-gate   int i;
5597c478bd9Sstevel@tonic-gate   char *z = 0;
5607c478bd9Sstevel@tonic-gate   Column *pCol;
5617c478bd9Sstevel@tonic-gate   if( (p = pParse->pNewTable)==0 ) return;
5627c478bd9Sstevel@tonic-gate   sqliteSetNString(&z, pName->z, pName->n, 0);
5637c478bd9Sstevel@tonic-gate   if( z==0 ) return;
5647c478bd9Sstevel@tonic-gate   sqliteDequote(z);
5657c478bd9Sstevel@tonic-gate   for(i=0; i<p->nCol; i++){
5667c478bd9Sstevel@tonic-gate     if( sqliteStrICmp(z, p->aCol[i].zName)==0 ){
5677c478bd9Sstevel@tonic-gate       sqliteErrorMsg(pParse, "duplicate column name: %s", z);
5687c478bd9Sstevel@tonic-gate       sqliteFree(z);
5697c478bd9Sstevel@tonic-gate       return;
5707c478bd9Sstevel@tonic-gate     }
5717c478bd9Sstevel@tonic-gate   }
5727c478bd9Sstevel@tonic-gate   if( (p->nCol & 0x7)==0 ){
5737c478bd9Sstevel@tonic-gate     Column *aNew;
5747c478bd9Sstevel@tonic-gate     aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0]));
5757c478bd9Sstevel@tonic-gate     if( aNew==0 ) return;
5767c478bd9Sstevel@tonic-gate     p->aCol = aNew;
5777c478bd9Sstevel@tonic-gate   }
5787c478bd9Sstevel@tonic-gate   pCol = &p->aCol[p->nCol];
5797c478bd9Sstevel@tonic-gate   memset(pCol, 0, sizeof(p->aCol[0]));
5807c478bd9Sstevel@tonic-gate   pCol->zName = z;
5817c478bd9Sstevel@tonic-gate   pCol->sortOrder = SQLITE_SO_NUM;
5827c478bd9Sstevel@tonic-gate   p->nCol++;
5837c478bd9Sstevel@tonic-gate }
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate /*
5867c478bd9Sstevel@tonic-gate ** This routine is called by the parser while in the middle of
5877c478bd9Sstevel@tonic-gate ** parsing a CREATE TABLE statement.  A "NOT NULL" constraint has
5887c478bd9Sstevel@tonic-gate ** been seen on a column.  This routine sets the notNull flag on
5897c478bd9Sstevel@tonic-gate ** the column currently under construction.
5907c478bd9Sstevel@tonic-gate */
sqliteAddNotNull(Parse * pParse,int onError)5917c478bd9Sstevel@tonic-gate void sqliteAddNotNull(Parse *pParse, int onError){
5927c478bd9Sstevel@tonic-gate   Table *p;
5937c478bd9Sstevel@tonic-gate   int i;
5947c478bd9Sstevel@tonic-gate   if( (p = pParse->pNewTable)==0 ) return;
5957c478bd9Sstevel@tonic-gate   i = p->nCol-1;
5967c478bd9Sstevel@tonic-gate   if( i>=0 ) p->aCol[i].notNull = onError;
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate /*
6007c478bd9Sstevel@tonic-gate ** This routine is called by the parser while in the middle of
6017c478bd9Sstevel@tonic-gate ** parsing a CREATE TABLE statement.  The pFirst token is the first
6027c478bd9Sstevel@tonic-gate ** token in the sequence of tokens that describe the type of the
6037c478bd9Sstevel@tonic-gate ** column currently under construction.   pLast is the last token
6047c478bd9Sstevel@tonic-gate ** in the sequence.  Use this information to construct a string
6057c478bd9Sstevel@tonic-gate ** that contains the typename of the column and store that string
6067c478bd9Sstevel@tonic-gate ** in zType.
607*1da57d55SToomas Soome */
sqliteAddColumnType(Parse * pParse,Token * pFirst,Token * pLast)6087c478bd9Sstevel@tonic-gate void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
6097c478bd9Sstevel@tonic-gate   Table *p;
6107c478bd9Sstevel@tonic-gate   int i, j;
6117c478bd9Sstevel@tonic-gate   int n;
6127c478bd9Sstevel@tonic-gate   char *z, **pz;
6137c478bd9Sstevel@tonic-gate   Column *pCol;
6147c478bd9Sstevel@tonic-gate   if( (p = pParse->pNewTable)==0 ) return;
6157c478bd9Sstevel@tonic-gate   i = p->nCol-1;
6167c478bd9Sstevel@tonic-gate   if( i<0 ) return;
6177c478bd9Sstevel@tonic-gate   pCol = &p->aCol[i];
6187c478bd9Sstevel@tonic-gate   pz = &pCol->zType;
6197c478bd9Sstevel@tonic-gate   n = pLast->n + Addr(pLast->z) - Addr(pFirst->z);
6207c478bd9Sstevel@tonic-gate   sqliteSetNString(pz, pFirst->z, n, 0);
6217c478bd9Sstevel@tonic-gate   z = *pz;
6227c478bd9Sstevel@tonic-gate   if( z==0 ) return;
6237c478bd9Sstevel@tonic-gate   for(i=j=0; z[i]; i++){
6247c478bd9Sstevel@tonic-gate     int c = z[i];
6257c478bd9Sstevel@tonic-gate     if( isspace(c) ) continue;
6267c478bd9Sstevel@tonic-gate     z[j++] = c;
6277c478bd9Sstevel@tonic-gate   }
6287c478bd9Sstevel@tonic-gate   z[j] = 0;
6297c478bd9Sstevel@tonic-gate   if( pParse->db->file_format>=4 ){
6307c478bd9Sstevel@tonic-gate     pCol->sortOrder = sqliteCollateType(z, n);
6317c478bd9Sstevel@tonic-gate   }else{
6327c478bd9Sstevel@tonic-gate     pCol->sortOrder = SQLITE_SO_NUM;
6337c478bd9Sstevel@tonic-gate   }
6347c478bd9Sstevel@tonic-gate }
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate /*
6377c478bd9Sstevel@tonic-gate ** The given token is the default value for the last column added to
6387c478bd9Sstevel@tonic-gate ** the table currently under construction.  If "minusFlag" is true, it
6397c478bd9Sstevel@tonic-gate ** means the value token was preceded by a minus sign.
6407c478bd9Sstevel@tonic-gate **
6417c478bd9Sstevel@tonic-gate ** This routine is called by the parser while in the middle of
6427c478bd9Sstevel@tonic-gate ** parsing a CREATE TABLE statement.
6437c478bd9Sstevel@tonic-gate */
sqliteAddDefaultValue(Parse * pParse,Token * pVal,int minusFlag)6447c478bd9Sstevel@tonic-gate void sqliteAddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
6457c478bd9Sstevel@tonic-gate   Table *p;
6467c478bd9Sstevel@tonic-gate   int i;
6477c478bd9Sstevel@tonic-gate   char **pz;
6487c478bd9Sstevel@tonic-gate   if( (p = pParse->pNewTable)==0 ) return;
6497c478bd9Sstevel@tonic-gate   i = p->nCol-1;
6507c478bd9Sstevel@tonic-gate   if( i<0 ) return;
6517c478bd9Sstevel@tonic-gate   pz = &p->aCol[i].zDflt;
6527c478bd9Sstevel@tonic-gate   if( minusFlag ){
6537c478bd9Sstevel@tonic-gate     sqliteSetNString(pz, "-", 1, pVal->z, pVal->n, 0);
6547c478bd9Sstevel@tonic-gate   }else{
6557c478bd9Sstevel@tonic-gate     sqliteSetNString(pz, pVal->z, pVal->n, 0);
6567c478bd9Sstevel@tonic-gate   }
6577c478bd9Sstevel@tonic-gate   sqliteDequote(*pz);
6587c478bd9Sstevel@tonic-gate }
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate /*
661*1da57d55SToomas Soome ** Designate the PRIMARY KEY for the table.  pList is a list of names
6627c478bd9Sstevel@tonic-gate ** of columns that form the primary key.  If pList is NULL, then the
6637c478bd9Sstevel@tonic-gate ** most recently added column of the table is the primary key.
6647c478bd9Sstevel@tonic-gate **
6657c478bd9Sstevel@tonic-gate ** A table can have at most one primary key.  If the table already has
6667c478bd9Sstevel@tonic-gate ** a primary key (and this is the second primary key) then create an
6677c478bd9Sstevel@tonic-gate ** error.
6687c478bd9Sstevel@tonic-gate **
6697c478bd9Sstevel@tonic-gate ** If the PRIMARY KEY is on a single column whose datatype is INTEGER,
6707c478bd9Sstevel@tonic-gate ** then we will try to use that column as the row id.  (Exception:
6717c478bd9Sstevel@tonic-gate ** For backwards compatibility with older databases, do not do this
6727c478bd9Sstevel@tonic-gate ** if the file format version number is less than 1.)  Set the Table.iPKey
6737c478bd9Sstevel@tonic-gate ** field of the table under construction to be the index of the
6747c478bd9Sstevel@tonic-gate ** INTEGER PRIMARY KEY column.  Table.iPKey is set to -1 if there is
6757c478bd9Sstevel@tonic-gate ** no INTEGER PRIMARY KEY.
6767c478bd9Sstevel@tonic-gate **
6777c478bd9Sstevel@tonic-gate ** If the key is not an INTEGER PRIMARY KEY, then create a unique
6787c478bd9Sstevel@tonic-gate ** index for the key.  No index is created for INTEGER PRIMARY KEYs.
6797c478bd9Sstevel@tonic-gate */
sqliteAddPrimaryKey(Parse * pParse,IdList * pList,int onError)6807c478bd9Sstevel@tonic-gate void sqliteAddPrimaryKey(Parse *pParse, IdList *pList, int onError){
6817c478bd9Sstevel@tonic-gate   Table *pTab = pParse->pNewTable;
6827c478bd9Sstevel@tonic-gate   char *zType = 0;
6837c478bd9Sstevel@tonic-gate   int iCol = -1, i;
6847c478bd9Sstevel@tonic-gate   if( pTab==0 ) goto primary_key_exit;
6857c478bd9Sstevel@tonic-gate   if( pTab->hasPrimKey ){
686*1da57d55SToomas Soome     sqliteErrorMsg(pParse,
6877c478bd9Sstevel@tonic-gate       "table \"%s\" has more than one primary key", pTab->zName);
6887c478bd9Sstevel@tonic-gate     goto primary_key_exit;
6897c478bd9Sstevel@tonic-gate   }
6907c478bd9Sstevel@tonic-gate   pTab->hasPrimKey = 1;
6917c478bd9Sstevel@tonic-gate   if( pList==0 ){
6927c478bd9Sstevel@tonic-gate     iCol = pTab->nCol - 1;
6937c478bd9Sstevel@tonic-gate     pTab->aCol[iCol].isPrimKey = 1;
6947c478bd9Sstevel@tonic-gate   }else{
6957c478bd9Sstevel@tonic-gate     for(i=0; i<pList->nId; i++){
6967c478bd9Sstevel@tonic-gate       for(iCol=0; iCol<pTab->nCol; iCol++){
6977c478bd9Sstevel@tonic-gate         if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ) break;
6987c478bd9Sstevel@tonic-gate       }
6997c478bd9Sstevel@tonic-gate       if( iCol<pTab->nCol ) pTab->aCol[iCol].isPrimKey = 1;
7007c478bd9Sstevel@tonic-gate     }
7017c478bd9Sstevel@tonic-gate     if( pList->nId>1 ) iCol = -1;
7027c478bd9Sstevel@tonic-gate   }
7037c478bd9Sstevel@tonic-gate   if( iCol>=0 && iCol<pTab->nCol ){
7047c478bd9Sstevel@tonic-gate     zType = pTab->aCol[iCol].zType;
7057c478bd9Sstevel@tonic-gate   }
706*1da57d55SToomas Soome   if( pParse->db->file_format>=1 &&
7077c478bd9Sstevel@tonic-gate            zType && sqliteStrICmp(zType, "INTEGER")==0 ){
7087c478bd9Sstevel@tonic-gate     pTab->iPKey = iCol;
7097c478bd9Sstevel@tonic-gate     pTab->keyConf = onError;
7107c478bd9Sstevel@tonic-gate   }else{
7117c478bd9Sstevel@tonic-gate     sqliteCreateIndex(pParse, 0, 0, pList, onError, 0, 0);
7127c478bd9Sstevel@tonic-gate     pList = 0;
7137c478bd9Sstevel@tonic-gate   }
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate primary_key_exit:
7167c478bd9Sstevel@tonic-gate   sqliteIdListDelete(pList);
7177c478bd9Sstevel@tonic-gate   return;
7187c478bd9Sstevel@tonic-gate }
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate /*
7217c478bd9Sstevel@tonic-gate ** Return the appropriate collating type given a type name.
7227c478bd9Sstevel@tonic-gate **
7237c478bd9Sstevel@tonic-gate ** The collation type is text (SQLITE_SO_TEXT) if the type
7247c478bd9Sstevel@tonic-gate ** name contains the character stream "text" or "blob" or
7257c478bd9Sstevel@tonic-gate ** "clob".  Any other type name is collated as numeric
7267c478bd9Sstevel@tonic-gate ** (SQLITE_SO_NUM).
7277c478bd9Sstevel@tonic-gate */
sqliteCollateType(const char * zType,int nType)7287c478bd9Sstevel@tonic-gate int sqliteCollateType(const char *zType, int nType){
7297c478bd9Sstevel@tonic-gate   int i;
7307c478bd9Sstevel@tonic-gate   for(i=0; i<nType-3; i++){
7317c478bd9Sstevel@tonic-gate     int c = *(zType++) | 0x60;
7327c478bd9Sstevel@tonic-gate     if( (c=='b' || c=='c') && sqliteStrNICmp(zType, "lob", 3)==0 ){
7337c478bd9Sstevel@tonic-gate       return SQLITE_SO_TEXT;
7347c478bd9Sstevel@tonic-gate     }
7357c478bd9Sstevel@tonic-gate     if( c=='c' && sqliteStrNICmp(zType, "har", 3)==0 ){
7367c478bd9Sstevel@tonic-gate       return SQLITE_SO_TEXT;
7377c478bd9Sstevel@tonic-gate     }
7387c478bd9Sstevel@tonic-gate     if( c=='t' && sqliteStrNICmp(zType, "ext", 3)==0 ){
7397c478bd9Sstevel@tonic-gate       return SQLITE_SO_TEXT;
7407c478bd9Sstevel@tonic-gate     }
7417c478bd9Sstevel@tonic-gate   }
7427c478bd9Sstevel@tonic-gate   return SQLITE_SO_NUM;
7437c478bd9Sstevel@tonic-gate }
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate /*
7467c478bd9Sstevel@tonic-gate ** This routine is called by the parser while in the middle of
7477c478bd9Sstevel@tonic-gate ** parsing a CREATE TABLE statement.  A "COLLATE" clause has
7487c478bd9Sstevel@tonic-gate ** been seen on a column.  This routine sets the Column.sortOrder on
7497c478bd9Sstevel@tonic-gate ** the column currently under construction.
7507c478bd9Sstevel@tonic-gate */
sqliteAddCollateType(Parse * pParse,int collType)7517c478bd9Sstevel@tonic-gate void sqliteAddCollateType(Parse *pParse, int collType){
7527c478bd9Sstevel@tonic-gate   Table *p;
7537c478bd9Sstevel@tonic-gate   int i;
7547c478bd9Sstevel@tonic-gate   if( (p = pParse->pNewTable)==0 ) return;
7557c478bd9Sstevel@tonic-gate   i = p->nCol-1;
7567c478bd9Sstevel@tonic-gate   if( i>=0 ) p->aCol[i].sortOrder = collType;
7577c478bd9Sstevel@tonic-gate }
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate /*
7607c478bd9Sstevel@tonic-gate ** Come up with a new random value for the schema cookie.  Make sure
7617c478bd9Sstevel@tonic-gate ** the new value is different from the old.
7627c478bd9Sstevel@tonic-gate **
7637c478bd9Sstevel@tonic-gate ** The schema cookie is used to determine when the schema for the
7647c478bd9Sstevel@tonic-gate ** database changes.  After each schema change, the cookie value
7657c478bd9Sstevel@tonic-gate ** changes.  When a process first reads the schema it records the
7667c478bd9Sstevel@tonic-gate ** cookie.  Thereafter, whenever it goes to access the database,
7677c478bd9Sstevel@tonic-gate ** it checks the cookie to make sure the schema has not changed
7687c478bd9Sstevel@tonic-gate ** since it was last read.
7697c478bd9Sstevel@tonic-gate **
7707c478bd9Sstevel@tonic-gate ** This plan is not completely bullet-proof.  It is possible for
7717c478bd9Sstevel@tonic-gate ** the schema to change multiple times and for the cookie to be
7727c478bd9Sstevel@tonic-gate ** set back to prior value.  But schema changes are infrequent
7737c478bd9Sstevel@tonic-gate ** and the probability of hitting the same cookie value is only
7747c478bd9Sstevel@tonic-gate ** 1 chance in 2^32.  So we're safe enough.
7757c478bd9Sstevel@tonic-gate */
sqliteChangeCookie(sqlite * db,Vdbe * v)7767c478bd9Sstevel@tonic-gate void sqliteChangeCookie(sqlite *db, Vdbe *v){
7777c478bd9Sstevel@tonic-gate   if( db->next_cookie==db->aDb[0].schema_cookie ){
7787c478bd9Sstevel@tonic-gate     unsigned char r;
7797c478bd9Sstevel@tonic-gate     sqliteRandomness(1, &r);
7807c478bd9Sstevel@tonic-gate     db->next_cookie = db->aDb[0].schema_cookie + r + 1;
7817c478bd9Sstevel@tonic-gate     db->flags |= SQLITE_InternChanges;
7827c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0);
7837c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_SetCookie, 0, 0);
7847c478bd9Sstevel@tonic-gate   }
7857c478bd9Sstevel@tonic-gate }
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate /*
7887c478bd9Sstevel@tonic-gate ** Measure the number of characters needed to output the given
7897c478bd9Sstevel@tonic-gate ** identifier.  The number returned includes any quotes used
7907c478bd9Sstevel@tonic-gate ** but does not include the null terminator.
7917c478bd9Sstevel@tonic-gate */
identLength(const char * z)7927c478bd9Sstevel@tonic-gate static int identLength(const char *z){
7937c478bd9Sstevel@tonic-gate   int n;
7947c478bd9Sstevel@tonic-gate   int needQuote = 0;
7957c478bd9Sstevel@tonic-gate   for(n=0; *z; n++, z++){
7967c478bd9Sstevel@tonic-gate     if( *z=='\'' ){ n++; needQuote=1; }
7977c478bd9Sstevel@tonic-gate   }
7987c478bd9Sstevel@tonic-gate   return n + needQuote*2;
7997c478bd9Sstevel@tonic-gate }
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate /*
8027c478bd9Sstevel@tonic-gate ** Write an identifier onto the end of the given string.  Add
8037c478bd9Sstevel@tonic-gate ** quote characters as needed.
8047c478bd9Sstevel@tonic-gate */
identPut(char * z,int * pIdx,char * zIdent)8057c478bd9Sstevel@tonic-gate static void identPut(char *z, int *pIdx, char *zIdent){
8067c478bd9Sstevel@tonic-gate   int i, j, needQuote;
8077c478bd9Sstevel@tonic-gate   i = *pIdx;
8087c478bd9Sstevel@tonic-gate   for(j=0; zIdent[j]; j++){
8097c478bd9Sstevel@tonic-gate     if( !isalnum(zIdent[j]) && zIdent[j]!='_' ) break;
8107c478bd9Sstevel@tonic-gate   }
8117c478bd9Sstevel@tonic-gate   needQuote =  zIdent[j]!=0 || isdigit(zIdent[0])
8127c478bd9Sstevel@tonic-gate                   || sqliteKeywordCode(zIdent, j)!=TK_ID;
8137c478bd9Sstevel@tonic-gate   if( needQuote ) z[i++] = '\'';
8147c478bd9Sstevel@tonic-gate   for(j=0; zIdent[j]; j++){
8157c478bd9Sstevel@tonic-gate     z[i++] = zIdent[j];
8167c478bd9Sstevel@tonic-gate     if( zIdent[j]=='\'' ) z[i++] = '\'';
8177c478bd9Sstevel@tonic-gate   }
8187c478bd9Sstevel@tonic-gate   if( needQuote ) z[i++] = '\'';
8197c478bd9Sstevel@tonic-gate   z[i] = 0;
8207c478bd9Sstevel@tonic-gate   *pIdx = i;
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate /*
8247c478bd9Sstevel@tonic-gate ** Generate a CREATE TABLE statement appropriate for the given
8257c478bd9Sstevel@tonic-gate ** table.  Memory to hold the text of the statement is obtained
8267c478bd9Sstevel@tonic-gate ** from sqliteMalloc() and must be freed by the calling function.
8277c478bd9Sstevel@tonic-gate */
createTableStmt(Table * p)8287c478bd9Sstevel@tonic-gate static char *createTableStmt(Table *p){
8297c478bd9Sstevel@tonic-gate   int i, k, n;
8307c478bd9Sstevel@tonic-gate   char *zStmt;
8317c478bd9Sstevel@tonic-gate   char *zSep, *zSep2, *zEnd;
8327c478bd9Sstevel@tonic-gate   n = 0;
8337c478bd9Sstevel@tonic-gate   for(i=0; i<p->nCol; i++){
8347c478bd9Sstevel@tonic-gate     n += identLength(p->aCol[i].zName);
8357c478bd9Sstevel@tonic-gate   }
8367c478bd9Sstevel@tonic-gate   n += identLength(p->zName);
8377c478bd9Sstevel@tonic-gate   if( n<40 ){
8387c478bd9Sstevel@tonic-gate     zSep = "";
8397c478bd9Sstevel@tonic-gate     zSep2 = ",";
8407c478bd9Sstevel@tonic-gate     zEnd = ")";
8417c478bd9Sstevel@tonic-gate   }else{
8427c478bd9Sstevel@tonic-gate     zSep = "\n  ";
8437c478bd9Sstevel@tonic-gate     zSep2 = ",\n  ";
8447c478bd9Sstevel@tonic-gate     zEnd = "\n)";
8457c478bd9Sstevel@tonic-gate   }
8467c478bd9Sstevel@tonic-gate   n += 35 + 6*p->nCol;
8477c478bd9Sstevel@tonic-gate   zStmt = sqliteMallocRaw( n );
8487c478bd9Sstevel@tonic-gate   if( zStmt==0 ) return 0;
8497c478bd9Sstevel@tonic-gate   strcpy(zStmt, p->iDb==1 ? "CREATE TEMP TABLE " : "CREATE TABLE ");
8507c478bd9Sstevel@tonic-gate   k = strlen(zStmt);
8517c478bd9Sstevel@tonic-gate   identPut(zStmt, &k, p->zName);
8527c478bd9Sstevel@tonic-gate   zStmt[k++] = '(';
8537c478bd9Sstevel@tonic-gate   for(i=0; i<p->nCol; i++){
8547c478bd9Sstevel@tonic-gate     strcpy(&zStmt[k], zSep);
8557c478bd9Sstevel@tonic-gate     k += strlen(&zStmt[k]);
8567c478bd9Sstevel@tonic-gate     zSep = zSep2;
8577c478bd9Sstevel@tonic-gate     identPut(zStmt, &k, p->aCol[i].zName);
8587c478bd9Sstevel@tonic-gate   }
8597c478bd9Sstevel@tonic-gate   strcpy(&zStmt[k], zEnd);
8607c478bd9Sstevel@tonic-gate   return zStmt;
8617c478bd9Sstevel@tonic-gate }
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate /*
8647c478bd9Sstevel@tonic-gate ** This routine is called to report the final ")" that terminates
8657c478bd9Sstevel@tonic-gate ** a CREATE TABLE statement.
8667c478bd9Sstevel@tonic-gate **
8677c478bd9Sstevel@tonic-gate ** The table structure that other action routines have been building
8687c478bd9Sstevel@tonic-gate ** is added to the internal hash tables, assuming no errors have
8697c478bd9Sstevel@tonic-gate ** occurred.
8707c478bd9Sstevel@tonic-gate **
8717c478bd9Sstevel@tonic-gate ** An entry for the table is made in the master table on disk, unless
8727c478bd9Sstevel@tonic-gate ** this is a temporary table or db->init.busy==1.  When db->init.busy==1
8737c478bd9Sstevel@tonic-gate ** it means we are reading the sqlite_master table because we just
8747c478bd9Sstevel@tonic-gate ** connected to the database or because the sqlite_master table has
8757c478bd9Sstevel@tonic-gate ** recently changes, so the entry for this table already exists in
8767c478bd9Sstevel@tonic-gate ** the sqlite_master table.  We do not want to create it again.
8777c478bd9Sstevel@tonic-gate **
8787c478bd9Sstevel@tonic-gate ** If the pSelect argument is not NULL, it means that this routine
879*1da57d55SToomas Soome ** was called to create a table generated from a
8807c478bd9Sstevel@tonic-gate ** "CREATE TABLE ... AS SELECT ..." statement.  The column names of
8817c478bd9Sstevel@tonic-gate ** the new table will match the result set of the SELECT.
8827c478bd9Sstevel@tonic-gate */
sqliteEndTable(Parse * pParse,Token * pEnd,Select * pSelect)8837c478bd9Sstevel@tonic-gate void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
8847c478bd9Sstevel@tonic-gate   Table *p;
8857c478bd9Sstevel@tonic-gate   sqlite *db = pParse->db;
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate   if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite_malloc_failed ) return;
8887c478bd9Sstevel@tonic-gate   p = pParse->pNewTable;
8897c478bd9Sstevel@tonic-gate   if( p==0 ) return;
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate   /* If the table is generated from a SELECT, then construct the
8927c478bd9Sstevel@tonic-gate   ** list of columns and the text of the table.
8937c478bd9Sstevel@tonic-gate   */
8947c478bd9Sstevel@tonic-gate   if( pSelect ){
8957c478bd9Sstevel@tonic-gate     Table *pSelTab = sqliteResultSetOfSelect(pParse, 0, pSelect);
8967c478bd9Sstevel@tonic-gate     if( pSelTab==0 ) return;
8977c478bd9Sstevel@tonic-gate     assert( p->aCol==0 );
8987c478bd9Sstevel@tonic-gate     p->nCol = pSelTab->nCol;
8997c478bd9Sstevel@tonic-gate     p->aCol = pSelTab->aCol;
9007c478bd9Sstevel@tonic-gate     pSelTab->nCol = 0;
9017c478bd9Sstevel@tonic-gate     pSelTab->aCol = 0;
9027c478bd9Sstevel@tonic-gate     sqliteDeleteTable(0, pSelTab);
9037c478bd9Sstevel@tonic-gate   }
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate   /* If the db->init.busy is 1 it means we are reading the SQL off the
9067c478bd9Sstevel@tonic-gate   ** "sqlite_master" or "sqlite_temp_master" table on the disk.
9077c478bd9Sstevel@tonic-gate   ** So do not write to the disk again.  Extract the root page number
9087c478bd9Sstevel@tonic-gate   ** for the table from the db->init.newTnum field.  (The page number
9097c478bd9Sstevel@tonic-gate   ** should have been put there by the sqliteOpenCb routine.)
9107c478bd9Sstevel@tonic-gate   */
9117c478bd9Sstevel@tonic-gate   if( db->init.busy ){
9127c478bd9Sstevel@tonic-gate     p->tnum = db->init.newTnum;
9137c478bd9Sstevel@tonic-gate   }
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate   /* If not initializing, then create a record for the new table
9167c478bd9Sstevel@tonic-gate   ** in the SQLITE_MASTER table of the database.  The record number
9177c478bd9Sstevel@tonic-gate   ** for the new table entry should already be on the stack.
9187c478bd9Sstevel@tonic-gate   **
9197c478bd9Sstevel@tonic-gate   ** If this is a TEMPORARY table, write the entry into the auxiliary
9207c478bd9Sstevel@tonic-gate   ** file instead of into the main database file.
9217c478bd9Sstevel@tonic-gate   */
9227c478bd9Sstevel@tonic-gate   if( !db->init.busy ){
9237c478bd9Sstevel@tonic-gate     int n;
9247c478bd9Sstevel@tonic-gate     Vdbe *v;
9257c478bd9Sstevel@tonic-gate 
9267c478bd9Sstevel@tonic-gate     v = sqliteGetVdbe(pParse);
9277c478bd9Sstevel@tonic-gate     if( v==0 ) return;
9287c478bd9Sstevel@tonic-gate     if( p->pSelect==0 ){
9297c478bd9Sstevel@tonic-gate       /* A regular table */
9307c478bd9Sstevel@tonic-gate       sqliteVdbeOp3(v, OP_CreateTable, 0, p->iDb, (char*)&p->tnum, P3_POINTER);
9317c478bd9Sstevel@tonic-gate     }else{
9327c478bd9Sstevel@tonic-gate       /* A view */
9337c478bd9Sstevel@tonic-gate       sqliteVdbeAddOp(v, OP_Integer, 0, 0);
9347c478bd9Sstevel@tonic-gate     }
9357c478bd9Sstevel@tonic-gate     p->tnum = 0;
9367c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_Pull, 1, 0);
9377c478bd9Sstevel@tonic-gate     sqliteVdbeOp3(v, OP_String, 0, 0, p->pSelect==0?"table":"view", P3_STATIC);
9387c478bd9Sstevel@tonic-gate     sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0);
9397c478bd9Sstevel@tonic-gate     sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0);
9407c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_Dup, 4, 0);
9417c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_String, 0, 0);
9427c478bd9Sstevel@tonic-gate     if( pSelect ){
9437c478bd9Sstevel@tonic-gate       char *z = createTableStmt(p);
9447c478bd9Sstevel@tonic-gate       n = z ? strlen(z) : 0;
9457c478bd9Sstevel@tonic-gate       sqliteVdbeChangeP3(v, -1, z, n);
9467c478bd9Sstevel@tonic-gate       sqliteFree(z);
9477c478bd9Sstevel@tonic-gate     }else{
9487c478bd9Sstevel@tonic-gate       assert( pEnd!=0 );
9497c478bd9Sstevel@tonic-gate       n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1;
9507c478bd9Sstevel@tonic-gate       sqliteVdbeChangeP3(v, -1, pParse->sFirstToken.z, n);
9517c478bd9Sstevel@tonic-gate     }
9527c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
9537c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
9547c478bd9Sstevel@tonic-gate     if( !p->iDb ){
9557c478bd9Sstevel@tonic-gate       sqliteChangeCookie(db, v);
9567c478bd9Sstevel@tonic-gate     }
9577c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_Close, 0, 0);
9587c478bd9Sstevel@tonic-gate     if( pSelect ){
9597c478bd9Sstevel@tonic-gate       sqliteVdbeAddOp(v, OP_Integer, p->iDb, 0);
9607c478bd9Sstevel@tonic-gate       sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0);
9617c478bd9Sstevel@tonic-gate       pParse->nTab = 2;
9627c478bd9Sstevel@tonic-gate       sqliteSelect(pParse, pSelect, SRT_Table, 1, 0, 0, 0);
9637c478bd9Sstevel@tonic-gate     }
9647c478bd9Sstevel@tonic-gate     sqliteEndWriteOperation(pParse);
9657c478bd9Sstevel@tonic-gate   }
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate   /* Add the table to the in-memory representation of the database.
9687c478bd9Sstevel@tonic-gate   */
9697c478bd9Sstevel@tonic-gate   if( pParse->explain==0 && pParse->nErr==0 ){
9707c478bd9Sstevel@tonic-gate     Table *pOld;
9717c478bd9Sstevel@tonic-gate     FKey *pFKey;
972*1da57d55SToomas Soome     pOld = sqliteHashInsert(&db->aDb[p->iDb].tblHash,
9737c478bd9Sstevel@tonic-gate                             p->zName, strlen(p->zName)+1, p);
9747c478bd9Sstevel@tonic-gate     if( pOld ){
9757c478bd9Sstevel@tonic-gate       assert( p==pOld );  /* Malloc must have failed inside HashInsert() */
9767c478bd9Sstevel@tonic-gate       return;
9777c478bd9Sstevel@tonic-gate     }
9787c478bd9Sstevel@tonic-gate     for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){
9797c478bd9Sstevel@tonic-gate       int nTo = strlen(pFKey->zTo) + 1;
9807c478bd9Sstevel@tonic-gate       pFKey->pNextTo = sqliteHashFind(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo);
9817c478bd9Sstevel@tonic-gate       sqliteHashInsert(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo, pFKey);
9827c478bd9Sstevel@tonic-gate     }
9837c478bd9Sstevel@tonic-gate     pParse->pNewTable = 0;
9847c478bd9Sstevel@tonic-gate     db->nTable++;
9857c478bd9Sstevel@tonic-gate     db->flags |= SQLITE_InternChanges;
9867c478bd9Sstevel@tonic-gate   }
9877c478bd9Sstevel@tonic-gate }
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate /*
9907c478bd9Sstevel@tonic-gate ** The parser calls this routine in order to create a new VIEW
9917c478bd9Sstevel@tonic-gate */
sqliteCreateView(Parse * pParse,Token * pBegin,Token * pName,Select * pSelect,int isTemp)9927c478bd9Sstevel@tonic-gate void sqliteCreateView(
9937c478bd9Sstevel@tonic-gate   Parse *pParse,     /* The parsing context */
9947c478bd9Sstevel@tonic-gate   Token *pBegin,     /* The CREATE token that begins the statement */
9957c478bd9Sstevel@tonic-gate   Token *pName,      /* The token that holds the name of the view */
9967c478bd9Sstevel@tonic-gate   Select *pSelect,   /* A SELECT statement that will become the new view */
9977c478bd9Sstevel@tonic-gate   int isTemp         /* TRUE for a TEMPORARY view */
9987c478bd9Sstevel@tonic-gate ){
9997c478bd9Sstevel@tonic-gate   Table *p;
10007c478bd9Sstevel@tonic-gate   int n;
10017c478bd9Sstevel@tonic-gate   const char *z;
10027c478bd9Sstevel@tonic-gate   Token sEnd;
10037c478bd9Sstevel@tonic-gate   DbFixer sFix;
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate   sqliteStartTable(pParse, pBegin, pName, isTemp, 1);
10067c478bd9Sstevel@tonic-gate   p = pParse->pNewTable;
10077c478bd9Sstevel@tonic-gate   if( p==0 || pParse->nErr ){
10087c478bd9Sstevel@tonic-gate     sqliteSelectDelete(pSelect);
10097c478bd9Sstevel@tonic-gate     return;
10107c478bd9Sstevel@tonic-gate   }
10117c478bd9Sstevel@tonic-gate   if( sqliteFixInit(&sFix, pParse, p->iDb, "view", pName)
10127c478bd9Sstevel@tonic-gate     && sqliteFixSelect(&sFix, pSelect)
10137c478bd9Sstevel@tonic-gate   ){
10147c478bd9Sstevel@tonic-gate     sqliteSelectDelete(pSelect);
10157c478bd9Sstevel@tonic-gate     return;
10167c478bd9Sstevel@tonic-gate   }
10177c478bd9Sstevel@tonic-gate 
10187c478bd9Sstevel@tonic-gate   /* Make a copy of the entire SELECT statement that defines the view.
10197c478bd9Sstevel@tonic-gate   ** This will force all the Expr.token.z values to be dynamically
10207c478bd9Sstevel@tonic-gate   ** allocated rather than point to the input string - which means that
10217c478bd9Sstevel@tonic-gate   ** they will persist after the current sqlite_exec() call returns.
10227c478bd9Sstevel@tonic-gate   */
10237c478bd9Sstevel@tonic-gate   p->pSelect = sqliteSelectDup(pSelect);
10247c478bd9Sstevel@tonic-gate   sqliteSelectDelete(pSelect);
10257c478bd9Sstevel@tonic-gate   if( !pParse->db->init.busy ){
10267c478bd9Sstevel@tonic-gate     sqliteViewGetColumnNames(pParse, p);
10277c478bd9Sstevel@tonic-gate   }
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate   /* Locate the end of the CREATE VIEW statement.  Make sEnd point to
10307c478bd9Sstevel@tonic-gate   ** the end.
10317c478bd9Sstevel@tonic-gate   */
10327c478bd9Sstevel@tonic-gate   sEnd = pParse->sLastToken;
10337c478bd9Sstevel@tonic-gate   if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){
10347c478bd9Sstevel@tonic-gate     sEnd.z += sEnd.n;
10357c478bd9Sstevel@tonic-gate   }
10367c478bd9Sstevel@tonic-gate   sEnd.n = 0;
10377c478bd9Sstevel@tonic-gate   n = sEnd.z - pBegin->z;
10387c478bd9Sstevel@tonic-gate   z = pBegin->z;
10397c478bd9Sstevel@tonic-gate   while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; }
10407c478bd9Sstevel@tonic-gate   sEnd.z = &z[n-1];
10417c478bd9Sstevel@tonic-gate   sEnd.n = 1;
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate   /* Use sqliteEndTable() to add the view to the SQLITE_MASTER table */
10447c478bd9Sstevel@tonic-gate   sqliteEndTable(pParse, &sEnd, 0);
10457c478bd9Sstevel@tonic-gate   return;
10467c478bd9Sstevel@tonic-gate }
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate /*
10497c478bd9Sstevel@tonic-gate ** The Table structure pTable is really a VIEW.  Fill in the names of
10507c478bd9Sstevel@tonic-gate ** the columns of the view in the pTable structure.  Return the number
10517c478bd9Sstevel@tonic-gate ** of errors.  If an error is seen leave an error message in pParse->zErrMsg.
10527c478bd9Sstevel@tonic-gate */
sqliteViewGetColumnNames(Parse * pParse,Table * pTable)10537c478bd9Sstevel@tonic-gate int sqliteViewGetColumnNames(Parse *pParse, Table *pTable){
10547c478bd9Sstevel@tonic-gate   ExprList *pEList;
10557c478bd9Sstevel@tonic-gate   Select *pSel;
10567c478bd9Sstevel@tonic-gate   Table *pSelTab;
10577c478bd9Sstevel@tonic-gate   int nErr = 0;
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate   assert( pTable );
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate   /* A positive nCol means the columns names for this view are
10627c478bd9Sstevel@tonic-gate   ** already known.
10637c478bd9Sstevel@tonic-gate   */
10647c478bd9Sstevel@tonic-gate   if( pTable->nCol>0 ) return 0;
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate   /* A negative nCol is a special marker meaning that we are currently
10677c478bd9Sstevel@tonic-gate   ** trying to compute the column names.  If we enter this routine with
10687c478bd9Sstevel@tonic-gate   ** a negative nCol, it means two or more views form a loop, like this:
10697c478bd9Sstevel@tonic-gate   **
10707c478bd9Sstevel@tonic-gate   **     CREATE VIEW one AS SELECT * FROM two;
10717c478bd9Sstevel@tonic-gate   **     CREATE VIEW two AS SELECT * FROM one;
10727c478bd9Sstevel@tonic-gate   **
10737c478bd9Sstevel@tonic-gate   ** Actually, this error is caught previously and so the following test
10747c478bd9Sstevel@tonic-gate   ** should always fail.  But we will leave it in place just to be safe.
10757c478bd9Sstevel@tonic-gate   */
10767c478bd9Sstevel@tonic-gate   if( pTable->nCol<0 ){
10777c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "view %s is circularly defined", pTable->zName);
10787c478bd9Sstevel@tonic-gate     return 1;
10797c478bd9Sstevel@tonic-gate   }
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate   /* If we get this far, it means we need to compute the table names.
10827c478bd9Sstevel@tonic-gate   */
10837c478bd9Sstevel@tonic-gate   assert( pTable->pSelect ); /* If nCol==0, then pTable must be a VIEW */
10847c478bd9Sstevel@tonic-gate   pSel = pTable->pSelect;
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate   /* Note that the call to sqliteResultSetOfSelect() will expand any
10877c478bd9Sstevel@tonic-gate   ** "*" elements in this list.  But we will need to restore the list
10887c478bd9Sstevel@tonic-gate   ** back to its original configuration afterwards, so we save a copy of
10897c478bd9Sstevel@tonic-gate   ** the original in pEList.
10907c478bd9Sstevel@tonic-gate   */
10917c478bd9Sstevel@tonic-gate   pEList = pSel->pEList;
10927c478bd9Sstevel@tonic-gate   pSel->pEList = sqliteExprListDup(pEList);
10937c478bd9Sstevel@tonic-gate   if( pSel->pEList==0 ){
10947c478bd9Sstevel@tonic-gate     pSel->pEList = pEList;
10957c478bd9Sstevel@tonic-gate     return 1;  /* Malloc failed */
10967c478bd9Sstevel@tonic-gate   }
10977c478bd9Sstevel@tonic-gate   pTable->nCol = -1;
10987c478bd9Sstevel@tonic-gate   pSelTab = sqliteResultSetOfSelect(pParse, 0, pSel);
10997c478bd9Sstevel@tonic-gate   if( pSelTab ){
11007c478bd9Sstevel@tonic-gate     assert( pTable->aCol==0 );
11017c478bd9Sstevel@tonic-gate     pTable->nCol = pSelTab->nCol;
11027c478bd9Sstevel@tonic-gate     pTable->aCol = pSelTab->aCol;
11037c478bd9Sstevel@tonic-gate     pSelTab->nCol = 0;
11047c478bd9Sstevel@tonic-gate     pSelTab->aCol = 0;
11057c478bd9Sstevel@tonic-gate     sqliteDeleteTable(0, pSelTab);
11067c478bd9Sstevel@tonic-gate     DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews);
11077c478bd9Sstevel@tonic-gate   }else{
11087c478bd9Sstevel@tonic-gate     pTable->nCol = 0;
11097c478bd9Sstevel@tonic-gate     nErr++;
11107c478bd9Sstevel@tonic-gate   }
11117c478bd9Sstevel@tonic-gate   sqliteSelectUnbind(pSel);
11127c478bd9Sstevel@tonic-gate   sqliteExprListDelete(pSel->pEList);
11137c478bd9Sstevel@tonic-gate   pSel->pEList = pEList;
1114*1da57d55SToomas Soome   return nErr;
11157c478bd9Sstevel@tonic-gate }
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate /*
11187c478bd9Sstevel@tonic-gate ** Clear the column names from the VIEW pTable.
11197c478bd9Sstevel@tonic-gate **
11207c478bd9Sstevel@tonic-gate ** This routine is called whenever any other table or view is modified.
11217c478bd9Sstevel@tonic-gate ** The view passed into this routine might depend directly or indirectly
11227c478bd9Sstevel@tonic-gate ** on the modified or deleted table so we need to clear the old column
11237c478bd9Sstevel@tonic-gate ** names so that they will be recomputed.
11247c478bd9Sstevel@tonic-gate */
sqliteViewResetColumnNames(Table * pTable)11257c478bd9Sstevel@tonic-gate static void sqliteViewResetColumnNames(Table *pTable){
11267c478bd9Sstevel@tonic-gate   int i;
11277c478bd9Sstevel@tonic-gate   Column *pCol;
11287c478bd9Sstevel@tonic-gate   assert( pTable!=0 && pTable->pSelect!=0 );
11297c478bd9Sstevel@tonic-gate   for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){
11307c478bd9Sstevel@tonic-gate     sqliteFree(pCol->zName);
11317c478bd9Sstevel@tonic-gate     sqliteFree(pCol->zDflt);
11327c478bd9Sstevel@tonic-gate     sqliteFree(pCol->zType);
11337c478bd9Sstevel@tonic-gate   }
11347c478bd9Sstevel@tonic-gate   sqliteFree(pTable->aCol);
11357c478bd9Sstevel@tonic-gate   pTable->aCol = 0;
11367c478bd9Sstevel@tonic-gate   pTable->nCol = 0;
11377c478bd9Sstevel@tonic-gate }
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate /*
11407c478bd9Sstevel@tonic-gate ** Clear the column names from every VIEW in database idx.
11417c478bd9Sstevel@tonic-gate */
sqliteViewResetAll(sqlite * db,int idx)11427c478bd9Sstevel@tonic-gate static void sqliteViewResetAll(sqlite *db, int idx){
11437c478bd9Sstevel@tonic-gate   HashElem *i;
11447c478bd9Sstevel@tonic-gate   if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
11457c478bd9Sstevel@tonic-gate   for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){
11467c478bd9Sstevel@tonic-gate     Table *pTab = sqliteHashData(i);
11477c478bd9Sstevel@tonic-gate     if( pTab->pSelect ){
11487c478bd9Sstevel@tonic-gate       sqliteViewResetColumnNames(pTab);
11497c478bd9Sstevel@tonic-gate     }
11507c478bd9Sstevel@tonic-gate   }
11517c478bd9Sstevel@tonic-gate   DbClearProperty(db, idx, DB_UnresetViews);
11527c478bd9Sstevel@tonic-gate }
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate /*
11557c478bd9Sstevel@tonic-gate ** Given a token, look up a table with that name.  If not found, leave
11567c478bd9Sstevel@tonic-gate ** an error for the parser to find and return NULL.
11577c478bd9Sstevel@tonic-gate */
sqliteTableFromToken(Parse * pParse,Token * pTok)11587c478bd9Sstevel@tonic-gate Table *sqliteTableFromToken(Parse *pParse, Token *pTok){
11597c478bd9Sstevel@tonic-gate   char *zName;
11607c478bd9Sstevel@tonic-gate   Table *pTab;
11617c478bd9Sstevel@tonic-gate   zName = sqliteTableNameFromToken(pTok);
11627c478bd9Sstevel@tonic-gate   if( zName==0 ) return 0;
11637c478bd9Sstevel@tonic-gate   pTab = sqliteFindTable(pParse->db, zName, 0);
11647c478bd9Sstevel@tonic-gate   sqliteFree(zName);
11657c478bd9Sstevel@tonic-gate   if( pTab==0 ){
11667c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "no such table: %T", pTok);
11677c478bd9Sstevel@tonic-gate   }
11687c478bd9Sstevel@tonic-gate   return pTab;
11697c478bd9Sstevel@tonic-gate }
11707c478bd9Sstevel@tonic-gate 
11717c478bd9Sstevel@tonic-gate /*
11727c478bd9Sstevel@tonic-gate ** This routine is called to do the work of a DROP TABLE statement.
11737c478bd9Sstevel@tonic-gate ** pName is the name of the table to be dropped.
11747c478bd9Sstevel@tonic-gate */
sqliteDropTable(Parse * pParse,Token * pName,int isView)11757c478bd9Sstevel@tonic-gate void sqliteDropTable(Parse *pParse, Token *pName, int isView){
11767c478bd9Sstevel@tonic-gate   Table *pTable;
11777c478bd9Sstevel@tonic-gate   Vdbe *v;
11787c478bd9Sstevel@tonic-gate   int base;
11797c478bd9Sstevel@tonic-gate   sqlite *db = pParse->db;
11807c478bd9Sstevel@tonic-gate   int iDb;
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate   if( pParse->nErr || sqlite_malloc_failed ) return;
11837c478bd9Sstevel@tonic-gate   pTable = sqliteTableFromToken(pParse, pName);
11847c478bd9Sstevel@tonic-gate   if( pTable==0 ) return;
11857c478bd9Sstevel@tonic-gate   iDb = pTable->iDb;
11867c478bd9Sstevel@tonic-gate   assert( iDb>=0 && iDb<db->nDb );
11877c478bd9Sstevel@tonic-gate #ifndef SQLITE_OMIT_AUTHORIZATION
11887c478bd9Sstevel@tonic-gate   {
11897c478bd9Sstevel@tonic-gate     int code;
11907c478bd9Sstevel@tonic-gate     const char *zTab = SCHEMA_TABLE(pTable->iDb);
11917c478bd9Sstevel@tonic-gate     const char *zDb = db->aDb[pTable->iDb].zName;
11927c478bd9Sstevel@tonic-gate     if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){
11937c478bd9Sstevel@tonic-gate       return;
11947c478bd9Sstevel@tonic-gate     }
11957c478bd9Sstevel@tonic-gate     if( isView ){
11967c478bd9Sstevel@tonic-gate       if( iDb==1 ){
11977c478bd9Sstevel@tonic-gate         code = SQLITE_DROP_TEMP_VIEW;
11987c478bd9Sstevel@tonic-gate       }else{
11997c478bd9Sstevel@tonic-gate         code = SQLITE_DROP_VIEW;
12007c478bd9Sstevel@tonic-gate       }
12017c478bd9Sstevel@tonic-gate     }else{
12027c478bd9Sstevel@tonic-gate       if( iDb==1 ){
12037c478bd9Sstevel@tonic-gate         code = SQLITE_DROP_TEMP_TABLE;
12047c478bd9Sstevel@tonic-gate       }else{
12057c478bd9Sstevel@tonic-gate         code = SQLITE_DROP_TABLE;
12067c478bd9Sstevel@tonic-gate       }
12077c478bd9Sstevel@tonic-gate     }
12087c478bd9Sstevel@tonic-gate     if( sqliteAuthCheck(pParse, code, pTable->zName, 0, zDb) ){
12097c478bd9Sstevel@tonic-gate       return;
12107c478bd9Sstevel@tonic-gate     }
12117c478bd9Sstevel@tonic-gate     if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTable->zName, 0, zDb) ){
12127c478bd9Sstevel@tonic-gate       return;
12137c478bd9Sstevel@tonic-gate     }
12147c478bd9Sstevel@tonic-gate   }
12157c478bd9Sstevel@tonic-gate #endif
12167c478bd9Sstevel@tonic-gate   if( pTable->readOnly ){
12177c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "table %s may not be dropped", pTable->zName);
12187c478bd9Sstevel@tonic-gate     pParse->nErr++;
12197c478bd9Sstevel@tonic-gate     return;
12207c478bd9Sstevel@tonic-gate   }
12217c478bd9Sstevel@tonic-gate   if( isView && pTable->pSelect==0 ){
12227c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "use DROP TABLE to delete table %s", pTable->zName);
12237c478bd9Sstevel@tonic-gate     return;
12247c478bd9Sstevel@tonic-gate   }
12257c478bd9Sstevel@tonic-gate   if( !isView && pTable->pSelect ){
12267c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "use DROP VIEW to delete view %s", pTable->zName);
12277c478bd9Sstevel@tonic-gate     return;
12287c478bd9Sstevel@tonic-gate   }
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate   /* Generate code to remove the table from the master table
12317c478bd9Sstevel@tonic-gate   ** on disk.
12327c478bd9Sstevel@tonic-gate   */
12337c478bd9Sstevel@tonic-gate   v = sqliteGetVdbe(pParse);
12347c478bd9Sstevel@tonic-gate   if( v ){
12357c478bd9Sstevel@tonic-gate     static VdbeOpList dropTable[] = {
12367c478bd9Sstevel@tonic-gate       { OP_Rewind,     0, ADDR(8),  0},
12377c478bd9Sstevel@tonic-gate       { OP_String,     0, 0,        0}, /* 1 */
12387c478bd9Sstevel@tonic-gate       { OP_MemStore,   1, 1,        0},
12397c478bd9Sstevel@tonic-gate       { OP_MemLoad,    1, 0,        0}, /* 3 */
12407c478bd9Sstevel@tonic-gate       { OP_Column,     0, 2,        0},
12417c478bd9Sstevel@tonic-gate       { OP_Ne,         0, ADDR(7),  0},
12427c478bd9Sstevel@tonic-gate       { OP_Delete,     0, 0,        0},
12437c478bd9Sstevel@tonic-gate       { OP_Next,       0, ADDR(3),  0}, /* 7 */
12447c478bd9Sstevel@tonic-gate     };
12457c478bd9Sstevel@tonic-gate     Index *pIdx;
12467c478bd9Sstevel@tonic-gate     Trigger *pTrigger;
12477c478bd9Sstevel@tonic-gate     sqliteBeginWriteOperation(pParse, 0, pTable->iDb);
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate     /* Drop all triggers associated with the table being dropped */
12507c478bd9Sstevel@tonic-gate     pTrigger = pTable->pTrigger;
12517c478bd9Sstevel@tonic-gate     while( pTrigger ){
12527c478bd9Sstevel@tonic-gate       assert( pTrigger->iDb==pTable->iDb || pTrigger->iDb==1 );
12537c478bd9Sstevel@tonic-gate       sqliteDropTriggerPtr(pParse, pTrigger, 1);
12547c478bd9Sstevel@tonic-gate       if( pParse->explain ){
12557c478bd9Sstevel@tonic-gate         pTrigger = pTrigger->pNext;
12567c478bd9Sstevel@tonic-gate       }else{
12577c478bd9Sstevel@tonic-gate         pTrigger = pTable->pTrigger;
12587c478bd9Sstevel@tonic-gate       }
12597c478bd9Sstevel@tonic-gate     }
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate     /* Drop all SQLITE_MASTER entries that refer to the table */
12627c478bd9Sstevel@tonic-gate     sqliteOpenMasterTable(v, pTable->iDb);
12637c478bd9Sstevel@tonic-gate     base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
12647c478bd9Sstevel@tonic-gate     sqliteVdbeChangeP3(v, base+1, pTable->zName, 0);
12657c478bd9Sstevel@tonic-gate 
12667c478bd9Sstevel@tonic-gate     /* Drop all SQLITE_TEMP_MASTER entries that refer to the table */
12677c478bd9Sstevel@tonic-gate     if( pTable->iDb!=1 ){
12687c478bd9Sstevel@tonic-gate       sqliteOpenMasterTable(v, 1);
12697c478bd9Sstevel@tonic-gate       base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
12707c478bd9Sstevel@tonic-gate       sqliteVdbeChangeP3(v, base+1, pTable->zName, 0);
12717c478bd9Sstevel@tonic-gate     }
12727c478bd9Sstevel@tonic-gate 
12737c478bd9Sstevel@tonic-gate     if( pTable->iDb==0 ){
12747c478bd9Sstevel@tonic-gate       sqliteChangeCookie(db, v);
12757c478bd9Sstevel@tonic-gate     }
12767c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_Close, 0, 0);
12777c478bd9Sstevel@tonic-gate     if( !isView ){
12787c478bd9Sstevel@tonic-gate       sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->iDb);
12797c478bd9Sstevel@tonic-gate       for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
12807c478bd9Sstevel@tonic-gate         sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb);
12817c478bd9Sstevel@tonic-gate       }
12827c478bd9Sstevel@tonic-gate     }
12837c478bd9Sstevel@tonic-gate     sqliteEndWriteOperation(pParse);
12847c478bd9Sstevel@tonic-gate   }
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate   /* Delete the in-memory description of the table.
12877c478bd9Sstevel@tonic-gate   **
12887c478bd9Sstevel@tonic-gate   ** Exception: if the SQL statement began with the EXPLAIN keyword,
12897c478bd9Sstevel@tonic-gate   ** then no changes should be made.
12907c478bd9Sstevel@tonic-gate   */
12917c478bd9Sstevel@tonic-gate   if( !pParse->explain ){
12927c478bd9Sstevel@tonic-gate     sqliteUnlinkAndDeleteTable(db, pTable);
12937c478bd9Sstevel@tonic-gate     db->flags |= SQLITE_InternChanges;
12947c478bd9Sstevel@tonic-gate   }
12957c478bd9Sstevel@tonic-gate   sqliteViewResetAll(db, iDb);
12967c478bd9Sstevel@tonic-gate }
12977c478bd9Sstevel@tonic-gate 
12987c478bd9Sstevel@tonic-gate /*
12997c478bd9Sstevel@tonic-gate ** This routine constructs a P3 string suitable for an OP_MakeIdxKey
13007c478bd9Sstevel@tonic-gate ** opcode and adds that P3 string to the most recently inserted instruction
13017c478bd9Sstevel@tonic-gate ** in the virtual machine.  The P3 string consists of a single character
13027c478bd9Sstevel@tonic-gate ** for each column in the index pIdx of table pTab.  If the column uses
13037c478bd9Sstevel@tonic-gate ** a numeric sort order, then the P3 string character corresponding to
13047c478bd9Sstevel@tonic-gate ** that column is 'n'.  If the column uses a text sort order, then the
13057c478bd9Sstevel@tonic-gate ** P3 string is 't'.  See the OP_MakeIdxKey opcode documentation for
13067c478bd9Sstevel@tonic-gate ** additional information.  See also the sqliteAddKeyType() routine.
13077c478bd9Sstevel@tonic-gate */
sqliteAddIdxKeyType(Vdbe * v,Index * pIdx)13087c478bd9Sstevel@tonic-gate void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){
13097c478bd9Sstevel@tonic-gate   char *zType;
13107c478bd9Sstevel@tonic-gate   Table *pTab;
13117c478bd9Sstevel@tonic-gate   int i, n;
13127c478bd9Sstevel@tonic-gate   assert( pIdx!=0 && pIdx->pTable!=0 );
13137c478bd9Sstevel@tonic-gate   pTab = pIdx->pTable;
13147c478bd9Sstevel@tonic-gate   n = pIdx->nColumn;
13157c478bd9Sstevel@tonic-gate   zType = sqliteMallocRaw( n+1 );
13167c478bd9Sstevel@tonic-gate   if( zType==0 ) return;
13177c478bd9Sstevel@tonic-gate   for(i=0; i<n; i++){
13187c478bd9Sstevel@tonic-gate     int iCol = pIdx->aiColumn[i];
13197c478bd9Sstevel@tonic-gate     assert( iCol>=0 && iCol<pTab->nCol );
13207c478bd9Sstevel@tonic-gate     if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){
13217c478bd9Sstevel@tonic-gate       zType[i] = 't';
13227c478bd9Sstevel@tonic-gate     }else{
13237c478bd9Sstevel@tonic-gate       zType[i] = 'n';
13247c478bd9Sstevel@tonic-gate     }
13257c478bd9Sstevel@tonic-gate   }
13267c478bd9Sstevel@tonic-gate   zType[n] = 0;
13277c478bd9Sstevel@tonic-gate   sqliteVdbeChangeP3(v, -1, zType, n);
13287c478bd9Sstevel@tonic-gate   sqliteFree(zType);
13297c478bd9Sstevel@tonic-gate }
13307c478bd9Sstevel@tonic-gate 
13317c478bd9Sstevel@tonic-gate /*
13327c478bd9Sstevel@tonic-gate ** This routine is called to create a new foreign key on the table
13337c478bd9Sstevel@tonic-gate ** currently under construction.  pFromCol determines which columns
13347c478bd9Sstevel@tonic-gate ** in the current table point to the foreign key.  If pFromCol==0 then
13357c478bd9Sstevel@tonic-gate ** connect the key to the last column inserted.  pTo is the name of
13367c478bd9Sstevel@tonic-gate ** the table referred to.  pToCol is a list of tables in the other
13377c478bd9Sstevel@tonic-gate ** pTo table that the foreign key points to.  flags contains all
13387c478bd9Sstevel@tonic-gate ** information about the conflict resolution algorithms specified
13397c478bd9Sstevel@tonic-gate ** in the ON DELETE, ON UPDATE and ON INSERT clauses.
13407c478bd9Sstevel@tonic-gate **
13417c478bd9Sstevel@tonic-gate ** An FKey structure is created and added to the table currently
13427c478bd9Sstevel@tonic-gate ** under construction in the pParse->pNewTable field.  The new FKey
13437c478bd9Sstevel@tonic-gate ** is not linked into db->aFKey at this point - that does not happen
13447c478bd9Sstevel@tonic-gate ** until sqliteEndTable().
13457c478bd9Sstevel@tonic-gate **
13467c478bd9Sstevel@tonic-gate ** The foreign key is set for IMMEDIATE processing.  A subsequent call
13477c478bd9Sstevel@tonic-gate ** to sqliteDeferForeignKey() might change this to DEFERRED.
13487c478bd9Sstevel@tonic-gate */
sqliteCreateForeignKey(Parse * pParse,IdList * pFromCol,Token * pTo,IdList * pToCol,int flags)13497c478bd9Sstevel@tonic-gate void sqliteCreateForeignKey(
13507c478bd9Sstevel@tonic-gate   Parse *pParse,       /* Parsing context */
13517c478bd9Sstevel@tonic-gate   IdList *pFromCol,    /* Columns in this table that point to other table */
13527c478bd9Sstevel@tonic-gate   Token *pTo,          /* Name of the other table */
13537c478bd9Sstevel@tonic-gate   IdList *pToCol,      /* Columns in the other table */
13547c478bd9Sstevel@tonic-gate   int flags            /* Conflict resolution algorithms. */
13557c478bd9Sstevel@tonic-gate ){
13567c478bd9Sstevel@tonic-gate   Table *p = pParse->pNewTable;
13577c478bd9Sstevel@tonic-gate   int nByte;
13587c478bd9Sstevel@tonic-gate   int i;
13597c478bd9Sstevel@tonic-gate   int nCol;
13607c478bd9Sstevel@tonic-gate   char *z;
13617c478bd9Sstevel@tonic-gate   FKey *pFKey = 0;
13627c478bd9Sstevel@tonic-gate 
13637c478bd9Sstevel@tonic-gate   assert( pTo!=0 );
13647c478bd9Sstevel@tonic-gate   if( p==0 || pParse->nErr ) goto fk_end;
13657c478bd9Sstevel@tonic-gate   if( pFromCol==0 ){
13667c478bd9Sstevel@tonic-gate     int iCol = p->nCol-1;
13677c478bd9Sstevel@tonic-gate     if( iCol<0 ) goto fk_end;
13687c478bd9Sstevel@tonic-gate     if( pToCol && pToCol->nId!=1 ){
13697c478bd9Sstevel@tonic-gate       sqliteErrorMsg(pParse, "foreign key on %s"
13707c478bd9Sstevel@tonic-gate          " should reference only one column of table %T",
13717c478bd9Sstevel@tonic-gate          p->aCol[iCol].zName, pTo);
13727c478bd9Sstevel@tonic-gate       goto fk_end;
13737c478bd9Sstevel@tonic-gate     }
13747c478bd9Sstevel@tonic-gate     nCol = 1;
13757c478bd9Sstevel@tonic-gate   }else if( pToCol && pToCol->nId!=pFromCol->nId ){
13767c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse,
13777c478bd9Sstevel@tonic-gate         "number of columns in foreign key does not match the number of "
13787c478bd9Sstevel@tonic-gate         "columns in the referenced table");
13797c478bd9Sstevel@tonic-gate     goto fk_end;
13807c478bd9Sstevel@tonic-gate   }else{
13817c478bd9Sstevel@tonic-gate     nCol = pFromCol->nId;
13827c478bd9Sstevel@tonic-gate   }
13837c478bd9Sstevel@tonic-gate   nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1;
13847c478bd9Sstevel@tonic-gate   if( pToCol ){
13857c478bd9Sstevel@tonic-gate     for(i=0; i<pToCol->nId; i++){
13867c478bd9Sstevel@tonic-gate       nByte += strlen(pToCol->a[i].zName) + 1;
13877c478bd9Sstevel@tonic-gate     }
13887c478bd9Sstevel@tonic-gate   }
13897c478bd9Sstevel@tonic-gate   pFKey = sqliteMalloc( nByte );
13907c478bd9Sstevel@tonic-gate   if( pFKey==0 ) goto fk_end;
13917c478bd9Sstevel@tonic-gate   pFKey->pFrom = p;
13927c478bd9Sstevel@tonic-gate   pFKey->pNextFrom = p->pFKey;
13937c478bd9Sstevel@tonic-gate   z = (char*)&pFKey[1];
13947c478bd9Sstevel@tonic-gate   pFKey->aCol = (struct sColMap*)z;
13957c478bd9Sstevel@tonic-gate   z += sizeof(struct sColMap)*nCol;
13967c478bd9Sstevel@tonic-gate   pFKey->zTo = z;
13977c478bd9Sstevel@tonic-gate   memcpy(z, pTo->z, pTo->n);
13987c478bd9Sstevel@tonic-gate   z[pTo->n] = 0;
13997c478bd9Sstevel@tonic-gate   z += pTo->n+1;
14007c478bd9Sstevel@tonic-gate   pFKey->pNextTo = 0;
14017c478bd9Sstevel@tonic-gate   pFKey->nCol = nCol;
14027c478bd9Sstevel@tonic-gate   if( pFromCol==0 ){
14037c478bd9Sstevel@tonic-gate     pFKey->aCol[0].iFrom = p->nCol-1;
14047c478bd9Sstevel@tonic-gate   }else{
14057c478bd9Sstevel@tonic-gate     for(i=0; i<nCol; i++){
14067c478bd9Sstevel@tonic-gate       int j;
14077c478bd9Sstevel@tonic-gate       for(j=0; j<p->nCol; j++){
14087c478bd9Sstevel@tonic-gate         if( sqliteStrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){
14097c478bd9Sstevel@tonic-gate           pFKey->aCol[i].iFrom = j;
14107c478bd9Sstevel@tonic-gate           break;
14117c478bd9Sstevel@tonic-gate         }
14127c478bd9Sstevel@tonic-gate       }
14137c478bd9Sstevel@tonic-gate       if( j>=p->nCol ){
1414*1da57d55SToomas Soome         sqliteErrorMsg(pParse,
1415*1da57d55SToomas Soome           "unknown column \"%s\" in foreign key definition",
14167c478bd9Sstevel@tonic-gate           pFromCol->a[i].zName);
14177c478bd9Sstevel@tonic-gate         goto fk_end;
14187c478bd9Sstevel@tonic-gate       }
14197c478bd9Sstevel@tonic-gate     }
14207c478bd9Sstevel@tonic-gate   }
14217c478bd9Sstevel@tonic-gate   if( pToCol ){
14227c478bd9Sstevel@tonic-gate     for(i=0; i<nCol; i++){
14237c478bd9Sstevel@tonic-gate       int n = strlen(pToCol->a[i].zName);
14247c478bd9Sstevel@tonic-gate       pFKey->aCol[i].zCol = z;
14257c478bd9Sstevel@tonic-gate       memcpy(z, pToCol->a[i].zName, n);
14267c478bd9Sstevel@tonic-gate       z[n] = 0;
14277c478bd9Sstevel@tonic-gate       z += n+1;
14287c478bd9Sstevel@tonic-gate     }
14297c478bd9Sstevel@tonic-gate   }
14307c478bd9Sstevel@tonic-gate   pFKey->isDeferred = 0;
14317c478bd9Sstevel@tonic-gate   pFKey->deleteConf = flags & 0xff;
14327c478bd9Sstevel@tonic-gate   pFKey->updateConf = (flags >> 8 ) & 0xff;
14337c478bd9Sstevel@tonic-gate   pFKey->insertConf = (flags >> 16 ) & 0xff;
14347c478bd9Sstevel@tonic-gate 
14357c478bd9Sstevel@tonic-gate   /* Link the foreign key to the table as the last step.
14367c478bd9Sstevel@tonic-gate   */
14377c478bd9Sstevel@tonic-gate   p->pFKey = pFKey;
14387c478bd9Sstevel@tonic-gate   pFKey = 0;
14397c478bd9Sstevel@tonic-gate 
14407c478bd9Sstevel@tonic-gate fk_end:
14417c478bd9Sstevel@tonic-gate   sqliteFree(pFKey);
14427c478bd9Sstevel@tonic-gate   sqliteIdListDelete(pFromCol);
14437c478bd9Sstevel@tonic-gate   sqliteIdListDelete(pToCol);
14447c478bd9Sstevel@tonic-gate }
14457c478bd9Sstevel@tonic-gate 
14467c478bd9Sstevel@tonic-gate /*
14477c478bd9Sstevel@tonic-gate ** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED
14487c478bd9Sstevel@tonic-gate ** clause is seen as part of a foreign key definition.  The isDeferred
14497c478bd9Sstevel@tonic-gate ** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE.
14507c478bd9Sstevel@tonic-gate ** The behavior of the most recently created foreign key is adjusted
14517c478bd9Sstevel@tonic-gate ** accordingly.
14527c478bd9Sstevel@tonic-gate */
sqliteDeferForeignKey(Parse * pParse,int isDeferred)14537c478bd9Sstevel@tonic-gate void sqliteDeferForeignKey(Parse *pParse, int isDeferred){
14547c478bd9Sstevel@tonic-gate   Table *pTab;
14557c478bd9Sstevel@tonic-gate   FKey *pFKey;
14567c478bd9Sstevel@tonic-gate   if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
14577c478bd9Sstevel@tonic-gate   pFKey->isDeferred = isDeferred;
14587c478bd9Sstevel@tonic-gate }
14597c478bd9Sstevel@tonic-gate 
14607c478bd9Sstevel@tonic-gate /*
1461*1da57d55SToomas Soome ** Create a new index for an SQL table.  pIndex is the name of the index
1462*1da57d55SToomas Soome ** and pTable is the name of the table that is to be indexed.  Both will
14637c478bd9Sstevel@tonic-gate ** be NULL for a primary key or an index that is created to satisfy a
14647c478bd9Sstevel@tonic-gate ** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable
14657c478bd9Sstevel@tonic-gate ** as the table to be indexed.  pParse->pNewTable is a table that is
14667c478bd9Sstevel@tonic-gate ** currently being constructed by a CREATE TABLE statement.
14677c478bd9Sstevel@tonic-gate **
14687c478bd9Sstevel@tonic-gate ** pList is a list of columns to be indexed.  pList will be NULL if this
14697c478bd9Sstevel@tonic-gate ** is a primary key or unique-constraint on the most recent column added
1470*1da57d55SToomas Soome ** to the table currently under construction.
14717c478bd9Sstevel@tonic-gate */
sqliteCreateIndex(Parse * pParse,Token * pName,SrcList * pTable,IdList * pList,int onError,Token * pStart,Token * pEnd)14727c478bd9Sstevel@tonic-gate void sqliteCreateIndex(
14737c478bd9Sstevel@tonic-gate   Parse *pParse,   /* All information about this parse */
14747c478bd9Sstevel@tonic-gate   Token *pName,    /* Name of the index.  May be NULL */
14757c478bd9Sstevel@tonic-gate   SrcList *pTable, /* Name of the table to index.  Use pParse->pNewTable if 0 */
14767c478bd9Sstevel@tonic-gate   IdList *pList,   /* A list of columns to be indexed */
14777c478bd9Sstevel@tonic-gate   int onError,     /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
14787c478bd9Sstevel@tonic-gate   Token *pStart,   /* The CREATE token that begins a CREATE TABLE statement */
14797c478bd9Sstevel@tonic-gate   Token *pEnd      /* The ")" that closes the CREATE INDEX statement */
14807c478bd9Sstevel@tonic-gate ){
14817c478bd9Sstevel@tonic-gate   Table *pTab;     /* Table to be indexed */
14827c478bd9Sstevel@tonic-gate   Index *pIndex;   /* The index to be created */
14837c478bd9Sstevel@tonic-gate   char *zName = 0;
14847c478bd9Sstevel@tonic-gate   int i, j;
14857c478bd9Sstevel@tonic-gate   Token nullId;    /* Fake token for an empty ID list */
14867c478bd9Sstevel@tonic-gate   DbFixer sFix;    /* For assigning database names to pTable */
14877c478bd9Sstevel@tonic-gate   int isTemp;      /* True for a temporary index */
14887c478bd9Sstevel@tonic-gate   sqlite *db = pParse->db;
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate   if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;
1491*1da57d55SToomas Soome   if( db->init.busy
14927c478bd9Sstevel@tonic-gate      && sqliteFixInit(&sFix, pParse, db->init.iDb, "index", pName)
14937c478bd9Sstevel@tonic-gate      && sqliteFixSrcList(&sFix, pTable)
14947c478bd9Sstevel@tonic-gate   ){
14957c478bd9Sstevel@tonic-gate     goto exit_create_index;
14967c478bd9Sstevel@tonic-gate   }
14977c478bd9Sstevel@tonic-gate 
14987c478bd9Sstevel@tonic-gate   /*
14997c478bd9Sstevel@tonic-gate   ** Find the table that is to be indexed.  Return early if not found.
15007c478bd9Sstevel@tonic-gate   */
15017c478bd9Sstevel@tonic-gate   if( pTable!=0 ){
15027c478bd9Sstevel@tonic-gate     assert( pName!=0 );
15037c478bd9Sstevel@tonic-gate     assert( pTable->nSrc==1 );
15047c478bd9Sstevel@tonic-gate     pTab =  sqliteSrcListLookup(pParse, pTable);
15057c478bd9Sstevel@tonic-gate   }else{
15067c478bd9Sstevel@tonic-gate     assert( pName==0 );
15077c478bd9Sstevel@tonic-gate     pTab =  pParse->pNewTable;
15087c478bd9Sstevel@tonic-gate   }
15097c478bd9Sstevel@tonic-gate   if( pTab==0 || pParse->nErr ) goto exit_create_index;
15107c478bd9Sstevel@tonic-gate   if( pTab->readOnly ){
15117c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
15127c478bd9Sstevel@tonic-gate     goto exit_create_index;
15137c478bd9Sstevel@tonic-gate   }
15147c478bd9Sstevel@tonic-gate   if( pTab->iDb>=2 && db->init.busy==0 ){
15157c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "table %s may not have indices added", pTab->zName);
15167c478bd9Sstevel@tonic-gate     goto exit_create_index;
15177c478bd9Sstevel@tonic-gate   }
15187c478bd9Sstevel@tonic-gate   if( pTab->pSelect ){
15197c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "views may not be indexed");
15207c478bd9Sstevel@tonic-gate     goto exit_create_index;
15217c478bd9Sstevel@tonic-gate   }
15227c478bd9Sstevel@tonic-gate   isTemp = pTab->iDb==1;
15237c478bd9Sstevel@tonic-gate 
15247c478bd9Sstevel@tonic-gate   /*
15257c478bd9Sstevel@tonic-gate   ** Find the name of the index.  Make sure there is not already another
1526*1da57d55SToomas Soome   ** index or table with the same name.
15277c478bd9Sstevel@tonic-gate   **
15287c478bd9Sstevel@tonic-gate   ** Exception:  If we are reading the names of permanent indices from the
15297c478bd9Sstevel@tonic-gate   ** sqlite_master table (because some other process changed the schema) and
15307c478bd9Sstevel@tonic-gate   ** one of the index names collides with the name of a temporary table or
15317c478bd9Sstevel@tonic-gate   ** index, then we will continue to process this index.
15327c478bd9Sstevel@tonic-gate   **
15337c478bd9Sstevel@tonic-gate   ** If pName==0 it means that we are
15347c478bd9Sstevel@tonic-gate   ** dealing with a primary key or UNIQUE constraint.  We have to invent our
15357c478bd9Sstevel@tonic-gate   ** own name.
15367c478bd9Sstevel@tonic-gate   */
15377c478bd9Sstevel@tonic-gate   if( pName && !db->init.busy ){
15387c478bd9Sstevel@tonic-gate     Index *pISameName;    /* Another index with the same name */
15397c478bd9Sstevel@tonic-gate     Table *pTSameName;    /* A table with same name as the index */
15407c478bd9Sstevel@tonic-gate     zName = sqliteTableNameFromToken(pName);
15417c478bd9Sstevel@tonic-gate     if( zName==0 ) goto exit_create_index;
15427c478bd9Sstevel@tonic-gate     if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
15437c478bd9Sstevel@tonic-gate       sqliteErrorMsg(pParse, "index %s already exists", zName);
15447c478bd9Sstevel@tonic-gate       goto exit_create_index;
15457c478bd9Sstevel@tonic-gate     }
15467c478bd9Sstevel@tonic-gate     if( (pTSameName = sqliteFindTable(db, zName, 0))!=0 ){
15477c478bd9Sstevel@tonic-gate       sqliteErrorMsg(pParse, "there is already a table named %s", zName);
15487c478bd9Sstevel@tonic-gate       goto exit_create_index;
15497c478bd9Sstevel@tonic-gate     }
15507c478bd9Sstevel@tonic-gate   }else if( pName==0 ){
15517c478bd9Sstevel@tonic-gate     char zBuf[30];
15527c478bd9Sstevel@tonic-gate     int n;
15537c478bd9Sstevel@tonic-gate     Index *pLoop;
15547c478bd9Sstevel@tonic-gate     for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
15557c478bd9Sstevel@tonic-gate     sprintf(zBuf,"%d)",n);
15567c478bd9Sstevel@tonic-gate     zName = 0;
15577c478bd9Sstevel@tonic-gate     sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0);
15587c478bd9Sstevel@tonic-gate     if( zName==0 ) goto exit_create_index;
15597c478bd9Sstevel@tonic-gate   }else{
15607c478bd9Sstevel@tonic-gate     zName = sqliteStrNDup(pName->z, pName->n);
15617c478bd9Sstevel@tonic-gate   }
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate   /* Check for authorization to create an index.
15647c478bd9Sstevel@tonic-gate   */
15657c478bd9Sstevel@tonic-gate #ifndef SQLITE_OMIT_AUTHORIZATION
15667c478bd9Sstevel@tonic-gate   {
15677c478bd9Sstevel@tonic-gate     const char *zDb = db->aDb[pTab->iDb].zName;
15687c478bd9Sstevel@tonic-gate 
15697c478bd9Sstevel@tonic-gate     assert( pTab->iDb==db->init.iDb || isTemp );
15707c478bd9Sstevel@tonic-gate     if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
15717c478bd9Sstevel@tonic-gate       goto exit_create_index;
15727c478bd9Sstevel@tonic-gate     }
15737c478bd9Sstevel@tonic-gate     i = SQLITE_CREATE_INDEX;
15747c478bd9Sstevel@tonic-gate     if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
15757c478bd9Sstevel@tonic-gate     if( sqliteAuthCheck(pParse, i, zName, pTab->zName, zDb) ){
15767c478bd9Sstevel@tonic-gate       goto exit_create_index;
15777c478bd9Sstevel@tonic-gate     }
15787c478bd9Sstevel@tonic-gate   }
15797c478bd9Sstevel@tonic-gate #endif
15807c478bd9Sstevel@tonic-gate 
15817c478bd9Sstevel@tonic-gate   /* If pList==0, it means this routine was called to make a primary
15827c478bd9Sstevel@tonic-gate   ** key out of the last column added to the table under construction.
15837c478bd9Sstevel@tonic-gate   ** So create a fake list to simulate this.
15847c478bd9Sstevel@tonic-gate   */
15857c478bd9Sstevel@tonic-gate   if( pList==0 ){
15867c478bd9Sstevel@tonic-gate     nullId.z = pTab->aCol[pTab->nCol-1].zName;
15877c478bd9Sstevel@tonic-gate     nullId.n = strlen(nullId.z);
15887c478bd9Sstevel@tonic-gate     pList = sqliteIdListAppend(0, &nullId);
15897c478bd9Sstevel@tonic-gate     if( pList==0 ) goto exit_create_index;
15907c478bd9Sstevel@tonic-gate   }
15917c478bd9Sstevel@tonic-gate 
1592*1da57d55SToomas Soome   /*
1593*1da57d55SToomas Soome   ** Allocate the index structure.
15947c478bd9Sstevel@tonic-gate   */
15957c478bd9Sstevel@tonic-gate   pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 +
15967c478bd9Sstevel@tonic-gate                         sizeof(int)*pList->nId );
15977c478bd9Sstevel@tonic-gate   if( pIndex==0 ) goto exit_create_index;
15987c478bd9Sstevel@tonic-gate   pIndex->aiColumn = (int*)&pIndex[1];
15997c478bd9Sstevel@tonic-gate   pIndex->zName = (char*)&pIndex->aiColumn[pList->nId];
16007c478bd9Sstevel@tonic-gate   strcpy(pIndex->zName, zName);
16017c478bd9Sstevel@tonic-gate   pIndex->pTable = pTab;
16027c478bd9Sstevel@tonic-gate   pIndex->nColumn = pList->nId;
16037c478bd9Sstevel@tonic-gate   pIndex->onError = onError;
16047c478bd9Sstevel@tonic-gate   pIndex->autoIndex = pName==0;
16057c478bd9Sstevel@tonic-gate   pIndex->iDb = isTemp ? 1 : db->init.iDb;
16067c478bd9Sstevel@tonic-gate 
16077c478bd9Sstevel@tonic-gate   /* Scan the names of the columns of the table to be indexed and
16087c478bd9Sstevel@tonic-gate   ** load the column indices into the Index structure.  Report an error
16097c478bd9Sstevel@tonic-gate   ** if any column is not found.
16107c478bd9Sstevel@tonic-gate   */
16117c478bd9Sstevel@tonic-gate   for(i=0; i<pList->nId; i++){
16127c478bd9Sstevel@tonic-gate     for(j=0; j<pTab->nCol; j++){
16137c478bd9Sstevel@tonic-gate       if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break;
16147c478bd9Sstevel@tonic-gate     }
16157c478bd9Sstevel@tonic-gate     if( j>=pTab->nCol ){
16167c478bd9Sstevel@tonic-gate       sqliteErrorMsg(pParse, "table %s has no column named %s",
16177c478bd9Sstevel@tonic-gate         pTab->zName, pList->a[i].zName);
16187c478bd9Sstevel@tonic-gate       sqliteFree(pIndex);
16197c478bd9Sstevel@tonic-gate       goto exit_create_index;
16207c478bd9Sstevel@tonic-gate     }
16217c478bd9Sstevel@tonic-gate     pIndex->aiColumn[i] = j;
16227c478bd9Sstevel@tonic-gate   }
16237c478bd9Sstevel@tonic-gate 
16247c478bd9Sstevel@tonic-gate   /* Link the new Index structure to its table and to the other
1625*1da57d55SToomas Soome   ** in-memory database structures.
16267c478bd9Sstevel@tonic-gate   */
16277c478bd9Sstevel@tonic-gate   if( !pParse->explain ){
16287c478bd9Sstevel@tonic-gate     Index *p;
1629*1da57d55SToomas Soome     p = sqliteHashInsert(&db->aDb[pIndex->iDb].idxHash,
16307c478bd9Sstevel@tonic-gate                          pIndex->zName, strlen(pIndex->zName)+1, pIndex);
16317c478bd9Sstevel@tonic-gate     if( p ){
16327c478bd9Sstevel@tonic-gate       assert( p==pIndex );  /* Malloc must have failed */
16337c478bd9Sstevel@tonic-gate       sqliteFree(pIndex);
16347c478bd9Sstevel@tonic-gate       goto exit_create_index;
16357c478bd9Sstevel@tonic-gate     }
16367c478bd9Sstevel@tonic-gate     db->flags |= SQLITE_InternChanges;
16377c478bd9Sstevel@tonic-gate   }
16387c478bd9Sstevel@tonic-gate 
16397c478bd9Sstevel@tonic-gate   /* When adding an index to the list of indices for a table, make
16407c478bd9Sstevel@tonic-gate   ** sure all indices labeled OE_Replace come after all those labeled
16417c478bd9Sstevel@tonic-gate   ** OE_Ignore.  This is necessary for the correct operation of UPDATE
16427c478bd9Sstevel@tonic-gate   ** and INSERT.
16437c478bd9Sstevel@tonic-gate   */
16447c478bd9Sstevel@tonic-gate   if( onError!=OE_Replace || pTab->pIndex==0
16457c478bd9Sstevel@tonic-gate        || pTab->pIndex->onError==OE_Replace){
16467c478bd9Sstevel@tonic-gate     pIndex->pNext = pTab->pIndex;
16477c478bd9Sstevel@tonic-gate     pTab->pIndex = pIndex;
16487c478bd9Sstevel@tonic-gate   }else{
16497c478bd9Sstevel@tonic-gate     Index *pOther = pTab->pIndex;
16507c478bd9Sstevel@tonic-gate     while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
16517c478bd9Sstevel@tonic-gate       pOther = pOther->pNext;
16527c478bd9Sstevel@tonic-gate     }
16537c478bd9Sstevel@tonic-gate     pIndex->pNext = pOther->pNext;
16547c478bd9Sstevel@tonic-gate     pOther->pNext = pIndex;
16557c478bd9Sstevel@tonic-gate   }
16567c478bd9Sstevel@tonic-gate 
16577c478bd9Sstevel@tonic-gate   /* If the db->init.busy is 1 it means we are reading the SQL off the
16587c478bd9Sstevel@tonic-gate   ** "sqlite_master" table on the disk.  So do not write to the disk
16597c478bd9Sstevel@tonic-gate   ** again.  Extract the table number from the db->init.newTnum field.
16607c478bd9Sstevel@tonic-gate   */
16617c478bd9Sstevel@tonic-gate   if( db->init.busy && pTable!=0 ){
16627c478bd9Sstevel@tonic-gate     pIndex->tnum = db->init.newTnum;
16637c478bd9Sstevel@tonic-gate   }
16647c478bd9Sstevel@tonic-gate 
16657c478bd9Sstevel@tonic-gate   /* If the db->init.busy is 0 then create the index on disk.  This
16667c478bd9Sstevel@tonic-gate   ** involves writing the index into the master table and filling in the
16677c478bd9Sstevel@tonic-gate   ** index with the current table contents.
16687c478bd9Sstevel@tonic-gate   **
1669*1da57d55SToomas Soome   ** The db->init.busy is 0 when the user first enters a CREATE INDEX
1670*1da57d55SToomas Soome   ** command.  db->init.busy is 1 when a database is opened and
16717c478bd9Sstevel@tonic-gate   ** CREATE INDEX statements are read out of the master table.  In
16727c478bd9Sstevel@tonic-gate   ** the latter case the index already exists on disk, which is why
16737c478bd9Sstevel@tonic-gate   ** we don't want to recreate it.
16747c478bd9Sstevel@tonic-gate   **
16757c478bd9Sstevel@tonic-gate   ** If pTable==0 it means this index is generated as a primary key
16767c478bd9Sstevel@tonic-gate   ** or UNIQUE constraint of a CREATE TABLE statement.  Since the table
16777c478bd9Sstevel@tonic-gate   ** has just been created, it contains no data and the index initialization
16787c478bd9Sstevel@tonic-gate   ** step can be skipped.
16797c478bd9Sstevel@tonic-gate   */
16807c478bd9Sstevel@tonic-gate   else if( db->init.busy==0 ){
16817c478bd9Sstevel@tonic-gate     int n;
16827c478bd9Sstevel@tonic-gate     Vdbe *v;
16837c478bd9Sstevel@tonic-gate     int lbl1, lbl2;
16847c478bd9Sstevel@tonic-gate     int i;
16857c478bd9Sstevel@tonic-gate     int addr;
16867c478bd9Sstevel@tonic-gate 
16877c478bd9Sstevel@tonic-gate     v = sqliteGetVdbe(pParse);
16887c478bd9Sstevel@tonic-gate     if( v==0 ) goto exit_create_index;
16897c478bd9Sstevel@tonic-gate     if( pTable!=0 ){
16907c478bd9Sstevel@tonic-gate       sqliteBeginWriteOperation(pParse, 0, isTemp);
16917c478bd9Sstevel@tonic-gate       sqliteOpenMasterTable(v, isTemp);
16927c478bd9Sstevel@tonic-gate     }
16937c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
16947c478bd9Sstevel@tonic-gate     sqliteVdbeOp3(v, OP_String, 0, 0, "index", P3_STATIC);
16957c478bd9Sstevel@tonic-gate     sqliteVdbeOp3(v, OP_String, 0, 0, pIndex->zName, 0);
16967c478bd9Sstevel@tonic-gate     sqliteVdbeOp3(v, OP_String, 0, 0, pTab->zName, 0);
16977c478bd9Sstevel@tonic-gate     sqliteVdbeOp3(v, OP_CreateIndex, 0, isTemp,(char*)&pIndex->tnum,P3_POINTER);
16987c478bd9Sstevel@tonic-gate     pIndex->tnum = 0;
16997c478bd9Sstevel@tonic-gate     if( pTable ){
17007c478bd9Sstevel@tonic-gate       sqliteVdbeCode(v,
17017c478bd9Sstevel@tonic-gate           OP_Dup,       0,      0,
17027c478bd9Sstevel@tonic-gate           OP_Integer,   isTemp, 0,
17037c478bd9Sstevel@tonic-gate           OP_OpenWrite, 1,      0,
17047c478bd9Sstevel@tonic-gate       0);
17057c478bd9Sstevel@tonic-gate     }
17067c478bd9Sstevel@tonic-gate     addr = sqliteVdbeAddOp(v, OP_String, 0, 0);
17077c478bd9Sstevel@tonic-gate     if( pStart && pEnd ){
17087c478bd9Sstevel@tonic-gate       n = Addr(pEnd->z) - Addr(pStart->z) + 1;
17097c478bd9Sstevel@tonic-gate       sqliteVdbeChangeP3(v, addr, pStart->z, n);
17107c478bd9Sstevel@tonic-gate     }
17117c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
17127c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
17137c478bd9Sstevel@tonic-gate     if( pTable ){
17147c478bd9Sstevel@tonic-gate       sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
17157c478bd9Sstevel@tonic-gate       sqliteVdbeOp3(v, OP_OpenRead, 2, pTab->tnum, pTab->zName, 0);
17167c478bd9Sstevel@tonic-gate       lbl2 = sqliteVdbeMakeLabel(v);
17177c478bd9Sstevel@tonic-gate       sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2);
17187c478bd9Sstevel@tonic-gate       lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0);
17197c478bd9Sstevel@tonic-gate       for(i=0; i<pIndex->nColumn; i++){
17207c478bd9Sstevel@tonic-gate         int iCol = pIndex->aiColumn[i];
17217c478bd9Sstevel@tonic-gate         if( pTab->iPKey==iCol ){
17227c478bd9Sstevel@tonic-gate           sqliteVdbeAddOp(v, OP_Dup, i, 0);
17237c478bd9Sstevel@tonic-gate         }else{
17247c478bd9Sstevel@tonic-gate           sqliteVdbeAddOp(v, OP_Column, 2, iCol);
17257c478bd9Sstevel@tonic-gate         }
17267c478bd9Sstevel@tonic-gate       }
17277c478bd9Sstevel@tonic-gate       sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0);
17287c478bd9Sstevel@tonic-gate       if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIndex);
17297c478bd9Sstevel@tonic-gate       sqliteVdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None,
17307c478bd9Sstevel@tonic-gate                       "indexed columns are not unique", P3_STATIC);
17317c478bd9Sstevel@tonic-gate       sqliteVdbeAddOp(v, OP_Next, 2, lbl1);
17327c478bd9Sstevel@tonic-gate       sqliteVdbeResolveLabel(v, lbl2);
17337c478bd9Sstevel@tonic-gate       sqliteVdbeAddOp(v, OP_Close, 2, 0);
17347c478bd9Sstevel@tonic-gate       sqliteVdbeAddOp(v, OP_Close, 1, 0);
17357c478bd9Sstevel@tonic-gate     }
17367c478bd9Sstevel@tonic-gate     if( pTable!=0 ){
17377c478bd9Sstevel@tonic-gate       if( !isTemp ){
17387c478bd9Sstevel@tonic-gate         sqliteChangeCookie(db, v);
17397c478bd9Sstevel@tonic-gate       }
17407c478bd9Sstevel@tonic-gate       sqliteVdbeAddOp(v, OP_Close, 0, 0);
17417c478bd9Sstevel@tonic-gate       sqliteEndWriteOperation(pParse);
17427c478bd9Sstevel@tonic-gate     }
17437c478bd9Sstevel@tonic-gate   }
17447c478bd9Sstevel@tonic-gate 
17457c478bd9Sstevel@tonic-gate   /* Clean up before exiting */
17467c478bd9Sstevel@tonic-gate exit_create_index:
17477c478bd9Sstevel@tonic-gate   sqliteIdListDelete(pList);
17487c478bd9Sstevel@tonic-gate   sqliteSrcListDelete(pTable);
17497c478bd9Sstevel@tonic-gate   sqliteFree(zName);
17507c478bd9Sstevel@tonic-gate   return;
17517c478bd9Sstevel@tonic-gate }
17527c478bd9Sstevel@tonic-gate 
17537c478bd9Sstevel@tonic-gate /*
17547c478bd9Sstevel@tonic-gate ** This routine will drop an existing named index.  This routine
17557c478bd9Sstevel@tonic-gate ** implements the DROP INDEX statement.
17567c478bd9Sstevel@tonic-gate */
sqliteDropIndex(Parse * pParse,SrcList * pName)17577c478bd9Sstevel@tonic-gate void sqliteDropIndex(Parse *pParse, SrcList *pName){
17587c478bd9Sstevel@tonic-gate   Index *pIndex;
17597c478bd9Sstevel@tonic-gate   Vdbe *v;
17607c478bd9Sstevel@tonic-gate   sqlite *db = pParse->db;
17617c478bd9Sstevel@tonic-gate 
17627c478bd9Sstevel@tonic-gate   if( pParse->nErr || sqlite_malloc_failed ) return;
17637c478bd9Sstevel@tonic-gate   assert( pName->nSrc==1 );
17647c478bd9Sstevel@tonic-gate   pIndex = sqliteFindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
17657c478bd9Sstevel@tonic-gate   if( pIndex==0 ){
17667c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "no such index: %S", pName, 0);
17677c478bd9Sstevel@tonic-gate     goto exit_drop_index;
17687c478bd9Sstevel@tonic-gate   }
17697c478bd9Sstevel@tonic-gate   if( pIndex->autoIndex ){
17707c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "index associated with UNIQUE "
17717c478bd9Sstevel@tonic-gate       "or PRIMARY KEY constraint cannot be dropped", 0);
17727c478bd9Sstevel@tonic-gate     goto exit_drop_index;
17737c478bd9Sstevel@tonic-gate   }
17747c478bd9Sstevel@tonic-gate   if( pIndex->iDb>1 ){
17757c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "cannot alter schema of attached "
17767c478bd9Sstevel@tonic-gate        "databases", 0);
17777c478bd9Sstevel@tonic-gate     goto exit_drop_index;
17787c478bd9Sstevel@tonic-gate   }
17797c478bd9Sstevel@tonic-gate #ifndef SQLITE_OMIT_AUTHORIZATION
17807c478bd9Sstevel@tonic-gate   {
17817c478bd9Sstevel@tonic-gate     int code = SQLITE_DROP_INDEX;
17827c478bd9Sstevel@tonic-gate     Table *pTab = pIndex->pTable;
17837c478bd9Sstevel@tonic-gate     const char *zDb = db->aDb[pIndex->iDb].zName;
17847c478bd9Sstevel@tonic-gate     const char *zTab = SCHEMA_TABLE(pIndex->iDb);
17857c478bd9Sstevel@tonic-gate     if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
17867c478bd9Sstevel@tonic-gate       goto exit_drop_index;
17877c478bd9Sstevel@tonic-gate     }
17887c478bd9Sstevel@tonic-gate     if( pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX;
17897c478bd9Sstevel@tonic-gate     if( sqliteAuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
17907c478bd9Sstevel@tonic-gate       goto exit_drop_index;
17917c478bd9Sstevel@tonic-gate     }
17927c478bd9Sstevel@tonic-gate   }
17937c478bd9Sstevel@tonic-gate #endif
17947c478bd9Sstevel@tonic-gate 
17957c478bd9Sstevel@tonic-gate   /* Generate code to remove the index and from the master table */
17967c478bd9Sstevel@tonic-gate   v = sqliteGetVdbe(pParse);
17977c478bd9Sstevel@tonic-gate   if( v ){
17987c478bd9Sstevel@tonic-gate     static VdbeOpList dropIndex[] = {
1799*1da57d55SToomas Soome       { OP_Rewind,     0, ADDR(9), 0},
18007c478bd9Sstevel@tonic-gate       { OP_String,     0, 0,       0}, /* 1 */
18017c478bd9Sstevel@tonic-gate       { OP_MemStore,   1, 1,       0},
18027c478bd9Sstevel@tonic-gate       { OP_MemLoad,    1, 0,       0}, /* 3 */
18037c478bd9Sstevel@tonic-gate       { OP_Column,     0, 1,       0},
18047c478bd9Sstevel@tonic-gate       { OP_Eq,         0, ADDR(8), 0},
18057c478bd9Sstevel@tonic-gate       { OP_Next,       0, ADDR(3), 0},
18067c478bd9Sstevel@tonic-gate       { OP_Goto,       0, ADDR(9), 0},
18077c478bd9Sstevel@tonic-gate       { OP_Delete,     0, 0,       0}, /* 8 */
18087c478bd9Sstevel@tonic-gate     };
18097c478bd9Sstevel@tonic-gate     int base;
18107c478bd9Sstevel@tonic-gate 
18117c478bd9Sstevel@tonic-gate     sqliteBeginWriteOperation(pParse, 0, pIndex->iDb);
18127c478bd9Sstevel@tonic-gate     sqliteOpenMasterTable(v, pIndex->iDb);
18137c478bd9Sstevel@tonic-gate     base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
18147c478bd9Sstevel@tonic-gate     sqliteVdbeChangeP3(v, base+1, pIndex->zName, 0);
18157c478bd9Sstevel@tonic-gate     if( pIndex->iDb==0 ){
18167c478bd9Sstevel@tonic-gate       sqliteChangeCookie(db, v);
18177c478bd9Sstevel@tonic-gate     }
18187c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_Close, 0, 0);
18197c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb);
18207c478bd9Sstevel@tonic-gate     sqliteEndWriteOperation(pParse);
18217c478bd9Sstevel@tonic-gate   }
18227c478bd9Sstevel@tonic-gate 
18237c478bd9Sstevel@tonic-gate   /* Delete the in-memory description of this index.
18247c478bd9Sstevel@tonic-gate   */
18257c478bd9Sstevel@tonic-gate   if( !pParse->explain ){
18267c478bd9Sstevel@tonic-gate     sqliteUnlinkAndDeleteIndex(db, pIndex);
18277c478bd9Sstevel@tonic-gate     db->flags |= SQLITE_InternChanges;
18287c478bd9Sstevel@tonic-gate   }
18297c478bd9Sstevel@tonic-gate 
18307c478bd9Sstevel@tonic-gate exit_drop_index:
18317c478bd9Sstevel@tonic-gate   sqliteSrcListDelete(pName);
18327c478bd9Sstevel@tonic-gate }
18337c478bd9Sstevel@tonic-gate 
18347c478bd9Sstevel@tonic-gate /*
18357c478bd9Sstevel@tonic-gate ** Append a new element to the given IdList.  Create a new IdList if
18367c478bd9Sstevel@tonic-gate ** need be.
18377c478bd9Sstevel@tonic-gate **
18387c478bd9Sstevel@tonic-gate ** A new IdList is returned, or NULL if malloc() fails.
18397c478bd9Sstevel@tonic-gate */
sqliteIdListAppend(IdList * pList,Token * pToken)18407c478bd9Sstevel@tonic-gate IdList *sqliteIdListAppend(IdList *pList, Token *pToken){
18417c478bd9Sstevel@tonic-gate   if( pList==0 ){
18427c478bd9Sstevel@tonic-gate     pList = sqliteMalloc( sizeof(IdList) );
18437c478bd9Sstevel@tonic-gate     if( pList==0 ) return 0;
18447c478bd9Sstevel@tonic-gate     pList->nAlloc = 0;
18457c478bd9Sstevel@tonic-gate   }
18467c478bd9Sstevel@tonic-gate   if( pList->nId>=pList->nAlloc ){
18477c478bd9Sstevel@tonic-gate     struct IdList_item *a;
18487c478bd9Sstevel@tonic-gate     pList->nAlloc = pList->nAlloc*2 + 5;
18497c478bd9Sstevel@tonic-gate     a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) );
18507c478bd9Sstevel@tonic-gate     if( a==0 ){
18517c478bd9Sstevel@tonic-gate       sqliteIdListDelete(pList);
18527c478bd9Sstevel@tonic-gate       return 0;
18537c478bd9Sstevel@tonic-gate     }
18547c478bd9Sstevel@tonic-gate     pList->a = a;
18557c478bd9Sstevel@tonic-gate   }
18567c478bd9Sstevel@tonic-gate   memset(&pList->a[pList->nId], 0, sizeof(pList->a[0]));
18577c478bd9Sstevel@tonic-gate   if( pToken ){
18587c478bd9Sstevel@tonic-gate     char **pz = &pList->a[pList->nId].zName;
18597c478bd9Sstevel@tonic-gate     sqliteSetNString(pz, pToken->z, pToken->n, 0);
18607c478bd9Sstevel@tonic-gate     if( *pz==0 ){
18617c478bd9Sstevel@tonic-gate       sqliteIdListDelete(pList);
18627c478bd9Sstevel@tonic-gate       return 0;
18637c478bd9Sstevel@tonic-gate     }else{
18647c478bd9Sstevel@tonic-gate       sqliteDequote(*pz);
18657c478bd9Sstevel@tonic-gate     }
18667c478bd9Sstevel@tonic-gate   }
18677c478bd9Sstevel@tonic-gate   pList->nId++;
18687c478bd9Sstevel@tonic-gate   return pList;
18697c478bd9Sstevel@tonic-gate }
18707c478bd9Sstevel@tonic-gate 
18717c478bd9Sstevel@tonic-gate /*
18727c478bd9Sstevel@tonic-gate ** Append a new table name to the given SrcList.  Create a new SrcList if
18737c478bd9Sstevel@tonic-gate ** need be.  A new entry is created in the SrcList even if pToken is NULL.
18747c478bd9Sstevel@tonic-gate **
18757c478bd9Sstevel@tonic-gate ** A new SrcList is returned, or NULL if malloc() fails.
18767c478bd9Sstevel@tonic-gate **
18777c478bd9Sstevel@tonic-gate ** If pDatabase is not null, it means that the table has an optional
18787c478bd9Sstevel@tonic-gate ** database name prefix.  Like this:  "database.table".  The pDatabase
18797c478bd9Sstevel@tonic-gate ** points to the table name and the pTable points to the database name.
18807c478bd9Sstevel@tonic-gate ** The SrcList.a[].zName field is filled with the table name which might
1881*1da57d55SToomas Soome ** come from pTable (if pDatabase is NULL) or from pDatabase.
18827c478bd9Sstevel@tonic-gate ** SrcList.a[].zDatabase is filled with the database name from pTable,
18837c478bd9Sstevel@tonic-gate ** or with NULL if no database is specified.
18847c478bd9Sstevel@tonic-gate **
18857c478bd9Sstevel@tonic-gate ** In other words, if call like this:
18867c478bd9Sstevel@tonic-gate **
18877c478bd9Sstevel@tonic-gate **         sqliteSrcListAppend(A,B,0);
18887c478bd9Sstevel@tonic-gate **
18897c478bd9Sstevel@tonic-gate ** Then B is a table name and the database name is unspecified.  If called
18907c478bd9Sstevel@tonic-gate ** like this:
18917c478bd9Sstevel@tonic-gate **
18927c478bd9Sstevel@tonic-gate **         sqliteSrcListAppend(A,B,C);
18937c478bd9Sstevel@tonic-gate **
18947c478bd9Sstevel@tonic-gate ** Then C is the table name and B is the database name.
18957c478bd9Sstevel@tonic-gate */
sqliteSrcListAppend(SrcList * pList,Token * pTable,Token * pDatabase)18967c478bd9Sstevel@tonic-gate SrcList *sqliteSrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){
18977c478bd9Sstevel@tonic-gate   if( pList==0 ){
18987c478bd9Sstevel@tonic-gate     pList = sqliteMalloc( sizeof(SrcList) );
18997c478bd9Sstevel@tonic-gate     if( pList==0 ) return 0;
19007c478bd9Sstevel@tonic-gate     pList->nAlloc = 1;
19017c478bd9Sstevel@tonic-gate   }
19027c478bd9Sstevel@tonic-gate   if( pList->nSrc>=pList->nAlloc ){
19037c478bd9Sstevel@tonic-gate     SrcList *pNew;
19047c478bd9Sstevel@tonic-gate     pList->nAlloc *= 2;
19057c478bd9Sstevel@tonic-gate     pNew = sqliteRealloc(pList,
19067c478bd9Sstevel@tonic-gate                sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) );
19077c478bd9Sstevel@tonic-gate     if( pNew==0 ){
19087c478bd9Sstevel@tonic-gate       sqliteSrcListDelete(pList);
19097c478bd9Sstevel@tonic-gate       return 0;
19107c478bd9Sstevel@tonic-gate     }
19117c478bd9Sstevel@tonic-gate     pList = pNew;
19127c478bd9Sstevel@tonic-gate   }
19137c478bd9Sstevel@tonic-gate   memset(&pList->a[pList->nSrc], 0, sizeof(pList->a[0]));
19147c478bd9Sstevel@tonic-gate   if( pDatabase && pDatabase->z==0 ){
19157c478bd9Sstevel@tonic-gate     pDatabase = 0;
19167c478bd9Sstevel@tonic-gate   }
19177c478bd9Sstevel@tonic-gate   if( pDatabase && pTable ){
19187c478bd9Sstevel@tonic-gate     Token *pTemp = pDatabase;
19197c478bd9Sstevel@tonic-gate     pDatabase = pTable;
19207c478bd9Sstevel@tonic-gate     pTable = pTemp;
19217c478bd9Sstevel@tonic-gate   }
19227c478bd9Sstevel@tonic-gate   if( pTable ){
19237c478bd9Sstevel@tonic-gate     char **pz = &pList->a[pList->nSrc].zName;
19247c478bd9Sstevel@tonic-gate     sqliteSetNString(pz, pTable->z, pTable->n, 0);
19257c478bd9Sstevel@tonic-gate     if( *pz==0 ){
19267c478bd9Sstevel@tonic-gate       sqliteSrcListDelete(pList);
19277c478bd9Sstevel@tonic-gate       return 0;
19287c478bd9Sstevel@tonic-gate     }else{
19297c478bd9Sstevel@tonic-gate       sqliteDequote(*pz);
19307c478bd9Sstevel@tonic-gate     }
19317c478bd9Sstevel@tonic-gate   }
19327c478bd9Sstevel@tonic-gate   if( pDatabase ){
19337c478bd9Sstevel@tonic-gate     char **pz = &pList->a[pList->nSrc].zDatabase;
19347c478bd9Sstevel@tonic-gate     sqliteSetNString(pz, pDatabase->z, pDatabase->n, 0);
19357c478bd9Sstevel@tonic-gate     if( *pz==0 ){
19367c478bd9Sstevel@tonic-gate       sqliteSrcListDelete(pList);
19377c478bd9Sstevel@tonic-gate       return 0;
19387c478bd9Sstevel@tonic-gate     }else{
19397c478bd9Sstevel@tonic-gate       sqliteDequote(*pz);
19407c478bd9Sstevel@tonic-gate     }
19417c478bd9Sstevel@tonic-gate   }
19427c478bd9Sstevel@tonic-gate   pList->a[pList->nSrc].iCursor = -1;
19437c478bd9Sstevel@tonic-gate   pList->nSrc++;
19447c478bd9Sstevel@tonic-gate   return pList;
19457c478bd9Sstevel@tonic-gate }
19467c478bd9Sstevel@tonic-gate 
19477c478bd9Sstevel@tonic-gate /*
19487c478bd9Sstevel@tonic-gate ** Assign cursors to all tables in a SrcList
19497c478bd9Sstevel@tonic-gate */
sqliteSrcListAssignCursors(Parse * pParse,SrcList * pList)19507c478bd9Sstevel@tonic-gate void sqliteSrcListAssignCursors(Parse *pParse, SrcList *pList){
19517c478bd9Sstevel@tonic-gate   int i;
19527c478bd9Sstevel@tonic-gate   for(i=0; i<pList->nSrc; i++){
19537c478bd9Sstevel@tonic-gate     if( pList->a[i].iCursor<0 ){
19547c478bd9Sstevel@tonic-gate       pList->a[i].iCursor = pParse->nTab++;
19557c478bd9Sstevel@tonic-gate     }
19567c478bd9Sstevel@tonic-gate   }
19577c478bd9Sstevel@tonic-gate }
19587c478bd9Sstevel@tonic-gate 
19597c478bd9Sstevel@tonic-gate /*
19607c478bd9Sstevel@tonic-gate ** Add an alias to the last identifier on the given identifier list.
19617c478bd9Sstevel@tonic-gate */
sqliteSrcListAddAlias(SrcList * pList,Token * pToken)19627c478bd9Sstevel@tonic-gate void sqliteSrcListAddAlias(SrcList *pList, Token *pToken){
19637c478bd9Sstevel@tonic-gate   if( pList && pList->nSrc>0 ){
19647c478bd9Sstevel@tonic-gate     int i = pList->nSrc - 1;
19657c478bd9Sstevel@tonic-gate     sqliteSetNString(&pList->a[i].zAlias, pToken->z, pToken->n, 0);
19667c478bd9Sstevel@tonic-gate     sqliteDequote(pList->a[i].zAlias);
19677c478bd9Sstevel@tonic-gate   }
19687c478bd9Sstevel@tonic-gate }
19697c478bd9Sstevel@tonic-gate 
19707c478bd9Sstevel@tonic-gate /*
19717c478bd9Sstevel@tonic-gate ** Delete an IdList.
19727c478bd9Sstevel@tonic-gate */
sqliteIdListDelete(IdList * pList)19737c478bd9Sstevel@tonic-gate void sqliteIdListDelete(IdList *pList){
19747c478bd9Sstevel@tonic-gate   int i;
19757c478bd9Sstevel@tonic-gate   if( pList==0 ) return;
19767c478bd9Sstevel@tonic-gate   for(i=0; i<pList->nId; i++){
19777c478bd9Sstevel@tonic-gate     sqliteFree(pList->a[i].zName);
19787c478bd9Sstevel@tonic-gate   }
19797c478bd9Sstevel@tonic-gate   sqliteFree(pList->a);
19807c478bd9Sstevel@tonic-gate   sqliteFree(pList);
19817c478bd9Sstevel@tonic-gate }
19827c478bd9Sstevel@tonic-gate 
19837c478bd9Sstevel@tonic-gate /*
19847c478bd9Sstevel@tonic-gate ** Return the index in pList of the identifier named zId.  Return -1
19857c478bd9Sstevel@tonic-gate ** if not found.
19867c478bd9Sstevel@tonic-gate */
sqliteIdListIndex(IdList * pList,const char * zName)19877c478bd9Sstevel@tonic-gate int sqliteIdListIndex(IdList *pList, const char *zName){
19887c478bd9Sstevel@tonic-gate   int i;
19897c478bd9Sstevel@tonic-gate   if( pList==0 ) return -1;
19907c478bd9Sstevel@tonic-gate   for(i=0; i<pList->nId; i++){
19917c478bd9Sstevel@tonic-gate     if( sqliteStrICmp(pList->a[i].zName, zName)==0 ) return i;
19927c478bd9Sstevel@tonic-gate   }
19937c478bd9Sstevel@tonic-gate   return -1;
19947c478bd9Sstevel@tonic-gate }
19957c478bd9Sstevel@tonic-gate 
19967c478bd9Sstevel@tonic-gate /*
19977c478bd9Sstevel@tonic-gate ** Delete an entire SrcList including all its substructure.
19987c478bd9Sstevel@tonic-gate */
sqliteSrcListDelete(SrcList * pList)19997c478bd9Sstevel@tonic-gate void sqliteSrcListDelete(SrcList *pList){
20007c478bd9Sstevel@tonic-gate   int i;
20017c478bd9Sstevel@tonic-gate   if( pList==0 ) return;
20027c478bd9Sstevel@tonic-gate   for(i=0; i<pList->nSrc; i++){
20037c478bd9Sstevel@tonic-gate     sqliteFree(pList->a[i].zDatabase);
20047c478bd9Sstevel@tonic-gate     sqliteFree(pList->a[i].zName);
20057c478bd9Sstevel@tonic-gate     sqliteFree(pList->a[i].zAlias);
20067c478bd9Sstevel@tonic-gate     if( pList->a[i].pTab && pList->a[i].pTab->isTransient ){
20077c478bd9Sstevel@tonic-gate       sqliteDeleteTable(0, pList->a[i].pTab);
20087c478bd9Sstevel@tonic-gate     }
20097c478bd9Sstevel@tonic-gate     sqliteSelectDelete(pList->a[i].pSelect);
20107c478bd9Sstevel@tonic-gate     sqliteExprDelete(pList->a[i].pOn);
20117c478bd9Sstevel@tonic-gate     sqliteIdListDelete(pList->a[i].pUsing);
20127c478bd9Sstevel@tonic-gate   }
20137c478bd9Sstevel@tonic-gate   sqliteFree(pList);
20147c478bd9Sstevel@tonic-gate }
20157c478bd9Sstevel@tonic-gate 
20167c478bd9Sstevel@tonic-gate /*
20177c478bd9Sstevel@tonic-gate ** Begin a transaction
20187c478bd9Sstevel@tonic-gate */
sqliteBeginTransaction(Parse * pParse,int onError)20197c478bd9Sstevel@tonic-gate void sqliteBeginTransaction(Parse *pParse, int onError){
20207c478bd9Sstevel@tonic-gate   sqlite *db;
20217c478bd9Sstevel@tonic-gate 
20227c478bd9Sstevel@tonic-gate   if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
20237c478bd9Sstevel@tonic-gate   if( pParse->nErr || sqlite_malloc_failed ) return;
20247c478bd9Sstevel@tonic-gate   if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return;
20257c478bd9Sstevel@tonic-gate   if( db->flags & SQLITE_InTrans ){
20267c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "cannot start a transaction within a transaction");
20277c478bd9Sstevel@tonic-gate     return;
20287c478bd9Sstevel@tonic-gate   }
20297c478bd9Sstevel@tonic-gate   sqliteBeginWriteOperation(pParse, 0, 0);
20307c478bd9Sstevel@tonic-gate   if( !pParse->explain ){
20317c478bd9Sstevel@tonic-gate     db->flags |= SQLITE_InTrans;
20327c478bd9Sstevel@tonic-gate     db->onError = onError;
20337c478bd9Sstevel@tonic-gate   }
20347c478bd9Sstevel@tonic-gate }
20357c478bd9Sstevel@tonic-gate 
20367c478bd9Sstevel@tonic-gate /*
20377c478bd9Sstevel@tonic-gate ** Commit a transaction
20387c478bd9Sstevel@tonic-gate */
sqliteCommitTransaction(Parse * pParse)20397c478bd9Sstevel@tonic-gate void sqliteCommitTransaction(Parse *pParse){
20407c478bd9Sstevel@tonic-gate   sqlite *db;
20417c478bd9Sstevel@tonic-gate 
20427c478bd9Sstevel@tonic-gate   if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
20437c478bd9Sstevel@tonic-gate   if( pParse->nErr || sqlite_malloc_failed ) return;
20447c478bd9Sstevel@tonic-gate   if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return;
20457c478bd9Sstevel@tonic-gate   if( (db->flags & SQLITE_InTrans)==0 ){
20467c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "cannot commit - no transaction is active");
20477c478bd9Sstevel@tonic-gate     return;
20487c478bd9Sstevel@tonic-gate   }
20497c478bd9Sstevel@tonic-gate   if( !pParse->explain ){
20507c478bd9Sstevel@tonic-gate     db->flags &= ~SQLITE_InTrans;
20517c478bd9Sstevel@tonic-gate   }
20527c478bd9Sstevel@tonic-gate   sqliteEndWriteOperation(pParse);
20537c478bd9Sstevel@tonic-gate   if( !pParse->explain ){
20547c478bd9Sstevel@tonic-gate     db->onError = OE_Default;
20557c478bd9Sstevel@tonic-gate   }
20567c478bd9Sstevel@tonic-gate }
20577c478bd9Sstevel@tonic-gate 
20587c478bd9Sstevel@tonic-gate /*
20597c478bd9Sstevel@tonic-gate ** Rollback a transaction
20607c478bd9Sstevel@tonic-gate */
sqliteRollbackTransaction(Parse * pParse)20617c478bd9Sstevel@tonic-gate void sqliteRollbackTransaction(Parse *pParse){
20627c478bd9Sstevel@tonic-gate   sqlite *db;
20637c478bd9Sstevel@tonic-gate   Vdbe *v;
20647c478bd9Sstevel@tonic-gate 
20657c478bd9Sstevel@tonic-gate   if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
20667c478bd9Sstevel@tonic-gate   if( pParse->nErr || sqlite_malloc_failed ) return;
20677c478bd9Sstevel@tonic-gate   if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return;
20687c478bd9Sstevel@tonic-gate   if( (db->flags & SQLITE_InTrans)==0 ){
20697c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "cannot rollback - no transaction is active");
2070*1da57d55SToomas Soome     return;
20717c478bd9Sstevel@tonic-gate   }
20727c478bd9Sstevel@tonic-gate   v = sqliteGetVdbe(pParse);
20737c478bd9Sstevel@tonic-gate   if( v ){
20747c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_Rollback, 0, 0);
20757c478bd9Sstevel@tonic-gate   }
20767c478bd9Sstevel@tonic-gate   if( !pParse->explain ){
20777c478bd9Sstevel@tonic-gate     db->flags &= ~SQLITE_InTrans;
20787c478bd9Sstevel@tonic-gate     db->onError = OE_Default;
20797c478bd9Sstevel@tonic-gate   }
20807c478bd9Sstevel@tonic-gate }
20817c478bd9Sstevel@tonic-gate 
20827c478bd9Sstevel@tonic-gate /*
20837c478bd9Sstevel@tonic-gate ** Generate VDBE code that will verify the schema cookie for all
20847c478bd9Sstevel@tonic-gate ** named database files.
20857c478bd9Sstevel@tonic-gate */
sqliteCodeVerifySchema(Parse * pParse,int iDb)20867c478bd9Sstevel@tonic-gate void sqliteCodeVerifySchema(Parse *pParse, int iDb){
20877c478bd9Sstevel@tonic-gate   sqlite *db = pParse->db;
20887c478bd9Sstevel@tonic-gate   Vdbe *v = sqliteGetVdbe(pParse);
20897c478bd9Sstevel@tonic-gate   assert( iDb>=0 && iDb<db->nDb );
20907c478bd9Sstevel@tonic-gate   assert( db->aDb[iDb].pBt!=0 );
20917c478bd9Sstevel@tonic-gate   if( iDb!=1 && !DbHasProperty(db, iDb, DB_Cookie) ){
20927c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_VerifyCookie, iDb, db->aDb[iDb].schema_cookie);
20937c478bd9Sstevel@tonic-gate     DbSetProperty(db, iDb, DB_Cookie);
20947c478bd9Sstevel@tonic-gate   }
20957c478bd9Sstevel@tonic-gate }
20967c478bd9Sstevel@tonic-gate 
20977c478bd9Sstevel@tonic-gate /*
20987c478bd9Sstevel@tonic-gate ** Generate VDBE code that prepares for doing an operation that
20997c478bd9Sstevel@tonic-gate ** might change the database.
21007c478bd9Sstevel@tonic-gate **
21017c478bd9Sstevel@tonic-gate ** This routine starts a new transaction if we are not already within
21027c478bd9Sstevel@tonic-gate ** a transaction.  If we are already within a transaction, then a checkpoint
21037c478bd9Sstevel@tonic-gate ** is set if the setCheckpoint parameter is true.  A checkpoint should
21047c478bd9Sstevel@tonic-gate ** be set for operations that might fail (due to a constraint) part of
21057c478bd9Sstevel@tonic-gate ** the way through and which will need to undo some writes without having to
21067c478bd9Sstevel@tonic-gate ** rollback the whole transaction.  For operations where all constraints
21077c478bd9Sstevel@tonic-gate ** can be checked before any changes are made to the database, it is never
21087c478bd9Sstevel@tonic-gate ** necessary to undo a write and the checkpoint should not be set.
21097c478bd9Sstevel@tonic-gate **
21107c478bd9Sstevel@tonic-gate ** Only database iDb and the temp database are made writable by this call.
21117c478bd9Sstevel@tonic-gate ** If iDb==0, then the main and temp databases are made writable.   If
21127c478bd9Sstevel@tonic-gate ** iDb==1 then only the temp database is made writable.  If iDb>1 then the
21137c478bd9Sstevel@tonic-gate ** specified auxiliary database and the temp database are made writable.
21147c478bd9Sstevel@tonic-gate */
sqliteBeginWriteOperation(Parse * pParse,int setCheckpoint,int iDb)21157c478bd9Sstevel@tonic-gate void sqliteBeginWriteOperation(Parse *pParse, int setCheckpoint, int iDb){
21167c478bd9Sstevel@tonic-gate   Vdbe *v;
21177c478bd9Sstevel@tonic-gate   sqlite *db = pParse->db;
21187c478bd9Sstevel@tonic-gate   if( DbHasProperty(db, iDb, DB_Locked) ) return;
21197c478bd9Sstevel@tonic-gate   v = sqliteGetVdbe(pParse);
21207c478bd9Sstevel@tonic-gate   if( v==0 ) return;
21217c478bd9Sstevel@tonic-gate   if( !db->aDb[iDb].inTrans ){
21227c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_Transaction, iDb, 0);
21237c478bd9Sstevel@tonic-gate     DbSetProperty(db, iDb, DB_Locked);
21247c478bd9Sstevel@tonic-gate     sqliteCodeVerifySchema(pParse, iDb);
21257c478bd9Sstevel@tonic-gate     if( iDb!=1 ){
21267c478bd9Sstevel@tonic-gate       sqliteBeginWriteOperation(pParse, setCheckpoint, 1);
21277c478bd9Sstevel@tonic-gate     }
21287c478bd9Sstevel@tonic-gate   }else if( setCheckpoint ){
21297c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_Checkpoint, iDb, 0);
21307c478bd9Sstevel@tonic-gate     DbSetProperty(db, iDb, DB_Locked);
21317c478bd9Sstevel@tonic-gate   }
21327c478bd9Sstevel@tonic-gate }
21337c478bd9Sstevel@tonic-gate 
21347c478bd9Sstevel@tonic-gate /*
21357c478bd9Sstevel@tonic-gate ** Generate code that concludes an operation that may have changed
21367c478bd9Sstevel@tonic-gate ** the database.  If a statement transaction was started, then emit
21377c478bd9Sstevel@tonic-gate ** an OP_Commit that will cause the changes to be committed to disk.
21387c478bd9Sstevel@tonic-gate **
21397c478bd9Sstevel@tonic-gate ** Note that checkpoints are automatically committed at the end of
2140*1da57d55SToomas Soome ** a statement.  Note also that there can be multiple calls to
21417c478bd9Sstevel@tonic-gate ** sqliteBeginWriteOperation() but there should only be a single
21427c478bd9Sstevel@tonic-gate ** call to sqliteEndWriteOperation() at the conclusion of the statement.
21437c478bd9Sstevel@tonic-gate */
sqliteEndWriteOperation(Parse * pParse)21447c478bd9Sstevel@tonic-gate void sqliteEndWriteOperation(Parse *pParse){
21457c478bd9Sstevel@tonic-gate   Vdbe *v;
21467c478bd9Sstevel@tonic-gate   sqlite *db = pParse->db;
21477c478bd9Sstevel@tonic-gate   if( pParse->trigStack ) return; /* if this is in a trigger */
21487c478bd9Sstevel@tonic-gate   v = sqliteGetVdbe(pParse);
21497c478bd9Sstevel@tonic-gate   if( v==0 ) return;
21507c478bd9Sstevel@tonic-gate   if( db->flags & SQLITE_InTrans ){
21517c478bd9Sstevel@tonic-gate     /* A BEGIN has executed.  Do not commit until we see an explicit
21527c478bd9Sstevel@tonic-gate     ** COMMIT statement. */
21537c478bd9Sstevel@tonic-gate   }else{
21547c478bd9Sstevel@tonic-gate     sqliteVdbeAddOp(v, OP_Commit, 0, 0);
21557c478bd9Sstevel@tonic-gate   }
21567c478bd9Sstevel@tonic-gate }
2157