SQLite4
Check-in [31b1faa995]
Not logged in

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

Overview
Comment:Remove the OP_CreateTable and OP_CreateIndex opcodes, which are not required with the key/value backend.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 31b1faa9954a449ce6774256e0eddd551e74b347
User & Date: drh 2012-02-22 00:11:19
Context
2012-02-22
02:44
Remove the OP_Destroy opcode. Add an implementation for OP_Clear. check-in: 15cf832dfc user: drh tags: trunk
00:11
Remove the OP_CreateTable and OP_CreateIndex opcodes, which are not required with the key/value backend. check-in: 31b1faa995 user: drh tags: trunk
2012-02-21
20:03
Only the bare basics work. But we might as well go ahead and call this the trunk since we are unlikely to ever need to bisect back into this massive rewrite effort. check-in: a101b3e1c4 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

207
208
209
210
211
212
213

















214
215
216
217
218
219
220
...
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
...
869
870
871
872
873
874
875

876
877
878
879
880
881
882
883
....
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
....
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
....
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
....
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
....
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
....
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
  pParse->nTab = 0;
  pParse->nMem = 0;
  pParse->nSet = 0;
  pParse->nVar = 0;
  pParse->cookieMask = 0;
  pParse->cookieGoto = 0;
}


















/*
** Run the parser and code generator recursively in order to generate
** code for the SQL statement given onto the end of the pParse context
** currently under construction.  When the parser is run recursively
** this way, the final OP_Halt is not appended and other initialization
** and finalization steps are omitted because those are handling by the
................................................................................

#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( isVirtual ){
      sqlite4VdbeAddOp0(v, OP_VBegin);
    }
#endif


    /* This just creates a place-holder record in the sqlite_master table.
    ** The record created does not contain anything yet.  It will be replaced
    ** by the real entry in code generated at sqlite4EndTable().
    **
    ** The rowid for the new entry is left in register pParse->regRowid.
    ** The root page number of the new table is left in reg pParse->regRoot.
    ** The rowid and root page number values are needed by the code that
................................................................................
    reg3 = ++pParse->nMem;
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
    if( isView || isVirtual ){
      sqlite4VdbeAddOp2(v, OP_Integer, 0, reg2);
    }else
#endif
    {

      sqlite4VdbeAddOp2(v, OP_CreateTable, iDb, reg2);
    }
    sqlite4OpenMasterTable(pParse, iDb);
    sqlite4VdbeAddOp2(v, OP_NewRowid, 0, reg1);
    sqlite4VdbeAddOp2(v, OP_Null, 0, reg3);
    sqlite4VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
    sqlite4VdbeChangeP5(v, OPFLAG_APPEND);
    sqlite4VdbeAddOp0(v, OP_Close);
................................................................................
#endif
}

/*
** Generate code that will erase and refill index *pIdx.  This is
** used to initialize a newly created index or to recompute the
** content of an index in response to a REINDEX command.
**
** if memRootPage is not negative, it means that the index is newly
** created.  The register specified by memRootPage contains the
** root page number of the index.  If memRootPage is negative, then
** the index already exists and must be cleared before being refilled and
** the root page number of the index is taken from pIndex->tnum.
*/
static void sqlite4RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
  Table *pTab = pIndex->pTable;  /* The table that is indexed */
  int iTab = pParse->nTab++;     /* Cursor used for pTab */
  int iIdx = pParse->nTab++;     /* Cursor used for pIndex */
  int iSorter;                   /* Cursor opened by OpenSorter (if in use) */
  int addr1;                     /* Address of top of loop */
  int addr2;                     /* Address to jump to for next iteration */
  int tnum;                      /* Root page of index */
................................................................................
#endif

  /* Require a write-lock on the table to perform this operation */
  sqlite4TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);

  v = sqlite4GetVdbe(pParse);
  if( v==0 ) return;
  if( memRootPage>=0 ){
    tnum = memRootPage;
  }else{
    tnum = pIndex->tnum;
    sqlite4VdbeAddOp2(v, OP_Clear, tnum, iDb);
  }
  pKey = sqlite4IndexKeyinfo(pParse, pIndex);
  sqlite4VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
                    (char *)pKey, P4_KEYINFO_HANDOFF);
  if( memRootPage>=0 ){
    sqlite4VdbeChangeP5(v, 1);
  }

