/ Check-in [88fa510e]
Login

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

Overview
Comment:Simple tests and fixes for writing to virtual tables. (CVS 3252)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 88fa510e4c684513bbb59031d034fdb5c51a6a15
User & Date: danielk1977 2006-06-15 07:29:01
Context
2006-06-15
10:41
Add tests (and modify test code) for writing to virtual tables. (CVS 3253) check-in: 6380a9b1 user: danielk1977 tags: trunk
07:29
Simple tests and fixes for writing to virtual tables. (CVS 3252) check-in: 88fa510e user: danielk1977 tags: trunk
04:28
Add void* argument to sqlite3_create_module to replace sqlite3_module.pAux. (CVS 3251) check-in: 470a3a0b user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
....
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
....
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
....
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
....
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.400 2006/06/14 19:00:21 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Initialize the pParse structure as needed.
................................................................................
  int onError,      /* What to do with a uniqueness conflict */
  int autoInc,      /* True if the AUTOINCREMENT keyword is present */
  int sortOrder     /* SQLITE_SO_ASC or SQLITE_SO_DESC */
){
  Table *pTab = pParse->pNewTable;
  char *zType = 0;
  int iCol = -1, i;
  if( pTab==0 ) goto primary_key_exit;
  if( pTab->hasPrimKey ){
    sqlite3ErrorMsg(pParse, 
      "table \"%s\" has more than one primary key", pTab->zName);
    goto primary_key_exit;
  }
  pTab->hasPrimKey = 1;
  if( pList==0 ){
................................................................................
*/
void sqlite3AddCheckConstraint(
  Parse *pParse,    /* Parsing context */
  Expr *pCheckExpr  /* The check expression */
){
#ifndef SQLITE_OMIT_CHECK
  Table *pTab = pParse->pNewTable;
  if( pTab ){
    /* The CHECK expression must be duplicated so that tokens refer
    ** to malloced space and not the (ephemeral) text of the CREATE TABLE
    ** statement */
    pTab->pCheck = sqlite3ExprAnd(pTab->pCheck, sqlite3ExprDup(pCheckExpr));
  }
#endif
  sqlite3ExprDelete(pCheckExpr);
................................................................................
** Set the collation function of the most recently parsed table column
** to the CollSeq given.
*/
void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){
  Table *p;
  int i;

  if( (p = pParse->pNewTable)==0 ) return;
  i = p->nCol-1;

  if( sqlite3LocateCollSeq(pParse, zType, nType) ){
    Index *pIdx;
    p->aCol[i].zColl = sqliteStrNDup(zType, nType);
  
    /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
................................................................................
  Table *p = pParse->pNewTable;
  int nByte;
  int i;
  int nCol;
  char *z;

  assert( pTo!=0 );
  if( p==0 || pParse->nErr ) goto fk_end;
  if( pFromCol==0 ){
    int iCol = p->nCol-1;
    if( iCol<0 ) goto fk_end;
    if( pToCol && pToCol->nExpr!=1 ){
      sqlite3ErrorMsg(pParse, "foreign key on %s"
         " should reference only one column of table %T",
         p->aCol[iCol].zName, pTo);







|







 







|







 







|







 







|







 







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
....
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
....
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
....
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
....
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.401 2006/06/15 07:29:01 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Initialize the pParse structure as needed.
................................................................................
  int onError,      /* What to do with a uniqueness conflict */
  int autoInc,      /* True if the AUTOINCREMENT keyword is present */
  int sortOrder     /* SQLITE_SO_ASC or SQLITE_SO_DESC */
){
  Table *pTab = pParse->pNewTable;
  char *zType = 0;
  int iCol = -1, i;
  if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
  if( pTab->hasPrimKey ){
    sqlite3ErrorMsg(pParse, 
      "table \"%s\" has more than one primary key", pTab->zName);
    goto primary_key_exit;
  }
  pTab->hasPrimKey = 1;
  if( pList==0 ){
................................................................................
*/
void sqlite3AddCheckConstraint(
  Parse *pParse,    /* Parsing context */
  Expr *pCheckExpr  /* The check expression */
){
#ifndef SQLITE_OMIT_CHECK
  Table *pTab = pParse->pNewTable;
  if( pTab && !IN_DECLARE_VTAB ){
    /* The CHECK expression must be duplicated so that tokens refer
    ** to malloced space and not the (ephemeral) text of the CREATE TABLE
    ** statement */
    pTab->pCheck = sqlite3ExprAnd(pTab->pCheck, sqlite3ExprDup(pCheckExpr));
  }
#endif
  sqlite3ExprDelete(pCheckExpr);
................................................................................
** Set the collation function of the most recently parsed table column
** to the CollSeq given.
*/
void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){
  Table *p;
  int i;

  if( (p = pParse->pNewTable)==0 || IN_DECLARE_VTAB ) return;
  i = p->nCol-1;

  if( sqlite3LocateCollSeq(pParse, zType, nType) ){
    Index *pIdx;
    p->aCol[i].zColl = sqliteStrNDup(zType, nType);
  
    /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
................................................................................
  Table *p = pParse->pNewTable;
  int nByte;
  int i;
  int nCol;
  char *z;

  assert( pTo!=0 );
  if( p==0 || pParse->nErr || IN_DECLARE_VTAB ) goto fk_end;
  if( pFromCol==0 ){
    int iCol = p->nCol-1;
    if( iCol<0 ) goto fk_end;
    if( pToCol && pToCol->nExpr!=1 ){
      sqlite3ErrorMsg(pParse, "foreign key on %s"
         " should reference only one column of table %T",
         p->aCol[iCol].zName, pTo);

Changes to src/insert.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.166 2006/06/14 19:00:21 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
    }

    /* Generate code to check constraints and generate index keys and
    ** do the insertion.
    */
#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( IsVirtual(pTab) ){
      sqlite3VdbeOp3(v, OP_VUpdate, 0, pTab->nCol+1,
                     (const char*)pTab->pVtab, P3_VTAB);
    }else
#endif
    {
      sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
                                     0, onError, endOfLoop);
      sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.167 2006/06/15 07:29:01 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
    }

    /* Generate code to check constraints and generate index keys and
    ** do the insertion.
    */
#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( IsVirtual(pTab) ){
      sqlite3VdbeOp3(v, OP_VUpdate, 0, pTab->nCol+2,
                     (const char*)pTab->pVtab, P3_VTAB);
    }else
#endif
    {
      sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
                                     0, onError, endOfLoop);
      sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,

Changes to src/test8.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
556
557
558
559
560
561
562

563
564
565
566
567
568
569
...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
...
600
601
602
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the virtual table interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test8.c,v 1.20 2006/06/15 04:28:13 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
    if( !zDelete ){
      rc = SQLITE_NOMEM;
    }else{
      sqlite3_stmt *pStmt = 0;
      rc = sqlite3_prepare(db, zDelete, -1, &pStmt, 0);
      assert( rc!=SQLITE_OK || pStmt );
      if( rc==SQLITE_OK ){

        sqlite3_step(pStmt);
        rc = sqlite3_finalize(pStmt);
      }
    }
  }

  /* If there is more than a single argument, INSERT a new row */
................................................................................
    const char *zTab = pVtab->zTableName;

    zInsert = sqlite3_mprintf("INSERT OR REPLACE INTO %Q (rowid", zTab);
    zValues = sqlite3_mprintf("?");

    for(ii=0; ii<pVtab->nCol && zInsert && zValues; ii++){
      char *zNew = sqlite3_mprintf("%s, %Q", zInsert, pVtab->aCol[ii]);
      sqliteFree(zInsert);
      zInsert = zNew;

      zNew = sqlite3_mprintf("%s, ?", zValues);
      sqliteFree(zValues);
      zValues = zNew;
    }

    if( zInsert && zValues ){
      zQuery = sqlite3_mprintf("%s) VALUES(%s)", zInsert, zValues);
    }
    if( zQuery ){
................................................................................
        sqlite3_step(pStmt);
        rc = sqlite3_finalize(pStmt);
      }else{
        sqlite3_finalize(pStmt);
      }
    }

    sqliteFree(zValues);
    sqliteFree(zInsert);
    sqliteFree(zQuery);
    if( rc==SQLITE_OK && (!zValues || !zInsert || !zQuery) ){

      rc = SQLITE_NOMEM;
    }
  }

  return rc;
}








|







 







>







 







|



|







 







|
|
|

>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
...
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
...
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the virtual table interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test8.c,v 1.21 2006/06/15 07:29:01 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
    if( !zDelete ){
      rc = SQLITE_NOMEM;
    }else{
      sqlite3_stmt *pStmt = 0;
      rc = sqlite3_prepare(db, zDelete, -1, &pStmt, 0);
      assert( rc!=SQLITE_OK || pStmt );
      if( rc==SQLITE_OK ){
        sqlite3_bind_value(pStmt, 1, apData[0]);
        sqlite3_step(pStmt);
        rc = sqlite3_finalize(pStmt);
      }
    }
  }

  /* If there is more than a single argument, INSERT a new row */
................................................................................
    const char *zTab = pVtab->zTableName;

    zInsert = sqlite3_mprintf("INSERT OR REPLACE INTO %Q (rowid", zTab);
    zValues = sqlite3_mprintf("?");

    for(ii=0; ii<pVtab->nCol && zInsert && zValues; ii++){
      char *zNew = sqlite3_mprintf("%s, %Q", zInsert, pVtab->aCol[ii]);
      sqlite3_free(zInsert);
      zInsert = zNew;

      zNew = sqlite3_mprintf("%s, ?", zValues);
      sqlite3_free(zValues);
      zValues = zNew;
    }

    if( zInsert && zValues ){
      zQuery = sqlite3_mprintf("%s) VALUES(%s)", zInsert, zValues);
    }
    if( zQuery ){
................................................................................
        sqlite3_step(pStmt);
        rc = sqlite3_finalize(pStmt);
      }else{
        sqlite3_finalize(pStmt);
      }
    }

    sqlite3_free(zValues);
    sqlite3_free(zInsert);
    sqlite3_free(zQuery);
    if( rc==SQLITE_OK && (!zValues || !zInsert || !zQuery) ){
      sqlite3FailedMalloc();
      rc = SQLITE_NOMEM;
    }
  }

  return rc;
}

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
4807
4808
4809
4810
4811
4812
4813

