SQLite

Check-in [deadaad2a0]
Login

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

Overview
Comment:Add test cases and fix minor error-handling issues in unionvtab.c.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: deadaad2a0801b3c30d2a076d8eb006b62d8557cff820e0939741c078477c83f
User & Date: dan 2017-07-18 20:49:15.448
Context
2017-07-18
20:59
Fix shell.c.in so that it aligns with shell.c. (check-in: 505fdc8ff5 user: drh tags: trunk)
20:49
Add test cases and fix minor error-handling issues in unionvtab.c. (check-in: deadaad2a0 user: dan tags: trunk)
20:30
Fix duplicate test name. No changes to code. (check-in: 47b80ecc67 user: mistachkin tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/misc/unionvtab.c.
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
** In this case, *pzErr may be set to point to an error message
** buffer allocated by sqlite3_malloc().
*/
static void unionReset(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
  int rc = sqlite3_reset(pStmt);
  if( *pRc==SQLITE_OK ){
    *pRc = rc;
    if( rc && pzErr ){
      *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(sqlite3_db_handle(pStmt)));
    }
  }
}

/*
** Call sqlite3_finalize() on SQL statement pStmt. If *pRc is set to 







|







250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
** In this case, *pzErr may be set to point to an error message
** buffer allocated by sqlite3_malloc().
*/
static void unionReset(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
  int rc = sqlite3_reset(pStmt);
  if( *pRc==SQLITE_OK ){
    *pRc = rc;
    if( rc ){
      *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(sqlite3_db_handle(pStmt)));
    }
  }
}

