Commit Graph

10697 Commits

Author SHA1 Message Date
joao.faria
2ba643cd68 fix: prevent DROP TABLE when table is referenced by foreign keys
Add foreign key constraint check in translate_drop_table to reject
dropping tables that are referenced by foreign keys when
PRAGMA foreign_keys=ON
2025-11-04 12:32:19 -03:00
Pekka Enberg
2c49c47300 Merge 'add some docs for index method' from Nikita Sivukhin
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>

Closes #3909
2025-11-03 15:53:36 +02:00
Nikita Sivukhin
94a39cef3a add some docs for index method 2025-11-03 16:40:18 +04:00
Pekka Enberg
2bf5eb84cf Merge 'Prevent misuse of subqueries that return multiple columns' from Jussi Saurio
Closes #3892
Closes #3888
Stuff like:
```sql
turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (1);
    insert into t2 values (1, 2);
    select case (select y, z from t2) when 1 then 'one' else 'other' end from t1;
  × Parse error: base expression in CASE must return 1 value

turso>     create table t(x, y);
    insert into t values (1, 2);
    select (select x, y from t) as result;
  × Parse error: result column must return 1 value, got 2

turso>     create table t1(x,y);
    create table t2(y);
    insert into t1 values (1,1);
    insert into t2 values (1);
    select * from t2 where y = (select x,y from t1);
  × Parse error: all arguments to binary operator = must return the same number of
  │ values. Got: (1) = (2)

turso>     create table orders(customer_id, amount);
    create table thresholds(min_amount, max_amount);
    insert into orders values (100, 50), (100, 150);
    insert into thresholds values (100, 200);
    select customer_id, sum(amount) as total 
    from orders 
    group by customer_id 
    having total > (select min_amount, max_amount from thresholds);
  × Parse error: all arguments to binary operator > must return the same number of
  │ values. Got: (1) > (2)

turso>     create table items(id);
    create table config(max_results, other_col);
    insert into items values (1), (2), (3);
    insert into config values (2, 3);
    select * from items limit (select max_results, other_col from config);
  × Parse error: limit expression must return 1 value, got 2

turso>     create table items(id);
    create table config(skip_count, other_col);
    insert into items values (1), (2), (3);
    insert into config values (1, 2);
    select * from items limit 1 offset (select skip_count, other_col from config);
  × Parse error: offset expression must return 1 value, got 2

turso>     create table items(id, name);
    create table sort_order(priority, other_col);
    insert into items values (1, 'a'), (2, 'b');
    insert into sort_order values (1, 2);
    select * from items order by (select priority, other_col from sort_order);
  × Parse error: order by expression must return 1 value, got 2

turso>     create table sales(product_id, amount);
    create table grouping(category, other_col);
    insert into sales values (1, 100), (2, 200);
    insert into grouping values (1, 2);
    select sum(amount) from sales group by (select category, other_col from grouping);
  × Parse error: group by expression must return 1 value, got 2

turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (1);
    insert into t2 values (1, 2);
    select case when (select y, z from t2) then 'yes' else 'no' end from t1;
  × Parse error: when expression in CASE must return 1 value. Got: (2)

turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (1);
    insert into t2 values (1, 2);
    select case when x = 1 then (select y, z from t2) else 0 end from t1;
  × Parse error: then expression in CASE must return 1 value. Got: (2)

turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (1);
    insert into t2 values (1, 2);
    select case when x = 2 then 0 else (select y, z from t2) end from t1;
  × Parse error: else expression in CASE must return 1 value. Got: (2)

turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (1);
    insert into t2 values (1, 2);
    select max((select y, z from t2)) from t1;
  × Parse error: argument 0 to function call max must return 1 value. Got: (2)

turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (1);
    insert into t2 values (1, 2);
    select x + (select y, z from t2) from t1;
  × Parse error: all arguments to binary operator + must return the same number of
  │ values. Got: (1) + (2)

turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (5);
    insert into t2 values (1, 2);
    select * from t1 where x between (select y, z from t2) and 10;
  × Parse error: all arguments to binary operator <= must return the same number of
  │ values. Got: (2) <= (1)

turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (1);
    insert into t2 values (1, 2);
    select cast((select y, z from t2) as integer) from t1;
  × Parse error: argument to CAST must return 1 value. Got: (2)

turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (1);
    insert into t2 values ('a', 'b');
    select (select y, z from t2) collate nocase from t1;
  × Parse error: argument to COLLATE must return 1 value. Got: (2)

turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (1);
    insert into t2 values (1, 2);
    select * from t1 where (select y, z from t2) is null;
  × Parse error: all arguments to binary operator IS must return the same number of
  │ values. Got: (2) IS (1)

turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (1);
    insert into t2 values (1, 2);
    select * from t1 where (select y, z from t2) not null;
  × Parse error: argument to NOT NULL must return 1 value. Got: (2)

turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (1);
    insert into t2 values ('a', 'b');
    select * from t1 where (select y, z from t2) like 'a%';
  × Parse error: left operand of LIKE must return 1 value. Got: (2)

turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (1);
    insert into t2 values (1, 2);
    select -(select y, z from t2) from t1;
  × Parse error: argument to unary operator - must return 1 value. Got: (2)

turso>     create table t1(x);
    create table t2(y, z);
    insert into t1 values (1);
    insert into t2 values (1, 2);
    select abs((select y, z from t2)) from t1;
  × Parse error: argument 0 to function call abs must return 1 value. Got: (2)
  ```