4814

4815
4816
4817
4818
4819
4820
4821
....
4850
4851
4852
4853
4854
4855
4856
4857




4858
4859
4860
4861
4862
4863
4864
4865
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.560 2006/06/14 19:00:22 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
  }else{
    int i;
    Mem **apArg = p->apArg;
    Mem *pX = &pTos[1-nArg];
    for(i = 0; i<nArg; i++, pX++){
      apArg[i] = pX->flags ? storeTypeInfo(pX,0), pX : 0;
    }

    rc = pModule->xUpdate(pVtab, nArg, apArg);

  }
  popStack(&pTos, nArg);
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

/* An other opcode is illegal...
................................................................................

    /* The following code adds nothing to the actual functionality
    ** of the program.  It is only here for testing and debugging.
    ** On the other hand, it does burn CPU cycles every time through
    ** the evaluator loop.  So we can leave it out when NDEBUG is defined.
    */
#ifndef NDEBUG
    /* Sanity checking on the top element of the stack */




    if( pTos>=p->aStack ){
      sqlite3VdbeMemSanity(pTos);
    }
    assert( pc>=-1 && pc<p->nOp );
#ifdef SQLITE_DEBUG
    /* Code for tracing the vdbe stack. */
    if( p->trace && pTos>=p->aStack ){
      int i;







|







 







>

>







 







|
>
>
>
>
|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
....
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.561 2006/06/15 07:29:01 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
  }else{
    int i;
    Mem **apArg = p->apArg;
    Mem *pX = &pTos[1-nArg];
    for(i = 0; i<nArg; i++, pX++){
      apArg[i] = pX->flags ? storeTypeInfo(pX,0), pX : 0;
    }
    if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
    rc = pModule->xUpdate(pVtab, nArg, apArg);
    if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
  }
  popStack(&pTos, nArg);
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

