[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