#ifndef SQLITE_OMIT_MERGE_SORT
  /* Open the sorter cursor if we are to use one. */
  iSorter = pParse->nTab++;
  sqlite4VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
#else
  iSorter = iTab;
................................................................................
  ** 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 ) */
    Vdbe *v;
    char *zStmt;
    int iMem = ++pParse->nMem;

    v = sqlite4GetVdbe(pParse);
    if( v==0 ) goto exit_create_index;


    /* Create the rootpage for the index
    */
    sqlite4BeginWriteOperation(pParse, 1, iDb);
    sqlite4VdbeAddOp2(v, OP_CreateIndex, iDb, iMem);

    /* Gather the complete text of the CREATE INDEX statement into
    ** the zStmt variable
    */
    if( pStart ){
      assert( pEnd!=0 );
      /* A named index with an explicit CREATE INDEX statement */
................................................................................
      /* zStmt = sqlite4MPrintf(""); */
      zStmt = 0;
    }

    /* Add an entry in sqlite_master for this index
    */
    sqlite4NestedParse(pParse, 
        "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
        db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
        pIndex->zName,
        pTab->zName,
        iMem,
        zStmt
    );
    sqlite4DbFree(db, zStmt);

    /* Fill the index with data and reparse the schema. Code an OP_Expire
    ** to invalidate all pre-compiled statements.
    */
    if( pTblName ){
      sqlite4RefillIndex(pParse, pIndex, iMem);
      sqlite4ChangeCookie(pParse, iDb);
      sqlite4VdbeAddParseSchemaOp(v, iDb,
         sqlite4MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
      sqlite4VdbeAddOp1(v, OP_Expire, 0);
    }
  }

................................................................................
static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
  Index *pIndex;              /* An index associated with pTab */

  for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
    if( zColl==0 || collationMatch(zColl, pIndex) ){
      int iDb = sqlite4SchemaToIndex(pParse->db, pTab->pSchema);
      sqlite4BeginWriteOperation(pParse, 0, iDb);
      sqlite4RefillIndex(pParse, pIndex, -1);
    }
  }
}
#endif

/*
** Recompute all indices of all tables in all databases where the
................................................................................
    sqlite4DbFree(db, z);
    return;
  }
  pIndex = sqlite4FindIndex(db, z, zDb);
  sqlite4DbFree(db, z);
  if( pIndex ){
    sqlite4BeginWriteOperation(pParse, 0, iDb);
    sqlite4RefillIndex(pParse, pIndex, -1);
    return;
  }
  sqlite4ErrorMsg(pParse, "unable to identify the object to be reindexed");
}
#endif

/*







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<







 







>
|







 







<
<
<
<
<
<

|







 







<
<
<
|
|
<



<
<
<







 







<








|







 







|



|








|







 







|







 







|







207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
...
867
868
869
870
871
872
873

874
875
876
877
878
879
880
...
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
....
2208
2209
2210
2211
2212
2213
2214






2215
2216
2217
2218
2219
2220
2221
2222
2223
....
2238
2239
2240
2241
2242
2243
2244



2245
2246

2247
2248
2249



2250
2251
2252
2253
2254
2255
2256
....
2716
2717
2718
2719
2720
2721
2722

2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
....
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
....
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
....
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
  pParse->nTab = 0;
  pParse->nMem = 0;
  pParse->nSet = 0;
  pParse->nVar = 0;
  pParse->cookieMask = 0;
  pParse->cookieGoto = 0;
}

/*
** Find an available table number for database iDb
*/
static int firstAvailableTableNumber(sqlite4 *db, int iDb){
  HashElem *i;
  int maxTab = 1;
  for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); i;i=sqliteHashNext(i)){
    Table *pTab = (Table*)sqliteHashData(i);
    if( pTab->tnum > maxTab ) maxTab = pTab->tnum;
  }
  for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash); i;i=sqliteHashNext(i)){
    Index *pIdx = (Index*)sqliteHashData(i);
    if( pIdx->tnum > maxTab ) maxTab = pIdx->tnum;
  }
  return maxTab+1;
}

