databaseHelper.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. const sqlite3 = require('sqlite3');
  2. const SessionModel = require('../model/session.js').SessionModel;
  3. const MediaFileModel = require('../model/mediaItem.js').MediaFileModel;
  4. const CONFIG = require('./config.js');
  5. let ALL_MODELS = [ SessionModel, MediaFileModel ];
  6. function DatabaseHelper() {
  7. this.db = null;
  8. }
  9. DatabaseHelper.prototype.init = function() {
  10. return new Promise((ok, ko) => {
  11. this.db = new sqlite3.Database(CONFIG.database, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE | sqlite3.OPEN_FULLMUTEX, async (err) => {
  12. if (err) {
  13. ko(err);
  14. return;
  15. }
  16. let types = ALL_MODELS;
  17. for (let i =0; i < types.length; ++i) {
  18. let instance = new types[i]();
  19. await instance.createOrUpdateBase(this);
  20. }
  21. console.log("Database is ready");
  22. ok();
  23. });
  24. });
  25. }
  26. DatabaseHelper.prototype.runSql = function(sqlStatement, args) {
  27. console.info("DatabaseHelper::runSql ", sqlStatement, args);
  28. return new Promise((ok, ko) => {
  29. if (sqlStatement.indexOf('--') >= 0) {
  30. console.error("Rejecting SQL request containing comments");
  31. ko("SQL Comment Error");
  32. return;
  33. }
  34. try {
  35. this.db.all(sqlStatement, args, (err, data) => {
  36. if (err) {
  37. console.error(err);
  38. ko(err);
  39. } else {
  40. ok(data);
  41. }
  42. });
  43. } catch (err) {
  44. console.error(err);
  45. ko(err);
  46. }
  47. });
  48. }
  49. DatabaseHelper.prototype.insertOne = async function(object) {
  50. let columns = [];
  51. let args = [];
  52. for (let [key, val] of Object.entries(object.describe())) {
  53. columns.push("`"+key+"`");
  54. args.push(val);
  55. }
  56. let request = "insert into `" +object.getTableName()
  57. +"` (" +columns.join(", ")
  58. +") VALUES (" +columns.map(i => "?").join(",")+")";
  59. await this.runSql(request, args);
  60. }
  61. DatabaseHelper.prototype.upsertOne = async function(obj) {
  62. let columns = [];
  63. let columnsVal = [];
  64. let args = [];
  65. let i =0;
  66. for (let [key, val] of Object.entries(obj.describe())) {
  67. columns.push("`"+key+"`");
  68. columnsVal.push("`"+key+"`=:"+(i++));
  69. args.push(val);
  70. }
  71. let request = "insert into `" +obj.getTableName()
  72. +"` (" +columns.join(", ")
  73. +") VALUES (" +columns.map((_, i) => `:${i}`).join(",")+")"
  74. +" ON CONFLICT DO UPDATE SET " +columnsVal.join(", ");
  75. await this.runSql(request, args);
  76. }
  77. DatabaseHelper.prototype.buildWhere = function(whereObj, columns, args) {
  78. columns = columns || [];
  79. args = args || [];
  80. if (!whereObj) {
  81. columns.push("1=1");
  82. } else {
  83. for (let [key, val] of Object.entries(whereObj)) {
  84. if (val === null) {
  85. columns.push("`"+key+"` is null");
  86. } else if (Array.isArray(val)) {
  87. columns.push("`"+key+"` in (" +val.map(i => "?").join(",") + ")");
  88. for (let i of val) args.push(i);
  89. } else {
  90. columns.push("`"+key+"`=?");
  91. args.push(val);
  92. }
  93. }
  94. }
  95. return {
  96. columns: columns,
  97. args: args
  98. };
  99. }
  100. DatabaseHelper.prototype.maxVersion = async function(instanceName) {
  101. let queryParts = [];
  102. for (let i of ALL_MODELS)
  103. queryParts.push("select max(" +i.prototype.versionColumn.call(null) +") as v from " +i.prototype.getTableName.call(null) +" where instance=:0");
  104. let version = await this.runSql("select max(v) as v from (" +queryParts.join(" union ") +")", [ instanceName ]);
  105. return (version?.[0]?.v) || 0;
  106. }
  107. DatabaseHelper.prototype.versionFetch = async function(objectPrototype, minVersion) {
  108. let query = "select * from `" +objectPrototype.prototype.getTableName.call(null) +"` where `" +objectPrototype.prototype.versionColumn.call(null)+"` > ? and instance=?";
  109. let result = [];
  110. for (let i of await this.runSql(query, [minVersion, CONFIG.instanceHostname]))
  111. {
  112. let resultObj = new objectPrototype();
  113. resultObj.fromDb(i);
  114. result.push(resultObj);
  115. }
  116. return result;
  117. }
  118. DatabaseHelper.prototype.fetch = async function(objectPrototype, where, orderBy) {
  119. let result = await this.fetchRaw("*", objectPrototype.prototype.getTableName.call(null), where, orderBy);
  120. let resultArr = [];
  121. for (let i of result)
  122. {
  123. let resultObj = new objectPrototype();
  124. resultObj.fromDb(i);
  125. resultArr.push(resultObj);
  126. }
  127. return resultArr;
  128. }
  129. DatabaseHelper.prototype.fetchRaw = async function(columns, tableName, where, orderBy) {
  130. let whereArgs = this.buildWhere(where);
  131. let query = "select " + (Array.isArray(columns) ? columns.join(","): columns) +" from `" +tableName +"` where " +whereArgs.columns.join(" and ");
  132. if (orderBy)
  133. query += " ORDER BY " +Object.keys(orderBy || {}).map(i => "`"+i+"` " +(orderBy[i] === 'DESC' ? "DESC":"ASC")).join(",");
  134. return await this.runSql(query, whereArgs.args);
  135. }
  136. DatabaseHelper.prototype.findOne = async function(objectPrototype, where) {
  137. let whereArgs = this.buildWhere(where);
  138. let result = await this.runSql("select * from `" +objectPrototype.prototype.getTableName.call(null) +"` where " +whereArgs.columns.join(" and "), whereArgs.args);
  139. if (result && result.length)
  140. {
  141. let resultObj = new objectPrototype();
  142. resultObj.fromDb(result[0]);
  143. return resultObj;
  144. }
  145. return null;
  146. }
  147. DatabaseHelper.prototype.update = async function(where, object) {
  148. if (object.lastUpdated)
  149. object.lastUpdated = new Date();
  150. await this.rawUpdate(object, where, object.describe());
  151. }
  152. DatabaseHelper.prototype.rawUpdate = async function(model, where, values) {
  153. let columns = [];
  154. let args = [];
  155. for (let [key, val] of Object.entries(values)) {
  156. columns.push("`"+key+"`=?");
  157. args.push(val);
  158. }
  159. let whereArgs = this.buildWhere(where, [], args);
  160. let query = "update `" +(model.prototype?.getTableName ? model.prototype.getTableName() : model.getTableName())
  161. +"` set " +columns.join(", ")
  162. +" WHERE " +whereArgs.columns.join(" and ");
  163. await this.runSql(query, args);
  164. }
  165. module.exports.DatabaseHelper = new DatabaseHelper();