I have completed my project which contains a pre populated sqlite database.
I have found this plugin and it works for me nicely. Lifehelper's products are truly remarkable and they have maintain pretty nice documentation.
However, when i open database, i use this format which is suggested their documentation for pre populated database.
var db = window.sqlitePlugin.openDatabase({name: "my.db", location: 'default', createFromLocation: 1});
However, my database is only for information. Application only read data from pre populated database. There is no any insert, update or delete query to keep per any user information.
In every new version pre populated data could modified, updated by me. So I need completely new app install along with new database when user will update their app.
But unfortunately, my app could not delete previous database. Changing version code also not working.
Someone suggest me, its about location which i am using to open database. But i can not understand how should dealing with it.
Help me, best answer is more important to me. Thanks.
To avoid increasing app size, you can do something like this:
function cleanupDatabases() {
var oldDatabases = ["2.1.0.db", "2.0.0.db"];
if (window.sqlitePlugin !== undefined) {
angular.forEach(oldDatabases, function(db) {
window.sqlitePlugin.deleteDatabase({
name: db,
location: 2
}, function() {
console.log("%c " + db + " is deleted", "background: green; color: white");
}, function(error) {
console.log("%c " + db + " could not be deleted", "background: red; color: white", error);
});
});
}
};
Related
I am working on a project that uses Ionic 1 and AngularJS. I have successfully stored data in SQLite. On the simulator of the Ionic (using ionic serve --lab) the data is displayed (console.log()) as follows:
SQLResultSetRowList {0: {…}, length: 1}
0: { // data }
length: 1
So I can get the data easily from accessing the object in the result array. However, on real mobile device (I am testing on Android), the data is displayed like this.
The problem is in here. I want to access the rows inside the Closure of that <function scope> that is inside the item: function, which I really don't know how it is generated (and I mean all of these) because the only result I want is as how I got just like in the simulator.
This is how I inserted the data.
$cordovaSQLite.execute(db, "INSERT OR REPLACE INTO token (token) VALUES (?)", [myData]).then(function (res) {
callback();
}, function (error) {
ErrorHandler.handle(error);
});
This is how I query the data.
$cordovaSQLite.execute(db, "SELECT * FROM token").then(function (res) {
console.log(res);
}, function (error) {
ErrorHandler.handle(error);
});
Anyone has an idea to solve this?
Any way is acceptable.
Okay. I have found the solution to solve this problem myself from this.
I need to use it like this.
if (res.rows.length > 0){
if (window.cordova) {
// Mobile Device
console.log(JSON.parse(res.rows.item(0)));
} else {
// Web
console.log(JSON.parse(res.rows[0]));
}
}
I have a big problem with the command VACUUM to free the memory from delete´s SQL sentences.
Im making a Cordova Android APP, and i know when i use a DELETE SQL sentence the space of the app don't down,... the space persist like a fragment HardDisk.
Then, i see that VACUUM can compact my DB, but i have a problem!
I use SQLite3, and VACUUM in all sites say that can´t execute in a transaction, like this:
var db = window.sqlitePlugin.openDatabase({name:"maintenance", location:'default'});
db.transaction(function (tx) {
tx.executeSql('VACUUM', [], function (tx, results) {
alert('done');
}, function (tx, error) {
alert('error');
alert(error.message);
});
});
Ok, well, then, if i can't do in a transaction, could u tell me how can i execute a vacuum or auto-vacuum or something similar to compact the BD without write a line command? (remember that its a mobile app)
According to the GitHub Page, you should be able to execute SQL outside of a transaction with db.executeSql:
db.executeSql("VACUUM", [], function(rs) {
// ok
}, function(err) {
// handle error
});
I have a pouch database that contains hundreds documents of 1 Mo, so the total size is ~100 Mo. It's an Android Cordova app and I'm using:
PouchDb 5.4.5
cordova-plugin-sqlite-2 1.0.4
Each document is like this:
{
data: '...', // Very long string of 1 Mo
filename: 'myFile', // Name of a file
index: 34 // An integer
}
I'd like to do a query on this db to list all documents indexed by filename and index, without retrieving data property which is heavy.
So I did a view like this:
var designDoc = {
_id: '_design/getByFilenameAndIndex',
views: {}
};
mapFunction = function(doc){
emit(doc.filename + '/' + doc.index);
}
designDoc.views['getByFilenameAndIndex'] = { map: mapFunction.toString() };
myDb.put(designDoc);
But when I try to query my db, like this:
myDb.query('getByFilenameAndIndex', {include_docs: false}).then(function(docsByFilenameAndIndex){
console.log(docsByFilenameAndIndex);
});
I get the following error:
Why I'm having this error ? I still have 900 Mo of ram available on my device (Android 6), and I'm not even including docs. If my db is less than 20 Mo it works fine.
It was working fine too with db of 40 Mo before using SQLite plugin, but I can't work without it since I need more than 50 Mo database.
Edit: I tried to do this and I get the error too: myDb.allDocs({include_docs: false});
Instead of directly inserting large binary strings into your documents, you should use attachments. These will ensure that when you do operations that don't touch attachments (such as queries, allDocs(), etc.), PouchDB won't read the attachments into memory. This should fix your Out Of Memory issues.
I am working on a Android app and is using Parse Database, and would like to add a IncrementKey function such that when a new image is added to the database, the image_id column would increase itself by 1.
Reference: https://www.parse.com/questions/incrementkey
Question:
However, googled for a long while, there are no explicit example to show how to get it work... it involves cloud code at parse. Would there be any hints on how could that be done?
Thanks!
To create a beforeSave trigger for Image (replace where relevant, I've assumed this is your Class that holds the images and counter column - these are properties of the same Object)
file: ./cloud_code/cloud/main.js or a filepath required by main.js
Parse.Cloud.beforeSave("Image", function(request, response) {
//check if this is a new or existing Image
if (!request.object.isNew()) {
//image exists, save as normal
response.success();
} else {
//find the last image saved
var checkImage = Parse.Object.extend("Image");
var imagesQuery = new Parse.Query(checkImage);
imagesQuery.select("image_id"); //save memory by only requesting image_id
imagesQuery.descending("image_id"); //sort, make sure image_id is a Number
imagesQuery.first().then(
function(lastImage) {
//increase the id by 1
var newId = lastImage.get("image_id") + 1;
//save the current object with the new id
request.object.set("image_id", newId);
response.success(); //this saves your request.object
},
function (error)
response.error(error);
}
);
}
});
Resources
Cloud code guide: https://parse.com/docs/cloudcode/guide
Cloud code beforeSave modify: https://parse.com/docs/cloudcode/guide#cloud-code-modifying-objects-on-save
Retrieving objects: https://www.parse.com/docs/js_guide#objects-retrieving
Increment (updating an existing field): https://parse.com/docs/js/guide#objects-counters
See also Parse cloudcode beforeSave obtain pre-updated object (the other way around)
Read the Cloud code guide to learn how to e.g. install the CLI tools to deploy your Cloud Code and check the Cloud logs for debugging.
Disclaimer: code above is untested but based on working functions
Note: use isNew() in a beforeSave handler, existed in an afterSave handler. There's a reported bug for existed in Parse Cloud Code versions 1.6.* - see Parse request.object.existed() return false
Me and my friend are working on an app., and we wish to use Parse.com as our data base from which we can retrieve info.
We can't decide what is the best way to access the data on Parse. For the sake of the example, our app. (i.e. client side) needs something stored on the Parse data base (say some number) - should it directly run the query using the Parse API, or should it make a request to a server side, let it retrieve that number from Parse, and send it back to the client?
We know there's no definite answer, but we couldn't find answer regarding this specific situation. We read this post: When to use client-side or server-side?,
but this not exactly the same case.
I claim that we should try to seperate as much as possible from client side and data bases, and leave these queries run by someone who's in charge (server), where my friend claims this adds unnecessary complication, since it's very natural to use the tools supplied by Parse to access the data base from the client side, without the need for a protocol etc.
We'd appriciate any advice,
Thank you.
In general, go right ahead and make a normal call.
I'd encourage you to do that first in any case, to get everything working on both ends.
Then if necessary go to Cloud Code.
If you are going to do more than one platform (ie iOS and Android), cloud code can be a huge timesaver.
BUT don't forget that for simple calls, cloud code is a waste of time. "Normal" Parse calls are amazingly, incredibly, amazingly, fast and quick to work with.
There is absolutely nothing "wrong" with using normal Parse calls - so do that.
Regarding the question, when do you literally have to use a cloud code call -- you'll know, because you won't be able to do it with a normal call :)
Don't forget very often you can simply use "afterSave" or "beforeSave" in cloud code, to do a huge amount of work. You often don't literally need to go to a "custom call" in cloud code.
Here's a fantastic
Rule of thumb for Parse cloud code --------->
If you have to do "more than one thing" ... in that case you will likely have to make it a cloud code function. If you have to do "three or more things" then DEFINITELY make it a cloud code function.
That's a good rule of thumb.
(Again, as I say, often just an "afterSave" or similar works brilliantly...rather than literally writing a full custom call.)
Here's a typical example of a cloud call that saves 18 billion lines of code in all the platforms covered by the dotcom. First the cloud code...
Parse.Cloud.define("clientRequestHandleInvite", function(request, response)
{
// called from the client, to accept an invite from invitorPerson
var thisUserObj = request.user;
var invitorPersonId = request.params.invitorPersonId;
var theMode = request.params.theMode;
// theMode is likely "accept" or "ignore"
console.log( "clientRequestAcceptInvite called.... invitorPersonId " + invitorPersonId + " By user: " + thisUserObj.id );
console.log( "clientRequestAcceptInvite called.... theMode is " + theMode );
if ( invitorPersonId == undefined || invitorPersonId == "" )
{
response.error("Problem in clientRequestAcceptInvite, 'invitorPersonId' missing or blank?");
return;
}
var query = new Parse.Query(Parse.User);
query.get(
invitorPersonId,
{
success: function(theInvitorPersonObject)
{
console.log("clientRequestFriendRemove ... internal I got the userObj ...('no response' mode)");
if ( theMode == "accept" )
{
createOneNewHaf( thisUserObj, theInvitorPersonObject );
createOneNewHaf( theInvitorPersonObject, thisUserObj );
}
// in both cases "accept" or "ignore", delete the invite in question:
// and on top of that you have to do it both ways
deleteFromInvites( theInvitorPersonObject, thisUserObj );
deleteFromInvites( thisUserObj, theInvitorPersonObject );
// (those further functions exist in the cloud code)
// for now we'll just go with the trick of LETTING THOSE RUN
// so DO NOT this ........... response.success( "removal attempt underway" );
// it's a huge problem with Parse that (so far, 2014) is poorly handled:
// READ THIS:
// parse.com/questions/can-i-use-a-cloud-code-function-within-another-cloud-code-function
},
error: function(object,error)
{
console.log("clientRequestAcceptInvite ... internal unusual failure: " + error.code + " " + error.message);
response.error("Problem, internal problem?");
return;
}
}
);
}
);
If you are new to Parse it's incredibly hard to figure out how to call these from Android or iOS! Here's that one being called from Android ...
this will save you a day of messing about with HashMaps :)
private static void handleInvite( ParseUser invitor, final boolean accepted )
{
String invitorId = invitor.getObjectId();
// you must SEND IDs, NOT PARSEUSER OBJECTS to cloud code. Sucks!
String cloudKode;
cloudKode = (accepted? "accept" : "ignore");
HashMap<String, Object> dict = new HashMap<String, Object>();
dict.put( "invitorPersonId", invitorId );
dict.put( "theMode", cloudKode );
Toast.makeText(State.mainContext, "contacting...", Toast.LENGTH_SHORT).show();
ParseCloud.callFunctionInBackground(
"clientRequestHandleInvite",
dict,
new FunctionCallback<Object>()
{
#Override
public void done(Object s, ParseException e)
{
Toast.makeText(State.mainContext, "blah", Toast.LENGTH_SHORT).show();
// be careful with handling the exception on return...
}
});
}
And here's the same cloud call from iOS ... well for now, until you have to do it in SWIFT
-(void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
int thisRow = indexPath.row;
PFUser *delFriend = [self.theFriends objectAtIndex:thisRow];
NSLog(#"you wish to delete .. %#", [delFriend fullName] );
// note, this cloud call is happily is set and forget
// there's no return either way. life's like that sometimes
[PFCloud callFunctionInBackground:#"clientRequestFriendRemove"
withParameters:#{
#"removeThisFriendId":delFriend.objectId
}
block:^(NSString *serverResult, NSError *error)
{
if (!error)
{
NSLog(#"ok, Return (string) %#", serverResult);
}
}];
[self back]; // that simple
}
Note For the iOS/Swift experience, click to: How to make this Parse.com cloud code call? which includes comments from the Parse.com team. Hope it saves someone some typing, cheers