node-postgres LEFT JOIN query - postgresql

I am attempting to effect a join query in node-postgres (pg) with the following function but am getting a syntax error. The problem is the join query, everything else works fine. What is the correct way to format a join query in pg?
exports.bigBook = function(req, res) {
var bookNumber = req.params.id;
pool.connect(function(err, client, done) {
if (err) { return console.error('error fetching client from pool', err);}
client.query('SELECT * FROM book WHERE id = $1 LEFT JOIN author
ON (book.author = author.auth_id)'), [bookNumber], function (err, results) {
client.release();
res.send(results.rows);
};
})
}

The LEFT JOIN is part of the FROM clause, so you'll have to move the WHERE clause to the end of the query.

Related

Trying to show a demo on SQL Injection

I'm trying to show a demo on SQL injection but doesn't seem to work. I have tried to truncate a table named demo with this: "SELECT * FROM products WHERE booktitle like '%'Songs'; TRUNCATE TABLE demo --%'" but is not working.
I'm using MySQL with Nodejs and here is the code:
app.post("/api/productsearch", (req, res) => {
db.query(`SELECT * FROM products WHERE booktitle like '%${req.body.searchData.booktitle}%'`, (err, result) => {
if (err) {
console.log(err);
} else {
res.json(result);
}
}
)
})
How do I do a SQL injection on the productsearch api? Many thanks in advance and greatly appreciate any helps. Thanks
If you enter booktitle as '; TRUNCATE TABLE demo -- , then the resulting SQL statement is
SELECT * FROM products WHERE booktitle like '%'; TRUNCATE TABLE demo -- %'

Knex, Objection.js, How to sort by number of associations

