Use NSArray in SQLite Statement - objective-c

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
)

Related

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

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

Do strings need to be escaped inside parametrized queries?

I'm discovering Express by creating a simple CRUD without ORM.
Issue is, I'm not able to find any record through the Model.findBy() function
model User {
static async findBy(payload) {
try {
let attr = Object.keys(payload)[0]
let value = Object.values(payload)[0]
let user = await pool.query(
`SELECT * from users WHERE $1::text = $2::text LIMIT 1;`,
[attr, value]
);
return user.rows; // empty :-(
} catch (err) {
throw err
}
}
}
User.findBy({ email: 'foo#bar.baz' }).then(console.log);
User.findBy({ name: 'Foo' }).then(console.log);
I've no issue using psql if I surround $2::text by single quote ' like:
SELECT * FROM users WHERE email = 'foo#bar.baz' LIMIT 1;
Though that's not possible inside parametrized queries. I've tried stuff like '($2::text)' (and escaped variations), but that looks far from what the documentation recommends.
I must be missing something. Is the emptiness of user.rows related to the way I fetch attr & value ? Or maybe, is some kind of escape required when passing string parameters ?
"Answer":
As stated in the comment section, issue isn't related to string escape, but to dynamic column names.
Column names are not identifiers, and therefore cannot be dynamically set using a query parameter.
See: https://stackoverflow.com/a/50813577/11509906

Invalid parameter number: number of bound variables does not match number of tokens PDO insert

function mysql_insert($data_array){
$sql = "insert into `". $this->table_name. '`';
$array_keys = array_keys($data_array);
$array_keys_comma = implode(",\n", preg_replace('/^(.*?)$/', "`$1`", $array_keys));
for($a=0,$b=count($data_array); $a<$b; $a++){ $question_marks .="?,"; }
$array_values = array_values($data_array);
$array_values_comma = implode(",", $array_values);
$sql.= " ($array_keys_comma) ";
$sql.= " values(". substr($question_marks, 0,-1) .")";
$prepare = $this->connDB->prepare($sql);
$insert = $prepare->execute(array($array_values_comma));
}
I want to creat like this universal functions, $data_array-comes from $_POST
This function will work for all form. But i dont know what is my wrong :S
I don't know what is my wrong
That's quite easy to know: number of bound variables does not match number of tokens.
I want to creat like this universal functions, $data_array-comes from $_POST
Here you go: Insert/update helper function using PDO
$array_values_comma is a scalar after you implode() the array. So you always pass an array of one element to your execute() function. You should pass $array_values.
Here's how I'd write this function:
function mysql_insert($data_array){
$columns = array_keys($data_array);
$column_list_delimited = implode(",",
array_map(function ($name) { return "`$name`"; }, $columns));
$question_marks = implode(",", array_fill(1, count($data_array), "?"));
$sql = "insert into `{$this->table_name}` ($column_list_delimited)
values ($question_marks)";
// always check for these functions returning FALSE, which indicates an error
// or alternatively set the PDO attribute to use exceptions
$prepare = $this->connDB->prepare($sql);
if ($prepare === false) {
trigger_error(print_r($this->connDB->errorInfo(),true), E_USER_ERROR);
}
$insert = $prepare->execute(array_values($data_array));
if ($insert === false) {
trigger_error(print_r($prepare->errorInfo(),true), E_USER_ERROR);
}
}
A further improvement would be to do some validation of $this->table_name and the keys of $data_array so you know they match an existing table and its columns.
See my answer to escaping column name with PDO for an example of validating column names.

ColdFusion - how do I execute an SQL "IN" clause in cfscript?

How would I construct an IN clause in cfscript? Here's what I have:
var tagList = "301,302,303,304";
var q = new Query ();
q.setDatasource ("mydatasource");
var sqlStmt = "SELECT * FROM Tags WHERE tagID IN (:tagList)";
// I know the next line is not correct!
q.addParam (name="tagList", value="#tagList#", cfsqltype="??? WHAT SHOULD IT BE ???");
Is there an easy way to do this, or do I need to iterate through the list of tags, adding each one separately?
There is a list attribute on <cfqueryparam> which ought to be supported:
q.addParam (name="tagList", value="#tagList#", cfsqltype="CF_SQL_INTEGER", list="yes");

Parameterized LIKE clause in SQL statement using Dapper

I want to perform the following query using Dapper, which currently doesn't return expected results (I think it must be treating the #pName param as literal text within the single quotes?):
var q = "SELECT * FROM Users WHERE Name LIKE '#pName%'";
#pName is the param I assign a value to upon executing the query.
Things work if I just build the SQL like:
var q = "SELECT * FROM Users WHERE Name LIKE '" + name + "%'";
.. but I would prefer to use a param if possible.
I am executing the query using the following code:
o = _cn.Query<User>(q, new { pName = new DbString { Value = name, IsFixedLength = false, Length = 25, IsAnsi = true } }).ToList();
How do I got about this using Dapper?
SELECT * FROM Users WHERE Name LIKE #pName + '%'
I would like to add here another possible solution:
var results = cn.Query("SELECT * FROM Table WHERE Column LIKE #value", new { value = value + "%" });
The wildcard is inside the string var itself, and then we reference that var in the SQL. Applies to any wildcard pattern you want.