Postgres JSON function passed string instead of object - javascript

So I've got a Postgres function in place designed to merge two JSONB objects recursively, and it works just fine on the production server but fails on my local Postgres installation. The function itself is written in plv8 (a v8 Javascript engine basically) and expects two arguments in JSONB format to merge; the problem is that the JSON is passed in as a string and not as an object, which essentially breaks the entire function.
This only happens on my local computer though, a fresh Postgres 9.4.5 installation. The production server is running 9.4.4, which shouldn't cause such a major change across versions...ideas on where to go to see what's broken here?
EDIT: Can now confirm that reverting to 9.4.4 doesn't make this behave any differently locally

Hard to say. Possibilities:
Different casts - you can define custom casts - CREATE CAST statement - try to check result of psql command \dC *json*
New bug introduced in 9.4.5

FWIW, upgrading to 9.5 seems to solve instances of this issue for me.

Related

Why the same mongodb query behaves inconsistently between different client?

firstly, let's take this simple query as example:
ObjectId('62663def4e578b0a1cb482c5').valueOf();
output in DataGrip v2021.3.1:
{"$oid": "62663def4e578b0a1cb482c5"}
output in Navicat for MongoDB v16.0.14:
62663def4e578b0a1cb482c5
output in mongosh 1.5.0:
ObjectId("62663def4e578b0a1cb482c5")
secondly, with typeof operator, i.e.:
typeof ObjectId('62663def4e578b0a1cb482c5').valueOf();, we can see the data type of the output. they are object in both DataGrip and Mongosh but string in Navicat for MongoDb.
This is an obvious issue and problematic when developers write complex queries, I believe there must be tickets raised for similar issue(but i haven't found one).
Why it it like this? It could be due to different mongoDB driver version integrated in each client but I searched around and haven't found any solid official documents. Could anyone help on this?
mongosh and MongoDB JDBC driver that is used in DataGrip have the same core so they should be very similar (and your examples show that. {"$oid": "62663def4e578b0a1cb482c5"} is just json representation of ObjectId type).
I don't remember what Navicat uses. I might guess that they have a wrapper for MongoDB NodeJS driver or they directly use old shell called mongo.
I would say that mongosh should have the most correct behaviour since it's a new shell that was developed very recently. If you think that this behaviour is incorrect try to create an issue in mongosh issue tracker https://jira.mongodb.org/projects/MONGOSH/issues/
If you think that behaviour of Navicat is incorrect, try to create an issue in their bug tracker

javascript localeCompare return different value on browser as comparing to my local testing

I have the following code executed:
var eng = 'image'
var chinese = '影像'
console.log(eng.localeCompare(chinese),"zh-hant")
on my browser console, the result is 1
But when I run npm test to execute the above code, the result is -1
My questions are:
What makes the code return different value?
How can I fix this unstable code?
I think you are trying to compare english language with chinese one. So, I suggest, you should use Collator when needed. Most modern browsers are supporting it
Collator will sort in almost any language you can think of and has numerous options for customizing sorting by accent marks, capitalization, etc.
This compare link can help you understand how to compare non-english strings in Javascript
The one you run in a browser (say Chrome) has better i18n support. And when you run it with npm test, you are dealing with node.js, most likely a version prior to v13, with which only the locale data for en-US is available by default.
Meaning the option you passed to localeCompare, in your case, "zh-hant", silently falls back to en-US, leading to the different behavior in your question.
Source: Browser compatibility MDN
The fix?
The easy path
Upgrade your node.js to a version later than v13. Then you have full ICU (locale) data available, meaning you will have the same result with the browser.
The hard option:
If the upgrade is not an option, you will need to do this the hard way. Here are some links to start:
Here you can install full icu
https://github.com/unicode-org/full-icu-npm
Provide icu data at run time https://nodejs.org/docs/latest/api/intl.html#intl_providing_icu_data_at_runtime

Logging a JSON object in firebase console

Does anyone know how to log JSON data in a readable manner to the firebase logs? When using:
console.log(req.body)
or
console.log(`${req.body.event}: ${JSON.stringify(req.body, null, 2)}`);
it prints it as seen in the picture below on multiple lines.
My firebase cloud functions run on Node 10
You are supposed to use functions.logger.log() with Node version 10 and above. See: https://firebase.google.com/docs/functions/writing-and-viewing-logs
I can confirm I have the same problem, since the update to Node 10 JSON objects are printed in multiple lines.
For now the solution is to import this dependency:
require('firebase-functions/lib/logger/compat');
Just put this at the top of your functions code.
You can check the official issue for updates: https://github.com/firebase/firebase-functions/issues/612
This multi-line behavior is likely due to the fact that you explicitly tell JSON.stringify() to add line breaks and indentation. The last parameter (2) tells JSON formatter that you want "structured" (aka "pretty") output with 2 spaces per indentation level. If you drop the last argument (you may safely drop "null" as well), then you should see good old one long string :)
FWIW, I don't see this logging behavior when using NodeJS 8 on my Firebase Functions. So something changed with Node 10 on the Firebase side...
Also check this GitHub issue: https://github.com/firebase/firebase-functions/issues/612

