PhoneGap + SQLite Issues - sqlite

For some reason, the following code doesn't work:
var users = window.SQLitePlugin.openDatabase("users","1.0","Demo",-1);
users.transaction(function(tx){
KovarApp.lib.say("Transaction Started");
var createString = "CREATE TABLE IF NOT EXISTS 'users' ('id' integer(11) primary key, 'username' varchar(25),'password' varchar(100),'firstname' varchar(25),'lastname' varchar(25),'qdatabase' varchar(20),'ugroup' varchar(50),'status' varchar(50))";
tx.executeSql(createString,[],function(tx,res){
KovarApp.lib.say("Create Worked");
},function(){
KovarApp.lib.say("Create Failed");
});
var insertString = "INSERT INTO users (username,password,firstname,lastname,qdatabase,ugroup,status) values ('jktest','e10adc3949ba59abbe56e057f20f883e','Andrew','Rhyne','basictemplate','admin','yes')";
tx.executeSql(insertString,[],function(tx,res){
KovarApp.lib.say("Insert Worked");
},function(){
KovarApp.lib.say("Insert Failed");
});
var testString = "SELECT 1 FROM users WHERE username = 'jktest'";
tx.executeSql(testString,[],function(tx,res){
KovarApp.lib.say("res.rows.length: " + res.rows.length + " -- should be 1");
});
KovarApp.lib.say('Transaction Ended');
});
My log function spits out transaction started and transaction ended, but the callbacks aren't firing for the individual queries. I am using Brody's sqlite3 plugin: https://github.com/brodyspark/PhoneGap-SQLitePlugin-Android
Any help here would be awesome. I don't really know what I am doing wrong but it isn't working at all. As a side note, he has specified that there isn't any limit on database size, and this is denoted by the -1 (meaning no size limit).

All callback functions are executed asynchronously.
In your code, the insert/select commands are started before the previous commands have finished, and the transaction ends before the individual commands have finished.
Move the code to start a command into the success callback function of the previous command.
In other words, the transaction and executeSql calls should always be the last statement in their containing function.

The Javascript files within Brody's project are platform-dependent for the time being. It looks like there will eventually be abstraction in place where the javascript is all portable, but this was the issue - I had the iOS version of the JS file running on Android. Duhh

Related

TypeOrm QueryBuilder dynamic auto delete function with crons job not working

