set timezone in pg-promise only once per client - postgresql

I have a timestamp with timezone column in postgressql, named created , that the data are saved in UTC.
I am using pg-promise 8.4.4 and I want to select the data, but set a different timezone for every client.
The logic is that my angular app uses the node.js endpoints as an api and I guess I can set the timezone while creating a DB connection, but that would be good just for my app.
What if another app, from another timezone, wants to hit the same node endpoint? How can they set the timezone?
So, in SQL I can do something like
set timezone to 'europe/athens';
select created from table;
But, how do I do this in pg-promise, for different clients?
I could do something like
cmsuser.generalQuery(`select firstname, created AT TIME ZONE '+02' from table WHERE AND activated = $1 ORDER BY created`, [true])
.then((resolved)=>{
res.json({success:true, activated:resolved});
})
and make the +02 part dynamic?
The cmsuser.generalQuery is
const generalQuery = (text, params) => {
const s = pgp.as.format(text, params);
return db.any(s)
}
There are two problems with this approach right now
-1- With the above query, without having the timezone part as dynamic, I get the firstname, but not the created, that is the date. No errors in the console.
-2- Setting the timezone per query is not a smart thing to do.
What can I do here?
Thank you

Related

MS-Access, Continuous form of multiple clients - Form.Text field containing Last Communication for Each Client / Customer in List

