I have a Phonegap (2.1.0) application that onDeviceready creates a DB and populates a table with info.
Running this locally (using the Ripple emulator) on Chrome works. Tables are being created and populated as required.
After installing the build .apk on my Android device my Eclipse logcat shows:
sqlite returned: error code = 14, msg = cannot open file at line 27712 of [8609a15dfa], db=/data/data/<project>/databases/webview.db
sqlite returned: error code = 14, msg = os_unix.c: open() at line 27712 - "" errno=2 path=/CachedGeoposition.db, db=/data/data/<project>/databases/webview.db
Which I believe according to this post here - can be ignored.
However - I also noticed this error in logcat:
sqlite returned: error code = 1, msg = no such table: latest_events, db=/data/data/<project>/databases/webview.db
I have also - through adb shell - confirmed that the DB is not created:
here: /data/data/com.application/databases.
or here: /data/data/com.application/app_databases
So - my code:
if (!window.openDatabase) {
doMessage('Databases are not supported on this device. Sorry','error');
return;
}else{
consoleLog('all good for storage');
var db;
var shortName = 'MyDB';
var version = '1.0';
var displayName = 'MyDB';
var maxSize = 102400;
function errorHandler(transaction, error) {consoleLog('Error: ' + error.message + ' code: ' + error.code);}
function nullHandler(){};
db = window.openDatabase(shortName, version, displayName,maxSize);
consoleLog('starting table creation');
db.transaction(function(tx){
tx.executeSql( 'CREATE TABLE IF NOT EXISTS latest_events (id integer PRIMARY KEY AUTOINCREMENT,EventID integer,EventLocation text,EventName text,EventDateFrom varchar,EventTime timestamp,EventPresentedBy varchar,EventVenue varchar,EventScript text,RequireRSVP varchar)',[],nullHandler,errorHandler);
db.transaction(function(tx){
tx.executeSql('SELECT count(id) as RowCount FROM device_info ', [],
function(tx, result) {
if (result != null && result.rows != null) {
for (var i = 0; i < result.rows.length; i++) {
var row = result.rows.item(i);
consoleLog('rowcount: '+row.RowCount);
if(row.RowCount==0){
tx.executeSql('INSERT INTO device_info (device_name, device_platform, device_uuid, device_os_ver, date_last_used) VALUES (?,?,?,?,?)',[device.name, device.platform, device.uuid, device.version, window.bowman_config.siteDate],nullHandler,errorHandler);
//doMessage('device info row added','notice');
}
}
}
},errorHandler);
},errorHandler,successCallBack('2'));
//doMessage('device info row added','notice');
},errorHandler,successCallBack('1'));
}
To add to my woes - on my logcat I do see the console.log output for "all good for storage", and the "starting table creation" messages.
My errorHandler functions are not returning anything and my successCallBack functions are triggered...but no DB created.
Thanks for the help.
When you pass in successCallBack("2") and successCallBack("1") then you are actually invoking them directly so you may be getting false positives on whether or not success has actually been called. You should provide two separate success call backs or just in-line some functions that call console.log("1") for instance.
Today this issue cost me 3 hours. What I tried:
Rewriting the copy database code.
Deleting the app from the emulator / device
Wiping emulator(s)
Cleaning eclipse
Changing file permissions
Validate a working SQLite database file
I solved the problem by copying the code from a shared Dropbox account to another location and refactoring the code in the Android Manifest and java files with another package name.
The application runs beautifully now, i.e. nothing wrong with the code, but somewhere it's muxed up by Dropbox.
I broke the nested functions up into single functions and 'chained' them based on their success or fail. It's actually been a lot simpler than I thought. RTFM it seemed. Thanks for all the help.
simplified:
var db = window.openDatabase("TheApp", "1.0", "The App", 50000000);
db.transaction(queryDB, errorCB, successCB);
// Query the database //
function queryDB(tx) {
//tx.executeSql('SELECT * FROM table", [], querySuccess, errorCB);
}
function querySuccess(tx, results) {
//do more functions here
}
function errorCB(err) {
console.log("Error processing SQL: "+err.code);
}
Related
I'm just getting started with Google Apps Script and doing development like this again after a long time. The following code returns:
Exception: No database selectedwhen I executetest202302110454()
It fails executing the createTable() function. The code is a mishmash of example code from Google for using its JDBC connector/library with a Google Apps Script Web app and my own modifications.
The back-end is a Google Cloud SQL MySQL database instance.
const debug = true;
debug ? Logger.log("I'm inside service/jdbc.gs.") : null ;
const jdbcEnv = ifSql(database);
// Check to see if we're using an SQL back-end rather than Firestore et al.
function ifSql(database) {
if (database == "sql") {
return initSql()
}
return [];
}
// If we're using SQL, set up the JDBC environment
function initSql() {
const url = "jdbc:google:mysql://goals-and-projects:us-central1:mysql-instance";
const db = "goalManagementApp";
const environmentObject = {
"instanceUrl": url,
"db": db,
"dbUrl": `${url}/${db}`,
"root": "root", // TODO: Move this to the Properties service
"rootPwd": "*****************", // TODO: Move this to the Properties service
};
return environmentObject;
}
function getSQLConnection(env) {
const connection = Jdbc.getCloudSqlConnection(env.instanceUrl, env.root, env.rootPwd);
return connection;
}
function test202302110454() {
Logger.log("I'm running a test function.");
Logger.log(jdbcEnv);
Logger.log(createDatabase(`database` + Date.now(), jdbcEnv));
Logger.log(createTable(`table` + Date.now(), jdbcEnv));
}
/**
* Create a new database within a Cloud SQL instance.
*/
function createDatabase(databaseName, env) {
debug ? Logger.log("Inside createDatabase()") : null;
const db = databaseName;
const connection = getSQLConnection(env);
try {
connection.createStatement().execute('CREATE DATABASE ' + db);
} catch (err) {
// TODO(developer) - Handle exception from the API
console.log('Failed with an error %s', err.message);
}
}
/**
* Create a new table in the database.
*/
function createTable(tableName, env) {
debug ? Logger.log("Inside createTable()") : null;
try {
const connection = getSQLConnection(env);
//const connection = Jdbc.getCloudSqlConnection(env.dbUrl, env.root, env.rootPwd);
debug ? Logger.log(env) : null;
connection.createStatement().execute(`CREATE TABLE ${tableName} ` +
'(guestName VARCHAR(255), content VARCHAR(255), ' +
'entryID INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(entryID));');
} catch (err) {
// TODO(developer) - Handle exception from the API
console.log('Failed with an error %s, %s', err.message, err);
}
}
However, this modification makes the createTable() function work as expected, without error:
//const connection = getSQLConnection(env);
const connection = Jdbc.getCloudSqlConnection(env.dbUrl, env.root, env.rootPwd);
When I try to use my own function getSQLConnection to create a connection object, it fails, but when I use Jdbc.getCloudSqlConnection it succeeds. Unless I'm missing something, this is not the case when running createDatabase() even though I think I'm setting them up the same way. I am outputting the connection objects that are used in each case and they both appear identical to me; there is no missing database name that I can tell.
What am I missing?
For more context:
The way I'm executing this is within the Google Apps Script scripting environment on the website. I'm selecting the test function (test202302110454) in the UI and running it there. I created the test202302110454 function to test out my other functions and ensure I know what they are doing.
The exact logging console output is:
11:20:10 PM Info I'm inside service/jdbc.gs.
11:20:10 PM Info I'm running a test function.
11:20:10 PM Info {dbUrl=jdbc:google:mysql://goals-and-projects:us-central1:mysql-instance/goalManagementApp, root=root, rootPwd=**********, db=goalManagementApp, instanceUrl=jdbc:google:mysql://goals-and-projects:us-central1:mysql-instance}
11:20:10 PM Info Inside createDatabase()
11:20:10 PM Info null
11:20:10 PM Info Inside createTable()
11:20:10 PM Info {rootPwd=***********, dbUrl=jdbc:google:mysql://goals-and-projects:us-central1:mysql-instance/goalManagementApp, db=goalManagementApp, instanceUrl=jdbc:google:mysql://goals-and-projects:us-central1:mysql-instance, root=root}
11:20:10 PM Info Failed with an error No database selected, Exception: No database selected
11:20:10 PM Info null
Maybe helpful references:
https://developers.google.com/apps-script/reference/jdbc/jdbc#getcloudsqlconnectionurl,-username,-password
The two calls differ in the first parameter:
const connection = Jdbc.getCloudSqlConnection(env.dbUrl, env.root, env.rootPwd);
const connection = Jdbc.getCloudSqlConnection(env.instanceUrl, env.root, env.rootPwd);
The env.dbUrl property adds /${db}, so that is probably what's missing.
I have a dynamodb table with a column called "approval", and several test items in it with values for "approval" that include "pending", "approved", and "not approved". I have 3 items with "pending".
I'm using the following Lambda function to retrieve items and I want get just the items that are "pending". So I'm using FilterExpression. This is my complete function:
var doc = require('dynamodb-doc');
var dynamo = new doc.DynamoDB();
exports.handler = function(event, context) {
var params = {
TableName: 'mytable',
FilterExpression: 'contains(approval, :approval_value)',
ExpressionAttributeValues: {':approval_value': 'pending'}
};
dynamo.scan(params, onScan);
function onScan(err, data) {
if (err) {
console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Scan succeeded.");
context.succeed(data);
}
}
};
Basically I want to do a, "SELECT * FROM mytable WHERE approval LIKE 'pending';" if it were in SQL.
Weirdly, only item is being returned while I'm expecting 3. I'm not using Limit. Why is it only returning one item?
Welp, embarrassingly, I was reading the execution result wrong. It was returning 3 results correctly, but only the first item appeared "above the fold" (probably another reason not to use the AWS console for this stuff).
Hopefully the code above, which works perfectly well, will help someone else as a simple example of using FilterExpression.
I am working on a mobile application using apache cordova.. I have a javascript file that reads data from an azure mobile service and persists it onto the local SQLITE database..
i have a function that is meant to query the azure mobile service but it gives me an error -"cannot read propert 'take' of undefinedType". The function is as follows
function refreshQuestionsTable() {
alert("questions refreshing");
var query = QuestionsTable.take(100).read().done(function (results) {
alert(results.length); //see how many records were returned
for (var i = 0; i < results.length; i++) {
alert(results[i].question); //display the question returned
commitQuestions(results[i].question_id, results[i].client_ref, results[i].question_set, results[i].question_dept, results[i].question, results[i].question_branch, null);
}
},function (err) {
alert("Error: " + err);
});
}
It looks like your client instantiation piece is wrong.
var client = new MobileServiceClient('feedbackmaster.azure-mobile.net/', 'oLMEOExWGFolBhpyYpTFkqvKuLNlyL91');
You had a ';' at the end of your URL for some reason. You should also do a .where() clause that is universally true. Take should work off of that.
Whenever I launch my Windows Store application, I get an error that 'alert' is undefined. I'm trying to query a table in Azure Mobile Services and make a list out of the column "type_of_service" from that table.
var typeOfServiceTable = client.getTable('TypeOfService');
// Create a list of type of services
var query = typeOfServiceTable.select("type_of_service").read().done(function (results) {
alert(JSON.stringify(results));
}, function (err) {
alert("Error: " + err);
})
alert() can not be used on Windows Store application.
Instead of using alert(), try the following function:
var msg = new Windows.UI.Popups.MessageDialog("Hello Windows!");
msg.showAsync();
I am working on an iOS app that was originally written for PhoneGap 1.0.0 that was recently upgraded to 2.2.0 so I can use SQLitePlugin with SQLCipher. I'm having problems with a SELECT statement never returning results, even though I know there's data in there.
Here's the rundown:
The database is created with the following code:
THDatabase.DatabaseConnection = sqlitePlugin.openDatabase(THDatabase.name, THDatabase.currentVersion, THDatabase.displayName, THDatabase.size);
THDatabase.DatabaseConnection.transaction(THDatabase.CreateUsersTable, THDatabase.FatalErrorCallback);
THDatabase.DatabaseConnection.transaction(THDatabase.CreateCentersTable, THDatabase.FatalErrorCallback);
...
Once a user registers, the Centers and Users tables have data inserted.
When the login screen loads, the db is queried for Centers and Users.
/* Centers */
LoadCenters: function LoadCenters() {
console.log("LoadCenters");
THDatabase.DatabaseConnection.transaction(THDatabase.LoadCentersImpl, THDatabase.FatalErrorCallback);
console.log('THDB.LoadCenters called from: ' + arguments.callee.caller.name);
},
LoadCentersImpl: function(tx) {
console.log("Loading centers.");
tx.executeSql('SELECT * FROM Centers', [], THDatabase.LoadCentersParse, THDatabase.RecoverableErrorCallback);
},
LoadCentersParse: function(tx, results) {
console.log('parsing centers');
var dataArray = [];
var len = results.rows.length;
...
},
/* Users */
LoadUsers: function LoadUsers() {
console.info("THDB.LoadUsers");
THDatabase.DatabaseConnection.transaction(THDatabase.LoadUsersImpl, THDatabase.FatalErrorCallback);
},
LoadUsersImpl: function (tx) {
console.info("Loading users...");
tx.executeSql('SELECT * FROM Users', [], THDatabase.LoadUsersParse, THDatabase.RecoverableErrorCallback);
},
LoadUsersParse: function (tx, results) {
console.info('parsing users...');
var dataArray = [];
var len = results.rows.length;
console.log(len);
...
}
...
The problem I'm having is that after LoadUsersImpl() runs, LoadUsersParse() never gets the results of the SELECT statement. The console.log stops at "Loading users...". I'm still able to log into the app, but nothing else that requires reading from the db works.
I've tried wrapping the call to LoadUsersParse() in an anonymous function, passing tx, results, which doesn't work. If I pass just results, then the results of the call show up in the console log, but it stops right after 'parsing users...' shows up.
This same code works fine without the SQLitePlugin installed in PhoneGap, but I can't figure out where it may be causing the problem.
Turning DEBUG on logs this right after "Loading users...":
SQLitePlugin.backgroundExecuteSqlBatch: {"executes":[{"query":["BEGIN"],"path":"ThinkHealthDBs.db","callback":"cb55"},{"query":["SELECT * FROM Users"],"path":"ThinkHealthDBs.db","callback":"cb56"}]}
This is a problem with and without SQLCipher being used, and on PhoneGap/Cordova 2.1.0.