SQLITE3 query in Python using current_user.email - python

I need to fetch rows of a table called records in SQLite based on a conditional query that selects only records that match value of email column = current_user.email. Current_user is the proxy for current logged in user, so I want this table to filter records only showing the records applicable to this user.
rows = c.execute("select * from records where email = current_user.email").fetchall()
There is no problem is resolving value of current_user.email. I can print it and it shows me the email. The problem is in the query the way and the way I am implementing it, does not filter the records. However when I replace current_user.email with the actual email id in quotes, for example "xyz#xyz.com", it filters perfectly.
So my question is how can I filter Sqlite column based on a value that is another variable (here: email = current_user.email), and not email = "xyz#xyz.com?

Use a ? placeholder in the sql statement, then pass the specific value you're looking for as an extra argument.
rows = c.execute("select * from records where email = ?", [current_user.email]).fetchall()

You need to add the content of the variable to your string. Right now, your SQL driver just sees "select * from records where email = user.email"
The code below should help.
rows = c.execute("select * from records where email = %(username)", {"username": current_user.email}).fetchall()
Bad Code that is vulnerable to SQL injection.
rows = c.execute("select * from records where email = {}".format(current_user.email)).fetchall()
Thanks to John Gordon for pointing it out.

Related

Passing arguments to mysql using python

I am trying to write a program in Python that accepts the user inputs and queries from the MySQL database.
My database has the following tables:-
Departments(dept_no (primary key), dept_name)
Employees(emp_no(primary key), f_name, l_name, dob, hire_date)
Salaries(emp_no(primary key), salary, from_date(primary key), to_date)
When I give the following input:- Display the employees with salary greater than 20000.
Then the program should perform the following action:-
from sqlite3 import Error
from MySQLdb import connect
def mysql_code():
try:
with connect(host="localhost", user="root", password="root", database="employees") as connection:
with connection.cursor() as cursor:
cursor.execute("SELECT e.emp_no, e.first_name, e.last_name, s.salary from employees e inner join "
"salaries s on e.emp_no = s.emp_no where s.salary > '20000'")
records = cursor.fetchall()
print(records)
print("Total results found = ", cursor.rowcount)
except Error as e:
print(e)
and display the results.
Is it possible to do so or do I have to write code for each possible query?
I previously used:
cursor.execute("SELECT * FROM {} WHERE {} like %s".format(table, column), (text,))
When I defined the query and gave the user options to choose from where I wrote a query for each of the possible user inputs like
to display all records,
search records with the first name and so on. When the user chose an option the result was displayed.
Now I want the user to give inputs such as
Display employees with salaries greater than 20000 working in dept_no d002. or similar queries.
The program should accept queries in the form of a string from the user.
The code should join the tables and display the result by joining the emp_no, first_name, last_name, salary, dept_no from the tables employees, salaries and departments respectively.
you have an error in your code the like after the on comparison is wrong
from sqlite3 import Error
from MySQLdb import connect
def mysql_code():
try:
with connect(host="localhost", user="root", password="root", database="employees") as connection:
with connection.cursor() as cursor:
cursor.execute("SELECT e.emp_no, e.first_name, e.last_name, s.salary from employees e inner join "
"salaries s on e.emp_no = s.emp_no where s.salary > '20000'")
records = cursor.fetchall()
print(records)
print("Total results found = ", cursor.rowcount)
except Error as e:
print(e)
If I'm understanding your question correctly, you want to perform customizable MySQL queries in Python, creating a constant function and passing it the query.
For this I would use f strings. With this you would create a string query
cursor.execute(f"SELECT {values_to_select} \
from {table_name} \
where {filters} \
{more_stuff/extra_queries}")
This way you can pass the values to the function and it will perform the query with the values specified.
Note: As a test this is fine, but if this code is going to be used in production, giving the end user access to queries can be a huge security risk, checkout SQL injection to see how these kinds of attacks happen. I would recommend to sanitize the given strings first so they can't create custom SQL queries.

Python, Flask, MySQL - Check if email exists in database

