Connecting to ACCDB using QT5 - c++

What I'm trying to do is find all .db (Paradox) files from a directory and save them to .mdb. The thing is, to try if this works properly I've tried first opening an ACCDB (.db and .mdb I'll be using are resources only available in my school's internal network).
I've already checked, and I've found the sql drivers in the Qt directory, I've also added QT +=sql in my pro file, I've installed the access database engine, VBA is also installed, but I can't manage to open the connection. I'm yet to try connecting to a SQLITE database to try if it works, but I'm guessing it will. Here is the code, triggered from a button:
db.addDatabase("QODBC");
explorador.setFileMode(QFileDialog::Directory);
ruta=explorador.getExistingDirectory(this,"Seleccionar directorio");
directorio.setPath(ruta);
subdir=directorio.entryList(QDir::AllDirs);
//La lista comienza en el 2ยบ elemento
for(int i=2;i<subdir.size();i++)
{
subruta=ruta+"/"+subdir.at(i);
directorio.setPath(subruta);
db.setDatabaseName("DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};DBQ="+subruta+"/Base de datos11.accdb");
bool check=db.open();
if(check)
{
dbg.setText("Prueba");
dbg.show();
}
else
{
dbg.setText("Pruebaaa");
dbg.show();
}
}
Have any ideas?? Thank you!

I eventually solved it kind of bypassing through access. If someone else is struggling with this you need:
-Paradox DB engine (Be sure the version you download matches your .db file)
-Jet engine 4.0 or later
-access 2007 (Following version have removed Paradox DB connection)
-Administrator privileges to access the database engine folders(both jet and paradox)
Simply open the database through a connection or database object. Sintax should be something like this (Via a VBA module in access):
database.open(path,*Dont rememer what goes in here,*here goes the read/write permits,"Paradox 5.x")
Path should be pointing to a folder containing one or more .db files, which will be opened as a a single database with the files being tables. It actually genereates a new database (Either .accdb or .mdb, depending how you save it)
It is not exactly like this, but I'm on my laptop. I'll edit the answer once I'm in front of my code
Sorry it is not a c++ answer, but from what I've found it is kind of a pain in the a** to work with paradox databases. Hope this helps others with the struggle.
Ricardo

Related

C++ Poco ODBC Transactions - AutoCommit mode

I am currently attempting to use transactions in my C++ app, but I have a problem with the ODBC's auto commit mode.
I am using the POCO libaries to create a connection to a PostgreSQL database on the same machine. Currently, I can send data to this database as single statements, but I cannot get my head around how to use Poco's transaction libraries to be able to send this data more quickly.
As I have several thousand records to insert, and so continuing to use single insert statements is extrememly slow and inpractical - So I am trying to use Poco's transaction to speed this up a bit (a fair bit).
The error I am encountering is a theoretically a simple one - Poco is throwing the following error:
'Invalid access: Session is in auto commit mode.'
I understand, as a result of this, I should somehow set "auto commit" to false - as it only allows me to commit data to the database line by line, rather than as a single transaction.
The problem is how I set this.
Currently, I have a session created from Session.h, that looks alot like this:
session = new Poco::Data::Session(
"ODBC",
connection_data.str()
);
Where connection data is a simple stringstream with the login information, password, database, server and "Driver={PostgreSQL ANSI};" to tell ODBC to utilize PostgreSQL's driver.
I have tried just setting a property "autocommit" to false through the session's setFeature or setProperty settings, this, of course, was to no avail. (it was more of a ditch attempt at this point).
session->setFeature("AUTOCOMMIT", false);
Looking around, I saw a possible alternative method by creating a ODBC sessionImpl directly from ODBC/session/SessionImpl.h instead of using this generic method above, and then creating a new session object from this.
The benefits of this are that ODBC's sessionImpl has references to autocommit mode in the header, which would suggest it would be able to handle this:
void autoCommit(const std::string&, bool val);
/// Sets autocommit property for the session.
However, having not used sessionImpl before, I cannot garuntee if this will work or if can can get this to work with the limited documentation available.
I am using C++ 03 (Not 11), with Visual Studio 2015
Poco 1.7.5
Boost (Where needed)
Would any one know the correct way of setting this feature (above) or a alternative method to achieving this?
edit: Looking at the source of poco, at:
https://github.com/pocoproject/poco/blob/develop/Data/ODBC/src/SessionImpl.cpp#L153
The property seems be named autoCommit, and looking at
https://github.com/pocoproject/poco/blob/develop/Data/include/Poco/Data/AbstractSessionImpl.h#L120
the case of the property names seem to matter. So, does it help if you use session->setFeature("autoCommit", false);?
Cant you just call session->begin(); and session->end(); on the corresponding Session object?
What is returned by session->canTransact()?
According to the doc begin() will start a new transaction, the doc does not mention any property that needs to be set before or after.
See: https://pocoproject.org/docs/Poco.Data.Session.html
Also faced a similar issue.
First of all before begin() need:
m_ses.setFeature("autoCommit", false);
m_ses.begin();
And the second issue is that this feature stays "autoCommit" in false for all other sessions. So don't forget for the next session call
session.setFeature("autoCommit", true);

