how to query column in SQL database via UPPER case conversion IN NODE.js javascript code.. - javascript

Hi I've recently updated my SEQUELIZE node package from v3 to v4.
In my code I used to query my user table via the following sytnax
var option = {
where: ["upper(email) = ?", ssousername.toUpperCase()]
};
This would effectively query my user table converting all user emails in DB to uppercase.
When upgrading to V4 I am now given the following error thrown by the above query
Unhandled rejection Error: Support for literal replacements in the `where` object has been removed.
I cannot find any documentation as to how I should syntactically format my former query executed via a node.js backend in order to produce the following SQL query
SELECT UPPER(email) AS email
FROM dashboard."user" WHERE email='user#email.com';
Would love some help , Thanks!

They are working on deprecating all string operators I think. Under querying it seems to suggest doing it like this:
let option = {
where: sequelize.where(
sequelize.fn('upper', sequelize.col('email')),
ssousername.toUpperCase()
),
};

Related

Node SQL Server IN query not working with request params

I want to run a query in Node SQL Server which is using IN clause. This is the string used for querying 'a','b','c'. This code works fine, but user is passing data so, I can't use it. May lead to attacks:
const dbResult = await request.query(`
SELECT OrderID, ParentSKURefNum, SKURefNum, OrderCompleteTime
FROM ${tables.ORDERS}
WHERE OrderID IN (${idsWithQuotes})
`);
I want to use request.input('OrderIDs', ids) and then code will be like this:
request.input('OrderIDs', ids);
const dbResult = await request.query(`
SELECT OrderID, ParentSKURefNum, SKURefNum, OrderCompleteTime
FROM ${tables.ORDERS}
WHERE OrderID IN (#OrderIDs)
`);
But the code above always shows: No data found. What am I doing wrong? In second situation I also tried removing first and last quote from the string assuming request automatically adds it.
Thanks for your help!
I'm using SQL Server 2012 which doesn't support STRING_SPLIT function to split CSV into some sort of table which then IN operator operates on.
I found it on stack overflow that we can split the values using XML which I didn't really understand but did the trick.
SELECT OrderID, ParentSKURefNum, SKURefNum, OrderCompleteTime
FROM ${tables.ORDERS}
WHERE OrderID IN (
SELECT Split.a.value('.', 'NVARCHAR(MAX)') DATA
FROM
(
SELECT CAST('<X>'+REPLACE(#OrderIDs, ',', '</X><X>')+'</X>' AS xml) AS STRING
) AS A
CROSS APPLY String.nodes('/X') AS Split(a)
)

How can I use DEFAULT values via knex insert?

My goal is to dynamically insert data into a table via knex.
Code looks like this:
const knexService = require("../knexService.js")
async function insertObjectToKnex() {
const insertObject = {
id: "DEFAULT",
someKey: "someValue"
};
await knexService.db("table").insert(inserObject);
}
On DEFAULT the next free id should be used as database id - table is configured and it works with raw sql. With knex.js I get the following error:
invalid input syntax for type integer: "DEFAULT"
Using the useNullAsDefault: true, config is not possible, because the id is not nullable.
How can I trigger the default value in knex - I did not find anything in the documentation or with google, that could at least give a hint to this issue!
While it is not mentioned in the documentation of knex.js one should simply not add fields with a DEFAULT assignement to a query. This will set the default value to the row column.

SAP Cloud SDK for Javascript: Filter on Expanded Entities

I know I am reopening an old one (Perform filter on expanded entity with SAP Cloud SDK), but it was a while ago and was referencing the Java version of the API used to consume an S/4 HANA service.
I'm testing the Javascript version of the API against the SuccessFactors OData API, which is indeed able to perform filters on expanded entities, like so:
<API_HOST>/odata/v2/PerPerson?$filter=personalInfoNav/firstName eq 'MARCO'&$expand=personalInfoNav&$select=personalInfoNav/firstName, personalInfoNav/lastName&$top=20
Translated into the SDK, it would be (TypeScript):
const personList: Array<PerPerson> =
await PerPerson.requestBuilder().getAll().top(20)
.select(
PerPerson.DATE_OF_BIRTH,
PerPerson.PERSONAL_INFO_NAV.select(
PerPersonal.PERSON_ID_EXTERNAL,
PerPersonal.FIRST_NAME,
PerPersonal.LAST_NAME,
PerPersonal.GENDER
)
).filter(PerPersonal.FIRST_NAME.equals('MARCO'))
.execute({ destinationName: this.configService.get<string>('ACTIVE_DESTINATION') });
But this code does not compile because of the incompatibility of types for the filter function, which here expects a "PerPerson" type and not "PerPersonal".
I was not able to find anything about this.
Considering that the plain OData query works perfectly, anyone has been able to make this work?
Update:
I didn't initially understand that Successfactors offered this functionality on top of the protocol. There are two possible workarounds I can think of:
use new Filter, e.g.:
PerPerson.requestBuilder().getAll().top(20)
.select(
...
).filter(
new Filter('personalInfoNav/firstName', 'eq', 'MARCO')
)
...
If this doesn't work, you can call build on the request builder instead of execute, which gives you the ODataRequest object from which you can get the URL, which you'd then have to manipulate manually. Then you should be able to use the executeHttpRequest function to execute this custom request object against a destination.
Let me know if one of these work for you!
Original answer:
filtering on expanded entities on OData v2 is only possible if the relationship between the two entities is 1:1. In the case the code would look like this:
PerPerson.requestBuilder().getAll().top(20)
.select(
PerPerson.DATE_OF_BIRTH,
PerPerson.PERSONAL_INFO_NAV.select(
PerPersonal.PERSON_ID_EXTERNAL,
PerPersonal.FIRST_NAME,
PerPersonal.LAST_NAME,
PerPersonal.GENDER
)
).filter(
PerPerson.PERSONAL_INFO_NAV.filter(
PerPersonal.FIRST_NAME.equals('MARCO')
))
...
If, however, the relationship is 1:n, filtering is not possible.
Hope that helps!

In sails/waterline get maximum value of a column in a database agnostic way

While using sails as ORM (version 1.0), I notice that there is a function called Model.avg (as well as sum). - However there is not a maximum or minimum function to get the maximum or minimum from a column in a model; so it seems this is not necessary because it is covered by other functions already?
Now in my database I need to get the "maximum id" in a list; and I have it working for postgresql by using a native query:
const maxnum = await Order.getDatastore().sendNativeQuery('SELECT MAX(\"orderNr\") FROM \"order\"')
While this isn't the most difficult thing, it is not what I truly want: it is limited to only sql-based datastores (so we wouldn't be able to move easily to mongodb); and the syntax might actually be even different for another sql database type.
So I wonder - can this be transformed in such a way it doesn't rely on sendNativeQuery?
You can try .query() to execute a raw SQL query using the specified model's datastore and if u want u can try pg , an NPM package used for communicating with PostgreSQL databases:
Pet.query('SELECT pet.name FROM pet WHERE pet.name = $1', [ 'dog' ]
,function(err, rawResult) {
if (err) { return res.serverError(err); }
sails.log(rawResult);
// (result format depends on the SQL query that was passed in, and
the adapter you're using)
// Then parse the raw result and do whatever you like with it.
return res.ok();
});
You can use the limit and order options waterline provides to get a single Model with a maximal value (then just extract that value).
const orderModel = await Order.find({
where: {},
select: ['orderNr'],
limit: 1,
sort: 'orderNr DESC'
});
console.log(orderModel.orderNr);
Like most things in Waterline, it's probably not as efficient as an SQL SELECT MAX query (or some equivalent in mongo, etc), but it should allow swapping out the database with no maintenance. Last note, don't forget to handle the case of no models found.

Couchbase Java API and javascript view not returning value for a specific Key

I am using couchbase API in java
View view = client.getView("dev_1", "view1");
Query query = new Query();
query.setIncludeDocs(true);
query.setKey(this.Key);
ViewResponse res=client.query(view, query);
for(ViewRow row: res)
{
// Print out some infos about the document
a=a+" "+row.getKey()+" : "+row.getValue()+"<br/>";
}
return a;
and the java script view in couchbase
function (doc,meta) {
emit(meta.id,doc);
}
So, when I remove the statement query.setkey(this.Key) it works returns me all the tables, what am I missing here .. How can I change the function to refect only the table name mentioned in the key
Change the map function like this:
function (doc,meta) {
emit(doc.table,null);
}
it is good practice not to emit the entire document like:
emit(doc.table, doc)
NB: This is surprisingly important:
i have tried using setKey("key") so many times from Java projects and setting the key using CouchBase Console 3.0.1's Filter Result dialog, but nothing get returned.
One day, i used setInclusiveEnd and it worked. i checked the setInclusiveEnd checkbox in CouchBase Console 3.0.1's Filter Result dialog and i got json output.
query.setKey("whatEverKey");
query.setInclusiveEnd(true);
i hope this will be helpful to others having the same issue. if anyone finds another way out, please feel free to add a comment about it.
i don't know why their documentation does not specify this.
EXTRA
If your json is derived from an entity class in a Java Project, make sure to include an if statement to test the json field for the entity class name to enclose you emit statement. This will avoid the key being emitted as null:
if(doc._class == "path.to.Entity") {
emit(doc.table, null);
}

Categories

Resources