-
Notifications
You must be signed in to change notification settings - Fork 714
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
Does not pass all PouchDB tests #255
Comments
Anybody who wants to help out on this: it is exceedingly easy to run the PouchDB test suite on your own machine, as described here. |
Quoted for reference here:
EDIT: you also have to start the CouchDB server on your localhost, as described at: https://github.com/pouchdb/pouchdb/blob/master/TESTING.md |
@nolanlawson I think it goes without saying that this should have been my task. Will take a look early next week. |
@brodybits No prob; I was going to look into it this weekend as well. :) BTW I updated the code snippet above; you no longer need a special branch, because pouchdb master is now cordova-friendly. |
FWIW, I just manually confirmed 100% tests passing for Cordova apps in:
I found the fastest way with Android is to use Genymotion, then (assuming CouchDB is installed) using the option:
(This was just a sanity check to make sure that the problem wasn't with PouchDB itself.) |
Do you mean that you tested with my plugin, or something else? Also how are you running the tests with Firefox OS, which this plugin does not (yet) support? |
Ah sorry for the confusion, I meant I was testing without the plugin. :) Just a sanity check to make sure that the failures were really due to this plugin. And yeah, I don't blame ya for not supporting FirefoxOS, given that they didn't make it possible. ;) |
I remember something now, which I discovered from BUG #232. If tx.executeSql() calls the error handler: the plugin will continue only if the error handler returns |
Of course, the problem in #232 would be very easy to fix, but I try to follow a test-first approach (which may not always be the best thing). The workaround (as I said in #232) is for the SQL error handler to explicitly return Also, #226 uncovered another issue. If a transaction SQL error handler returns TRUE, no more SQL callbacks should be fired before aborting the transaction. Today is my sabbath and I am taking off now, I am happy to work on this tonight. What I am thinking is to first try to get the full test suite working in Travis/Circle CI, then fix #232 and perhaps #226. |
@nolanlawson am I correct that it possible for PouchDB to store binary data using this plugin without using Base64? I need this answer for the discussion in #260. |
PouchDB stores binary strings in WebSQL/this plugin, not base64-encoded strings or Blobs. I actually added some tests to confirm the the behavior of this plugin matched WebSQL: 05ff6cc |
Okay, when I look at the test in the commit it says "unicode" and not "binary data". Do we simply infer that if a "Unicode" test is passing then we can expect a binary data test to pass? Actually, after reading your blog entries, I think we can consider "binary data" to be very similar to Unicode, in that when passing back and forth between Javascript and any data-storage library, we should be able to deal with a limited number of "trouble cases" and otherwise just store and retrieve it as a normal Javascript string. So my answer to the question above would be "yes". @nolanlawson do you agree with me or not and do you have any more comments? |
Sorry, that's a misnomer. That test is also checking whether the database supports UTF-16 (Safari <8) or UTF-8 (everything else), hence my focus on unicode. As long as you can store strings in JavaScript exactly as-is, this plugin will pass the tests just fine. :) So yes. |
I looked at that before creating the blob solution in PR #170. The two solutions are not mutually exclusive because Nolan's solution is not actually storing data using the sqlite blob type. PR #170 gives you the option to work with real binary data in sqlite which is required in scenarios where your databases are created by 3rd party authoring tools--something much more likely in Cordova apps than WebSQL. If you don't need byte for byte accuracy when data is at rest in the database, then sure, you can twiddle a few bytes like PouchDB does and store a binary string in the database but then you're incompatible with any tools expecting that data to be in a blob column and have byte for byte accuracy. Even after the blob support added in PR #170 you still have the option of storing binary data like PouchDB using string columns. In fact, there is a toBinaryString() method on the SQLBlob for this purpose that you can use (with custom twiddling logic like PouchDB) when binding the column. I think it's worth supporting both and leaving it to applications to decide what is the optimum solution for their scenario. |
To clarify some implementation details, the SQLBlob in PR #170 stores data in memory as either a Base64 or url encoded UTF-8 string. The latter should perform fairly well in most circumstances. Data can be extracted for column binding with either |
One more clarification. :) Regardless of SQLBlob's implementation, the actual changes on the native side from PR #170 continue to support storing binary data in sqlite string columns, they just add a path for using real sqlite blob columns too. |
I would like to address a couple points you make about PouchDB:
Looking carefully at some of the code changed by pouchdb/pouchdb#2900: var type = attachment.content_type;
var sql = 'SELECT escaped, ' +
'CASE WHEN escaped = 1 THEN body ELSE HEX(body) END AS body FROM ' +
ATTACH_STORE + ' WHERE digest=?';
tx.executeSql(sql, [digest], function (tx, result) {
// websql has a bug where \u0000 causes early truncation in strings
// and blobs. to work around this, we used to use the hex() function,
// but that's not performant. after migration 6, we remove \u0000
// and add it back in afterwards
var item = result.rows.item(0);
var data = item.escaped ? websqlUtils.unescapeBlob(item.body) :
parseHexString(item.body, encoding); we see that the binary data is coming form the And here is the SQL that I found where the var attach = 'CREATE TABLE IF NOT EXISTS ' + ATTACH_STORE +
' (digest UNIQUE, escaped TINYINT(1), body BLOB)'; So I would argue that the PouchDB adapter is using BLOB in the sql.
Can you think of a case that can prove the approach taken by PouchDB does not get the byte for byte accuracy? In general, I do really like the approach of the SQLBlob class that you talk about (in another project). |
https://www.sqlite.org/datatype3.html
What this means is that the SQLite column types specified when the table is created are for informational purposes only. Column type is actually determined at the time the row is inserted and if you step through the code as I did when creating SQLBlob, you'll see that the plugin in the PouchDB case is doing a string binding on the blob column. You can do a select on the data afterwards and retrieve the column type and sqlite will report to you that the column type is TEXT or VARCHAR and not BLOB. Additionally, the PouchDB code above is removing `\u0000' values when persisting and putting them back when reading. That means the data at rest is not byte compatible and a 3rd party tool reading (or providing) the data will not be aware of this. |
Also, it's fine if we move SQLBlob to another project, but there were other changes from PR #170 on the native side for Android that I think were never integrated. Those would need to be in place for a solution like SQLBlob to support true blob columns. |
Yup!
Correct. We definitely don't want to take the same approach as PouchDB when storing binary data. Moving further discussion about dealing with blobs (back) to #260. |
The
I didn't believe this at first, so I checked it out in the debugger: And you're right! :) PouchDB is actually storing text, not SQLite BLOBs. I should update our documentation to reflect that. Thanks! In general, though, if the SQLite plugin were able to use normal HTML5 Blobs and accept them as arguments, we could rewrite PouchDB to use them instead of binary strings. Would be a nice improvement to storage efficiency! |
Indeed, I had added to that WebKit bug you filed to add more context about the root cause when I fixed the same issue in this plugin. Regarding column types, thanks for confirming. :-) It was a surprise to me too initially. The problem with HTML 5 Blobs as far as I have been able to tell is that there is no way to marshal them across the JS / native boundary using the techniques that Cordova employs (which could be XHR, frame inserts, or various other hacks). At some point, Cordova will convert the data to a string and run an encoder over it. The compromise I settled on in PR #170 was to have a SQLBlob type that the plugin could automatically serialize to a sqlite blob column during column binding. It stores data in memory using either base64 or url encoding which makes the additional Cordova encoding a no-op, and you can create one directly from an ArrayBuffer if you like. I'd love to come up with something more efficient, but the built-in WebView APIs on various platforms tend to only allow string marshaling. |
I forgot to mention, regardless of the marshaling constraints I mentioned above, PR #170 actually does store data in sqlite blob format, so depending on your data, there are storage efficiency gains. |
@nolanlawson, that actually makes things easier for me, for the time being. Plenty of other backlog for me to deal with!
Absolutely! I just file #263 for this. |
@nolanlawson I followed the steps you gave me to clone and do local Running command: /Users/cbrody/Documents/brodybits/sqltest1/pouchtest1/pouchdb/tests/integration/cordova/platforms/android/cordova/run --emulator
Buildfile: /Users/cbrody/Documents/brodybits/sqltest1/pouchtest1/pouchdb/tests/integration/cordova/platforms/android/build.xml does not exist!
Build failed
/Users/cbrody/Documents/brodybits/sqltest1/pouchtest1/pouchdb/tests/integration/cordova/platforms/android/cordova/node_modules/q/q.js:126
throw e;
^
Error code 1 for command: ant with args: debug,-f,/Users/cbrody/Documents/brodybits/sqltest1/pouchtest1/pouchdb/tests/integration/cordova/platforms/android/build.xml,-Dout.dir=ant-build,-Dgen.absolute.dir=ant-gen
Error: /Users/cbrody/Documents/brodybits/sqltest1/pouchtest1/pouchdb/tests/integration/cordova/platforms/android/cordova/run: Command failed with exit code 1
at ChildProcess.whenDone (/Users/cbrody/Documents/brodybits/sqltest1/pouchtest1/pouchdb/node_modules/cordova/src/superspawn.js:126:23)
at ChildProcess.emit (events.js:110:17)
at maybeClose (child_process.js:1015:16)
at Process.ChildProcess._handle.onexit (child_process.js:1087:5) Will try another way to run the tests. |
@brodybits Currently our build only supports Node 0.10. If you use |
I used I discovered that I (still) have to start the Couch server (as described in the PouchDB TESTING.md), and just updated the comment with the testing instructions above to reflect this. I had to fix --- a/tests/integration/cordova/config.xml
+++ b/tests/integration/cordova/config.xml
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
-<widget id="com.pouchdb.tests" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+<widget id="com.pouchdb.tests" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:gap="http://phonegap.com/ns/1.0">
<name>PouchDB Test Runner</name>
<description>
Runs the unit tests suite for the PouchDB project on Cordova. But then when I run the app on the emulator, I get an alert that the connection to the server was unsuccessful, with a reference to file:///android_asset/www/tests/integration/index.html I really cannot understand this because for the installation, index.html is there in my project under both Before switching to node 0.10(.38), I did create the test app project using What I am thinking to try now is to move index.html to the root of |
You mean the connection to CouchDB? Make sure it's accessible on You shouldn't need to move the index.html anywhere. For me, the tests work fine by just starting an Android emulator (NOT Genymotion - the 10.0.2.2 path to localhost doesn't work; it's 10.0.3.2 instead) and running You can also specify the path to CouchDB by doing As for |
Oh right that |
As pointed out by @brodybits in storesafe/cordova-sqlite-storage#255. To be honest, I don't even know how it was passing in Blackberry when I added this. It's not valid XML without this fix.
As pointed out by @brodybits in storesafe/cordova-sqlite-storage#255. To be honest, I don't even know how it was passing in Blackberry when I added this. It's not valid XML without this fix.
This was only a problem when using the Android version with sqlite4java (by default). According to the comment in nolanlawson/sqlite-plugin-fork#1 (comment), the workaround was to use |
As reported by @nolanlawson in #247:
and another comment by @nolanlawson:
NOTEs:
androidDatabaseImplementation
option set to2
in sqlitePlugin.openDatabase() (as specified in README.md) and check results (also did we check this for iOS?)The text was updated successfully, but these errors were encountered: