modelbasicoperation.cpp 13 KB

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