Skip to content

Commit e3b8cf7

Browse files
authored
Merge branch 'main' into ptrmap-data-corruption
2 parents 9639769 + 72edc6d commit e3b8cf7

File tree

29 files changed

+520
-202
lines changed

29 files changed

+520
-202
lines changed

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
<p align="center">
1111
<a title="Build Status" target="_blank" href="https://github.com/tursodatabase/turso/actions/workflows/rust.yml"><img src="https://img.shields.io/github/actions/workflow/status/tursodatabase/turso/rust.yml?style=flat-square"></a>
1212
<a title="Releases" target="_blank" href="https://github.com/tursodatabase/turso/releases"><img src="https://img.shields.io/github/release/tursodatabase/turso?style=flat-square&color=9CF"></a>
13-
<a title="Rust" target="_blank" href="https://crates.io/crates/turso"><img alt="PyPI" src="https://img.shields.io/crates/v/turso"></a>
14-
<a title="JavaScript" target="_blank" href="https://www.npmjs.com/package/@tursodatabase/database"><img alt="PyPI" src="https://img.shields.io/npm/v/@tursodatabase/database"></a>
13+
<a title="Rust" target="_blank" href="https://crates.io/crates/turso"><img alt="Crate" src="https://img.shields.io/crates/v/turso"></a>
14+
<a title="JavaScript" target="_blank" href="https://www.npmjs.com/package/@tursodatabase/database"><img alt="NPM" src="https://img.shields.io/npm/v/@tursodatabase/database"></a>
1515
<a title="Python" target="_blank" href="https://pypi.org/project/pyturso/"><img alt="PyPI" src="https://img.shields.io/pypi/v/pyturso"></a>
16+
<a title="Java" target="_blank" href="https://central.sonatype.com/artifact/tech.turso/turso"><img alt="Maven Central" src="https://img.shields.io/maven-central/v/tech.turso/turso"></a>
1617
<a title="MIT" target="_blank" href="https://github.com/tursodatabase/turso/blob/main/LICENSE.md"><img src="http://img.shields.io/badge/license-MIT-orange.svg?style=flat-square"></a>
1718
<br>
1819
<a title="GitHub Pull Requests" target="_blank" href="https://github.com/tursodatabase/turso/pulls"><img src="https://img.shields.io/github/issues-pr-closed/tursodatabase/turso.svg?style=flat-square&color=FF9966"></a>
@@ -398,12 +399,14 @@ Even during Alpha, if you find a bug that leads to a data corruption and demonst
398399
how our simulator failed to catch it, you can get up to $1,000.00. As the project matures we will
399400
increase the size of the prize, and the scope of the bugs.
400401