/* An other opcode is illegal...
................................................................................

    /* The following code adds nothing to the actual functionality
    ** of the program.  It is only here for testing and debugging.
    ** On the other hand, it does burn CPU cycles every time through
    ** the evaluator loop.  So we can leave it out when NDEBUG is defined.
    */
#ifndef NDEBUG
    /* Sanity checking on the top element of the stack. If the previous
    ** instruction was VNoChange, then the flags field of the top
    ** of the stack is set to 0. This is technically invalid for a memory
    ** cell, so avoid calling MemSanity() in this case.
    */
    if( pTos>=p->aStack && pTos->flags ){
      sqlite3VdbeMemSanity(pTos);
    }
    assert( pc>=-1 && pc<p->nOp );
#ifdef SQLITE_DEBUG
    /* Code for tracing the vdbe stack. */
    if( p->trace && pTos>=p->aStack ){
      int i;

Changes to src/vtab.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
**    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.
**
*************************************************************************
** This file contains code used to help implement virtual tables.
**
** $Id: vtab.c,v 1.12 2006/06/15 04:28:13 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"

/*
** External API function used to create a new virtual-table module.
*/
................................................................................
    sqlite3VdbeAddOp(v, OP_Expire, 0, 0);
    zWhere = sqlite3MPrintf("name='%q'", pTab->zName);
    sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
    sqlite3VdbeOp3(v, OP_VCreate, iDb, 0, pTab->zName, strlen(pTab->zName) + 1);
  }

  /* If we are rereading the sqlite_master table create the in-memory
  ** record of the table. 
  **
  ** TODO: If the module is already registered, should we call xConnect()
  ** here, or should it wait until the table is first referenced? Maybe
  ** it's better to be lazy here, in case xConnect() is expensive to call
  ** and the schema is reparsed a number of times.
  */
  else {
    Table *pOld;
    Schema *pSchema = pTab->pSchema;
    const char *zName = pTab->zName;
    int nName = strlen(zName) + 1;
    pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab);







