Python MySQL INSERT query doesn't get executed - python

I'm currently writing a chat bot with plugin functionality and at the moment, I'm working on a permission system.
However, my insert query into my database somehow doesn't work. If I do it by hand, it works flawless.
Here's that piece of code... hopefully you see what I try here:
def dothis(message):
if message.content.split()[1].lower() == "op":
user = get_member_by_name(message, message.content.split()[2])
try:
pmcon = mdb.connect(db_server, db_user, db_pass, db_name)
pmcur = pmcon.cursor()
pmcur.execute("INSERT INTO users (username,userid,hasop) VALUES (\'{}\',\'{}\',{})".format(message.content.split()[2], user.id, "TRUE"))
except: mdb.Error, e:
print "Error %d: %s" % (e.args[0], e.args[1])
finally:
if pmcon:
pmcon.close()
I already tried putting the query in a string and let it be printed out, but I don't see an error.
Am I doing something wrong?

if your database connection is not configured to autocommit, you need to commit your statements:
pmcon.commit()
(after the execute statement.)

Related

psycopg2 why is the schema not created?

im trying to create a schema in postgres database using psycopg2.
For some reason the schema is not created and later on the code crashes because it tries to refer to the missing schema. The connection is set to auto commit mode, which definetly works because i can create a database with this specific connection.
For debugging purposes i have wrapped every step in it's own try/except statement.
Code is below, as it is right there, it does not raise any exceptions, just the follow up crashes because the schema is missing.
def createDB(dbName, connString):
conn = psycopg2.connect(connString)
conn.set_session(autocommit =True) # autocommit must be True sein, else CREATE DATABASE will fail https://www.psycopg.org/docs/usage.html#transactions-control
cursor = conn.cursor()
createDB = sql.SQL('CREATE DATABASE {};').format(
sql.Identifier(dbName)
)
createSchema = sql.SQL('CREATE SCHEMA IF NOT EXISTS schema2;')
searchpath = sql.SQL('ALTER DATABASE {} SET search_path TO public, schema2;').format(
sql.Identifier(dbName)
)
dropDB = sql.SQL('DROP DATABASE IF EXISTS {};').format(
sql.Identifier(dbName)
)
try:
cursor.execute(dropDB)
except Exception as e:
print('drop DB failed')
logging.error(e)
conn.close()
exit()
try:
cursor.execute(createDB)
except Exception as e:
print('create DB failed')
logging.error(e)
conn.close()
exit()
try:
cursor.execute(createSchema)
print('schema created')
except Exception as e:
print('create schema failed')
logging.error(e)
conn.close()
exit()
try:
cursor.execute(searchpath)
except Exception as e:
print('set searchpath failed')
logging.error(e)
conn.close()
exit()
conn.close()
Adding an explicit commit does not do the trick either.
What am i missing?
EDIT
I have added a small screenshot with the console logs. As you can see, the code below gets executed.
EDIT 2
Out of sheer curiosity, i have tried to execute this very SQL statement in pgadmin:
CREATE SCHEMA IF NOT EXISTS schema2
and it works just fine, which shows, that my SQL is not wrong, so back to square one.
EDIT 3 -- Solution
So i have come up with a solution, thank to you #jjanes for pointing me in the right direction. This function does not connect to a specific database, but the server as a whole, since im using it to create new databases, hence the connection string looks something like this :
user=postgres password=12345 host=localhost port=5432
Which allows me to perform server level operations like create and drop database. But schemas are a Database level operation. Moving the exact same logic to the part of the code which is connected to the newly created database works like a charm.
You create the schema in the original database specified by the connect string. Once you create the new database, you need to connect to it in order to work in it. Otherwise, you are just working in the old database.

mysql.connector.cursor.execute() proceeds silently but makes no changes despite commit()

I need to execute certain MySQL commands in a python script, which is a straight-forward task. For testing purposes I have boiled down the commands to this:
import mysql.connector
script = """
CREATE DATABASE `new_project`;
CREATE TABLE `new_project`.`category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
UNIQUE KEY `unq_name` (`name`),
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
"""
connection = mysql.connector.connect(
host="localhost",
port="3306",
user="root",
passwd="somepassword",
)
cursor = connection.cursor()
try:
print("begin execution")
cursor.execute(script, multi=True)
warnings = cursor.fetchwarnings()
if warnings:
for warning in warnings:
print(warning)
connection.commit()
cursor.close()
connection.close()
print("connection closed")
except mysql.connector.Error as err:
print(err.msg)
The user credentials are replaced with the correct information when running the script.
The output of this script is
begin execution
connection closed
with no errors, warnings or other output. The database new_project is not created. When I run the same MySQL commands in another interface, they work as expected and create the database and the table.
I must be overlooking something very simple.
The documentation of execute mentions that the method returns an iterator with the results for each query when multi=True. It seems the queries are not doing anything until the iterator has been processed, regardless of commit(). However, CREATE statements do not produce any results and trying to iterate over the return value of execute results in an exception: generator raised StopIteration. This is related to a bug in the connector module and has been fixed in version 8.0.13 with support of python 3.7.
The solution is now to always iterate over the return value of execute, even if no return data is expected, and to upgrade the connector module. If the upgrade is not feasible it is possible to catch the failed iteration and continue.
The fixed code (including the part for earlier versions of the connector module) now looks something like this:
try:
results = cursor.execute(script, multi=True)
try:
for result in results:
pass
except Exception as e:
pass
warnings = cursor.fetchwarnings()
if warnings:
for warning in warnings:
# handle warning
connection.commit()
cursor.close()
connection.close()
except mysql.connector.Error as err:
# handle error
Try using password="somepassword" instead of passwd="somepassword". And remove multi=True. It'll create a warning but will still execute both of your statements.

