I am working on an API endpoint (Python + Sqlite) that runs a SQL query based on the following parameters: race, gender, age, location. The caveat, however, is that all of these parameters are optional and any combination of the parameters is valid. For example, the following requests are all valid.
localhost:8000/api?age=10&gender=M
localhost:8000/api?race=Asian&age=3&location=US&gender=F
localhost:8000/api
I'm not sure how to best approach this. It seems like a simple logic puzzle, but I can't seem to wrap my head around it. The only difference between all of these would be the "Where" statement in the SQL query.
Any advice or related ideas I could look into would be appreciated. Sorry if I didn't explain the problem clearly, I am struggling to even articulate the issue. Thanks.
What you can do is construct the SQL query based on the parameters received in the incoming request.
Simple pseudo code :
SQLquery = "SELECT * FROM mytable "
if there are any parameters
SQLquery = SQLquery + "WHERE "
any more parameters?
SQLquery = SQLquery + " and "
if input request has age
SQLquery = SQLquery + "age = " + agevalue
any more parameters?
SQLquery = SQLquery + " and "
if input request has race
SQLquery = SQLquery + "race = " + racevalue
any more parameters?
SQLquery = SQLquery + " and "
if input request has gender
SQLquery = SQLquery + "gender = " + gendervalue
any more parameters?
SQLquery = SQLquery + " and "
if input request has location
SQLquery = SQLquery + "location = " + locationvalue
Use SQLquery to fetch data from database
Related
Solution: I had an out of date version of sqlite installed which didn't support RANK(). I fixed this by installing Python3.7.4
I am trying to find the position of a user when they are sorted in descending order based on the sum of two columns. I tested this query in SQLite DB Browser and it returned the correct result, but when I copied it into my Python script it throws a syntax error at one of the "("
I have tried running the code and stopping it just before it executes the query so that I can copy the query verbatim into the db browser. When I do that it works perfectly, but when I execute the query in my script it fails
Here is the plain text query that the string concatenation returns:
SELECT top_rank FROM (
SELECT username, RANK() OVER(ORDER BY summed DESC) AS 'top_rank'
FROM (
SELECT SUM(positive_qc) - SUM(negative_qc) AS 'summed', username
FROM sub_activity
WHERE sub_name IN('cryptocurrency', 'cryptomarkets', 'cryptotechnology', 'blockchain')
GROUP BY username)
) WHERE username = 'someuser'
Here is the code I use to get that query:
select_str = "SELECT top_rank FROM(" + \
"SELECT " + self.KEY2_USERNAME + ", RANK() OVER(ORDER BY summed DESC) AS 'top_rank' " \
"FROM(" \
"SELECT SUM(" + self.KEY2_POSITIVE_QC + ") - SUM(" + self.KEY2_NEGATIVE_QC + ") " \
"AS 'summed', " + self.KEY2_USERNAME + " " \
"FROM " + self.TABLE_SUB_ACTIVITY + " " \
"WHERE " + self.KEY2_SUB_NAME + " IN('" + "', '".join(sub_list) + "') " \
"GROUP BY " + self.KEY2_USERNAME + ")" \
") WHERE " + self.KEY2_USERNAME + " = ?"
The exact error I get when executing it in the script is
sqlite3.OperationalError: near "(": syntax error
Update: I have narrowed down the error to the RANK () OVER(ORDER BY summed DESC) portion of the query
Give this a try... I aliased each subquery. ui and uo.
SELECT top_rank FROM (
SELECT username, RANK() OVER(ORDER BY summed DESC) AS 'top_rank'
FROM (
SELECT SUM(positive_qc) - SUM(negative_qc) AS 'summed', username
FROM sub_activity
WHERE sub_name IN ('cryptocurrency', 'cryptomarkets', 'cryptotechnology', 'blockchain')
GROUP BY username) ui
) uo WHERE username = 'someuser'
I have two web services called getCourseCodeWS and checkStudentOnCourseWS both with 1 corresponding DB. The first WS returns a courseCode from a DB. This courseCode should work as a parameter in my checkStudentOnCourseWS which should use the courseCode + another parameter called personalIdentityNumber, which I get from checkStudentOnCourseWS's DB. This should return a true/false depending on if the arguments match the database, in other words, if the student appears in the course.
My question is how do I request the actual respons I get from my getCourseCodeWS to work as an argument for checkStudentOnCourseWS?
#app.route('/courses/<course>/<period>', methods= ["GET"])
def checkCourseCodeWS(course, period):
myCursor2 = mydb.cursor()
query2 = ("SELECT courseCode FROM paraplyet.courseInfo WHERE courseName = " + "'" + course + "' AND duration = " + "'" + period + "'")
myCursor2.execute(query2)
myresult2 = myCursor2.fetchall()
return jsonify(myresult2)
I am wondering how to securely parameterize a dynamic mysql query in python. By dynamic, I mean it changes depending on how the if statements evaluate.
I understand how to parameterize a mysql query in python, by using a comma, rather than a percent sign, like as follows.
c.execute("SELECT * FROM foo WHERE bar = %s AND baz = %s", (param1, param2))
Here is an example of a 'dynamic query'. I am looking to find a more secure way than using the percent sign.
def queryPhotos(self, added_from, added, added_to):
sql = "select * from photos where 1=1 "
if added_from is not None:
sql = sql + "and added >= '%s' " % added_from
if added is not None:
sql = sql + "and added = '%s' " % added
if added_to is not None:
sql = sql + "and added <= '%s' " % added_to
Thank you for your insight.
thanks to #Nullman I came to an answer.
def queryPhotos(self, added_from, added, added_to):
vars = []
sql = "select * from photos where 1=1 "
if added_from is not None:
sql = sql + "and added >= %s "
vars.append(added_from)
if added is not None:
sql = sql + "and added = %s "
vars.append(added)
if added_to is not None:
sql = sql + "and added <= %s "
vars.append(added_to)
vars = tuple(vars)
results = c.execute(sql, vars)
I need to insert a record into the table MemberDetails but I end up with the error stating " _mysql_exceptions.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 'I' at line 1") "
sql5="INSERT INTO MemberDetails VALUES"+"("+"'2016-2020','"+PhoneNum+"','VEC','"+Address+"','"+StuID+"','"+DOB+"','1000','"+Name+"','"+Pass+"','"+dept+"','"+year+"','"+sec+"')"
cursor.execute(sql5)
You need to add spacing as well as the columns in the table each variable will be inserted into, your query should be like this:
"INSERT INTO MemberDetails (datetime, phone, code, address, stuid, birthdate, num, name, pass, dept, year, sec) VALUES (" + "'2016-2020','" + PhoneNum + "','VEC','" + Address + "','" + StuID + "','" +DOB +"','1000','" + Name + "','" + Pass + "','" + dept + "','" + year + "','" +sec + "')"
Just replace the variables in the first set of brackets with the column name you want each variable to be put into.
I have a script that pulls data from a weather API & save this info into a MySQL database on localhost. I want to have the UPDATE script prevent any SQL injection but the following doesn't seem to run the UPDATE at all. There isnt an error just the query doesn't seem to have been executed when I check the database.
Can anyone suggest the problem? I am using the mysql.connector import/plugin
def save_to_database(self, uid):
sql = "UPDATE weather_data " \
"SET temperature=%s, temperature_feels=%s, humidity=%s, precipitation=%s, weather_status=%s " \
"WHERE UID =%s"
temperature = self.weather_data['temperature']
temperature_feels = self.weather_data['temperature_feels']
humidity = self.weather_data['humidity']
precipitation = self.weather_data['precipitation']
weather_status = self.weather_data['type']
print(sql)
c = self._db.cursor()
c.execute(sql, (temperature, temperature_feels, humidity, precipitation, weather_status, uid))
UPDATE
The following works fine - but isn't 'safe'
def save_weather_forecast(self, uid):
print(self.weather_data);
sql = "UPDATE weather_data SET temperature = "+ str(self.weather_data['temperature']) + ", " \
+"temperature_feels = "+ str(self.weather_data['temperature_feels']) +", " \
+"humidity = "+ str(self.weather_data['humidity']) +", " \
+"weather_status = '"+ str(self.weather_data['type']) +"', " \
+"precipitation = "+ str(self.weather_data['precipitation']) +"" \
+" WHERE UID = '"+ str(uid) +"'"
print(sql)
c = self._db.cursor()
c.execute(sql)
c.close()
The Python DB API standard explicitly turns off auto commit which means you have to commit any transactions manually otherwise they are not effected at the database.
Committing is done at connection, so you need to add:
self._db.commit()
After the c.execute() line.