how to see full query with values in ponyorm - python

Today i am using the sql_debug(True) that helps me to see the queries but without the values.
How could i see how ponyorm translate the query with values ?
Thank you very much.
This is an example of query i'm using.
with db_session:
access = select(p for p in Access if raw_sql('( lower(first_name) = lower($first_name) and lower(last_name) = lower($last_name) ) '
'or ( lower(first_name) = lower($last_name) and lower(last_name) = lower($first_name) ) '
'or (lower(facebook_url) = lower($facebook_url)) '
'or (lower(twitter_url) = lower($twitter_url)) '
'or (lower(linkedin_url) = lower($linkedin_url)) '))
.order_by(desc(Access.twitter_url),desc(Access.facebook_url),desc(Access.linkedin_url),
desc(Access.facebook_url))
print(access.get_sql())

I use
logging.getLogger(__name__).debug('SQL:\n\n\t\t\t%s\n', '\n'.join(unicode(x) for x in request._construct_sql_and_arguments()[:2]).replace('\n', '\n\t\t\t'))
for that.
For example,
19:30:01.902 data.py:231 [DEBUG] SQL:
SELECT "x"."_id", "x"."filename", "x"."_created", "x"."_updated"
FROM "reports" "x"
WHERE "x"."_id" <= ?
AND "x"."_created" >= ?
(50, '2019-04-17 19:30:01.900028')
will be printed out.

You can use set_sql_debug(debug=True, show_values=True).
Reference here.

There is a method called get_sql()
query_obj = select(c for c in Category if c.name.startswith('v'))
sql = query_obj.get_sql()
print(sql)
output:
SELECT "c"."id", "c"."name"
FROM "category" "c"
WHERE "c"."name" LIKE 'v%%'
code continue:
for obj in query_obj:
print('id:', obj.id, 'name:', obj.name)
output:
id: 1 name: viki
here is a link to the docs https://docs.ponyorm.com/api_reference.html#Query.get_sql
You can log the sql or simply print it.
Update:
OP updated the question:
If the sql query has a variable like $name it is passed as a sql parameter.
first_name = 'viki'
query = select(c for c in Category if raw_sql('( lower(name) = lower($first_name))'))
query.get_sql()
so get_sql() will return the value with a placeholder, and the output will look like this:
'SELECT "c"."id", "c"."name", "c"."age"\nFROM "Category" "c"\nWHERE ( lower(name) = lower(?))'
If we want no placeholders should be there in the query then we can avoid passing direct sql to query and instead build it separately in python.
Like this:
query = select(c for C in Category if c.name == 'viki')
query.get_sql()
output:
'SELECT "c"."id", "c"."name", "c"."age"\nFROM "Category" "c"\nWHERE "c"."name" = \'viki\''

Related

SQLAlchemy pass parameters with like '%STRING%' in raw sql

I have a sql:
select *
from my table
where exists (
select
from unnest(procedure) elem
where elem like '%String%'
)
It works well when directly execute in database ide.
My question is how can I set 'String' as a parameters ?
I have tried:
String = 'hello world'
my_query = '''
select *
from my_table
where exists (
select
from unnest(procedure) elem
where elem like '% :String %'
)
'''
result=connection.execute(text(my_query),String=String)
However it returns nothing,I think maybe "like %" is special ?
Any friend can help ?
I think a better solution is to put the percent signs in the variable itself, and have only :String in the query:
String = '%hello world%'
my_query = '''
...
where elem like :String
'''

Python SQL NOT LIKE , trying to exclude multiple values

