WARNING: USE THIS SOFTWARE AT YOUR OWN RISK! THIS IS EXPERIMENTAL SOFTWARE NOT INTENDED FOR PRODUCTION USE! Zuble is currently an early stage prototype. As such Zuble is minimally tested and inherently unstable. It is provided for experimental, development, and demonstration purposes only. Zuble QML Types   |  Zuble C++ Classes   |  Zuble Overview
Zuble  0.1
Zuble Framework C++/QML extension API
ZsqlQuery.cpp
Go to the documentation of this file.
1 /*
2  * Zuble - A run-time system for QML/Javascript applications
3  * Copyright (C) 2013, 2014 Bob Dinitto
4  *
5  * ZsqlQuery.cpp
6  *
7  * Created on: 06-Aug, 2014
8  * Author: Bob Dinitto bob@ninzo.com
9  *
10  * Zuble is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  *
24  */
25 
26 #include "ZsqlQuery.h"
27 #include "ZsqlDatabase.h"
28 #include "ZsqlError.h"
29 #include "ZsqlRecord.h"
30 #include "ZTableModel.h"
31 #include "zglobal.h"
32 #include <QList>
33 
34 
35 namespace Zbl
36 {
37 
38 QVariant ZsqlQuery::m_tags;
39 
41  QSqlQuery* query,
42  QObject *parent)
43 : QObject(parent),m_q(query)
44 {
45  createTags();
46 }
47 
49 {
50  release();
51 }
52 
53 
55 {
56  if(!m_tags.isNull())
57  return;
58 
59  QVariantMap map;
60 
61  map.insert("paramtypeIn", In);
62  map.insert("paramtypeOut", Out);
63  map.insert("paramtypeInOut", InOut);
64  map.insert("paramtypeBinary", Binary);
65 
66  map.insert("batchexemodeValuesAsRows", ValuesAsRows);
67  map.insert("batchexemodeValuesAsColumns", ValuesAsColumns);
68 
69  m_tags = QVariant::fromValue(map);
70 }
71 
72 void ZsqlQuery::ensureParamType(int paramType)
73 {
74  if(paramType != QSql::In
75  && paramType != QSql::Out
76  && paramType != QSql::InOut
77  && paramType != QSql::Binary
78  )
79  {
80  throw ZblException(QString(
81  "ERROR: paramType is an invalid QSql::ParamType value: %1")
82  .arg(paramType));
83  }
84 }
85 
87 {
88  validateQuery();
89 
90  if(!m_q->isActive())
91  throw ZblException("ZsqlQuery::validateGetTableModel - ERROR: inactive query");
92 
93  if(!m_q->isSelect())
94  throw ZblException("ZsqlQuery::validateGetTableModel - ERROR: non-SELECT query");
95 
96  if(!m_q->first())
97  throw ZblException("ZsqlQuery::validateGetTableModel - ERROR: no data in query");
98 }
99 
101 {
102  if(!model)
103  throw ZblException("ZsqlQuery::tableModel - Error: null model object");
104 
106 
108 
109  model->setColumnCount(1);
110 
111  const int colCount = metaRow.count();
112 
113  //QHash<int, QByteArray> roleNames;
114 
115  for(int i=0; i<colCount; i++)
116  {
117  model->addRole(i, metaRow.at(i));
118  //roleNames.insert(i, metaRow.at(i).toUtf8());
119  }
120 
121  //model->setRoleNames(roleNames);
122 
123  ZRoleRowList rowList;
124 
125  do
126  {
127  ZRoleRow row;
128 
129  for(int col=0; col < colCount; col++)
130  {
131  QList<QVariant> rowData;
132 
133  rowData.append(m_q->value(col));
134 
135  row.insert(col, rowData);
136  }
137 
138  rowList.push_back(row);
139 
140  } while(m_q->next());
141 
142  QVariant vRows = QVariant::fromValue(rowList);
143 
144  model->appendRows(vRows); // debug
145 
146  return true;
147 }
148 
150 {
151  if(!database.isValid())
152  return NULL;
153 
154  if(!database.isOpen())
155  return NULL;
156 
157  ZsqlQuery* z = NULL;
158  QSqlQuery* q = NULL;
159 
160  try
161  {
162  q = new QSqlQuery(*database.m_db);
163  }
164  catch(...)
165  {
166  if(q)
167  {
168  delete q;
169  return NULL;
170  }
171  }
172 
173  try
174  {
175  z = new ZsqlQuery(q, &database);
176  }
177  catch(...)
178  {
179  if(z)
180  {
181  z->deleteLater();
182  return NULL;
183  }
184  }
185 
186  return z;
187 }
188 
190 {
191  return m_tags;
192 }
193 
195 {
196  if(!m_q)
197  return; // done!
198 
200  delete m_q;
201  m_q = NULL;
203 }
204 
205 void ZsqlQuery::bindValue(const QString& placeholder, const QVariant &value, int paramType)
206 {
208  validateQuery();
209  ensureParamType(paramType);
210  m_q->bindValue(placeholder, value, (QSql::ParamTypeFlag)paramType);
213 }
214 
215 QVariant ZsqlQuery::boundValue(const QString & placeholder) const
216 {
218  validateQuery();
219  ZBL_SLOT_END_RETURN(m_q->boundValue(placeholder), QVariant(),
221 }
222 
223 QVariant ZsqlQuery::value(const QString & name) const
224 {
226  validateQuery();
227  ZBL_SLOT_END_RETURN(m_q->value(name), QVariant(),
229 }
230 
231 bool ZsqlQuery::isNull(int field) const
232 {
234  validateQuery();
235  ZBL_SLOT_END_RETURN(m_q->isNull(field), true,
237 }
238 
239 bool ZsqlQuery::isValid() const
240 {
242  validateQuery();
243  ZBL_SLOT_END_RETURN(m_q->isValid(), true,
245 }
246 bool ZsqlQuery::isActive() const
247 {
249  validateQuery();
250  ZBL_SLOT_END_RETURN(m_q->isActive(), true,
252 }
253 
255 {
257  validateQuery();
258  ZBL_SLOT_END_RETURN(m_q->isForwardOnly(), true,
260 }
261 
262 
264 {
266  validateQuery();
267  ZBL_SLOT_END_RETURN(m_q->exec(), true,
268  Z_FAC_JS, ZsqlQuery::exec, exec failed)
269 }
270 
271 bool ZsqlQuery::prepare(const QString& query)
272 {
274  validateQuery();
275  ZBL_SLOT_END_RETURN(m_q->prepare(query), true,
277 
278 }
279 
280 void ZsqlQuery::setForwardOnly(bool forward)
281 {
283  validateQuery();
284  m_q->setForwardOnly(forward);
287 }
288 
290 {
292  validateQuery();
293  ZBL_SLOT_END_RETURN(m_q->at(), -1,
295 
296 }
297 QString ZsqlQuery::lastQuery() const
298 {
300  validateQuery();
301  ZBL_SLOT_END_RETURN(m_q->lastQuery(), QString(),
303 
304 }
305 
306 int ZsqlQuery::numRowsAffected() const
307 {
309  validateQuery();
310  ZBL_SLOT_END_RETURN(m_q->numRowsAffected(), -1,
312 }
313 
314 bool ZsqlQuery::exec(const QString& query, int
315  resultType, QObject* tableModel)
316 {
317  bool ok = false;
318 
320 
321  if(resultType != ZsqlQuery::TableModel)
322  throw ZblException(
323  "QSqlQuery::exec - Error: only ZsqlQuery::TableModel "
324  "result type is currently supported. Sorry.");
325 
326  if(!tableModel)
327  throw ZblException(
328  "QSqlQuery::exec - Error: you must pass a ZTableModel "
329  "object as argument 3 to receive the query data.");
330 
331  validateQuery();
332 
333  ok = m_q->exec(query);
334 
335  if(!ok)
336  throw ZblException("QSqlQuery::exec - query failed.");
337 
338 #if 0
339 
340  ok = getTableModel(tableModel);
341 
342  if(resultType == ZsqlQuery::TableModel)
343  {
344  emit queryResult(tableModel());
345  }
346 #endif
347 
348  ok = true;
349 
350  ZBL_SLOT_END_RETURN(ok, ok,
351  Z_FAC_JS, ZsqlQuery::exec, exec failed)
352 }
353 
354 bool ZsqlQuery::populateTableModel(QObject* model)
355 {
357 
358  ZTableModel* zModel = qobject_cast<ZTableModel*>(model);
359  if(!zModel)
360  ZblException("Error: ZTableModel object required!");
361 
362  ZBL_SLOT_END_RETURN(getTableModel(zModel), false,
364 }
365 
367 {
368  validateQuery();
369 
371 
372  QSqlRecord rec(m_q->record());
373 
374  int fieldCount = rec.count();
375 
376  for(int i=0; i<fieldCount; i++)
377  metaRow.append(rec.fieldName(i));
378 
379  return metaRow;
380 }
381 
382 QVariant ZsqlQuery::getJsMetaRow() const
383 {
384  //QJSValue jsRow;
385 
387  #if 0
389 
390  const int colCount = metaRow.size();
391 
392  jsRow = m_zApp->engine().newArray(colCount);
393 
394  for(int i = 0; i<colCount; i++)
395  jsRow.setProperty(i, QJSValue(metaRow[i]));
396 
397  ZBL_SLOT_END_RETURN(jsRow, QJSValue(),
399  #else
400 
401  QVariantList jsRow;
402 
403  zMetaRow metaRow = getMetaRow();
404 
405  const int colCount = metaRow.size();
406 
407  for(int i = 0; i<colCount; i++)
408  jsRow.append(QVariant(metaRow[i]));
409 
410  ZBL_SLOT_END_RETURN(QVariant::fromValue(jsRow), QVariant(),
412 
413  #endif
414 }
415 
416 
418 {
419  ZsqlError* error = NULL;
420  bool ok = false;
422  validateQuery();
423  error = new ZsqlError();
424  *error = m_q->lastError();
425  ok = true;
428 
429  if(!ok)
430  {
431  if(error)
432  error->deleteLater();
433 
434  return NULL;
435  }
436 
437  return error;
438 }
439 
440 bool ZsqlQuery::isSelect() const
441 {
443  validateQuery();
444  ZBL_SLOT_END_RETURN(m_q->isSelect(), false,
446 }
447 
448 int ZsqlQuery::size() const
449 {
451  validateQuery();
452  ZBL_SLOT_END_RETURN(m_q->size(), -1,
453  Z_FAC_JS, ZsqlQuery::size, size failed)
454 }
455 
457 {
459  validateQuery();
460  switch(policy)
461  {
462 
467 
468  m_q->setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy(policy));
469  break;
470 
471  default:
472 
473  throw ZblException(QString("Invalid NumericalPrecisionPolicy value: %1")
474  .arg(policy));
475  }
476  ZBL_SLOT_END_VOID(Z_FAC_JS, ZsqlDatabase::setNumericalPrecisionPolicy,
478 
479 
480 }
481 
483 {
485  validateQuery();
486  ZBL_SLOT_END_RETURN(m_q->numericalPrecisionPolicy(), -1,
488 }
489 
491 {
493  validateQuery();
494  ZBL_SLOT_END_RETURN(QVariant::fromValue(m_q->boundValues()), QVariant(),
496 }
497 
499 {
501  validateQuery();
502  ZBL_SLOT_END_RETURN(m_q->executedQuery(), QString(),
504 }
505 
507 {
509  validateQuery();
510  ZBL_SLOT_END_RETURN(m_q->lastInsertId(), QVariant(),
512 }
513 
514 QVariant ZsqlQuery::value(int i) const
515 {
517  validateQuery();
518  ZBL_SLOT_END_RETURN(m_q->value(i), QVariant(),
520 }
521 
522 
523 bool ZsqlQuery::seek(int i, bool relative)
524 {
526  validateQuery();
527  ZBL_SLOT_END_RETURN(m_q->seek(i, relative), false,
528  Z_FAC_JS, ZsqlQuery::seek, seek failed)
529 }
530 
532 {
534  validateQuery();
535  ZBL_SLOT_END_RETURN(m_q->next(), false,
536  Z_FAC_JS, ZsqlQuery::next, next failed)
537 }
538 
540 {
542  validateQuery();
543  ZBL_SLOT_END_RETURN(m_q->previous(), false,
545 }
546 
548 {
550  validateQuery();
551  ZBL_SLOT_END_RETURN(m_q->first(), false,
553 }
554 
556 {
558  validateQuery();
559  ZBL_SLOT_END_RETURN(m_q->last(), false,
560  Z_FAC_JS, ZsqlQuery::last, last failed)
561 }
562 
564 {
566  validateQuery();
567  if(m_q)
568  m_q->clear();
570 }
571 
573 {
575  validateQuery();
576  m_q->finish();
578 
579 }
580 
582 {
584  validateQuery();
585  ZBL_SLOT_END_RETURN(m_q->nextResult(), false,
587 }
588 
589 QVariant ZsqlQuery::boundValue(int pos) const
590 {
592  validateQuery();
593  ZBL_SLOT_END_RETURN(m_q->boundValue(pos), QVariant(),
595 }
596 
597 bool ZsqlQuery::execBatch(int mode)
598 {
600  validateQuery();
601  if(mode != QSqlQuery::ValuesAsRows
602  && mode != QSqlQuery::ValuesAsColumns
603  )
604  {
605  throw ZblException(QString("ERROR: invalid mode: %1 is not a "
606  "QSqlQuery::BatchExecutionMode value!").arg(mode));
607  }
608  ZBL_SLOT_END_RETURN(m_q->execBatch(QSqlQuery::BatchExecutionMode(mode)), false,
610 }
611 
612 void ZsqlQuery::bindValue(int pos, const QVariant& val, ZsqlQuery::ParamType type)
613 {
615  validateQuery();
616  ensureParamType(type);
617  m_q->bindValue(pos, val, QSql::ParamType(type));
619 }
620 
621 void ZsqlQuery::addBindValue(const QVariant& val, ZsqlQuery::ParamType type)
622 {
624  validateQuery();
625  ensureParamType(type);
626  m_q->addBindValue(val, QSql::ParamType(type));
628 }
629 
631 {
632 
633  ZsqlRecord* r = NULL;
634 
636  validateQuery();
637  r = new ZsqlRecord();
638  r->m_r = m_q->record();
640 
641  if(zThreadErr.isError())
642  {
643  if(r)
644  {
645  r->deleteLater();
646  r = NULL;
647  }
648  }
649 
650  return r;
651 }
652 
653 
654 
655 } // Zbl
ZsqlQuery(QSqlQuery *query, QObject *parent=0)
Definition: ZsqlQuery.cpp:40
Q_INVOKABLE void addBindValue(const QVariant &val, ZsqlQuery::ParamType=In)
Adds the value val to the list of values when using positional value binding.
Definition: ZsqlQuery.cpp:621
Q_INVOKABLE void bindValue(const QString &placeholder, const QVariant &value, int paramType)
Definition: ZsqlQuery.cpp:205
bool isValid
Determines if this database connection has a valid database driver.
Definition: ZsqlDatabase.h:153
Q_INVOKABLE bool execBatch(int mode=ValuesAsRows)
Executes a previously prepared SQL query in a batch.
Definition: ZsqlQuery.cpp:597
QVariant metaRow
Returns the ID of the last inserted row.
Definition: ZsqlQuery.h:209
void setNumericalPrecisionPolicy(int policy)
Definition: ZsqlQuery.cpp:456
Q_INVOKABLE void finish()
Instruct the database driver that no more data will be fetched from this query until it is re-execute...
Definition: ZsqlQuery.cpp:572
QVariant getLastInsertId() const
Definition: ZsqlQuery.cpp:506
void createTags()
Create the m_tag object that presents a Javascript interface for ZsqlQuery enumeration values...
Definition: ZsqlQuery.cpp:54
virtual ~ZsqlQuery()
Definition: ZsqlQuery.cpp:48
#define Z_FAC_JS
Definition: zglobal.h:123
Q_INVOKABLE bool seek(int i, bool relative=false)
Definition: ZsqlQuery.cpp:523
Q_INVOKABLE bool populateTableModel(QObject *model)
Populates an empty ZTableModel object with the query result.
Definition: ZsqlQuery.cpp:354
void queryResult(QObject *qResult)
int getPosition() const
Definition: ZsqlQuery.cpp:289
bool isActive() const
bool isForwardOnly() const
Definition: ZsqlQuery.cpp:254
Q_INVOKABLE bool last()
Retrieves the last record in the result, if available, and positions the query on the retrieved recor...
Definition: ZsqlQuery.cpp:555
bool isSelect() const
bool isValid() const
Q_INVOKABLE bool first()
Retrieves the first record in the result, if available, and positions the query on the retrieved reco...
Definition: ZsqlQuery.cpp:547
void initGetTableModel()
Checks that the embedded QSqlQuery object can populate a Zuble table model from it&#39;s result sets and ...
Definition: ZsqlQuery.cpp:86
Q_INVOKABLE void clear()
Clears the result set and releases any resources held by the query. Sets the query state to inactive...
Definition: ZsqlQuery.cpp:563
QSqlRecord m_r
Encapsulated QSqlRecord object.
Definition: ZsqlRecord.h:107
QVariant getTags()
Obtains a javascript dictionary object that maps constants, enumerations and flags for use with ZsqlQ...
Definition: ZsqlQuery.cpp:189
A javascript wrapper class for QSqlDatabase objects. This object represents a database connection...
Definition: ZsqlDatabase.h:71
QString getExecutedQuery() const
Definition: ZsqlQuery.cpp:498
Q_INVOKABLE void appendRows(QVariant data)
int numRowsAffected() const
Definition: ZAndGate.cpp:6
int getNumericalPrecisionPolicy() const
Definition: ZsqlQuery.cpp:482
A javascript wrapper class for QSqlQuery objects. This object represents a query on a database connec...
Definition: ZsqlQuery.h:67
bool getTableModel(ZTableModel *model)
Definition: ZsqlQuery.cpp:100
QMap< int, QList< QVariant > > ZRoleRow
Represents a single row (or column for column headers) of data cell values for multiple roles...
Definition: ZTableModel.h:63
QObject * getLastError()
Definition: ZsqlQuery.cpp:417
Javascript wrapper for a QSqlRecord object.
Definition: ZsqlRecord.h:39
#define ZBL_SLOT_BEGIN_TRY
Definition: zglobal.h:128
static QVariant m_tags
A QVariantMap used to pass ZsqlQuery enumeration values to Javascript programs.
Definition: ZsqlQuery.h:555
QString lastQuery() const
QSqlQuery * m_q
Encapsulated QSqlQuery object.
Definition: ZsqlQuery.h:543
QObject * getLastError()
QVariant getBoundValues() const
Definition: ZsqlQuery.cpp:490
QList< QString > zMetaRow
Definition: ZsqlQuery.h:71
void setForwardOnly(bool forward)
Definition: ZsqlQuery.cpp:280
#define zThreadErr
where does this show up?
Definition: ZblThreadErr.h:39
This two dimensional table model is used to store and manipulate data.
Definition: ZTableModel.h:96
#define ZBL_SLOT_END_VOID(facility, code, error_message)
Definition: zglobal.h:134
static ZsqlQuery * newQuery(ZsqlDatabase &database)
Constructs an empty ZsqlQuery object for the specified database connection.
Definition: ZsqlQuery.cpp:149
int size() const
Q_INVOKABLE bool next()
Retrieves the next record in the result, if available, and positions the query on the retrieved recor...
Definition: ZsqlQuery.cpp:531
void ensureParamType(int paramType)
Checks the specified value and throws a ZblException if it isn&#39;t a ZsqlQuery::ParamType value...
Definition: ZsqlQuery.cpp:72
QVariant getJsMetaRow() const
Definition: ZsqlQuery.cpp:382
Q_INVOKABLE bool exec()
Definition: ZsqlQuery.cpp:263
Q_INVOKABLE void setColumnCount(int count)
Sets the number of columns the table will contain. This method may block the current thread...
Q_INVOKABLE QVariant value(const QString &name) const
Definition: ZsqlQuery.cpp:223
Zuble&#39;s Qt Exception Object.
Definition: ZblException.h:45
Q_INVOKABLE QVariant boundValue(const QString &placeholder) const
Definition: ZsqlQuery.cpp:215
Q_INVOKABLE bool prepare(const QString &query)
Definition: ZsqlQuery.cpp:271
zMetaRow getMetaRow() const
Definition: ZsqlQuery.cpp:366
Q_INVOKABLE bool isNull(int field) const
Definition: ZsqlQuery.cpp:231
Q_INVOKABLE bool addRole(int roleNumber)
Adds the specified role to the data model. This method may block the current thread.
QSqlDatabase * m_db
An encapsulated SQL database object.
Definition: ZsqlDatabase.h:387
QList< QMap< int, QList< QVariant > > > ZRoleRowList
Represents multiple rows of data cell values for multiple roles for multiple columns.
Definition: ZTableModel.h:69
Q_INVOKABLE QObject * record()
Obtains a ZsqlRecord object representing the query result.
Definition: ZsqlQuery.cpp:630
Q_INVOKABLE bool nextResult()
Discards the current result set and navigates to the next if available.
Definition: ZsqlQuery.cpp:581
void validateQuery() const
Checks that the embedded QSqlQuery object exists and throws a ZblException if not.
Definition: ZsqlQuery.h:560
Q_INVOKABLE bool previous()
Retrieves the previous record in the result, if available, and positions the query on the retrieved r...
Definition: ZsqlQuery.cpp:539
Q_INVOKABLE void release()
Releases references from this object to wrapped Qt C++ objects.
Definition: ZsqlQuery.cpp:194
#define ZBL_SLOT_END_RETURN(return_success, return_failed, facility, code, error_message)
Definition: zglobal.h:141
bool isOpen
Determines if this database connection is currently open.
Definition: ZsqlDatabase.h:161
A Javascript wrapper for QSqlError objects. (database sprocket)
Definition: ZsqlError.h:40