python peewee raw query without escaping characters - python

Is there any way to prevent escaping backslash in python peewee (peewee-2.8.8) ORM?
I would like to execute query in MySQL database:
SHOW MASTER STATUS\G
The "\G" part is essential! I need to the results in vertical form.
The problem is that peewee always escapes backslash (\) so it ends in MySQL as:
SHOW MASTER STATUS\\G
and of course MySQL issues an error:
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\\G' at line 1"
I tried to use plain "execute_sql" method:
cursor = RaDatabase.execute_sql('SHOW MASTER STATUS\G')
and also "raw" method:
query = BaseModel.raw('SHOW MASTER STATUS\G')
result = query.execute()
but both ended with escaping characters.

Have you tried using a "raw" string?
cursor = RaDatabase.execute_sql(r'SHOW MASTER STATUS\G')
For what it's worth, whatever you pass in to .execute_sql() is essentially handed over to the MySQL driver (pymysql, or whatever you're using). Peewee itself does not do any escaping.

Related

Using mysql-connector-python, how to insert a "complicated" (with delimiter instruction) trigger to MariaDB?

I wish to create a trigger in MariaDB 5.5.68.
Base on this official example, I built this query:
query = ("""
DELIMITER //
create trigger set_uuid_query
before insert on DLMNT.QUERY for each row
begin
if new.id is null then
set new.id = uuid() ;
end if ;
end//
DELIMITER ;
""")
cursor = mydb.cursor()
cursor.execute(query)
for e in cursor:
print(e)
However, while this worked well with a MariaDB 5.5.64 via MySQL Workbench, this throws:
1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'DELIMITER //
create trigger set_uuid_query
before insert on DLMNT.QUERY for each' at line 1
I am afraid that this is not possible. While it is about MySQL, this answer states that DELIMITER is a client side thing.
Also, based on the last line of this doc, I though "\G" could be used as a delimiter, but this answer states something completely different (and it throws the exact same error anyway when I try it).
So, using this Python library, how can I make such a query ?
PS: the lib I am using is:
mysql-connector-python 8.0.27
You do not DELIMITER to create trigger, when using python (or any other) connector. DELIMITER is a command line client's special trick. Command line client wishes to know when to send a potentially multiline input query to the server. Usually it can rely on semicolons at the end of string, but not in the case of "complex" statements, such as trigger and stored procedure.

SQLAlchemy error when adding parameter to string SQL query

I'm trying to compose a string SQL query using SQLALchemy 1.1.2. I followed the explanation from the docs about using textual SQL but encountered a syntax error when I ran the following code:
from sqlalchemy.sql import text
# Create a database connection called "connection"...
q = text('USE :name')
connection.execute(q, name='DATABASE_NAME')
Here's the error message:
"You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near ''DATABASE_NAME'' at line 1") [SQL: u'USE %s;'] [parameters:
(u'DATABASE_NAME',)]
Since I'm using the named colon format and passing the parameters as arguments to connection.execute I can't figure out why this problem is arising. I'm using a MySQL server, but if I read the docs correctly the text method should be DB-agnostic.
Thanks in advance for the help.
According to the documentation you need to use the bindparams like so:
q = text('USE :name')
q.bindparams(name="DATABASE_NAME")
connection.execute(q)
or like this:
q = text('USE :name')
q = q.bindparams(bindparam("name", String))
connection.execute(q, {"name": "DATABASE_NAME"})
This worked for me with no issues. Edit: I was wrong, it didn't work.
The problem is the bind params is going to auto wrap your value with a single quote. So what's happening is you get the final compiles statement (which is invalid syntax):
use 'DATABASE_NAME'
If you were to create the query: "Select * from mytable where column_a=:name"; this will work. Because it's wrapping the value with single quotes.
I would suggest for your use statement to do:
q = "USE {}".format("DATABASE_NAME")
Or something similar.

Can I write a python/SQL code that is independent of the sql engine (PostGres / Sqlite)

I have a python code, in which I make SQL requests in a database. I would like to be able to switch between a postgresql (using module psycopg2) database and a sqlite one (using module sqlite3), without need of adapting my code. This means, I would like to have in my code some fixed SQL request strings, and I want to switch between the engine, only changing the definition of the database connector object, using one of those:
my_db = psycopg2.connect(...)
my_db = sqlite3.connect(...)
For the moment, I don't see any possibilty since:
Everyone knows that one should NOT use string concatenation to pass arguments to a SQL request, but rather use placeholders (from psycopg2 docu :never, NEVER use Python string concatenation ... to pass variables to a SQL query string. Not even at gunpoint. )
The synthax for placeholders are different is the 2 APIs psycopg2 and sqlite3. Even for NON-named placeholders. Psycopg uses "%" and sqlite3 uses "?":
my_cursor.execute("SELECT * FROM table WHERE id= ?", (my_id,)) # for SQLITE3
my_cursor.execute("SELECT * FROM table WHERE id= %", (my_id,)) # for PSYCOPG2
One could in principle use the SQL built-in placeholder synthax ("?"
for postgresql), but this would mean precisely preparing a SQL-string with python string concatenation, and so on... that is forbidden by 1.
I'm lacking ideas...

How to insert unicode string to mysql

the code is like below:
Connect server
MySQLdb.connect(host=ip, user='root', passwd='root',db='test',use_unicode=True,charset="utf8")
......
sql = "INSERT INTO ci(id,name) VALUES (493,u'Hello')"
print sql
ret = root.execute(sql)
.....
In the server, the tyoe of name is VARCHAR(1000). Then when i run this script, it shows error ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near
But when i replace u'Hello' with 'Hello', it is OK. So maybe it doesn't support unicode,then i insert unicode string such as "你好" to the table by GUI manually, it is also OK. I can not find what is the reason, who can help me
MySQL needs strings to be enclosed in straight quotes: '你好', 'u' symbol is not allowed. Just declare the whole string as Unicode and pass it to MySQL. Here I am using a prepared statement:
sql = u"INSERT INTO ci(id,name) VALUES (493,'你好')"
Don't forget to run "SET NAMES 'UTF-8'" (or UTF-16 - don't know, what encoding you are using) after you connect to MySQL to ensure, that the server will correctly interpret the string you send it.

Prevent MySQL-Python from inserting quotes around database name parameter

I'm working on a project that requires me to programmatically create MySQL users from a django app. I can create the users just fine:
from django.db import connection, transaction
cursor = connection.cursor()
cursor.execute("CREATE USER %s#'%'", 'username')
cursor.execute("SET PASSWORD FOR %s#'%' = PASSWORD(%s)", ('username', 'pass'))
That works perfectly. The problem is when I try to grant permissions. The database name is also determined programmatically:
cursor.execute("GRANT SELECT ON %s.* TO %s#'%'", ('dbname', 'username'))
This results in a mysql error because when it does the string substitution, it places single quotes around the database name, which is syntactically incorrect:
DatabaseError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''dbname'.* to 'username'#'%'' at line 1")
How do I prevent the single quotes from being added around the %s for database name? I know that I could simply do the string substitution in Python and fix this, but that could potentially cause a SQL injection vulnerability.
Sometimes placeholders won't work (as you've found out), so you'll have to use string concatenation. Be careful - validate the string, make sure it's only composed of the characters you expect (don't just look for characters you don't expect), and you should be OK. Also get another developer to check your code, and comment it to make sure no-one else thinks you ought to be using placeholders.

Categories