[Qt-interest] Custom SQLite Driver
Bill King
bill.king at nokia.com
Tue Jan 5 01:02:52 CET 2010
The way we handle passing new information down to the internal results
is via the virtual virtual_hook function.
This allows us to retain binary compatibility, when needing to add a new
communication channel between the top and bottom levels. The code is the
documentation sadly, as it's mostly been an internal trick until now.
On 01/02/2010 06:22 AM, ext Neville Dastur wrote:
> Thanks for the suggestions. The invoke method thing works for the
> driver, but I also then needed to modify the QSQLiteResult class which
> is not a Q_OBJECT and so neither method works.
>
> So the solution that seems to work so far is to set a flag using
> Q_PROPERTY in the driver, then in QSQLiteResult test for the flag and
> act accordingly.
>
> class Q_EXPORT_SQLDRIVER_SQLITE QSQLiteDriver : public QSqlDriver
> {
> Q_OBJECT
> Q_PROPERTY(bool ExecNoReturn READ getExecNoReturn WRITE setExecNoReturn)
> ....
> private:
> // Property Functions
> bool ExecNoReturn;
> bool getExecNoReturn() { return ExecNoReturn; };
> void setExecNoReturn(bool flag) {ExecNoReturn=flag;};
> private:
> QSQLiteDriverPrivate* d;
> };
> bool QSQLiteResult::reset(const QString &query)
> {
> // Perform as a sqlite3_exec() instead if property flag set, but reset on each use
> QVariant ret = this->driver()->property("ExecNoReturn");
> if (ret.isValid() & ret.toBool()) {
> QSqlDriver *d = const_cast<QSqlDriver *>(driver());
> d->setProperty("ExecNoReturn", QVariant::fromValue(false));
> return this->_execNoReturnSet(query);
> }
> else {
> if (!prepare(query))
> return false;
> return exec();
> }
> }
> then in the QSQLiteResult class we have:
> bool QSQLiteResult::_execNoReturnSet(const QString &query) {
> if (!driver() || !driver()->isOpen() || driver()->isOpenError())
> return false;
> char* localError=0;
> int res = sqlite3_exec((sqlite3*) d->access, query.toLocal8Bit().constData(), 0, 0, &localError);
> if (res != SQLITE_OK) {
> setLastError(qMakeError(d->access, QCoreApplication::translate("QSQLiteResult",
> "Unable to execute statement using sqlite3_exec"), QSqlError::StatementError, res));
> return false;
> }
> return true;
> }
>
> In the calling source we do:
> QSqlQuery q;
> QSqlDriver *d = const_cast<QSqlDriver *>(q.driver());
> d->setProperty("ExecNoReturn", QVariant::fromValue(true));
> q.exec(SQL_CREATE_DB);
>
>
> Again, just posting this to find out if there is a better solution.
> Also might help someone else.
>
> The underlying problem here is that the current SQLite driver won't
> handle SQL with multiple statements i.e. separated by ; so wanted a
> way to use the sqlite3_exec function.
>
>
>
> André Somers wrote:
>> Would it be sensible to express the key as a property? In that case, you
>> could use setProperty("key") on your driver, and loose the conversion. Check
>> out Q_PROPERTY to see how. Perhaps slightly less hackish than using
>> invokeMethod(), though I use that approach myself quite frequently.
>>
>> André
>>
>>
>> -----Oorspronkelijk bericht-----
>> Van: qt-interest-bounces at trolltech.com
>> [mailto:qt-interest-bounces at trolltech.com] Namens Mohammed Sameer
>> Verzonden: zondag 29 november 2009 14:25
>> Aan: qt-interest at trolltech.com
>> Onderwerp: Re: [Qt-interest] Custom SQLite Driver
>>
>> I'm not an expert here but...
>>
>> On Sun, Nov 29, 2009 at 12:03:16PM +0000, Neville Dastur wrote:
>>
>>> I am writing a custom SQLite driver to use the encryption routines from
>>> wxSqlite. I have got the whole thing compiling and working by following
>>> the docs on writing your own driver
>>> (http://qt.nokia.com/doc/4.5/qsqldatabase.html#addDatabase-2) , but I am
>>> having a problem including a new method.
>>>
>>> To set a password on the database the ReKey function needs to be called.
>>> I created a public method:
>>> void QSQLiteDriver::ReKey(const QString & key)
>>>
>>> When calling QSQLDatabase m_db->driver()->ReKey("test"); the function
>>> ReKey can't be found.
>>> and
>>>
>>> QSQLiteDriver *driver = m_db->driver();
>>> driver->ReKey("test");
>>>
>>
>> QSQLiteDriver *driver = dynamic_cast<QSQLiteDriver *>(m_db->driver()); //
>> Some might prefer qobject_cast
>>
>>
>>> What is this the best way of adding new functionality to a QSQLDriver.
>>>
>>
>> Maybe a public slot and then use QMetaObject::invokeMethod() ?
>>
>> Sounds ugly but I can't find something else ;-)
>>
>> Cheers,
>>
>>
--
Bill King, Software Engineer
Qt Development Frameworks, Nokia Pty Ltd
Brisbane Office
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.qt-project.org/pipermail/qt-interest-old/attachments/20100105/b5b23f24/attachment.html
More information about the Qt-interest-old
mailing list