QtSql connection

I am trying to create a connection to a database and insert/delete/make queries to the database. I know SQL relatively well but I cannot seem to wrap my head around it in Qt. I used to program in Delphi.
This is my code so far:
QSqlDatabase db;
db.addDatabase("QSQLITE");
db.setHostName( "localhost" ); //I don't know if i should include this the database is in the same directory as my program
db.setDatabaseName( "Xmato.odb" );
db.setUserName( "" ); //There is no username
db.setPassword( "" ); //There is no password
db.open();
db.prepare("SELECT * FROM Members");
db.exec();
I have added this to my .pro file:
QT += sql;
An included QtSql to my main file.
When I run this code I get the error:
QSqlQuery::prepare: database not open
Any ideas will me much appreciated.
P.S.: I use c++ on Linux Ubuntu 12.04 and used LibreOffice Base to create my database.
After a bit of google-ing - openoffice libre's internal database is using HSQLDB (natural choice for Java). Here's a small discussion about HSQLDB.
It appears that some versions of openlibre base is also able to connect to external databases. I would recommend setting up something that is more accessible to C++, specifically Qt.
Only a few drivers like ODBC & SQLite is included by default.
Which means that depending on the database being used, one may need to get additional source code (or packages) and compile a plugin/dll/so. The library is loaded dynamically (i.e. run-time) by the QtSql module. I've run into this for mysql drivers.
When you get all of that setup, your call to addDatabase should match the kind of database you're using.
QSqlDatabase::addDatabase( "QODBC" ); // For something like MSSQL
QSqlDatabase::addDatabase( "QSQLITE" ); // For SQLite
QSqlDatabase::addDatabase( "QMYSQL" ); // For MySQL
Personally, if you're just doing this for kicks, a quick and easy database is SQLITE. You can even download plugins/extensions for Mozilla Firefox that will offer you a GUI to the database.
Driver not loaded
you need the QSQLITE driver.
db.drivers() returns a list of all the available database drivers.
In Ubuntu 12.04 the driver for sqlite is in a package named libqt4-sql-sqlite.
But: is odb a sqlite database??
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName( "Xmato.odb" );
if (db.open())
{
QSqlQuery query(db); // if multiple connections used, without the `db` in constructor will cause the query to use the default database (first opened and available one)
query.exec("select * from members");
}
should do the same. username and password are not needed and since it is a file, you just have to use setDatabaseName to set what file you want to open.

Issue with CQN registration getting dropped implictly

Using custom C++ OCI wrappers, I can successful register a CQN C++ callback-based registration, but it appears that somehow the subscription is dropped right away, behind my back. I get no call back on simple DMLs. If I try to unregister that subscription, for which register() worked just fine, I get ORA-29970: Specified registration id does not exist.
I'm running this test on a Win7 (64-bit) box, running a local 11.2.0.1.0 Oracle Server, and I connect with a C++ client app built against instantclient-11.2.0.2.0 that runs on that same machine.
I tried setting OCI_ATTR_SUBSCR_TIMEOUT explicitly to 0, to no avail.
I checked the job_queue_processes instance param to make sure it's not 0 (it's 1000).
Of course, the user/schema I'm connecting with has been granted CHANGE NOTIFICATION
I'm running out of ideas on this issue, and I would appreciate some insights on what else I could try or check.
I'm starting to wonder if CQN needs to be activated somehow. My DBA skills are close to nonexistent, this is a stock install of 11gR1 on Windows using the installer, with no special configurations or customization done at all.
Thanks, --DD
Update #1
A colleague successfully ran that same test, and he ran it using the server-provided oci.dll. I tried that (I build using instantclient, but forced the PATH at runtime: Path=D:\oracle\product\11.2.0\dbhome_1\BIN;$(Path) in VS Property Page> Debugging> Environment), and indeed the CQN test works! We still haven't figured out whether the slight version difference between client and server, or using instantclient (the Light variant by the way) vs a full client vs a server install is the real culprit.
But it is bad news that a newer instantclient does not support CQN...
Update #2
I've tried all 6 combinations of instantclient Light (65 MB) or Normal (150 MB) in versions 12.2.0.(1|2|3).0 on Win64, and none of them worked. Haven't tested the Full Client yet, nor have we tested on Linux just yet.
Environment_var cqn_env = Environment::create(OCI_EVENTS + OCI_OBJECT);
Connection_var cqn_conn = Connection::logon2(...);
Subscription sub(cqn_conn, "cqn_test", OCI_SUBSCR_NAMESPACE_DBCHANGE);
sub.set<attr::SUBSCR_CALLBACK>( &cqn_callback_func );
sub.set<attr::SUBSCR_CQ_QOSFLAGS>( OCI_SUBSCR_CQ_QOS_QUERY );
try {
sub.register_self();
} catch (const OracleException& ex) {
BOOST_REQUIRE(ex.error_code && *ex.error_code == 29972);
cerr << "\nSKIPPED: test requires CHANGE NOTIFICATION privilege" << endl;
return;
}

