closes#3282
includes minor refactor, removing `column_is_rowid_alias`, which is only
checking the public field of the argument Column.
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>
Closes#3385
We had code for this, but the code had a fatal flaw: it tried to detect
a complex operation (an operation that needs projection), and return
false (no need for projection), for the others.
This is the exact opposite of what we should do: we should identify the
*simple* operations, and then return true (needs projection) for the
rest.
CAST is a special beast, since it is not a function, but rather, a
special opcode. Everything else above is the true just the same. But for
CAST, we have to do the extra work to capture it in the logical plan and
pass it down.
Fixes#3372Fixes#3370Fixes#3369
Discovered this one while working on #3322
It was a bit more elusive because the original error was essentially a
red herring:
```
turso> CREATE INDEX idx ON "t t" (`a a`);
× unexpected token at SourceSpan { offset: SourceOffset(22), length: 1 }
╭────
1 │ CREATE INDEX idx ON "t t" (`a a`);
· ┬
· ╰── here
╰────
help: expected [TK_LP] but found TK_ID
```
Reviewed-by: Preston Thorpe <preston@turso.tech>
Closes#3345
This PR implements the `json_tree` table-valued function.
It's not 100% compatible with SQLite, because SQLite does some iffy
things with the `key` and `path` columns. I started a
[thread](https://www.sqlite.org/forum/forumpost/48f5763d8c) on their
forum and I linked it to the disabled tests in `json.test`.
Reviewed-by: Preston Thorpe <preston@turso.tech>
Closes#3256
fixes#1976
and #1605
```zsh
turso> DROP TABLE IF EXISTS t;
CREATE TABLE t (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT
);
turso> INSERT INTO t (name) VALUES ('A'); SELECT * FROM sqlite_sequence;
┌──────┬─────┐
│ name │ seq │
├──────┼─────┤
│ t │ 1 │
└──────┴─────┘
turso> DROP TABLE IF EXISTS t;
CREATE TABLE t (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT
);
turso> INSERT INTO t (name) VALUES ('A'); SELECT * FROM sqlite_sequence;
┌──────┬─────┐
│ name │ seq │
├──────┼─────┤
│ t │ 1 │
└──────┴─────┘
turso> INSERT INTO t (name) VALUES ('A'); SELECT * FROM sqlite_sequence;
┌──────┬─────┐
│ name │ seq │
├──────┼─────┤
│ t │ 2 │
└──────┴─────┘
turso>
```
Reviewed-by: Preston Thorpe <preston@turso.tech>
Closes#2983
This PR makes all JS db packages to have uniform interface: `new
Database(...)` constructor with explicit `connect()` and `close()`
methods.
Also, this PR adds docstrings in the code and properly support few
better-sqlite options (readonly, fileMustExist, timeout)
Closes#3334
Closes#3320Closes#3286
In addition to the problem reported in the ticket, 2 more issues were
identified:
1. Renaming a column for a table with a special character in its name
failed with
```
turso> CREATE TABLE `t t`(a);
turso> ALTER TABLE `t t` RENAME COLUMN a TO `a a`;
thread 'main' panicked at core/vdbe/execute.rs:7870:14:
table being renamed should be in schema
```
2. The renamed table in the `sql` column of `sqlite_schema` was not
reflected correctly after renaming:
```
turso> select * from sqlite_schema;
┌───────┬──────┬──────────┬──────────┬──────────────────────┐
│ type │ name │ tbl_name │ rootpage │ sql │
├───────┼──────┼──────────┼──────────┼──────────────────────┤
│ table │ t t │ t t │ 2 │ CREATE TABLE t t (a) │
└───────┴──────┴──────────┴──────────┴──────────────────────┘
```
3. `sql` for indexes was not reflected correctly after renaming a column
that contains special characters:
```
turso> ALTER TABLE `t t` RENAME COLUMN `a a` TO `b b`;
turso> SELECT sql FROM sqlite_schema;
┌───────────────────────────────────┐
│ sql │
├───────────────────────────────────┤
│ CREATE TABLE `t t` (`b b`) │
├───────────────────────────────────┤
│ CREATE INDEX idx ON `t t` (`a a`) │
├───────────────────────────────────┤
```
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>
Closes#3322
In e.g. `SELECT x AS y, y AS x FROM t ORDER BY x;`, the `x` in the
`ORDER BY` should reference t.y, which has been aliased as `x` for this
query. The same goes for GROUP BY, JOIN ON etc. but NOT for WHERE.
Previously we had wrong precedence in `bind_and_rewrite_expr`.
fixes#3231
```zsh
❯ sqlite3
SQLite version 3.50.4 2025-07-30 19:33:53
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> CREATE TABLE t1 (a);
ALTER TABLE t1 ADD COLUMN a;
Parse error: duplicate column name: a
sqlite> ALTER TABLE t1 ADD COLUMN name varchar(255);
SELECT sql FROM sqlite_schema WHERE name = 't1';
CREATE TABLE t1 (a, name varchar(255))
sqlite>
```
```zsh
turso>
turso> CREATE TABLE t1 (a);
ALTER TABLE t1 ADD COLUMN a;
x Parse error: duplicate column name: a
turso> ALTER TABLE t1 ADD COLUMN name varchar(255);
SELECT sql FROM sqlite_schema WHERE name = 't1';
┌─────────────────────────────────────────┐
│ sql │
├─────────────────────────────────────────┤
│ CREATE TABLE t1 (a, name varchar (255)) │
└─────────────────────────────────────────┘
turso>
```
Reviewed-by: Pere Diaz Bou <pere-altea@homail.com>
Closes#3249
This PR implements the `Sequence` and `SequenceTest` opcodes, although
does not yet add plumbing to emit the latter.
SQLite has two distinct mechanisms that determine the final row order
with aggregates:
Traversal order of GROUP BY, and ORDER BY tiebreaking. When ORDER BY
contains only aggregate expressions and/or constants, SQLite has no
extra tiebreak key, but when ORDER BY mixes aggregate and non-aggregate
terms, SQLite adds an implicit, stable row `sequence` so “ties” respect
the input order.
This PR also fixes an issue with a query like the following:
```sql
SELECT u.first_name, COUNT(*) AS c
FROM users u
JOIN orders o ON o.user_id = u.id
GROUP BY u.first_name
ORDER BY c DESC;
```
Because ORDER BY has only an aggregate (COUNT(*) DESC) and no non-
aggregate terms, SQLite traverses the group key (u.first_name) in DESC
order in this case, so ties on c naturally appear with group keys in
descending order.
Previously tursodb would return the group key sorted in ASC order,
because it was used in all cases as the default
Closes#3287