SQLite3 with Flask Insert only allowing 1 character - sqlite

I'm using Flask and trying to insert names (text) into an SQLite3 DB. The DB has one table (guests) and one column (name). However, it will only accept 1 character during the insert; anything more is failing.
If I hardcode 'nm' as a value, it still fails, so I don't think it's the Html template. I can manually add a value of varying length to the DB with the 'DB Browser' app, so I'm really at a loss here. Here's a code snippet.
#app.route('/addrec', methods=['POST', 'GET'])
def addrec():
msg = "msg"
if request.method == 'POST':
try:
nm = request.form['nm']
with sqlite3.connect("database.db") as con:
cur = con.cursor()
cur.execute('''Insert into guests values (?)''', nm)
con.commit()
msg = "Record successfully added"

Second argument to cur.execute should be a tuple:
cur.execute('''Insert into guests values (?)''', (nm,))
Why? If, for example, you call that argument arg then arg[0] is the string value you require (nm): the first item in that tuple.
Otherwise (when passing nm instead of the tuple) it will read nm[0] which is the first character of the string nm.

Related

Query is unable to match parts after "/" or parts within "()" in the data

I have a search request written as
import sqlite3
conn = sqlite3.connect('locker_data.db')
c = conn.cursor()
def search1(teacher):
test = 'SELECT Name FROM locker_data WHERE Name or Email LIKE "%{0}%"'.format(teacher)
data1 = c.execute(test)
return data1
def display1(data1):
Display1 = []
for Name in data1:
temp1 = str(Name[0])
Display1.append("Name: {0}".format(temp1))
return Display1
def locker_searcher(teacher):
data = display1(search1(teacher))
return data
This allows me to search for the row containing "Mr FishyPower (Mr Swag)" or "Mr FishyPower / Mr Swag" with a search input of "FishyPower". However, when I try searching with an input of "Swag", I am then unable to find the same row.
In the search below, it should have given me the same search results.
The database is just a simple 1x1 sqlite3 database containing 'FishyPower / Mr Swag'
Search Error on 'Swag'
Edit: I technically did solve it by limiting the columns being searched to only 'Name' but I intended the code search both the 'Name' and 'Email' columns and output the results as long as the search in within either or both columns.
Edit2: SELECT Name FROM locker_data WHERE Email LIKE "%{0}%" or Name LIKE "%{0}%" was the right way to go.
I'm gonna guess that Mr. FishyPower's email address is something like mrFishyPower#something.com. The query is only comparing Email to teacher. If it was
WHERE Name LIKE "%{0}%"
OR Email LIKE "%{0}%"'
you would (probably) get the result you want.

Passing list of search string in contains in FilterExpression

Is there any way to pass a list of search strings in the contains() method of FilterExpression in DynamoDb?
Something like below:
search_str = ['value-1', 'value-2', 'value-3']
result = kb_table.scan(
FilterExpression="contains (title, :titleVal)",
ExpressionAttributeValues={ ":titleVal": search_str }
)
For now I can only think of looping through the list and scanning the table multiple times (as in below code), but I think it will be resource heavy.
for item in search_str:
result += kb_table.scan(
FilterExpression="contains (title, :titleVal)",
ExpressionAttributeValues={ ":titleVal": item }
)
Any suggestions.
For the above scenario, the CONTAINS should be used with OR condition. When you give array as input for CONTAINS, DynamoDB will check for the SET attribute ("SS", "NS", or "BS"). It doesn't looks for the sub-sequence on the string attribute.
If the target attribute of the comparison is of type String, then the
operator checks for a substring match. If the target attribute of the
comparison is of type Binary, then the operator looks for a
subsequence of the target that matches the input. If the target
attribute of the comparison is a set ("SS", "NS", or "BS"), then the
operator evaluates to true if it finds an exact match with any member
of the set.
Example:-
movies1 = "MyMovie"
movies2 = "Big New"
fe1 = Attr('title').contains(movies1)
fe2 = Attr('title').contains(movies2)
response = table.scan(
FilterExpression=fe1 or fe2
)
a little bit late but to allow people to find a solution i give here my method.
lets assume that in your DB you have a props called 'EMAIL you want to filter your scan on this EMAIL with a list of value. you can proceed as following.
list_of_elem=['mail1#mail.com','mail2#mail.com','mail3#mail.com']
#set an empty string to create your query
stringquery=""
# loop each element in your list
for index,value in enumerate(list_of_elem):
# add your query of contains with mail value
stringquery=stringquery+f"Attr('EMAIL').contains('{value }')"
# while your value is not the last element in list add the 'OR' operator
if index < len(list_of_elem)-1:
stringquery=stringquery+ ' | '
dynamodb = boto3.resource('dynamodb')
# Use eval of your query string to parse the string as filter expression
tableUser = dynamodb.Table('mytable')
tableUser.scan(
FilterExpression=eval(stringquery)
)

Update random row in DB using Flask-Sqlalchemy

