aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules/objects/KvsObject_sql.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/objects/KvsObject_sql.cpp')
-rw-r--r--src/modules/objects/KvsObject_sql.cpp603
1 files changed, 603 insertions, 0 deletions
diff --git a/src/modules/objects/KvsObject_sql.cpp b/src/modules/objects/KvsObject_sql.cpp
new file mode 100644
index 000000000..2c7b32438
--- /dev/null
+++ b/src/modules/objects/KvsObject_sql.cpp
@@ -0,0 +1,603 @@
+//=============================================================================
+//
+// File : KvsObject_sql.cpp
+// Creation date : Wed Gen 28 2009 21:07:55 by Alessandro Carbone
+//
+// This file is part of the KVIrc irc client distribution
+// Copyright (C) 2000-2010 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//============================================================================
+
+#include "kvi_debug.h"
+#include "KviMemory.h"
+#include "KviLocale.h"
+#include "KvsObject_sql.h"
+#include <QtSql>
+#include "KvsObject_memoryBuffer.h"
+#include <stdlib.h>
+#include <QHash>
+
+static KviPointerList <KvsObject_sql> sql_instances;
+
+static bool checkDuplicatedConnection(QString &szConnectionName)
+{
+ if(!sql_instances.count()) return false;
+ bool bFound=false;
+ for(KvsObject_sql *i = sql_instances.first(); i; i = sql_instances.next())
+ {
+ QSqlQuery *q=i->getQueryConnectionsDict().value(szConnectionName);
+ if (q)
+ {
+ i->closeQueryConnection(q);
+ bFound=true;
+ break;
+ }
+ }
+ return bFound;
+}
+static void KviKvsSqlInstanceRegister(KvsObject_sql *instance)
+{
+ sql_instances.setAutoDelete(false);
+ sql_instances.append(instance);
+}
+static void KviKvsSqlInstanceUnregister(KvsObject_sql *instance)
+{
+ int idx=sql_instances.findRef(instance);
+ sql_instances.remove(idx);
+}
+
+#define CHECK_QUERY_IS_INIT if (!m_pCurrentSQlQuery)\
+ {\
+ c->error("No query has been initialized!");\
+ return false;}
+
+
+/*
+ @doc: sql
+ @keyterms:
+ Sql database.
+ @title:
+ sql class
+ @type:
+ class
+ @short:
+ A sql database interface.
+ @inherits:
+ [class]object[/class]
+ @description:
+ This class permits KVIrc to have an interface with a SQL database supported by Qt library drivers.
+ @functions:
+ !fn: <boolean> $setConnection(<connection_name:string>,<database_name:string>,[<user:string>,<host_name_string>,<password:string>,<database_driver:string>])
+ Connects to the DBMS using the connection <connection_name> and selecting the database <database_name>.[br]
+ If the optional parameter <database_driver> is passed, it will be used the corresponding driver (if present), otherwise Sqlite will be used.
+ Returns true if the operation is successful, false otherwise.
+ !fn:: <array or string> $connectionNames([<stringreturnflag>:'s'])
+ Returns as array or, if the flag 's' is passed, as a comma separate string all the database active connection's names.
+ !fn: <array> $tablesList(<connection_name:string>)
+ Returns as array the database tables list.
+ !fn: $queryInit(<connection_name:string>)
+ Initialize the query for the database <connection_name> which has to be already connected.
+ !fn: $transaction()
+ Begin a transaction.
+ !fn: $commit()
+ Commit the transaction.
+ !fn: $setCurrentQuery(<connection_name:string>)
+ Sets the query for the database connection <connection_name>, which has to be already connected, as current query.
+ !fn: <connection_name:string> $currentQuery()
+ Returns the name of the database connection for the current query, or an empty string if there aren't any initialized queries.
+ !fn: $closeConnection(<connection_name:string>)
+ Closes the connection <connection_name>.
+ !fn: <size:integer> $queryResultsSize()
+ Returns the query size in rows or -1 if the query is empty or the database driver doesn' support the function.
+ !fn: <error:string> $lastError(<more_details:boolean>)
+ Returns last error occurred. Use the more_details flag for more info about the error.
+ !fn: <ok:boolean> $queryExec([<query:string>])
+ Execs the current query <query>. The string must follow the right syntax against the database in use.
+ If there are no parameters, it will exec the query previously done.
+ After the execution, the query will positioned on the first resulting record.
+ Returns true if the operation is successful, false otherwise.
+ See also [classfnc]$queryPrepare[/classfnc]()
+ !fn: <ok:boolean> $queryPrepare(<query_string>)
+ Prepare the query <query> to execute. The string must follow the right syntax against the database in use.
+ It's possible to use the placeholders. It's supported either the identifier ':' and '?' but it's not possible to use them together.
+ Returns true if the operation is successful, false otherwise.
+ See also [classfnc]$queryExec[/classfnc]and[classfnc]$queryBindValue[/classfnc.
+ !fn: $queryBindValue()
+ Sets the placeholder <placeholder> to be bound to the value <val> in the prepared statement.
+ Note that the placeholder mark (e.g :) must be included when specifing the placeholder name.
+ !fn: <boolean> $queryPrevious()
+ Sets the current query position to the previous resulting record.
+ Returns true if the operation is successful, false otherwise.
+ !fn: <boolean> $queryNext()
+ Sets the current query position to the next resulting record.
+ Returns true if the operation is successful, false otherwise.
+ !fn: <boolean> $queryLast()
+ Sets the current query position to the last resulting record.
+ Returns true if the operation is successful, false otherwise.
+ !fn: <boolean> $queryFirst()
+ Sets the current query position to the first resulting record.
+ Returns true if the operation is successful, false otherwise.
+ !fn: <record:hash> $queryRecord()
+ Returns a hash containing the current query's record fields.
+ !fn: $queryFinish()
+ Sets the current query to inactive.
+*/
+
+
+
+KVSO_BEGIN_REGISTERCLASS(KvsObject_sql,"sql","object")
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,queryLastInsertId)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,commit)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,beginTransaction)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,setConnection)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,connectionNames)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,setCurrentQuery)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,tablesList)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,currentQuery)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,closeConnection)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,queryInit)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,queryFinish)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,queryResultsSize)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,queryExec)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,queryPrepare)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,queryBindValue)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,queryPrevious)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,queryNext)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,queryLast)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,queryFirst)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,queryRecord)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,lastError)
+ KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_sql,features)
+KVSO_END_REGISTERCLASS(KvsObject_sql)
+
+
+KVSO_BEGIN_CONSTRUCTOR(KvsObject_sql,KviKvsObject)
+m_pCurrentSQlQuery=0;
+KviKvsSqlInstanceRegister(this);
+KVSO_END_CONSTRUCTOR(KvsObject_sql)
+
+
+KVSO_BEGIN_DESTRUCTOR(KvsObject_sql)
+QHashIterator<QString,QSqlQuery *> t(queryConnectionsDict);
+while (t.hasNext())
+{
+ t.next();
+ QString szConnectionName=t.key();
+ queryConnectionsDict.value(szConnectionName)->finish();
+ delete queryConnectionsDict.value(szConnectionName);
+ QSqlDatabase::removeDatabase(szConnectionName);
+}
+KviKvsSqlInstanceUnregister(this);
+queryConnectionsDict.clear();
+
+KVSO_END_DESTRUCTOR(KvsObject_sql)
+
+KVSO_CLASS_FUNCTION(sql,setConnection)
+{
+ QString szConnectionName,szDbName,szDbDriver,szUserName,szHostName,szPassword;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("connection_name",KVS_PT_STRING,0,szConnectionName)
+ KVSO_PARAMETER("database_name",KVS_PT_STRING,0,szDbName)
+ KVSO_PARAMETER("user_name",KVS_PT_STRING,KVS_PF_OPTIONAL,szUserName)
+ KVSO_PARAMETER("host_name",KVS_PT_STRING,KVS_PF_OPTIONAL,szHostName)
+ KVSO_PARAMETER("password",KVS_PT_STRING,KVS_PF_OPTIONAL,szPassword)
+ KVSO_PARAMETER("database_type",KVS_PT_STRING,KVS_PF_OPTIONAL,szDbDriver)
+ KVSO_PARAMETERS_END(c)
+ if(!szDbDriver.isEmpty())
+ {
+ QStringList drivers = QSqlDatabase::drivers();
+ if (!drivers.contains(szDbDriver))
+ {
+ c->error(__tr2qs_ctx("Missing Qt plugin for database %Q","objects"),&szDbDriver);
+ return false;
+ }
+ }
+ else szDbDriver="QSQLITE";
+ if (checkDuplicatedConnection(szConnectionName))
+ {
+ c->warning(__tr2qs_ctx("Duplicate connection name '%Q', old query connection removed","objects"),&szConnectionName);
+ }
+ QSqlDatabase db=QSqlDatabase::addDatabase(szDbDriver,szConnectionName);
+ db.setDatabaseName(szDbName);
+ db.setHostName(szHostName);
+ db.setUserName(szUserName);
+ db.setPassword(szPassword);
+
+ c->returnValue()->setBoolean(db.open());
+ return true;
+}
+
+KVSO_CLASS_FUNCTION(sql,connectionNames)
+{
+
+ QString szFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("stringreturnflag",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlag)
+ KVSO_PARAMETERS_END(c)
+ QStringList szConnectionsList=QSqlDatabase::connectionNames();
+ if(szFlag.indexOf('s',0,Qt::CaseInsensitive) != -1)
+ {
+ QString szConnections=szConnectionsList.join(",");
+ c->returnValue()->setString(szConnections);
+ }
+ else
+ {
+ KviKvsArray *pArray=new KviKvsArray();
+ for(int i=0;i<szConnectionsList.count();i++)
+ {
+ pArray->set(i,new KviKvsVariant(szConnectionsList.at(i)));
+ }
+ c->returnValue()->setArray(pArray);
+ }
+ return true;
+}
+
+KVSO_CLASS_FUNCTION(sql,queryLastInsertId)
+{
+ CHECK_QUERY_IS_INIT
+ QVariant value=m_pCurrentSQlQuery->lastInsertId();
+ if (value.type()==QVariant::LongLong){
+ c->returnValue()->setInteger((kvs_int_t) value.toLongLong());
+ }
+ return true;
+ }
+KVSO_CLASS_FUNCTION(sql,features)
+{
+ QString szConnectionName;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("connectionName",KVS_PT_STRING,0,szConnectionName)
+ KVSO_PARAMETERS_END(c)
+
+ QStringList connections = QSqlDatabase::connectionNames();
+ if (!connections.contains(szConnectionName))
+ {
+ c->warning(__tr2qs_ctx("Connection %Q does not exists","objects"),&szConnectionName);
+ return true;
+ }
+ QSqlDatabase db=QSqlDatabase::database(szConnectionName);
+ QSqlDriver *sqlDriver=db.driver();
+ QStringList features;
+ if (sqlDriver->hasFeature(QSqlDriver::Transactions)) features.append("transactions");
+ if (sqlDriver->hasFeature(QSqlDriver::QuerySize)) features.append("querysize");
+ if (sqlDriver->hasFeature(QSqlDriver::BLOB)) features.append("blob");
+ if (sqlDriver->hasFeature(QSqlDriver::PreparedQueries)) features.append("preparedqueries");
+ if (sqlDriver->hasFeature(QSqlDriver::NamedPlaceholders)) features.append("namedplaceholders");
+ if (sqlDriver->hasFeature(QSqlDriver::PositionalPlaceholders)) features.append("positionaplaceholders");
+ if (sqlDriver->hasFeature(QSqlDriver::LastInsertId)) features.append("lastinsertid");
+ if (sqlDriver->hasFeature(QSqlDriver::BatchOperations)) features.append("batchoperations");
+ if (sqlDriver->hasFeature(QSqlDriver::SimpleLocking)) features.append("simplelocking");
+ if (sqlDriver->hasFeature(QSqlDriver::LowPrecisionNumbers)) features.append("lowprecisionnumbers");
+ if (sqlDriver->hasFeature(QSqlDriver::EventNotifications)) features.append("eventnotifications");
+ if (sqlDriver->hasFeature(QSqlDriver::FinishQuery)) features.append("finishquery");
+ if (sqlDriver->hasFeature(QSqlDriver::MultipleResultSets)) features.append("multipleresults");
+ c->returnValue()->setString(features.join(","));
+ return true;
+}
+
+KVSO_CLASS_FUNCTION(sql,beginTransaction)
+{
+ QString szConnectionName;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("connectionName",KVS_PT_STRING,0,szConnectionName)
+ KVSO_PARAMETERS_END(c)
+
+ QStringList connections = QSqlDatabase::connectionNames();
+ if (!connections.contains(szConnectionName))
+ {
+ c->warning(__tr2qs_ctx("Connection %Q does not exists","objects"),&szConnectionName);
+ return true;
+ }
+ QSqlDatabase db=QSqlDatabase::database(szConnectionName);
+ db.transaction();
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,commit)
+{
+ QString szConnectionName;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("connectionName",KVS_PT_STRING,0,szConnectionName)
+ KVSO_PARAMETERS_END(c)
+
+ QStringList connections = QSqlDatabase::connectionNames();
+ if (!connections.contains(szConnectionName))
+ {
+ c->warning(__tr2qs_ctx("Connection %Q does not exists","objects"),&szConnectionName);
+ return true;
+ }
+ QSqlDatabase db=QSqlDatabase::database(szConnectionName);
+ db.commit();
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,closeConnection)
+{
+ QString szConnectionName;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("connectionName",KVS_PT_STRING,0,szConnectionName)
+ KVSO_PARAMETERS_END(c)
+
+ QStringList connections = QSqlDatabase::connectionNames();
+ if (!connections.contains(szConnectionName))
+ {
+ c->warning(__tr2qs_ctx("Connection %Q does not exists","objects"),&szConnectionName);
+ return true;
+ }
+ QSqlQuery *q=queryConnectionsDict.value(szConnectionName);
+ if (q) closeQueryConnection(q);
+ QSqlDatabase::removeDatabase(szConnectionName);
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,tablesList)
+{
+ QString szConnectionName;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("connectionName",KVS_PT_STRING,0,szConnectionName)
+ KVSO_PARAMETERS_END(c)
+ QStringList connections = QSqlDatabase::connectionNames();
+ if (!connections.contains(szConnectionName))
+ {
+ c->warning(__tr2qs_ctx("Connection %Q does not exists","objects"),&szConnectionName);
+ return true;
+ }
+ QSqlDatabase db=QSqlDatabase::database(szConnectionName);
+ QStringList tables=db.tables();
+ KviKvsArray *pArray=new KviKvsArray();
+ for(int i=0;i<tables.count();i++)
+ {
+ pArray->set(i,new KviKvsVariant(tables.at(i)));
+ }
+ c->returnValue()->setArray(pArray);
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,setCurrentQuery)
+{
+ QString szConnectionName;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("connection_name",KVS_PT_STRING,0,szConnectionName)
+ KVSO_PARAMETERS_END(c)
+ QSqlQuery *q=queryConnectionsDict.value(szConnectionName);
+ if(!q)
+ {
+ c->warning(__tr2qs_ctx("Connection query %Q does not exists","objects"),&szConnectionName);
+ return true;
+ }
+ m_pCurrentSQlQuery=q;
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,queryFinish)
+{
+ QString szConnectionName;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("connection_name",KVS_PT_STRING,KVS_PF_OPTIONAL,szConnectionName)
+ KVSO_PARAMETERS_END(c)
+ QSqlQuery *q;
+ if(szConnectionName.isEmpty())
+ {
+ q=m_pCurrentSQlQuery;
+ if (!q)
+ {
+ c->warning(__tr2qs_ctx("No query connection is open","objects"));
+ return true;
+ }
+ }
+ else
+ {
+ q=queryConnectionsDict.value(szConnectionName);
+ if(!q)
+ {
+ c->warning(__tr2qs_ctx("Query for connection %Q does not exists","objects"),&szConnectionName);
+ return true;
+ }
+ }
+ q->finish();
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,currentQuery)
+{
+ if (!m_pCurrentSQlQuery) c->returnValue()->setString(QString());
+ else
+ {
+ QString szKey=queryConnectionsDict.key(m_pCurrentSQlQuery);
+ c->returnValue()->setString(szKey);
+ }
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,queryInit)
+{
+ QString szConnectionName;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("connection_name",KVS_PT_STRING,0,szConnectionName)
+ KVSO_PARAMETERS_END(c)
+ if (queryConnectionsDict.value(szConnectionName))
+ {
+ c->warning(__tr2qs_ctx("Query %Q already initialized","objects"),&szConnectionName);
+ return true;
+ }
+ if(!QSqlDatabase::connectionNames().contains(szConnectionName))
+ {
+ c->error(__tr2qs_ctx("Connection %Q is not open!","objects"),&szConnectionName);
+ return false;
+ }
+ m_pCurrentSQlQuery=new QSqlQuery(QSqlDatabase::database(szConnectionName));
+ queryConnectionsDict[szConnectionName]=m_pCurrentSQlQuery;
+ return true;
+}
+
+
+KVSO_CLASS_FUNCTION(sql,queryPrepare)
+{
+ CHECK_QUERY_IS_INIT
+ QString szQuery;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("query",KVS_PT_STRING,0,szQuery)
+ KVSO_PARAMETERS_END(c)
+ c->returnValue()->setBoolean(m_pCurrentSQlQuery->prepare(szQuery));
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,queryBindValue)
+{
+ CHECK_QUERY_IS_INIT
+ QString szFieldName;
+ KviKvsVariant *v;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bindName",KVS_PT_STRING,0,szFieldName)
+ KVSO_PARAMETER("value",KVS_PT_VARIANT,0,v)
+ KVSO_PARAMETERS_END(c)
+ QString szType;
+ v->getTypeName(szType);
+ if (v->isString()|| v->isNothing())
+ {
+ QString szText;
+ v->asString(szText);
+ m_pCurrentSQlQuery->bindValue(szFieldName,QVariant(szText));
+ }
+ else if (v->isReal())
+ {
+ kvs_real_t i;
+ v->asReal(i);
+ m_pCurrentSQlQuery->bindValue(szFieldName,QVariant((double)i));
+ }
+ else if (v->isInteger())
+ {
+ kvs_int_t i;
+ v->asInteger(i);
+ m_pCurrentSQlQuery->bindValue(szFieldName,QVariant((int)i));
+ }
+ else if (v->isBoolean())
+ {
+ bool b=v->asBoolean();
+ m_pCurrentSQlQuery->bindValue(szFieldName,QVariant(b));
+ }
+ else if (v->isHObject())
+ {
+ kvs_hobject_t hOb;
+ v->asHObject(hOb);
+ KviKvsObject *pObject;
+ pObject=KviKvsKernel::instance()->objectController()->lookupObject(hOb);
+ if (pObject->inheritsClass("memorybuffer"))
+ m_pCurrentSQlQuery->bindValue(szFieldName,QVariant(*((KvsObject_memoryBuffer *)pObject)->pBuffer()));
+ else c->warning(__tr2qs_ctx("Only memorybuffer class object is supported","objects"));
+ }
+ else
+ {
+ QString szTypeName;
+ v->getTypeName(szTypeName);
+ c->warning(__tr2qs_ctx("Type value %Q not supported","objects"),&szTypeName);
+ }
+ return true;
+}
+
+KVSO_CLASS_FUNCTION(sql,queryExec)
+{
+ CHECK_QUERY_IS_INIT
+ QString szQuery;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("query",KVS_PT_STRING,KVS_PF_OPTIONAL,szQuery)
+ KVSO_PARAMETERS_END(c)
+ bool bOk;
+ if (szQuery.isEmpty()) bOk=m_pCurrentSQlQuery->exec();
+ else bOk=m_pCurrentSQlQuery->exec(szQuery.toLatin1());
+ c->returnValue()->setBoolean(bOk);
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,queryNext)
+{
+ CHECK_QUERY_IS_INIT
+ if (m_pCurrentSQlQuery->isActive() && m_pCurrentSQlQuery->isSelect()) c->returnValue()->setBoolean(m_pCurrentSQlQuery->next());
+ else c->returnValue()->setNothing();
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,queryPrevious)
+{
+ CHECK_QUERY_IS_INIT
+ if (m_pCurrentSQlQuery->isActive() && m_pCurrentSQlQuery->isSelect()) c->returnValue()->setBoolean(m_pCurrentSQlQuery->previous());
+ else c->returnValue()->setNothing();
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,queryResultsSize)
+{
+ CHECK_QUERY_IS_INIT
+ c->returnValue()->setInteger(m_pCurrentSQlQuery->size());
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,queryFirst)
+{
+ CHECK_QUERY_IS_INIT
+ if (m_pCurrentSQlQuery->isActive() && m_pCurrentSQlQuery->isSelect()) c->returnValue()->setBoolean(m_pCurrentSQlQuery->first());
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,queryLast)
+{
+ CHECK_QUERY_IS_INIT
+ if (m_pCurrentSQlQuery->isActive() && m_pCurrentSQlQuery->isSelect()) c->returnValue()->setBoolean(m_pCurrentSQlQuery->last());
+ return true;
+}
+KVSO_CLASS_FUNCTION(sql,queryRecord)
+{
+ CHECK_QUERY_IS_INIT
+ KviKvsHash *pHash=new KviKvsHash();
+ QSqlRecord record=m_pCurrentSQlQuery->record();
+ for(int i=0;i<record.count();i++)
+ {
+ KviKvsVariant *pValue=0;
+ QVariant value=record.value(i);
+ if (value.type()==QVariant::LongLong) pValue=new KviKvsVariant((kvs_int_t) value.toLongLong());
+ else if (value.type()==QVariant::String) pValue=new KviKvsVariant(value.toString());
+ else if (value.type()==QVariant::ByteArray)
+ {
+ KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass("memoryBuffer");
+ KviKvsVariantList params(new KviKvsVariant(QString()));
+ KviKvsObject * pObject = pClass->allocateInstance(0,"",c->context(),&params);
+ *((KvsObject_memoryBuffer *)pObject)->pBuffer()=value.toByteArray();
+ pValue=new KviKvsVariant(pObject->handle());
+ }
+ else pValue=new KviKvsVariant(QString());
+ pHash->set(record.fieldName(i),pValue);
+ KviKvsVariant *value2=pHash->get(record.fieldName(i));
+ value2->type();
+ }
+ c->returnValue()->setHash(pHash);
+ return true;
+}
+
+KVSO_CLASS_FUNCTION(sql,lastError)
+{
+ CHECK_QUERY_IS_INIT
+ bool bMoreErrorDetails;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("more",KVS_PT_BOOLEAN,KVS_PF_OPTIONAL,bMoreErrorDetails)
+ KVSO_PARAMETERS_END(c)
+ QString szError;
+ QSqlError error=m_pCurrentSQlQuery->lastError();
+ if (bMoreErrorDetails) szError=error.text();
+ else
+ {
+ if (error.type()==QSqlError::StatementError) szError="SyntaxError";
+ else if (error.type()==QSqlError::ConnectionError) szError="ConnectionError";
+ else if (error.type()==QSqlError::TransactionError) szError="TransactionError";
+ else szError="UnkonwnError";
+ }
+ c->returnValue()->setString(szError);
+ return true;
+}
+void KvsObject_sql::closeQueryConnection(QSqlQuery * query)
+{
+ if (query==m_pCurrentSQlQuery) m_pCurrentSQlQuery=0;
+ query->finish();
+ queryConnectionsDict.remove(queryConnectionsDict.key(query));
+ delete query;
+ }
+