Get SQL Server default data path via ADO/C++? - c++

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

Related

Why is this SQL query not seem to be failing but actually failing?

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.

MySQL C++ Connector: How do I get the thread/connection Id?

I'm trying to find out how to obtain the MySQL Connection/thread id using Connector C++.
mysql_thread_id(MYSQL* ) seems to be available for just this, but I'm not sure how to get an instance of MYSQL from the Connector C++.
What I've tried:
int threadId = mysql_thread_id(NULL);
But this just returns zero.
Any ideas?
The function mysql_thread_id() expects a pointer to a connection object created by the native MySQL C API's mysql_connect(...) function. Connector/C++ has buried that object very deep (I looked). The alternative suggested by MySQL's documentation here is to execute query SELECT CONNECTION_ID() and the returned result will be the ID you're looking for.

How to check if file is appropriated with database driver in Qt

Assuming I want to open a connection to SQLite3 database in Qt. It will be connected to an existed database dbName.
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
Now I need to set db.setDatabaseName(dbName), where dbName is received through a QFileDialog.
However, as long as dbName is a valid file name, then db.open() is always true. Is there anyway to check if the file dbName is a SQLite3 database, but not of any other type? What I can do now is to execute a query and check for error like:
db.setDatabaseName(dbName);
if (db.open()) {
QSqlQuery qr(db);
if (!qr.exec(".database;")) {
qDebug() << qr.lastError().text();
return false;
}
}
but it won't work if the file is empty.
Qt always uses the SQLITE_OPEN_CREATE flag, so nonexistent or empty files are considered valid (for a new, empty database).
If you don't want to change Qt, or write your own database driver, the only alternative is to manually check for a valid database header in the file.
I had to face the same problem.
In fact, there is two issues :
1/ As CL said, Qt always uses the SQLITE_OPEN_CREATE flag, so if you try to open a database that point to a non-existent file, the database will be created and you get a success.
You can adress this issue by checking if the file exists before open (see QFile::Exists static method)
2/ SQLite use "lazy initialization", so until you make a request on the database, the file is not really opened.
You can adress this issue by executing a simple request right after the database open, and check the result.
If you don't know anything in advance about the database schema, you can try to read one of the "PRAGMA" values : http://www.sqlite.org/pragma.html#pragma_table_info

Addressing to temporary table created through CDatabase::ExecuteSQL

Consider following code and advise, why can I not address the temporary table created in the current session.
CDatabase cdb;
CString csConnectionString = "Dsn=prm2;Driver={INFORMIX 3.34 32 BIT};Host=10.XXX.XXX.XXX;Server=SRVNAME;Service=turbo;Protocol=olsoctcp;Database=DBNAME;Uid=user;Pwd=password";
cdb.OpenEx(csConnectionString, CDatabase::noOdbcDialog);
cdb.ExecuteSQL(CString("Set Isolation to Dirty Read"));
...
CString csStatement1 = "SELECT serno FROM TABLE1 into temp ttt_1;"
CString csStatement2 = "DROP TABLE ttt_1";
cdb.ExecuteSQL(csStatement1); // point1
cdb.ExecuteSQL(csStatement2); // point2
...
cdb.Close();
At point1 everything is fine. At point2 I have:
The specified table (ttt_1) is not in the database. State:S0002,Native:-206,Origin:[Informix][Informix ODBC Driver][Informix]
I tried to specify username as prefix (like user.ttt_1 or "user".ttt_1); I tried to create permanent table within respective statement in csStatement1 and every time it failed at point2. But when I tried to create same temporary table twice within csStatement1 I got the message that the temporary table already exists in session.
Please advise: what is wrong and how can I address created temporary tables.
it is all to do with ODBC autocommit mode. By default ODBC uses the option what is defined during the connection, and according to connectionstrings.com the default settings for Informix is commitretain=false.
You have two options: either set it via the connection string (commitretain=true) or (better option) via the ODBC. For a set of statements where you'd like to retain the temp table activate the manual commit mode via SqlSetConnectAttr, then execute a few statements and then call SqlEndTran. Please note, that in manual mode you do not need to call BEGIN TRANSACTION, as it will start automatically (behaviour similar to Oracle)
Please note that ODBC applications should not use Transact-SQL transaction statements such as BEGIN TRANSACTION, COMMIT TRANSACTION, or ROLLBACK TRANSACTION, but use the ODBC commands.

SQLite database update in C++

I have an application where I show data from a database. In fact we can say it's a database editor.
Now I want to perform update/delete command on this opened database. Using the following commands, the database opens successfully.
int nRet = sqlite3_open(szFile, &mpDB);
From C# (.net api) I am able to update data from database
dbCmd5 = New SQLiteCommand(
"update Tbl_Tmp_Cal_Res Load_Time=5 WHERE Part_Index= 5", g_dbFlow);
dbCmd5.ExecuteNonQuery()
But from C++ I am getting error 5 (database is locked)
C++ code
int nRet = sqlite3_open(szFile, &mpDB);//database opened successfully.
sqlite3_exec(mpDB, "UPDATE query", 0, 0, &szError);//Error for this statement
Multithreading is not used in application.
Is the database used from another location in the code? Since something else clearly seems to have the database locked, I would guess that you're using the database from another location in the code and have forgotten to call sqlite3_finalize on a select statement or something similar.
maybe you have forgotten authentication step (username/password & etc)