/*
** Call sqlite3_finalize() on SQL statement pStmt. If *pRc is set to 
311
312
313
314
315
316
317

318
319
320
321

322
323
324
325
326
327
328
  sqlite3_stmt *pStmt,
  char **pzErr                    /* OUT: Error message */
){
  char *zRet = 0;
  if( *pRc==SQLITE_OK ){
    int bPk = 0;
    const char *zType = 0;


    int rc = sqlite3_table_column_metadata(
        db, pSrc->zDb, pSrc->zTab, "_rowid_", &zType, 0, 0, &bPk, 0
    );

    if( rc==SQLITE_ERROR 
     || (rc==SQLITE_OK && (!bPk || sqlite3_stricmp("integer", zType)))
    ){
      rc = SQLITE_ERROR;
      *pzErr = sqlite3_mprintf("no such rowid table: %s%s%s",
          (pSrc->zDb ? pSrc->zDb : ""),
          (pSrc->zDb ? "." : ""),







>

|


>







311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
  sqlite3_stmt *pStmt,
  char **pzErr                    /* OUT: Error message */
){
  char *zRet = 0;
  if( *pRc==SQLITE_OK ){
    int bPk = 0;
    const char *zType = 0;
    int rc;

    sqlite3_table_column_metadata(
        db, pSrc->zDb, pSrc->zTab, "_rowid_", &zType, 0, 0, &bPk, 0
    );
    rc = sqlite3_errcode(db);
    if( rc==SQLITE_ERROR 
     || (rc==SQLITE_OK && (!bPk || sqlite3_stricmp("integer", zType)))
    ){
      rc = SQLITE_ERROR;
      *pzErr = sqlite3_mprintf("no such rowid table: %s%s%s",
          (pSrc->zDb ? pSrc->zDb : ""),
          (pSrc->zDb ? "." : ""),
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488

489
490
491
492
493
494
495
    unionFinalize(&rc, pStmt);
    pStmt = 0;

    /* Verify that all source tables exist and have compatible schemas. */
    if( rc==SQLITE_OK ){
      pTab->db = db;
      rc = unionSourceCheck(pTab, pzErr);
    }

    /* Compose a CREATE TABLE statement and pass it to declare_vtab() */
    pStmt = unionPreparePrintf(&rc, pzErr, db, "SELECT "
        "'CREATE TABLE xyz('"
        "    || group_concat(quote(name) || ' ' || type, ', ')"
        "    || ')',"
        "max((cid+1) * (type='INTEGER' COLLATE nocase AND pk=1))-1 "
        "FROM pragma_table_info(%Q, ?)", 
        pTab->aSrc[0].zTab, pTab->aSrc[0].zDb
    );

    if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
      const char *zDecl = (const char*)sqlite3_column_text(pStmt, 0);
      rc = sqlite3_declare_vtab(db, zDecl);
      pTab->iPK = sqlite3_column_int(pStmt, 1);
    }

    unionFinalize(&rc, pStmt);







|
<
|
|
|
|
|
|
|
|
|
>







473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
    unionFinalize(&rc, pStmt);
    pStmt = 0;

    /* Verify that all source tables exist and have compatible schemas. */
    if( rc==SQLITE_OK ){
      pTab->db = db;
      rc = unionSourceCheck(pTab, pzErr);


      /* Compose a CREATE TABLE statement and pass it to declare_vtab() */
      pStmt = unionPreparePrintf(&rc, pzErr, db, "SELECT "
          "'CREATE TABLE xyz('"
          "    || group_concat(quote(name) || ' ' || type, ', ')"
          "    || ')',"
          "max((cid+1) * (type='INTEGER' COLLATE nocase AND pk=1))-1 "
          "FROM pragma_table_info(%Q, ?)", 
          pTab->aSrc[0].zTab, pTab->aSrc[0].zDb
      );
    }
    if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
      const char *zDecl = (const char*)sqlite3_column_text(pStmt, 0);
      rc = sqlite3_declare_vtab(db, zDecl);
      pTab->iPK = sqlite3_column_int(pStmt, 1);
    }

    unionFinalize(&rc, pStmt);
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
        , pSrc->zTab
    );
    if( zSql==0 ){
      rc = SQLITE_NOMEM;
      break;
    }

    if( zSql ){
      if( iMin==iMax ){
        zSql = sqlite3_mprintf("%z WHERE rowid=%lld", zSql, iMin);
      }else{
        const char *zWhere = "WHERE";
        if( iMin!=SMALLEST_INT64 && iMin>pSrc->iMin ){
          zSql = sqlite3_mprintf("%z WHERE rowid>=%lld", zSql, iMin);
          zWhere = "AND";
        }
        if( iMax!=LARGEST_INT64 && iMax<pSrc->iMax ){
          zSql = sqlite3_mprintf("%z %s rowid<=%lld", zSql, zWhere, iMax);
        }
      }
    }
  }


  if( rc==SQLITE_OK ){
    if( zSql==0 ) return SQLITE_OK;
    pCsr->pStmt = unionPrepare(&rc, pTab->db, zSql, &pTab->base.zErrMsg);
  }
  sqlite3_free(zSql);

  if( rc!=SQLITE_OK ) return rc;
  return unionNext(pVtabCursor);
}

/*
** xBestIndex.
**







<
|
|
|
|
|
|
|
|
|
|
<





<
|
|
<

<







656
657
658
659
660
661
662

663
664
665
666
667
668
669
670
671
672

673
674
675
676
677

678
679

680

681
682
683
684
685
686
687
        , pSrc->zTab
    );
    if( zSql==0 ){
      rc = SQLITE_NOMEM;
      break;
    }


    if( iMin==iMax ){
      zSql = sqlite3_mprintf("%z WHERE rowid=%lld", zSql, iMin);
    }else{
      const char *zWhere = "WHERE";
      if( iMin!=SMALLEST_INT64 && iMin>pSrc->iMin ){
        zSql = sqlite3_mprintf("%z WHERE rowid>=%lld", zSql, iMin);
        zWhere = "AND";
      }
      if( iMax!=LARGEST_INT64 && iMax<pSrc->iMax ){
        zSql = sqlite3_mprintf("%z %s rowid<=%lld", zSql, zWhere, iMax);

      }
    }
  }



  if( zSql==0 ) return rc;
  pCsr->pStmt = unionPrepare(&rc, pTab->db, zSql, &pTab->base.zErrMsg);

  sqlite3_free(zSql);

  if( rc!=SQLITE_OK ) return rc;
  return unionNext(pVtabCursor);
}

/*
** xBestIndex.
**
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
  int i;

  for(i=0; i<pIdxInfo->nConstraint; i++){
    struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
    if( p->usable && (p->iColumn<0 || p->iColumn==pTab->iPK) ){
      switch( p->op ){
        case SQLITE_INDEX_CONSTRAINT_EQ:
          if( iEq<0 ) iEq = i;
          break;
        case SQLITE_INDEX_CONSTRAINT_LE:
        case SQLITE_INDEX_CONSTRAINT_LT:
          if( iLt<0 ) iLt = i;
          break;
        case SQLITE_INDEX_CONSTRAINT_GE:
        case SQLITE_INDEX_CONSTRAINT_GT:
          if( iGt<0 ) iGt = i;
          break;
      }
    }
  }

  if( iEq>=0 ){
    pIdxInfo->estimatedRows = 1;







|



|



|







711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
  int i;

  for(i=0; i<pIdxInfo->nConstraint; i++){
    struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
    if( p->usable && (p->iColumn<0 || p->iColumn==pTab->iPK) ){
      switch( p->op ){
        case SQLITE_INDEX_CONSTRAINT_EQ:
          iEq = i;
          break;
        case SQLITE_INDEX_CONSTRAINT_LE:
        case SQLITE_INDEX_CONSTRAINT_LT:
          iLt = i;
          break;
        case SQLITE_INDEX_CONSTRAINT_GE:
        case SQLITE_INDEX_CONSTRAINT_GT:
          iGt = i;
          break;
      }
    }
  }

  if( iEq>=0 ){
    pIdxInfo->estimatedRows = 1;
Added test/unionvtabfault.test.








































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# 2017-07-15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    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 implements regression tests for SQLite library.  The
# focus of this file is percentile.c extension
#

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


forcedelete test.db2
do_execsql_test 1.0 {
  ATTACH 'test.db2' AS aux;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);
  CREATE TABLE t2(a INTEGER PRIMARY KEY, b TEXT);
  CREATE TABLE aux.t3(a INTEGER PRIMARY KEY, b TEXT);

  INSERT INTO t1 VALUES(1, 'one'), (2, 'two'), (3, 'three');
  INSERT INTO t2 VALUES(10, 'ten'), (11, 'eleven'), (12, 'twelve');
  INSERT INTO t3 VALUES(20, 'twenty'), (21, 'twenty-one'), (22, 'twenty-two');
}
faultsim_save_and_close

do_faultsim_test 1.1 -faults * -prep {
  faultsim_restore_and_reopen
  load_static_extension db unionvtab
  execsql { ATTACH 'test.db2' AS aux; }
  execsql { CREATE TEMP TABLE xyz(x); }
} -body {
  execsql {
    CREATE VIRTUAL TABLE temp.uuu USING unionvtab(
    "VALUES(NULL, 't1', 1, 9),  ('main', 't2', 10, 19), ('aux', 't3', 20, 29)"
    );
  }
} -test {
  faultsim_test_result {0 {}}             \
     {1 {vtable constructor failed: uuu}} \
     {1 {sql error: interrupted}}
}

faultsim_restore_and_reopen
load_static_extension db unionvtab
execsql { ATTACH 'test.db2' AS aux; }
execsql { CREATE TEMP TABLE xyz(x); }
execsql {
  CREATE VIRTUAL TABLE temp.uuu USING unionvtab(
      "VALUES(NULL, 't1', 1, 9),  ('main', 't2', 10, 19), ('aux', 't3', 20, 29)"
  );
}
do_faultsim_test 1.2 -faults oom* -prep {
} -body {
  execsql { SELECT * FROM uuu }
} -test {
  faultsim_test_result {0 {1 one 2 two 3 three 10 ten 11 eleven 12 twelve 20 twenty 21 twenty-one 22 twenty-two}} 
}


finish_test