Python aiomysql puts a set of quote around my query argument - python

I'm using python's aiomysql execute function to execute sql queries.
#asyncio.coroutine
def select(sql,args=None,size=None):
log(sql,args)
global __pool
with (yield from __pool) as conn:
cur = yield from conn.cursor()
yield from cur.execute(sql.replace('?','%s'),args or ())
if size:
rs = yield from cur.fetchmany(size)
else:
rs = yield from cur.fetchall()
__pool.close()
yield from __pool.wait_closed()
return rs
In the test function I did
#asyncio.coroutine
def test():
yield from create_pool(loop=loop,user='app',passwd='app')
sql = 'select ? from ?'
arg = ['id','users']
rs = yield from select(sql,arg)
print(rs)
global __pool
__pool.close()
yield from __pool.wait_closed()
In the terminal I got an error
pymysql.err.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 ''users'' at line 1")
There appears to be a set of quote around users. I tried changing the last ? to %s and that somehow worked, apparently the ? worked for id but not for users. Why is there a set of quote around users and how can I fix it?
Thank your for your answer

SQL parameters cannot be used for metadata with MySQL. You will need to sanitize the value and substitute it normally.

For anyone else that might have the same problem, it seems like it's impossible to use arg to refer to the tables, the table must be specified before passing into execute

Related

Check row exists in MySQL through function in python class

I am trying to implement a function in my database manager class that checks if a row (user) exists (through their email) in my MySQL table.
See code below:
def has_user(self, table_name : str, user_credentials: UserCredentials) -> bool:
mysql_hasuser_query = """
SELECT COUNT(1) FROM {t_name} WHERE email = {u_email}
""".format(t_name=table_name, u_email=user_credentials.email)
cursor = self.connection.cursor()
cursor.execute(mysql_hasuser_query)
if cursor.fetchone()[0]:
print("User exists in database!")
return True
I am receiving the following syntax error mysql.connector.errors.ProgrammingError: 1064 (42000): 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 '#gmail.com' at line 1
However, I implemented this in MySQL query editor and it worked fine. I am not sure what I am doing wrong here.
You're not quoting the email in the query. But you should use a parameter instead of formatting the string into the query.
def has_user(self, table_name : str, user_credentials: UserCredentials) -> bool:
mysql_hasuser_query = """
SELECT COUNT(1) FROM {t_name} WHERE email = %s
""".format(t_name=table_name)
cursor = self.connection.cursor()
cursor.execute(mysql_hasuser_query, (user_credentials.email,))
if cursor.fetchone()[0]:
print("User exists in database!")
return True

Save resulting dict from api into db - psycopg2

