Commit Graph

1215 Commits

Author SHA1 Message Date
Glauber Costa
57a1113460 make readonly a property of the database
There's no such thing as a read-only connection.
In a normal connection, you can have many attached databases. Some
r/o, some r/w.

To properly fix that, we also need to fix the OpenWrite opcode. Right
now we are passing a name, which is the name of the table. That
parameter is not used anywhere. That is also not what the SQLite opcode
specifies. Same as OpenRead, the p3 register should be the database
index.

With that change, we can - for now - pass the index 0, which is all
we support anyway, and then use that to test if we are r/o.
2025-07-22 09:41:32 -05:00
Pekka Enberg
afc22da07c Merge 'Fix duplicate SET statement compatibility with SQLite' from Ihor Andrianov
For duplicate SET statements, SQLite uses last one

Closes #2117
2025-07-22 09:02:16 +03:00
Pekka Enberg
8f83b150b7 Merge 'Implement pragma database_list' from Glauber Costa
And also the CLI option .databases, which is just manipulating that.
This is one step in the road to attach.

Closes #2195
2025-07-21 17:13:26 +03:00
Glauber Costa
0545049d59 Implement pragma database_list
And also the CLI option .databases, which is just manipulating that.

This is one step in the road to attach.
2025-07-21 08:49:35 -05:00
Jussi Saurio
81d8dc7e3d Merge 'Fix column order for multi-row insertion' from Nikita Sivukhin
Column order handled incorrectly for multi-rows insert case
```sql
turso> CREATE TABLE t(x, y, z);
turso> INSERT INTO t(z, x) VALUES (1, 2), (3, 4);
turso> SELECT * FROM t;
┌───┬───┬───┐
│ x │ y │ z │
├───┼───┼───┤
│   │ 2 │   │
├───┼───┼───┤
│   │ 4 │   │
└───┴───┴───┘
```

Closes #2109
2025-07-21 00:02:43 +03:00
Glauber Costa
65312baee6 fix opcodes missing a database register
Two of the opcodes we implement (OpenRead and Transaction) should have
an opcode specifying the database to use, but they don't.

Add it, and for now always use 0 (the main database).
2025-07-20 12:27:26 -05:00
Nikita Sivukhin
e733365057 fix code generation for insert command 2025-07-20 14:22:16 +04:00
Pekka Enberg
068a7bbe43 Merge 'implement pragma application_id' from Glauber Costa
Just for completeness, because it is easy.

Reviewed-by: Preston Thorpe (@PThorpe92)

Closes #2180
2025-07-20 09:22:20 +03:00
Glauber Costa
6506b3147d implement pragma application_id
Just for completeness, because it is easy.
2025-07-19 20:44:06 -05:00
Glauber Costa
024d79fc0d implement write side of pragma schema_version
It is insane that SQLite even allows this.
They actually don't if "defensive mode" is enabled:

"It is always safe to read the schema_version, but changing the
schema_version can cause problems. For this reason, attempts to change
the value of schema_version are a silent no-op when defensive mode is
enabled for a database connection.

Warning: Misuse of this pragma can result in database corruption."

We also update the compat table, which was not updated to reflect
the read version of this pragma being implemented.
2025-07-19 20:39:30 -05:00
Pekka Enberg
c2a8a6f178 Merge 'improve handling of double quotes' from Glauber Costa
I ended up hitting #1974 today and wanted to fix it. I worked with
Claude to generate a more comprehensive set of queries that could fail
aside from just the insert query described in the issue. He got most of
them right - lots of cases were indeed failing. The ones that were
gibberish, he told me I was absolutely right for pointing out they were
bad.
But alas. With the test cases generated, we can work on fixing it. The
place where the assertion was hit, all we need to do there is return
true (but we assert that this is indeed a string literal, it shouldn't
be anything else at this point).
There are then just a couple of places where we need to make sure we
handle double quotes correctly. We already tested for single quotes in a
couple of places, but never for double quotes.
There is one funny corner case where you can just select "col" from tbl,
and if there is no column "col" on the table, that is treated as a
string literal. We handle that too.
Fixes #1974

Closes #2152
2025-07-18 20:55:37 +03:00
Glauber Costa
cbdd5c5fc7 improve handling of double quotes
I ended up hitting #1974 today and wanted to fix it. I worked with
Claude to generate a more comprehensive set of queries that could fail
aside from just the insert query described in the issue. He got most of
them right - lots of cases were indeed failing. The ones that were
gibberish, he told me I was absolutely right for pointing out they were
bad.

But alas. With the test cases generated, we can work on fixing it. The
place where the assertion was hit, all we need to do there is return
true (but we assert that this is indeed a string literal, it shouldn't
be anything else at this point).

