| 
									
										
										
										
											2017-10-21 21:10:33 -04:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-07 22:01:52 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @module sql | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 22:17:48 -04:00
										 |  |  | const log = require('./log'); | 
					
						
							| 
									
										
										
										
											2020-06-20 21:42:41 +02:00
										 |  |  | const Database = require('better-sqlite3'); | 
					
						
							|  |  |  | const dataDir = require('./data_dir'); | 
					
						
							| 
									
										
										
										
											2021-03-12 23:48:14 +01:00
										 |  |  | const cls = require('./cls'); | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 21:42:41 +02:00
										 |  |  | const dbConnection = new Database(dataDir.DOCUMENT_PATH); | 
					
						
							|  |  |  | dbConnection.pragma('journal_mode = WAL'); | 
					
						
							| 
									
										
										
										
											2017-12-03 22:29:23 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-15 17:56:53 +02:00
										 |  |  | [`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `SIGTERM`].forEach(eventType => { | 
					
						
							| 
									
										
										
										
											2020-04-14 22:15:55 +02:00
										 |  |  |     process.on(eventType, () => { | 
					
						
							|  |  |  |         if (dbConnection) { | 
					
						
							|  |  |  |             // closing connection is especially important to fold -wal file into the main DB file
 | 
					
						
							|  |  |  |             // (see https://sqlite.org/tempfiles.html for details)
 | 
					
						
							|  |  |  |             dbConnection.close(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function insert(tableName, rec, replace = false) { | 
					
						
							| 
									
										
										
										
											2017-10-25 22:39:21 -04:00
										 |  |  |     const keys = Object.keys(rec); | 
					
						
							|  |  |  |     if (keys.length === 0) { | 
					
						
							| 
									
										
										
										
											2019-03-25 22:06:17 +01:00
										 |  |  |         log.error("Can't insert empty object into table " + tableName); | 
					
						
							| 
									
										
										
										
											2017-10-25 22:39:21 -04:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const columns = keys.join(", "); | 
					
						
							|  |  |  |     const questionMarks = keys.map(p => "?").join(", "); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-25 22:06:17 +01:00
										 |  |  |     const query = "INSERT " + (replace ? "OR REPLACE" : "") + " INTO " + tableName + "(" + columns + ") VALUES (" + questionMarks + ")"; | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  |     const res = execute(query, Object.values(rec)); | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-27 21:09:13 +01:00
										 |  |  |     return res ? res.lastInsertRowid : null; | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function replace(tableName, rec) { | 
					
						
							|  |  |  |     return insert(tableName, rec, true); | 
					
						
							| 
									
										
										
										
											2019-03-25 22:06:17 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function upsert(tableName, primaryKey, rec) { | 
					
						
							| 
									
										
										
										
											2019-03-25 22:06:17 +01:00
										 |  |  |     const keys = Object.keys(rec); | 
					
						
							|  |  |  |     if (keys.length === 0) { | 
					
						
							|  |  |  |         log.error("Can't upsert empty object into table " + tableName); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const columns = keys.join(", "); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-17 23:03:46 +02:00
										 |  |  |     const questionMarks = keys.map(colName => "@" + colName).join(", "); | 
					
						
							| 
									
										
										
										
											2019-03-25 22:06:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-17 23:03:46 +02:00
										 |  |  |     const updateMarks = keys.map(colName => `${colName} = @${colName}`).join(", "); | 
					
						
							| 
									
										
										
										
											2019-03-25 22:06:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const query = `INSERT INTO ${tableName} (${columns}) VALUES (${questionMarks}) 
 | 
					
						
							|  |  |  |                    ON CONFLICT (${primaryKey}) DO UPDATE SET ${updateMarks}`;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-17 23:03:46 +02:00
										 |  |  |     for (const idx in rec) { | 
					
						
							|  |  |  |         if (rec[idx] === true || rec[idx] === false) { | 
					
						
							|  |  |  |             rec[idx] = rec[idx] ? 1 : 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  |     execute(query, rec); | 
					
						
							| 
									
										
										
										
											2017-10-29 22:22:30 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-17 23:03:46 +02:00
										 |  |  | const statementCache = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function stmt(sql) { | 
					
						
							|  |  |  |     if (!(sql in statementCache)) { | 
					
						
							|  |  |  |         statementCache[sql] = dbConnection.prepare(sql); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return statementCache[sql]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function getRow(query, params = []) { | 
					
						
							| 
									
										
										
										
											2020-06-20 21:42:41 +02:00
										 |  |  |     return wrap(query, s => s.get(params)); | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function getRowOrNull(query, params = []) { | 
					
						
							|  |  |  |     const all = getRows(query, params); | 
					
						
							| 
									
										
										
										
											2017-10-28 19:55:55 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 22:22:30 -04:00
										 |  |  |     return all.length > 0 ? all[0] : null; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function getValue(query, params = []) { | 
					
						
							|  |  |  |     const row = getRowOrNull(query, params); | 
					
						
							| 
									
										
										
										
											2017-10-29 22:22:30 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!row) { | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return row[Object.keys(row)[0]]; | 
					
						
							| 
									
										
										
										
											2017-10-28 19:55:55 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-16 22:57:48 +02:00
										 |  |  | // smaller values can result in better performance due to better usage of statement cache
 | 
					
						
							|  |  |  | const PARAM_LIMIT = 100; | 
					
						
							| 
									
										
										
										
											2018-05-30 20:28:10 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function getManyRows(query, params) { | 
					
						
							| 
									
										
										
										
											2018-05-30 20:28:10 -04:00
										 |  |  |     let results = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (params.length > 0) { | 
					
						
							| 
									
										
										
										
											2019-05-13 20:40:00 +02:00
										 |  |  |         const curParams = params.slice(0, Math.min(params.length, PARAM_LIMIT)); | 
					
						
							| 
									
										
										
										
											2018-05-30 20:28:10 -04:00
										 |  |  |         params = params.slice(curParams.length); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-17 23:03:46 +02:00
										 |  |  |         const curParamsObj = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let j = 1; | 
					
						
							|  |  |  |         for (const param of curParams) { | 
					
						
							|  |  |  |             curParamsObj['param' + j++] = param; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-30 20:28:10 -04:00
										 |  |  |         let i = 1; | 
					
						
							| 
									
										
										
										
											2020-06-17 23:03:46 +02:00
										 |  |  |         const questionMarks = curParams.map(() => ":param" + i++).join(","); | 
					
						
							| 
									
										
										
										
											2018-05-30 20:28:10 -04:00
										 |  |  |         const curQuery = query.replace(/\?\?\?/g, questionMarks); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-16 22:57:48 +02:00
										 |  |  |         const statement = curParams.length === PARAM_LIMIT | 
					
						
							|  |  |  |             ? stmt(curQuery) | 
					
						
							|  |  |  |             : dbConnection.prepare(curQuery); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const subResults = statement.all(curParamsObj); | 
					
						
							| 
									
										
										
										
											2020-06-20 23:24:34 +02:00
										 |  |  |         results = results.concat(subResults); | 
					
						
							| 
									
										
										
										
											2018-05-30 20:28:10 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return results; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function getRows(query, params = []) { | 
					
						
							| 
									
										
										
										
											2020-06-20 21:42:41 +02:00
										 |  |  |     return wrap(query, s => s.all(params)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function iterateRows(query, params = []) { | 
					
						
							|  |  |  |     return stmt(query).iterate(params); | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function getMap(query, params = []) { | 
					
						
							| 
									
										
										
										
											2017-11-02 22:55:22 -04:00
										 |  |  |     const map = {}; | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  |     const results = getRows(query, params); | 
					
						
							| 
									
										
										
										
											2017-11-02 22:55:22 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (const row of results) { | 
					
						
							|  |  |  |         const keys = Object.keys(row); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         map[row[keys[0]]] = row[keys[1]]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return map; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function getColumn(query, params = []) { | 
					
						
							| 
									
										
										
										
											2017-10-24 23:14:26 -04:00
										 |  |  |     const list = []; | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  |     const result = getRows(query, params); | 
					
						
							| 
									
										
										
										
											2017-10-24 23:14:26 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-14 22:16:26 -05:00
										 |  |  |     if (result.length === 0) { | 
					
						
							|  |  |  |         return list; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const key = Object.keys(result[0])[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 23:14:26 -04:00
										 |  |  |     for (const row of result) { | 
					
						
							|  |  |  |         list.push(row[key]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function execute(query, params = []) { | 
					
						
							| 
									
										
										
										
											2020-06-20 21:42:41 +02:00
										 |  |  |     return wrap(query, s => s.run(params)); | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function executeWithoutTransaction(query, params = []) { | 
					
						
							|  |  |  |     dbConnection.run(query, params); | 
					
						
							| 
									
										
										
										
											2020-05-29 21:55:08 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function executeMany(query, params) { | 
					
						
							| 
									
										
										
										
											2020-07-09 23:59:27 +02:00
										 |  |  |     while (params.length > 0) { | 
					
						
							|  |  |  |         const curParams = params.slice(0, Math.min(params.length, PARAM_LIMIT)); | 
					
						
							|  |  |  |         params = params.slice(curParams.length); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const curParamsObj = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let j = 1; | 
					
						
							|  |  |  |         for (const param of curParams) { | 
					
						
							|  |  |  |             curParamsObj['param' + j++] = param; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let i = 1; | 
					
						
							|  |  |  |         const questionMarks = curParams.map(() => ":param" + i++).join(","); | 
					
						
							|  |  |  |         const curQuery = query.replace(/\?\?\?/g, questionMarks); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dbConnection.prepare(curQuery).run(curParamsObj); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-11-01 22:09:51 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function executeScript(query) { | 
					
						
							| 
									
										
										
										
											2020-06-20 21:42:41 +02:00
										 |  |  |     return dbConnection.exec(query); | 
					
						
							| 
									
										
										
										
											2017-10-15 17:31:49 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 21:42:41 +02:00
										 |  |  | function wrap(query, func) { | 
					
						
							|  |  |  |     const startTimestamp = Date.now(); | 
					
						
							| 
									
										
										
										
											2020-08-30 22:29:38 +02:00
										 |  |  |     let result; | 
					
						
							| 
									
										
										
										
											2020-05-03 21:27:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 22:29:38 +02:00
										 |  |  |     try { | 
					
						
							|  |  |  |         result = func(stmt(query)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     catch (e) { | 
					
						
							|  |  |  |         if (e.message.includes("The database connection is not open")) { | 
					
						
							|  |  |  |             // this often happens on killing the app which puts these alerts in front of user
 | 
					
						
							|  |  |  |             // in these cases error should be simply ignored.
 | 
					
						
							|  |  |  |             console.log(e.message); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return null | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-12-16 20:58:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         throw e; | 
					
						
							| 
									
										
										
										
											2020-08-30 22:29:38 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 21:42:41 +02:00
										 |  |  |     const milliseconds = Date.now() - startTimestamp; | 
					
						
							| 
									
										
										
										
											2019-12-01 12:51:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 23:24:34 +02:00
										 |  |  |     if (milliseconds >= 20) { | 
					
						
							| 
									
										
										
										
											2020-06-20 21:42:41 +02:00
										 |  |  |         if (query.includes("WITH RECURSIVE")) { | 
					
						
							|  |  |  |             log.info(`Slow recursive query took ${milliseconds}ms.`); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							| 
									
										
										
										
											2020-12-11 15:24:44 +01:00
										 |  |  |             log.info(`Slow query took ${milliseconds}ms: ${query.trim().replace(/\s+/g, " ")}`); | 
					
						
							| 
									
										
										
										
											2020-06-20 21:42:41 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-01 20:31:44 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-11-18 18:57:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 21:42:41 +02:00
										 |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2017-11-01 20:31:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function transactional(func) { | 
					
						
							| 
									
										
										
										
											2021-03-12 23:48:14 +01:00
										 |  |  |     try { | 
					
						
							|  |  |  |         const ret = dbConnection.transaction(func).deferred(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!dbConnection.inTransaction) { // i.e. transaction was really committed (and not just savepoint released)
 | 
					
						
							| 
									
										
										
										
											2021-03-21 22:43:41 +01:00
										 |  |  |             require('./ws.js').sendTransactionEntityChangesToAllClients(); | 
					
						
							| 
									
										
										
										
											2021-03-12 23:48:14 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-29 18:50:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 23:48:14 +01:00
										 |  |  |         return ret; | 
					
						
							| 
									
										
										
										
											2020-06-21 13:44:47 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-12 23:48:14 +01:00
										 |  |  |     catch (e) { | 
					
						
							|  |  |  |         cls.clearEntityChanges(); | 
					
						
							| 
									
										
										
										
											2017-10-31 00:15:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 23:48:14 +01:00
										 |  |  |         throw e; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-29 18:50:28 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-14 22:54:39 +01:00
										 |  |  | function fillParamList(paramIds, truncate = true) { | 
					
						
							|  |  |  |     if (paramIds.length === 0) { | 
					
						
							| 
									
										
										
										
											2020-12-10 21:27:21 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (truncate) { | 
					
						
							|  |  |  |         execute("DELETE FROM param_list"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-14 22:54:39 +01:00
										 |  |  |     paramIds = Array.from(new Set(paramIds)); | 
					
						
							| 
									
										
										
										
											2020-12-10 21:27:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-14 22:54:39 +01:00
										 |  |  |     if (paramIds.length > 30000) { | 
					
						
							|  |  |  |         fillParamList(paramIds.slice(30000), false); | 
					
						
							| 
									
										
										
										
											2020-12-10 21:27:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-14 22:54:39 +01:00
										 |  |  |         paramIds = paramIds.slice(0, 30000); | 
					
						
							| 
									
										
										
										
											2020-12-10 21:27:21 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // doing it manually to avoid this showing up on the sloq query list
 | 
					
						
							| 
									
										
										
										
											2021-03-14 22:54:39 +01:00
										 |  |  |     const s = stmt(`INSERT INTO param_list VALUES ` + paramIds.map(paramId => `(?)`).join(','), paramIds); | 
					
						
							| 
									
										
										
										
											2020-12-10 21:27:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-14 22:54:39 +01:00
										 |  |  |     s.run(paramIds); | 
					
						
							| 
									
										
										
										
											2020-12-10 21:27:21 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  | module.exports = { | 
					
						
							| 
									
										
										
										
											2020-06-20 23:09:34 +02:00
										 |  |  |     dbConnection, | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  |     insert, | 
					
						
							| 
									
										
										
										
											2017-10-29 22:22:30 -04:00
										 |  |  |     replace, | 
					
						
							| 
									
										
										
										
											2021-04-07 22:01:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get single value from the given query - first column from first returned row. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @method | 
					
						
							|  |  |  |      * @param {string} query - SQL query with ? used as parameter placeholder | 
					
						
							|  |  |  |      * @param {object[]} [params] - array of params if needed | 
					
						
							|  |  |  |      * @return [object] - single value | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2018-01-29 17:41:59 -05:00
										 |  |  |     getValue, | 
					
						
							| 
									
										
										
										
											2021-04-07 22:01:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get first returned row. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @method | 
					
						
							|  |  |  |      * @param {string} query - SQL query with ? used as parameter placeholder | 
					
						
							|  |  |  |      * @param {object[]} [params] - array of params if needed | 
					
						
							|  |  |  |      * @return {object} - map of column name to column value | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2018-01-29 17:41:59 -05:00
										 |  |  |     getRow, | 
					
						
							|  |  |  |     getRowOrNull, | 
					
						
							| 
									
										
										
										
											2021-04-07 22:01:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get all returned rows. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @method | 
					
						
							|  |  |  |      * @param {string} query - SQL query with ? used as parameter placeholder | 
					
						
							|  |  |  |      * @param {object[]} [params] - array of params if needed | 
					
						
							|  |  |  |      * @return {object[]} - array of all rows, each row is a map of column name to column value | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2018-01-29 17:41:59 -05:00
										 |  |  |     getRows, | 
					
						
							| 
									
										
										
										
											2020-06-20 21:42:41 +02:00
										 |  |  |     iterateRows, | 
					
						
							| 
									
										
										
										
											2018-05-30 20:28:10 -04:00
										 |  |  |     getManyRows, | 
					
						
							| 
									
										
										
										
											2021-04-07 22:01:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get a map of first column mapping to second column. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @method | 
					
						
							|  |  |  |      * @param {string} query - SQL query with ? used as parameter placeholder | 
					
						
							|  |  |  |      * @param {object[]} [params] - array of params if needed | 
					
						
							|  |  |  |      * @return {object} - map of first column to second column | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2017-11-02 22:55:22 -04:00
										 |  |  |     getMap, | 
					
						
							| 
									
										
										
										
											2021-04-07 22:01:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get a first column in an array. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @method | 
					
						
							|  |  |  |      * @param {string} query - SQL query with ? used as parameter placeholder | 
					
						
							|  |  |  |      * @param {object[]} [params] - array of params if needed | 
					
						
							|  |  |  |      * @return {object[]} - array of first column of all returned rows | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2018-01-29 17:41:59 -05:00
										 |  |  |     getColumn, | 
					
						
							| 
									
										
										
										
											2021-04-07 22:01:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Execute SQL | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @method | 
					
						
							|  |  |  |      * @param {string} query - SQL query with ? used as parameter placeholder | 
					
						
							|  |  |  |      * @param {object[]} [params] - array of params if needed | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  |     execute, | 
					
						
							| 
									
										
										
										
											2020-06-14 00:35:53 +02:00
										 |  |  |     executeWithoutTransaction, | 
					
						
							| 
									
										
										
										
											2019-11-01 22:09:51 +01:00
										 |  |  |     executeMany, | 
					
						
							| 
									
										
										
										
											2017-10-15 17:31:49 -04:00
										 |  |  |     executeScript, | 
					
						
							| 
									
										
										
										
											2019-03-25 22:06:17 +01:00
										 |  |  |     transactional, | 
					
						
							| 
									
										
										
										
											2020-12-10 21:27:21 +01:00
										 |  |  |     upsert, | 
					
						
							| 
									
										
										
										
											2021-03-14 22:54:39 +01:00
										 |  |  |     fillParamList | 
					
						
							| 
									
										
										
										
											2020-05-12 13:40:42 +02:00
										 |  |  | }; |