I want to save an API response, on some table of my database, I'm using Postgres along with psycopg2.
This is my code:
import json
import requests
import psycopg2
def my_func():
response = requests.get("https://path/to/api/")
data = response.json()
while data['next'] is not None:
response = requests.get(data['next'])
data = response.json()
for item in data['results']:
try:
connection = psycopg2.connect(user="user",
password="user",
host="127.0.0.1",
port="5432",
database="mydb")
cursor = connection.cursor()
postgres_insert_query = """ INSERT INTO table_items (NAME VALUES (%s)"""
record_to_insert = print(item['name'])
cursor.execute(postgres_insert_query, record_to_insert)
connection.commit()
count = cursor.rowcount
print (count, "success")
except (Exception, psycopg2.Error) as error :
if(connection):
print("error", error)
finally:
if(connection):
cursor.close()
connection.close()
my_func()
I mean, I just wanted to sort of "print" all the resulting data from my request into the db, is there a way to accomplish this?
I'm a bit confused as You can see, I mean, what could be some "print" equivalent to achieve this?
I mean, I just want to save from the API response, the name field, into the database table. Or actually INSERT that, I guess psycopg2 has some sort of function for this circumstance?
Any example You could provide?
EDIT
Sorry, I forgot, if I run this code it will throw this:
PostgreSQL connection is closed
A particular name
Failed to insert record into table_items table syntax error at or near "VALUES"
LINE 1: INSERT INTO table_items (NAME VALUES (%s)
There are a few issues here. I'm not sure what the API is or what it is returning, but I will make some assumptions and suggestions based on those.
There is a syntax error in your query, it is missing a ) it should be:
postgres_insert_query = 'INSERT INTO table_items (NAME) VALUES (%s)'
(I'm also assuming thatNAME` is a real column in your database).
Even with this correction, you will have a problem since:
record_to_insert = print(item['name']) will set record_to_insert to None. The return value of the print function is always None. The line should instead be:
record_to_insert = item['name']
(assuming the key name in the dict item is actually the field you're looking for)
I believe calls to execute must pass replacements as a tuple so the line: cursor.execute(postgres_insert_query, record_to_insert) should be:
cursor.execute(postgres_insert_query, (record_to_insert,))

Python connector error on trying to delete using user input

I have implemented most other basic database transactions including insert,update,select with similar syntax,but on trying to delete,i get error
mysql.connector.errors.ProgrammingError: 1064 (42000): 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 '%s' at line 1
What would the correct syntax be? I must delete according to user input. Here is a shortened version of my code,minus the insert,select,update part.:
elif (choice == 4):
mail=raw_input('Enter email of user to be deleted:')
print 'Deleting..'
delete_user_details(mail)
def delete_user_details(email):
sql = "DELETE FROM users WHERE email = %s"
cursor.execute(sql,email)
You need to pass query parameters to cursor.execute() as a tuple, even for a single parameter. Try this:
sql = "DELETE FROM users WHERE email = %s"
cursor.execute(sql, (email,))

Filter python mysql result

I am running a mysql query from python using mysql.connector library as per code below
cnx = mysql.connector.connect(host=mysql_localhost, user=user, password=password, database=database)
cursor = cnx.cursor()
cursor.execute("select * from settings" )
results = cursor.fetchall()
ID, server, port, user, password, temp_min ,temp_max = results[0]
print(user)
cursor.close()
cnx.close()
the result is as follow
u'admin'
I noticed that values stored in the database as varchar display with u''
how can I get the value without the u'' so the desired output is
admin
u means that this is a unicode string. You should read Unicode HOWTO for better understanding.
You can use str() to get rid of the u:
print str(user)
FYI-the u means it is unicode.
The u in front of your variable means that it is a unicode string. Is that really a problem? If you really need to convert it to a regular string you can use str(user).

Twisted - Using a Deferred for another sql query

I've got a twisted based network application. Now I would like to implement a new database design but I''m getting stuck with the Deferred object.
I write sessions into my database by using this two functions:
def createSession(self, peerIP, peerPort, hostIP, hostPort):
SessionUUID = uuid.uuid1().hex
yield self.writeSession(SessionUUID, peerIP, hostIP)
sid = self.db.runQuery("SELECT id FROM sessions WHERE sid = %s",
(SessionUUID,))
yield sid
#defer.inlineCallbacks
def writeSession(self, SessionUUID, peerIP, hostIP):
sensorname = self.getSensor() or hostIP
r = yield self.db.runQuery("SELECT id FROM sensors WHERE ip = %s",
(sensorname,))
if r:
id = r[0][0]
else:
yield self.db.runQuery("INSERT INTO sensors (ip) VALUES (%s)",
(sensorname,))
r = yield self.db.runQuery("""SELECT LAST_INSERT_ID()""")
id = int(r[0][0])
self.simpleQuery(
"""
INSERT INTO sessions (sid, starttime, sensor, ip)
VALUES (%s, FROM_UNIXTIME(%s), %s, %s)
""",
(SessionUUID, self.nowUnix(), id, peerIP))
In short words:
createSession creates an UUID for the session and calls writeSession to write this into my db. After this is written I try to select the ID of the last insert by using the UUID in the where statement and return the result.
Now my problem. To update the session information I call this function:
def handleConnectionLost(self, sid, args):
self.simpleQuery("UPDATE sessions SET endtime = now() WHERE sid = %s",
(sid))
As you can see I try to use the sid from createSession which is an Deferred object and not an integer. If I got this right and I add a Callback to handleConnectionLost it will run the query at this time so that I can use the value here. But this is not my only function where I need the sid. So it would be an overhead when I do every time a callback when I need the sid.
Is there a way that I can give my sid as an integer to my functions? So that I'm just running the query one time? How does it have to look like?
When I'm using a Deferred query with a now() statement. Will it use now() when I added this query to my Callbacks or will it use now() when the query is fired?
You can immediately get the ID after inserting a new row for later use, similar question was answered here: The equivalent of SQLServer function SCOPE_IDENTITY() in mySQL?
it will use now() when the query is fired

Categories

Resources