Giter Club home page Giter Club logo

Comments (7)

jgallagher avatar jgallagher commented on June 4, 2024

I'm not sure that's actually possible, in general. SQLite's C API doesn't provide the equivalent of a "clone connection". To share an in-memory database, you have to open using a URI filename and enabled shared caching. We should definitely allow that, and I don't think we provide all the hooks necessary at the moment.

To the more general question of implementing Clone - the only way I can think to do it would be to save off the path that a connection was opened with and attempt to open it again. That won't let us impl clone though, since it might fail, or worse, it might succeed but not actually be a second connection to the same database.

Another possibility is to add a second connection type that implements Sync which performs the open in Serialized mode.

from rusqlite.

marcusklaas avatar marcusklaas commented on June 4, 2024

Ah, I was afraid this was the case. Too bad, but I completely understand the reasoning.

Could you elaborate a bit on the second option? I don't see how Serialized mode and the Sync trait are related, as Sync allows threads to share a single connection and serialized mode makes concurrent connections play nice together.

from rusqlite.

jgallagher avatar jgallagher commented on June 4, 2024

Multi-thread mode (the second item on SQLite's threadsafety page) allows SQLite to be used from multiple threads as long as each thread uses its own connection. This is the level of multithreading that rusqlite currently assumes. The default threading mode (Serialized) allows a single connection to be shared and used from multiple threads simultaneously; this was added in SQLite 3.5 way back in 2007 - see the 3.5 Changelog, section 4.0.

Currently rusqlite doesn't really do anything special, and may even be unintentionally unsafe (e.g., if SQLite was compiled for single-threaded use only, rusqlite should not be used from multiple threads either.) I'm not sure what the right level of support / detail to provide is. Some options:

  • Stick with the interface rusqlite currently has, which restricts connections to Send. We should perhaps add a check that the SQLite we link against wasn't compiled in single-threaded mode, although I could see an argument for not even doing that (if someone wants to use rusqlite with a single-threaded SQLite, that seems reasonable, but I don't know how to enforce the "you can't use rusqlite from multiple threads at all even with different connections" in Rust).
  • Provide different Rust connection handles for each of the three different SQLite threading modes. I don't think I want to do this, because it doesn't play nicely with people passing their own arguments to open (since open arguments can change the threading mode for that connection).

It is unfortunate that rusqlite may be more restrictive than SQLite, though, since in many cases the connection could be Sync. Nontrivial changes on the Rust side would be necessary to support this (SqliteConnection currently uses a RefCell, for example), and some operations would become inherently racy (like last_insert_rowid()).

What do you think?

from rusqlite.

dashed avatar dashed commented on June 4, 2024

@jgallagher would it be better to share the same connection through something like Arc<RwLock<T>>?

EDIT as of Dec 17, 2015: suggestion won't work b/c of missing Sync trait

from rusqlite.

jgallagher avatar jgallagher commented on June 4, 2024

You shouldn't be able to put a connection into an RwLock and have it be usable from multiple threads because the connections don't implement Sync. This will (correctly) fail to compile:

    let locked = Arc::new(RwLock::new(SqliteConnection::open("foo.db").unwrap()));
    thread::spawn(move || {
        let db = locked.lock().unwrap();
        // do something with db
    });

Since Rust provides this kind of threading guarantee, our default flags for opening connections includes the SQLITE_OPEN_NOMUTEX flag, which puts SQLite into multi-thread mode:

In this mode, SQLite can be safely used by multiple threads provided that no single database connection is used simultaneously in two or more threads.

We could always open SQLite in serialized mode and then impl Sync for the connection, allowing it to be shared across threads, but that seems not ideal because we're forcing everyone to use SQLite's internal locking, even if they don't use the connection across multiple threads.

If you must share the same connection object, you can put it into an Arc<Mutex<_>> (which obviously will only allow one thread at a time to do anything). A better solution is probably just to open multiple connections to the same database for each thread.

from rusqlite.

jgallagher avatar jgallagher commented on June 4, 2024

I'm going to go ahead and close this since the original issue (implementing Clone for connections) isn't possible. If there are other threading issues, please open them!

from rusqlite.

dashed avatar dashed commented on June 4, 2024

@jgallagher ah yeah, I was learning the ropes of rust when I made the suggestion at https://github.com/jgallagher/rusqlite/issues/28#issuecomment-151867432. You pretty much described why it wouldn't work when I attempted it. I've edited my comment for any future github issue lurkers.

from rusqlite.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.