#!/usr/bin/env tclsh set testdir [file dirname $argv0] source $testdir/tester.tcl load_extension test_ext do_execsql_test_in_memory_error_content create-virtual-table-duplicate-name-1 { CREATE VIRTUAL TABLE t1 USING kv_store; CREATE VIRTUAL TABLE t1 USING kv_store; } {Table t1 already exists} do_execsql_test_in_memory_error_content create-virtual-table-duplicate-name-2 { CREATE TABLE t2 (col INTEGER); CREATE VIRTUAL TABLE t2 USING kv_store; } {Table t2 already exists} do_execsql_test_in_memory_error_content create-virtual-table-duplicate-name-3 { CREATE VIRTUAL TABLE t3 USING kv_store; CREATE TABLE t3 (col INTEGER); } {Table t3 already exists} do_execsql_test_on_specific_db {:memory:} create-virtual-table-if-not-exists-1 { CREATE TABLE t2 (col INTEGER); CREATE VIRTUAL TABLE IF NOT EXISTS t2 USING kv_store; } {} do_execsql_test_on_specific_db {:memory:} create-virtual-table-if-not-exists-2 { CREATE VIRTUAL TABLE t1 USING kv_store; CREATE VIRTUAL TABLE IF NOT EXISTS t1 USING kv_store; } {} do_execsql_test_on_specific_db {:memory:} drop-virtual-table { CREATE VIRTUAL TABLE t USING kv_store; INSERT INTO t VALUES ('hello', 'world'); DROP TABLE t; } {} do_execsql_test_in_memory_error_content drop-virtual-table-twice { CREATE VIRTUAL TABLE t USING kv_store; INSERT INTO t VALUES ('hello', 'world'); DROP TABLE t; DROP TABLE t; } {no such table: t} do_execsql_test_on_specific_db {:memory:} select-hidden-column { create virtual table t using kv_store; insert into t(key, value) values ('k0', 'v0'); select comment from t where key = 'k0'; } {auto-generated} # hidden columns are not exposed by subqueries by default do_execsql_test_in_memory_error select-hidden-column-subquery-1 { create virtual table t using kv_store; insert into t(key, value) values ('k0', 'v0'); select comment from (select * from t where key = 'k0'); } {.*no such column.*} do_execsql_test_on_specific_db {:memory:} select-hidden-column-subquery-2 { create virtual table t using kv_store; insert into t(key, value) values ('k0', 'v0'); select * from (select comment from t where key = 'k0'); } {auto-generated} do_execsql_test_on_specific_db {:memory:} insert-hidden-column { create virtual table t using kv_store; insert into t(comment, key, value) values ('my comment', 'hidden', 'test'); select comment from t where key = 'hidden'; } {"my comment"} # hidden columns should be excluded from * expansion do_execsql_test_on_specific_db {:memory:} select-star-hidden-column { create virtual table t using kv_store; insert into t(comment, key, value) values ('my comment', 'hidden', 'test'); select * from t where key = 'hidden'; } {hidden|test} # hidden columns should be excluded from .* expansion do_execsql_test_on_specific_db {:memory:} select-table-star-hidden-column { create virtual table t using kv_store; insert into t(comment, key, value) values ('my comment', 'hidden', 'test'); select t.* from t where key = 'hidden'; } {hidden|test} do_execsql_test_in_memory_error insert-values-column-count-mismatch { create virtual table t using kv_store; insert into t(comment, key, value) values ('insert_hidden', 'test'); } {.*2 values for 3 columns.*} do_execsql_test_on_specific_db {:memory:} update-hidden-column { create virtual table t using kv_store; insert into t(comment, key, value) values ('my comment', 'hidden', 'test'); update t set comment = 'updated comment' where key = 'hidden'; select comment from t where key = 'hidden'; } {"updated comment"} # hidden columns are not listed in the dataset returned by 'PRAGMA table_info' do_execsql_test_on_specific_db {:memory:} pragma-table-info-hidden-columns { create virtual table t using kv_store; PRAGMA table_info=t; } {0|key|TEXT|0||1 1|value|TEXT|0||0} do_execsql_test_on_specific_db {:memory:} group-by-hidden-column { create virtual table t using kv_store; insert into t(key, value) values ('k0', 'v0'); insert into t(key, value) values ('k1', 'v1'); insert into t(comment, key, value) values ('updated_comment', 'hidden', 'test'); select comment, count(*) from t group by comment order by comment; } {auto-generated|2 updated_comment|1} do_execsql_test_on_specific_db {:memory:} order-by-hidden-column { CREATE VIRTUAL TABLE o USING kv_store; INSERT INTO o(comment, key, value) VALUES ('0', '5', 'a'); INSERT INTO o(comment, key, value) VALUES ('1', '4', 'b'); INSERT INTO o(comment, key, value) VALUES ('2', '3', 'c'); SELECT * FROM o ORDER BY comment; } {5|a 4|b 3|c} do_execsql_test_in_memory_error order-by-hidden-column-index { CREATE VIRTUAL TABLE o USING kv_store; INSERT INTO o(comment, key, value) VALUES ('0', '5', 'a'); SELECT * FROM o ORDER BY 0; } {.*(invalid column index|term out of range).*} do_execsql_test_on_specific_db {:memory:} order-by-standard-column-index { CREATE VIRTUAL TABLE o USING kv_store; INSERT INTO o(comment, key, value) VALUES ('0', '5', 'a'); INSERT INTO o(comment, key, value) VALUES ('1', '4', 'b'); INSERT INTO o(comment, key, value) VALUES ('2', '3', 'c'); SELECT * FROM o ORDER BY 1; } {3|c 4|b 5|a} do_execsql_test_on_specific_db {:memory:} natural-join-hidden-column-1 { CREATE TABLE r (comment, key, value); INSERT INTO r VALUES ('comment0', '2', '3'); INSERT INTO r VALUES ('comment1', '4', '5'); CREATE VIRTUAL TABLE l USING kv_store; INSERT INTO l(comment, key, value) values ('comment1', '2', '3'); SELECT * FROM l NATURAL JOIN r; } {2|3|comment0} do_execsql_test_on_specific_db {:memory:} natural-join-hidden-column-2 { CREATE TABLE r (comment, key, value); INSERT INTO r VALUES ('comment0', '2', '3'); INSERT INTO r VALUES ('comment1', '4', '5'); CREATE VIRTUAL TABLE l USING kv_store; INSERT INTO l(comment, key, value) values ('comment1', '2', '3'); SELECT * FROM r NATURAL JOIN l; } {comment0|2|3} do_execsql_test_on_specific_db {:memory:} join-using-hidden-column { CREATE TABLE r (comment, key, value); INSERT INTO r VALUES ('comment0', '2', '3'); INSERT INTO r VALUES ('comment1', '4', '5'); CREATE VIRTUAL TABLE l USING kv_store; INSERT INTO l(comment, key, value) values ('comment1', '2', '3'); SELECT * FROM l JOIN r USING (comment); } {2|3|4|5} do_execsql_test_on_specific_db {:memory:} join-on-hidden-column { CREATE TABLE r (comment, key, value); INSERT INTO r VALUES ('comment0', '2', '3'); INSERT INTO r VALUES ('comment1', '4', '5'); CREATE VIRTUAL TABLE l USING kv_store; INSERT INTO l(comment, key, value) values ('comment1', '2', '3'); SELECT * FROM l JOIN r ON l.comment = r.comment; } {2|3|comment1|4|5} do_execsql_test_on_specific_db {:memory:} natural-join-hidden-column-multiple-vtabs-1 { CREATE TABLE r (comment, key, value); INSERT INTO r VALUES ('comment0', '2', '3'); INSERT INTO r VALUES ('comment1', '4', '5'); CREATE VIRTUAL TABLE l USING kv_store; INSERT INTO l(comment, key, value) values ('comment1', '2', '3'); SELECT * FROM l NATURAL JOIN r NATURAL JOIN r; } {2|3|comment0} do_execsql_test_on_specific_db {:memory:} natural-join-hidden-column-multiple-vtabs-2 { CREATE TABLE r (comment, key, value); INSERT INTO r VALUES ('comment0', '2', '3'); INSERT INTO r VALUES ('comment1', '4', '5'); CREATE VIRTUAL TABLE l USING kv_store; INSERT INTO l(comment, key, value) values ('comment1', '2', '3'); SELECT * FROM l NATURAL JOIN r NATURAL JOIN l; } {2|3|comment0} do_execsql_test_on_specific_db {:memory:} natural-join-hidden-column-multiple-vtabs-3 { CREATE TABLE r (comment, key, value); INSERT INTO r VALUES ('comment0', '2', '3'); INSERT INTO r VALUES ('comment1', '4', '5'); CREATE VIRTUAL TABLE l USING kv_store; INSERT INTO l(comment, key, value) values ('comment1', '2', '3'); SELECT * FROM r NATURAL JOIN l NATURAL JOIN r; } {comment0|2|3} do_execsql_test_on_specific_db {:memory:} join-using-hidden-column-subquery-1 { CREATE TABLE r (comment, key, value); INSERT INTO r VALUES ('comment0', '2', '3'); INSERT INTO r VALUES ('comment1', '4', '5'); CREATE VIRTUAL TABLE l USING kv_store; INSERT INTO l(comment, key, value) values ('comment1', '2', '3'); SELECT * FROM (SELECT * FROM l JOIN r USING(key, value)) JOIN r USING(comment, key, value); } {2|3|comment0} do_execsql_test_on_specific_db {:memory:} join-using-hidden-column-subquery-2 { CREATE TABLE r (comment, key, value); INSERT INTO r VALUES ('comment0', '2', '3'); INSERT INTO r VALUES ('comment1', '4', '5'); CREATE VIRTUAL TABLE l USING kv_store; INSERT INTO l(comment, key, value) values ('comment1', '2', '3'); SELECT * FROM (SELECT * FROM l NATURAL JOIN r) JOIN r USING(comment, key, value); } {2|3|comment0} do_execsql_test_on_specific_db {:memory:} multiple-join-using-hidden-column { CREATE TABLE r (comment, key, value); INSERT INTO r VALUES ('comment0', '2', '3'); INSERT INTO r VALUES ('comment1', '4', '5'); CREATE VIRTUAL TABLE l USING kv_store; INSERT INTO l(comment, key, value) values ('comment1', '2', '3'); SELECT * FROM l JOIN r USING(key, value) JOIN r USING(comment, key, value); } {} do_execsql_test_on_specific_db {:memory:} natural-join-using-hidden-column { CREATE TABLE r (comment, key, value); INSERT INTO r VALUES ('comment0', '2', '3'); INSERT INTO r VALUES ('comment1', '4', '5'); CREATE VIRTUAL TABLE l USING kv_store; INSERT INTO l(comment, key, value) values ('comment1', '2', '3'); SELECT * FROM l NATURAL JOIN r JOIN r USING(comment, key, value); } {} do_execsql_test tvf-hidden-column-constraints-as-args { SELECT * FROM generate_series WHERE start = 1 AND stop = 10; } {1 2 3 4 5 6 7 8 9 10} do_execsql_test tvf-hidden-column-constraints-as-args-rhs { SELECT * FROM generate_series WHERE 1 = start AND 10 = stop; } {1 2 3 4 5 6 7 8 9 10} do_execsql_test tvf-hidden-column-constraints-as-args-reversed { SELECT * FROM generate_series WHERE stop = 10 AND start = 1; } {1 2 3 4 5 6 7 8 9 10} do_execsql_test tvf-predicate-not-used-as-arg-1 { SELECT * FROM generate_series(1, 10) WHERE value < 5; } {1 2 3 4} do_execsql_test tvf-predicate-not-used-as-arg-2 { SELECT * FROM generate_series WHERE start = 1 AND stop = 10 AND value < 5; } {1 2 3 4} do_execsql_test tvf-multiple-constraints-on-same-column-1 { SELECT * FROM generate_series WHERE start = 1 AND stop = 10 AND start = 5; } {} do_execsql_test tvf-multiple-constraints-on-same-column-2 { SELECT * FROM generate_series WHERE start = 1 AND stop = 10 AND start > 5; } {} do_execsql_test tvf-multiple-constraints-on-same-column-3 { SELECT * FROM generate_series WHERE start = 1 AND stop = 10 AND step = 2; } {1 3 5 7 9} do_execsql_test_error_content tvf-too-many-args { SELECT * FROM generate_series(1, 10, 2, 3); } {too many arguments} do_execsql_test tvf-join-basic { SELECT a.value a_val, b.value b_val FROM generate_series(1, 3) a JOIN generate_series(1, 1) b ON a.value = b.value; } {1|1} do_execsql_test_on_specific_db {:memory:} insert-into-select-from-tvf { CREATE TABLE target (id integer primary key); INSERT INTO target SELECT * FROM generate_series(1, 5); SELECT * FROM target; } {1 2 3 4 5} do_execsql_test_on_specific_db {:memory:} tvf-arg-from-left-table-column { CREATE TABLE target (id integer primary key); INSERT INTO target SELECT * FROM generate_series(1, 5); SELECT t.id, series.value FROM target t, generate_series(t.id, 3) series WHERE t.id <= 3; } {1|1 1|2 1|3 2|2 2|3 3|3} do_execsql_test_on_specific_db {:memory:} tvf-arg-from-right-table-column { CREATE TABLE target (id integer primary key); INSERT INTO target SELECT * FROM generate_series(1, 5); SELECT t.id, series.value FROM generate_series(t.id, 3) series, target t WHERE t.id <= 3; } {1|1 1|2 1|3 2|2 2|3 3|3} do_execsql_test tvf-arg-from-left-subquery-column { SELECT one.value, series.value FROM (SELECT 1 AS value) one, generate_series(one.value, 3) series; } {1|1 1|2 1|3} do_execsql_test tvf-arg-from-right-subquery-column { SELECT one.value, series.value FROM generate_series(one.value, 3) series, (SELECT 1 AS value) one; } {1|1 1|2 1|3} do_execsql_test tvf-args-from-natural-join-columns { SELECT * FROM generate_series(a.start, a.stop) series NATURAL JOIN (SELECT 1 AS start, 3 AS stop, 2 AS value) a; } {2|1|3} do_execsql_test tvf-args-from-join-using-columns { SELECT * FROM generate_series(a.start, a.stop) JOIN (SELECT 1 AS start, 3 AS stop) a USING (start, stop); } {1 2 3} do_execsql_test tvf-args-from-another-tvf { SELECT a.value, b.value FROM generate_series(b.value, b.value+1) a JOIN generate_series(1, 2) b; } {1|1 2|1 2|2 3|2} do_execsql_test_error tvf-circular-column-references { SELECT * FROM generate_series(a.start, a.stop) b, generate_series(b.start, b.stop) a; } {No valid query plan found|no query solution}