undefined vue variable when executing db.each - sqlite

i'm learning with electronjs and sqlite3 and i used vue too, when i tried to to do tb.push in db.each the message was "undefined this.tb", i could fix it with no understanding how
so why the code below works
var app=new Vue({
el:'#resultDiv',
data:{
message:'hi',
tb:[],
},
mounted(){
var tb=[];
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database(':memory:');
db.serialize(function() {
db.run("CREATE TABLE lorem (info TEXT)");
var stmt = db.prepare("INSERT INTO lorem VALUES (?)");
for (var i = 0; i < 10; i++) {
stmt.run("Ipsum " + i);
}
stmt.finalize();
var textee;
db.each("SELECT rowid AS id, info FROM lorem", function(err, row) {
textee=row.id + ": " + row.info;
console.log(textee);
tb.push(textee);
});
});
db.close();
this.tb=tb;
}
});
but this below does not
var app=new Vue({
el:'#resultDiv',
data:{
message:'hi',
tb:[],
},
mounted(){
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database(':memory:');
db.serialize(function() {
db.run("CREATE TABLE lorem (info TEXT)");
var stmt = db.prepare("INSERT INTO lorem VALUES (?)");
for (var i = 0; i < 10; i++) {
stmt.run("Ipsum " + i);
}
stmt.finalize();
var textee;
db.each("SELECT rowid AS id, info FROM lorem", function(err, row) {
textee=row.id + ": " + row.info;
console.log(textee);
this.tb.push(textee);//this not working
});
});
db.close();
}
});

This is because in your non-working example
db.each("SELECT rowid AS id, info FROM lorem", function(err, row) {
textee=row.id + ": " + row.info;
console.log(textee);
this.tb.push(textee);//this not working
});
the keyword this doesn't refer to the vue component, but to the execution context of the each-function.
This is caused by using the function() {}-way of describing anonymous functions.
If you'd instead use the arrow-function way to express the callback:
db.serialize(() => {
db.each("SELECT rowid AS id, info FROM lorem", (err, row) => {
textee=row.id + ": " + row.info;
console.log(textee);
this.tb.push(textee);//this now working
});
});
this now refers to your vue component's execution context and your code should work. Note that I had to use arrow function expression's for the serialize-function as well, otherwise this would have referred to that functions execution context instead.
Alternatives
If you, for some reason, cannot use the arrow function expression, you have several alternatives. You could explicitly bind this to the vue context like so:
db.serialize((function () {
db.each(..., (function (err, row) {
...
}).bind(this));
}).bind(this));
I don't particularly like this approach.
Or you could capture the this context in a variable under the closure of the mounted-method.
mounted() {
var self = this;
...
db.each("SELECT rowid AS id, info FROM lorem", function(err, row) {
textee=row.id + ": " + row.info;
console.log(textee);
self.tb.push(textee);
});
}

Related

Can't delete SQLite database using Qt with QML transaction

Trying to use localstorage example in Qt 5.14, the database is locked and can't be deleted.
on Qt documentation it's saying:
"Database connections are automatically closed during Javascript garbage collection."
but that is not the case...
function dbInit()
{
var db = LocalStorage.openDatabaseSync("Activity_Tracker_DB", "", "Track exercise", 1000000)
try {
db.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS trip_log (date text,trip_desc text,distance numeric)')
})
} catch (err) {
console.log("Error creating table in database: " + err)
};
}
function dbGetHandle()
{
try {
var db = LocalStorage.openDatabaseSync("Activity_Tracker_DB", "",
"Track exercise", 1000000)
} catch (err) {
console.log("Error opening database: " + err)
}
return db
}
function dbInsert(Pdate, Pdesc, Pdistance)
{
var db = dbGetHandle()
var rowid = 0;
db.transaction(function (tx) {
tx.executeSql('INSERT INTO trip_log VALUES(?, ?, ?)',
[Pdate, Pdesc, Pdistance])
var result = tx.executeSql('SELECT last_insert_rowid()')
rowid = result.insertId
})
return rowid;
}
function dbReadAll()
{
var db = dbGetHandle()
db.transaction(function (tx) {var results = tx.executeSql(
'SELECT rowid,date,trip_desc,distance FROM trip_log order by rowid desc')
for (var i = 0; i < results.rows.length; i++) {
listModel.append({
id: results.rows.item(i).rowid,
checked: " ",
date: results.rows.item(i).date,
trip_desc: results.rows.item(i).trip_desc,
distance: results.rows.item(i).distance
})
}
})
}
How can I unlock/close the database?

