jquery mobile function not returning value - sqlite

I'm trying to run a check on a webdb running on a cordova/jQuery-mobile application:
This function will check whether the table exists in the DB and subsequently return a true or false. I have tried to change the return type from boolean to integer (0 and 1) but with no success.
function checkConfigTable(tablename) {
db.transaction
(
function (tx)
{
tx.executeSql
(
'SELECT name FROM sqlite_master WHERE type="table" AND name=?',
[tablename],
function(tx,results)
{
var len = results.rows.length;
if(len>0)
{
return true;
}
else {
return false;
}
}, errorCB
);
},errorCB,successCB
);
}
I want to then call checkConfigTable from this other one just to alert the return value (only for test purposes at the moment) but I am always getting "undefined" as return value.
// Function to retrieve current login config
function getSavedLogin(configid) {
var x = checkConfigTable("config");
alert('table: ' + x);
}
If I substitute the return with an alert directly in checkConfigTable() the correct values are shown in the alert box.

Related

sqlite_reset() on an INSERT with RETURNING statement rollback/cancel it

I want to INSERT data in a SQLite table and do this :
sqlite3_stmt *pStmt;
sqlite3_prepare(db,"INSERT INTO table(col2,col3) VALUES (?,?) RETURNING col1;",-1,&pStmt,NULL);
for (int i = 0; i < dataset_length; i++) {
sqlite3_bind_int(pStmt,1,dataset[i].value1);
sqlite3_bind_int(pStmt,2,dataset[i].value2);
switch (sqlite3_step(pStmt)) {
case SQLITE_ROW: {
// Nice! A row has been inserted.
dataset[i].id = sqlite3_column_int(pStmt,0);
} break;
case SQLITE_DONE: {
// No results. What? Return an error.
} return false;
default: {
// Return an error
} return false;
}
// ↓ Problem below ↓
sqlite3_reset(pStmt);
}
//sqlite3_cleanup(pStmt); <- Don't worry about cleanups
return true;
sqlite3_step() always returns SQLITE_ROW and the RETURNING expression works.
If I do a SELECT before the sqlite3_reset(), it returns the freshly inserted row. If I prepare and run the same query after the sqlite3_reset(), my table is empty, the row is vanished.
I tried without the sqlite3_reset() and that works, but I don't understand why and think it's due to the auto-reset feature I OMIT in the Windows build.
Where I am wrong in my SQLite usage?
I finally find out where I was wrong. SQLite mandate to call sqlite_reset() only after receiving an error or SQLITE_DONE.
In my code I only generate a SQLITE_ROW, but I sqlite_reset() before getting a SQLITE_DONE and it cause SQLite to somewhat "reset" the statement and rolling back changes from my point of view.
The correct way is to after a SQLITE_ROW, to call sqlite_step() again that generate a SQLITE_DONE and then sqlite_reset(). That means :
// The way to SQLite with a RETURNING INSERT
for (...) {
// sqlite3_bind...()
sqlite3_step(); // Returns SQLITE_ROW
// sqlite3_column...()
sqlite3_step(); // Returns SQLITE_DONE
sqlite3_reset(); // Returns SQLITE_OK
}
Here is below my fixed code from my question :
sqlite3_stmt *pStmt;
sqlite3_prepare(db,"INSERT INTO table(col2,col3) VALUES (?,?) RETURNING col1;",-1,&pStmt,NULL);
for (int i = 0; i < dataset_length; i++) {
sqlite3_bind_int(pStmt,1,dataset[i].value1);
sqlite3_bind_int(pStmt,2,dataset[i].value2);
switch (sqlite3_step(pStmt)) {
case SQLITE_ROW: {
// Nice! A row has been inserted.
dataset[i].id = sqlite3_column_int(pStmt,0);
// Generate a SQLITE_DONE
if (sqlite3_step(pStmt) != SQLITE_DONE)
// Something went wrong, return an error
return false;
} break;
case SQLITE_DONE: {
// No results. What? Return an error.
} return false;
default: {
// Return an error
} return false;
}
sqlite3_reset(pStmt);
}
//sqlite3_cleanup(pStmt); <- Don't worry about cleanups
return true;
Of course my code imply that there is only 1 row returned by SQLite, adapt your code if SQLite returns more. The rule is that a sqlite_step() must returns a SQLITE_DONE before doing a sqlite_reset().