/*
** Run the parser and code generator recursively in order to generate
** code for the SQL statement given onto the end of the pParse context
** currently under construction.  When the parser is run recursively
** this way, the final OP_Halt is not appended and other initialization
** and finalization steps are omitted because those are handling by the
................................................................................

#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( isVirtual ){
      sqlite4VdbeAddOp0(v, OP_VBegin);
    }
#endif


    /* This just creates a place-holder record in the sqlite_master table.
    ** The record created does not contain anything yet.  It will be replaced
    ** by the real entry in code generated at sqlite4EndTable().
    **
    ** The rowid for the new entry is left in register pParse->regRowid.
    ** The root page number of the new table is left in reg pParse->regRoot.
    ** The rowid and root page number values are needed by the code that
................................................................................
    reg3 = ++pParse->nMem;
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
    if( isView || isVirtual ){
      sqlite4VdbeAddOp2(v, OP_Integer, 0, reg2);
    }else
#endif
    {
      int tnum = firstAvailableTableNumber(db, iDb);
      sqlite4VdbeAddOp2(v, OP_Integer, tnum, reg2);
    }
    sqlite4OpenMasterTable(pParse, iDb);
    sqlite4VdbeAddOp2(v, OP_NewRowid, 0, reg1);
    sqlite4VdbeAddOp2(v, OP_Null, 0, reg3);
    sqlite4VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
    sqlite4VdbeChangeP5(v, OPFLAG_APPEND);
    sqlite4VdbeAddOp0(v, OP_Close);
................................................................................
#endif
}

/*
** Generate code that will erase and refill index *pIdx.  This is
** used to initialize a newly created index or to recompute the
** content of an index in response to a REINDEX command.






*/
static void sqlite4RefillIndex(Parse *pParse, Index *pIndex){
  Table *pTab = pIndex->pTable;  /* The table that is indexed */
  int iTab = pParse->nTab++;     /* Cursor used for pTab */
  int iIdx = pParse->nTab++;     /* Cursor used for pIndex */
  int iSorter;                   /* Cursor opened by OpenSorter (if in use) */
  int addr1;                     /* Address of top of loop */
  int addr2;                     /* Address to jump to for next iteration */
  int tnum;                      /* Root page of index */
................................................................................
#endif

  /* Require a write-lock on the table to perform this operation */
  sqlite4TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);

  v = sqlite4GetVdbe(pParse);
  if( v==0 ) return;



  tnum = pIndex->tnum;
  sqlite4VdbeAddOp2(v, OP_Clear, tnum, iDb);

  pKey = sqlite4IndexKeyinfo(pParse, pIndex);
  sqlite4VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
                    (char *)pKey, P4_KEYINFO_HANDOFF);




#ifndef SQLITE_OMIT_MERGE_SORT
  /* Open the sorter cursor if we are to use one. */
  iSorter = pParse->nTab++;
  sqlite4VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
#else
  iSorter = iTab;
................................................................................
  ** 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 ) */
    Vdbe *v;
    char *zStmt;


    v = sqlite4GetVdbe(pParse);
    if( v==0 ) goto exit_create_index;


    /* Create the rootpage for the index
    */
    sqlite4BeginWriteOperation(pParse, 1, iDb);
    pIndex->tnum = firstAvailableTableNumber(db, iDb);

    /* Gather the complete text of the CREATE INDEX statement into
    ** the zStmt variable
    */
    if( pStart ){
      assert( pEnd!=0 );
      /* A named index with an explicit CREATE INDEX statement */
................................................................................
      /* zStmt = sqlite4MPrintf(""); */
      zStmt = 0;
    }

    /* Add an entry in sqlite_master for this index
    */
    sqlite4NestedParse(pParse, 
        "INSERT INTO %Q.%s VALUES('index',%Q,%Q,%d,%Q);",
        db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
        pIndex->zName,
        pTab->zName,
        pIndex->tnum,
        zStmt
    );
    sqlite4DbFree(db, zStmt);

    /* Fill the index with data and reparse the schema. Code an OP_Expire
    ** to invalidate all pre-compiled statements.
    */
    if( pTblName ){
      sqlite4RefillIndex(pParse, pIndex);
      sqlite4ChangeCookie(pParse, iDb);
      sqlite4VdbeAddParseSchemaOp(v, iDb,
         sqlite4MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
      sqlite4VdbeAddOp1(v, OP_Expire, 0);
    }
  }