Cordova Android SQLLIteplugin.open exception

I am trying to use SQLLItePlugin for Android but its not working. I will list my steps:
1. I have installed cordova pjhonegap from phonegap. I am developing my mobile app Phonegap, html5, javascript, css3 using Netbeans as IDE.
2. Downloaded plugin from https://github.com/brodysoft/Cordova-SQLitePlugin.
3. Added SQLitePlugin.js to js folder of project.
4. Added com.brodysoft.sqlitePlugin.file=https://github.com/brodysoft/Cordova-SQLitePlugin.git in plugin.properties.
5. Am opening database on deviceready as
var app = {
initialize: function () {
this.bindEvents();
},
bindEvents: function () {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
onDeviceReady: function () {
app.receivedEvent('deviceready');
var db = window.sqlitePlugin.openDatabase('gdata.db');
console.log('ready');
db.transaction(function (tx) {
tx.executeSql('DROP TABLE IF EXISTS test_table');
tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data text, data_num integer)');
// demonstrate PRAGMA:
db.executeSql("pragma table_info (test_table);", [], function (res) {
console.log("PRAGMA res: " + JSON.stringify(res));
});
tx.executeSql("INSERT INTO test_table (data, data_num) VALUES (?,?)", ["test", 100], function (tx, res) {
console.log("insertId: " + res.insertId + " -- probably 1");
console.log("rowsAffected: " + res.rowsAffected + " -- should be 1");
db.transaction(function (tx) {
tx.executeSql("select count(id) as cnt from test_table;", [], function (tx, res) {
console.log("res.rows.length: " + res.rows.length + " -- should be 1");
console.log("res.rows.item(0).cnt: " + res.rows.item(0).cnt + " -- should be 1");
});
});
}, function (e) {
console.log("ERROR: " + e.message);
});
});
},
// Update DOM on a Received Event
receivedEvent: function (id) {
var parentElement = document.getElementById(id);
console.log('Received Event: ' + id);
}
};
app.initialize();
Running the build on android devvice directly.
It keeps on throwing the error
Uncaught TypeError: Object # has no method 'exec'
(13:52:13:450 | error, javascript)
at SQLitePlugin.open (www/js/libs/SQLitePlugin.js:112:15)
at SQLitePlugin (www/js/libs/SQLitePlugin.js:54:10)
at (anonymous function) (www/js/libs/SQLitePlugin.js:425:14)
at (anonymous function) (www/js/libs/SQLitePlugin.js:30:20)
at createandpopulatedb (www/js/dborarray.js:30:30)
at onDeviceReady3 (www/dborarray.html:96:33)
at onload (www/dborarray.html:16:155) SQLitePlugin openargs: {"name":"gdataenter code here.db"} (13:52:19:609) at
www/js/libs/SQLitePlugin.js:39
Can somebody help.
try thhis
window.sqlitePlugin.openDatabase({name: "gdata.db"});
instead of this
window.sqlitePlugin.openDatabase('gdata.db');

How to get the total count of a Meteor collection with a limit set?

In my meteor app, I'm doing infinite scrolling so I must have a limit set on my subscriptions in order to achieve this, but I also need to show the total count from that same collection and update it if the count changes. How would I achieve that?
I have a partial solution that achieves this but only returns the paginated counts, as follows:
function getTotalCount(system) {
var user = Meteor.user(),
queryObject = getSystemQueryObject(system);
if (queryObject) {
var query = queryObject.find({$and: [
{user: user.username},
{status: {$nin: status_complete}}
]});
var count = 0;
var handle = query.observeChanges({
added: function (id, user) {
$('#' + system + 'Count').text(++count);
$('#' + system + 'Count').addClass("ma-count-badge");
console.log(system + " count incremented: " + count);
},
removed: function () {
$('#' + system + 'Count').text(--count);
$('#' + system + 'Count').addClass("ma-count-badge");
console.log(system + " count decremented: " + count);
}
});
}
else {
return 0;
}
}
The other way is to push this method up to the server as a server method, but then it is not reactive, as follows:
Meteor.call('getSystemsTotalCount', system, function (err, counted) {
if (err) {
throw err;
}
if (counted > 0) {
$('#' + system + 'Count').text(counted);
$('#' + system + 'Count').addClass("ma-count-badge");
}
Session.get('listLimit');
});
}
you can to get the count with following way
var count= queryObject.find({$and: [
{user: user.username},
{status: {$nin: status_complete}}
]}).count();
after that, you can to save in a Session
Session('countCollection',count);
if the collection changes your Session also it will do
So the trick really is to combine both options I have in the question. The first part adds reactivity to adds/deletes and the second part calls out to the server to go get the total count. Now my code looks like:
query.observeChanges({
added: function(id, user) { updateListCount(system);},
removed: function(id) { updateListCount(system);}
});
And I just wrap the Method.call from the second excerpt above with a function called updateListCount invoked by the above. This addresses the issue.

