I would be happy to use ? placeholder to populate ids for SQL IN clause. Unfortunately the following does not work
let idList :: [ RequestId ]
idList = []
let sql :: String
sql = "SELECT ?? FROM request WHERE request.id IN ?"
rs <- runDB $ rawSql sql [ toPersistValue idList ]
Such code results in database error similar to:
syntax error at or near "'[283,282,281]'"
Wrapping ? placeholder with brackets (e.g. IN (?)) gives another type of error:
invalid input syntax for integer: "[283,282,281]"
Is there a way to accomplish this?
P.S. Looks like it's a horrible title, have no idea how to improve that
I don't think there is a way to do it with persistent.
postrgresql-simple (assuming that we are talking about Postgres here) which is used by persistent does have special In construct which is correctly translated into In (..) in SQL, but persistent doesn't seem to use it.
One may hope that a workaround is to use PersistDbSpecific constructor which takes ByteString as an argument (so we could manually render and pass something like (123,456,789)) but unfortunately it is converted into SQL via Unknown which is then rendered via Escape which not only escapes the string but also encloses it into quotes which makes our SQL invalid. If persistent were using Plain (which in my view would make much more sence) this approach would work, but unfortunately it is not the case.
The solution is to not use IN, but the more flexible ANY function:
let idList :: [ RequestId ]
idList = []
let sql :: String
sql = "SELECT ?? FROM request WHERE request.id = ANY(?)"
rs <- runDB $ rawSql sql [ PersistArray (map toPersistValue idList) ]
(PersistArray makes sure persistent renders the list using array literals. toPersistValue alone gives a syntax error).
You can read more about the syntax at https://www.postgresql.org/docs/13/functions-comparisons.html (look at the ANY/SOME (array) section).
Related
I have the following query for a PostgreSQL databse using knex:
knex('mytable').select('name').then(function(rows) {
console.log(rows[1].name);
var a = "Test";
var b = rows[1].name;
console.log(a + " " + b)
})
The query is working however the "rows[1].name" value is a... object thingy whatever which looks like {"value"} instead of simply a string containing the value 'value'.
My question here is: Am I doing something "wrong" ? Are we generally speaking supposed to work with this type of values when using SQL databases rather than plain old string values ? If so how exactly should i treat these objects (say if I wished to display the value inside of it on an html page)?
Furthermore, if I am to convert this object to a string, is there a knex function that allows me to do so (obviously I can do it using plain of js and substr but I'd think it would be rather inefficient, possibly not "The right way" to do such a thing) ?
I am not using prepared statements and i dont want to use it if not necessary
Example :
$sqlServ = new mysqli(SQL_HOST, SQL_USER, SQL_PASS);
$char = isset($_GET['char']) ? sanitize($_GET['char']) : null;
$check = $sqlServ->query("SELECT name FROM player.player WHERE name LIKE '{$char}'");
function sanitize($var)
{
$var = htmlentities($var, ENT_QUOTES);
$var = htmlspecialchars($var, ENT_QUOTES, 'UTF-8');
if (get_magic_quotes_gpc()) {
$var = stripslashes($var);
}
return $var;
}
Is it enough for sql injection protection?
Thanks for answer.
$var = htmlentities($var, ENT_QUOTES);
This is a bad idea. HTML-encoding is for the output stage, where you <?php echo htmlspecialchars($var); ?> variables in an HTML template. If you try to handle this output-time concern at input-time you end up with input that is unnecessarily encoded in the database, preventing you from properly matching, slicing and sorting it. And if you then output the content from the database without escaping, you've still got XSS bugs for any content that comes in through a means other than form input.
HTML-encode when creating HTML and at no other time.
$var = htmlspecialchars($var, ENT_QUOTES, 'UTF-8');
Huh? It's already HTML-encoded, why double-encode it? This is guaranteed to mangle characters like & and <, as well as (because of the previous htmlentities) all non-ASCII characters.
Is it enough for sql injection protection?
Not exactly. Mainly: there is no SQL injection protection code here at all.
There is HTML-escaping, but backslashes are special characters in MySQL string literals, and backslashes are not touched by HTML-escaping. So input strings with a trailing backslash break the end ' in the query, making the query invalid.
It so happens that because there are no other ' characters or injections in the string after that, there isn't a way to exploit this particular query; you can only make it break. But as soon as the query changes that's no longer true.
To do SQL injection ‘protection’, you would call $sqlServ->real_escape_string() on the value just before putting it into the string literal in the query. But this is really easy to forget or get wrong. Using parameterised queries consistently is a more reliable approach and no more difficult.
I am bridging R and psql, wish to remove vulnerability to sql injection. Looking at documentation, I had hoped that:
postgresqlExecStatement(con, statement, params, ...)
Would allow use of something like:
postgresqlExecStatement(con, "DELETE FROM foos WHERE id = ? AND baz = ?", c(1, "bar"))
But unfortunately this does not seem to work. Maybe I'm using the wrong
symbol for parameter (something other than ?).
Best compromise I've found is escaping strings via:
postgresqlEscapeStrings(con, string)
(note: connection is necessary so function can know how to properly escape).
Means I have to escape every string I use in a paste when putting together
my queries. Not so elegant. But seems best option. Anyone have other
ideas?
Use
postgresqlExecStatement(con, "DELETE FROM foos WHERE id = $1 AND baz = $2", list(1, "bar"))
I always pass my parameters to be bound as a list since c will force it into one mode. You also have to clear the results belonging to con if this statement succeeds before you can use it again.
Also, please note hadley's comments to use the new package RPostgres.
This question already has answers here:
Is there an equivalent of PHP's mysql_real_escape_string() for Perl's DBI?
(5 answers)
Closed 9 years ago.
I've a set of elements in an array which is read from a file.Now i want to use this array value in sql statement in in Claus!for that i need to enclose these string by '(single quote).so I've tried with for loop to do this! is there any way to do this same opp? like any in build functions like qw...
code:
open FILE, "<tab_name.txt" or die $!;
my #tab=<FILE>;
chomp(#tab);
#tab=split(",",$tab[0]);#set of like eg:$tab[0]=asc,cdf,sad,casd,aea,aee,asdf
my #sql_str=();
foreach my $item(#tab){
$item="'".$item."'";
push(#sql_str,$item);#add comma
push(#sql_str,",");
}
pop(#sql_str);#remove lase unwanted comma
i got the desired output like 'asc','cdf','sad','casd','aea','aee','asdf'
but is there any way to do this?
Do You need an array, or a string fr the in clasue? I assume a string is proper, so what about this?
my $sql_str = join ",", map { $dbh->quote $_ } split ",", $tab[0];
But Miguel Prz is right, You should use parameter binding instead! This will save Your Oracle server for parsing over and over again the same SQL statements.
Other minor issue. If You use my #tab=<FILE>; it will read the whole file. But in the code only the first line is used. So You could use my $tab = <FILE>; to read only the first line.
To do this with placeholders (i.e., properly), you need to first gather all the values for the IN clause into a single array (#values) so that you know how many of them there are, then:
my $in_clause = join(', ', ('?') x scalar #values);
my $sql_str = "select field1, field2 from my_table where id in ( $in_clause )";
my $sth = $dbh->prepare($sql_str);
$sth->execute(#values);
(scalar isn't strictly necessary here, but included to make it a little more obvious what's going on for the OP.)
This may works:
my $sql_str = join ',' => map { $_ = qq|'$_'|; } #tab;
But, manually building your SQL this way is a bad idea. Parameter binding is the proper way to solve this problem.
Alright, I'm trying to query a sqlite database. I was trying to be good and use the query method of SQLiteDatabase and pass in the values in the selectArgs parameter to ensure everything got properly escaped, but it wouldn't work. I never got any rows returned (no errors, either).
I started getting curious about the SQL that this generated so I did some more poking around and found SQLiteQueryBuilder (and apparently Stack Overflow doesn't handle links with parentheses in them well, so I can't link to the anchor for the buildQuery method), which I assume uses the same logic to generate the SQL statement. I did this:
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(BarcodeDb.Barcodes.TABLE_NAME);
String sql = builder.buildQuery(new String[] { BarcodeDb.Barcodes.ID, BarcodeDb.Barcodes.TIMESTAMP, BarcodeDb.Barcodes.TYPE, BarcodeDb.Barcodes.VALUE },
"? = '?' AND ? = '?'",
new String[] { BarcodeDb.Barcodes.VALUE, barcode.getValue(), BarcodeDb.Barcodes.TYPE, barcode.getType()},
null, null, null, null);
Log.d(tag, "Query is: " + sql);
The SQL that gets logged at this point is:
SELECT _id, timestamp, type, value FROM barcodes WHERE (? = '?' AND ? = '?')
However, here's what the documentation for SQLiteQueryBuilder.buildQuery says about the selectAgs parameter:
You may include ?s in selection, which
will be replaced by the values from
selectionArgs, in order that they
appear in the selection.
...but it isn't working. Any ideas?
The doc for SQLiteQueryBuilder.buildQuery also says, "The values will be bound as Strings." This tells me that it is doing the straight-forward thing, which is writing the SQL leaving the ? parameter markers in place, which is what you are seeing, and binding the selectArgs as input parameters.
The ? are replaced by sqlite when it runs the query, not in the SQL string. The first string in the array will go where you see the first ?, and so on, when the query actually executes. I would expect the logged SQL to still have the ? markers.
Probably, your query fails because you are quoting the ?. For example, don't use WHERE ID = '?', just use WHERE ID = ?, and make sure the selectArgs is a string that satisfies the query.
Two things:
The ? substitution will not be done at this point, but only when the query is executed by the SQLiteDatabase.
From what I've seen, ? substitution only works for the right side of comparison clauses. For example, some people have tried to use ? for the table name, which blows up. I haven't seen anyone try using ? for the left side of the comparison clause, so it might work -- I'm just warning you that it might not.