|







 







|
|
<
<
<
<







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
190
191
192
193
194
195
196
197
198




199
200
201
202
203
204
205
**    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.
**
*************************************************************************
** This file contains code used to help implement virtual tables.
**
** $Id: vtab.c,v 1.13 2006/06/15 07:29:01 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"

/*
** External API function used to create a new virtual-table module.
*/
................................................................................
    sqlite3VdbeAddOp(v, OP_Expire, 0, 0);
    zWhere = sqlite3MPrintf("name='%q'", pTab->zName);
    sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
    sqlite3VdbeOp3(v, OP_VCreate, iDb, 0, pTab->zName, strlen(pTab->zName) + 1);
  }

  /* If we are rereading the sqlite_master table create the in-memory
  ** record of the table. If the module has already been registered,
  ** also call the xConnect method here.




  */
  else {
    Table *pOld;
    Schema *pSchema = pTab->pSchema;
    const char *zName = pTab->zName;
    int nName = strlen(zName) + 1;
    pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab);

Changes to test/vtab1.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
...
400
401
402
403
404
405
406






































407

#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is creating and dropping virtual tables.
#
# $Id: vtab1.test,v 1.15 2006/06/14 22:07:11 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !vtab {
  finish_test
  return
................................................................................
# vtab1-5.*: Test queries that include joins. This brings the
#            sqlite3_index_info.estimatedCost variable into play.
#
# This file uses the "echo" module (see src/test8.c). Refer to comments
# in that file for the special behaviour of the Tcl $echo_module variable.
#
# TODO: 
#
# * How to test the sqlite3_index_constraint_usage.omit field? Or

#   sqlite3_index_info.orderByConsumed?
#


#----------------------------------------------------------------------
# Test cases vtab1.1.*
#

................................................................................
  }
} {2 5 sort}
do_test vtab1-4.4 {
  set echo_module
} [list xBestIndex {SELECT rowid, * FROM 'treal'} \
        xFilter    {SELECT rowid, * FROM 'treal'} ]







































finish_test








|







 







<
|
>
|







 







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

>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
...
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is creating and dropping virtual tables.
#
# $Id: vtab1.test,v 1.16 2006/06/15 07:29:01 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !vtab {
  finish_test
  return
................................................................................
# vtab1-5.*: Test queries that include joins. This brings the
#            sqlite3_index_info.estimatedCost variable into play.
#
# This file uses the "echo" module (see src/test8.c). Refer to comments
# in that file for the special behaviour of the Tcl $echo_module variable.
#
# TODO: 

#   * How to test the sqlite3_index_constraint_usage.omit field?
#   * vtab1-5.*
#   * 
#


#----------------------------------------------------------------------
# Test cases vtab1.1.*
#

................................................................................
  }
} {2 5 sort}
do_test vtab1-4.4 {
  set echo_module
} [list xBestIndex {SELECT rowid, * FROM 'treal'} \
        xFilter    {SELECT rowid, * FROM 'treal'} ]

execsql {
  DROP TABLE t1;
  DROP TABLE treal;
}

#----------------------------------------------------------------------
# Test cases vtab1-6 test INSERT, UPDATE and DELETE operations 
# on virtual tables.
do_test vtab1-6-1 {
  execsql { SELECT sql FROM sqlite_master }
} {}
do_test vtab1-6-2 {
  execsql {
    CREATE TABLE treal(a PRIMARY KEY, b, c);
    CREATE VIRTUAL TABLE techo USING echo(treal);
    SELECT name FROM sqlite_master WHERE type = 'table';
  }
} {treal techo}
do_test vtab1-6-3 {
  execsql {
    INSERT INTO techo VALUES(1, 2, 3);
    SELECT * FROM techo;
  }
} {1 2 3}
do_test vtab1-6-4 {
  execsql {
    UPDATE techo SET a = 5;
    SELECT * FROM techo;
  }
} {5 2 3}
do_test vtab1-6-5 {
  execsql {
    DELETE FROM techo;
    SELECT * FROM techo;
  }
} {}
# check_echo_table vtab1-6.3 treal techo

finish_test