Closes #3906
2025-11-03 13:06:38 +02:00
Pekka Enberg
9aae220509 Merge 'Optimize and refactor schema::Column type' from Preston Thorpe
closes https://github.com/tursodatabase/turso/issues/3773
## Before
```rust
#[derive(Debug, Clone)]
pub struct Column {
    pub name: Option<String>,
    pub ty: Type,
    // many sqlite operations like table_info retain the original string
    pub ty_str: String,
    pub primary_key: bool,
    pub is_rowid_alias: bool,
    pub notnull: bool,
    pub default: Option<Box<Expr>>,
    pub unique: bool,
    pub collation: Option<CollationSeq>,
    pub hidden: bool,
}
```
obviously not ideal. so lets pack `type`, `hidden`, `primary_key`,
`is_rowid_alias`, `notnull` and `collation` into a u16.
## After:
```rust
#[derive(Debug, Clone)]
pub struct Column {
    pub name: Option<String>,
    pub ty_str: String,
    pub default: Option<Box<Expr>>,
    raw: u16,
}
```
Also saw a place to replace a `Mutex<Enum>` with `AtomicEnum`, so I
snuck that in here too

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

Closes #3905
2025-11-03 13:05:35 +02:00
Pekka Enberg
b4efb8bbab Merge 'Fix error handling on provided insert column count mismatch' from Jussi Saurio
Closes #3875

Closes #3907
2025-11-03 13:05:08 +02:00
Jussi Saurio
1c2a8e62ca Fix: return error on provided insert column count mismatch 2025-11-03 11:41:50 +02:00
Jussi Saurio
005d922ab4 Fix: prevent misuse of subqueries that return multiple columns 2025-11-03 11:04:09 +02:00
PThorpe92
481d86f567 Optimize and refactor schema::Column type 2025-11-02 20:46:02 -05:00
Pekka Enberg
72edc6d758 Merge 'Clean up Connection::from_uri() by using DatabaseOpts' from Rohith Suresh
Fixes #3900
Migrating the `from_uri` function to use `DatabaseOpts`

Reviewed-by: Preston Thorpe <preston@turso.tech>

Closes #3901
2025-11-02 16:55:44 +02:00
Pekka Enberg
d35b55d0a4 Merge 'Select correct collation sequence for compound select' from Pedro Muniz
Fixes #3673
We were only considering the right `SelectPlan` for determining the
collation sequence when creating the `EphemeralIndex` for
`CompoundSelect` statements. Now, we pass both the left and the right
plans, and correctly select the collation sequence prioritizing the left
plan collation.

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

Closes #3851
2025-11-02 16:54:58 +02:00
pedrocarlo
0eb0fc5c22 add tests 2025-11-02 11:27:05 -03:00
pedrocarlo
28c52cdf09 pass the left select in compound select to correctly choose the collation sequence 2025-11-02 11:26:48 -03:00
RS2007
60cbc6d8ea migrating from_uri to database opts 2025-11-02 16:28:22 +05:30
Pekka Enberg
a733007228 Merge 'core: Disable autovacuum by default' from Pekka Enberg
People have discovered various bugs in autovacuum so let's disable it by
default for now.

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

Closes #3899
2025-11-02 12:29:03 +02:00
Pekka Enberg
913b7ac600 core: Disable autovacuum by default
People have discovered various bugs in autovacuum so let's disable it by
default for now.
2025-11-02 12:09:21 +02:00
Pekka Enberg
e2271a3ef8 Update README with bug reward cases
Added a list of rewarded cases for bug reports.
2025-11-02 10:46:54 +02:00
Pekka Enberg
a87323855b Merge 'core/vdbe: Fix incorrect unreachable condition in op_seek_rowid' from Preston Thorpe
closes https://github.com/tursodatabase/turso-go/issues/55
In `apply_affinity_char`: we have things like the following:
```rust
    if matches!(value, Value::Blob(_)) {
        return true;
    }
````
Then at the call site in `op_seek_rowid` in execute.rs, we were saying
it was an unreachable condition that a blob was in the register..
```rust
                        let converted = apply_affinity_char(&mut temp_reg, Affinity::Numeric);
                        if converted {
                            match temp_reg.get_value() {
                                Value::Integer(i) => Some(*i),
                                Value::Float(f) => Some(*f as i64),
                                _ => unreachable!(),
                            }
```

Closes #3897
2025-11-02 10:00:10 +02:00
PThorpe92
23496f0bea Fix incorrect unreachable precondition for affinity char in op_seek_rowid 2025-11-01 20:43:44 -04:00
Pekka Enberg
6128ef0afc Merge 'Make mimalloc dependency optional' from Pekka Enberg
Closes #3881
2025-11-01 12:00:08 +02:00
Pekka Enberg
0217588d13 Make mimalloc dependency optional 2025-11-01 11:43:32 +02:00
Pekka Enberg
9336f1c213 Merge 'Update and fix nix build' from Alexander Hirner
This makes `nix build .#turso_cli` succeed.
#835 argueed to remove nix packaging from the repo. I agree and hope
that a talented maintainer will include `turso_cli` in nixpkgs.
Given the currently broken state and the recent Beta release, maybe it's
worth to unbreak it for some last time.

Closes #3879
2025-11-01 11:13:19 +02:00
Pekka Enberg
c091f94de8 Merge 'Fix INSERT UNION ALL' from Duy Dang
Close #3849
Close #3855

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

Closes #3877
2025-11-01 11:12:38 +02:00
Pekka Enberg
7283f35a29 Merge 'Fix LEFT JOIN subqueries reusing stale right-side values' from Duy Dang
Close #3867

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

Closes #3874
2025-11-01 11:12:24 +02:00
Pekka Enberg
74d1652a60 Merge 'Throw an error in case duplicate CTE names are found' from Rohith Suresh
* Fixes bug #3674
* With this fix:
```
turso>  WITH t AS (SELECT 1), t AS (SELECT 2) SELECT * FROM x;
  × Parse error: duplicate WITH table name: t
```

Reviewed-by: Preston Thorpe <preston@turso.tech>
Reviewed-by: Mikaël Francoeur (@LeMikaelF)

Closes #3719
2025-11-01 11:12:10 +02:00
ahirner
ef1f359ffc package rename from turso to limbo 2025-11-01 07:16:32 +01:00
ahirner
5d1b8252b4 flake update to nixpkgs ca. 2025-10-12 2025-11-01 07:13:44 +01:00
Duy Dang
e0f6b7cffe Fix INSERT handling for compound VALUES sources 2025-11-01 02:27:42 +07:00
Duy Dang
4b18e3bab5 Fix VALUES UNION ALL register reuse during INSERTs 2025-11-01 02:01:30 +07:00
Duy Dang
3ee47a2c3c Fix LEFT JOIN subqueries reusing stale right-side values 2025-11-01 01:24:31 +07:00
RS2007
bdf720d205 adding regression test for duplicate cte 2025-10-31 23:15:11 +05:30
RS2007
7fff8daaa5 Fixing clippy error 2025-10-31 23:14:08 +05:30
RS2007
1f576593ec adding duplicate cte name checks in planner.rs 2025-10-31 23:14:08 +05:30
Pekka Enberg
41aa49c7b5 Merge 'Fix self-insert SUM when table uses INTEGER PRIMARY KEY' from Duy Dang
Close #3868

Closes #3870
2025-10-31 17:01:22 +02:00
Pekka Enberg
cdd9ec3438 Merge 'bindings/java: Implement setObject(int, Object) in JDBC4PreparedStatement' from Orange banana
## Purpose
* Implement `setObject(int, Object)` to support binding of common Java
types to SQL parameters in JDBC4.
* This implementation currently covers only standard JDBC4 supported
types. LOB and stream bindings are not yet implemented.
## Changes
* Implemented JDBC4PreparedStatement#setObject(int, Object) handling for
  * `String`, `Integer`, `Long`, `Boolean`, `Double`, `Float`, `Byte`,
`Short`
  * `byte[]`, `Date`, `Time`, `Timestamp`, `BigDecimal`
* Added validation for unsupported types (`Blob`, `Clob`, `InputStream`,
`Reader`)
* Added corresponding unit test `testSetObjectCoversAllSupportedTypes`
to verify correctness
## Note
* Additional work (e.g., LOB/Stream handling) will be addressed
separately once driver support is available.
## Related Issue
#615

Reviewed-by: Kim Seon Woo (@seonWKim)

Closes #3864
2025-10-31 17:00:31 +02:00
Pekka Enberg
11f95253a4 Merge 'Update Java package version in scripts/update-version.py' from Pekka Enberg
Closes #3873
2025-10-31 15:59:46 +02:00
Pekka Enberg
8ae49b0dad Add Java badge to README.md 2025-10-31 13:57:33 +02:00
Pekka Enberg
8ee5b5621e Update Java package version in scripts/update-version.py 2025-10-31 13:43:45 +02:00
Orange flavored banana
5fef79d9f6 feat(jdbc): remove unnecessary java.sql prefixes in setObject 2025-10-31 10:38:30 +09:00
Duy Dang
733dc762ed Fix self-insert SUM when table uses INTEGER PRIMARY KEY 2025-10-31 03:34:10 +07:00
Pekka Enberg
331ba14e7c Turso 0.3.0 2025-10-30 18:16:12 +02:00
Pekka Enberg
a4d43d51d4 Update CHANGELOG.md 2025-10-30 18:15:59 +02:00
Pekka Enberg
c91b66ba38 Turso 0.3.0-pre.7 2025-10-30 18:15:14 +02:00
Pekka Enberg
128f2f1ca5 Merge 'Add 'make test-single'' from Jussi Saurio
e.g. `make test-single TEST=subquery.test`
Plus: chmod +x to all tcl tests in testing folder

Closes #3865
2025-10-30 14:19:46 +02:00
Pekka Enberg
43b5ea5363 Merge 'antithesis: Upload config image in GitHub Actions workflow' from Pekka Enberg
The Antithesis config image was not being uploaded during CI runs, only
the workload image. This caused experiment failures when the config
image expired from the registry after 6 months of inactivity.

Closes #3863
2025-10-30 12:57:42 +02:00
Jussi Saurio
7e65657ab0 Add 'make test-single'
e.g. `make test-single TEST=subquery.test`

Plus: chmod +x to all tcl tests in testing folder
2025-10-30 11:38:56 +02:00
Orange flavored banana
4cd007f2eb Test(jdbc): Add coverage for setObject(int, Object) 2025-10-30 15:35:31 +09:00
Pekka Enberg
d71a33a188 antithesis: Upload config image in GitHub Actions workflow
The Antithesis config image was not being uploaded during CI runs, only
the workload image. This caused experiment failures when the config
image expired from the registry after 6 months of inactivity.
2025-10-30 07:49:44 +02:00
Orange flavored banana
53ab453015 Feat(jdbc): Implement setObject(int, Object) in JDBC4PreparedStatement 2025-10-30 09:54:42 +09:00
Pekka Enberg
84a367b00e Merge 'Implement wasNull tracking in ResultSet getter methods' from 김민석
## Summary
Implemented comprehensive wasNull tracking and refactored getter methods
in JDBC4ResultSet to ensure JDBC specification compliance and improve
code maintainability.
### Changes
Added wasNull tracking to all getter methods: Covers primitive types,
objects, dates/times, streams, and BigDecimal
Refactored columnLabel getters to use delegation pattern: Eliminates
code duplication and ensures consistent wasNull behavior
### Bug Fixes & Code Quality
- Fixed getString(String) to return null instead of empty string for
null values
- Added @Nullable annotation to getBytes(String) to fix NullAway error
- Preserved String parsing in getDate(String) for TEXT-formatted dates
- Extracted timezone offset calculation to helper method
### Testing
Added comprehensive tests for wasNull tracking, columnLabel getters,
stream methods, and null handling

Closes #3838
2025-10-29 18:10:42 +02:00