How to integration test an object with database queries

How can i write unitintegration tests that talk to a database. e.g.:
public int GetAppLockCount(DbConnection connection)
{
string query :=
"SELECT"+CRLF+
" tl.resource_type AS ResourceType,"+CRLF+
" tl.resource_description AS ResourceName,"+CRLF+
" tl.request_session_id AS spid"+CRLF+
"FROM sys.dm_tran_locks tl"+CRLF+
"WHERE tl.resource_type = 'APPLICATION'"+CRLF+
"AND tl.resource_database_id = ("+CRLF+
" SELECT dbid"+CRLF+
" FROM master.dbo.sysprocesses"+CRLF+
" WHERE spid = ##spid)";
IRecordset rdr = Connection.Execute(query);
int nCount = 0;
while not rdr.EOF do
{
nCount := nCount+1;
rdr.Next;
}
return nCount;
}
In this case i am trying to exorcise this code of bugs (the IRecordset returns empty recordset).
[UnitTest]
void TestGetLockCountShouldAlwaysSucceed();
{
DbConnection conn = GetConnectionForUnit_IMean_IntegrationTest();
GetAppLockCount(conn);
CheckTrue(True, "We should reach here, whether there are app locks or not");
}
Now all i need is a way to connect to some database when running a unit integration testing.
Do people store connection strings somewhere for the test-runner to find? A .ini or .xml or .config file?
Note: Language/framework agnostic. The code intentionally contains elements from:
C#
Delphi
ADO.net
ADO
NUnit
DUnit
in order to drive that point home.
Now all i need is a way to connect to some database when running a unit integration testing.
Either use an existing database or an in-memory database. I've tried both an currently use an existing database that is splatted and rebuilt using Liquibase scripts in an ant file.
Advantages to in-memory - no dependencies on other applications.
Disadvantages - Not quite as real, can take time to start up.
Advantages to real database - Can be identical to the real world
Disadvantages - Requires access to a 3rd party machine. More work setting up a new user (i.e. create new database)
Do people store connection strings somewhere for the test-runner to find? A .ini or .xml or .config file?
Yeap. In C# I used a .config file, in java a .props file. With in-memory you can throw this into the version control as it will be the same for each person, with a real database running somewhere it will need to be different for each user.
You will also need to consider seed data. In Java I've used dbUnit in the past. Not the most readable, but works. Now I use a Ruby ActiveRecord task.
How do you start this? First can you rebuild your database? You need to be able to automate this before going to far down this road.
Next you should build up a blank local database for your tests. I go with one-per-developer, some other teams share but don't commit. In a .NET/MS SQL world I think in memory would be quite easy to do.

Upload file to SharePoint WSS 3.0 with WebRequest PUT

Hey, I've got this nice little piece of code, much like all the other versions of this method of upload using WSS WebServices. I've got one major problem though - once I have uploaded a file into my doc list, and updated the list item to write a comment/description, the file is stuck there. What I mean is that this method will not overwrite the file once I've uploaded it. Nobody else out there seems to have posted this issue yet, so .. anyone?
I have another version of the method which uses a byte[] instead of a Stream .. same issue though.
Note: I have switched off the 'require documents to be checked out before they can be edited' option for the library. No luck tho .. The doc library does have versioning turned on though, with a major version being created for each update.
private void UploadStream(string fullPath, Stream uploadStream)
{
WebRequest request = WebRequest.Create(fullPath);
request.Credentials = CredentialCache.DefaultCredentials; // User must have 'Contributor' access to the document library
request.Method = "PUT";
request.Headers.Add("Overwrite", "t");
byte[] buffer = new byte[4096];
using (Stream stream = request.GetRequestStream())
{
for (int i = uploadStream.Read(buffer, 0, buffer.Length); i > 0; i = uploadStream.Read(buffer, 0, buffer.Length))
{
stream.Write(buffer, 0, i);
}
}
WebResponse response = request.GetResponse(); // Upload the file
response.Close();
}
Original credits to: http://geek.hubkey.com/2007/10/upload-file-to-sharepoint-document.html
EDIT -- major finding .. when I call it from my nUnit test project it works fine. It seems it only fails when I call it from my WCF application (nUnit running under logged on user account, WCF app has app pool running under that same user -- my account, which also has valid permissions in SharePoint).
Nuts. "Now where to start?!", I muses to myself.
SOLVED -- I found a little bug - the file was being created in the right place, but the update path was wrong.. I ended up finding a folder full of files with many, many new versions.. doh!
Why not use the out-of-the-box SharePoint webservice, Lists.asmx? You'll find it in
http://SITEURL/___vti_bin/Lists.asmx
Edit, I checked out the link and it seems you are calling the out of the box web service. This has got be versioning related then. Can you check out the different versions that exist in the doc lib of the specific file? see if it perhaps gets added as a minor version through the service?
Have you tried using a capital T? SharePoint's webdav header processing is not very likely to be case-sensitive, but the protocol does specify a capital T. Oh, and what is the response? A 412 error code or something altogether different?