Run a function in javascript when an array is being "written" or "read"

I have an array (actually the database data from alasql on github), and I want to run a function when it is "written" or "read" in script.
"written" stands for push, pull and Assignment operator like =,
While "read" stands for direct access to the array value like array (whole array), array[0] (an element of the array) etc., and reading properties like array.length
Actually I use those function for accessing the localStorage.
I have already read this stackoverflow question but I still don't have my own solution since I have a few restrictions here.
I have to monitor not just push() but = so Override the push method does not work for me.
That array is actually created by the javascript library alasql and I am not going to change the library code since it can be a big big task, so Create a custom observable array is not possible.
The library access the array directly for SQL statements as the store the data of the SQL table, so it is impossible to use proxy.
My script is going to run on a firefox on a slow computer running xp bought at least 10 years ago with hardware like < 1GB RAM and single-core CPU, and the array which is actually the SQL table will have entries like 10000 entries, hence the array is performance required. If I use library like underscore-observe on github, which relies on scanning every 250ms, that dumb computer will simply die.
Use smart-collection on github. Well, I actually don't know what does that answer and the readme on github talking about, but I don't think it will works since I have to create another array for it (?)
Use localStorage engine of alasql on github readme, fine, this could be the best one initially and I tried it. But I decided to left it when I found a bug of it which block my work.
I would be glad if someone can give me a solution on how to do the trick, since it is a main and big issue in my project so far.
P.S.: My project is to develop a single HTML page that run a POS-like system with sell and borrow functionality with SQL, and It is going to run in a dumb old computer without internet connection.

How do you encode an Object in a Web Worker for it to be passed via postMessage?

Internally, Firefox will JSON encode an object passed via postMessage to and from the Web Worker. However, this only works in Trunk builds of Firefox (3.6+) and not in Firefox 3.5, so the question is really how to add backwards support of this operation to the current platform. The window.atob() and window.btoa() methods had been suggested before, but alas these are not available internally to the threads because they don't have access to the DOM.
Mozilla publicly states this on their developer wiki, but it has been noticed by many in the community that this happens. Check ejohn's blog test: http://ejohn.org/files/bugs/postMessage/
I've verified that this is the case as well, in 3.5, it passes only strings, and in 3.6 is will pass the object.
I haven't noticed the automatic JSON-encoding not working in Firefox 3.5, but I've mainly been working with Gears, which doesn't support it anyway.
Try including a JSON utility in both the worker script and the parent script, then manually encode and decode it yourself. This works fairly well for me with Gears.
This approach shouldn't break when Firefox begins automatically doing the JSON encoding for you, since the encoded JSON string will remain a string.
In JavaScript there are two functions respectively for decoding and encoding base64 strings:
atob()
btoa()
I found the solution to my own problem!
It seems that if the thread variable, even if declared globally, loses its .onmessage property if that said property was declared inside another function. If the property is instantiated on the global scope, then JSON messages are parsed correctly.
I'm still not sure I understand what's going on here, but at least I've figured out a way to pass objects around without having to rely on any additional stingify/json libraries.
If anyone could explain this to me so I have a better understanding, it would be appreciated :)
I setup a test case here: http://x.miernicki.com/ which logs the inter-thread messages to the firebug console if anyone cares. This helped me to get objects passed around in Fox3.5 and ultimately allowed me to see what the problem was.
Since you are clearly looking for a FF-only solution, have you tried yourObject.toSource()?

Categories