Catching SQL errors using Qt - c++

The code below doesn't work for catching sql errors with Qt and sqlite. I've also tried isNull. I'm getting a blank string for lasterror.text() and -1 for error number with working queries. I don't understand why isEmpty or isNull aren't working.
if (!query.lastError().text().isEmpty())
{
logfile(sqlstatement);
logfile("SqLite error:" + query.lastError().text());
logfile("SqLite error code:"+ QString::number( query.lastError().number() ));
}

Do you really execute your query?
Take a look at way of doing access do SQLite DB + logging in OpenSource application Mixxx (Opening database, applying query):
...
#define LOG_FAILED_QUERY(query) qDebug() << __FILE__ << __LINE__ << "FAILED QUERY [" \
<< (query).executedQuery() << "]" << (query).lastError()
...
// Check if you have QSQLITE2/QSQLITE driver avaiable
qDebug() << "Available QtSQL drivers:" << QSqlDatabase::drivers();
m_db.setHostName(...);
m_db.setDatabaseName(...);
m_db.setUserName(...);
m_db.setPassword(...);
bool ok = m_db.open();
qDebug() << "DB status:" << m_db.databaseName() << "=" << ok;
if (m_db.lastError().isValid()) {
qDebug() << "Error loading database:" << m_db.lastError();
}
...
QSqlQuery query(m_database);
query.setForwardOnly(true);
query.prepare(queryString);
if (!query.exec()) {
LOG_FAILED_QUERY(query);
return;
}
And be sure that this works :)

Related

Creating logical device in Vulkan returns -8, but only sometimes

While using a class to hold my window class and Vulkan class, this error VK_ERROR_FEATURE_NOT_PRESENT is returned when I use vkCreateDevice however, when I put the same code the class is running into the main class, it works completely fine. I also had a similar problem with getting the instance extensions via SDL_Vulkan_GetInstanceExtensions.
working main.cpp
window.createWindow();
engine.window = window.window;
try {
engine.initialize();
}
catch (XiError error) {
std::cout << "Error " << error.code << ": " << error.definition << std::endl;
}
window.instance = engine.getVkInstance();
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(engine.physicalDevice, &deviceProperties);
std::cout << deviceProperties.deviceName << ", Driver Version " << deviceProperties.driverVersion << std::endl;
try {
window.createSurface();
}
catch (XiError error) {
std::cout << "Error " << error.code << ": " << error.definition << std::endl;
}
window.mainLoop();
vkDestroyDevice(engine.logicalDevice, nullptr);
vkDestroySurfaceKHR(engine.instance, window.surface, nullptr);
vkDestroyInstance(engine.instance, nullptr);
SDL_DestroyWindow(window.window);
SDL_Quit();
not working main.cpp
try {
app.run();
}
catch (XiError error) {
std::cout << "Error " << error.code << ": " << error.definition << std::endl;
}
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(app.engine.physicalDevice, &deviceProperties);
std::cout << deviceProperties.deviceName << ", Driver Version " << deviceProperties.driverVersion << std::endl;
app.window.mainLoop();
app.shutDown();
app.run()
window.createWindow();
engine.window = window.window;
engine.createVulkanInstance();
window.instance = engine.getVkInstance();
window.createSurface();
engine.getPhysicalDevices();
engine.selectPhysicalDevice();
engine.createLogicalDevice();
window.mainLoop();
app.shutDown()
vkDestroyDevice(engine.logicalDevice, nullptr);
vkDestroySurfaceKHR(engine.instance, window.surface, nullptr);
vkDestroyInstance(engine.instance, nullptr);
SDL_DestroyWindow(window.window);
SDL_Quit();
window engine and app are pre-defined by my own classes
I've tried manually adding the different required and supported extensions, and it works, but it feels hacky and is quite a large bulk of code. If this is a weird out of scope error, I've really no idea. if any other code is needed I'll be happy to provide it and the GitHub can also be found here: https://github.com/XiniaDev/Xinia-Engine
I think your problem is that requiredFeatures in XiEngine is not initialised. You set a few values to true, but I think you need a memset(&requiredFeatures, 0, sizeof(requiredFeatures)); or similar at the start of XiEngine::XiEngine to fix it.

