QSqlDatabase failing to open with no useful information using lastError() - python

I'm having trouble opening a QSqlDatabase (QSQLITE) in PyQT, and I don't seem to be getting a useful error telling me why it's failing. I'm using Python 3.4.3 and PyQt 4.11.3.
Here's a snippet of my code that I quickly hacked together just to try and get the thing working:
def __init__(self):
self.__database = QtSql.QSqlDatabase.addDatabase("QSQLITE")
if self.__database.isValid():
print("DB is Valid")
else:
print("DB is Not Valid")
if not self.__database.open():
print("Could not open database.")
print("Text: " + self.__database.lastError().text())
print("Type: " + str(self.__database.lastError().type()))
print("Number: " + str(self.__database.lastError().number()))
query = QtSql.QSqlQuery(self.__database)
query.exec("create table person (id int primary key, firstname varchar(20), lastname varchar(20))");
query.exec("insert into person values(101, 'Danny', 'Young')");
query.exec("insert into person values(102, 'Christine', 'Holand')");
query.exec("insert into person values(103, 'Lars', 'Gordon')");
And here's the output when the above is ran:
DB is Valid
Could not open database.
Text:
Type: 0
Number: -1
QSqlQuery::exec: database not open
QSqlQuery::exec: database not open
QSqlQuery::exec: database not open
QSqlQuery::exec: database not open
Any direction would be much appreciated! It's frustrating that the error messages aren't useful at all.

Dumb mistake by me. Fixed by setting a database name using QtSql.QSqlDatabase.setDatabaseName("name_here.db")

Related

How do I prevent an SQL database from being locked when using UPDATE?

I have a program that uses a couple sql databases to store data. I have a class that manages the various sql functions, such as getting a value, an entire table or just updating a value. All of the processes work fine until I run a function that uses UPDATE. I execute an UPDATE command and try to commit the change and the database is always locked. Every function I have in my custom sql class has
cursor.close
database.close
So there shouldn't be any issue with the database connection still being open. Am I missing something in this syntax that is not connecting to the database correctly? I used the extra print statements in an attempt to find out where the problem is occurring, so those can be ignored.
import sqlite3 as db
import os
databaseName = "site"
class MassDb:
def __init__(self,databaseName):
super(MassDb, self).__init__()
print("Current Directory: ",os.getcwd())
self.databaseName = databaseName
def updateValue(self, location, metric, input_value):
print("OPEN CONNECTION UPDATE - running updateValue: ",location, metric, input_value)
if self.databaseName == "site":
try:
siteConn = db.connect("site_data.db")
siteCursor = siteConn.cursor()
siteCursor.execute("UPDATE sites SET " + metric + " = ? WHERE LOCATI ON = ?", (input_value, location))
siteConn.commit()
except:
print("UPDATE FAILED")
finally:
siteCursor.close
siteConn.close
elif self.databaseName == "comp":
try:
compConn = db.connect("comp_data.db")
compCursor = compConn.cursor()
compCursor.execute("UPDATE competitors SET " + metric + " = ? WHERE NAME = ?", (input_value, location))
compConn.commit()
except:
print("UPDATE FAILED")
finally:
compCursor.close
compConn.close
print("CLOSED CONNECTION UPDATE - Update Connection Closed")
else:
print("Update Error")
MassDb("site").updateValue("Location", "CURRENT_SCORE", "100")
As #roganjosh commented, my problem was that I wasn't properly closing the database. If
commit()
is used, there's no need to close the database. However,
cursor.close()
and
conn.close()
need to be written as such. Leaving off the parentheses would be as though an attribute is being referenced, rather than a method. In order to execute the close method, the () must be present. Seems obvious now, but I wasn't aware at the time. Hopefully this can help someone else if they too run across this.
Additionally, using a context manager works and eliminates the need to use close()
with conn:
#do stuff here
commit()

Using Sqlite with WAL

I've been following Python documentation on the SQLite tutorial and I managed to create an Employee table and write to it.
import sqlite3
conn = sqlite3.connect('employee.db')
c = conn.cursor()
firstname = "Ann Marie"
lastname = "Smith"
email = "ams#cia.com"
employee = (email, firstname, lastname)
c.execute('INSERT INTO Employee Values (?,?,?)', employee)
conn.commit()
# Print the table contents
for row in c.execute("select * from Employee"):
print(row)
conn.close()
I've been reading about the Write-Ahead Logging, but I can't find a tutorial that explains how to implement it. Can someone provide an example?
I notice Firefox, which uses SQLite, locks the file in such a way that if you attempt to delete the sqlite file while using Firefox, it will fail saying "file is open or being used"(or something similar), how do I achieve this? I'm running Python under Windows 10.
conn = sqlite3.connect('app.db', isolation_level=None)
Set journal mode to WAL:
conn.execute('pragma journal_mode=wal')
Or another way (just show how to off wal mode)
cur = conn.cursor()
cur.execute('pragma journal_mode=DELETE')
The PRAGMA journal_mode documentation says:
If the journal mode could not be changed, the original journal mode is returned. […]
Note also that the journal_mode cannot be changed while a transaction is active.
So you have to ensure that the database library does not try to be clever and automatically starts a transaction.