ServiceNow: Calling onSubmit in a callback function leads to infinite loop

Here I am comparing 2 variables for dates start_date and end_date and allowing to submit the form only in case end_date is bigger than start_date, else rejecting the form to be submitted, but while running this code, it goes into the infinite loop and if i make this asynchronous by using getXMLWait() instead of getXML(checkDateDiff) it's not supported with mobile api's.
Also there are lot of client script which help in comparing dates but none of them is supported with mobile apis.
Please have a look at the below code and help!!!!
function onSubmit() {
var requestType = g_form.getValue('request_type');
if (requestType == 'mifi') {
console.log("calling validateTravelEndDate()");
validateTravelEndDate();
return false;
} else
return true;
}
//Helper function which calls a AJAX script include called "ClientDateTimeUtils" which gives the response in a callback where i am deciding whether to submit the form or not based on the status of days result.
function validateTravelEndDate() {
var startDate = g_form.getValue('travel_start'); //First Date/Time field
var endDate = g_form.getValue('travel_end'); //Second Date/Time field
var dttype = 'day'; //this can be day, hour, minute, second. By default it will return seconds.
console.log("startDate :" + startDate + "endDate :" + endDate);
var ajax = new GlideAjax('ClientDateTimeUtils'); // This is the script include which can be used for date validation.
ajax.addParam('sysparm_name', 'getDateTimeDiff');
ajax.addParam('sysparm_fdt', startDate);
ajax.addParam('sysparm_sdt', endDate);
ajax.addParam('sysparm_difftype', dttype);
console.log("before " + g_form.getValue('travel_end'));
ajax.getXML(checkDateDiff);
}
// callback function where deciding to go ahead or not with form submission.
function checkDateDiff(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
console.log("difference in days:" + answer);
if (answer <= 0) {
alert("Travel End date must be after Travel Start date.");
g_form.setValue('travel_end', '');
g_form.showFieldMsg('travel_end', 'Please provide a future date', 'error');
return false;
} else {
console.log("%%%%%%%%%%%%%%% Calling g_form.submit()");
g_form.submit(); // This has some issue as it’s going in the infinite loop and if we just return true/false from here as it’s asynchronous call , it’s not handled by the onSubmit function
}
}
Your onSubmit() function always returns false for a mifi request. onSubmit() functions can execute a safer submit when they return a true. Also, g_form functions cannot be run in the callback function, since that is executed on the server.
Rather than have a g_form.submit() at the end of your checkDateDiff function, have onSubmit() function return true.
Something like this should work. I commented every line that I changed:
function onSubmit() {
var requestType = g_form.getValue('request_type');
if (requestType == 'mifi') {
console.log("calling validateTravelEndDate()");
// **CHANGED CODE: instead of g_form.submit(), this will return true
if(validateTravelEndDate()){
return true;
}
else{
return false;
}
} else
return true;
}
//Helper function which calls a AJAX script include called "ClientDateTimeUtils" which gives the response in a callback where i am deciding whether to submit the form or not based on the status of days result.
function validateTravelEndDate() {
var startDate = g_form.getValue('travel_start'); //First Date/Time field
var endDate = g_form.getValue('travel_end'); //Second Date/Time field
var dttype = 'day'; //this can be day, hour, minute, second. By default it will return seconds.
console.log("startDate :" + startDate + "endDate :" + endDate);
var ajax = new GlideAjax('ClientDateTimeUtils'); // This is the script include which can be used for date validation.
ajax.addParam('sysparm_name', 'getDateTimeDiff');
ajax.addParam('sysparm_fdt', startDate);
ajax.addParam('sysparm_sdt', endDate);
ajax.addParam('sysparm_difftype', dttype);
console.log("before " + g_form.getValue('travel_end'));
// **CHANGED CODE: validateTravelEndDate returns the callback value
return ajax.getXML(checkDateDiff);
}
// callback function where deciding to go ahead or not with form submission.
function checkDateDiff(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
console.log("difference in days:" + answer);
if (answer <= 0) {
alert("Travel End date must be after Travel Start date.");
g_form.setValue('travel_end', '');
g_form.showFieldMsg('travel_end', 'Please provide a future date', 'error');
return false;
}
else {
// **CHANGED CODE: checkDateDiff will return true
return true;
}
}