MySQL C++ Not reading results

I am trying to read data from a database using the 8.0.13 MySQL C++ Connector. I am able to successfully write to a database no problem, but when I try to get the results of the database (using result next) it never runs.
bool outPutBool;
string outPut;
try {
sql::Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
string test = getTest();
/* Create a connection */
driver = get_driver_instance();
con = driver->connect("tcp://ip:port", "root", "password");
/* Connect to the MySQL test database */
con->setSchema("database name");
stmt = con->createStatement();
res = stmt->executeQuery("SELECT `column name` FROM `table name` WHERE `test column` = '" + variable + "'"); //Variable is defined in the function input
while (res->next()) {
outPut = res->getString(1);
cout << outPut << endl;
cout << "Test\n"; //never runs
}
delete res;
delete stmt;
delete con;
}
catch (sql::SQLException &e) {
cout << "# ERR: SQLException in " << __FILE__;
cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << endl;
cout << "# ERR: " << e.what();
cout << " (MySQL error code: " << e.getErrorCode();
cout << ", SQLState: " << e.getSQLState() << " )" << endl;
}
Sleep(10000); //Temporary delay so I can see if anything comes up before it runs another function
if (test != outPut)
doSomething();
else
doSomethingElse();
The while loop never runs and I am clueless to why this happens as it seems to work for a lot of other people. I have included all libraries and headers in the connector library, but to no help.
Using the SQL Query function in phpmyadmin properly displays the output, so it's not the query's fault.
I would greatly appreciate it if anyone could give me some help here, and if you have any questions or need more of my code just ask. Thanks a lot for the help!
I'm not sure how, but after just simply adding a cout statement between the query and the while loop it suddenly solved itself. I removed the cout and now it's works perfectly no problem. Not sure what caused this error, but I'm happy that it solved itself after I have been trying to fix it for quite a while!
When you concatenate an SQL statement dynamically and when it then does not return the results you are expecting, it is very often that the generated SQL statement is not as you expected to be.
It's hard to tell what's wrong, because we cannot reproduce it without your DBMS, of course.
But usually one will write the SQL statement to stdout, copy it to an interactive SQL console then and see what happens:
std::string query = "SELECT `column name` FROM `table name` WHERE `test column` = '" + variable + "'";
std::cout << query << std::endl; // open console and copy/paste it to your DBMS
res = stmt->executeQuery(query); //Variable is defined in the function input

Qt ODBC driver crashes on QDatabase::open() OS X

While trying to connect to a MS SQL database the app crashes.
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
db.setHostName("test");
db.setDatabaseName("test");
db.setUserName("test");
db.setPassword("test");
qDebug() << "Is driver available:" << db.isDriverAvailable("QODBC");
qDebug() << "Drivers:" << db.drivers();
qDebug() << "Db is valid:" << db.isValid();
qDebug() << "Last error:" << db.lastError();
if (!db.open()) // Crashes here
qDebug() << "Database error";
I saw some posts where unixODBC and FreeTDS is a solution but I was unable to get it working.
The output of qDebug() calls is:
Is driver available: true
Drivers: ("QSQLITE", "QMYSQL", "QMYSQL3", "QODBC", "QODBC3", "QPSQL", "QPSQL7")
Db is valid: true
Last error: QSqlError("", "", "")

C++ MySQL-connector on Arch-Linux/arm

