Files
turso/testing/pragma.test
Jussi Saurio beaf393476 Merge 'Treat table-valued functions as tables' from Piotr Rżysko
First step toward resolving
https://github.com/tursodatabase/limbo/issues/1643.
### This PR
With this change, the following two queries are considered equivalent:
```sql
SELECT value FROM generate_series(5, 50);
SELECT value FROM generate_series WHERE start = 5 AND stop = 50;
```
Arguments passed in parentheses to the virtual table name are now
matched to hidden columns.
Additionally, I fixed two bugs related to virtual tables.
### TODO (I'll handle this in a separate PR)
Column references are still not supported as table-valued function
arguments. The only difference is that previously, a query like:
```sql
SELECT one.value, series.value
FROM (SELECT 1 AS value) one, generate_series(one.value, 3) series;
```
would cause a panic. Now, it returns a proper error message instead.
Adding support for column references is more nuanced for two main
reasons:
* We need to ensure that in joins where a TVF depends on other tables,
those other tables are processed first. For example, in:
```sql
SELECT one.value, series.value
FROM generate_series(one.value, 3) series, (SELECT 1 AS value) one;
```
the one table must be processed by the top-level loop, and series must
be nested.
* For outer joins involving TVFs, the arguments must be treated as `ON`
predicates, not `WHERE` predicates.

Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>

Closes #1727
2025-07-15 12:23:45 +03:00

232 lines
6.3 KiB
Tcl
Executable File

