modelbasicoperation.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. #include "modelbasicoperation.h"
  2. #include "qobject.h"
  3. CWF_BEGIN_NAMESPACE
  4. ModelBasicOperation::ModelBasicOperation(SqlDatabaseStorage &connection)
  5. : connection(connection)
  6. {}
  7. bool ModelBasicOperation::createTable(const QString &name)
  8. {
  9. SqlQueryManager queryManager(connection);
  10. QJsonObject json = queryManager.exec(queryManager.createTable(name));
  11. bool success = json["success"].toBool();
  12. if (!success) {
  13. qFatal("%s",
  14. ("ModelBasicOperation::createTable: CREATE TABLE " + name
  15. + json["message"].toString())
  16. .toStdString()
  17. .data());
  18. }
  19. queryManager.reset();
  20. queryManager.insert("table_version", "table_name, version_number");
  21. queryManager.prepare();
  22. queryManager.addBindValue(name);
  23. queryManager.addBindValue(0);
  24. json = queryManager.exec();
  25. success = json["success"].toBool();
  26. if (!success) {
  27. qFatal("%s",
  28. ("ModelBasicOperation::createTable: INSERT INTO table_version "
  29. + json["message"].toString())
  30. .toStdString()
  31. .data());
  32. }
  33. return success;
  34. }
  35. bool ModelBasicOperation::createVersionTable()
  36. {
  37. const auto &json
  38. = SqlQueryManager(connection)
  39. .exec("CREATE TABLE table_version (table_name TEXT, version_number INTEGER);");
  40. bool success = json["success"].toBool();
  41. if (!success) {
  42. qFatal("ModelBasicOperation::createTable: CREATE TABLE table_version " //
  43. "(tableName TEXT, version_number INTEGER);");
  44. }
  45. return success;
  46. }
  47. bool ModelBasicOperation::addFieldToTable(const QString &fieldName,
  48. const QVariant::Type type,
  49. const QString &tableName) const
  50. {
  51. QString fieldTypeStr = convertQVariantTypeToSQLType(type);
  52. SqlQueryManager queryManager(connection);
  53. QJsonObject json = queryManager.exec(
  54. queryManager.alterTable(tableName).addColumn(fieldName, fieldTypeStr).getQueryText());
  55. bool success = json.value("success").toBool();
  56. if (!success) {
  57. qDebug() << "ModelBasicOperation::addFieldToTable:"
  58. << "ALTER TABLE" << json.value("message").toString();
  59. }
  60. return success;
  61. }
  62. bool ModelBasicOperation::changeTableVersion(const QString &tableName, qint32 version) const
  63. {
  64. SqlQueryManager queryManager(connection);
  65. QJsonObject json;
  66. queryManager.update("table_version", "version_number=?").where("table_name=?");
  67. queryManager.prepare();
  68. queryManager.addBindValue(version);
  69. queryManager.addBindValue(tableName);
  70. json = queryManager.exec();
  71. bool success = json["success"].toBool();
  72. if (!success) {
  73. qFatal("%s",
  74. ("ModelBasicOperation::changeTableVersion: Error in UPDATE version message:"
  75. + json["message"].toString())
  76. .toStdString()
  77. .data());
  78. }
  79. return success;
  80. }
  81. QStringList ModelBasicOperation::fields(const QString &tableName) const
  82. {
  83. QStringList output;
  84. const auto &record = connection.getDatabase().record(tableName);
  85. for (int i = 0, numOfFields = record.count(); i < numOfFields; i++) {
  86. output.push_back(record.fieldName(i));
  87. }
  88. return output;
  89. }
  90. qint32 ModelBasicOperation::tableVersion(const QString &tableName) const
  91. {
  92. SqlQueryManager queryManager(connection);
  93. QJsonObject json;
  94. QJsonArray jsonArray;
  95. queryManager.select("version_number", "table_version").where("table_name=?");
  96. queryManager.prepare();
  97. queryManager.addBindValue(tableName);
  98. json = queryManager.exec();
  99. if (!json.value("success").toBool()) {
  100. qFatal("%s",
  101. ("ModelBasicOperation::tableVersion: SELECT " + json["message"].toString())
  102. .toStdString()
  103. .data());
  104. }
  105. auto array = queryManager.toJson();
  106. if (array.isEmpty()) {
  107. qFatal("%s",
  108. ("ModelBasicOperation::tableVersion: Empty array " + json["message"].toString())
  109. .toStdString()
  110. .data());
  111. }
  112. int version = array.at(0).toObject()["version_number"].toInt();
  113. return version;
  114. }
  115. QString ModelBasicOperation::convertQVariantTypeToSQLType(const QVariant::Type type) const
  116. {
  117. QString output("");
  118. switch (type) {
  119. case QVariant::Invalid: {
  120. qDebug() << "ModelBasicOperation::convertQVariantTypeToSQLType:"
  121. << "Type was invalid";
  122. qFatal("Type was invalid");
  123. }
  124. case QVariant::Type::ByteArray: {
  125. output = "BLOB";
  126. break;
  127. }
  128. case QVariant::UInt:
  129. case QVariant::Int: {
  130. output = "INTEGER";
  131. break;
  132. }
  133. case QVariant::Char:
  134. case QMetaType::SChar: {
  135. output = "INTEGER";
  136. break;
  137. }
  138. case QVariant::Bool: {
  139. output = "INTEGER";
  140. break;
  141. }
  142. case QVariant::ULongLong:
  143. case QVariant::LongLong: {
  144. output = "INTEGER";
  145. break;
  146. }
  147. case QVariant::String: {
  148. output = "TEXT";
  149. break;
  150. }
  151. case QVariant::Double: {
  152. output = "REAL";
  153. break;
  154. }
  155. default: {
  156. qDebug() << "ModelBasicOperation::convertQVariantTypeToSQLType:"
  157. << "Type was not defined " << type;
  158. qFatal("Type was not defined");
  159. }
  160. }
  161. return output;
  162. }
  163. qint64 ModelBasicOperation::save(const QString &tableName, const QMap<QString, QVariant> &map)
  164. {
  165. QVariant idValue = map["id"];
  166. qint64 id = idValue.toInt();
  167. if (id == -1) {
  168. id = insertEntry(tableName, map);
  169. } else {
  170. id = updateEntry(tableName, map);
  171. }
  172. return id;
  173. }
  174. QVector<QMap<QString, QVariant> > ModelBasicOperation::buildVector(
  175. const QString &tableName,
  176. const QMap<QString, QVariant> &selectCondition,
  177. const QStringList &props,
  178. const QString &orderBy)
  179. {
  180. /* Example of insert query
  181. SELECT id, type, datetime, entry, comment, status, priority, observerId, observationId FROM data WHERE id = ?;
  182. */
  183. CWF::SqlQuery query(connection);
  184. QJsonObject json;
  185. // *****************************
  186. // Query contruction
  187. // *****************************
  188. QString what("");
  189. // Loop on all the object properties
  190. for (int i = 0, ie = props.size(); i < ie; i++) {
  191. what += props.at(i);
  192. if (i >= 0 && i < ie - 1)
  193. what += ", ";
  194. }
  195. QString cond("");
  196. QVector<QVariant> selectValues;
  197. qint32 count = 0;
  198. qint32 selectCondNum = selectCondition.size();
  199. // Loop on all the select conditions
  200. for (const auto &it : selectCondition.toStdMap()) {
  201. const QString &name = it.first;
  202. const QVariant &value = it.second;
  203. cond += name + " = ?";
  204. if (count >= 0 && count < selectCondNum - 1)
  205. cond += " AND ";
  206. selectValues.push_back(value);
  207. count++;
  208. }
  209. SqlQueryManager queryManager(connection);
  210. queryManager.select(what, tableName).where(cond).orderBy(orderBy);
  211. QString queryText = queryManager.textQuery(true);
  212. // Prepare the query
  213. query.prepare(queryText);
  214. // *****************************
  215. // Bindings with values
  216. // *****************************
  217. // Loop on all the prop inserted in the sql query
  218. for (const auto &v : selectValues) {
  219. query.addBindValue(v);
  220. }
  221. // *****************************
  222. // Run the query
  223. // *****************************
  224. json = query.exec();
  225. if (!json.value("success").toBool()) {
  226. qDebug() << "ModelBasicOperation::build:"
  227. << "Error in insert for table" << tableName << json.value("message").toString()
  228. << query.executedQuery();
  229. }
  230. // *****************************
  231. // Get the result
  232. // *****************************
  233. QVector<QMap<QString, QVariant> > output;
  234. if (query.first()) {
  235. do {
  236. QMap<QString, QVariant> map;
  237. for (const QString &propName : props) {
  238. QVariant val = query.value(propName);
  239. map.insert(propName, val);
  240. }
  241. output.push_back(map);
  242. } while (query.next());
  243. }
  244. return output;
  245. }
  246. QMap<QString, QVariant> ModelBasicOperation::build(const QString &tableName,
  247. const QMap<QString, QVariant> &selectCondition,
  248. const QStringList &props)
  249. {
  250. QVector<QMap<QString, QVariant> > output = buildVector(tableName, selectCondition, props);
  251. if (!output.empty())
  252. return output.at(0);
  253. return QMap<QString, QVariant>();
  254. }
  255. bool ModelBasicOperation::remove(const QString &tableName, const qint64 &id)
  256. {
  257. CWF::SqlQuery query(connection);
  258. SqlQueryManager qm(connection);
  259. qm.remove(tableName, "id=?");
  260. QString textQuery = qm.textQuery(true);
  261. query.prepare(textQuery);
  262. query.bindValue(0, id);
  263. QJsonObject json;
  264. json = query.exec();
  265. if (!json.value("success").toBool()) {
  266. qDebug() << "ModelBasicOperation::remove:"
  267. << "Error in index creation for table" << tableName
  268. << json.value("message").toString() << query.executedQuery();
  269. return false;
  270. }
  271. return true;
  272. }
  273. bool ModelBasicOperation::createIndex(const QString &tableName,
  274. const QString &column,
  275. bool unique) const
  276. {
  277. QString indexName = QString("index_") + tableName + QString("_") + column;
  278. CWF::SqlQuery query(connection);
  279. QJsonObject json;
  280. SqlQueryManager queryManager(connection);
  281. queryManager.createIndex(indexName, tableName, column, unique);
  282. QString queryText = queryManager.textQuery(true);
  283. query.prepare(queryText);
  284. json = query.exec();
  285. if (!json.value("success").toBool()) {
  286. qDebug() << "ModelBasicOperation::createIndex:"
  287. << "Error in index creation for table" << tableName
  288. << json.value("message").toString() << query.executedQuery();
  289. return false;
  290. }
  291. return true;
  292. }
  293. QString ModelBasicOperation::constructInsertTextQuery(const QString &tableName,
  294. const QMap<QString, QVariant> &map,
  295. QVector<QVariant> &values)
  296. {
  297. QString fields;
  298. for (const auto &it : map.toStdMap()) {
  299. const QString &name = it.first.toLower();
  300. const QVariant &value = it.second;
  301. if (name == "id")
  302. continue;
  303. fields += name;
  304. fields += ",";
  305. values.push_back(value);
  306. }
  307. fields = fields.remove(fields.size() - 1, 1);
  308. SqlQueryManager queryManager(connection);
  309. queryManager.insert(tableName, fields);
  310. QString queryText = queryManager.textQuery(true);
  311. return queryText;
  312. }
  313. QString ModelBasicOperation::constructUpdateTextQuery(const QString &tableName,
  314. const QMap<QString, QVariant> &map,
  315. QVector<QVariant> &values)
  316. {
  317. QString fieldValues;
  318. for (const auto &it : map.toStdMap()) {
  319. const QString &name = it.first;
  320. const QVariant &value = it.second;
  321. if (name == "id")
  322. continue;
  323. fieldValues += name + " = ?,";
  324. values.push_back(value);
  325. }
  326. fieldValues = fieldValues.remove(fieldValues.size() - 1, 1);
  327. SqlQueryManager queryManager(connection);
  328. queryManager.update(tableName, fieldValues);
  329. queryManager.where("id=?");
  330. return queryManager.getQueryText() + ";";
  331. }
  332. qint64 ModelBasicOperation::insertEntry(const QString &tableName, const QMap<QString, QVariant> &map)
  333. {
  334. CWF::SqlQuery query(connection);
  335. QJsonObject json;
  336. QVector<QVariant> values;
  337. query.prepare(constructInsertTextQuery(tableName, map, values));
  338. for (const auto &it : values) {
  339. query.addBindValue(it);
  340. }
  341. json = query.exec();
  342. if (!json["success"].toBool()) {
  343. qDebug() << "ModelBasicOperation::insertEntry:"
  344. << "Error in insert for table" << tableName << json["message"].toString()
  345. << query.executedQuery();
  346. return -1;
  347. }
  348. return query.lastInsertId().toInt();
  349. }
  350. qint64 ModelBasicOperation::updateEntry(const QString &tableName, const QMap<QString, QVariant> &map)
  351. {
  352. CWF::SqlQuery query(connection);
  353. QVector<QVariant> values;
  354. query.prepare(constructUpdateTextQuery(tableName, map, values));
  355. for (const auto &it : values) {
  356. query.addBindValue(it);
  357. }
  358. int id = map.value("id").toInt();
  359. query.addBindValue(map.value("id"));
  360. QJsonObject json = query.exec();
  361. if (!json["success"].toBool()) {
  362. id = -1;
  363. qDebug() << "ModelBasicOperation::updateEntry: Error in insert for table" << tableName
  364. << json["message"].toString();
  365. }
  366. return id;
  367. }
  368. CWF_END_NAMESPACE