I've been trying to update a randomly selected row in my Sqlite database using Flask and the Flask-Sqlalchemy. I have just a few rows in the database with columns called "word", "yes", and "no", where word is a string and yes and no are integers. There are two buttons on the "vote" view, yes and no. When a button is pressed, the appropriate code executes, should increment the yes or no column, and the view is updated with a new random word from the Word table.
#app.route("/vote", methods=["GET", "POST"])
def vote():
#Get random row from database
query = db.session.query(Word)
rowCount = int(query.count())
row = query.offset(int(rowCount*random.random())).first()
#POST
# If "yes" button is pressed, increment yes column in database
if request.method == "POST":
if request.form.get("yes"):
row.yes += 1
db.session.commit()
return render_template("vote.html", row=row)
# otherwise increment no column
elif request.form.get("no"):
row.no += 1
db.session.commit()
return redirect(url_for("vote"))
#GET
# on get request, render vote.html
return render_template("vote.html", row=row)
This code is working, but the yes and no columns are only updated when the view comes back around to the random word the next time. If I close the browser right after clicking a button, the database is not incremented. I think this has something to do with db.session.commit(), or something about the session. It seems like:
row.yes += 1
is saved in the session object, but only committed when that database row is queried the next time. This code DID work when I replaced the query at the top of the method with:
row = Word.query.get(4)
which returns the row with id of 4. With this query, the yes or no column are updated immediately.
Any thoughts?
Thanks
Thanks all. I figured out the problem. The database incrementing was actually working fine, but I wasn't incrementing the correct rows. The problem was that I generated a random row from the database on each call of the vote() method, which meant that I got a random value for the GET request, and a different random value for the POST request, and ended up incrementing that different random value in the POST request.
I separated the logic out into two methods for the "/vote" route, getWord() and vote(), and created a randRow() method for the row generation. I needed to store the random row that gets generated when getWord() is called, so I used session variables so I could access the random row from the vote() method. It's a bit verbose, but seems to work.
Anyone have a better idea about how to achieve this?
#app.route('/vote', methods=["GET"])
def getWord():
wordObj = randRow()
session['word'] = wordObj.word
session['yesVotes'] = wordObj.yes
session['noVotes'] = wordObj.no
return render_template("vote.html", word=session['word'], yesVotes=session['yesVotes'], noVotes=session['noVotes'])
#app.route('/vote', methods=["POST"])
def vote():
# store session 'word' in word variable
# look up word in database and store object in wordObj
word = session['word']
wordObj = Word.query.filter_by(word=word).first()
# check button press on vote view, increment yes or no column
# depending on which button was pressed
if request.form.get("yes"):
wordObj.yes = wordObj.yes + 1
elif request.form.get("no"):
wordObj.no = wordObj.no + 1
db.session.commit()
return redirect(url_for("getWord"))
###### HELPERS ######
# returns a random row from the database
def randRow():
rowId = Word.query.order_by(func.random()).first().id
row = Word.query.get(rowId)
return row
I think you need to add the update into the session before the commit, using code like this:
[...]
row.yes += 1
db.session.add(row)
db.session.commit()
[...]
That's the pattern that I use for a basic update in Flask-SQLAlchemy.

Passing a variable into a SQL request : Attempt to concatenate local 'variable' (a table value)

I would like to pass a variable in different functions, within an SQL request, as described below :
popup = display.newImage( "interface/popup-1.png")
popup.width=568
popup.height=232
popup.anchorX=0.5
popup.anchorY=0.5
popup.isVisible=false
popup.y=-700
popup:addEventListener( 'tap', displaySpeech)
popup.destination="mycharacter"
camera:add(popup,1,false)
This is where i took my variable 'character'
function speak(event)
character = event.target.destination
displaySpeech(character)
end
num=1
function displaySpeech(character)
displaySpeech_get(""..num.."",character)
num=num+1
end
function displaySpeech_get(number,character)
for row in db:nrows("SELECT * FROM speeches WHERE character='"..character.."' LIMIT "..tostring(number)..",1") do
myMessage.text=row.speech
end
end
The first "reply" of my SQL request appareas but once i call a second time the function displaySpeech_get(number, character) it shows an error. I tried to print the variable 'character', it gets a table ID !
Any solution ?

Asp.Net SqlDataReader value magically turns into null on attempt to access and use it

I have an sql command that depends on the results of other sql commands. There are five sql commands in this chain, but the problem occurs in the 4th.
The 5th command must save data to the archive table. When it has to run and take the completion_date value from the 4th command, it throws a null reference exception. Actually it says, that Reader4[0] can't be read because it has null value. That's wrong because it has value, because in the database these queries work fine and also because the condition if (Reader4.HasRows == true) is true, it means that WHERE statement is true in the 4th command, which also includes checking the completion_date! What's wrong with this asp.net?
Command4 = new SqlCommand("SELECT trade_date FROM Schedule WHERE traider_id=#traiderID AND good_id=#goodID AND position_id=#positionID AND status_id=1 AND completion_date IS NOT NULL", Connection4); //note the completion_date check
Command4.Parameters.Add("#traiderID", Convert.ToInt32(Reader3[0]));
Command4.Parameters.Add("#positionID", CurrentPosition);
Command4.Parameters.Add("#goodID", Convert.ToInt32(Reader1[0]));
Reader4 = Command4.ExecuteReader();
if (Reader4.HasRows == true) //this check is done successfully
{
Command5 = new SqlCommand("INSERT INTO Archive (traider_id, good_id, completion_date) VALUES (#traiderID, #goodID, #completionDate)", Connection5);
Command5.Parameters.Add("#traiderID", Convert.ToInt32(Reader3[0]));
Command5.Parameters.Add("#goodID", Convert.ToInt32(Reader1[0]));
Command5.Parameters.Add("#completionDate", Convert.ToDateTime(Reader4[0])); //Here is the problem
Command5.ExecuteNonQuery();
}
Reader4.Close();
Where are you startin to read from the reader?
i.e. where do you call
Reader4.Read();
after
Reader4 = Command4.ExecuteReader();

Resources