#!/usr/bin/env tclsh
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_execsql_test_on_specific_db ":memory:" pragma-cache-size-default {
PRAGMA cache_size
} {-2000}
do_execsql_test pragma-set-cache-size {
PRAGMA cache_size = 100;
PRAGMA cache_size
} {100}
# Even though the cache size was set to 100 in previous test, a new connection defaults back to -2000.
do_execsql_test pragma-cache-size {
PRAGMA cache_size
} {-2000}
do_execsql_test pragma-function-cache-size {
SELECT * FROM pragma_cache_size()
} {-2000}
do_execsql_test pragma-update-journal-mode-wal {
PRAGMA journal_mode=WAL
} {wal}
do_execsql_test pragma-function-update-journal-mode {
SELECT * FROM pragma_journal_mode()
} {wal}
do_execsql_test pragma-table-info-equal-syntax {
PRAGMA table_info=sqlite_schema
} {0|type|TEXT|0||0
1|name|TEXT|0||0
2|tbl_name|TEXT|0||0
3|rootpage|INT|0||0
4|sql|TEXT|0||0
}
do_execsql_test pragma-table-info-call-syntax {
PRAGMA table_info(sqlite_schema)
} {0|type|TEXT|0||0
1|name|TEXT|0||0
2|tbl_name|TEXT|0||0
3|rootpage|INT|0||0
4|sql|TEXT|0||0
}
do_execsql_test pragma-table-info-alt-name-equal-syntax {
PRAGMA table_info=sqlite_master
} {0|type|TEXT|0||0
1|name|TEXT|0||0
2|tbl_name|TEXT|0||0
3|rootpage|INT|0||0
4|sql|TEXT|0||0
}
do_execsql_test pragma-table-info-alt-name-call-syntax {
PRAGMA table_info(sqlite_master)
} {0|type|TEXT|0||0
1|name|TEXT|0||0
2|tbl_name|TEXT|0||0
3|rootpage|INT|0||0
4|sql|TEXT|0||0
}
do_execsql_test pragma-function-table-info-alt-name {
SELECT * FROM pragma_table_info('sqlite_master')
} {0|type|TEXT|0||0
1|name|TEXT|0||0
2|tbl_name|TEXT|0||0
3|rootpage|INT|0||0
4|sql|TEXT|0||0
}
do_execsql_test pragma-function-table-info {
SELECT * FROM pragma_table_info('sqlite_schema')
} {0|type|TEXT|0||0
1|name|TEXT|0||0
2|tbl_name|TEXT|0||0
3|rootpage|INT|0||0
4|sql|TEXT|0||0
}
do_execsql_test pragma-vtab-table-info {
SELECT * FROM pragma_table_info WHERE arg = 'sqlite_schema'
} {0|type|TEXT|0||0
1|name|TEXT|0||0
2|tbl_name|TEXT|0||0
3|rootpage|INT|0||0
4|sql|TEXT|0||0
}
do_execsql_test pragma-table-info-invalid-table {
PRAGMA table_info=pekka
} {}
do_execsql_test pragma-function-table-info-invalid-table {
SELECT * FROM pragma_table_info('pekka')
} {}
do_execsql_test pragma-vtab-table-info-invalid-table {
SELECT * FROM pragma_table_info WHERE arg = 'pekka'
} {}
# temporarily skip this test case. The issue is detailed in #1407
#do_execsql_test_on_specific_db ":memory:" pragma-page-count-empty {
# PRAGMA page_count
#} {0}
do_execsql_test_on_specific_db ":memory:" pragma-page-count-table {
CREATE TABLE foo(bar);
PRAGMA page_count
} {2}
do_execsql_test_on_specific_db "testing/testing_user_version_10.db" pragma-user-version-user-set {
PRAGMA user_version
} {10}
do_execsql_test_on_specific_db ":memory:" pragma-user-version-default {
PRAGMA user_version
} {0}
do_execsql_test_on_specific_db ":memory:" pragma-user-version-update {
PRAGMA user_version = 42;
PRAGMA user_version;
} {42}
do_execsql_test_on_specific_db ":memory:" pragma-user-version-negative-value {
PRAGMA user_version = -10;
PRAGMA user_version;
} {-10}
do_execsql_test_on_specific_db ":memory:" pragma-user-version-float-value {
PRAGMA user_version = 10.9;
PRAGMA user_version;
} {10}
do_execsql_test pragma-legacy-file-format {
PRAGMA legacy_file_format
} {}
do_execsql_test_error pragma-function-legacy-file-format {
SELECT * FROM pragma_legacy_file_format()
} {(no such table|Table.*not found)}
do_execsql_test_error_content pragma-function-too-many-arguments {
SELECT * FROM pragma_table_info('sqlite_schema', 'main', 'arg3')
} {"Too many arguments"}
do_execsql_test_error pragma-function-update {
SELECT * FROM pragma_wal_checkpoint()
} {(no such table|Table.*not found)}
do_execsql_test pragma-function-nontext-argument {
SELECT * FROM pragma_table_info('sqlite_schema', NULL);
} {0|type|TEXT|0||0
1|name|TEXT|0||0
2|tbl_name|TEXT|0||0
3|rootpage|INT|0||0
4|sql|TEXT|0||0
}
do_execsql_test pragma-vtab-nontext-argument {
SELECT * FROM pragma_table_info WHERE arg ='sqlite_schema' AND schema IS NULL;
} {0|type|TEXT|0||0
1|name|TEXT|0||0
2|tbl_name|TEXT|0||0
3|rootpage|INT|0||0
4|sql|TEXT|0||0
}
do_execsql_test pragma-function-no-arguments {
SELECT * FROM pragma_table_info();
} {}
do_execsql_test pragma-vtab-no-arguments {
SELECT * FROM pragma_table_info;
} {}
do_execsql_test_on_specific_db ":memory:" pragma-function-argument-with-space {
CREATE TABLE "foo bar"(c0);
SELECT * FROM pragma_table_info('foo bar')
} {0|c0||0||0}
# If the argument passed to the first function call were simply concatenated with the underlying PRAGMA statement,
# we would end up with: PRAGMA table_info='sqlite_schema';CREATE TABLE foo(c0);SELECT 'bar'. Depending on how many
# statements are executed at once, at least one of the following would run:
# - PRAGMA table_info='sqlite_schema';
# - CREATE TABLE foo(c0);
# - SELECT 'bar';
# No output means that none of them were executed.
do_execsql_test pragma-function-sql-injection {
SELECT * FROM pragma_table_info('sqlite_schema'';CREATE TABLE foo(c0);SELECT ''bar');
SELECT * FROM pragma_table_info('foo');
} {}
do_execsql_test_on_specific_db ":memory:" pragma-page-size-default {
PRAGMA page_size
} {4096}
do_execsql_test_on_specific_db ":memory:" pragma-page-size-set {
PRAGMA page_size=1024;
PRAGMA page_size
} {1024}
# pragma page_size=xxx doesn't change the page size of an initialized database.
do_execsql_test_on_specific_db ":memory:" pragma-page-size-set-initialized-db {
CREATE TABLE "foo bar"(c0);
PRAGMA page_size=1024;
PRAGMA page_size
} {4096}
# pragma page_size=xxx changes the page size of an uninitialized database and persists the change.
set test_pragma_page_size_db "testing/testing_pragma_page_size.db"
catch {file delete -force $test_pragma_page_size_db}
catch {file delete -force "${test_pragma_page_size_db}-wal"}
# set user_version to trigger database initialization.
do_execsql_test_on_specific_db $test_pragma_page_size_db pragma-page-size-set-uninitialized-db-1 {
PRAGMA page_size=1024;
PRAGMA user_version=1;
PRAGMA page_size
} {1024}
do_execsql_test_on_specific_db $test_pragma_page_size_db pragma-page-size-set-uninitialized-db-2 {
PRAGMA page_size
} {1024}
catch {file delete -force $test_pragma_page_size_db}
catch {file delete -force "${test_pragma_page_size_db}-wal"}