CALL multiple procedures with python

I have a linux server and I would like to run a python script every day to run mysql procedures but I do not know how to run multiple procedures and put a condition if there is an error that it sends me an email with the description of the error. Here is my script with only one procedure:
#!/usr/bin/python
import MySQLdb
# Open database connection
db = MySQLdb.connect("localhost","user","password","bddname" )
# prepare a cursor object using cursor() method
cursor = db.cursor()
# execute SQL query using execute() method.
cursor.execute("CALL proc_commande_clts_detail7();")
# Fetch a single row using fetchone() method.
data = cursor.fetchone()
print "Database version : %s " % data
# disconnect from server
db.close()
Thank you for your help.
You can use callproc method to execute MySQL procedures
for proc_name in proc_name_list:
try:
result_args = cursor.callproc(proc_name, args=())
except Exception as e:
send_mail(str(e))
If you want to call multiple procedures, you can put callproc in some kind of loop and use try...catch for error handling.
wrapping them in try/except block and trigger email in except block?
Scheduling can be done through cron job.
import traceback
try:
cursor.execute("CALL proc_commande_clts_detail7();")
catch Exception as e:
email_msg = traceback.format_exc()
#send email logic

PostgreSQL and Python: Automated Password change

I've been trying to automate the installation of an Open Street Map Server since no one has published one yet and the task is pretty tedious. In order to do this I'm dealing with PostgreSQL databases in a script, which I left Python in charge of.
Here's the situation: Basically I'm running python scripts dealing with the database throughout bash code. I'm trying to make the install as user friendly as possible, part of that is automating the PostgreSQL setup. I prompt the user, in bash, for a password they would like to use for the postgres database that already comes with PostgreSQL. I then send their password as a command line argument to a Python script.
This is the part of the script I'm having problems with:
import psycopg2
import sys
con = None
code = sys.argv[1]
try:
con = psycopg2.connect(database='postgres', user='postgres')
cur = con.cursor()
cur.execute("ALTER USER postgres WITH PASSWORD '%s'" % code)
Basically: On the bottom line where I change the password for the postgres database, it doesn't actually work. I know this because later I am prompted in my bash script to enter the password and it results in an authentication failure.
I'm pretty new to this, so if anyone has some good advice, it would be greatly appreciated.
Please use the below code, you can generate random passwords and update them
NOTE: For this code to work, the readwrite1 user has to be present in database prior using this
from psycopg2 import Error
import psycopg2
import random
#password generation
def password_generator(password_length):
# maximum length of password needed
characters = string.ascii_letters + string.digits + '!##$%^&*()'
password = ''.join(random.choice(characters) for i in range(password_length))
return password
#define a function that handles and parses psycopg2 exceptions
def print_psycopg2_exception(err):
err_type, err_obj, traceback = sys.exc_info()
# get the line number when exception occured
line_num = traceback.tb_lineno
# print the connect() error
print ("\npsycopg2 ERROR:", err, "on line number:", line_num)
print ("psycopg2 traceback:", traceback, "-- type:", err_type)
# psycopg2 extensions.Diagnostics object attribute
print ("\nextensions.Diagnostics:", err.diag)
# print the pgcode and pgerror exceptions
print ("pgerror:", err.pgerror)
print ("pgcode:", err.pgcode, "\n")
def update_password():
password=password_generator(10)
try:
con = psycopg2.connect(host="host here",database="dbhere", user="username",password="password")
cur = con.cursor()
cur.execute("alter user readwrite1 with password %(password)s;", {'password': password})
con.commit()
except Exception as err:
# pass exception to function
print_psycopg2_exception(err)
exit(1)
finally:
print('password is: ', password)
if con:
con.close()
return password

How to avoid crashing python script when executing faulty SQL query?

I am using Python 2.7.6 and MySqldb module. I have a MySQL query that crashes sometimes. It is hard to catch the rootcause for the time being. How can I avoid crashing the python script when executing the SQL query? How can I make it fail gracefully?
The code looks like something;
cursor.execute(query)
You should throw an exception:
try:
cursor.execute(query)
except mysql.connector.Error:
"""your handling here"""
Here is a link to the MySQL Python Dev guide:
You can handle run time errors by using try except block.
At last you must use finally for cleanups like close the connection , rollback , free all the used resources etc.
Here is the example ,
import mysql.connector
try:
cnx = mysql.connector.connect(user='scott', database='employees')
cursor = cnx.cursor()
cursor.execute("SELECT * FORM employees") # Syntax error in query
cnx.close()
except mysql.connector.Error as err:
print("Something went wrong: {}".format(err))
finally:
# cleanup (close the connection, etc...)

Categories