sqlite/test/vtab1.test
drh 6a03a1c5f7 For infix functions (LIKE, GLOB, REGEXP, and MATCH) treat the left
operand as the first argument for the purposes of virtual table
function overloading, even though the left operand is really the
the second argument. (CVS 3324)

FossilOrigin-Name: 6e98373ca11c9d476f4c6b1841c6e006b7a49f29
2006-07-08 18:34:59 +00:00

871 lines
21 KiB
Plaintext

# 2006 June 10
#
# 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 creating and dropping virtual tables.
#
# $Id: vtab1.test,v 1.35 2006/07/08 18:35:00 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !vtab||!schema_pragmas {
finish_test
return
}
#----------------------------------------------------------------------
# Organization of tests in this file:
#
# vtab1-1.*: Error conditions and other issues surrounding creation/connection
# of a virtual module.
# vtab1-2.*: Test sqlite3_declare_vtab() and the xConnect/xDisconnect methods.
# vtab1-3.*: Table scans and WHERE clauses.
# vtab1-4.*: Table scans and ORDER BY clauses.
# vtab1-5.*: Test queries that include joins. This brings the
# sqlite3_index_info.estimatedCost variable into play.
# vtab1-6.*: Test UPDATE/INSERT/DELETE on vtables.
# vtab1-7.*: Test sqlite3_last_insert_rowid().
#
# 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.*
#
# We cannot create a virtual table if the module has not been registered.
#
do_test vtab1-1.1 {
catchsql {
CREATE VIRTUAL TABLE t1 USING echo;
}
} {1 {no such module: echo}}
do_test vtab1-1.2 {
execsql {
SELECT name FROM sqlite_master ORDER BY 1
}
} {}
# Register the module
register_echo_module [sqlite3_connection_pointer db]
# Once a module has been registered, virtual tables using that module
# may be created. However if a module xCreate() fails to call
# sqlite3_declare_vtab() an error will be raised and the table not created.
#
# The "echo" module does not invoke sqlite3_declare_vtab() if it is
# passed zero arguments.
#
do_test vtab1-1.3 {
catchsql {
CREATE VIRTUAL TABLE t1 USING echo;
}
} {1 {vtable constructor did not declare schema: t1}}
do_test vtab1-1.4 {
execsql {
SELECT name FROM sqlite_master ORDER BY 1
}
} {}
# The "echo" module xCreate method returns an error and does not create
# the virtual table if it is passed an argument that does not correspond
# to an existing real table in the same database.
#
do_test vtab1-1.5 {
catchsql {
CREATE VIRTUAL TABLE t1 USING echo(no_such_table);
}
} {1 {vtable constructor failed: t1}}
do_test vtab1-1.6 {
execsql {
SELECT name FROM sqlite_master ORDER BY 1
}
} {}
# Test to make sure nothing goes wrong and no memory is leaked if we
# select an illegal table-name (i.e a reserved name or the name of a
# table that already exists).
#
do_test vtab1-1.7 {
catchsql {
CREATE VIRTUAL TABLE sqlite_master USING echo;
}
} {1 {object name reserved for internal use: sqlite_master}}
do_test vtab1-1.8 {
catchsql {
CREATE TABLE treal(a, b, c);
CREATE VIRTUAL TABLE treal USING echo(treal);
}
} {1 {table treal already exists}}
do_test vtab1-1.9 {
execsql {
DROP TABLE treal;
SELECT name FROM sqlite_master ORDER BY 1
}
} {}
do_test vtab1-1.10 {
execsql {
CREATE TABLE treal(a, b, c);
CREATE VIRTUAL TABLE techo USING echo(treal);
}
db close
sqlite3 db test.db
catchsql {
SELECT * FROM techo;
}
} {1 {no such module: echo}}
do_test vtab1-1.11 {
catchsql {
INSERT INTO techo VALUES(1, 2, 3);
}
} {1 {no such module: echo}}
do_test vtab1-1.12 {
catchsql {
UPDATE techo SET a = 10;
}
} {1 {no such module: echo}}
do_test vtab1-1.13 {
catchsql {
DELETE FROM techo;
}
} {1 {no such module: echo}}
do_test vtab1-1.14 {
catchsql {
PRAGMA table_info(techo)
}
} {1 {no such module: echo}}
do_test vtab1-1.15 {
catchsql {
DROP TABLE techo;
}
} {1 {no such module: echo}}
register_echo_module [sqlite3_connection_pointer db]
do_test vtab1-1.X {
execsql {
DROP TABLE techo;
DROP TABLE treal;
SELECT sql FROM sqlite_master;
}
} {}
#----------------------------------------------------------------------
# Test cases vtab1.2.*
#
# At this point, the database is completely empty. The echo module
# has already been registered.
# If a single argument is passed to the echo module during table
# creation, it is assumed to be the name of a table in the same
# database. The echo module attempts to set the schema of the
# new virtual table to be the same as the existing database table.
#
do_test vtab1-2.1 {
execsql {
CREATE TABLE template(a, b, c);
}
execsql { PRAGMA table_info(template); }
} [list \
0 a {} 0 {} 0 \
1 b {} 0 {} 0 \
2 c {} 0 {} 0 \
]
do_test vtab1-2.2 {
execsql {
CREATE VIRTUAL TABLE t1 USING echo(template);
}
execsql { PRAGMA table_info(t1); }
} [list \
0 a {} 0 {} 0 \
1 b {} 0 {} 0 \
2 c {} 0 {} 0 \
]
# Test that the database can be unloaded. This should invoke the xDisconnect()
# callback for the successfully create virtual table (t1).
#
do_test vtab1-2.3 {
set echo_module [list]
db close
set echo_module
} [list xDisconnect]
# Re-open the database. This should not cause any virtual methods to
# be called. The invocation of xConnect() is delayed until the virtual
# table schema is first required by the compiler.
#
do_test vtab1-2.4 {
set echo_module [list]
sqlite3 db test.db
db cache size 0
set echo_module
} {}
# Try to query the virtual table schema. This should fail, as the
# echo module has not been registered with this database connection.
#
do_test vtab1.2.6 {
breakpoint
catchsql { PRAGMA table_info(t1); }
} {1 {no such module: echo}}
# Register the module
register_echo_module [sqlite3_connection_pointer db]
# Try to query the virtual table schema again. This time it should
# invoke the xConnect method and succeed.
#
do_test vtab1.2.7 {
execsql { PRAGMA table_info(t1); }
} [list \
0 a {} 0 {} 0 \
1 b {} 0 {} 0 \
2 c {} 0 {} 0 \
]
do_test vtab1.2.8 {
set echo_module
} {xConnect echo main t1 template}
# Drop table t1. This should cause the xDestroy (but not xDisconnect) method
# to be invoked.
do_test vtab1-2.5 {
set echo_module ""
execsql {
DROP TABLE t1;
}
set echo_module
} {xDestroy}
do_test vtab1-2.6 {
execsql {
PRAGMA table_info(t1);
}
} {}
do_test vtab1-2.7 {
execsql {
SELECT sql FROM sqlite_master;
}
} [list {CREATE TABLE template(a, b, c)}]
# Clean up other test artifacts:
do_test vtab1-2.8 {
execsql {
DROP TABLE template;
SELECT sql FROM sqlite_master;
}
} [list]
#----------------------------------------------------------------------
# Test case vtab1-3 test table scans and the echo module's
# xBestIndex/xFilter handling of WHERE conditions.
do_test vtab1-3.1 {
set echo_module ""
execsql {
CREATE TABLE treal(a INTEGER, b INTEGER, c);
CREATE INDEX treal_idx ON treal(b);
CREATE VIRTUAL TABLE t1 USING echo(treal);
}
set echo_module
} [list xCreate echo main t1 treal \
xSync echo(treal) \
xCommit echo(treal) \
]
# Test that a SELECT on t1 doesn't crash. No rows are returned
# because the underlying real table is currently empty.
#
do_test vtab1-3.2 {
execsql {
SELECT a, b, c FROM t1;
}
} {}
# Put some data into the table treal. Then try a few simple SELECT
# statements on t1.
#
do_test vtab1-3.3 {
execsql {
INSERT INTO treal VALUES(1, 2, 3);
INSERT INTO treal VALUES(4, 5, 6);
SELECT * FROM t1;
}
} {1 2 3 4 5 6}
do_test vtab1-3.4 {
execsql {
SELECT a FROM t1;
}
} {1 4}
do_test vtab1-3.5 {
execsql {
SELECT rowid FROM t1;
}
} {1 2}
do_test vtab1-3.6 {
set echo_module ""
execsql {
SELECT * FROM t1;
}
} {1 2 3 4 5 6}
do_test vtab1-3.7 {
execsql {
SELECT rowid, * FROM t1;
}
} {1 1 2 3 2 4 5 6}
do_test vtab1-3.8 {
execsql {
SELECT a AS d, b AS e, c AS f FROM t1;
}
} {1 2 3 4 5 6}
# Execute some SELECT statements with WHERE clauses on the t1 table.
# Then check the echo_module variable (written to by the module methods
# in test8.c) to make sure the xBestIndex() and xFilter() methods were
# called correctly.
#
do_test vtab1-3.8 {
set echo_module ""
execsql {
SELECT * FROM t1;
}
set echo_module
} [list xBestIndex {SELECT rowid, * FROM 'treal'} \
xFilter {SELECT rowid, * FROM 'treal'} ]
do_test vtab1-3.9 {
set echo_module ""
execsql {
SELECT * FROM t1 WHERE b = 5;
}
} {4 5 6}
do_test vtab1-3.10 {
set echo_module
} [list xBestIndex {SELECT rowid, * FROM 'treal' WHERE b = ?} \
xFilter {SELECT rowid, * FROM 'treal' WHERE b = ?} 5 ]
do_test vtab1-3.10 {
set echo_module ""
execsql {
SELECT * FROM t1 WHERE b >= 5 AND b <= 10;
}
} {4 5 6}
do_test vtab1-3.11 {
set echo_module
} [list xBestIndex {SELECT rowid, * FROM 'treal' WHERE b >= ? AND b <= ?} \
xFilter {SELECT rowid, * FROM 'treal' WHERE b >= ? AND b <= ?} 5 10 ]
do_test vtab1-3.12 {
set echo_module ""
execsql {
SELECT * FROM t1 WHERE b BETWEEN 2 AND 10;
}
} {1 2 3 4 5 6}
do_test vtab1-3.13 {
set echo_module
} [list xBestIndex {SELECT rowid, * FROM 'treal' WHERE b >= ? AND b <= ?} \
xFilter {SELECT rowid, * FROM 'treal' WHERE b >= ? AND b <= ?} 2 10 ]
# Add a function for the MATCH operator. Everything always matches!
#proc test_match {lhs rhs} {
# lappend ::echo_module MATCH $lhs $rhs
# return 1
#}
#db function match test_match
set echo_module ""
do_test vtab1-3.12 {
set echo_module ""
catchsql {
SELECT * FROM t1 WHERE a MATCH 'string';
}
} {1 {MATCH is not implemented}}
do_test vtab1-3.13 {
set echo_module
} [list xBestIndex {SELECT rowid, * FROM 'treal'} \
xFilter {SELECT rowid, * FROM 'treal'}]
do_test vtab1-3.14 {
set echo_module ""
btree_breakpoint
execsql {
SELECT * FROM t1 WHERE b MATCH 'string';
}
} {}
do_test vtab1-3.15 {
set echo_module
} [list xBestIndex \
{SELECT rowid, * FROM 'treal' WHERE b LIKE (SELECT '%'||?||'%')} \
xFilter \
{SELECT rowid, * FROM 'treal' WHERE b LIKE (SELECT '%'||?||'%')} \
string ]
#----------------------------------------------------------------------
# Test case vtab1-3 test table scans and the echo module's
# xBestIndex/xFilter handling of ORDER BY clauses.
# This procedure executes the SQL. Then it checks to see if the OP_Sort
# opcode was executed. If an OP_Sort did occur, then "sort" is appended
# to the result. If no OP_Sort happened, then "nosort" is appended.
#
# This procedure is used to check to make sure sorting is or is not
# occurring as expected.
#
proc cksort {sql} {
set ::sqlite_sort_count 0
set data [execsql $sql]
if {$::sqlite_sort_count} {set x sort} {set x nosort}
lappend data $x
return $data
}
do_test vtab1-4.1 {
set echo_module ""
cksort {
SELECT b FROM t1 ORDER BY b;
}
} {2 5 nosort}
do_test vtab1-4.2 {
set echo_module
} [list xBestIndex {SELECT rowid, * FROM 'treal' ORDER BY b ASC} \
xFilter {SELECT rowid, * FROM 'treal' ORDER BY b ASC} ]
do_test vtab1-4.3 {
set echo_module ""
cksort {
SELECT b FROM t1 ORDER BY b DESC;
}
} {5 2 nosort}
do_test vtab1-4.4 {
set echo_module
} [list xBestIndex {SELECT rowid, * FROM 'treal' ORDER BY b DESC} \
xFilter {SELECT rowid, * FROM 'treal' ORDER BY b DESC} ]
do_test vtab1-4.3 {
set echo_module ""
cksort {
SELECT b FROM t1 ORDER BY b||'';
}
} {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-5 test SELECT queries that include joins on virtual
# tables.
proc filter {log} {
set out [list]
for {set ii 0} {$ii < [llength $log]} {incr ii} {
if {[lindex $log $ii] eq "xFilter"} {
lappend out xFilter
lappend out [lindex $log [expr $ii+1]]
}
}
return $out
}
do_test vtab1-5-1 {
execsql {
CREATE TABLE t1(a, b, c);
CREATE TABLE t2(d, e, f);
INSERT INTO t1 VALUES(1, 'red', 'green');
INSERT INTO t1 VALUES(2, 'blue', 'black');
INSERT INTO t2 VALUES(1, 'spades', 'clubs');
INSERT INTO t2 VALUES(2, 'hearts', 'diamonds');
CREATE VIRTUAL TABLE et1 USING echo(t1);
CREATE VIRTUAL TABLE et2 USING echo(t2);
}
} {}
do_test vtab1-5-2 {
set echo_module ""
execsql {
SELECT * FROM et1, et2;
}
} [list \
1 red green 1 spades clubs \
1 red green 2 hearts diamonds \
2 blue black 1 spades clubs \
2 blue black 2 hearts diamonds \
]
do_test vtab1-5-3 {
filter $echo_module
} [list \
xFilter {SELECT rowid, * FROM 't1'} \
xFilter {SELECT rowid, * FROM 't2'} \
xFilter {SELECT rowid, * FROM 't2'} \
]
do_test vtab1-5-4 {
set echo_module ""
execsql {
SELECT * FROM et1, et2 WHERE et2.d = 2;
}
} [list \
1 red green 2 hearts diamonds \
2 blue black 2 hearts diamonds \
]
do_test vtab1-5-5 {
filter $echo_module
} [list \
xFilter {SELECT rowid, * FROM 't1'} \
xFilter {SELECT rowid, * FROM 't2'} \
xFilter {SELECT rowid, * FROM 't2'} \
]
do_test vtab1-5-6 {
execsql {
CREATE INDEX i1 ON t2(d);
}
db close
sqlite3 db test.db
register_echo_module [sqlite3_connection_pointer db]
set echo_module ""
execsql {
SELECT * FROM et1, et2 WHERE et2.d = 2;
}
} [list \
1 red green 2 hearts diamonds \
2 blue black 2 hearts diamonds \
]
do_test vtab1-5-7 {
filter $echo_module
} [list \
xFilter {SELECT rowid, * FROM 't2' WHERE d = ?} \
xFilter {SELECT rowid, * FROM 't1'} \
]
execsql {
DROP TABLE t1;
DROP TABLE t2;
DROP TABLE et1;
DROP TABLE et2;
}
#----------------------------------------------------------------------
# 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 {
UPDATE techo set a = a||b||c;
SELECT * FROM techo;
}
} {523 2 3}
do_test vtab1-6-6 {
execsql {
UPDATE techo set rowid = 10;
SELECT rowid FROM techo;
}
} {10}
do_test vtab1-6-7 {
execsql {
DELETE FROM techo;
SELECT * FROM techo;
}
} {}
file delete -force test2.db
file delete -force test2.db-journal
sqlite3 db2 test2.db
execsql {
CREATE TABLE techo(a PRIMARY KEY, b, c);
} db2
proc check_echo_table {tn} {
set ::data1 [execsql {SELECT rowid, * FROM techo}]
set ::data2 [execsql {SELECT rowid, * FROM techo} db2]
do_test $tn {
string equal $::data1 $::data2
} 1
}
set tn 0
foreach stmt [list \
{INSERT INTO techo VALUES('abc', 'def', 'ghi')} \
{INSERT INTO techo SELECT a||'.'||rowid, b, c FROM techo} \
{INSERT INTO techo SELECT a||'x'||rowid, b, c FROM techo} \
{INSERT INTO techo SELECT a||'y'||rowid, b, c FROM techo} \
{DELETE FROM techo WHERE (oid % 3) = 0} \
{UPDATE techo set rowid = 100 WHERE rowid = 1} \
{INSERT INTO techo(a, b) VALUES('hello', 'world')} \
{DELETE FROM techo} \
] {
execsql $stmt
execsql $stmt db2
check_echo_table vtab1-6.8.[incr tn]
}
db2 close
#----------------------------------------------------------------------
# Test cases vtab1-7 tests that the value returned by
# sqlite3_last_insert_rowid() is set correctly when rows are inserted
# into virtual tables.
do_test vtab1.7-1 {
execsql {
CREATE TABLE real_abc(a PRIMARY KEY, b, c);
CREATE VIRTUAL TABLE echo_abc USING echo(real_abc);
}
} {}
do_test vtab1.7-2 {
execsql {
INSERT INTO echo_abc VALUES(1, 2, 3);
SELECT last_insert_rowid();
}
} {1}
do_test vtab1.7-3 {
execsql {
INSERT INTO echo_abc(rowid) VALUES(31427);
SELECT last_insert_rowid();
}
} {31427}
do_test vtab1.7-4 {
execsql {
INSERT INTO echo_abc SELECT a||'.v2', b, c FROM echo_abc;
SELECT last_insert_rowid();
}
} {31429}
do_test vtab1.7-5 {
execsql {
SELECT rowid, a, b, c FROM echo_abc
}
} [list 1 1 2 3 \
31427 {} {} {} \
31428 1.v2 2 3 \
31429 {} {} {} \
]
# Now test that DELETE and UPDATE operations do not modify the value.
do_test vtab1.7-6 {
execsql {
UPDATE echo_abc SET c = 5 WHERE b = 2;
SELECT last_insert_rowid();
}
} {31429}
do_test vtab1.7-7 {
execsql {
UPDATE echo_abc SET rowid = 5 WHERE rowid = 1;
SELECT last_insert_rowid();
}
} {31429}
do_test vtab1.7-8 {
execsql {
DELETE FROM echo_abc WHERE b = 2;
SELECT last_insert_rowid();
}
} {31429}
do_test vtab1.7-9 {
execsql {
SELECT rowid, a, b, c FROM echo_abc
}
} [list 31427 {} {} {} \
31429 {} {} {} \
]
do_test vtab1.7-10 {
execsql {
DELETE FROM echo_abc WHERE b = 2;
SELECT last_insert_rowid();
}
} {31429}
do_test vtab1.7-11 {
execsql {
SELECT rowid, a, b, c FROM real_abc
}
} [list 31427 {} {} {} \
31429 {} {} {} \
]
do_test vtab1.7-12 {
execsql {
DELETE FROM echo_abc;
SELECT last_insert_rowid();
}
} {31429}
do_test vtab1.7-13 {
execsql {
SELECT rowid, a, b, c FROM real_abc
}
} {}
do_test vtab1.8-1 {
set echo_module ""
execsql {
ATTACH 'test2.db' AS aux;
CREATE VIRTUAL TABLE aux.e2 USING echo(real_abc);
}
set echo_module
} [list xCreate echo aux e2 real_abc \
xSync echo(real_abc) \
xCommit echo(real_abc) \
]
do_test vtab1.8-2 {
execsql {
DROP TABLE aux.e2;
DROP TABLE treal;
DROP TABLE techo;
DROP TABLE echo_abc;
DROP TABLE real_abc;
}
} {}
do_test vtab1.9-1 {
set echo_module ""
execsql {
CREATE TABLE r(a, b, c);
CREATE VIRTUAL TABLE e USING echo(r, e_log);
SELECT name FROM sqlite_master;
}
} {r e e_log}
do_test vtab1.9-2 {
execsql {
DROP TABLE e;
SELECT name FROM sqlite_master;
}
} {r}
do_test vtab1.9-3 {
set echo_module ""
execsql {
CREATE VIRTUAL TABLE e USING echo(r, e_log, virtual 1 2 3 varchar(32));
}
set echo_module
} [list \
xCreate echo main e r e_log {virtual 1 2 3 varchar(32)} \
xSync echo(r) \
xCommit echo(r) \
]
do_test vtab1.10-1 {
execsql {
CREATE TABLE del(d);
CREATE VIRTUAL TABLE e2 USING echo(del);
}
db close
sqlite3 db test.db
register_echo_module [sqlite3_connection_pointer db]
execsql {
DROP TABLE del;
}
catchsql {
SELECT * FROM e2;
}
} {1 {vtable constructor failed: e2}}
do_test vtab1.10-2 {
set rc [catch {
set ptr [sqlite3_connection_pointer db]
sqlite3_declare_vtab $ptr {CREATE TABLE abc(a, b, c)}
} msg]
list $rc $msg
} {1 {library routine called out of sequence}}
do_test vtab1.10-3 {
set ::echo_module_begin_fail r
catchsql {
INSERT INTO e VALUES(1, 2, 3);
}
} {1 {SQL logic error or missing database}}
do_test vtab1.10-4 {
catch {execsql {
EXPLAIN SELECT * FROM e WHERE rowid = 2;
EXPLAIN QUERY PLAN SELECT * FROM e WHERE rowid = 2 ORDER BY rowid;
}}
} {0}
do_test vtab1.10-5 {
set echo_module ""
execsql {
SELECT * FROM e WHERE rowid||'' MATCH 'pattern';
}
set echo_module
} [list \
xBestIndex {SELECT rowid, * FROM 'r'} \
xFilter {SELECT rowid, * FROM 'r'} \
]
proc match_func {args} {return ""}
do_test vtab1.10-6 {
set echo_module ""
db function match match_func
execsql {
SELECT * FROM e WHERE match('pattern', rowid, 'pattern2');
}
set echo_module
} [list \
xBestIndex {SELECT rowid, * FROM 'r'} \
xFilter {SELECT rowid, * FROM 'r'} \
]
# Testing the xFindFunction interface
#
do_test vtab1.11-1 {
execsql {
INSERT INTO r(a,b,c) VALUES(1,'?',99);
INSERT INTO r(a,b,c) VALUES(2,3,99);
SELECT a GLOB b FROM e
}
} {1 0}
proc ::echo_glob_overload {a b} {
return [list $b $a]
}
do_test vtab1.11-2 {
execsql {
SELECT a like 'b' FROM e
}
} {0 0}
do_test vtab1.11-3 {
execsql {
SELECT a glob '2' FROM e
}
} {{1 2} {2 2}}
do_test vtab1.11-4 {
execsql {
SELECT glob('2',a) FROM e
}
} {0 1}
do_test vtab1.11-5 {
execsql {
SELECT glob(a,'2') FROM e
}
} {{2 1} {2 2}}
finish_test