There are then just a couple of places where we need to make sure we
handle double quotes correctly. We already tested for single quotes in a
couple of places, but never for double quotes.

There is one funny corner case where you can just select "col" from tbl,
and if there is no column "col" on the table, that is treated as a
string literal. We handle that too.

Fixes #1974
2025-07-18 10:39:02 -05:00
Jussi Saurio
55151a8061 Fix cases where Insn::Insert needs to seek to ensure correct insertion 2025-07-18 13:48:23 +03:00
Jussi Saurio
9201030e67 Ephemeral UNION indexes don't need to be UNIQUE 2025-07-18 13:48:23 +03:00
Jussi Saurio
483dc27539 Merge 'make most instrumentation levels to be Debug or Trace instead' from Pedro Muniz
Span creation in debug mode is very slow and impacts our ability to run
the Simulator faster.

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

Closes #2146
2025-07-17 23:45:07 +03:00
Jussi Saurio
1b52b5c764 Merge 'chore: update rust to version 1.88.0' from Nils Koch
This PR updates to version Rust 1.88.0 ([Release
notes](https://releases.rs/docs/1.88.0/)) and fixes all the clippy
errors that come with the new Rust version.
This is possible in the latest Rust version:
```rust
if let Some(foo) = bar && foo.is_cool() {
  ...
}
```
There are three complications in the migration (so far):
- A BUNCH of Clippy warnings (mostly fixed in
https://github.com/tursodatabase/limbo/pull/1827)
- Windows cross compilation failed; linking `advapi32` on windows fixes
it
  - Since Rust 1.87.0, advapi32 is not linked by default anymore
([Release notes](https://github.com/rust-
lang/rust/blob/master/RELEASES.md#compatibility-notes-1),
[PR](https://github.com/rust-lang/rust/pull/138233))
- Rust is more strict with FFIs and aligning pointers now. CI checks
failed with error below
  - Fixed in https://github.com/tursodatabase/turso/pull/2064
```
thread 'main' panicked at
core/ext/vtab_xconnect.rs:64:25:
misaligned pointer dereference: address must be
a multiple of 0x8 but is 0x7ffd9d901554
```

Closes #1807
2025-07-17 23:35:33 +03:00
pedrocarlo
c15f1e02d3 make most instrumentation levels to be Debug or Trace instead. Span creation in debug mode is very slow and impacts our ability to run the Simulator fast enough 2025-07-17 16:48:24 -03:00
Jussi Saurio
a45ac11462 translate/create index: fix wrong collations 2025-07-17 21:07:48 +03:00
Pekka Enberg
d2158ff201 Merge 'Clean up AST unparsing, remove ToSqlString' from Levy A.
Enables formatting `Expr::Column` by adding the context to `ToTokens`
instead of creating a new unparsing implementation for each node.
`ToTokens` implemented for:
- [x] `UpdatePlan`
- [x] `Plan`
- [x] `JoinedTable`
- [x] `SelectPlan`
- [x] `DeletePlan`

Reviewed-by: Pedro Muniz (@pedrocarlo)

Closes #1949
2025-07-17 08:44:31 +03:00
Nils Koch
8dc066503e chore: fix clippy errors 2025-07-16 19:34:42 +01:00
Nikita Sivukhin
97b82fe6d8 rename operation_xxx to change_xxx to make naming more consistent 2025-07-16 20:16:24 +04:00
Levy A.
714225b9f0 remove ToSqlString trait 2025-07-16 12:16:34 -03:00
Levy A.
6fe2505425 add more ToTokens impls 2025-07-16 12:16:31 -03:00
Levy A.
373a4a26c4 fix: comma function 2025-07-16 12:16:28 -03:00
Levy A.
765b90aeb9 feat: implement ToTokens for UpdatePlan 2025-07-16 12:16:23 -03:00
Ihor Andrianov
37dd5da436 clippy 2025-07-16 15:05:06 +03:00
Ihor Andrianov
6d4e542522 last set clause wins 2025-07-16 14:56:10 +03:00
Nikita Sivukhin
c018b06bf5 fix bug in concat_ws translation 2025-07-16 00:48:17 +04:00
Nikita Sivukhin
f7fb2aac5e adjust extra_amount for schema translation code 2025-07-16 00:47:59 +04:00
Nikita Sivukhin
be0a607ba8 rename amount -> extra_amount 2025-07-16 00:46:17 +04:00
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
meteorgan
f123c77ee8 fix set page_size in pager 2025-07-15 16:34:07 +08:00
meteorgan
e2ab673624 fix self.pager.replace() panic 2025-07-15 16:34:07 +08:00
meteorgan
bf69b86e94 fix: not all pragma need transaction 2025-07-15 16:34:07 +08:00
meteorgan
a6faab17e9 fix query page size 2025-07-15 16:34:07 +08:00
meteorgan
cf126824de Support set page size 2025-07-15 16:34:07 +08:00
Pekka Enberg
1653b0883a Merge 'core/vector: Euclidean distance support for vector search' from KarinaMilet
This PR provides Euclidean distance support for limbo's vector search.
At the same time, some type abstractions are introduced, such as
`DistanceCalculator`, etc. This is because I hope to unify the current
vector module in the future to make it more structured, clearer, and
more extensible.
While practicing Euclidean distance for Limbo, I discovered that many
checks could be done using the type system or in advance, rather than
waiting until the distance is calculated. By building these checks into
the type system or doing them ahead of time, this would allow us to
explore more efficient computations, such as automatic vectorization or
SIMD acceleration, which is future work.

Reviewed-by: Nikita Sivukhin (@sivukhin)

Closes #1986
2025-07-14 13:07:20 +03:00
Pekka Enberg
0b544717a1 Merge 'do not check rowid alias for null' from Nikita Sivukhin
Simple PR to check minor issue that `INTEGER PRIMARY KEY NOT NULL` (`NOT
NULL` is redundant here obviously) will prevent user to insert anything
to the table as rowid-alias column always set to null by `turso-db`

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

Closes #2063
2025-07-14 11:55:06 +03:00
Nikita Sivukhin
e94ebbad04 remove unwanted changes 2025-07-14 11:27:51 +04:00
Nikita Sivukhin
81cd04dd65 add bin_record_json_object and table_columns_json_array functions 2025-07-14 11:19:45 +04:00
Nikita Sivukhin
eed89993f9 fix clippy 2025-07-14 11:17:32 +04:00
Nikita Sivukhin
5409812610 properly implement generation of before/after records for new modes 2025-07-14 11:17:32 +04:00
Nikita Sivukhin
fabb00f385 fix test 2025-07-14 11:16:06 +04:00
Nikita Sivukhin
b258c10c9a generate before/after row values in modification statements 2025-07-14 11:16:06 +04:00
Nikita Sivukhin
9129991b62 add id,before,after,full modes 2025-07-14 11:16:06 +04:00
Piotr Rzysko
30ae6538ee Treat table-valued functions as tables
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.

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.
2025-07-14 07:16:53 +02:00
Piotr Rzysko
9102f4a2f4 Extract table parsing into separate method
This is in preparation for reusing the method when parsing `TableCall`s.
2025-07-14 07:16:53 +02:00
Piotr Rzysko
44b1b1852a Fix referencing virtual table predicates
We need to enumerate first and filter afterward — not the other way
around — because we later use the indexes produced by `enumerate` to
access the original `predicates` slice.
2025-07-14 07:16:53 +02:00
Piotr Rzysko
319cdbe3af Don't use search for virtual tables
Previously, the test queries added in this commit would fail with:
thread 'main' panicked at core/schema.rs:129:34:
not implemented
stack backtrace:
   0: rust_begin_unwind
             at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/std/src/panicking.rs:665:5
   1: core::panicking::panic_fmt
             at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/panicking.rs:74:14
   2: core::panicking::panic
             at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/panicking.rs:148:5
   3: limbo_core::schema::Table::get_root_page
             at ./core/schema.rs:129:34
   4: limbo_core::translate::main_loop::init_loop
             at ./core/translate/main_loop.rs:260:44
   5: limbo_core::translate::emitter::emit_query
             at ./core/translate/emitter.rs:568:5
   6: limbo_core::translate::emitter::emit_program_for_select
             at ./core/translate/emitter.rs:496:5
   7: limbo_core::translate::emitter::emit_program
             at ./core/translate/emitter.rs:187:31
   8: limbo_core::translate::select::translate_select
             at ./core/translate/select.rs:82:5
   9: limbo_core::translate::translate_inner
             at ./core/translate/mod.rs:241:13
  10: limbo_core::translate::translate
             at ./core/translate/mod.rs:95:17
  11: limbo_core::Connection::run_cmd
             at ./core/lib.rs:416:31
  12: <limbo_core::QueryRunner as core::iter::traits::iterator::Iterator>::next
             at ./core/lib.rs:916:22
  13: limbo::app::Limbo::run_query
             at ./cli/app.rs:442:27
  14: limbo::app::Limbo::handle_input_line
             at ./cli/app.rs:544:13
  15: limbo::main
             at ./cli/main.rs:51:31
  16: core::ops::function::FnOnce::call_once
2025-07-14 07:16:53 +02:00
Piotr Rzysko
000d70f1f3 Propagate info about hidden columns 2025-07-14 07:16:53 +02:00