I'm pretty new to SQL but I need it for a school project. I'm trying to make a (python) web-app which requires accounts. I'm able to put data into my SQL database but now I need some way to verify if an e-mail (inputted via html form) already exists inside the database. Probably the easiest query ever but I haven't got a single clue on how to get started. :(
I'm sorry if this is a duplicate question but I can't find anything out there that does what I need.
if you are using SQLAlchemy in your project:
#app.route("/check_email")
def check_email():
# get email from you form data
email = request.form.get("email")
# check if someone already register with the email
user = Users.query.filter_by(email=email).first()
if not user:
# the email doesnt exist
pass
else:
# the email exists
pass
Users.query.filter_by(email=email).first() equal to SQL:
SELECT * from users where email="EMAIL_FROM_FORM_DATA"
if you are using pymsql(or something like that):
import pymsql
#app.route("/check_email")
def check_email():
# get email from you form data
email = request.form.get("email")
conn = connect(host='localhost',port=3306,user='',password='',database='essentials')
cs1 = conn.cursor()
params = [email]
# cursor return affected rows
count = cs1.execute('select * from users where email=%s', params) # prevent SqlInject
if count == 0:
# count 0 email
else:
# the email exists
# and if you want to fetch the user's info
user_info = cs1.fetchall() # the user_info should be a tuple
# close the connection
cs1.close()
conn.close()
I was able to solve my issue by simply using
INSERT IGNORE and after that checking if it was ignored with the primary key.
Thank you for everyone that helped out though!

Trying to find last insert row ID; returned value is encrypted

I'm using pypyodbc with SQL Server 2016.
I am trying to insert and grab the last id inserted into database following another user's remarks but the returned value seems to be encrypted. Is there a way to decrypt it?
def executeSQL (command):
connection = pypyodbc.connect('Driver={SQL Native Client};'
'Server=blah\blah;'
'Database=Impact;'
'uid=Admin;pwd=F$sfgdfgs99')
cursor=connection.cursor()
cursor.execute(command)
id = cursor.execute("SELECT ##IDENTITY")
connection.commit()
connection.close()
return id
sqlexecute = 'INSERT INTO PERSONS([LastName], [FirstName]) VALUES(\''+lastname.encode('utf-8')+'\',\''+firstname.encode('utf-8')+'\');\n'
lastid = executeSQL(sqlexecute)
print lastid
Output:
<pypyodbc.Cursor instance at 0x000000000B870C88>
It is not encrypted, it is telling you the type of the object that this is an instance of. In this case, it is pypyodbc.Cursor.
To fetch the actual rows, you do id.fetchall() which will return a list of the results. You can then loop over them to read the contents.

SQL Select where not working

I am using Python/Flask and trying to query my DB.
conn = sqlite3.connect('./flaskdb.db')
cur = conn.cursor()
cur.execute('SELECT email FROM users WHERE email=\'%s\'', "name")
I have 2 columns, email, password and the value name, password as one of the row/entries.
Why isn't this working? I get the error:
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 7 supplied.
I think you are getting bogged down with using prepared statements here. Try this code:
conn = sqlite3.connect('./flaskdb.db')
cur = conn.cursor()
name = 'someone#somewhere.com'
cur.execute('SELECT email FROM users WHERE email=?', (name,))
Corrections include using ? as a placeholder instead of %s, the latter which is what might be used for other databases. Also, if you want to bind a variable called name, then it too should not have quotes around it.
I have a solution:
cur.execute('SELECT password FROM users WHERE email=(?)', (email,))
you need it as a tuple and (?) as a placeholder.

SELECT FROM WHERE: 2 variables

I have a database with username and password. I want to search for both these to be matching and if it matches, user can login (and if not error shows).
However the if condition of my code doesn't ever fulfil (even when username and password match).
My SQL query must be wrong, I tried finding a solution to searching for more than one variable in a query but couldn't find an answer that worked for me unfortunately, hence why I've asked.
def userLogin(self):
username, password = self.getUserPass()
con = sql.connect("database.db")
cur = con.cursor()
cur.execute("SELECT * FROM users WHERE (?) AND (?)", (username, password))
if cur.fetchmany(size=1):
print("Username and Password match!")
else:
print("Wrong username and password combination.")
Parameter substitution simply inserts the contents of the given variables into the query. So for user "myuser" and password "mypass", the query you're running is:
SELECT * FROM users WHERE ('myuser') AND ('mypass')
This isn't going to do what you expect because you haven't specified which columns to check. Start by writing a full example query that you could run from an interactive SQLite shell. For example, if your username column is called "user" and your password column is called "pass", your query might be:
SELECT * FROM users WHERE user='myuser' AND pass='mypass'
Then just replace the variable values (including quotes if it's a string) with question marks:
SELECT * FROM users WHERE user=? AND pass=?
Substitute that query into your code and it should act as you expect.

Categories