/ Check-in [af5c2be4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Eliminate the use of callbacks during schema initialization. (CVS 1242)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: af5c2be4aed1c50f69eb9634cf051a26263dcf51
User & Date: drh 2004-02-14 23:05:53
Context
2004-02-14
23:59
Eliminate obsolete code associated with the older callback functionality. (CVS 1243) check-in: 2dbc4593 user: drh tags: trunk
23:05
Eliminate the use of callbacks during schema initialization. (CVS 1242) check-in: af5c2be4 user: drh tags: trunk
17:35
Fix problems with malloc-failure handling. (CVS 1241) check-in: 398bc294 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to src/build.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
...
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
...
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
...
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
...
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
...
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
...
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
....
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
....
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
....
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
....
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
....
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
....
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
....
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
....
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
....
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.168 2004/02/14 16:31:03 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
................................................................................
** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables.
** If it does, then read it.
*/
void sqliteBeginParse(Parse *pParse, int explainFlag){
  sqlite *db = pParse->db;
  int i;
  pParse->explain = explainFlag;
  if((db->flags & SQLITE_Initialized)==0 && pParse->initFlag==0 ){
    int rc = sqliteInit(db, &pParse->zErrMsg);
    if( rc!=SQLITE_OK ){
      pParse->rc = rc;
      pParse->nErr++;
    }
  }
  for(i=0; i<db->nDb; i++){
................................................................................
  sqlite *db = pParse->db;
  Vdbe *v;
  int iDb;

  pParse->sFirstToken = *pStart;
  zName = sqliteTableNameFromToken(pName);
  if( zName==0 ) return;
  if( pParse->iDb==1 ) isTemp = 1;
#ifndef SQLITE_OMIT_AUTHORIZATION
  assert( (isTemp & 1)==isTemp );
  {
    int code;
    char *zDb = isTemp ? "temp" : "main";
    if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
      sqliteFree(zName);
................................................................................
  ** index or table name.  Issue an error message if it does.
  **
  ** If we are re-reading the sqlite_master table because of a schema
  ** change and a new permanent table is found whose name collides with
  ** an existing temporary table, that is not an error.
  */
  pTable = sqliteFindTable(db, zName, 0);
  iDb = isTemp ? 1 : pParse->iDb;
  if( pTable!=0 && (pTable->iDb==iDb || !pParse->initFlag) ){
    sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n,
        " already exists", 0, 0);
    sqliteFree(zName);
    pParse->nErr++;
    return;
  }
  if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 &&
          (pIdx->iDb==0 || !pParse->initFlag) ){
    sqliteSetString(&pParse->zErrMsg, "there is already an index named ", 
       zName, (char*)0);
    sqliteFree(zName);
    pParse->nErr++;
    return;
  }
  pTable = sqliteMalloc( sizeof(Table) );
................................................................................
  ** the SQLITE_MASTER table.  Note in particular that we must go ahead
  ** and allocate the record number for the table entry now.  Before any
  ** PRIMARY KEY or UNIQUE keywords are parsed.  Those keywords will cause
  ** indices to be created and the table record must come before the 
  ** indices.  Hence, the record number for the table must be allocated
  ** now.
  */
  if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
    sqliteBeginWriteOperation(pParse, 0, isTemp);
    if( !isTemp ){
      sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0);
      sqliteVdbeAddOp(v, OP_SetCookie, 0, 1);
    }
    sqliteOpenMasterTable(v, isTemp);
    sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
................................................................................
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.
**
** The table structure that other action routines have been building
** is added to the internal hash tables, assuming no errors have
** occurred.
**
** An entry for the table is made in the master table on disk,
** unless this is a temporary table or initFlag==1.  When initFlag==1,
** it means we are reading the sqlite_master table because we just
** connected to the database or because the sqlite_master table has
** recently changes, so the entry for this table already exists in
** the sqlite_master table.  We do not want to create it again.
**
** If the pSelect argument is not NULL, it means that this routine
** was called to create a table generated from a 
................................................................................
    p->nCol = pSelTab->nCol;
    p->aCol = pSelTab->aCol;
    pSelTab->nCol = 0;
    pSelTab->aCol = 0;
    sqliteDeleteTable(0, pSelTab);
  }

  /* If the initFlag is 1 it means we are reading the SQL off the
  ** "sqlite_master" or "sqlite_temp_master" table on the disk.
  ** So do not write to the disk again.  Extract the root page number
  ** for the table from the pParse->newTnum field.  (The page number
  ** should have been put there by the sqliteOpenCb routine.)
  */
  if( pParse->initFlag ){
    p->tnum = pParse->newTnum;
  }

  /* If not initializing, then create a record for the new table
  ** in the SQLITE_MASTER table of the database.  The record number
  ** for the new table entry should already be on the stack.
  **
  ** If this is a TEMPORARY table, write the entry into the auxiliary
  ** file instead of into the main database file.
  */
  if( !pParse->initFlag ){
    int n;
    Vdbe *v;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) return;
    if( p->pSelect==0 ){
      /* A regular table */
................................................................................
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    if( p->pSelect==0 ){
      sqliteVdbeChangeP3(v, -1, "table", P3_STATIC);
    }else{
      sqliteVdbeChangeP3(v, -1, "view", P3_STATIC);
    }
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeChangeP3(v, -1, p->zName, P3_STATIC);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeChangeP3(v, -1, p->zName, P3_STATIC);
    sqliteVdbeAddOp(v, OP_Dup, 4, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    if( pSelect ){
      char *z = createTableStmt(p);
      n = z ? strlen(z) : 0;
      sqliteVdbeChangeP3(v, -1, z, n);
      sqliteFree(z);
................................................................................
  /* Make a copy of the entire SELECT statement that defines the view.
  ** This will force all the Expr.token.z values to be dynamically
  ** allocated rather than point to the input string - which means that
  ** they will persist after the current sqlite_exec() call returns.
  */
  p->pSelect = sqliteSelectDup(pSelect);
  sqliteSelectDelete(pSelect);
  if( !pParse->initFlag ){
    sqliteViewGetColumnNames(pParse, p);
  }

  /* Locate the end of the CREATE VIEW statement.  Make sEnd point to
  ** the end.
  */
  sEnd = pParse->sLastToken;
................................................................................
  int i, j;
  Token nullId;    /* Fake token for an empty ID list */
  DbFixer sFix;    /* For assigning database names to pTable */
  int isTemp;      /* True for a temporary index */
  sqlite *db = pParse->db;

  if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;
  if( pParse->initFlag 
     && sqliteFixInit(&sFix, pParse, pParse->iDb, "index", pName)
     && sqliteFixSrcList(&sFix, pTable)
  ){
    goto exit_create_index;
  }

  /*
  ** Find the table that is to be indexed.  Return early if not found.
................................................................................
  if( pTab==0 || pParse->nErr ) goto exit_create_index;
  if( pTab->readOnly ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
      " may not be indexed", (char*)0);
    pParse->nErr++;
    goto exit_create_index;
  }
  if( pTab->iDb>=2 && pParse->initFlag==0 ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, 
      " may not have indices added", (char*)0);
    pParse->nErr++;
    goto exit_create_index;
  }
  if( pTab->pSelect ){
    sqliteSetString(&pParse->zErrMsg, "views may not be indexed", (char*)0);
................................................................................
  ** one of the index names collides with the name of a temporary table or
  ** index, then we will continue to process this index.
  **
  ** If pName==0 it means that we are
  ** dealing with a primary key or UNIQUE constraint.  We have to invent our
  ** own name.
  */
  if( pName && !pParse->initFlag ){
    Index *pISameName;    /* Another index with the same name */
    Table *pTSameName;    /* A table with same name as the index */
    zName = sqliteStrNDup(pName->z, pName->n);
    if( zName==0 ) goto exit_create_index;
    if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
      sqliteSetString(&pParse->zErrMsg, "index ", zName, 
         " already exists", (char*)0);
................................................................................

  /* Check for authorization to create an index.
  */
#ifndef SQLITE_OMIT_AUTHORIZATION
  {
    const char *zDb = db->aDb[pTab->iDb].zName;

    assert( pTab->iDb==pParse->iDb || isTemp );
    if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
      goto exit_create_index;
    }
    i = SQLITE_CREATE_INDEX;
    if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
    if( sqliteAuthCheck(pParse, i, zName, pTab->zName, zDb) ){
      goto exit_create_index;
................................................................................
  pIndex->aiColumn = (int*)&pIndex[1];
  pIndex->zName = (char*)&pIndex->aiColumn[pList->nId];
  strcpy(pIndex->zName, zName);
  pIndex->pTable = pTab;
  pIndex->nColumn = pList->nId;
  pIndex->onError = onError;
  pIndex->autoIndex = pName==0;
  pIndex->iDb = isTemp ? 1 : pParse->iDb;

  /* Scan the names of the columns of the table to be indexed and
  ** load the column indices into the Index structure.  Report an error
  ** if any column is not found.
  */
  for(i=0; i<pList->nId; i++){
    for(j=0; j<pTab->nCol; j++){
................................................................................
    while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
      pOther = pOther->pNext;
    }
    pIndex->pNext = pOther->pNext;
    pOther->pNext = pIndex;
  }

  /* If the initFlag is 1 it means we are reading the SQL off the
  ** "sqlite_master" table on the disk.  So do not write to the disk
  ** again.  Extract the table number from the pParse->newTnum field.
  */
  if( pParse->initFlag && pTable!=0 ){
    pIndex->tnum = pParse->newTnum;
  }

  /* If the initFlag is 0 then create the index on disk.  This
  ** involves writing the index into the master table and filling in the
  ** index with the current table contents.
  **
  ** The initFlag is 0 when the user first enters a CREATE INDEX 
  ** command.  The initFlag is 1 when a database is opened and 
  ** CREATE INDEX statements are read out of the master table.  In
  ** the latter case the index already exists on disk, which is why
  ** we don't want to recreate it.
  **
  ** If pTable==0 it means this index is generated as a primary key
  ** or UNIQUE constraint of a CREATE TABLE statement.  Since the table
  ** has just been created, it contains no data and the index initialization
  ** step can be skipped.
  */
  else if( pParse->initFlag==0 ){
    int n;
    Vdbe *v;
    int lbl1, lbl2;
    int i;
    int addr;

    v = sqliteGetVdbe(pParse);
................................................................................
    }
    sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeChangeP3(v, -1, "index", P3_STATIC);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeChangeP3(v, -1, pIndex->zName, strlen(pIndex->zName));
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
    addr = sqliteVdbeAddOp(v, OP_CreateIndex, 0, isTemp);
    sqliteVdbeChangeP3(v, addr, (char*)&pIndex->tnum, P3_POINTER);
    pIndex->tnum = 0;
    if( pTable ){
      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
      sqliteVdbeAddOp(v, OP_Integer, isTemp, 0);
      sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0);
................................................................................
      sqliteVdbeChangeP3(v, addr, pStart->z, n);
    }
    sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
    if( pTable ){
      sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
      sqliteVdbeAddOp(v, OP_OpenRead, 2, pTab->tnum);
      sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
      lbl2 = sqliteVdbeMakeLabel(v);
      sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2);
      lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0);
      for(i=0; i<pIndex->nColumn; i++){
        int iCol = pIndex->aiColumn[i];
        if( pTab->iPKey==iCol ){
          sqliteVdbeAddOp(v, OP_Dup, i, 0);







|







 







|







 







|







 







|
|







|







 







|







 







|
|







 







|


|


|
|









|







 







|

|







 







|







 







|
|







 







|







 







|







 







|







 







|







 







|

|

|
|


|



|
|









|







 







|







 







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
...
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
...
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
...
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
...
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
...
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
...
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
....
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
....
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
....
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
....
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
....
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
....
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
....
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
....
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
....
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.169 2004/02/14 23:05:53 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
................................................................................
** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables.
** If it does, then read it.
*/
void sqliteBeginParse(Parse *pParse, int explainFlag){
  sqlite *db = pParse->db;
  int i;
  pParse->explain = explainFlag;
  if((db->flags & SQLITE_Initialized)==0 && db->init.busy==0 ){
    int rc = sqliteInit(db, &pParse->zErrMsg);
    if( rc!=SQLITE_OK ){
      pParse->rc = rc;
      pParse->nErr++;
    }
  }
  for(i=0; i<db->nDb; i++){
................................................................................
  sqlite *db = pParse->db;
  Vdbe *v;
  int iDb;

  pParse->sFirstToken = *pStart;
  zName = sqliteTableNameFromToken(pName);
  if( zName==0 ) return;
  if( db->init.iDb==1 ) isTemp = 1;
#ifndef SQLITE_OMIT_AUTHORIZATION
  assert( (isTemp & 1)==isTemp );
  {
    int code;
    char *zDb = isTemp ? "temp" : "main";
    if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
      sqliteFree(zName);
................................................................................
  ** index or table name.  Issue an error message if it does.
  **
  ** If we are re-reading the sqlite_master table because of a schema
  ** change and a new permanent table is found whose name collides with
  ** an existing temporary table, that is not an error.
  */
  pTable = sqliteFindTable(db, zName, 0);
  iDb = isTemp ? 1 : db->init.iDb;
  if( pTable!=0 && (pTable->iDb==iDb || !db->init.busy) ){
    sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n,
        " already exists", 0, 0);
    sqliteFree(zName);
    pParse->nErr++;
    return;
  }
  if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 &&
          (pIdx->iDb==0 || !db->init.busy) ){
    sqliteSetString(&pParse->zErrMsg, "there is already an index named ", 
       zName, (char*)0);
    sqliteFree(zName);
    pParse->nErr++;
    return;
  }
  pTable = sqliteMalloc( sizeof(Table) );
................................................................................
  ** the SQLITE_MASTER table.  Note in particular that we must go ahead
  ** and allocate the record number for the table entry now.  Before any
  ** PRIMARY KEY or UNIQUE keywords are parsed.  Those keywords will cause
  ** indices to be created and the table record must come before the 
  ** indices.  Hence, the record number for the table must be allocated
  ** now.
  */
  if( !db->init.busy && (v = sqliteGetVdbe(pParse))!=0 ){
    sqliteBeginWriteOperation(pParse, 0, isTemp);
    if( !isTemp ){
      sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0);
      sqliteVdbeAddOp(v, OP_SetCookie, 0, 1);
    }
    sqliteOpenMasterTable(v, isTemp);
    sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
................................................................................
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.
**
** The table structure that other action routines have been building
** is added to the internal hash tables, assuming no errors have
** occurred.
**
** An entry for the table is made in the master table on disk, unless
** this is a temporary table or db->init.busy==1.  When db->init.busy==1
** it means we are reading the sqlite_master table because we just
** connected to the database or because the sqlite_master table has
** recently changes, so the entry for this table already exists in
** the sqlite_master table.  We do not want to create it again.
**
** If the pSelect argument is not NULL, it means that this routine
** was called to create a table generated from a 
................................................................................
    p->nCol = pSelTab->nCol;
    p->aCol = pSelTab->aCol;
    pSelTab->nCol = 0;
    pSelTab->aCol = 0;
    sqliteDeleteTable(0, pSelTab);
  }

  /* If the db->init.busy is 1 it means we are reading the SQL off the
  ** "sqlite_master" or "sqlite_temp_master" table on the disk.
  ** So do not write to the disk again.  Extract the root page number
  ** for the table from the db->init.newTnum field.  (The page number
  ** should have been put there by the sqliteOpenCb routine.)
  */
  if( db->init.busy ){
    p->tnum = db->init.newTnum;
  }

  /* If not initializing, then create a record for the new table
  ** in the SQLITE_MASTER table of the database.  The record number
  ** for the new table entry should already be on the stack.
  **
  ** If this is a TEMPORARY table, write the entry into the auxiliary
  ** file instead of into the main database file.
  */
  if( !db->init.busy ){
    int n;
    Vdbe *v;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) return;
    if( p->pSelect==0 ){
      /* A regular table */
................................................................................
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    if( p->pSelect==0 ){
      sqliteVdbeChangeP3(v, -1, "table", P3_STATIC);
    }else{
      sqliteVdbeChangeP3(v, -1, "view", P3_STATIC);
    }
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeChangeP3(v, -1, p->zName, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeChangeP3(v, -1, p->zName, 0);
    sqliteVdbeAddOp(v, OP_Dup, 4, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    if( pSelect ){
      char *z = createTableStmt(p);
      n = z ? strlen(z) : 0;
      sqliteVdbeChangeP3(v, -1, z, n);
      sqliteFree(z);
................................................................................
  /* Make a copy of the entire SELECT statement that defines the view.
  ** This will force all the Expr.token.z values to be dynamically
  ** allocated rather than point to the input string - which means that
  ** they will persist after the current sqlite_exec() call returns.
  */
  p->pSelect = sqliteSelectDup(pSelect);
  sqliteSelectDelete(pSelect);
  if( !pParse->db->init.busy ){
    sqliteViewGetColumnNames(pParse, p);
  }

  /* Locate the end of the CREATE VIEW statement.  Make sEnd point to
  ** the end.
  */
  sEnd = pParse->sLastToken;
................................................................................
  int i, j;
  Token nullId;    /* Fake token for an empty ID list */
  DbFixer sFix;    /* For assigning database names to pTable */
  int isTemp;      /* True for a temporary index */
  sqlite *db = pParse->db;

  if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;
  if( db->init.busy 
     && sqliteFixInit(&sFix, pParse, db->init.iDb, "index", pName)
     && sqliteFixSrcList(&sFix, pTable)
  ){
    goto exit_create_index;
  }

  /*
  ** Find the table that is to be indexed.  Return early if not found.
................................................................................
  if( pTab==0 || pParse->nErr ) goto exit_create_index;
  if( pTab->readOnly ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
      " may not be indexed", (char*)0);
    pParse->nErr++;
    goto exit_create_index;
  }
  if( pTab->iDb>=2 && db->init.busy==0 ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, 
      " may not have indices added", (char*)0);
    pParse->nErr++;
    goto exit_create_index;
  }
  if( pTab->pSelect ){
    sqliteSetString(&pParse->zErrMsg, "views may not be indexed", (char*)0);
................................................................................
  ** one of the index names collides with the name of a temporary table or
  ** index, then we will continue to process this index.
  **
  ** If pName==0 it means that we are
  ** dealing with a primary key or UNIQUE constraint.  We have to invent our
  ** own name.
  */
  if( pName && !db->init.busy ){
    Index *pISameName;    /* Another index with the same name */
    Table *pTSameName;    /* A table with same name as the index */
    zName = sqliteStrNDup(pName->z, pName->n);
    if( zName==0 ) goto exit_create_index;
    if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
      sqliteSetString(&pParse->zErrMsg, "index ", zName, 
         " already exists", (char*)0);
................................................................................

  /* Check for authorization to create an index.
  */
#ifndef SQLITE_OMIT_AUTHORIZATION
  {
    const char *zDb = db->aDb[pTab->iDb].zName;

    assert( pTab->iDb==db->init.iDb || isTemp );
    if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
      goto exit_create_index;
    }
    i = SQLITE_CREATE_INDEX;
    if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
    if( sqliteAuthCheck(pParse, i, zName, pTab->zName, zDb) ){
      goto exit_create_index;
................................................................................
  pIndex->aiColumn = (int*)&pIndex[1];
  pIndex->zName = (char*)&pIndex->aiColumn[pList->nId];
  strcpy(pIndex->zName, zName);
  pIndex->pTable = pTab;
  pIndex->nColumn = pList->nId;
  pIndex->onError = onError;
  pIndex->autoIndex = pName==0;
  pIndex->iDb = isTemp ? 1 : db->init.iDb;

  /* Scan the names of the columns of the table to be indexed and
  ** load the column indices into the Index structure.  Report an error
  ** if any column is not found.
  */
  for(i=0; i<pList->nId; i++){
    for(j=0; j<pTab->nCol; j++){
................................................................................
    while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
      pOther = pOther->pNext;
    }
    pIndex->pNext = pOther->pNext;
    pOther->pNext = pIndex;
  }

  /* If the db->init.busy is 1 it means we are reading the SQL off the
  ** "sqlite_master" table on the disk.  So do not write to the disk
  ** again.  Extract the table number from the db->init.newTnum field.
  */
  if( db->init.busy && pTable!=0 ){
    pIndex->tnum = db->init.newTnum;
  }

  /* If the db->init.busy is 0 then create the index on disk.  This
  ** involves writing the index into the master table and filling in the
  ** index with the current table contents.
  **
  ** The db->init.busy is 0 when the user first enters a CREATE INDEX 
  ** command.  db->init.busy is 1 when a database is opened and 
  ** CREATE INDEX statements are read out of the master table.  In
  ** the latter case the index already exists on disk, which is why
  ** we don't want to recreate it.
  **
  ** If pTable==0 it means this index is generated as a primary key
  ** or UNIQUE constraint of a CREATE TABLE statement.  Since the table
  ** has just been created, it contains no data and the index initialization
  ** step can be skipped.
  */
  else if( db->init.busy==0 ){
    int n;
    Vdbe *v;
    int lbl1, lbl2;
    int i;
    int addr;

    v = sqliteGetVdbe(pParse);
................................................................................
    }
    sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeChangeP3(v, -1, "index", P3_STATIC);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeChangeP3(v, -1, pIndex->zName, strlen(pIndex->zName));
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeChangeP3(v, -1, pTab->zName, 0);
    addr = sqliteVdbeAddOp(v, OP_CreateIndex, 0, isTemp);
    sqliteVdbeChangeP3(v, addr, (char*)&pIndex->tnum, P3_POINTER);
    pIndex->tnum = 0;
    if( pTable ){
      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
      sqliteVdbeAddOp(v, OP_Integer, isTemp, 0);
      sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0);
................................................................................
      sqliteVdbeChangeP3(v, addr, pStart->z, n);
    }
    sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
    if( pTable ){
      sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
      sqliteVdbeAddOp(v, OP_OpenRead, 2, pTab->tnum);
      sqliteVdbeChangeP3(v, -1, pTab->zName, 0);
      lbl2 = sqliteVdbeMakeLabel(v);
      sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2);
      lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0);
      for(i=0; i<pIndex->nColumn; i++){
        int iCol = pIndex->aiColumn[i];
        if( pTab->iPKey==iCol ){
          sqliteVdbeAddOp(v, OP_Dup, i, 0);

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
29
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
..
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81
82
83

84
85
86



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
...
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
...
241
242
243
244
245
246
247

248
249
250
251
252
253
254
...
265
266
267
268
269
270
271

272
273
274
275
276
277
278
...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340

341
342

343
344
345
346
347
348
349
350

351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
...
377
378
379
380
381
382
383

384
385

386
387
388
389
390
391
392
393

394
395
396
397
398
399
400
...
665
666
667
668
669
670
671

672
673
674

675
676
677
678
679
680
681
682
...
684
685
686
687
688
689
690


691
692
693
694
695
696
697
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.153 2004/02/14 17:35:07 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information
................................................................................
  char **pzErrMsg;    /* Error message stored here */
} InitData;

/*
** Fill the InitData structure with an error message that indicates
** that the database is corrupt.
*/
static void corruptSchema(InitData *pData){
  sqliteSetString(pData->pzErrMsg, "malformed database schema", (char*)0);

}

/*
** This is the callback routine for the code that initializes the
** database.  See sqliteInit() below for additional information.
**
** Each callback contains the following information:
................................................................................
**     argv[4] = "1" for temporary files, "0" for main database, "2" or more
**               for auxiliary database files.
**
*/
static
int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){
  InitData *pData = (InitData*)pInit;
  Parse sParse;
  int nErr = 0;

  assert( argc==5 );
  if( argv==0 ) return 0;   /* Might happen if EMPTY_RESULT_CALLBACKS are on */
  if( argv[0]==0 ){
    corruptSchema(pData);
    return 1;
  }
  switch( argv[0][0] ){
    case 'v':
    case 'i':
    case 't': {  /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */

      if( argv[2]==0 || argv[4]==0 ){
        corruptSchema(pData);
        return 1;
      }
      if( argv[3] && argv[3][0] ){
        /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
        ** But because sParse.initFlag is set to 1, no VDBE code is generated
        ** or executed.  All the parser does is build the internal data
        ** structures that describe the table, index, or view.
        */
        memset(&sParse, 0, sizeof(sParse));
        sParse.db = pData->db;
        sParse.initFlag = 1;
        sParse.iDb = atoi(argv[4]);

        sParse.newTnum = atoi(argv[2]);
        sParse.useCallback = 1;
        sqliteRunParser(&sParse, argv[3], pData->pzErrMsg);



      }else{
        /* If the SQL column is blank it means this is an index that
        ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
        ** constraint for a CREATE TABLE.  The index should have already
        ** been created when we processed the CREATE TABLE.  All we have
        ** to do here is record the root page number for that index.
        */
        int iDb;
        Index *pIndex;

        iDb = atoi(argv[4]);
        assert( iDb>=0 && iDb<pData->db->nDb );
        pIndex = sqliteFindIndex(pData->db, argv[1], pData->db->aDb[iDb].zName);
        if( pIndex==0 || pIndex->tnum!=0 ){
          /* This can occur if there exists an index on a TEMP table which
          ** has the same name as another index on a permanent index.  Since
          ** the permanent table is hidden by the TEMP table, we can also
          ** safely ignore the index on the permanent table.
          */
          /* Do Nothing */;
................................................................................
  int rc;
  BtCursor *curMain;
  int size;
  Table *pTab;
  char *azArg[6];
  char zDbNum[30];
  int meta[SQLITE_N_BTREE_META];
  Parse sParse;
  InitData initData;

  /*
  ** The master database table has a structure like this
  */
  static char master_schema[] = 
     "CREATE TABLE sqlite_master(\n"
................................................................................
     "WHERE type='index'";


  assert( iDb>=0 && iDb!=1 && iDb<db->nDb );

  /* Construct the schema tables: sqlite_master and sqlite_temp_master
  */

  azArg[0] = "table";
  azArg[1] = MASTER_NAME;
  azArg[2] = "2";
  azArg[3] = master_schema;
  sprintf(zDbNum, "%d", iDb);
  azArg[4] = zDbNum;
  azArg[5] = 0;
................................................................................
    azArg[4] = "1";
    sqliteInitCallback(&initData, 5, azArg, 0);
    pTab = sqliteFindTable(db, TEMP_MASTER_NAME, "temp");
    if( pTab ){
      pTab->readOnly = 1;
    }
  }


  /* Create a cursor to hold the database open
  */
  if( db->aDb[iDb].pBt==0 ) return SQLITE_OK;
  rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain);
  if( rc ){
    sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0);
................................................................................
    return SQLITE_FORMAT;
  }
  sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size);
  sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]);

  /* Read the schema information out of the schema tables
  */
  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  sParse.xCallback = sqliteInitCallback;
  sParse.pArg = (void*)&initData;
  sParse.initFlag = 1;
  sParse.useCallback = 1;
  if( iDb==0 ){
    sqliteRunParser(&sParse,

        db->file_format>=2 ? init_script : older_init_script,
        pzErrMsg);

  }else{
    char *zSql = 0;
    sqliteSetString(&zSql, 
       "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
       db->aDb[iDb].zName, "\".sqlite_master", (char*)0);
    sqliteRunParser(&sParse, zSql, pzErrMsg);
    sqliteFree(zSql);
  }

  sqliteBtreeCloseCursor(curMain);
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", (char*)0);
    sParse.rc = SQLITE_NOMEM;
    sqliteResetInternalSchema(db, 0);
  }
  if( sParse.rc==SQLITE_OK ){
    DbSetProperty(db, iDb, DB_SchemaLoaded);
    if( iDb==0 ){
      DbSetProperty(db, 1, DB_SchemaLoaded);
    }
  }else{
    sqliteResetInternalSchema(db, iDb);
  }
  return sParse.rc;
}

/*
** Initialize all database files - the main database file, the file
** used to store temporary tables, and any additional database files
** created using ATTACH statements.  Return a success code.  If an
** error occurs, write an error message into *pzErrMsg.
................................................................................
** is opened.  If that fails (perhaps because another process
** has the sqlite_master table locked) than another attempt
** is made the first time the database is accessed.
*/
int sqliteInit(sqlite *db, char **pzErrMsg){
  int i, rc;
  

  assert( (db->flags & SQLITE_Initialized)==0 );
  rc = SQLITE_OK;

  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
    if( DbHasProperty(db, i, DB_SchemaLoaded) ) continue;
    assert( i!=1 );  /* Should have been initialized together with 0 */
    rc = sqliteInitOne(db, i, pzErrMsg);
    if( rc ){
      sqliteResetInternalSchema(db, i);
    }
  }

  if( rc==SQLITE_OK ){
    db->flags |= SQLITE_Initialized;
    sqliteCommitInternalChanges(db);
  }

  /* If the database is in formats 1 or 2, then upgrade it to
  ** version 3.  This will reconstruct all indices.  If the
................................................................................
  sqlite_vm **ppVm,           /* OUT: The virtual machine */
  char **pzErrMsg             /* OUT: Write error messages here */
){
  Parse sParse;

  if( pzErrMsg ) *pzErrMsg = 0;
  if( sqliteSafetyOn(db) ) goto exec_misuse;

  if( (db->flags & SQLITE_Initialized)==0 ){
    int rc, cnt = 1;
    while( (rc = sqliteInit(db, pzErrMsg))==SQLITE_BUSY

       && db->xBusyCallback && db->xBusyCallback(db->pBusyArg, "", cnt++)!=0 ){}
    if( rc!=SQLITE_OK ){
      sqliteStrRealloc(pzErrMsg);
      sqliteSafetyOff(db);
      return rc;
    }
    if( pzErrMsg ){
      sqliteFree(*pzErrMsg);
................................................................................
    }
  }
  if( db->file_format<3 ){
    sqliteSafetyOff(db);
    sqliteSetString(pzErrMsg, "obsolete database file format", (char*)0);
    return SQLITE_ERROR;
  }


  if( db->pVdbe==0 ){ db->nChange = 0; }
  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  sParse.useCallback = 0;
  if( db->xTrace ) db->xTrace(db->pTraceArg, zSql);
  sqliteRunParser(&sParse, zSql, pzErrMsg);
  if( sqlite_malloc_failed ){







|







 







|
|
>







 







<





|






>

|




|



|
|
<
|
>
|
|
|
>
>
>











|
|







 







<







 







>







 







>







 







|
|
<
<
<
<

<
>

<
>





|


>



|


|







|







 







>


>








>







 







>



>
|







 







>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
..
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
188
189
190
191
192
193
194

195
196
197
198
199
200
201
...
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
...
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
...
331
332
333
334
335
336
337
338
339




340

341
342

343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
...
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
...
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.154 2004/02/14 23:05:53 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information
................................................................................
  char **pzErrMsg;    /* Error message stored here */
} InitData;

/*
** Fill the InitData structure with an error message that indicates
** that the database is corrupt.
*/
static void corruptSchema(InitData *pData, const char *zExtra){
  sqliteSetString(pData->pzErrMsg, "malformed database schema",
     zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
}

/*
** This is the callback routine for the code that initializes the
** database.  See sqliteInit() below for additional information.
**
** Each callback contains the following information:
................................................................................
**     argv[4] = "1" for temporary files, "0" for main database, "2" or more
**               for auxiliary database files.
**
*/
static
int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){
  InitData *pData = (InitData*)pInit;

  int nErr = 0;

  assert( argc==5 );
  if( argv==0 ) return 0;   /* Might happen if EMPTY_RESULT_CALLBACKS are on */
  if( argv[0]==0 ){
    corruptSchema(pData, 0);
    return 1;
  }
  switch( argv[0][0] ){
    case 'v':
    case 'i':
    case 't': {  /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */
      sqlite *db = pData->db;
      if( argv[2]==0 || argv[4]==0 ){
        corruptSchema(pData, 0);
        return 1;
      }
      if( argv[3] && argv[3][0] ){
        /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
        ** But because db->init.busy is set to 1, no VDBE code is generated
        ** or executed.  All the parser does is build the internal data
        ** structures that describe the table, index, or view.
        */
        char *zErr;
        assert( db->init.busy );

        db->init.iDb = atoi(argv[4]);
        assert( db->init.iDb>=0 && db->init.iDb<db->nDb );
        db->init.newTnum = atoi(argv[2]);
        if( sqlite_exec(db, argv[3], 0, 0, &zErr) ){
          corruptSchema(pData, zErr);
          sqlite_freemem(zErr);
        }
        db->init.iDb = 0;
      }else{
        /* If the SQL column is blank it means this is an index that
        ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
        ** constraint for a CREATE TABLE.  The index should have already
        ** been created when we processed the CREATE TABLE.  All we have
        ** to do here is record the root page number for that index.
        */
        int iDb;
        Index *pIndex;

        iDb = atoi(argv[4]);
        assert( iDb>=0 && iDb<db->nDb );
        pIndex = sqliteFindIndex(db, argv[1], db->aDb[iDb].zName);
        if( pIndex==0 || pIndex->tnum!=0 ){
          /* This can occur if there exists an index on a TEMP table which
          ** has the same name as another index on a permanent index.  Since
          ** the permanent table is hidden by the TEMP table, we can also
          ** safely ignore the index on the permanent table.
          */
          /* Do Nothing */;
................................................................................
  int rc;
  BtCursor *curMain;
  int size;
  Table *pTab;
  char *azArg[6];
  char zDbNum[30];
  int meta[SQLITE_N_BTREE_META];

  InitData initData;

  /*
  ** The master database table has a structure like this
  */
  static char master_schema[] = 
     "CREATE TABLE sqlite_master(\n"
................................................................................
     "WHERE type='index'";


  assert( iDb>=0 && iDb!=1 && iDb<db->nDb );

  /* Construct the schema tables: sqlite_master and sqlite_temp_master
  */
  sqliteSafetyOff(db);
  azArg[0] = "table";
  azArg[1] = MASTER_NAME;
  azArg[2] = "2";
  azArg[3] = master_schema;
  sprintf(zDbNum, "%d", iDb);
  azArg[4] = zDbNum;
  azArg[5] = 0;
................................................................................
    azArg[4] = "1";
    sqliteInitCallback(&initData, 5, azArg, 0);
    pTab = sqliteFindTable(db, TEMP_MASTER_NAME, "temp");
    if( pTab ){
      pTab->readOnly = 1;
    }
  }
  sqliteSafetyOn(db);

  /* Create a cursor to hold the database open
  */
  if( db->aDb[iDb].pBt==0 ) return SQLITE_OK;
  rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain);
  if( rc ){
    sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0);
................................................................................
    return SQLITE_FORMAT;
  }
  sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size);
  sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]);

  /* Read the schema information out of the schema tables
  */
  assert( db->init.busy );
  sqliteSafetyOff(db);




  if( iDb==0 ){

    rc = sqlite_exec(db, 
        db->file_format>=2 ? init_script : older_init_script,

        sqliteInitCallback, &initData, 0);
  }else{
    char *zSql = 0;
    sqliteSetString(&zSql, 
       "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
       db->aDb[iDb].zName, "\".sqlite_master", (char*)0);
    rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
    sqliteFree(zSql);
  }
  sqliteSafetyOn(db);
  sqliteBtreeCloseCursor(curMain);
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", (char*)0);
    rc = SQLITE_NOMEM;
    sqliteResetInternalSchema(db, 0);
  }
  if( rc==SQLITE_OK ){
    DbSetProperty(db, iDb, DB_SchemaLoaded);
    if( iDb==0 ){
      DbSetProperty(db, 1, DB_SchemaLoaded);
    }
  }else{
    sqliteResetInternalSchema(db, iDb);
  }
  return rc;
}

/*
** Initialize all database files - the main database file, the file
** used to store temporary tables, and any additional database files
** created using ATTACH statements.  Return a success code.  If an
** error occurs, write an error message into *pzErrMsg.
................................................................................
** is opened.  If that fails (perhaps because another process
** has the sqlite_master table locked) than another attempt
** is made the first time the database is accessed.
*/
int sqliteInit(sqlite *db, char **pzErrMsg){
  int i, rc;
  
  if( db->init.busy ) return SQLITE_OK;
  assert( (db->flags & SQLITE_Initialized)==0 );
  rc = SQLITE_OK;
  db->init.busy = 1;
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
    if( DbHasProperty(db, i, DB_SchemaLoaded) ) continue;
    assert( i!=1 );  /* Should have been initialized together with 0 */
    rc = sqliteInitOne(db, i, pzErrMsg);
    if( rc ){
      sqliteResetInternalSchema(db, i);
    }
  }
  db->init.busy = 0;
  if( rc==SQLITE_OK ){
    db->flags |= SQLITE_Initialized;
    sqliteCommitInternalChanges(db);
  }

  /* If the database is in formats 1 or 2, then upgrade it to
  ** version 3.  This will reconstruct all indices.  If the
................................................................................
  sqlite_vm **ppVm,           /* OUT: The virtual machine */
  char **pzErrMsg             /* OUT: Write error messages here */
){
  Parse sParse;

  if( pzErrMsg ) *pzErrMsg = 0;
  if( sqliteSafetyOn(db) ) goto exec_misuse;
  if( !db->init.busy ){
    if( (db->flags & SQLITE_Initialized)==0 ){
      int rc, cnt = 1;
      while( (rc = sqliteInit(db, pzErrMsg))==SQLITE_BUSY
         && db->xBusyCallback
         && db->xBusyCallback(db->pBusyArg, "", cnt++)!=0 ){}
      if( rc!=SQLITE_OK ){
        sqliteStrRealloc(pzErrMsg);
        sqliteSafetyOff(db);
        return rc;
      }
      if( pzErrMsg ){
        sqliteFree(*pzErrMsg);
................................................................................
      }
    }
    if( db->file_format<3 ){
      sqliteSafetyOff(db);
      sqliteSetString(pzErrMsg, "obsolete database file format", (char*)0);
      return SQLITE_ERROR;
    }
  }
  assert( (db->flags & SQLITE_Initialized)!=0 || db->init.busy );
  if( db->pVdbe==0 ){ db->nChange = 0; }
  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  sParse.useCallback = 0;
  if( db->xTrace ) db->xTrace(db->pTraceArg, zSql);
  sqliteRunParser(&sParse, zSql, pzErrMsg);
  if( sqlite_malloc_failed ){

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
314
315
316
317
318
319
320


321
322
323
324
325
326
327
328
329
330
331
332
333
334





335
336
337
338
339
340
341
...
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.211 2004/02/12 18:46:39 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
................................................................................
  int nDb;                      /* Number of backends currently in use */
  Db *aDb;                      /* All backends */
  Db aDbStatic[2];              /* Static space for the 2 default backends */
  int flags;                    /* Miscellanous flags. See below */
  u8 file_format;               /* What file format version is this database? */
  u8 safety_level;              /* How aggressive at synching data to disk */
  u8 want_to_close;             /* Close after all VDBEs are deallocated */


  int next_cookie;              /* Next value of aDb[0].schema_cookie */
  int cache_size;               /* Number of pages to use in the cache */
  int temp_store;               /* 1=file, 2=memory, 0=compile-time default */
  int nTable;                   /* Number of tables in the database */
  void *pBusyArg;               /* 1st Argument to the busy callback */
  int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
  void *pCommitArg;             /* Argument to xCommitCallback() */   
  int (*xCommitCallback)(void*);/* Invoked at every commit. */
  Hash aFunc;                   /* All functions that can be in SQL exprs */
  int lastRowid;                /* ROWID of most recent insert */
  int priorNewRowid;            /* Last randomly generated ROWID */
  int onError;                  /* Default conflict algorithm */
  int magic;                    /* Magic number for detect library misuse */
  int nChange;                  /* Number of rows changed */





  struct Vdbe *pVdbe;           /* List of active virtual machines */
  void (*xTrace)(void*,const char*);     /* Trace function */
  void *pTraceArg;                       /* Argument to the trace function */
#ifndef SQLITE_OMIT_AUTHORIZATION
  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
                                /* Access authorization function */
  void *pAuthArg;               /* 1st argument to the access auth function */
................................................................................
  Token sFirstToken;   /* The first token parsed */
  Token sLastToken;    /* The last token parsed */
  const char *zTail;   /* All SQL text past the last semicolon parsed */
  Table *pNewTable;    /* A table being constructed by CREATE TABLE */
  Vdbe *pVdbe;         /* An engine for executing database bytecode */
  u8 colNamesSet;      /* TRUE after OP_ColumnName has been issued to pVdbe */
  u8 explain;          /* True if the EXPLAIN flag is found on the query */
  u8 initFlag;         /* True if reparsing CREATE TABLEs */
  u8 nameClash;        /* A permanent table name clashes with temp table name */
  u8 useAgg;           /* If true, extract field values from the aggregator
                       ** while generating expressions.  Normally false */
  u8 iDb;              /* Index of database whose schema is being parsed */
  u8 useCallback;      /* True if callbacks should be used to report results */
  int newTnum;         /* Table number to use when reparsing CREATE TABLEs */
  int nErr;            /* Number of errors seen */
  int nTab;            /* Number of previously allocated VDBE cursors */
  int nMem;            /* Number of memory cells used so far */
  int nSet;            /* Number of sets used so far */
  int nAgg;            /* Number of aggregate expressions */
  int nVar;            /* Number of '?' variables seen in the SQL so far */
  AggExpr *aAgg;       /* An array of aggregate expressions */







|







 







>
>


<








<


>
>
>
>
>







 







<



<

<







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
314
315
316
317
318
319
320
321
322
323
324

325
326
327
328
329
330
331
332

333
334
335
336
337
338
339
340
341
342
343
344
345
346
...
879
880
881
882
883
884
885

886
887
888

889

890
891
892
893
894
895
896
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.212 2004/02/14 23:05:53 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
................................................................................
  int nDb;                      /* Number of backends currently in use */
  Db *aDb;                      /* All backends */
  Db aDbStatic[2];              /* Static space for the 2 default backends */
  int flags;                    /* Miscellanous flags. See below */
  u8 file_format;               /* What file format version is this database? */
  u8 safety_level;              /* How aggressive at synching data to disk */
  u8 want_to_close;             /* Close after all VDBEs are deallocated */
  u8 temp_store;                /* 1=file, 2=memory, 0=compile-time default */
  u8 onError;                   /* Default conflict algorithm */
  int next_cookie;              /* Next value of aDb[0].schema_cookie */
  int cache_size;               /* Number of pages to use in the cache */

  int nTable;                   /* Number of tables in the database */
  void *pBusyArg;               /* 1st Argument to the busy callback */
  int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
  void *pCommitArg;             /* Argument to xCommitCallback() */   
  int (*xCommitCallback)(void*);/* Invoked at every commit. */
  Hash aFunc;                   /* All functions that can be in SQL exprs */
  int lastRowid;                /* ROWID of most recent insert */
  int priorNewRowid;            /* Last randomly generated ROWID */

  int magic;                    /* Magic number for detect library misuse */
  int nChange;                  /* Number of rows changed */
  struct sqliteInitInfo {       /* Information used during initialization */
    int iDb;                       /* When back is being initialized */
    int newTnum;                   /* Rootpage of table being initialized */
    u8 busy;                       /* TRUE if currently initializing */
  } init;
  struct Vdbe *pVdbe;           /* List of active virtual machines */
  void (*xTrace)(void*,const char*);     /* Trace function */
  void *pTraceArg;                       /* Argument to the trace function */
#ifndef SQLITE_OMIT_AUTHORIZATION
  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
                                /* Access authorization function */
  void *pAuthArg;               /* 1st argument to the access auth function */
................................................................................
  Token sFirstToken;   /* The first token parsed */
  Token sLastToken;    /* The last token parsed */
  const char *zTail;   /* All SQL text past the last semicolon parsed */
  Table *pNewTable;    /* A table being constructed by CREATE TABLE */
  Vdbe *pVdbe;         /* An engine for executing database bytecode */
  u8 colNamesSet;      /* TRUE after OP_ColumnName has been issued to pVdbe */
  u8 explain;          /* True if the EXPLAIN flag is found on the query */

  u8 nameClash;        /* A permanent table name clashes with temp table name */
  u8 useAgg;           /* If true, extract field values from the aggregator
                       ** while generating expressions.  Normally false */

  u8 useCallback;      /* True if callbacks should be used to report results */

  int nErr;            /* Number of errors seen */
  int nTab;            /* Number of previously allocated VDBE cursors */
  int nMem;            /* Number of memory cells used so far */
  int nSet;            /* Number of sets used so far */
  int nAgg;            /* Number of aggregate expressions */
  int nVar;            /* Number of '?' variables seen in the SQL so far */
  AggExpr *aAgg;       /* An array of aggregate expressions */

Changes to src/trigger.c.

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  ** 2. the table (or view) does exist in the same database as the trigger.
  ** 3. that we are not trying to create a trigger on the sqlite_master table
  ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
  ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
  */
  if( sqlite_malloc_failed ) goto trigger_cleanup;
  assert( pTableName->nSrc==1 );
  if( pParse->initFlag 
   && sqliteFixInit(&sFix, pParse, pParse->iDb, "trigger", pName)
   && sqliteFixSrcList(&sFix, pTableName)
  ){
    goto trigger_cleanup;
  }
  tab = sqliteSrcListLookup(pParse, pTableName);
  if( !tab ){
    goto trigger_cleanup;
  }
  iDb = isTemp ? 1 : tab->iDb;
  if( iDb>=2 && !pParse->initFlag ){
    sqliteErrorMsg(pParse, "triggers may not be added to auxiliary "
       "database %s", db->aDb[tab->iDb].zName);
    goto trigger_cleanup;
  }

  zName = sqliteStrNDup(pName->z, pName->n);
  sqliteDequote(zName);
................................................................................
          && sqliteFixTriggerStep(&sFix, nt->step_list) ){
    goto triggerfinish_cleanup;
  }

  /* if we are not initializing, and this trigger is not on a TEMP table, 
  ** build the sqlite_master entry
  */
  if( !pParse->initFlag ){
    static VdbeOp insertTrig[] = {
      { OP_NewRecno,   0, 0,  0          },
      { OP_String,     0, 0,  "trigger"  },
      { OP_String,     0, 0,  0          },  /* 2: trigger name */
      { OP_String,     0, 0,  0          },  /* 3: table name */
      { OP_Integer,    0, 0,  0          },
      { OP_String,     0, 0,  0          },  /* 5: SQL */







|
|









|







 







|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  ** 2. the table (or view) does exist in the same database as the trigger.
  ** 3. that we are not trying to create a trigger on the sqlite_master table
  ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
  ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
  */
  if( sqlite_malloc_failed ) goto trigger_cleanup;
  assert( pTableName->nSrc==1 );
  if( db->init.busy
   && sqliteFixInit(&sFix, pParse, db->init.iDb, "trigger", pName)
   && sqliteFixSrcList(&sFix, pTableName)
  ){
    goto trigger_cleanup;
  }
  tab = sqliteSrcListLookup(pParse, pTableName);
  if( !tab ){
    goto trigger_cleanup;
  }
  iDb = isTemp ? 1 : tab->iDb;
  if( iDb>=2 && !db->init.busy ){
    sqliteErrorMsg(pParse, "triggers may not be added to auxiliary "
       "database %s", db->aDb[tab->iDb].zName);
    goto trigger_cleanup;
  }

  zName = sqliteStrNDup(pName->z, pName->n);
  sqliteDequote(zName);
................................................................................
          && sqliteFixTriggerStep(&sFix, nt->step_list) ){
    goto triggerfinish_cleanup;
  }

  /* if we are not initializing, and this trigger is not on a TEMP table, 
  ** build the sqlite_master entry
  */
  if( !db->init.busy ){
    static VdbeOp insertTrig[] = {
      { OP_NewRecno,   0, 0,  0          },
      { OP_String,     0, 0,  "trigger"  },
      { OP_String,     0, 0,  0          },  /* 2: trigger name */
      { OP_String,     0, 0,  0          },  /* 3: table name */
      { OP_Integer,    0, 0,  0          },
      { OP_String,     0, 0,  0          },  /* 5: SQL */