Suppose I have a table called 'logs' in mysql and I want to get the create query of this table in Qt(5.2 mingw).
Here is what I have done so far:
QSqlQuery query(connection);
query.prepare("SHOW CREATE TABLE logs");
if(query.exec())
{
if(query.next())
query.value(1).toString();
}
After executing the code, the query.exec() returns true but the query.next() returns false.
This query executes successfully in the mysql client(navicat) so I'm pretty sure about the query.
Note that QSqlQuery::lastError() gives -1 means no error!
I'll appreciate for any guidance or help.
query.next() is only appropriate when executing a SELECT statement. It has no meaning for any other SQL statement.
Related
I am adding a logger class to my web server and noticed that my logs are not being inserted although the query does not return a failure value.
This is my database handler class's query executer function:
//_mysql = MYSQL*
bool DatabaseConnection::query(const std::string &query) const {
return _mysql && 0 == mysql_real_query(_mysql, query.c_str(), query.length());
}
And this is the SQL query I attempted to execute:
insert into user_logs (id, action, when) value (1, 2, 1615856674);
When the C++ program executed this query it returned success however did not actually insert the row. So, I tried to manually execute it via a client and the query failed by telling me to wrap when with `.
After that the query worked as expected both in the client's console and in the C++ program.
I wonder why did it not fail in the C++ program?
"When the C++ program executed this query it returned success however did not actually insert the row."
It depdens on the client your C++ program is using. It might have simply swallowed the exeption and gives you the impression that it succeeded while it's not. To figure out why, you will need to dig into the C++ mysql client's source code.
When you try to execute queries using C++ code, try removing the terminating semicolon ;.
As an example, will not work. std::str query = "select * from table;"; But,
std::str query = "select * from table"; will work.
When Poco::Data creates an SQL statment and sends it to a database (like SQLite) is there anyway to see what SQL is generated? Say even before it is sent?
For instance in the following code (similar to one of the Poco provided samples in version 1.6.1 Poco/Data/samples/TypeHandler/src/TypeHandler.cpp) is there anyway to see the generated SQL for the INSERT statement? Even if there is an InvalidSQLException thrown eventually?
using namespace Poco::Data::Keywords;
using Poco::Data::Session;
using Poco::Data::Statement;
int main() {
Person aperson("firstName", "lastName", 1234);
Poco::Data::SQLite::Connector::registerConnector();
Session session("SQLite", "sample.db");
session << "DROP TABLE IF EXISTS Person", now;
session << "CREATE TABLE Person (Name VARCHAR(30), LastName VARCHAR(30), ID INTEGER(10))", now;
session << "INSERT INTO Person VALUES (?,?,?)", use(aperson), now;
return 0;
}
I'm not sure if it's possible for SQLite because, when binding, SQLite API wants the string with placeholders to be prepared and then bound data is bound calling sqlite3_bind*(). ODBC works differently and we can print out the native SQL string that is executed by the back-end.
db browser tool has option to execute sql. (http://sqlitebrowser.org/)
I am trying to get the SQL Server default data path via ADO/Visual C++.
I find the SQL statements that will do that in How do I find the data directory for a SQL Server instance?
So I just concat all the statements above into a CString object strStatements, then try to open a recordset as follows:
_RecordsetPtr m_pRecordset;
m_pRecordset.CreateInstance(__uuidof(Recordset));
m_pRecordset->Open(_bstrt(strStatements), _variant_t((IDispath *)m_pConnection, true), adOpenDymanic, adLockOptimistic, 0);
m_pRecordset->MoveFirst();
The last MoveFirst statement will cause com_error, which said
“ADODB.Recordset error '800a0e78'
Operation is not allowed when the object is closed.
It seems that there are no data in the recordset at all. What is the problem?
Thanks
I am using QT framework. Basically I am creating application for ARM devices.
Now I've created sample application using SQLite for DB work. Thing is that one is working in my desktop but when I cross compiled it for device and tried to execute it in my device Getting error.
So I logged some error messages. Finally i found that DB file was created successfully but unable to create table in device.
Is it because of out of memory issue?
Code :
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("songs.db");
if (!db.open()) {
QMessageBox::critical(0, qApp->tr("Cannot open database"),
qApp->tr("Unable to establish a database connection.\n"
"This example needs SQLite support. Please read "
"the Qt SQL driver documentation for information how "
"to build it.\n\n"
"Click Cancel to exit."), QMessageBox::Cancel);
//return false;
debugLog("#fileListThread::run()-> Unable to establish a database connection.."<<db.lastError(););
}
else
{
debugLog("#fileListThread::run()-> opened songs.db successfully..");
}
QSqlQuery query;
bool queryStatus = query.exec("create table songsList (id int primary key, "
"Song varchar(20), Artist varchar(20),Producer varchar(20))");
if(queryStatus)
{
debugLog("#fileListThread::run()-> created table in songs DB successfully..");
}
else
{
debugLog("#fileListThread::run()-> failed to create table in songs DB.."<<query.lastError(););
}
Okay! One more quick question-> Is it possible to create DB file and executing queries inside in embeedded devices. In my device available free memory is 9MB.
Thanks,
Vishnu
I think you should use
CREATE TABLE IF NOT EXISTS songsList
sql statement rather than
create table songsList
Otherwise once the table is created , the second time you try to execute it, you may get an error.
Other than that I don't see a problem but who knows... I hope this helps.
I am thinking of using SQLite as a backend DB for a C++ applicatiojn I am writing. I have read the relevant docs on both teh trolltech site and sqlite, but the information seems a little disjointed, there is no simple snippet that shows a complete CRUD example.
I want to write a set of helper functions to allow me to execute CRUD actions in SQLite easily, from my app.
The following smippet is pseudocode for the helper functions I envisage writing. I would be grateful for suggestions on how to "fill up" the stub functions. One thing that is particularly frustrating is that there is no clear mention in any of the docs, on the relationship between a query and the database on which the query is being run - thus suggesting some kind of default connection/table.
In my application, I need to be able to explicitly specify the database on which queries are run, so it would be useful if any answers spell out how to explicitly specify the database/table involved in a query (or other database action for that matter).
My pseudocode follows below:
#include <boost/shared_ptr.hh>
typedef boost::shared_ptr<QSqlDatabase> dbPtr;
dbPtr createConnection(const QString& conn_type = "QSQLITE", const QString& dbname = ":memory:")
{
dbPtr db (new QSQlDatabase::QSqlDatabase());
if (db.get())
{
db->addDatabase(conn_type);
db->setDatabaseName(dbname);
if (!db.get()->open)
db.reset();
}
return db;
}
bool runQuery(const Qstring& sql)
{
//How does SQLite know which database to run this SQL statement against ?
//How to iterate over the results of the run query?
}
bool runPreparedStmtQuery(const QString query_name, const QString& params)
{
//How does SQLite know which database to run this SQL statement against ?
//How do I pass parameters (say a comma delimited list to a prepared statement ?
//How to iterate over the results of the run query?
}
bool doBulkInsertWithTran(const Qstring& tablename, const MyDataRows& rows)
{
//How does SQLite know which database to run this SQL statement against ?
//How to start/commit|rollback
}
In case what I'm asking is not clear, I am asking what would be the correct wat to implement each of the above functions (possibly with the exception of the first - unless it can be bettered of course).
[Edit]
Clarified question by removing requirement to explicitly specify a table (this is already done in the SQL query - I forgot. Thanks for pointing that out Tom
By default, Qt uses the application's default database to run queries against. That is the database that was added using the default connection name. See the Qt documentation for more information. I am not sure what you mean by the default database table, since the table to operate on is normally specified in the query itself?
To answer your question, here is an implementation for one of your methods. Note that instead of returning a bool I would return a QSqlQuery instance instead to be able to iterate over the results of a query.
QSqlQuery runQuery(const Qstring& sql)
{
// Implicitly uses the database that was added using QSqlDatabase::addDatabase()
// using the default connection name.
QSqlQuery query(sql);
query.exec();
return query;
}
You would use this as follows:
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setHostName("localhost");
db.setDatabaseName("data.db");
if (!db.open())
{
raise ...
}
QSqlQuery query = runQuery("SELECT * FROM user;");
while (query.next())
{
...
}
Note that it is also possible to explicitly specify for which database a query should be run by explicitly specifying the relevant QSqlDatabase instance as the second parameter for the QSqlQuery constructor:
QSqlDatabase myDb;
...
QSqlQuery query = QSqlQuery("SELECT * FROM user;", myDb);
...