I have an Express API using Postgres via Knex and Objection.
I want to set up a Model method or scope that returns an array of Parent model instances in order of number of associated Children.
I have looked through the Knex an Objection docs
I have seen the following SQL query that will fit, but trying to figure out how to do this in Knex:
SELECT SUM(O.TotalPrice), C.FirstName, C.LastName
FROM [Order] O JOIN Customer C
ON O.CustomerId = C.Id
GROUP BY C.FirstName, C.LastName
ORDER BY SUM(O.TotalPrice) DESC
This is how it should be done with knex (https://runkit.com/embed/rj4e0eo1d27f):
function sum(colName) {
return knex.raw('SUM(??)', [colName]);
}
knex('Order as O')
.select(sum('O.TotalPrice'), 'C.FirstName', 'C.LastName')
.join('Customer C', 'O.CustomerId', 'C.Id')
.groupBy('C.FirstName', 'C.LastName')
.orderBy(sum('O.TotalPrice'), 'desc')
// Outputs:
// select SUM("O"."TotalPrice"), "C"."FirstName", "C"."LastName"
// from "Order" as "O"
// inner join "Customer C" on "O"."CustomerId" = "C"."Id"
// group by "C"."FirstName", "C"."LastName"
// order by SUM("O"."TotalPrice") desc
But if you are really using objection.js then you should setup models for your Order and Customer tables and do something like this:
await Order.query()
.select(sum('TotalPrice'), 'c.FirstName', 'c.LastName')
.joinRelated('customer as c')
.groupBy('c.FirstName', 'c.LastName')
.orderBy(sum('TotalPrice'), 'desc')
In case anyone is interested, I just included the raw SQL query as follows:
router.get('/leaderboard', async (req, res) => {
let results = await knex.raw('SELECT users_id, username, COUNT(acts.id) FROM acts INNER JOIN users ON acts.users_id = users.id GROUP BY users_id, username ORDER BY COUNT(acts.id) DESC');
console.log(results);
res.json(results.rows);
});

I have a issue in Loopback

I have the following SQL:
SELECT *
FROM table1 INNER JOIN table2 ON table1.id = table2.id_table1
WHERE table2.column_name = 'value';
I have tried
{include:'table2',where:{'table2.column':'value'}}
but can't. What should I do?
this works for me
include: {
relation: 'table2',
scope: {
fields: ['fields', 'you', 'want'],
where: {
column: 'value'
}
}
}
in case it's not working, you need to make sure you have right relations in your table1.json and table2.json file
loopback does not support inner join it only support left join you can use raw query to achieve your requirement try something like this
yourmodalname.customremotemethod= function(ctx,options, cb) {
const ds = yourmodalname.dataSource
var query ="SELECT * FROM table1 INNER JOIN table2 ON table1.id =table2.id_table1 WHERE table2.column_name = 'value'";
ds.connector.query(query, function(err, res){
if(err){
cb(null,err)
}else{
cb(null,res)
}
});
};

Limit join to one row using knex

I am trying to fetch data from two tables using a join. The problem is forum_posts will contain several items with the same thread_id. I would only like to get the first one, either by id or by creating date.
function getByGroup(groupId) {
return knex('forum_threads')
.select('forum_threads.id', 'forum_threads.updated_at', 'forum_posts.content')
.where('forum_threads.group_id', '=', groupId)
.leftJoin('forum_posts', function() {
this.on('forum_posts.thread_id', '=', 'forum_threads.id');
})
.orderBy('updated_at', 'desc')
.then(function(threads) {
return threads;
});
}
I would like to add a limit(1) or a min to the join but not entirely sure how to do it.
You need to add a filter like the following to your left join criteria:
.andOn('forum_posts.created_at', '=', knex.raw("(select min(created_at) from forum_posts where forum_posts.thread_id = forum_threads.id)"))
This says to include the forum post record (as a left join match) if it has the minimum updated_at value for that id.
The full code. The below code isn't tested, although I did test the above snippet in a piece of my code.
function getByGroup(groupId) {
return knex('forum_threads')
.select('forum_threads.id', 'forum_threads.updated_at', 'forum_posts.content')
.where('forum_threads.group_id', '=', groupId)
.leftJoin('forum_posts', function() {
this.on('forum_posts.thread_id', '=', 'forum_threads.id')
/* The new line here */
.andOn('forum_posts.created_at', '=', knex.raw("(select min(created_at) from forum_posts where forum_posts.thread_id = forum_threads.id)"))
})
.orderBy('updated_at', 'desc')
.then(function(threads) {
return threads;
});
}
Cheers!
PS: You didn't ask, but something I find very helpful when debugging Knex is the .on() query reporting clauses:
// ...
.orderBy('updated_at', 'desc')
/* your code above */
.on('query', function(data) {
// outputs the SQL query you generated & runtime data bindings.
console.log(data);
})
.on('query-error', function(error, obj) {
// outputs the Knex failed query, data, etc.
console.log("Error:", error);
console.log("Object: ", obj);
})
/* your code below */
.then(function(threads) {
return threads;
});

How can I execute this Postgres query in Sequelize?

I need to translate this join query into Sequelize. I have associated the three tables involved in the join:
tracks.belongsToMany(tracks_playlists, { foreignKey: 'track_id' });
tracks.belongsToMany(tracks_meta, { foreignKey: 'track_id' });
tracks_meta.belongsToMany(tracks_playlists, { foreignKey: 'track_id'});
Here's the raw query that works:
SELECT tracks_playlists.playlist_id, tracks_playlists.track_id, tracks.track, tracks.track_type, tracks_meta.status, tracks_meta.app_id, tracks_meta.description, tracks_meta.ip
FROM tracks_playlists
INNER JOIN tracks on tracks_playlists.track_id = tracks.track_id
INNER JOIN tracks_meta on tracks.track_id = tracks_meta.track_id
WHERE tracks_playlists.playlist_id = 4;
When I try to run the following code
self.tracks_playlists_table.find({
where: {
playlist_id: 4
},
include: [{
model: self.tracks_table
}]
})
.then(function(resp) {
console.log(resp);
});
it spits out this error:
relation "playlists.trackstracks_playlists" does not exist
This is the query that it generates from my code:
SELECT "TracksPlaylists".*, "Tracks"."track_id" AS "Tracks.track_id",
"Tracks"."track" AS "Tracks.track", "Tracks"."track_type" AS "Tracks.track_type", "Tracks"."created" AS "Tracks.created", "Tracks"."updated" AS "Tracks.updated", "Tracks.trackstracks_playlists"."created" AS "Tracks.trackstracks_playlists.created", "Tracks.trackstracks_playlists"."updated" AS "Tracks.trackstracks_playlists.updated", "Tracks.trackstracks_playlists"."track_id" AS "Tracks.trackstracks_playlists.track_id"
FROM (SELECT "TracksPlaylists"."track_playlist_id", "TracksPlaylists"."track_id", "TracksPlaylists"."playlist_id", "TracksPlaylists"."created", "TracksPlaylists"."updated"
FROM "playlists"."tracks_playlists" AS "TracksPlaylists"
WHERE "TracksPlaylists"."playlist_id" = 4 LIMIT 1) AS "TracksPlaylists"
LEFT OUTER JOIN ("playlists"."trackstracks_playlists" AS "Tracks.trackstracks_playlists"
INNER JOIN "playlists"."tracks" AS "Tracks"
ON "Tracks"."track_id" = "Tracks.trackstracks_playlists"."track_id")
ON "TracksPlaylists"."track_playlist_id" = "Tracks.trackstracks_playlists"."track_id";
Why is it creating the column "trackstracks_playlists"?