................................................................................
static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
  Index *pIndex;              /* An index associated with pTab */

  for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
    if( zColl==0 || collationMatch(zColl, pIndex) ){
      int iDb = sqlite4SchemaToIndex(pParse->db, pTab->pSchema);
      sqlite4BeginWriteOperation(pParse, 0, iDb);
      sqlite4RefillIndex(pParse, pIndex);
    }
  }
}
#endif

/*
** Recompute all indices of all tables in all databases where the
................................................................................
    sqlite4DbFree(db, z);
    return;
  }
  pIndex = sqlite4FindIndex(db, z, zDb);
  sqlite4DbFree(db, z);
  if( pIndex ){
    sqlite4BeginWriteOperation(pParse, 0, iDb);
    sqlite4RefillIndex(pParse, pIndex);
    return;
  }
  sqlite4ErrorMsg(pParse, "unable to identify the object to be reindexed");
}
#endif

/*

Changes to src/vdbe.c.

3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
** See also: Destroy
*/
case OP_Clear: {
  assert( 0 );
  break;
}

/* Opcode: CreateTable P1 P2 * * *
**
** Allocate a new table in the main database file if P1==0 or in the
** auxiliary database file if P1==1 or in an attached database if
** P1>1.  Write the root page number of the new table into
** register P2
**
** The difference between a table and an index is this:  A table must
** have a 4-byte integer key and can have arbitrary data.  An index
** has an arbitrary key but no data.
**
** See also: CreateIndex
*/
/* Opcode: CreateIndex P1 P2 * * *
**
** Allocate a new index in the main database file if P1==0 or in the
** auxiliary database file if P1==1 or in an attached database if
** P1>1.  Write the root page number of the new table into
** register P2.
**
** See documentation on OP_CreateTable for additional information.
*/
case OP_CreateIndex:            /* out2-prerelease */
case OP_CreateTable: {          /* out2-prerelease */
  sqlite4_uint64 iTabno;
  Db *pDb;
  KVCursor *pCur;
  const KVByteArray *aKey;
  KVSize nKey;
  int n;
  KVByteArray aProbe[12];

  iTabno = 0;
  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  pDb = &db->aDb[pOp->p1];
  memset(aProbe, 0xff, 9);
  rc = sqlite4KVStoreOpenCursor(pDb->pKV, &pCur);
  if( rc ) break;
  rc = sqlite4KVCursorSeek(pCur, aProbe, 9, -1);
  if( rc==SQLITE_OK ){
    sqlite4KVCursorClose(pCur);
    rc = SQLITE_CORRUPT;
    break;
  }
  if( rc==SQLITE_NOTFOUND ){
    iTabno = 2;
    n = 1;
    rc = SQLITE_OK;
  }else if( rc==SQLITE_INEXACT ){
    rc = sqlite4KVCursorKey(pCur, &aKey, &nKey);
    n = sqlite4GetVarint64(aKey, nKey, &iTabno);
  }else{
    break;
  }
  sqlite4KVCursorClose(pCur);
  if( n==0 ){
    rc = SQLITE_CORRUPT;
  }
  pOut->u.i = iTabno;
  break;
}

/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
** that match the WHERE clause P4. 
**
** This opcode invokes the parser to create a new virtual machine,







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







3713
3714
3715
3716
3717
3718
3719





























































3720
3721
3722
3723
3724
3725
3726
** See also: Destroy
*/
case OP_Clear: {
  assert( 0 );
  break;
}































































/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
** that match the WHERE clause P4. 
**
** This opcode invokes the parser to create a new virtual machine,