pg-promise, format with json-object - javascript

From pg-promise's example, one can format a query like below, where ${this~} becomes all of the keys in the object that is the second parameter of "format()".
// automatically list object properties as sql names:
format('INSERT INTO table(${this~}) VALUES(${one}, ${two})', {
one: 1,
two: 2
});
//=> INSERT INTO table("one","two") VALUES(1, 2)
Is it possible to also get all of the values of the object, without explicitly typing all of them? I want to do it like below (should do the same thing as the snippet above, but without typing all of the values):
format('INSERT INTO table(${this~}) VALUES(${this#})', {
one: 1,
two: 2
});

Is it possible to also get all of the values of the object, without explicitly typing all of them?
No, it is not possible, because while column names require the same-type SQL Name escaping, values do not, they require templating that's possible only via explicitly defined variables.
I want to do it like below...
For that you should use the helpers methods of the library:
const cs = new pgp.helpers.ColumnSet(['one', 'two'], {table: 'my-table'});
const query = pgp.helpers.insert(values, cs);

Related

giving a different value to a variable on each different value from a JavaScript array

I have a JS array with more than a million entries.
I want JavaScript to assign a specific color to flag on every different value from the array
say that my Array contains this:
var foo = new Array([10,20,30,40,50,36,60,70,80,90,100]);
It is worth knowing that my array contains 58 different values.
I am trying to do something like this:
if (foo.every(10)) flag = "red";
if (foo.every(20)) flag = "yellow";
I need a way to do it for all the values in the array without having to repeat the line above 58 times.
note that I know that the flag will be overridden and the flag in my code is unique for every different value.
Also note that the array is imported as JSON data from a MySQL table using PHP, so any PHP approaches to this problem will also be appreciated.
Easy JS solution:
var numberToColorDictionary = {
10: "red",
20: "yellow"
...
}
// After this runs, 'flags' should contain all the right flags.
var flags = foo.map(function(number) {
return numberToColorDictionary[number];
});
Although, this does sound like you're querying your database wrong. If the numbers are ids from MySQL, you should use join to get the correct flags.
And by the way, you don't need the new Array syntax. just do:
var foo = [10,20,30,40,50,36,60,70,80,90,100];

'default' option in pgp.as.format()

I need to format SQL query with default option for missing object fields. I can do it with an external call to pgp.as.format:
let formattedQuery = pgp.as.format('INSERT INTO some_table (a,b,c) VALUES ($(a), $(b), $(c))', object, {default: null});
db.none(formattedQuery);
Is it possible to pass default option directly without pre-formatting the query? Basically, i would like to do something like this:
db.none('INSERT INTO some_table (a,b,c) VALUES ($(a), $(b), $(c))', object, {default: null})
I'm the author of pg-promise.
All query methods in pg-promise rely on the default query formatting, for better reliability, i.e. when a query template refers to a property, the property must exist, or else an error is thrown. It is logical to keep it that way, because a query cannot execute correctly while having properties in it that haven't been replaced with values.
Internally, the query engine does support advanced query formatting options, via method as.format, such as partial and default. And there are several objects in the library that make use of those options.
One in particular that you should use for generating inserts is helpers.insert, which can generate both single-insert and multi-insert queries. That method, along with even more useful helpers.update make use of type ColumnSet, which is highly configurable, supporting default values for missing properties (among other things), via type Column.
Using ColumnSet, you can specify a default value either for selective columns or for all of them.
For example, let's assume that column c may be missing, in which case we want to set it to null:
var pgp = require('pg-promise')({
capSQL: true // to capitalize all generated SQL
});
// declaring a reusable ColumnSet object:
var csInsert = new pgp.helpers.ColumnSet(['a', 'b',
{
name: 'c',
def: null
}
], {table: 'some_table'});
var data = {a:1, b:'text'};
// generating our insert query:
var insert = pgp.helpers.insert(data, csInsert);
//=> INSERT INTO "some_table"("a","b","c") VALUES(1,'text',null)
This makes it possible to generate multi-insert queries automatically:
var data = [{a:1, b:'text'}, {a:2, b:'hello'}];
// generating a multi-insert query:
var insert = pgp.helpers.insert(data, csInsert);
//=> INSERT INTO "some_table"("a","b","c") VALUES(1,'text',null),(2,'hello',null)
The same approach works nicely for single-update and multi-update queries.
In all, to your original question:
Is it possible to pass default option directly without pre-formatting the query?
No, and neither it should. Instead, you should use the aforementioned methods within the helpers namespace to generate correct queries. They are way more powerful and flexible ;)

How can I create an object or array of array data in JS with key named elements?