"Meteor code must always run within a Fiber" when using Meteor.runAsync

Using cassandra with meteor.
let client = new cassandra.Client({contactPoints: [cassandraHost]});
var cassandraExecSync = Meteor.wrapAsync(client.execute, client);
MyProject.Feed.CassandraMeteorWrap = {
insertNewPost: function (userId, postContentJson, relevance) {
var insertCommand = insert(userId, postContentJson, relevance);
try {
return cassandraExecSync(insertCommand);
} catch (err) {
console.log("error inserting: " + insertCommand);
console.log(err);
}
}
So I wrapped Cassandra.client.execute (which has last arg as callback) with Meteor.wrapAsync
The first few inserts work, but after a few inserts (the insert is being called periodically) I get a:
[Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.]
Update: Debug meteor showed the stack trace and the exception starts from the npm package I use "cassandra-driver" on the .onTimeout():
function listOnTimeout() {
var msecs = this.msecs;
var list = this;
debug('timeout callback ' + msecs);
var now = Timer.now();
debug('now: %d', now);
var first;
while (first = L.peek(list)) {
// If the previous iteration caused a timer to be added,
// update the value of "now" so that timing computations are
// done correctly. See test/simple/test-timers-blocking-callback.js
// for more information.
if (now < first._monotonicStartTime) {
now = Timer.now();
debug('now: %d', now);
}
var diff = now - first._monotonicStartTime;
if (diff < msecs) {
list.start(msecs - diff, 0);
debug(msecs + ' list wait because diff is ' + diff);
return;
} else {
L.remove(first);
assert(first !== L.peek(list));
if (!first._onTimeout) continue;
// v0.4 compatibility: if the timer callback throws and the
// domain or uncaughtException handler ignore the exception,
// other timers that expire on this tick should still run.
//
// https://github.com/joyent/node/issues/2631
var domain = first.domain;
if (domain && domain._disposed) continue;
try {
if (domain)
domain.enter();
var threw = true;
**first._onTimeout();**
if (domain)
domain.exit();
threw = false;
} finally {
if (threw) {
// We need to continue processing after domain error handling
// is complete, but not by using whatever domain was left over
// when the timeout threw its exception.
var oldDomain = process.domain;
process.domain = null;
process.nextTick(function() {
list.ontimeout();
});
process.domain = oldDomain;
}
}
}
}
debug(msecs + ' list empty');
assert(L.isEmpty(list));
list.close();
delete lists[msecs];
}

cleaning repeated code that uses return

I have many functions (funcOne, funcTwo, etc.), all of them share the same block of checks at the beginning (I want to move those blocks to a separate function or something so I'm not repeating code, but the problem is that I use return. Please read on)
If any of these checks fail, I output a specific message that this specific check failed, and return (so the actual code of the function doesn't execute)
If all checks pass, the function continues to the specific code of the function.
What I want to do is move those checks to a separate function. But the problem is that I'm using return; which would return out of the new function, but wouldn't return from funcOne and funcTwo. Can someone help me refactor this code so I don't have to repeat the duplicate checks in every function that uses them.
protected function funcOne(event:MouseEvent):void
{
if( check 1 doesn't pass){
Alert.show("error 1, returning);
return;
}
if( check 2 doesn't pass){
Alert.show("error 2, returning);
return;
}
.... more checks here, all of them return specific messages
//if all checks pass
//execute the specific code of this funcOne
}
protected function funcTwo(event:MouseEvent):void
{
if( check 1 doesn't pass){
Alert.show("error 1, returning);
return;
}
if( check 2 doesn't pass){
Alert.show("error 2, returning);
return;
}
.... more checks here, all of them return specific messages
//if all checks pass
//execute the specific code of this funcTwo
}
protected function funcOne(event:MouseEvent):void
{
if( !checkAll(event) ){
return;
}
//if all checks pass
//execute the specific code of this funcOne
}
protected function funcTwo(event:MouseEvent):void
{
if( !checkAll(event) ){
return;
}
//if all checks pass
//execute the specific code of this funcTwo
}
private function checkAll(event:MouseEvent):Boolean
{
if( check 1 doesn't pass){
Alert.show("error 1, returning);
return false;
}
if( check 2 doesn't pass){
Alert.show("error 2, returning);
return false;
}
return true;
}
You can build a string of errors in your error checking function, then return that string to your main function. If the string has contents, display it and break your program;
protected function funcOne(event:MouseEvent):void
{
errors = checkForErrors();
if( errors != null || errors != "" )
{
Alert.show( errors );
return;
}
}
protected function checkForErrors():String
{
var errorString:String = '';
if( check 1 doesn't pass){
errorString +="error 1\n";
}
if( check 2 doesn't pass){
errorString +="error 1\n";
{
return errorString;
}
Here's a quick way to do it. You could also return the actual message string if you want to handle the alert elsewhere. If the message string is null, then there's no error.
protected function funcOne(event:MouseEvent):void
{
if(validate())
{
//if all checks pass
//execute the specific code of this funcOne
}
}
protected function funcTwo(event:MouseEvent):void
{
if(validate())
{
//if all checks pass
//execute the specific code of this funcOne
}
}
//returns false if not valid
protected function validate():Boolean
{
var errorMessage:String = null;
if( check 1 doesn't pass)
errorMessage = "error 1, returning";
else if( check 2 doesn't pass)
errorMessage = "error 2, returning";
if(errorMessage)
Alert.show(errorMessage);
return !errorMessage as Boolean; //will return true if errorMessage is null
}

Enumerate the properties of an AS3 object that may or may not be dynamic

In order to send a POST request I need to enumerate all properties of a given object. This object may or may not be dynamic. I'm looking for the most elegant solution. This is what I've got so far:
function createURLVariables(params:Object):URLVariables
{
// Workaround: Flash Player performs a GET if no params are passed
params ||= {forcePost: true};
var vars:URLVariables = new URLVariables();
var propertyName:String;
var propertyList:XMLList = describeType(params)..variable;
var propertyListLength:int = propertyList.length();
// A dynamic object won't return properties in this fashion
if (propertyListLength > 0)
{
for (var i:int; i < propertyListLength; i++)
{
propertyName = propertyList[i].#name;
vars[propertyName] = params[propertyName];
}
}
else
{
for (propertyName in params)
vars[propertyName] = params[propertyName];
}
return vars;
}
One potential problem is that this won't return properties for getters (accessors).
I took the following approach in the as3corelib JSON Encoder. You'll have to modify this to suit your needs, but it should give you an idea to work from. Note that there is some recursion in here (the convertToString call, which you might not need:
/**
* Converts an object to it's JSON string equivalent
*
* #param o The object to convert
* #return The JSON string representation of <code>o</code>
*/
private function objectToString( o:Object ):String
{
// create a string to store the object's jsonstring value
var s:String = "";
// determine if o is a class instance or a plain object
var classInfo:XML = describeType( o );
if ( classInfo.#name.toString() == "Object" )
{
// the value of o[key] in the loop below - store this
// as a variable so we don't have to keep looking up o[key]
// when testing for valid values to convert
var value:Object;
// loop over the keys in the object and add their converted
// values to the string
for ( var key:String in o )
{
// assign value to a variable for quick lookup
value = o[key];
// don't add function's to the JSON string
if ( value is Function )
{
// skip this key and try another
continue;
}
// when the length is 0 we're adding the first item so
// no comma is necessary
if ( s.length > 0 ) {
// we've already added an item, so add the comma separator
s += ","
}
s += escapeString( key ) + ":" + convertToString( value );
}
}
else // o is a class instance
{
// Loop over all of the variables and accessors in the class and
// serialize them along with their values.
for each ( var v:XML in classInfo..*.(
name() == "variable"
||
(
name() == "accessor"
// Issue #116 - Make sure accessors are readable
&& attribute( "access" ).charAt( 0 ) == "r" )
) )
{
// Issue #110 - If [Transient] metadata exists, then we should skip
if ( v.metadata && v.metadata.( #name == "Transient" ).length() > 0 )
{
continue;
}
// When the length is 0 we're adding the first item so
// no comma is necessary
if ( s.length > 0 ) {
// We've already added an item, so add the comma separator
s += ","
}
s += escapeString( v.#name.toString() ) + ":"
+ convertToString( o[ v.#name ] );
}
}
return "{" + s + "}";
}

Resources