Comments (16)
I think we need callr::r(function() ...)
:
path_db = tempfile()
con = DBI::dbConnect(RSQLite::SQLite(), path_db)
# break the connection/external pointers by saving
# to file system and restoring again
path = tempfile()
saveRDS(con, file = path)
con = readRDS(path)
# detection works in current session
DBI::dbIsValid(con)
#> [1] FALSE
# detection fails in remote session, RSQLite is not loaded
callr::r(function(con) DBI::dbIsValid(con), list(con = con))
#> Error: callr subprocess failed: unable to find an inherited method for function ‘dbIsValid’ for signature ‘"SQLiteConnection"’
# RSQLite is loaded on print
callr::r(function(con) { print(con); DBI::dbIsValid(con) }, list(con = con))
#> [1] FALSE
Created on 2020-04-14 by the reprex package (v0.3.0)
I'm not too familiar with S4. What do we need to do to fix this?
from dbi3.
Oh, I misread. I don't think you can send con
objects to other R sessions, the involved external pointers won't survive serialization.
from dbi3.
Oh, I misread. I don't think you can send
con
objects to other R sessions, the involved external pointers won't survive serialization.
Sure, but shouldn't dbIsValid()
return FALSE
if the external pointer is NULL (R_ExternalPtrAddr(s) == NULL
)?
from dbi3.
Yeah, I would have expected that deserialization of con
loads RSQLite, this doesn't seem to happen. This feels more like a callr issue though.
from dbi3.
I have come across this issue too (I run a check function prior to executing a SQL call), and I am wondering how you imagined it could be solved, I agree that it should return false in this instance.
from dbi3.
@life-droid Are you sure it's the same issue? Are you also running callr?
from dbi3.
@life-droid Are you sure it's the same issue? Are you also running callr?
Note that you have the same problem during parallelization, e.g. with socket clusters.
from dbi3.
So, every time a connection object is passed across process boundaries? Can we reprex this without using callr?
from dbi3.
@life-droid Are you sure it's the same issue? Are you also running callr?
Note that you have the same problem during parallelization, e.g. with socket clusters.
Sorry guys, I think my novice understanding of your issue is causing some confusion and I may be muddying the waters.
My issue is that if I had a connection to a DB, then reopen a project (or in the case I had at the time, rebuild a package) the object is still present with type "S4" but calling dbIsValid(dbo)
returns the error message mentioned rather than FALSE.
unable to find an inherited method for function ‘dbIsValid’ for signature ‘"missing"'
from dbi3.
@life-droid Are you sure it's the same issue? Are you also running callr?
Not sure, it was occuring after a package build, the connection to my dbo was broken and I want to add some error proofing so I use dbIsValid(dbo)
to determine if I need to run my function to connect to the dbo.
from dbi3.
Does "reopen a project" mean loading a saved session state? This seems equivalent to serializing. It should work if you load the RSQLite package first, I wonder why this is necessary.
from dbi3.
So, every time a connection object is passed across process boundaries? Can we reprex this without using callr?
path_db = tempfile()
con = DBI::dbConnect(RSQLite::SQLite(), path_db)
cl = parallel::makePSOCKcluster("localhost")
parallel::clusterApply(cl, con, DBI::dbIsValid)
from dbi3.
# library(RSQLite)
#
# con <- dbConnect(RSQLite::SQLite())
# string <- rawToChar(serialize(con, NULL, ascii = TRUE))
# dput(string)
string <- "A\n3\n262147\n197888\n5\nUTF-8\n66329\n1026\n1\n262153\n3\nptr\n22\n254\n254\n1026\n1\n262153\n6\ndbname\n16\n1\n262153\n0\n\n1026\n1\n262153\n19\nloadable.extensions\n10\n1\n1\n1026\n1\n262153\n5\nflags\n13\n1\n70\n1026\n1\n262153\n3\nvfs\n16\n1\n262153\n0\n\n1026\n1\n262153\n3\nref\n4\n0\n242\n254\n19\n29\n254\n254\n254\n254\n254\n254\n254\n254\n254\n254\n254\n254\n254\n254\n254\n254\n254\n254\n254\n1026\n1\n262153\n6\nresult\n254\n254\n254\n254\n254\n254\n254\n254\n254\n254\n254\n254\n1026\n1\n262153\n6\nbigint\n16\n1\n262153\n9\ninteger64\n1026\n1\n262153\n5\nclass\n528\n1\n262153\n16\nSQLiteConnection\n1026\n1\n262153\n7\npackage\n16\n1\n262153\n7\nRSQLite\n254\n254\n"
con <- unserialize(charToRaw(string))
DBI::dbIsValid(con)
#> Loading required package: RSQLite
#> Error in (function (classes, fdef, mtable) : unable to find an inherited method for function 'dbIsValid' for signature '"SQLiteConnection"'
requireNamespace("RSQLite")
DBI::dbIsValid(con)
#> [1] FALSE
Created on 2021-01-19 by the reprex package (v0.3.0)
from dbi3.
So, the workaround is to load the RSQLite package before attempting to call dbIsValid()
. Let's see if we can do more about this problem; it might be too much of an edge case though.
from dbi3.
Does "reopen a project" mean loading a saved session state? This seems equivalent to serializing. It should work if you load the RSQLite package first, I wonder why this is necessary.
Correct, if I have a project with a functioning connection when I check if it is valid I get the expected result:
> DBI::dbIsValid(m1)
[1] TRUE
Closing the project then reopening it (saving the workspace on close), the connection object is still visible but has a null pointer. When I run DBI::dbIsValid(m1)
in this state I get the following:
Error in (function (classes, fdef, mtable) :
unable to find an inherited method for function ‘dbIsValid’ for signature ‘"Microsoft SQL Server"’
from dbi3.
Let's consider serializable connections in a rewrite. (The connection object should know how to reconnect when the external pointer is missing.)
from dbi3.
Related Issues (20)
- Test for formals(dbXxx) ineffective
- Specify and test case-sensitivity for table names
- Name collision when creating tables
- Avoid hard-coded data types in queries HOT 1
- Support passing lists as arguments for queries like `SELECT a, b WHERE a IN ($1)` HOT 5
- Support arrays natively HOT 15
- Stronger guarantees for quoting literals
- Reading and writing tables with dots in name
- Rethink `immediate` argument
- Arrow/Flight SQL
- How to run tests on a user's database?
- Feature Request: Virtual connection HOT 2
- Add default dbWriteTable() method HOT 2
- Specify limits per connection or per driver
- How to create an external table in Hive? HOT 1
- Reconnection
- `dbQuoteIdentifier` should validate SQL inputs HOT 1
- Streaming multiple statements in a single dbExecute/dbQuery/etc. call HOT 1
- Default connection
- Optionally return tibbles
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dbi3.