401-
More details [here](https://turso.algora.io).
402+
List of rewarded cases:
402403

403-
You can see an example of an awarded case on [#2049](https://github.com/tursodatabase/turso/issues/2049).
404+
* B-Tree interior cell replacement issue in btrees with depth >=3 ([#2106](https://github.com/tursodatabase/turso/issues/2106))
405+
* Don't allow autovacuum to be flipped on non-empty databases ([#3830](https://github.com/tursodatabase/turso/pull/3830))
404406

405-
Turso core staff are not eligible.
407+
More details [here](https://turso.algora.io).
406408

409+
Turso core staff are not eligible.
407410

408411
## FAQ
409412

bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,47 @@ public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQ
189189

190190
@Override
191191
public void setObject(int parameterIndex, Object x) throws SQLException {
192-
// TODO
192+
requireNonNull(this.statement);
193+
if (x == null) {
194+
this.statement.bindNull(parameterIndex);
195+
return;
196+
}
197+
if (x instanceof String) {
198+
setString(parameterIndex, (String) x);
199+
} else if (x instanceof Integer) {
200+
setInt(parameterIndex, (Integer) x);
201+
} else if (x instanceof Long) {
202+
setLong(parameterIndex, (Long) x);
203+
} else if (x instanceof Boolean) {
204+
setBoolean(parameterIndex, (Boolean) x);
205+
} else if (x instanceof Double) {
206+
setDouble(parameterIndex, (Double) x);
207+
} else if (x instanceof Float) {
208+
setFloat(parameterIndex, (Float) x);
209+
} else if (x instanceof Byte) {
210+
setByte(parameterIndex, (Byte) x);
211+
} else if (x instanceof Short) {
212+
setShort(parameterIndex, (Short) x);
213+
} else if (x instanceof byte[]) {
214+
setBytes(parameterIndex, (byte[]) x);
215+
} else if (x instanceof Timestamp) {
216+
setTimestamp(parameterIndex, (Timestamp) x);
217+
} else if (x instanceof Date) {
218+
setDate(parameterIndex, (Date) x);
219+
} else if (x instanceof Time) {
220+
setTime(parameterIndex, (Time) x);
221+
} else if (x instanceof BigDecimal) {
222+
setBigDecimal(parameterIndex, (BigDecimal) x);
223+
} else if (x instanceof Blob
224+
|| x instanceof Clob
225+
|| x instanceof InputStream
226+
|| x instanceof Reader) {
227+
throw new SQLException(
228+
"setObject does not yet support LOB or Stream types because the corresponding set methods are unimplemented. Type found: "
229+
+ x.getClass().getName());
230+
} else {
231+
throw new SQLException("Unsupported object type in setObject: " + x.getClass().getName());
232+
}
193233
}
194234

195235
@Override

bindings/java/src/test/java/tech/turso/jdbc4/JDBC4PreparedStatementTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,56 @@ void testInsertMultipleTypes() throws SQLException {
338338
assertArrayEquals(new byte[] {4, 5, 6}, rs.getBytes(4));
339339
}
340340

341+
@Test
342+
void testSetObjectCoversAllSupportedTypes() throws SQLException {
343+
connection
344+
.prepareStatement(
345+
"CREATE TABLE test ("
346+
+ "col1 INTEGER, "
347+
+ "col2 REAL, "
348+
+ "col3 TEXT, "
349+
+ "col4 BLOB, "
350+
+ "col5 INTEGER, "
351+
+ "col6 TEXT, "
352+
+ "col7 TEXT, "
353+
+ "col8 TEXT, "
354+
+ "col9 TEXT"
355+
+ ")")
356+
.execute();
357+
358+
PreparedStatement stmt =
359+
connection.prepareStatement("INSERT INTO test VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
360+
361+
stmt.setObject(1, 42);
362+
stmt.setObject(2, 3.141592d);
363+
stmt.setObject(3, "string_value");
364+
stmt.setObject(4, new byte[] {1, 2, 3});
365+
stmt.setObject(5, 1L);
366+
stmt.setObject(6, java.sql.Date.valueOf("2025-10-30"));
367+
stmt.setObject(7, java.sql.Time.valueOf("10:45:00"));
368+
stmt.setObject(8, java.sql.Timestamp.valueOf("2025-10-30 10:45:00"));
369+
stmt.setObject(9, new java.math.BigDecimal("12345.6789"));
370+
371+
stmt.execute();
372+
373+
PreparedStatement stmt2 = connection.prepareStatement("SELECT * FROM test;");
374+
ResultSet rs = stmt2.executeQuery();
375+
376+
assertTrue(rs.next());
377+
assertEquals(42, rs.getInt(1));
378+
assertEquals(3.141592d, rs.getDouble(2), 0.000001);
379+
assertEquals("string_value", rs.getString(3));
380+
assertArrayEquals(new byte[] {1, 2, 3}, rs.getBytes(4));
381+
assertTrue(rs.getBoolean(5));
382+
assertEquals(java.sql.Date.valueOf("2025-10-30"), rs.getDate(6));
383+
assertEquals(java.sql.Time.valueOf("10:45:00"), rs.getTime(7));
384+
assertEquals(java.sql.Timestamp.valueOf("2025-10-30 10:45:00"), rs.getTimestamp(8));
385+
String decimalText = rs.getString(9);
386+
assertEquals(
387+
new java.math.BigDecimal("12345.6789").stripTrailingZeros(),
388+
new java.math.BigDecimal(decimalText).stripTrailingZeros());
389+
}
390+
341391
@Test
342392
void execute_insert_should_return_number_of_inserted_elements() throws Exception {
343393
connection.prepareStatement("CREATE TABLE test (col INTEGER)").execute();

bindings/python/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::cell::RefCell;
66
use std::num::NonZeroUsize;
77
use std::rc::Rc;
88
use std::sync::Arc;
9-
use turso_core::Value;
9+
use turso_core::{DatabaseOpts, Value};
1010

1111
mod errors;
1212

@@ -317,7 +317,7 @@ impl Drop for Connection {
317317
#[allow(clippy::arc_with_non_send_sync)]
318318
#[pyfunction(signature = (path))]
319319
pub fn connect(path: &str) -> Result<Connection> {
320-
match turso_core::Connection::from_uri(path, true, false, false, false, false, false) {
320+
match turso_core::Connection::from_uri(path, DatabaseOpts::default()) {
321321
Ok((io, conn)) => Ok(Connection { conn, _io: io }),
322322
Err(e) => Err(PyErr::new::<ProgrammingError, _>(format!(
323323
"Failed to create connection: {e:?}"

bindings/rust/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,19 @@ repository.workspace = true
1010
description = "Turso Rust API"
1111

1212
[features]
13-
default = ["experimental_indexes"]
13+
default = ["experimental_indexes", "mimalloc"]
1414
conn_raw_api = ["turso_core/conn_raw_api"]
1515
experimental_indexes = []
1616
antithesis = ["turso_core/antithesis"]
1717
tracing_release = ["turso_core/tracing_release"]
18+
mimalloc = ["dep:mimalloc"]
1819

1920
[dependencies]
2021
turso_core = { workspace = true, features = ["io_uring"] }
2122
thiserror = { workspace = true }
2223
tracing-subscriber.workspace = true
2324
tracing.workspace = true
24-
mimalloc = { workspace = true }
25+
mimalloc = { workspace = true, optional = true }
2526

2627
[dev-dependencies]
2728
tempfile = { workspace = true }

bindings/rust/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
//! # }
3333
//! ```
3434
35-
#[cfg(all(not(target_family = "wasm"), not(miri)))]
35+
#[cfg(all(feature = "mimalloc", not(target_family = "wasm"), not(miri)))]
3636
#[global_allocator]
3737
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
3838

cli/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,13 @@ serde_json = "1.0"
4949
termimad = "0.30"
5050
include_dir = "0.7"
5151
rand = "0.8"
52-
mimalloc = { workspace = true }
52+
mimalloc = { workspace = true, optional = true }
5353

5454
[features]
55-
default = ["io_uring"]
55+
default = ["io_uring", "mimalloc"]
5656
io_uring = ["turso_core/io_uring"]
5757
tracing_release = ["turso_core/tracing_release"]
58+
mimalloc = ["dep:mimalloc"]
5859

5960
[build-dependencies]
6061
syntect = { git = "https://github.com/trishume/syntect.git", rev = "64644ffe064457265cbcee12a0c1baf9485ba6ee" }

cli/app.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ use std::{
3232
use tracing_appender::non_blocking::WorkerGuard;
3333
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
3434
use turso_core::{
35-
Connection, Database, LimboError, OpenFlags, QueryMode, Statement, StepResult, Value,
35+
Connection, Database, DatabaseOpts, LimboError, OpenFlags, QueryMode, Statement, StepResult,
36+
Value,
3637
};
3738

3839
#[derive(Parser, Debug)]
@@ -80,6 +81,8 @@ pub struct Opts {
8081
pub experimental_encryption: bool,
8182
#[clap(long, help = "Enable experimental index method feature")]
8283
pub experimental_index_method: bool,
84+
#[clap(long, help = "Enable experimental autovacuum feature")]
85+
pub experimental_autovacuum: bool,
8386
}
8487

8588
const PROMPT: &str = "turso> ";
@@ -186,15 +189,17 @@ impl Limbo {
186189
.as_ref()
187190
.map_or(":memory:".to_string(), |p| p.to_string_lossy().to_string());
188191
let indexes_enabled = opts.experimental_indexes.unwrap_or(true);
192+
189193
let (io, conn) = if db_file.contains([':', '?', '&', '#']) {
190194
Connection::from_uri(
191195
&db_file,
192-
indexes_enabled,
193-
opts.experimental_mvcc,
194-
opts.experimental_views,
195-
opts.experimental_strict,
196-
opts.experimental_encryption,
197-
opts.experimental_index_method,
196+
DatabaseOpts::new()
197+
.with_indexes(indexes_enabled)
198+
.with_mvcc(opts.experimental_mvcc)
199+
.with_views(opts.experimental_views)
200+
.with_strict(opts.experimental_strict)
201+
.with_encryption(opts.experimental_encryption)
202+
.with_index_method(opts.experimental_index_method),
198203
)?
199204
} else {
200205
let flags = if opts.readonly {
@@ -213,6 +218,7 @@ impl Limbo {
213218
.with_strict(opts.experimental_strict)
214219
.with_encryption(opts.experimental_encryption)
215220
.with_index_method(opts.experimental_index_method)
221+
.with_autovacuum(opts.experimental_autovacuum)
216222
.turso_cli(),
217223
None,
218224
)?;

cli/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::{
1616
sync::{atomic::Ordering, LazyLock},
1717
};
1818

19-
#[cfg(all(not(target_family = "wasm"), not(miri)))]
19+
#[cfg(all(feature = "mimalloc", not(target_family = "wasm"), not(miri)))]
2020
#[global_allocator]
2121
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
2222

cli/mcp_server.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ impl TursoMcpServer {
408408

409409
// Open the new database connection
410410
let conn = if path == ":memory:" || path.contains([':', '?', '&', '#']) {
411-
match Connection::from_uri(&path, true, false, false, false, false, false) {
411+
match Connection::from_uri(&path, DatabaseOpts::default()) {
412412
Ok((_io, c)) => c,
413413
Err(e) => return format!("Failed to open database '{path}': {e}"),
414414
}
@@ -417,7 +417,9 @@ impl TursoMcpServer {
417417
&path,
418418
None::<&str>,
419419
OpenFlags::default(),
420-
DatabaseOpts::new().with_indexes(true),
420+
DatabaseOpts::new()
421+
.with_indexes(true)
422+
.with_autovacuum(false),
421423
None,
422424
) {
423425
Ok((_io, db)) => match db.connect() {

0 commit comments

Comments
 (0)