PyHDB gets "Could not find table/view" from SAP HANA Express

I have the following Python Code [pyhdb] to connect to SAP HANA Express:
Is there an error in my code? or has it something to do with the SYSTEM user?
Error Message is:
Could not find table/view TABLE in schema APP: line 1 col 19 (at pos 18)
import os
import random
import platform
from constant import *
import pyhdb
def is_rpi():
return 'arm' in platform.uname()[4]
if is_rpi():
import Adafruit_DHT
def read_dht():
if is_rpi():
sensor = Adafruit_DHT.DHT22
humidity, temperature = Adafruit_DHT.read_retry(sensor, DHT_PIN)
if humidity is not None and temperature is not None:
print('Temp={0:0.1f}*C Humidity={1:0.1f}%'.format(temperature, humidity))
return int(humidity), int(temperature)
else:
return None, None
else:
return random.randint(20, 30), random.randint(40, 70)
if __name__ == '__main__':
connection = pyhdb.connect(host=SAP_HOST, port=39015, user=SAP_USER, password=SAP_PWD)
cursor = connection.cursor()
temp, humi = read_dht()
query = "INSERT INTO \"{}\".\"{}\" VALUES(\'{}\', {}, {}, \'{}\')".format(
SAP_SCHEMA, SAP_TABLE, DEVICE_ID, temp, humi, ROOM_NAME)
print("Executing query: "), query
cursor.execute(query)
print("New Row count: "), cursor.rowcount
connection.close()
And here is the constant code:
DHT_PIN = 4
DEVICE_ID = '0ada9de4-bc4f-4e53-990a-cbcfccaed4c4'
ROOM_NAME = 'room 101
SAP_HOST = 'hxehost'
SAP_USER = 'SYSTEM'
SAP_PWD = 'XXXXXXXXXXXX'
SAP_SCHEMA = 'APP'
SAP_TABLE = 'TABLE'
The error message
Could not find table/view TABLE in schema APP
points to the fact that the table does not exist. In order to check whether the table is known to the system you could, e.g., also run the SQL statement
SELECT * FROM TABLES WHERE SCHEMA_NAME='APP' AND TABLE_NAME='TABLE';
which would lead to an empty result set for a non-existing table.
In case of an authorization problem you could rather expect an error like
insufficient privilege: Not authorized
Regarding the question about checking the authorization, you might want to take a look into the system views EFFECTIVE_PRIVILEGES, EFFECTIVE_ROLES resp. GRANTED_PRIVILEGES and GRANTED_ROLES (refer to the SAP HANA Security Guide). Generally, a privilege can be granted either by a user or a role. Roles can contain other roles, which might make finding the authorization a bit more complex.
However, in your specific case, you could probably try the rather simple SQL query:
SELECT * FROM "PUBLIC"."EFFECTIVE_PRIVILEGES"
WHERE USER_NAME='SYSTEM' AND SCHEMA_NAME='APP' AND PRIVILEGE='INSERT';
(Depending on your scenario, you might also want to check for the UPDATE privilege.)
Please allow me to add the remark that your INSERT statement from the example probably needs to be explicitly committed to be effective, as by default the connection sets autocommit=False, if I remember correctly.
The user SYSTEM had not enough privilege to insert into table. Solved Thanks to everyone.

Accessing an encrypted SQLite3 database in Python (I have the Key)

I apologize if its redundant but I couldn't seem to find answer anywhere. I set up a password(encryption key) for my database using DB browser for SQLite3. It uses sqlcipher.
Now I cannot access it. I'm not able to provide password\key. Here's my code:
import sqlite3
from Data.Item import item
import sys
conn = sqlite3.connect('maindb.db')
c = conn.cursor()
c.execute("PRAGMA KEY = 'password'")
def items():
c.execute("SELECT * FROM Item")
data=c.fetchall()
details=items()
My platform is Windows.
I've tried pysqlcipher, It does not gets installed throws an error. How do I proceed from here? What should I do?
My goal is to make my database file unreadable for some obvious reasons.
I get the following error:
c.execute("SELECT * FROM Item")
sqlite3.DatabaseError: file is encrypted or is not a database