I am a First time user of StackOverFlow here!
I have been trying to figure this out for two days and have come up short.
We have a form that displays every single Client / Customer that we have at the firm, in a continuous form view.
We want to be able to display on this form the date, for each client, when we last communicated, or called, the client. (We want to be sure that we prevent a situation where we have not called a client for more than 1.5 months).
I have a query on a table tracking our correspondence, and other activities, regarding our clients that, in SQL, looks like:
' Query ContactCommunications
SELECT Context, ID, NoteDate, ContactID
FROM Comments
WHERE (((Context)="Communication with Client" Or (Context)="Phone Call with Client"));
(ContactID is a secondary key for Contacts table - we are tracking not
only clients but also opposing parties and such)
This is intended to show all the dates we called or communicated with our clients.
I have a second query that then gets the Last Date from this table, grouped by ContactID, which looks like:
' Query qryLastCommunicationAgg
SELECT ContactID, Last(CommentDate) AS LastOfCommentDate
FROM Comments INNER JOIN qryContactCommunications
ON Comments.ID = qryContactCommunications.ID
GROUP BY Comments.ContactID;
My question is how do I get the query result (When we last called each client) into a text field in our Continuous form list? At the moment there will be some null values as well.
I have tried the expression:
=DLookUp("CommentDate","qryLastCommunicationAgg",[ID]=[ContactID])
But it does not work, giving me #Name?
Not sure what I did wrong. :-(
I appreciate greatly any assistance or suggestions!
-Glenn
First, use Max:
SELECT ContactID, Max(CommentDate) AS LastOfCommentDate
Then try with:
=DLookUp("LastCommentDate","qryLastCommunicationAgg","[ID]=" & [ContactID] & "")
("Below is the fixed version of the DLookup script - Glenn")
=DLookUp("LastOfCommentDate","qryLastCommunicationAgg","[ContactID]=" & [ID] & "")

grails 3.3.x java.sql.Date property is type-mismatched

In my domain class, I have something like this:
class User {
String name
java.sql.Date birthDate
}
I am getting the app working with scaffolding, and the scaffolded creation pages correctly show the d/m/y drop down date picker to specify the date, which is very good.
But when I hit the "Create" button, it gives:
Property birthDate is type-mismatched"
I am using the built in H2 DB currently, but will switch to MySQL later.
Any suggestions? I don't want to use the normal date/time as I only need the date, and it must not be affected by time zones. Obviously I could manually store the day, month and year fields separately, but this makes it harder to use later (e.g. for comparison).
We had a trick to get this working with Grails 2.x, but I don't have a copy of this old code.
Does anyone have a workaround for getting this working with the fields plugins?
In my update controller method, even if I manually set user.birthDate to a correct java.sql.Date instance, calling user.save() still fails with the type-missmatch error. It seems to be something in the save() method, which is presumably GORM code.

How to have SQL and database createdAt dates match exactly?

I have an app which includes a functionality which allows users to send messages to one another. The process for sending the message involves saving the sent message to the sender's internal SQL database while at the same time saving the message to the overall app's database, which is a parse-server (and then actually send the message via push notifications to the recipient). What I am concerned about is with the discrepancy that is bound to arise between the 'createdAt' parameter for the message in the database and the same parameter for that message in the SQL database. The reason for the perceived discrepancy is because I have it set up as follows:
import Parse
func sendMessage(){
let newMessage = newMessage(messageString: "Hi", createdAt: Date())
//drop the newMessage into the SQL table... will save the Date() as a String at time A
let newMessageToDB = PFObject(className: "messages")
newMessageToDB["messageString"] = newMessage.messageString
//parse-server will automatically give the object a "createdAt" parameter when saved
newMessageToDB.saveInBackground()
//Since this is created automatically, the value will be the exact moment
//the object is saved to the DB, at time B
}
Since the createdAt value for SQL is created by Date(), this value is set at time A. The createdAt for the database is created by the completion of the async function saveInBackground() and will therefore be saved at time B. With this method, I can in no way guarantee that time A = time B. This creates the problem that for the recipient the time of the message will be time B from the database (which will be put into their SQL table with time B), while, for the sender, the time of the message will be time A.
My question:
1. First and foremost, does this discrepancy even matter? The entire explanation of the problem might be irrelevant if this difference doesn't actually create any issues.
2. If it is relevant and may cause issues, how do I fix it? I know I can send it to the server, and then read the value back immediately after it is created to get the database's 'createdAt' to be saved in the SQL statement, but is that inefficient? To save an object, then immediately read it back from the DB to extract a value?

How to know if the CloudKit Zone exists already

To add a CKRecord in a private CKRecordZone you need to make sure the zone exists already.
But does it mean that every time I need to insert a record I need to fetch all the zones and find if my zone exists using fetchAllRecordZonesWithCompletionHandler ? It wouldn't be very efficient.
What is the best strategy to adopt ?
Most of the examples I have seen show how to create a zone and add a record into it. But you are not going to create the zone every time, and you can't just assume it exists...
Code below will fail if the zone has not been created already
let customZone = CKRecordZone(zoneName: self.zoneName!)
// Create a CKRecord
let lessonRecord = CKRecord(recordType: self.recordType, zoneID: customZone.zoneID)
Thanks for your help.
To see if a specific zone exists, use CKFetchRecordZonesOperation and pass just the one record zone ID.
You only need to do this once if your code is setup properly.
Create a class that represents a record zone. This class should perform all of the CloudKit operations for a given zone. When you initialize an instance of this class for a specific zone, you can check to see if the zone exists. If not, then create the zone. Then you use that specific instance of this zone helper class each time you need to read or write data to that zone.
Of course every read and write operation needs to check error results to check for CKErrorZoneNotFound errors. Getting such an error probably means the zone was deleted from another copy of the app.

Mobile Services Offline PullAsync only retrieves data where updatedAt date > the latest record

I am using offline data sync in Mobile Services and the following function only retrieves data where UpdatedAt > the largest updatedAt in the userTable:
await userTable.PullAsync(userTable.Where(a => a.UserName == userName));
The first time this function is executed, it retrieves my data correctly. The second time the function executes, whith a different username, it will only retrieve data where UpdatedAt is greater than the greatest UpdatedAt datetime that is already present in my SQLite db. If I change an UpdatedAt field in the backend (by setting it to DateTime.Now), this record is retrieved. Is this by design or am I missing something?
For anybody else having issues with this: I have started another thread here where you will find the complete answer
Basically what it comes down to is this:
This will retrieve all records from the backend where username is donna:
await itemTable.PullAsync(itemTable.Where(a => a.UserName == "donna"));
This will retrieve all records where username is "donna" the first time, and after that only updated records. (incremental)
await itemTable.PullAsync("itemtabledonna", itemTable.Where(a => a.UserName == "donna"));
The first parameter is the queryKey. This is used to track your requests to the backend. A very important thing to know is that there is a restriction on this queryKey:
^[a-zA-Z][a-zA-Z0-9]{0,24}$
Meaning: alphanumeric characters, max 25 characters long. So no hyphens either (at the time of this writing). If your queryKey does not match this regex, no recrods will be returned. There is currently no exception thrown and no documentation on this.
PullAsync() is supposed to use an incremental sync (getting only records what have a newer date than the last record it retrieved) when you pass in a query key. If not, it should execute your query and pull down all matching records.
It sounds like a bug is occurring if you are getting that behavior without passing in a query key.
Also, in the incremental sync case, it is not the latest updated at in the SQLite DB but a cached version from the last time PullAsync() was ran (that was cached under the given query key)
Your updatedAt column also by default will have a trigger that causes its timestamp to update whenever the row is modified, so you shouldn't have to take any additional actions when using incremental sync.
If the above is not what you are seeing, I recommend submitting a github bug against azure-mobile-services so it can be reviewed.