INTRO -
In the below python snippet,
I'm querying and fetching users' results from MySQL with the all(), then iterating the result and adding an address to a list of addresses related to a user, nothing special.
PROBLEM -
until now, I have always did it like this -
address = Address(...)
users = db.query(User).all()
for user in users :
user.addresses.append(address)
db.add(user)
db.commit()
so why when using the "SQL Expression Language" I need to iterate the result this way?
(when omitting the model notation it throws "Could not locate column in row for column")
stmt = select(User).join(Country, User.country_id == Country.id).where(Country.iso_code == iso_code).outerjoin(User.addresses)
related_users: Optional[List[User]] = db.execute(stmt).all()
if related_users:
address_in_db = self.get_or_create_address(...)
for user in related_users:
user.User.addresses.append(address_in_db ) # why this is not user.addresses.append(address)
db.add(user.User) # same here, why not just user
db.commit()
Related
My variable values are derived from the edited grid cell. The function works but the edited field name is named "Read". I fixed it by changing the column name, but I am curious why that is an error and if there are any other field name titles I should avoid.
Message=(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 'Read = 'ALL' where User_ID = 'j_adams58'' at line 1")
Table fields
| User_ID | Password | Read | Edit |
def onCellChanged(self,event):
#Establish connection
self.connect_mysql()
#Update database
key_id = str(self.GetCellValue(event.GetRow(),1))
target_col = str(self.GetColLabelValue(event.GetCol()))
key_col = str(self.GetColLabelValue(1))
nVal = self.GetCellValue(event.GetRow(),event.GetCol())
sql_update = f"""Update {tbl} set {target_col} = %s where {key_col} = %s"""
row_data = ''
self.cursor.execute(sql_update, (nVal, key_id,))
#Close connection
self.close_connection()
Read is a reserved keyword in MySQL, so you shouldn't use it as a column name, but if you really need to, you should be able to access it by putting single backticks around it, like `Read`, but again, it's really bad style and you shouldn't do it. You should also avoid using other keywords, but it's usually best to try the queries you'll run in SQL first so you can check if you can.
See: https://dev.mysql.com/doc/refman/8.0/en/keywords.html#keywords-8-0-detailed-R
I want to choose a field to Update from my sqlite3 db using postman by utilizing request.data. However, I receive this error "OperationalError at /
near "?": syntax error". I tried this code
def put(self,request,*args,**kwargs):
connection = sqlite3.connect('/Users/lambda_school_loaner_182/Documents/job-search-be/jobsearchbe/db.sqlite3')
cursor = connection.cursor()
req = request.data
for key in req:
if key == id:
pass
else:
print(key)
cursor.execute("UPDATE users SET ? = ? WHERE id = ?;",(key,req[key],req['id']) )
connection.commit()
cursor.execute("SELECT * FROM users WHERE id=?", (request.data['id'],))
results = cursor.fetchall()
data = []
# if request.data['id']
for row in results:
object1 = {}
col_name_list = [tuple[0] for tuple in cursor.description]
for x in range(0,len(col_name_list) ):
object1[col_name_list[x]] = row[x]
data.append(object1)
cursor.close()
# serializer =PostSerializer(data = request.data )
# if serializer.is_valid():
# serializer.save()
return Response(data)
You won't be able to use ? for identifiers (the database structures, like table and column names). You will need to use string interpolation to put in the column name.
f"UPDATE users SET {key} = ? WHERE id = ?"
? are basically for values (user-supplied data).
https://docs.python.org/3/library/sqlite3.html
Usually your SQL operations will need to use values from Python variables. You shouldn’t assemble your query using Python’s string operations because doing so is insecure; it makes your program vulnerable to an SQL injection attack (see https://xkcd.com/327/ for humorous example of what can go wrong).
Instead, use the DB-API’s parameter substitution. Put ? as a placeholder wherever you want to use a value, and then provide a tuple of values as the second argument to the cursor’s execute() method. (Other database modules may use a different placeholder, such as %s or :1.)
I am trying to check for a string that is being passed from a form in an html page. So the form picks up the user name and then checks the database if it already has been made. If it hasn't, it goes ahead and creates it. My errors are in the part of the logic that looks up that user name.
Note, I have commented out some areas where various errors have popped up:
import mysql.connector
import web
from mysql.connector import Error
import cgi, cgitb
cgitb.enable()
conn = mysql.connector.connect(host='localhost', database='database', user='root', password='root')
cursor = conn.cursor()
form = cgi.FieldStorage()
username = form.getvalue('username')
password = form.getvalue('password')
# check_existence = """
# SELECT username FROM members WHERE username = '%s'
# """
check_existence = """
SELECT username FROM members WHERE username = %s
"""
# cursor.execute(check_existence, username)
# "Wrong number of arguments during string formatting")
cursor.execute(check_existence, (username))
# ^pushes down to con.commit
# cursor.execute(check_existence, (username,))
# ^wrpmg number of arguments during string formatting
# with comma, the error is in commit, with comma, its in execute
conn.commit()
matches = cursor.rowcount()
Now the error is pointing to conn.commit. Though this is depending on the syntax, sometimes it points to the line above it.
Error:
=> 203 conn.commit()
<class 'mysql.connector.errors.InternalError'>: Unread result found.
args = (-1, 'Unread result found.', None)
errno = -1
message = ''
msg = 'Unread result found.'
In my limited experience, commit() is only used to save (commit) updates to the database. It looks like you're executing a select query, but doing nothing with the results, and the error is related to that. Try moving the commit to the end, or doing away with it. Try using/doing something with the results stored in the cursor. I believe the latter is the solution.
The .commit method was off to a start but it wasn't the only problem with the code. I had two problems though one of them is not posted in the original post, I will explain both.
A) cursor.rowcount returns -1. Not sure why but it does. My understanding of it was that it will return the number of rows. But you can use cursor.fetchall() instead. This will return matches in an array....but if the array is empty, it'll return an empty array.
So I used this logic:
if not(cursor.fetchall()):
the set/array is empty>> Create user
else:
something was found >>dont create user
B) This was in the rest of my code. I was checking if the connection was connected:
if conn.is_connected():
The problem with doing this is that if you do this after a .execute, it will return false. So I put it higher up in the logic, to check right when it attempts to connect to the database.
I'm trying to make a function where that returns the name of the logged in user if one can be identified or None if not. i want to do this by finding the session id from the cookie in the Bottle request if present, and using it to look up the user in the sessions table.
My code so far:
def session_user(db):
"""try to
retrieve the user from the sessions table
return usernick or None if no valid session is present
"""
cursor = db.cursor()
sessionid = bottle.request.get_cookie(COOKIE_NAME)
usernick = None
if sessionid:
cursor.execute("SELECT usernick FROM sessions WHERE sessionid=?", (sessionid,))
usernick = cursor.fetchall()
return usernick
The table in database:
DROP TABLE IF EXISTS sessions;
CREATE TABLE sessions (
sessionid text unique primary key,
usernick text,
FOREIGN KEY(usernick) REFERENCES users(nick)
);
When i use the current code in my function i get a unit test error:
line 125, in test_session_user
self.assertEqual(nick_from_cookie, None, "Expected None in case with invalid session id, got %s" % str(nick_from_cookie))
AssertionError: [] != None : Expected None in case with invalid session id, got []
See the cursor.fetchall documentation:
Fetches all (remaining) rows of a query result, returning a list. Note that the cursor’s arraysize attribute can affect the performance of this operation. An empty list is returned when no rows are available.
Since an empty list in Python is a false-y expression this normally works out well - when not doing explicit compares with False/None. Always returning a list also makes code that iterates the result set (or checks the length) easier because no special case for None has to be done.
Use the aptly named fetchone to get a single result record, or None.
Using Google App Engine with python and their database, and trying to simply see if a given row already exists.
result = db.GqlQuery(
"SELECT phone WHERE phone = :1", self.request.get('phone'))
if result is not None:
self.response.status = 409
self.response.out.write(json.dumps({
"err": self.request.get('phone') + " is already subscribed."
}))
return
This does not seem to work, even though there is no row with a given phone number. Is result always not None?
result is an instance of GqlQuery, and will never be None. You're going to have to do something like iterate over it to see if you get results.