modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/rtree/rtreeC.test (about)

     1  # 2011 March 2
     2  #
     3  # The author disclaims copyright to this source code.  In place of
     4  # a legal notice, here is a blessing:
     5  #
     6  #    May you do good and not evil.
     7  #    May you find forgiveness for yourself and forgive others.
     8  #    May you share freely, never taking more than you give.
     9  #
    10  #***********************************************************************
    11  # Make sure the rtreenode() testing function can handle entries with
    12  # 64-bit rowids.
    13  # 
    14  
    15  if {![info exists testdir]} {
    16    set testdir [file join [file dirname [info script]] .. .. test]
    17  } 
    18  source $testdir/tester.tcl
    19  ifcapable !rtree { finish_test ; return }
    20  set testprefix rtreeC
    21  
    22  do_execsql_test 1.0 {
    23    CREATE VIRTUAL TABLE r_tree USING rtree(id, min_x, max_x, min_y, max_y);
    24    CREATE TABLE t(x, y);
    25  }
    26  
    27  do_eqp_test 1.1 {
    28    SELECT * FROM r_tree, t 
    29    WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
    30  } {
    31    0 0 1 {SCAN TABLE t}
    32    0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
    33  }
    34  
    35  do_eqp_test 1.2 {
    36    SELECT * FROM t, r_tree
    37    WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
    38  } {
    39    0 0 0 {SCAN TABLE t}
    40    0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
    41  }
    42  
    43  do_eqp_test 1.3 {
    44    SELECT * FROM t, r_tree
    45    WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
    46  } {
    47    0 0 0 {SCAN TABLE t}
    48    0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
    49  }
    50  
    51  do_eqp_test 1.5 {
    52    SELECT * FROM t, r_tree
    53  } {
    54    0 0 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:}
    55    0 1 0 {SCAN TABLE t} 
    56  }
    57  
    58  do_execsql_test 2.0 {
    59    INSERT INTO t VALUES(0, 0);
    60    INSERT INTO t VALUES(0, 1);
    61    INSERT INTO t VALUES(0, 2);
    62    INSERT INTO t VALUES(0, 3);
    63    INSERT INTO t VALUES(0, 4);
    64    INSERT INTO t VALUES(0, 5);
    65    INSERT INTO t VALUES(0, 6);
    66    INSERT INTO t VALUES(0, 7);
    67    INSERT INTO t VALUES(0, 8);
    68    INSERT INTO t VALUES(0, 9);
    69  
    70    INSERT INTO t SELECT x+1, y FROM t;
    71    INSERT INTO t SELECT x+2, y FROM t;
    72    INSERT INTO t SELECT x+4, y FROM t;
    73    INSERT INTO r_tree SELECT NULL, x-1, x+1, y-1, y+1 FROM t;
    74    ANALYZE;
    75  }
    76  
    77  db close
    78  sqlite3 db test.db
    79  
    80  do_eqp_test 2.1 {
    81    SELECT * FROM r_tree, t 
    82    WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
    83  } {
    84    0 0 1 {SCAN TABLE t}
    85    0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
    86  }
    87  
    88  do_eqp_test 2.2 {
    89    SELECT * FROM t, r_tree
    90    WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
    91  } {
    92    0 0 0 {SCAN TABLE t}
    93    0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
    94  }
    95  
    96  do_eqp_test 2.3 {
    97    SELECT * FROM t, r_tree
    98    WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
    99  } {
   100    0 0 0 {SCAN TABLE t}
   101    0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
   102  }
   103  
   104  do_eqp_test 2.5 {
   105    SELECT * FROM t, r_tree
   106  } {
   107    0 0 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:}
   108    0 1 0 {SCAN TABLE t} 
   109  }
   110  
   111  #-------------------------------------------------------------------------
   112  # Test that the special CROSS JOIN handling works with rtree tables.
   113  #
   114  do_execsql_test 3.1 {
   115    CREATE TABLE t1(x);
   116    CREATE TABLE t2(y);
   117    CREATE VIRTUAL TABLE t3 USING rtree(z, x1,x2, y1,y2);
   118  }
   119  
   120  do_eqp_test 3.2.1 { SELECT * FROM t1 CROSS JOIN t2 } {
   121    0 0 0 {SCAN TABLE t1} 
   122    0 1 1 {SCAN TABLE t2}
   123  }
   124  do_eqp_test 3.2.2 { SELECT * FROM t2 CROSS JOIN t1 } {
   125    0 0 0 {SCAN TABLE t2} 0 1 1 {SCAN TABLE t1}
   126  }
   127  
   128  do_eqp_test 3.3.1 { SELECT * FROM t1 CROSS JOIN t3 } {
   129    0 0 0 {SCAN TABLE t1}
   130    0 1 1 {SCAN TABLE t3 VIRTUAL TABLE INDEX 2:} 
   131  }
   132  do_eqp_test 3.3.2 { SELECT * FROM t3 CROSS JOIN t1 } {
   133    0 0 0 {SCAN TABLE t3 VIRTUAL TABLE INDEX 2:} 
   134    0 1 1 {SCAN TABLE t1}
   135  }
   136  
   137  #--------------------------------------------------------------------
   138  # Test that LEFT JOINs are not reordered if the right-hand-side is
   139  # a virtual table.
   140  #
   141  reset_db
   142  do_execsql_test 4.1 {
   143    CREATE TABLE t1(a);
   144    CREATE VIRTUAL TABLE t2 USING rtree(b, x1,x2);
   145  
   146    INSERT INTO t1 VALUES(1);
   147    INSERT INTO t1 VALUES(2);
   148  
   149    INSERT INTO t2 VALUES(1, 0.0, 0.1);
   150    INSERT INTO t2 VALUES(3, 0.0, 0.1);
   151  }
   152  
   153  do_execsql_test 4.2 {
   154    SELECT a, b FROM t1 LEFT JOIN t2 ON (+a = +b);
   155  } {1 1 2 {}}
   156  
   157  do_execsql_test 4.3 {
   158    SELECT b, a FROM t2 LEFT JOIN t1 ON (+a = +b);
   159  } {1 1 3 {}}
   160  
   161  #--------------------------------------------------------------------
   162  # Test that the sqlite_stat1 data is used correctly.
   163  #
   164  reset_db
   165  do_execsql_test 5.1 {
   166    CREATE TABLE t1(x PRIMARY KEY, y);
   167    CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
   168  
   169    INSERT INTO t1(x) VALUES(1);
   170    INSERT INTO t1(x) SELECT x+1 FROM t1;   --   2
   171    INSERT INTO t1(x) SELECT x+2 FROM t1;   --   4
   172    INSERT INTO t1(x) SELECT x+4 FROM t1;   --   8
   173    INSERT INTO t1(x) SELECT x+8 FROM t1;   --  16
   174    INSERT INTO t1(x) SELECT x+16 FROM t1;  --  32
   175    INSERT INTO t1(x) SELECT x+32 FROM t1;  --  64
   176    INSERT INTO t1(x) SELECT x+64 FROM t1;  -- 128
   177    INSERT INTO t1(x) SELECT x+128 FROM t1; -- 256
   178    INSERT INTO t1(x) SELECT x+256 FROM t1; -- 512
   179    INSERT INTO t1(x) SELECT x+512 FROM t1; --1024
   180  
   181    INSERT INTO rt SELECT x, x, x+1 FROM t1 WHERE x<=5;
   182  }
   183  
   184  # First test a query with no ANALYZE data at all. The outer loop is
   185  # real table "t1".
   186  #
   187  do_eqp_test 5.2 {
   188    SELECT * FROM t1, rt WHERE x==id;
   189  } {
   190    0 0 0 {SCAN TABLE t1} 
   191    0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
   192  }
   193  
   194  # Now create enough ANALYZE data to tell SQLite that virtual table "rt"
   195  # contains very few rows. This causes it to move "rt" to the outer loop.
   196  #
   197  do_execsql_test 5.3 {
   198    ANALYZE;
   199    DELETE FROM sqlite_stat1 WHERE tbl='t1';
   200  }
   201  db close
   202  sqlite3 db test.db
   203  do_eqp_test 5.4 {
   204    SELECT * FROM t1, rt WHERE x==id;
   205  } {
   206    0 0 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:} 
   207    0 1 0 {SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?)}
   208  }
   209  
   210  # Delete the ANALYZE data. "t1" should be the outer loop again.
   211  #
   212  do_execsql_test 5.5 { DROP TABLE sqlite_stat1; }
   213  db close
   214  sqlite3 db test.db
   215  do_eqp_test 5.6 {
   216    SELECT * FROM t1, rt WHERE x==id;
   217  } {
   218    0 0 0 {SCAN TABLE t1} 
   219    0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
   220  }
   221  
   222  # This time create and attach a database that contains ANALYZE data for
   223  # tables of the same names as those used internally by virtual table
   224  # "rt". Check that the rtree module is not fooled into using this data.
   225  # Table "t1" should remain the outer loop.
   226  #
   227  do_test 5.7 {
   228    db backup test.db2
   229    sqlite3 db2 test.db2
   230    db2 eval {
   231      ANALYZE;
   232      DELETE FROM sqlite_stat1 WHERE tbl='t1';
   233    }
   234    db2 close
   235    db close
   236    sqlite3 db test.db
   237    execsql { ATTACH 'test.db2' AS aux; }
   238  } {}
   239  do_eqp_test 5.8 {
   240    SELECT * FROM t1, rt WHERE x==id;
   241  } {
   242    0 0 0 {SCAN TABLE t1} 
   243    0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
   244  }
   245  
   246  #--------------------------------------------------------------------
   247  # Test that having a second connection drop the sqlite_stat1 table
   248  # before it is required by rtreeConnect() does not cause problems.
   249  #
   250  ifcapable rtree {
   251    reset_db
   252    do_execsql_test 6.1 {
   253      CREATE TABLE t1(x);
   254      CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
   255      INSERT INTO t1 VALUES(1);
   256      INSERT INTO rt VALUES(1,2,3);
   257      ANALYZE;
   258    }
   259    db close
   260    sqlite3 db test.db
   261    do_execsql_test 6.2 { SELECT * FROM t1 } {1}
   262    
   263    do_test 6.3 {
   264      sqlite3 db2 test.db
   265      db2 eval { DROP TABLE sqlite_stat1 }
   266      db2 close
   267      execsql { SELECT * FROM rt }
   268    } {1 2.0 3.0}
   269    db close
   270  }
   271  
   272  #--------------------------------------------------------------------
   273  # Test that queries featuring LEFT or CROSS JOINS are handled correctly.
   274  # Handled correctly in this case means:
   275  #
   276  #   * Terms with prereqs that appear to the left of a LEFT JOIN against
   277  #     the virtual table are always available to xBestIndex.
   278  #
   279  #   * Terms with prereqs that appear to the right of a LEFT JOIN against
   280  #     the virtual table are never available to xBestIndex.
   281  #
   282  # And the same behaviour for CROSS joins.
   283  #
   284  reset_db
   285  do_execsql_test 7.0 {
   286    CREATE TABLE xdir(x1);
   287    CREATE TABLE ydir(y1);
   288    CREATE VIRTUAL TABLE rt USING rtree_i32(id, xmin, xmax, ymin, ymax);
   289  
   290    INSERT INTO xdir VALUES(5);
   291    INSERT INTO ydir VALUES(10);
   292  
   293    INSERT INTO rt VALUES(1, 2, 7, 12, 14);      -- Not a hit
   294    INSERT INTO rt VALUES(2, 2, 7, 8, 12);       -- A hit!
   295    INSERT INTO rt VALUES(3, 7, 11, 8, 12);      -- Not a hit!
   296    INSERT INTO rt VALUES(4, 5, 5, 10, 10);      -- A hit!
   297  
   298  }
   299  
   300  proc do_eqp_execsql_test {tn sql res} {
   301    set query "EXPLAIN QUERY PLAN $sql ; $sql "
   302    uplevel [list do_execsql_test $tn $query $res]
   303  }
   304  
   305  do_eqp_execsql_test 7.1 {
   306    SELECT id FROM xdir, rt, ydir 
   307    ON (y1 BETWEEN ymin AND ymax)
   308    WHERE (x1 BETWEEN xmin AND xmax);
   309  } {
   310    0 0 0 {SCAN TABLE xdir} 
   311    0 1 2 {SCAN TABLE ydir} 
   312    0 2 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1}
   313    2 4
   314  }
   315  
   316  do_eqp_execsql_test 7.2 {
   317    SELECT * FROM xdir, rt LEFT JOIN ydir 
   318    ON (y1 BETWEEN ymin AND ymax)
   319    WHERE (x1 BETWEEN xmin AND xmax);
   320  } {
   321    0 0 0 {SCAN TABLE xdir} 
   322    0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
   323    0 2 2 {SCAN TABLE ydir} 
   324  
   325    5 1 2 7 12 14 {}
   326    5 2 2 7  8 12 10
   327    5 4 5 5 10 10 10
   328  }
   329  
   330  do_eqp_execsql_test 7.3 {
   331    SELECT id FROM xdir, rt CROSS JOIN ydir 
   332    ON (y1 BETWEEN ymin AND ymax)
   333    WHERE (x1 BETWEEN xmin AND xmax);
   334  } {
   335    0 0 0 {SCAN TABLE xdir} 
   336    0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
   337    0 2 2 {SCAN TABLE ydir} 
   338    2 4
   339  }
   340  
   341  do_eqp_execsql_test 7.4 {
   342    SELECT id FROM rt, xdir CROSS JOIN ydir 
   343    ON (y1 BETWEEN ymin AND ymax)
   344    WHERE (x1 BETWEEN xmin AND xmax);
   345  } {
   346    0 0 1 {SCAN TABLE xdir} 
   347    0 1 0 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
   348    0 2 2 {SCAN TABLE ydir} 
   349    2 4
   350  }
   351  
   352  finish_test