How to subscribe a publish collection in Meteor?

I copy code from: How does the messages-count example in Meteor docs work? it does not work. client call Counts.find().count() method, I expect it to output 1 but the result is 0 ,can you tell me why?
//server code
if (Meteor.is_server)
{
Meteor.startup(function (){
console.log("server is startup...");
Messages = new Meteor.Collection("messages");
if(Messages.find().count() == 0){
for(var i=0;i<7;i++){
Messages.insert({room_id:"00"+i,text:"message "+i});
}
}
console.log("room_id:001 messages count="+Messages.find({room_id:"001"}).count());
//print--->room_id:001 messages count=1 (it's ok)
Meteor.publish("counts-by-room", function (roomId) {
var self = this;
var uuid = Meteor.uuid();
var count = 0;
var handle = Messages.find({room_id: roomId}).observe({
added: function (doc, idx) {
count++;
self.set("counts", uuid, {roomId: roomId, count: count});
self.flush();
},
removed: function (doc, idx) {
count--;
self.set("counts", uuid, {roomId: roomId, count: count});
self.flush();
}
// don't care about moved or changed
});
// remove data and turn off observe when client unsubs
self.onStop(function () {
handle.stop();
self.unset("counts", uuid, ["roomId", "count"]);
self.flush();
});
});
});
}
//client code
if (Meteor.is_client)
{
Meteor.startup(function () {
Counts = new Meteor.Collection("counts");
Session.set("roomId","001");
Meteor.autosubscribe(function () {
Meteor.subscribe("counts-by-room", Session.get("roomId"));
});
console.log("I client,Current room "+Session.get("roomId")+" has "
+ Counts.find().count() + " messages.");
//print--->I client,Current room 001 has 0 messages.(trouble:I expect it to output "...has 1 messages" here)
});
}
I try many times and I find the bug.
change the client code to like below,it will print the correct result.
//client code
Meteor.startup(function () {
Counts = new Meteor.Collection("counts");
Session.set("roomId","001");
Meteor.autosubscribe(function () {
Meteor.subscribe("counts-by-room", Session.get("roomId"));
data = Counts.findOne();
if(data){
console.log("I client,Current room "+Session.get("roomId")+" has "
+ data.count + " messages.");
//print--->I client,Current room 001 has 1 messages.(now it's ok!)
}
})
});
Try it like that
Counts = new Meteor.Collection("counts-by-room"); /* correct name of the collection */
/*... subscribing stuff */
Counts.findOne('counts') /* this is the count you published */

Adobe AIR - SQL statement against DB

This is my javascript for Adobe Air:
$(document).ready(function(e) {
setupDB();
var tasks = getTasks();
$("#tasks").empty();
var numRecords = tasks.data.length;
for(i=0; i<numRecords; i++) {
$("<li/>").append('<span>'+ tasks.data[i].id +' - '+ tasks.data[i].task +'</span>').appendTo("#tasks");
}
});
var db = new air.SQLConnection();
function setupDB() {
var dbFile = air.File.applicationStorageDirectory.resolvePath("airTasks.db");
try {
db.open(dbFile);
} catch (error) {
alert("DB Error: "+ error.message);
alert("Details: "+ error.details);
air.trace("DB Error: "+ error.message);
air.trace("Details: "+ error.details);
}
}
function getTasks() {
var query = new air.SQLStatement();
query.sqlConnection = db;
query.text = "SELECT id, task FROM tasks";
try {
query.execute();
} catch(error) {
alert("Error getting tasks from DB: "+ error.message +", DETAILS: "+ error.details);
air.trace("Error getting tasks from DB: "+ error);
air.trace(error.message);
return;
}
return query.getResults();
}
Here is a screenshot of the Database Version 3 - airTasks.db
I keep getting:
ERROR: Table "tasks" not found.
Double check that your filepath being opened actually exists. If it doesn't, SQLite creates one for you.
Try this to troubleshoot before you call db.open():
alert(dbFile);
Is this the correct path to your db?

Resources