pyodbc execute command not accepting ? parameters correctly? - sql

This code:
cursor.execute('select RLAMBD from ?', OPTable)
print cursor.fetchone().RLAMBD
produces this error:
ProgrammingError: ('42S02', '[42S02] [Oracle][ODBC][Ora]ORA-00903: invalid table name\n (903) (SQLExecDirectW)')
OPTable is an alphanumeric string which I've built from another database query which contains the table name I want to select from.
The following code works just fine within the same script.
sql = 'select RLAMBD from ' + OPTable
cursor.execute(sql)
print cursor.fetchone().RLAMBD
I guess it's not a huge deal to build the sql statements this way, but I just don't understand why it's not accepting the ? parameters. I even have another query in the same script which uses the ? parameterization and works just fine. The parameters for the working query are produced using the raw_input function, though. Is there some subtle difference between the way those two strings might be formatted that's preventing me from getting the query to work? Thank you all.
I'm running python 2.7 and pyodbc 3.0.10.

Parameter placeholders cannot be used to represent object names (e.g., table or column names) or SQL keywords. They are only used to pass data values, e.g., numbers, strings, dates, etc..

Related

Pandas read_sql Challenging syntax for postgres query

I am querying a postgres db using python/pandas with sqlalchemy. I have an sql query that looks like this:
SELECT table_name
FROM fixed_602fcccd0f189c2434611b14.information_schema."tables" t
WHERE table_type='BASE TABLE'
and table_schema='di_602fccd10f189c2434611be9'
and (
table_name like 'general_journal%'
or table_name like 'output_journal_line%'
or table_name like 'output_journal_tx%'
or table_name like 'flats%'
)
I've tested it in dBeaver and it works perfectly. I am now trying to pass the same query through pandas read_sql as follows:
from_string = pg_db + '.information_schema."tables"'
print(from_string)
pg_query = queries.id_tables.format(from_string,di_id)
The idea is that I construct the query with variables 'pg_db' (string) and 'di_id' (string) as I make a series of queries. The problem is the query returns empty array when done this way. No error is thrown.
I suspected the challenge is the "tables" attribute that when pandas interprets the query eg. strips off the ", but that doesn't actually seem to matter. Any thoughts on how to make this work with pandas?
UPDATE:
I have tried parameterized and met with the same problem. It seems to boil down to the FROM parameter gets passed in with double quotes. I have tried to strip these but it looks like pandas appends them anyways. In principle double quotes should be fine according to postgres docs but that doesn't seem to be the case even when doing the query in dBeaver. If I pass in the query via pandas as it is written at the top of this post, no problem. The challenge is when I try to use variables for the FROM and table_schema parameters, I get syntax errors.
It turns out that the problem disappeared when I removed the parentheses I put around the 'or' statements. I think the message is to pay attention to how you construct the query eg. form and join all the strings and variables before passing them to pandas.
That said I have used parentheses with much more complex queries in pandas and they were not a problem.
I would first suggest that you use a parameterized query for input but in some cases its just easier to use a built in function repr()
s = "SQL sometimes likes \"here\" and %s \"now\" problems"
print(repr(s))
gives
'SQL sometimes likes "here" and %s "now" problems'

Knex not properly escaping raw postgres queries

