How to pass order info to sequelize.js raw query? - node.js

In sequelize, I can use
my_table.findAll({ order: [['datetime', 'desc']] })
to query data and order by a column. But when I try to use parameterized raw query like:
var input_parameters = {order_column: 'datetime', order: 'desc'};
sequelize.query('select * from my_table order by :order_column :order', { replacements: input_parameters, type: models.sequelize.QueryTypes.SELECT });
It can't return the correct order because
the order info asc/desc is escaped in the query, the final prepared query is like 'select * from my_table order by 'datetime' 'desc''.
Is there a way to pass order info to raw parameterized query?

This might not be the sequelize way, but...what if:
let order_column = 'something';
let order = 'DESC';
sequelize.query(`select * from my_table order by ${order_column} ${order}`, { type: models.sequelize.QueryTypes.SELECT });
UPDATE:
This is the right answer
await sequelize.query(
'SELECT * FROM projects ORDER BY ? ?',
{
replacements: ['something', 'desc'],
type: QueryTypes.SELECT,
}
);
This way sequelize still protects you from sql injection.

I wondered samething. But I think there's no options in raw query.
So I usually define class methods in model to use method much sequelize-like follows.
/**
* usage :
*
* model.findSomething({
* where: whereCondition,
* limit: limit,
* offset: offset,
* order: [
* ['col1', 'asc'],
* ['col2', 'desc']
* ]})
*/
model.findSomething = function ({where, limit, offset, order}) {
let sql = 'SELECT col1, col2 FROM some_table '
... (build where conditions)
// build order conditions
if (order && order.length > 0) {
let orderBy = ' ORDER BY '
for (let i = 0; i < order.length; i++) {
if (order[i].length > 0) { // [column] or [column, asc/desc]
orderBy += (i > 0 ? ', ' : ' ') + order[i].join(' ')
}
}
sql += orderBy
} else {
sql += ` ORDER BY comment_group, comment_depth, comments.comment_id`
}
... (build limit and offset)
}
Before you call sequelize.query, just build the sql statement first.
Too late answer, but I hope this let help you.

let order_column = 'something';
let order = 'DESC';
sequelize.query('select * from my_table order by " + order_column +' ' order, { replacements: input_parameters, type: models.sequelize.QueryTypes.SELECT })

Related

Need a sequelize alternative to a find raw query

SELECT * FROM recommended_plan WHERE user_id = ? AND created_at = (SELECT MAX(created_at) FROM recommended_plan WHERE user_id = ?)
I am stuck at converting this raw query into a sequelize one.
CASE 1 - you have only one record with max created_at value
First you can convert it to this equivalent one:
SELECT * FROM recommended_plan WHERE user_id = ?
order by created_at desc
limit 1
(Please pay attention that the limit option depends on a certain DBMS and could have a different name and/or syntax).
Now you can easily construct the corresponding Sequelize query:
const plan = await RecommendedPlan.findAll({
where: {
user_id: userId
},
limit: 1,
order: [['created_at', 'desc']]
})
CASE 2 - you have several records with max created_at value:
You can use Sequelize.literal to use a condition with a subquery:
const plan = await RecommendedPlan.findAll({
where: {
user_id: userId,
created_at: Sequelize.literal('(SELECT MAX(created_at) FROM recommended_plan rp WHERE rp.user_id = $userId)')
},
bind: {
userId: userId
}
})

How to create a Search all columns in SuiteScript 2.0 version

How I can create select * from in suitescript?
I need all columns from the object.
you can use the 'N/query'
require(['N/query'], function(query) {
var sql = "SELECT * from TRANSACTION WHERE TRANSACTION_ID=XXXX;
var resultIterator = query.runSuiteQLPaged({
query: sql,
pageSize: 10
}).iterator();
resultIterator.each(function(page) {
var pageIterator = page.value.data.iterator();
pageIterator.each(function(row) {
log.debug('ID: ' + row.value.getValue(0) + ', Context: ' + row.value.getValue(1));
return true;
});
return true;
});
});
Before you do that run the query in ODBC because some columns cannot been loaded (pdf,xml data)

TypeORM : Generate query with nested AND and OR

I am using NodeJS + TypeORM + PostgreSQL
I find it difficult to generate queries based on my requirements.
I need to generate the following query:
select * from clinics where status = 1 and (last_sync_date < x or last_sync_date is null)
Here x is current date - 10 days.
I tried the following query:
let now = Date();
now.setDate(now.getDate() - 10);
let clinics = await clinicRepo.find({
where: [
{ status: 1, last_sync_date: LessThan(now) },
{ last_sync_date: IsNull() }
]
});
But the result is this:
select * from clinics where (status = 1 and last_sync_date < x) or last_sync_date is null;
What do I need to change in the code above?
I want to use find so that I can load relations as well.
You can solve this by creating the query with js conditions and then assign it to the FindConditions.
For example:
const whereCondition = testResultId ?
{patientId, id: Not(testResultId), clinicId} :
{patientId, clinicId}
const tr = await TestResult.findOne({
where: whereCondition,
})
Or you can use Raw operator:
let clinics= await clinicRepo.find({
where : [
{status: 1,
last_sync_date: Raw(alias => `(${alias} < ${now} OR ${alias} IS NULL)`}
]
});

Equivalent sequelize operation for given sql server query

SELECT *
FROM (SELECT *, ROW_NUMBER() OVER ( ORDER BY No_ ) AS RowNum
FROM Item) DerivedTable
WHERE RowNum >= 501 AND RowNum <= 501 + ( 5 - 1 );
I think the older sql server versions do no support FETCH ROWS and NEXT ROWS which is equivalent to OFFSET and LIMIT in mysql, the above query seems the only way to apply that logic.
How can sequelize implement the above query, which creates a virtual table "DerivedTable" with a column "RowNum" that is used in the WHERE clause.
Is there any other method to do this in sequelize, maybe including raw query or anything else?
It seems you are not alone with this issue. With SQL Server 2012, you can just use:
Model
.findAndCountAll({
where: {
title: {
$like: 'foo%'
}
},
offset: 10,
limit: 2
})
.then(function(result) {
console.log(result.count);
console.log(result.rows);
});
However since you are on an earlier version it seems you are stick with having to hand write the query.
Something like this:
var theQuery = 'declare #rowsPerPage as bigint; '+
'declare #pageNum as bigint;'+
'set #rowsPerPage='+rowsPerPage+'; '+
'set #pageNum='+page+'; '+
'With SQLPaging As ( '+
'Select Top(#rowsPerPage * #pageNum) ROW_NUMBER() OVER (ORDER BY ID asc) '+
'as resultNum, * '+
'FROM myTableName)'+
'select * from SQLPaging with (nolock) where resultNum > ((#pageNum - 1) * #rowsPerPage);';
sequelize.query(theQuery)
.spread(function(result) {
console.log("Good old paginated results: ", result);
});
});
see this and this