I have written a program using C++/C, the MySQL C++ connector and ncurses/CDK. It compiles just fine, and runs fine as well on an x86/64 architecture. It crashes, however, when run on a Raspberry Pi B+ (ArchLinux).
I realize this is a pretty hard question to answer, but maybe someone more experienced can help.
Here's the (hopefully) relevant Code:
//Open Connection to the Database
nrpeout::MYSQL_CON localhost("127.0.0.1", 3306, "root", "toor");
//localhost.write_attributes_to_console();
con = localhost.open_database_connection();
//Create a new object of type nrpeoutputquery
nrpeout::Nrpeoutputquery current_query("SELECT * FROM nrpeout", con);
//Execute query
res = current_query.execute_query();
//Close Database Connection
localhost.close_database_connection(con);
} catch (sql::SQLException &e) {
//Handle SQL-Exceptions
std::cout << "# ERR: SQLException in " << __FILE__;
std::cout << "(" << __FUNCTION__ << ") on line "
<< __LINE__ << std::endl;
std::cout << "# ERR: " << e.what();
std::cout << " (MySQL error code: " << e.getErrorCode();
std::cout << ", SQLState: " << e.getSQLState() << " )" << std::endl;
} catch(...) {
//Handle Standard Exceptions
std::cout << "Unknown Exception raised. Please contact your Administrator" << std::endl;
}
nrpeout::NrpeResultSet* currentResults = new nrpeout::NrpeResultSet(res);
Using Valgrind and GDB, I have tried to narrow the error down to the line where I create the object "currentResults".
Here's the member function that saves the query results:
nrpeout::NrpeResultSet::NrpeResultSet(sql::ResultSet* res)
{
for (unsigned int i = 0; i < res->rowsCount(); ++i)
{
res->next();
std::string command = res->getString("command");
//Shorten the String
size_t posCommand = command.find("_");
std::string shortened_command = command.substr(posCommand+1);
int ret = res->getInt("ret");
std::string text = res->getString("text");
//Shorten the Text
size_t posText = text.find("|");
std::string shortened_text = text.substr(0, posText-1);
std::string last_updated = res->getString("last_updated");
this->results.push_back(Row(shortened_command, ret, shortened_text, last_updated));
}
Well, you are not catching an exception, which you may want to handle. InvalidInstanceException is thrown when using closed databse connections, statements or resultsets.
My suggestion is to run your code with a gdb and catch exceptions:
gdb ./some-program
$ catch throw
$ r
This will break after each exception being thrown. (But also includes handled exceptions, so there may be quite a few breaks, depending on how long it takes you to get to the important part.)

SEGFAULT Getting Results Using MySQL/C++ Connector

I'm trying to display a small MySQL table via C++ using the MySQL/C++ Connector, but when I execute the following function, my program either quits with the message "Aborted" or I get a segfault. Can anyone tell me what I'm doing wrong here? I thought I followed the documentation pretty well. :/
void
addressBook::display(sql::Connection* con)
{
sql::Statement *stmt;
sql::ResultSet *res;
// Create the statement object
stmt = con->createStatement();
// Execute a query and store the result in res
res = stmt->executeQuery("SELECT * FROM address_book "
"ORDER BY last_name, first_name");
// Loop through the results and display them
if(res)
{
while(res->next())
{
std::cout << "Name: " << res->getString("first_name")
<< " " << res->getString("last_name") << std::endl
<< "Phone: " << res->getString("phone") << std::endl
<< "eMail: " << res->getString("email") << std::endl
<< "City: " << res->getString("city") << std::endl
<< "Comments: " << res->getString("comments")
<< std::endl << std::endl;
}
}
delete stmt;
delete res;
}
The full (as of yet, unfinished) program may be found here, for reference. http://pastebin.com/kWnknHi4
Also, each field in the table being called contains a valid string.
Edit The debugger message can be found here: http://pastebin.com/NnSqV8hv
It looks like you're calling delete in the wrong order. The example deletes res first.
The ResultSet destructor may reference the associated Statement.
Generally, you should do free/delete in the opposite order you created/allocated the object.
The problem was that the libraries were installed incorrectly on my system; according to the docs, you run make clean as an intermediary step, when it should just be make.
Thanks to vinleod from ##c++-basic (Vincent Damewood of http://damewood.us/) for the help in figuring that out.