MySQL Connector in Python does not allow LOAD DATA INFILE Syntax

I' m trying to send a text file into MySQL database. I am trying to do this with mysql connector in python 3.2. The problem is about LOAD DATA INFILE syntax. You can find my code above. My first question is is there anyway to solve this problem. Note that I have tried local-infile =1 option and Python does not allow this option. Second, is there any other way to send this data as a block into the mysql database?
from __future__ import print_function
import os
import mysql.connector
from mysql.connector import errorcode
config = {
'user':'root',
'password':'3778',
## 'host':'localhost',
# 'database':'microstructure',
# 'local-infile':'1',
}
DB_NAME = 'EURUSD'
TABLES ={}
TABLES['microstructure']=(
"CREATE TABLE `microstructure` ("
# " `p_id` int NOT NULL AUTO_INCREMENT,"
" `ticker` varchar(255),"
" `time` date,"
" `last_price` decimal(6,3)"
") ENGINE=InnoDB")
TABLES['cumulative']=(
"CREATE TABLE `cumulative` ("
" `p_id` int NOT NULL AUTO_INCREMENT,"
" `ticker` varchar(255),"
" `time` date,"
" `last_price` decimal(6,3),"
" PRIMARY KEY(`p_id`)"
") ENGINE=InnoDB")
cnx = mysql.connector.connect(**config)
cursor = cnx.cursor()
path_txt = 'C:/Users/ibrahim/Desktop/testfile.txt'
def create_database(cursor):
try:
cursor.execute(
"CREATE DATABASE IF NOT EXISTS {} DEFAULT CHARACTER SET 'utf8'".format(DB_NAME))
except mysql.connector.Error as err:
print("Failed creating database: {}".format(err))
exit(1)
try:
cnx.database = DB_NAME
except mysql.connector.Error as err:
if err.errno == errorcode.ER_BAD_DB_ERROR:
create_database(cursor)
cnx.database=DB_NAME
else:
print(err)
exit(1)
for name, ddl in TABLES.items():
try:
print("Creating table {}: ".format(name), end ='')
cursor.execute(ddl)
except mysql.connector.Error as err:
if err.errno == errorcode.ER_TABLE_EXISTS_ERROR:
print("Already exists")
else:
print(err)
else:
print("OK")
cursor.execute("SET ##global.local_infile = 1")
cursor.execute("LOAD DATA LOCAL INFILE 'testfile.txt' into table microstructure")
os.system("start")
cursor.close()
I just saw this old post, but None of theses answers solved my problem.
I saw here that there is an argument dedicated for LOCAL DATA INFILE:
allow_local_infile=True
So it is possible to do:
mysql.connector.connect(user='[username]', password='[pass]', host='[host]', allow_local_infile=True)
When in MySQLdb I use this to enable LOAD DATA LOCAL INFILE feature:
MySQLdb.connect(..., local_infile=True)
I had similar problems too. I am new to python and mysqldb. i added a conn.commit and it worked.
it seems that it protects the database by requiring a commit.
I am using:
MySQL server 8.0.25
mysql-connector-python 8.0.25
Python 3.8.10
#Maaz's answer to this question worked for me. I can't comment, so I thought I would post an answer to show activity on this page.
I also dug a little bit after the fact that adding this argument made a difference despite it shouldn't since the default should be allow_local_infile=True according to #abu and the link provided.
After a quick dive into the constructor of mysql.connector.connect, I found that the default eventually traced to [python packages]\mysql\connector\constants.py, in which it listed defaults for many of the arguments, one of which was 'allow_local_infile': False.
I hope this helps any people finding this problem in the future! :D
What version of mysql.connector are you using? I'm on 1.0.11 and I got the feature working. What I did is create data.txt with three lines (1, 2, 3), cd into it, start python 3.3.1, then ran:
import mysql.connector
conn = mysql.connector.connect(database='test', user='test', password='xx')
curs = conn.cursor()
curs.execute('''CREATE TABLE foo (id text)''')
curs.execute('''LOAD DATA INFILE '/<full path to>/data.txt' INTO TABLE foo''')
curs.execute('''SELECT * FROM FOO''')
print(curs.fetchall())
curs.execute('''DROP TABLE foo''')
My output:
[('1',), ('2',), ('3',)]
Note that you'll need to grant the FILE privilege to the 'test' user, e.g.,
GRANT FILE ON *.* TO 'test'#'localhost';
I answered this same question here: https://stackoverflow.com/a/25495823/2364773
in short, you need to add a client flag in the connection using the client_flags parameter

Categories