-
Notifications
You must be signed in to change notification settings - Fork 87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Database connections are cached by name #115
Comments
The following test will work because it circumvents the caching of the database connections. const exec = (db, sql, dbnr) =>
new Promise((resolve, reject) =>
db._db.exec(
[
{
sql,
args: [],
},
],
false,
(e, result) => {
if (result[0].error) {
console.error({ dbnr, sql, e, result, row: result[0].rows });
reject(result)
} else {
console.log({ dbnr, sql, e, result, row: result[0].rows });
resolve(result);
}
}
)
);
const rnd = Math.random() // don't accidentally use a previous DB
const db1 = SQLite.openDatabase(`./test${rnd}.db`); // since the caching does not do path sanitisation, but the `stringByAppendingPathComponent` does, we can get around the caching with putting a second slash in the path
const db2 = SQLite.openDatabase(`.//test${rnd}.db`); // Removing second slash will fail the test on iOS, because then it uses the cached database transaction
await exec(
db1,
"CREATE TABLE IF NOT EXISTS schema_version(" +
"version_id INTEGER PRIMARY KEY NOT NULL);"
);
await exec(db1, "BEGIN;", 1);
await exec(db2, "BEGIN;", 2); // the native iOS SQLite does not allow two BEGINs on the same (cached) connection, whereas the shipped Android version will ignore it
await exec(db1, "SELECT * FROM schema_version;", 1);
await exec(db2, "SELECT * FROM schema_version;", 2);
await exec(db1, "COMMIT;", 1);
await exec(db2, "COMMIT;", 2); Removing one of the slashes in the path of |
The native module needs to open the database on every query:
So, it has to be cached in the native side by design. |
Couldn't one split up the function |
@craftzdog Fair enough, I have changed the issue title from "Database connections are cached" to "Database connections are cached by name" - To make it clear: Instead of being cached by name, they should be cached by connection identity. |
@craftzdog First of all thanks a lot for your work in this project! Should I create a MR for this suggestion? |
Please hold on. I'm working on restructuring the library now. |
It's ready for accepting your PR: #116 |
I thought a bit about it and it might be a breaking change if we change the API (e.g. if it is called many times). @craftzdog What do you think about having a |
I guess it wouldn't be a breaking change because you could issue an ID for each database connection instead of using database names for referring the connections. I don't understand why having a |
Thanks a lot for your feedback! You right, my explanation was very bad of what I had in mind and now I think that my suggestion of the hook is a bad idea. And I also completely agree with you that having a new API is generally bad, because the users would need to adapt it. My fears are that (theoretically) one could rely on the caching the same database connection with class MyComponent extends React.Component {
render() {
const db = openDatabase('my.db') // currently only opens one connection and then does the lookup in the cached Databases
// With the changed behaviour this would open a connection on every render
const onSave = () => {
// store to database
}
return <Something onSave={onSave}/>;
}
} Do you think that this is a realistic scenario? My (now probably discarded) thoughts about the const useDatabase = (name) => {
const db = React.useRef()
if (!db) {
db.current = openNewConnectionById(name) // the `openDatabase` without caching is only called once
}
return db.current
} but of course this would only work for functional components and also limits the usage there quite a lot. Everyone who needs it could implement it if the |
It is the native-side issue. |
It appears that both the IOS and Android implementation cache database connections, by name. This causes #109, but also surprises users who rely on working with more than one connection.
A tyical usecase for having multiple connections is to operate on the same database from different parts of the program that BEGIN and COMMIT their own (deferred) transactions. By operating on their own connections, they can rely on concurrent transactions being serialized by sqlite. WIth the connection caching implemented in this library, the cordova predecessor, and other libraries that copied from this one, the BEGIN and COMMIT statements will become interleaved and it results in unexpected errors such as "No transaction active."
It should be reconsidered whether this caching of connections is necessary, what problem it is supposed to solve, and if any, whether it should be enabled by default. At the very least, users should have an option to bypass it.
The text was updated successfully, but these errors were encountered: