How to extract the query string from a SQLite object in nodejs? - sql

How to extract the query string from a SQLite object in nodejs?
For example if we have this:
import sqlite3 from 'sqlite3';
import { open } from 'sqlite';
const db = await open({
filename: 'test.db',
driver: sqlite3.Database
});
var ret = await db.get('SELECT * FROM `test` WHERE id=? AND foo=?', [100, 'bar']);
How can we achieve this:
SELECT * FROM `test` WHERE id="100" AND foo="bar"
I expect something like this to happen:
db.getQueryString();

es6 string replacement is supporet by nodesjs.
var my_id = 100
var my_var = 'bar';
var s = `SELECT * FROM `test` WHERE id="${my_id}" AND foo="${my_var}" `;
console.log(s);
But you should prepare your statements to make the secure like https://stackoverflow.com/a/49328621/5193536
Depending if ydo want the strings in the log to be used, for testing, you must add single quotes to the sting above, which the query makes automatically

Related

How to build query as variable (from user Input) in prisma.queryRaw without using queryRawUnsafe

I was trying to query my (postgres) db with a customizable statement built front end.
My resolver gets the built query inside the input param, but when I use the queryRaw method I get this error:
`"\nInvalid `prisma.queryRaw()` invocation:\n\n\n Raw query failed. Code: `42601`. Message: `db error: ERROR: syntax error at or near \"$1\"`"`
Is there a way to build a custom query and pass it like the input variable WITHOUT USING queryRawUnsafe to prisma? (queryRawUnsafe works fine, but well.. it's unsafe XD) Thanks <3
Here is my code.
getCars: (_parent, { input }, { prisma }) => {
if(input){
console.log(input) // --> SELECT * FROM car WHERE car."plate" ILIKE '%123%' //type String
const differentInput = '%123%'
// const result = prisma.$queryRaw`SELECT * FROM car WHERE car."plate" ILIKE '%123%'` // works
// const result = prisma.$queryRaw`SELECT * FROM car WHERE car."plate" ILIKE ${differentInput}` // works
// const result = prisma.$queryRawUnsafe(input) // works
const result = prisma.$queryRaw`${input}` // Doesn`t work
return result
}
// ... Other code
}
prisma.$queryRaw only accepts templated strings, not just strings. You can use the Prisma.sql helper to generate those templated strings to get the expected results. That might look like:
const sql = Prisma.sql`SELECT * FROM car WHERE car."plate" ILIKE '%123%'`
const result = prisma.$queryRaw`${sql}`
The queryRaw documentation mentions Prisma.sql with other examples but doesn't show any examples of what you are trying to do.

How to Insert in SQL with NodeJs and mssql library with params

I have 2 arrays, the first one contains the columns for the insert and the second one contains de values
const columns = ['columnName1','columnName2','columnName3','columnName4','columnName5','columnName6'];
const values2 = ['test1', 'test2', 27, 1, 'an address', null];
module.exports = {columns, values2}
And I'm trying to do the insert using mmsql library but not even the documentation contains a sample with multiple columns to insert values to.
This is a sample of my insert
let pool = await sql.connect(config)
const result = await pool.request().query(`INSERT INTO [Test].[TableName] (${testData.columns}) VALUES ?`, [[testData.values2]]);
console.dir(result);
And I'm getting the following error:
RequestError: Incorrect syntax near '?'.
I was able to select to the db with no issues but there's something about the syntax that it doesn't seem to like..
At least you forgot to wrap ? with round brackets:
const result = await pool.request().query(`INSERT INTO [Test].[TableName] (${testData.columns}) VALUES (?)`, [[testData.values2]]);
As I can't find a single example, where you pass the parameters of your sql-query to the query function or use ? as a placeholder in their documentation, I'm not sure, whether node-mssql supports this. But if it does, you should at least create as many ? in the sql statement as you add values.
var cols = [...]; //your columns
const sqlquery = `insert into sometable (${cols}) values (${new Array(cols.length).fill('?')})`;
The documented way would be using input parameters
await pool.request()
.input('p1', sql.Int, value1)
.input('p2', sql.VarChar(50), value2)
.query('insert into sometable(col1, col2) values(#p1, #p2)');
To keep this flexible you could use something like the following
var cols = ['col1', 'col2'];
var vals = ['a string', 23];
const request = pool.request();
for (let i = 0; i < vals.length; i++)
request.input(`param_${i}`, vals[i]); //if you skip the parametertype, mssql will guess it from the value
const sqlquery = `insert into sometable(${cols}) values (${vals.map((_,i) => `#param_${i}`)`;
const result = await request.query(sqlquery);

How to structure syntax for `SELECT` with `IN` SQL Server Query from Node via `mssql` package

I want to make use of SELECT and IN to match on values between tables from two different SQL databases in my Node app that makes use of the mssql package:
My question is, if I am passing a variable representing that array of values in my Node app, that looks like this:
const arr = ["1323", "2311", "1234"];
would I do this?:
N'[arr]'
or this?
N'arr'
Or is there some other syntax I should use?
Right now, this is the full query I'm passing:
// An array *like* this, saved in a variable name:
const sourceIdArr = ["1323", "2311", "1234"];
const selectInQuery = `
DECLARE #sourceIdArr NVARCHAR(4000) = N 'sourceIdArr'
SELECT NDID FROM SR_Empsheets
WHERE NDID IN ( SELECT value from openjson(#sourceIdArr) )
`;
Will this work, or should I approach it differently?
So something like
const sourceIdArr = ["1323", "2311", "1234"];
const selectInQuery = `
SELECT NDID FROM SR_Empsheets
WHERE NDID IN ( SELECT value from openjson(#sourceIdArr) )
`;
new sql.Request()
.input("sourceIdArr", sql.VarChar(sql.MAX), JSON.stringify(sourceIdArr) )
.execute(selectInQuery , (err, result) => {
// ... error checks
console.dir(result)
});

How safe is this generated query from SQL injection?

I am trying to make a search bar which works with multiple words, but I am worried about SQL injection.
I am using node express with the npm mssql package.
Here's the code which gets the criteria, generates the SQL and runs it:
router
.get('/search/:criteria', function (req, res) {
var criteria = req.params.criteria;
var words = criteria.split(" ");
var x = ""
words.map(word => x += `name like '%${word}%' and `);
x = x.substring(0, x.length - 5); // Remove trailing 'and'
var query = `SELECT * FROM table WHERE ${x}`
new sql.ConnectionPool(db).connect().then(pool => {
return pool.request().query(query)
}).then(result => {
})
});
A search for something to search would result in this query:
SELECT * FROM table
WHERE
name like '%something%'
and name like '%to%'
and name like '%search%'
I tried some SQL injections myself, but none of them seem to work.
Note: I am aware that we should always use inputs for this. It works fine for one word, but I don't know how to use inputs for many words. Ex:
new sql.ConnectionPool(db).connect().then(pool => {
return pool.request()
.input('input', '%'+criteria+'%')
.query(query)
})
The answer is: It's not safe. Your code does exactly nothing to make it safe, either. Don't build SQL by concatenating/interpolating user-supplied data into the statement.
In addition, you don't do any escaping for LIKE itself, either, so that is just as unclean.
If you need dynamic SQL, build a prepared SQL statement with the expected number of placeholders and then bind user-supplied values to those placeholders.
router.get('/search/:criteria', (req, res) => {
const ps = new sql.PreparedStatement();
const sqlConditions = [];
const escapedValues = {};
// set up escaped values, safe SQL bits, PS parameters
req.params.criteria.split(" ").forEach((v, i) => {
const paramName = 'val' + i;
escapedValues[paramName] = v.replace(/[\\%_]/g, '\\$&');
sqlConditions.push(`name LIKE '%' + #${paramName} + '%' ESCAPE '\'`);
ps.input(paramName, sql.VarChar);
});
// build safe SQL string, prepare statement
const sql = 'SELECT * FROM table WHERE ' + sqlConditions.join(' AND ');
ps.prepare(sql);
// connect, execute, return
ps.execute(escapedValues).then(result => {
res(result)
});
});
(Disclaimer: code is untested, as I have no SQL Server available right now, but you get the idea.)

Use NSArray in SQLite Statement

I use SQLite.swift and want to replace the question marks in a statement. This can be done for single entries like this:
let stmt = db.prepare("INSERT INTO users (email) VALUES (?)")
for email in ["betty#icloud.com", "cathy#icloud.com"] {
stmt.run(email)
}
I did not see how I can do the following to use a array like:
var values:[String] = ["test1","test2", "test3"]
in a Statement like:
let stmt = db.prepare("SELECT * from users where email in (?)")
The following does not work:
stmt.run(values)
How do I use an NSArray as an argument for a statement?
If you're using the type-safe layer, you can use contains():
users.filter(contains(["test1", "test2"], email))
// the above assumes this boilerplate precedes it:
let email = Expression<String>("email")
let users = db["users"]
If you're using the raw SQLite3 API, it does not support arrays, so you'll need to format those yourself:
let emails = ["test1", "test2"]
let template = join(", ", [String](count: count(emails), repeatedValue: "?"))
let stmt = db.prepare(
"SELECT * FROM users WHERE email IN (\(template))", emails
)