how to use SQL wildcard % with Queryset extra>select? - mysql

I'm using the extra() modifier in a view.
(See http://docs.djangoproject.com/en/1.1/ref/models/querysets/#extra-select-none-where-none-params-none-tables-none-order-by-none-select-params-none )
Here's the the code:
def viewname(request)
...
exact_matchstrings=[]
exact_matchstrings.append("(accountprofile.first_name LIKE '" + term + "')")
exact_matchstrings.append("(accountprofile.first_name LIKE '" + term + '\%' + "')")
extraquerystring = " + ".join(exact_matchstrings)
return_queryset = return_queryset.extra(
select = { 'match_weight': extraquerystring },
)
The two append statements above are almost completely alike except that the second adds a % SQL wildcard character. This is causing an error; the statement without the % causes no problems. What's going on with the %? I'm surprised that django thinks this character is not defined, since it's in SQL specification. For example, the following SQL statement executes just fine:
select (first_name like "Car") + (first_name like "Car%") from accountprofile;
But trying to run it via the extra() modifier in my view code and evaluating the resulting queryset gives me an error. I think "%" needs to be escaped, so I tried that already. Any ideas?

Just ran into this issue ourselves doing a extra query with LIKE. To escape a % you need to do %%
Percentage sign not working

It looks like you are missing some quotes from the 2nd string. And I'm not sure that you need to escape the percent (%) unless this is required by django.
_matchstrings.append("(accountprofile.first_name LIKE '" + term + "%" + "')")

Related

Optimizing "OR" operator to get around SQL Exception "maximum number of expressions in a list is 1000"

I have a query using the IN operator, in an array with 1000+ values. I've searched the error so far but couldn't find what I want : my SELECT is not optimized because I'm using the OR operator and it takes quite a lot of time.
I'm chopping my query into different arrays at the moment :
query = "SELECT\n" +
" filename,\n" +
" status\n" +
"FROM\n" +
" table1\n" +
"WHERE\n" +
" filename IN " + allFileNames[0];
for(int m=1; m<allFileNames.length; m++) {
query +=
" OR\n" +
" filename IN " + allFileNames[m];
}
What this does is essentially I have the allFileNames array at the moment, and each element of the array contains a string with 1000 file names. I'm using a OR operator on each element of the array.
How can I optimize all of this ? Is it possible without creating a temporary table ? Maybe using a substring, but I haven't quite found the solution yet.
Thanks in advance!
EDIT: I can't use temporary table since I don't have writing access to the database
Assuming single allFileNames entry is a single file name, then you can flatten everything under one IN statement.
query = "SELECT\n" +
" filename,\n" +
"FROM\n" +
" table1\n" +
"WHERE\n" +
" filename IN (" + allFileNames.stream().collect(Collectors.joining(","))
+")"
Because all of your conditions, joined by OR statements are using same property, you should merge them.
But if your allFileNames collections is too large, then you may consider executing your query in batches:
split your allFileNames collection to batches of 100-1000 then execute query for each batch
aggregate all results

How to insert file path into mysql table using nodejs

I am currently using mutler to upload the files to the server. Below is my query:
var insertSQL = "INSERT INTO ic_photos (icFrontURL,icBackURL,selfieURL,customer_id) VALUES ('" + frontICPath + "','"+backICPath + "','" + selfiePath + "','" + customerID + "')";
Console.log returns
"INSERT INTO ic_photos (icFrontURL,icBackURL,selfieURL,customer_id) VALUES ('public\images\frontIC_1526709299585_potato.png','public\images\backIC_1526709299595_potato2.jpg','public\images\selfie_1526709299596_potato3.jpg','41')"
But when it goes into mysql table, it shows the following value:
'publicimagesfrontIC_1526709040516_potato.png'
The slashes are missing. How can I fix this when I make the insert query ?
This replaces the backslash with two backslashes. When it got inserted into the table, it will become one backslash
frontICPath = frontICPath.replace(/\\/g, "\\\\");
In most, if not all string-based interpretation environments, a backslash is considered a special character. To use a backslash explicitly, please use: "\\".
The two slashes above consist of 4 slashes in total through the text editor.

MySQL SELECT with varying WHERE fields

At a high-level this sounds trivial, but it turns out I've been scratching my head for a a couple of hours.
Situation:
I have table T, with columns a,b,c,d,e. Column a holds a string, while b,c,d,e each hold a boolean value.
I am allowing a user to perform a kind of search, where I prompt the user to enter values for a,b,c,d,e, and return all the rows where those values all match.
In a perfect world, the user enters all values (lets say a="JavaScript" , b="true", c="false", d="false", e="true") and a resulting query (In Scala, referencing a remote DB running MySQL) might look something like this:
connection.createStatement().executeQuery("SELECT * FROM T
WHERE a = '" + a_input + "'
and b = " + b_input + "
and c = " + c_input + "
and d = " + d_input + "
and e = " + e_input + ";")
Problem:
I give the user the option to 'loosen' the constraints, so it is possible that a_input="" and b_input="", etc... Potentially all fields a,b,c,d,e can be empty ("") If a field is omitted, it should not affect the resulting response. In other words, if c is not entered, the result can contain entries where c is TRUE or FALSE
Question:
How do I write ONE query that covers the situation where potentially all fields can be empty, or just some, or none?
Just build the WHERE dynamically. Instead of always searching for c = 'whatever', only include c in the WHERE if the user supplied a value for it.
you could use
Select *
from table
where a in ('','othervalue','othervalue')
and b in ('','othervalue','morevalues')
and so on.....that is like using an or for each field and it will match even if it's empty
This is tricky because the DB contains booleans but the parms are strings. Are the parms always blank. 'true', or 'false'? If so try
(B_input=''
Or (b_input=''true' and b)
Or (b_input='false' and ((not b)))

SQL injection using the value of a parameter as its name

Am I vulnerable to sql injection if I use the the value of parameter as its name?
for(String tag : choixalerte.selectedNomExestingtags)
where += " ach.NOM_ACHTEUR LIKE :" + tag + " or ao.OBJET LIKE :" + tag + " or lot.INTITULE LIKE :" + tag + "";
// ...
Query native_query = entityManager.createNativeQuery(...);
if(choixalerte.selectedNomExestingtags != null)
for(String tag : choixalerte.selectedNomExestingtags)
native_query.setParameter(tag, "%" + tag + "%");
Yes. You should not concatenate string in a query.
If you do not want to suffer attack you have some options:
1) Do not concatenate, use "?" instead
2) Sanitize your parameters, you could remove all invalid characters. Remove like # or -- and any other kind of sql commands.
Be aware that you will need to always take a good care in this code because, if a new kind of attack appears you will need to edit the sanitize code.

MySQL Statement error in JSP

I have an issue with an sql statement and i dont know how to handle it. Here is the problem:
query = "INSERT INTO `mmr`(`userID`, `RunningProjects`, `MainOrders`) VALUES ("
+ session.getAttribute("id")
+ ",'"
+ request.getParameter("RunningProjects")
+ "','"
+ request.getParameter("MainOrders")')";
The values are obtained from the post form which contains free text. The problem is, whenever a user enters characters like ', i will get an error because that tells the compiler that the value is over here(i suppose) and now look for the next value. I don't know how to include these characters and send them to database without having an error. Any help would be appreciated. Thank you.
The character ' is used to surround literals in MySQL. And if any data contains such character as part of it, we have to escape it. This can be done using Prepared Statement in Java.
Change your query code accordingly.
query = "INSERT INTO `mmr`(`userID`, `RunningProjects`, `MainOrders`)
VALUES ( ?, ?,? )";
Now define a PreparedStatement instance and use it to bind values.
PreparedStatement pst = con.prepareStatement( query );
pst.setString( 1, session.getAttribute("id") );
pst.setString( 2, request.getParameter("RunningProjects") );
pst.setString( 3, request.getParameter("MainOrders") );
int result = pst.executeUpdate();
And, I suggest use of beans to handle business logic.
change
query = "INSERT INTO `mmr`(`userID`, `RunningProjects`, `MainOrders`) VALUES ("
+ session.getAttribute("id")
+ ",'"
+ request.getParameter("RunningProjects")
+ "','"
+ request.getParameter("MainOrders")
+ "')";
I think you are using normal statement in your JDBC code. Instead, I would suggest you to use Prepared statement. Prepared statement is generally used to eliminate this kind of problem and caching issue. If you will use prepared statement I think your problem will be solved