I have an array called values. At present, I'm appending new data to this array as such:
values.push(guests);
The result of my array is something like this:
["123456789", "Joe", "Bloggs", "Test Corp", "fiji", true, "guest, guest 2, guest 3", true]
I have now realised that in its present state this data is useless to me as I cannot tell what each element is. In my example above, the first long number is an account number and the second element is a first name but these are liable to change. E.g the company name Test Corp may not always exist in the data. This means I cannot use the numerical key [3] to target it because it may not be present.
Therefore I need to code this data into something that I can assign both a label for the data, and the data value. I'm guessing the best way to do this would be with an JSON object.
How can I create a key->value pair object? I would need to replace my .push() code above to instead add the value of COMPANY NAME -> Test Corp so that it can be deciphered later.
For reference, I am then stringifying this data and using an AJAX request to POST it to a PHP script where it will need to be arranged into variables e.g $company_name = 'Test Corp';
You're talking about a plain JavaScript object. JSON is a transfer format inspired by JavaScript syntax.
To make an object, just initialize a variable:
var values = {};
And add properties:
values.accountNumber = "123456789";
values.firstName = "Joe";
etc. If you know the properties up front and have values available, you can make the object in one step:
var values = {
accountNumber: "12345678",
firstName: "Joe",
// ...
};

How do I use #DbLookup results to populate a Readers field in xpages?

db = new Array("myserver", "myfolder\\mydb.nsf")
dir = getComponent("Dir").value;
div = getComponent("Div").value;
lu = #DbLookup(db, "ManagerAccess", dir + "PP" + div, "DTManagers");
var a = [];
a.push(lu);
var item:NotesItem = docBackEnd.replaceItemValue('FormReaders', #Unique(a));
item.setReaders(true);
That code is on the querySaveDocument ssjs. The result I get from the #DbLookup (when I put in a computed field) look like this:
Pedro Martinez,Manny Ramirez,David Ortiz,Terry Francona
I tried doing an #Explode(#Implode) thing on it, but it doesn't seem to work.
The error I get in the browser just tells me that the replaceItemValue line is broken.
To test it, I pushed several strings one at a time, and it worked correctly populating my FormReaders field with the multiple entries.
What am I doing wrong?
I see several problems here:
A. In cases as described by you #Dblookup in fact would return an array. If you push an array into a plain computedField control it will exactly look as that you wrote:
value1, value2, ..., valueN
A computedField doesn't know anything about multiple values etc, it just can display strings, or data that can be converted to strings.
If you want to test the return value you could try to return something like lu[0]; you then should receive the array's 1st element, or a runtime error, if lu is NOT an array. Or you could ask for the array's size using lu.length. That returns the number of array elements, or the number of characters if it's just a plain string.
B. your code contains these two lines:
var a = [];
a.push(lu);
By that you create an empty array, then push lu[] to the first element of a[]. The result is something like this:
a[0] = [value1, value2, ..., valueN],
i.e. a is an array where the first element contains another array. Since you don't want that, just use #Unique(lu) in your replaceItemValue-method.
C. I don't see why replaceItemValue would throw an error here, apart from what I wrote in topic B. Give it a try by writing lu directly to the item (first without #Unique). That should work.
D. for completeness: in the first line you used "new Array". A much better way to define your db parameters is
var db = ["myserver", "myfolder/mydb.nsf"];
(see Tim Tripcony's comment in your recent question, or see his blog entry at http://www.timtripcony.com/blog.nsf/d6plinks/TTRY-9AN5ZK)

flatten/expand objects: am I on the right tracks?

I want to flatten a multi-level object and vice versa.
For example:
{
option1:value1,
option2:value2,
option3:{
key1:value31,
key2:value32
},
option4:[value40,value41,value42]
}
Would be equivalent to:
{
option1:value1,
option2:value2,
"option3.key1":value31,
"option3.key2":value32,
"option4.0":value40,
"option4.1":value41,
"option4.2":value42
}
This is for small objects, the objective of the flattened expression is to facilitate the data collection in a form and the merge with default options. For example I can have form elements like this:
<input name="option4.0" value="value40"/>
Is this a standard approach, or is there a better way? Are there libraries that already do this?
That format ({ option4.2: value42 }) won't work (because the . in the key will be parsed as a dot operator). Instead, you'll need to quote the key:
{ 'option4.2': value42 }
However, this is very non-standard. Flattening objects is typically not required - if you want to submit such an object to a server, you can use JSON to serialize it without flattening:
var stringForServer = JSON.stringify(normalObject);
If you're looking for a library to manipulate objects and arrays etc, underscore is probably your best bet:
http://underscorejs.org/
cheers!
I experimented with my idea, it works fine but has a few limitations.
The obvious ones is that a key cannot contain a dot (dots are delimiters with this technique), and keys cannot be numbers (or else the algorithm interprets it as an array index).
Another issue is that it won't work if a value is an empty object or array (e.g. option4:[]).

Categories