I am using Knex (with typescript) to try to query a postgres database. My database table products has a column name that I want to search through as the user types into a search box. For example, a query of just the letter 'p' should return all products with a name that contains a word that begins with 'p'. For this, I am using the ts_vector and ts_query functions. My query looks like this:
const query = ... // got from user input
const result = await knex(knex.raw('products'))
.whereRaw(`to_tsvector(name) ## to_tsquery('?:*')`, query)
.select('*')
When I run this query, I get the following error:
Unhandled error { error: select * from products where to_tsvector(name) ## to_tsquery('$1:*') - bind message supplies 1 parameters, but prepared statement "" requires 0
If I replace the whereRaw line with: .whereRaw(`to_tsvector(name) ## to_tsquery('p:*')`), it correctly runs the query, selecting products whose names contain words beginning with a P.
It seems like there is some conflict with the postgres syntax and knex's raw queries. I want to use a raw query over using `${query}:*` because I want my inputs to be sanitized and protected from SQL injection. How can I get Knex to properly escape this?
I have tried various combinations of quotes, slashes and colons, but none seem to work. Any help would be appreciated.
PostgreSQL doesn't process placeholders when they are inside quotes (and I am a little surprised that knex does).
You need to do the concatenation explicitly, either inside PostgreSQL:
.whereRaw(`to_tsvector(name) ## to_tsquery(? ||':*')`,query)
Or inside typescript:
.whereRaw(`to_tsvector(name) ## to_tsquery(?)`, query+":*")

Getting parameters error when using ibm_db_dbi sql query in python

I'm trying to use the results from one query to use in the where clause of another and cannot get it to work. at the moment i'm getting an error....
ProgrammingError: ibm_db_dbi::ProgrammingError: Exception('Statement Execute Failed: [IBM][CLI Driver] CLI0100E Wrong number of parameters. SQLSTATE=07001 SQLCODE=-99999')
My code below (eventually, 'result' will just be a variable assigned to the results from another query, but for now i'm just trying to get it to work with a static variable. Thanks in advance!
import ibm_db_dbi as db
result = ['c80fS4Pn1', '9f*hzNT21']
conn = db.connect('DRIVER=DB2 zOS;'
'DATABASE=xxxx;'
'HOSTNAME=xxxx.com;'
'PORT=xxx;'
'PROTOCOL=xxxx;'
'UID=id;'
'PWD=passord;', '', '')
cur = conn.cursor()
sql = "SELECT * FROM SCHEMA.TABLE WHERE PRIM_KEY IN (?)"
cur.execute(sql, (result))
conn.close()
The reason you get error CLI0100E is because in your code-sample you show a list (called result) with two entries, while in your query there is a single parameter-marker (?)
The number of parameters to be bound (as done by the cur.execute()), must exactly match the number of parameter-markers in the query
As you usually do not know in advance the number of rows returned from a query, you usually don't know the number of parameter-markers in advance.
You could dynamically generate the number of parameter markers to match the number of rows in the previous result-set. Or you could generate the SQL string in full without parameter markers which is inefficient and might not scale.
It is wise to do in SQL the things that SQL is good at doing, such as passing the results of a sub-query into another query. Trying to do that in client side code (instead of inside the SQL engine) may be inelegant and slow.

Get ADODB to parse unicode in where clause, prefix with N

I'm updating one of our older applications to support unicode. It's littered with literal sql queries (SELECT * FROM ...) against the ADODB libraries. Most of this is working OK until I get to the SEEK code. We have some methods that transform user data into a where clause. So it parses a dictionary and produces a string. If the user is looking for something with unicode data I need to append the statement with an N. However, when I add this to the text and pass the command through the recordset.open, ADODB throws an exception :
Failed to Parse SQL
Existing SQL output:
SELECT * FROM ACCOUNT WHERE NAME ='ӐӕӔҔҖӸӽӳ'
this goes through the record set, but fails to retrieve any data.
What I need, but is throwing the exception:
SELECT * FROM ACCOUNT WHERE NAME = N'ӐӕӔҔҖӸӽӳ'
Is there some special magic I need to do to the record set to allow the N through? Or is there another approach I need to take for this to work? (and yes, I realize we SHOULD be parameterizing the queries and that's the long-term fix, but this is spaghetti code).

Can you explain this SQL injection?

The website i worked was recently attempted to be hacked by the following SQL injection script
boys' and 3=8 union
select 1,
concat(0x232425,ifnull(`table_name`,0x30),char(9),ifnull(`table_rows`,0x30), char(9),0x252423),
3,4,5,6,7,8,9
from `information_schema`.`tables`
where table_schema=0x62646B3032 limit 44,1 -- And '8'='8
This injection returned the mysql table name. This was reported by the error reporting system on that website and we managed to fix that part however I am not able to understand what does the above injection mean?
Anyone can explain this?
Penuel
They're using a select from the Information Schema views in mysql server :
http://dev.mysql.com/doc/refman/5.0/en/information-schema.html
They use some clever hacks to rout out simple sql injection prevention techniques.
According to this the MySQL concat()
Returns the string that results from
concatenating the arguments. May have
one or more arguments. If all
arguments are nonbinary strings, the
result is a nonbinary string. If the
arguments include any binary strings,
the result is a binary string. A
numeric argument is converted to its
equivalent binary string form
So 0x232425 is converted to #$% which is simply added to the begining and end of the table_name field. Maybe just to make it easier for them to pull out the Table names later using Regex.
Later on the char(9) is equivalent to a tab as you can see here and is just there to format the output nicer.
The 3,4,5,6,7,8,9 is just there so that the columns match the boys table that they are performing the Union on.
This injection returned the mysql table name.
Do you mean that your website displayed the table name when you gave it this input, or that the query returns that when run from the mysql client? If it showed on your website, then the attacker has the ability to inject much more harmful queries. Check your data.