Using nodejs 'cassandra-driver' prepared query with IN query

This is a potential newbie question but I couldn't find an answer out in the wild.
I'm currently building a simple user event log of this form (some attributes elided to keep this simple):
CREATE TABLE events.by_hour (
level tinyint, /* 60 = FATAL, 10 = TRACE */
hour int, /* in YYYYMMDDHH format */
insertion_time timeuuid,
userid TEXT,
message TEXT,
PRIMARY KEY ((type,hour),userid,insertion_time))
WITH CLUSTERING ORDER BY (userid ASC, insertion_time ASC);
I would like to make a prepared query to fetch all events optionally filtered by a given user over some set of levels ideally over the course of several hours.
I can easily build a query that queries a single level and hour:
var cassandra = require('cassandra-driver');
var client = new cassandra.Client({contactPoints: ['127.0.0.1']});
var query
= 'SELECT * FROM events.by_hour
WHERE level IN (?) and hour IN (?) and userid = ?;';
var options = [ 10, 2016032117,'user_uuid' ];
client.execute(query, options, {
prepare: true
}, function (err, result) {
// Do stuff...
next(err);
});
This works fine for a single hour and level. I would love to specify multiple hours and levels in the above query but playing with the code I'm unable to get that to work either by specifying the set as a string or as an array of values.
I think I'm forced to do something like this:
Build the query based upon the number of levels and hours are needed:
// for 1 level and 2 hours:
query = 'SELECT * FROM events.by_hour
WHERE level IN (?) and hour IN (?,?) and userid = ?;';
options = [ 10, 2016032117,2016032118,'user_uuid' ];
client.execute(query, options, {
prepare: true
}, function (err, result) {
// Do stuff...
next(err);
});
// for 2 levels and 2 hours:
query = 'SELECT * FROM events.by_hour
WHERE level IN (?,?) and hour IN (?,?) and userid = ?;';
options = [ 10, 20, 2016032117,2016032118,'user_uuid' ];
client.execute(query, options, {
prepare: true
}, function (err, result) {
// Do stuff...
next(err);
});
I don't love this. BUT I can still get the benefits of prepared queries even here since we can just pass in 'prepared: true'. It feels like there should be a better way... but I'm not sure what I'm trying to do is even possible with single prepared query.
Can anyone lend some wisdom here?
Thanks!
You should use the IN operator followed by the query marker (no parenthesis) and provide the parameter for the query marker as an array:
const query = 'SELECT * FROM events.by_hour WHERE level IN ? and ' +
'hour IN ? and userid = ?';
const params = [ [ 10, 20, 30] , [ 2016032117, 2016032118 ],'user_uuid' ];
client.execute(query, params, { prepare: true }, callback);

Resources