I have a code, below, where a user can put a list of allergies. I want my code to come up with a list of recipes, that exclude the ingredients from the user allergy list. I made a test code but cannot figure out how to exclude all three ingredients at the same time.
userallergy = conn.execute ('SELECT Allergies from User where userid = 4')
userallergy = userallergy.fetchall()
userallergy = userallergy[0][0].replace(" ","")
listallergy=list(userallergy.split(","))
listallergy = ["'%" + i.capitalize() + "%'" for i in listallergy]
print([listallergy])
query='SELECT RecipeName FROM Recipess where Ingredients Not LIKE {}'.format(listallergy[1])
print(query)
aller = conn.execute(query)
saferecipe = aller.fetchall()
print(saferecipe)
Use REGEXP for a clean approach(Though you can't use it directly, check out the answer of Problem with regexp python and sqlite ):
def regexp(expr, item):
reg = re.compile(expr)
return reg.search(item) is not None
conn.create_function("REGEXP", 2, regexp)
allergies = "|".join([i.capitalize() for i in listallergy])
print(allergies)
query='SELECT RecipeName FROM Recipess where Ingredients Not REGXP \'{}\''.format(allergies)
print(query)
A simple approach is to join all the statements by AND operator(but as #alexis mentioned in comments it comes with it's own issues):
allergies = " AND ".join(["Ingredients Not LIKE '%" + i.capitalize() + "%'" for i in listallergy])
print(allergies)
query='SELECT RecipeName FROM Recipess where {}'.format(allergies)
print(query)
You may use MySQL REGEX 'OR' to exclude all three. Your query should then look like this:
query = f"SELECT RecipeName FROM `Recipess` WHERE Ingredients NOT REGEXP '{('|').join(listallergy)}'"

How can I use multiple parameters using pandas pd.read_sql_query?

I am trying to pass three variables in a sql query. These are region, feature, newUser. I am using SQL driver SQL Server Native Client 11.0.
Here is my code that works.
query = "SELECT LicenseNo FROM License_Mgmt_Reporting.dbo.MATLAB_NNU_OPTIONS WHERE Region = ?"
data_df = pd.read_sql_query((query),engine,params={region})
output.
LicenseNo
0 12
1 5
Instead i want to pass in three variables and this code does not work.
query = "SELECT LicenseNo FROM License_Mgmt_Reporting.dbo.MATLAB_NNU_OPTIONS WHERE Region = ? and FeatureName = ? and NewUser =?"
nnu_data_df = pd.read_sql_query((query),engine,params={region, feature, newUser})
Output returns an empty data frame.
Empty DataFrame
Columns: [LicenseNo]
Index: []
try a string in a tuple, also you can take out the () in the query:
so you could do something like
query = "SELECT LicenseNo FROM License_Mgmt_Reporting.dbo.MATLAB_NNU_OPTIONS WHERE Region = ? and FeatureName = ? and NewUser =?"
region = 'US'
feature = 'tall'
newUser = 'john'
data_df = pd.read_sql_query(query, engine, params=(region, feature , newUser))
Operator error by me :( I was using the wrong variable and the database returned no results because it didn't exist!

select name where id = "in the python list"?

Let's say i have a python list of customer id like this:
id = ('12','14','15','11',.......)
the array has 1000 values in it, and i need to insert the customer name to a table based on the ids from the list above.
my code is like:
ids = ",".join(id)
sql = "insert into cust_table(name)values(names)where cust_id IN('ids')"
cursor.execute(sql)
after running the code, i get nothing inserted to the table. What mistake do i have?
Please help :(
You need to format the string.
ids = ",".join(id)
sql = "insert into cust_table(name)values(names)where cust_id IN('{ids}')"
cursor.execute(sql.format(ids= ids))
Simply writing the name of a variable into a string doesn't magically make its contents appear in the string.
>>> p = 'some part'
>>> s = 'replace p of a string'
>>> s
'replace p of a string'
>>> s = 'replace %s of a string' % p
>>> s
'replace some part of a string'
>>> s = 'replace {} of a string'.format(p)
>>> s
'replace some part of a string'
In your case this would mean:
>>> sql = "insert into cust_table (name) values (names) where cust_id IN ('%s')"
>>> ids = ", ".join(id)
>>> cursor.execute(sql % ids)
although I strongly suspect that you have a similar problem with names.
In order to avoid possible sql injection problems, it would be preferable to use a "parameterized statement". This would look something like:
>>> sql = 'insert into ... where cust_id IN %s'
>>> cursor.execute(sql, (id,))
Some database connectors for python are capable of this, but yours probably isn't.
A workaround might be something like
>>> params = ', '.join(['%s']*len(id))
>>> sql = 'insert into ... where cust_id IN (%s)' % params
>>> cursor.execute(sql, id)

Error: Cursor' object has no attribute '_last_executed

I have this cursor
cursor.execute("SELECT price FROM Items WHERE itemID = (
SELECT item_id FROM Purchases
WHERE purchaseID = %d AND customer_id = %d)",
[self.purchaseID, self.customer])
I get this error
'Cursor' object has no attribute '_last_executed'
But when I try this:
cursor.execute("SELECT price FROM Items WHERE itemID = (
SELECT item_id FROM Purchases
WHERE purchaseID = 1 AND customer_id = 1)",
)
there is no error. How do I fix this?
I encountered this problem too. I changed the %d to %s, and it is solved. Wish this is useful for you.
The problem is that you are not making substitutions properly in your select string. From docs:
def execute(self, query, args=None):
"""Execute a query.
query -- string, query to execute on server
args -- optional sequence or mapping, parameters to use with query.
Note: If args is a sequence, then %s must be used as the
parameter placeholder in the query. If a mapping is used,
%(key)s must be used as the placeholder.
Returns long integer rows affected, if any
"""
So, it should be:
cursor.execute("SELECT price FROM Items WHERE itemID = (
SELECT item_id FROM Purchases
WHERE purchaseID = ? AND customer_id = ?)",
(self.purchaseID, self.customer))
The reason is that you are using '%d'. When you use '%' in SQL, the execute will interpret the '%' as the format. You should write your statement like this:
cursor.execute("SELECT price FROM Items WHERE itemID = (
SELECT item_id FROM Purchases
WHERE purchaseID = %%d AND customer_id = %%d)",
[self.purchaseID, self.customer])
Depending on your SQL package, you may need to use cursor.statement instead.
Worked for me using double %%
"SELECT title, address from table t1, table t2 on t1.id=t2.id where t1.title like '%%Brink%%' "
from django.db import connection
print(connection.queries)
The code above should display all the requeries that are executed on the request.

Categories