Token for email verification is created with User registration and needs to be deleted from database within 24 hours with crons job help. In a delete function using query builder, token gets deleted only if date value is manually provided in form of string: {delDate: "2021-02-08T17:59:48.485Z" }. Here, all tokens with date before or equal 2021-02-08 get deleted, and is working fine. But thats a static input, manually put in hard code!
Since this must be a dynamic input, I set up variable 'delTime',which stores current date minus 24 hrs in it, but it seems .where condition will not take a variable as value, and will not delete, as: {delDate: deltime}. In fact, 'delDate' consoles exactly the info I need, but it will only work in form of string.
There is a ton of content online teaching how to delete stuff with a static value in typeorm querybuilder, but so hard to find with dynamic values....
How else can I make this work in a dynamic way ?
async delete(req: Request, res: Response){
try {
const tokenRepository = getRepository(Token);
var delTime = new Date();
delTime.setDate( delTime.getDate() - 1 );
console.log(delTime) //consoles 24 hors ago
await tokenRepository
.createQueryBuilder()
.delete()
.from(Token)
.where("tokenDate <= :deleteTime", { deleteTime: delTime})//value dynamically stored in variable does not delete
//.where("tokenDate <= :deleteTime", { deleteTime: "2021-02-08T18:01:10.489Z"})//static hard code value deletes
//.where("tokenDate <= :delTime", { delTime})//Variable put this way will not work either...
.execute();
} catch (error) {
res.status(404).send("Tokens not found");
return;
}
res.status(200).send('Tokens deleted successfuly');
}
Your parameterized query looks correct.
Switch on TypeOrm Query Logging to see the generated SQL, maybe you will be able to see what's going wrong. Paste the generated SQL into the SQL query console to debug.
Alternatively you can write your delete query without parameters and let Sqlite calculate current date -1 day:
.where("tokenDate <= DateTime('Now', '-1 Day'"); // for Sqlite
Note 1: Sqlite DateTime('Now') uses UTC time, so your tokenDate should use UTC also.
Note 2: This syntax is specific to Sqlite, you can do the same in other databases but the syntax is different, e.g. Microsoft SQL Server:
.where("tokenDate <= DATEADD(day, -1, SYSUTCDATETIME()); // for MS SQL Server

Ingest from storage with persistDetails = true not save ingest status result

I'm now implement a program to migrate large amount of data to ADX base on Ingest from Storage feature of ADX and I'm need to check that status of each ingestion request each time the request finish but I'm facing an issue
Base on MS document in here
If I set the persistDetails = true for example with the command below it must save the ingestion status but currently this setting seem not work (with or without it)
.ingest async into table MigrateTable
(
h'correct blob url link'
)
with (
jsonMappingReference = 'table_mapping',
format = 'json',
persistDetails = true
)
Above command will return an OperationId and when I using it to check export status when the ingest task finish I always get this error message :
Error An admin command cannot be executed due to an invalid state: State='Operation 'DataIngestPull' does not persist its operation results' clientRequestId: KustoWebV2;
Can someone clarify for me what is the root cause relate to this? With me it seem like a bug relate to ADX
Ingesting data directly against the Data Engine, by running .ingest commands, is usually not recommended, compared to using Queued Ingestion (motivation included in the link). Using Kusto's ingestion client library allows you to track the ingestion status.
Some tools/services already do that for you, and you can consider using them directly. e.g. LightIngest, Azure Data Factory
If you don't follow option 1, you can still look for the state/status of your command using the operation ID you get when using the async keyword, by using .show operations
You can also use the client request ID to filter the result set of .show commands to view the state/status of your command.
If you're interested in looking specifically at failures, .show ingestion failures is also available for you.
The persistDetails option you specified in your .ingest command actually has no effect - as mentioned in the docs:
Not all control commands persist their results, and those that do usually do so by default on asynchronous executions only (using the async keyword). Please search the documentation for the specific command and check if it does (see, for example data export).
============ Update sample code follow suggestion from Yoni ========
Turn out, other member in my team mess up with access right with adx, after fixing it everything work fine
I just have one concern relate to PartiallySucceeded that need clarify from #yoni or someone have better knowledge relate to that
try
{
var ingestProps = new KustoQueuedIngestionProperties(model.DatabaseName, model.IngestTableName)
{
ReportLevel = IngestionReportLevel.FailuresAndSuccesses,
ReportMethod = IngestionReportMethod.Table,
FlushImmediately = true,
JSONMappingReference = model.IngestMappingName,
AdditionalProperties = new Dictionary<string, string>
{
{"jsonMappingReference",$"{model.IngestMappingName}" },
{ "format","json"}
}
};
var sourceId = Guid.NewGuid();
var clientResult = await IngestClient.IngestFromStorageAsync(model.FileBlobUrl, ingestProps, new StorageSourceOptions
{
DeleteSourceOnSuccess = true,
SourceId = sourceId
});
var ingestionStatus = clientResult.GetIngestionStatusBySourceId(sourceId);
while (ingestionStatus.Status == Status.Pending)
{
await Task.Delay(WaitingInterval);
ingestionStatus = clientResult.GetIngestionStatusBySourceId(sourceId);
}
if (ingestionStatus.Status == Status.Succeeded)
{
return true;
}
LogUtils.TraceError(_logger, $"Error when ingest blob file events, error: {ingestionStatus.ErrorCode.FastGetDescription()}");
return false;
}
catch (Exception e)
{
return false;
}

Fire an action once a transaction ends

I'm using Stephen Celis iOS lib for handling SQLite3 databases, here is the github link.
Taking the example on the git :
try db.transaction {
let rowid = try db.run(users.insert(email <- "betty#icloud.com"))
try db.run(users.insert(email <- "cathy#icloud.com", managerId <- rowid))
}
// BEGIN DEFERRED TRANSACTION
// INSERT INTO "users" ("email") VALUES ('betty#icloud.com')
// INSERT INTO "users" ("email", "manager_id") VALUES ('cathy#icloud.com', 2)
// COMMIT TRANSACTION
I tried to implement the commitHook block but it is fired for each insert. I'd like to fire an action only when all the requests are sent :-D
What should I do ?
Cheers
Edit :
Here is how I implemented the commit hook.
for bay in list{
try! self.themanager.db.transaction {
try! self.themanager.db.run(self.themanager.bays.insert(
//insert values
))
self.themanager.db.commitHook({
print("end commit hook")
})
}
}
Maybe it's related to my main loop :/
From SQLite TRIGGER docs:
At this time SQLite supports only FOR EACH ROW triggers, not FOR EACH STATEMENT triggers. Hence explicitly specifying FOR EACH ROW is optional. FOR EACH ROW implies that the SQL statements specified in the trigger may be executed (depending on the WHEN clause) for each database row being inserted, updated or deleted by the statement causing the trigger to fire.
Commit hooks work like triggers. Unfortunately, the "FOR EACH STATEMENT" behavior is not supported yet.

How do you ensure an update has finished in meteor before running a find?

I have a fairly typical need, to ensure an insert / update has finished before I run a find. The code goes something like this:
//Update my collections
Messages.insert({author:_id,text:text});
Authors.update({_id:_id},{$inc:{messages:1}});
//Wait until the update / insert has finished
//Perform some actions on the collections just updated
var author = Authors.findOne({task:taskId},{sort:{'messages':1}});
//Do some more complex stuff...
While in most cases this would be fine as asynchronous calls, with the dom updating as and when things complete, in my case it is essential that the insert and update have completed before I run the function call.
Do I need to perform the insert and update as a server side call with a callback function, or is there some way I could do this on the client side?
At the moment I have something like:
Meteor.call("recordMessage", _id, text,
function(err, out){postMessage(_id)}
);
which works - but I'd like to know if I could do this on the client side.
Isn't that what the optional callback arguments are for?
var author;
Messages.insert({author:_id, text:text},
function(err, result) {
Authors.update({_id: result},
{$inc: {messages:1}},
function(err, result) {
author = Authors.findOne({task:taskId},
{sort:{'messages':1}});
}
);
});

Meteor insert into collection appears to work, but remains empty

I'm doing a simple insert into a meteor collection that appears work, but leaves the collection empty.
The collection is defined properly on the server:
Meteor.publish("comments", function () {
return Comments.find();
});
Subscribed to properly in the client.js:
Meteor.subscribe("commments");
And set up properly on the model.js:
Comments = new Meteor.Collection("comments");
The insert code is as follows:
Meteor.methods({
addComment: function (options) {
check(options.post_id, String);
check(options.comment, NonEmptyString);
if (! this.userId)
throw new Meteor.Error(403, "You must be logged in to comment.");
if (options.comment.length > 1000)
throw new Meteor.Error(413, "Comment is too long");
var post = Posts.findOne(options.post_id);
if (! post)
throw new Meteor.Error(404, "No such post");
// add new comment
var timestamp = (new Date()).getTime();
console.log('Comment: ' + options.comment);
console.log('Post: ' + options.post_id);
console.log('UserId: ' + this.userId);
var saved = Comments.insert({
owner: this.userId,
post_id: options.post_id,
timestamp: timestamp,
text: options.comment});
console.log('Saved: ' + saved);
}
});
Once the insert is called, the console prints out the following:
Comment: Something
Post: xRjqaBBEMa6qjGnDm
UserId: SCz9e6zrpcQrKXYWX
Saved: FCxww9GsrDsjFQAGF
> Comments.find().count()
0
I have inserts into several other collections that work just fine (Posts being one of them as you can see the post ID in the code). In the docs ist said that if the insert errors out it will print to the console, but as you can see it appears to be working, yet is actually empty.
Thanks.
UPDATE: I did find that the data is being put into the database, but for some reason is not showing up. I'm not sure why the data is not being published properly since there are no filters on the find().
I'm not sure exactly what's wrong, but there's a few things to check here.
• First, this:
Meteor.publish("comments", function () {
return Comments.find();
});
directs the server to publish the Collection, but doesn't actually establish the collection server side.
You should have Comments = new Meteor.Collection("comments"); available on both the client and the server. I tend to put in a file called model.js like the examples tend to do.
• Second possibility, you don't have a subscribe function shown above, such as Meteor.subscribe("comments"); If you don't have a subscribe function, your client isn't going to know about it, even though it does exist in the collection.
You can test this theory by typing meteor mongo in the shell (with your Meteor app running), and db.comments.find() to see if your comments are actually in the database but not subscribed to.
Verify you do not have an error in your client code. With Meteor.call, if you do not initialize a variable you can have an error condition that will block reactive updating in your templates but continue to write fine to your console just before hand.
I've made that mistake which I talk about here:
http://doctormehmet.blogspot.com/2013/07/revoltdc-hackathon-20130622-iteration-3.html
Specifically I had something like
Template.mytemplate.helpers({
somevar: function({
if (some_session_var_set_by_a_call.party){
//do something
}
}
Now the somevar function gets called on render, before the Meteor.call returns. Therefore the variable some_session_var_set_by_a_call isn't set yet. The whole thing stops client side on the undefined error.

Resources