NodeJS, sqlite3, and WHERE IN paramaters - javascript

Does the sqlite3 library for NodeJS support parameters for WHERE IN queries?
I have the following small program.
const sqlite3 = require('sqlite3');
const db = new sqlite3.Database('./data/data.db');
const sql = `
SELECT * FROM accounts
WHERE
name IN ('Business Expense - Internet Service','RCSB Checking')`;
db.all( sql,
function getAccout(error, rows) {
console.log(error);
console.log(rows);
});
The program "works". It queries the database, and the rows variable is successfully populated with data from two separate rows.
However, I don't want hard coded values. I want to parameterize my values. The following code works for that.
const sql = `
SELECT * FROM accounts
WHERE
name = ? OR name = ?`;
db.all( sql,
['Business Expense - Internet Service','RCSB Checking'],
function getAccout(error, rows) {
console.log(error);
console.log(rows);
});
However, I want this to work with any number of names. i.e. I want to parameterize the original WHERE IN query. However, the following program
const sql = `
SELECT * FROM accounts
WHERE
name IN (?)`;
db.all( sql,
[['Business Expense - Internet Service','RCSB Checking']],
function getAccout(error, rows) {
console.log(error);
console.log(rows);
});
does not work. It runs without error, but returns zero rows. I also tried using a concatenated string as the param
const sql = `
SELECT * FROM accounts
WHERE
name IN (?)`;
db.all( sql,
["'Business Expense - Internet Service','RCSB Checking'"],
function getAccout(error, rows) {
console.log(error);
console.log(rows);
});
and this also didn't work.
Does the sqlite3 library support parameterizing WHERE IN queries? If so, what's the syntax for doing so? If not, are there common work arounds to this in the NodeJS community?

I don't know if there is support for it, but in case there is not
const params = [...]
const sql = `
SELECT * FROM accounts
WHERE
name IN (${new Array(params.length).fill('?').join(',')})`;

I was going to suggest using JS string literals as well. Seems more like the 'node way' of doing things.

Related

How do I prevent sql injection on a WHERE IN request with parameterized query? [duplicate]

I am trying to workout how to pass in a comma sepated string of values into a postgres select within in clause query using node-postgres but unfortunately can't seem to get it working and can't find any examples.
I have the following code:
function getUser() {
let inList = "'qwerty', 'qaz'";
const result = await pgPool.query("SELECT name FROM my_table WHERE info IN ($1)", [inList]);
if (result.rowCount == 1) return result.rows.map(row => row.name)
return false
}
Basically want the end result query to process:
SELECT name FROM my_table WHERE info IN ('qwerty', 'qaz')
Unsure if this is actually the correct way of doing this with pgPool?
The right way is in the FAQ on Github --> https://github.com/brianc/node-postgres/wiki/FAQ#11-how-do-i-build-a-where-foo-in--query-to-find-rows-matching-an-array-of-values
You should be able to do it that way :
pgPool.query("SELECT name FROM my_table WHERE info = ANY ($1)", [jsArray], ...);

TypeORM createQueryBuilder: Is possible to use table name as string instead of entity

In my current scenario, a third party will be creating tables dynamically on my DB, and storing the table name as a varchar and column names as jsonb in other table which is defined as an Entity in my NestJS backend.
This is so I can keep track (and query) these tables, since I have no control over its creation.
For this purpose I'd like to use TypeORM's createQueryBuilder instead of using raw queries as its easier for me to play with abstraction.
As far as I know TypeORMs createQueryBuilder needs a defined Entity in the from clause.
Something like this:
return await getManager()
.createQueryBuilder()
.select('*')
.from(MyDefinedModel, 'modelAlias')
.getRawMany();
}
So I'd like to do something like:
const tableName = await getDynamicallyGenetaredTableNames().getFirstOne()
// now tableName points to a string that is a table name, i.e 'table-data-192239'
return await getManager()
.createQueryBuilder()
.select('*')
.from(tableName, 'tableAlias')
.getRawMany();
So passing the table name I point to the right table, but TypeORM (and TS) complains because that tableName is a string, and not an Entity (Class) type
I really don't want to type-cast and start doing nasty things if there is something cleaner to achieve this.
I didn't find any solution in the official docs
Any brilliant ideas out there?
Thanks, y'all
We can pass table name instead of Entity for getRepository.
let tableName = 'user';
let query = getRepository(tableName).createQueryBuilder(tableName);
You can select from a table by its table name without defining an entity before like this:
const res = await manager
.createQueryBuilder()
.select()
.from("tableName", null)
.where("tableName.id = :id", { id: 1 })
.getRawMany();
Be sure that you set the second parameter of the from() explicitly to null.
You could try using a raw query:
import { getManager } from 'typeorm'
const tableName = await getDynamicallyGenetaredTableNames().getFirstOne()
// Use the table name in a raw SQL query
const result = await getManager().query(`SELECT * FROM ${tableName}`)

How i take a value that is like field in my database?

I try to get values that contains words in my sql database. I try with "contains" but I get an error. I work with SQL
This is my code:
router.post('/busca',isLoggedIn, async (req,res) => {
const {busca} = req.body;
const buscar = Object.values({busca});
const bus = await pool.query('SELECT * FROM links WHERE title CONTAINS ?',[buscar]);
res.render('links/busca',{buscar, bus});
});
I have this error:
UnhandledPromiseRejectionWarning: Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(title, 'a')' at line 1
You can use LIKE operator :
SELECT * FROM links WHERE title LIKE '%word%';
if you are more than one word use and or or operator
SELECT * FROM links WHERE title LIKE '%word%' AND title LIKE '%secondword%';
Contains doesn't exist in mysql .
use LIKE
const bus = await pool.query('SELECT * FROM links WHERE title LIKE ?',[%buscar%]);

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.

Nodejs and mysql, multiple criteria in a query

I m actually using the mysql module to query my database and I m facing a problem. In fact, I need to escape a full object and parse it in a query that mysql could understand.
Actually, I have :
getByCriteria: (collectionName, criteria)->
sql = 'SELECT * FROM ?? WHERE ?'
inserts = [collectionName, criteria]
sql = MySql.format(sql, inserts)
deferred = Q.defer()
MysqlAdapter.CONNECTION.query(sql, (err, rows, fields)->
console.log err
if err
deferred.reject(new Error(err))
else
deferred.resolve(rows)
)
return deferred.promise
But the console.log(sql) prints :
SELECT * FROM user WHERE username = 'admin', id=1
So I have guessed that the "Mysql.format" returns a string for the INSERT/UPDATE SQL actions.
How can I do it with mysql, without parsing the entire string with a homemade solution ?
THanks for advance
I'm afraid that MySql.format() is very simple (https://github.com/felixge/node-mysql/blob/master/lib/protocol/SqlString.js#L67) so you'll need to do your own formatting.
Just remember to escape values with MySql.escape() and identifiers with MySql.escapeId()
You'll need something similar to SqlString.objectToValues() https://github.com/felixge/node-mysql/blob/master/lib/protocol/SqlString.js#L109 but with values joined with AND instead of ,

Categories

Resources