1. 2const path = require('path');
2. 2const sqlite3 = require('./sqlite3-binding.js');
3. 2const EventEmitter = require('events').EventEmitter;
4. 2module.exports = exports = sqlite3;
5. 2
6. 12function normalizeMethod (fn) {
7. 4130 return function (sql) {
8. 4130 let errBack;
9. 4130 const args = Array.prototype.slice.call(arguments, 1);
10. 4130
11. 1120 if (typeof args[args.length - 1] === 'function') {
12. 1120 const callback = args[args.length - 1];
13. 1120 errBack = function(err) {
14. 1120 if (err) {
15. 1120 callback(err);
16. 1120 }
17. 1120 };
18. 1120 }
19. 4130 const statement = new Statement(this, sql, errBack);
20. 4130 return fn.call(this, statement, args);
21. 4130 };
22. 12}
23. 2
24. 6function inherits(target, source) {
25. 6 for (const k in source.prototype)
26. 108 target.prototype[k] = source.prototype[k];
27. 6}
28. 2
29. 2sqlite3.cached = {
30. 4 Database: function(file, a, b) {
31. -0 if (file === '' || file === ':memory:') {
32. -0 // Don't cache special databases.
33. -0 return new Database(file, a, b);
34. -0 }
35. 4
36. 4 let db;
37. 4 file = path.resolve(file);
38. 4
39. 2 if (!sqlite3.cached.objects[file]) {
40. 2 db = sqlite3.cached.objects[file] = new Database(file, a, b);
41. 2 }
42. 2 else {
43. 2 // Make sure the callback is called.
44. 2 db = sqlite3.cached.objects[file];
45. -0 const callback = (typeof a === 'number') ? b : a;
46. 2 if (typeof callback === 'function') {
47. 2 function cb() { callback.call(db, null); }
48. 2 if (db.open) process.nextTick(cb);
49. 2 else db.once('open', cb);
50. 2 }
51. 2 }
52. 4
53. 4 return db;
54. 4 },
55. 2 objects: {}
56. 2};
57. 2
58. 2
59. 2const Database = sqlite3.Database;
60. 2const Statement = sqlite3.Statement;
61. 2const Backup = sqlite3.Backup;
62. 2
63. 2inherits(Database, EventEmitter);
64. 2inherits(Statement, EventEmitter);
65. 2inherits(Backup, EventEmitter);
66. 2
67. 2// Database#prepare(sql, [bind1, bind2, ...], [callback])
68. 2000Database.prototype.prepare = normalizeMethod(function(statement, params) {
69. 2000 return params.length
70. 7 ? statement.bind.apply(statement, params)
71. 1993 : statement;
72. 2000});
73. 2
74. 2// Database#run(sql, [bind1, bind2, ...], [callback])
75. 2077Database.prototype.run = normalizeMethod(function(statement, params) {
76. 2077 statement.run.apply(statement, params).finalize();
77. 2077 return this;
78. 2077});
79. 2
80. 2// Database#get(sql, [bind1, bind2, ...], [callback])
81. 35Database.prototype.get = normalizeMethod(function(statement, params) {
82. 35 statement.get.apply(statement, params).finalize();
83. 35 return this;
84. 35});
85. 2
86. 2// Database#all(sql, [bind1, bind2, ...], [callback])
87. 9Database.prototype.all = normalizeMethod(function(statement, params) {
88. 9 statement.all.apply(statement, params).finalize();
89. 9 return this;
90. 9});
91. 2
92. 2// Database#each(sql, [bind1, bind2, ...], [callback], [complete])
93. 7Database.prototype.each = normalizeMethod(function(statement, params) {
94. 7 statement.each.apply(statement, params).finalize();
95. 7 return this;
96. 7});
97. 2
98. 2Database.prototype.map = normalizeMethod(function(statement, params) {
99. 2 statement.map.apply(statement, params).finalize();
100. 2 return this;
101. 2});
102. 2
103. 2// Database#backup(filename, [callback])
104. 2// Database#backup(filename, destName, sourceName, filenameIsDest, [callback])
105. 15Database.prototype.backup = function() {
106. 15 let backup;
107. 13 if (arguments.length <= 2) {
108. 13 // By default, we write the main database out to the main database of the named file.
109. 13 // This is the most likely use of the backup api.
110. 13 backup = new Backup(this, arguments[0], 'main', 'main', true, arguments[1]);
111. 13 } else {
112. 2 // Otherwise, give the user full control over the sqlite3_backup_init arguments.
113. 2 backup = new Backup(this, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
114. 2 }
115. 15 // Per the sqlite docs, exclude the following errors as non-fatal by default.
116. 15 backup.retryErrors = [sqlite3.BUSY, sqlite3.LOCKED];
117. 15 return backup;
118. 15};
119. 2
120. 2Statement.prototype.map = function() {
121. 2 const params = Array.prototype.slice.call(arguments);
122. 2 const callback = params.pop();
123. 2 params.push(function(err, rows) {
124. -0 if (err) return callback(err);
125. 2 const result = {};
126. 2 if (rows.length) {
127. 2 const keys = Object.keys(rows[0]);
128. 2 const key = keys[0];
129. 1 if (keys.length > 2) {
130. 1 // Value is an object
131. 5 for (let i = 0; i < rows.length; i++) {
132. 5 result[rows[i][key]] = rows[i];
133. 5 }
134. 1 } else {
135. 1 const value = keys[1];
136. 1 // Value is a plain value
137. 5 for (let i = 0; i < rows.length; i++) {
138. 5 result[rows[i][key]] = rows[i][value];
139. 5 }
140. 1 }
141. 2 }
142. 2 callback(err, result);
143. 2 });
144. 2 return this.all.apply(this, params);
145. 2};
146. 2
147. 2let isVerbose = false;
148. 2
149. 2const supportedEvents = [ 'trace', 'profile', 'insert', 'update', 'delete' ];
150. 2
151. 7Database.prototype.addListener = Database.prototype.on = function(type) {
152. 7 const val = EventEmitter.prototype.addListener.apply(this, arguments);
153. 4 if (supportedEvents.indexOf(type) >= 0) {
154. 4 this.configure(type, true);
155. 4 }
156. 7 return val;
157. 7};
158. 2
159. 2Database.prototype.removeListener = function(type) {
160. 2 const val = EventEmitter.prototype.removeListener.apply(this, arguments);
161. 1 if (supportedEvents.indexOf(type) >= 0 && !this._events[type]) {
162. 1 this.configure(type, false);
163. 1 }
164. 2 return val;
165. 2};
166. 2
167. 1Database.prototype.removeAllListeners = function(type) {
168. 1 const val = EventEmitter.prototype.removeAllListeners.apply(this, arguments);
169. 1 if (supportedEvents.indexOf(type) >= 0) {
170. 1 this.configure(type, false);
171. 1 }
172. 1 return val;
173. 1};
174. 2
175. 2// Save the stack trace over EIO callbacks.
176. 1sqlite3.verbose = function() {
177. 1 if (!isVerbose) {
178. 1 const trace = require('./trace');
179. 1 [
180. 1 'prepare',
181. 1 'get',
182. 1 'run',
183. 1 'all',
184. 1 'each',
185. 1 'map',
186. 1 'close',
187. 1 'exec'
188. 8 ].forEach(function (name) {
189. 8 trace.extendTrace(Database.prototype, name);
190. 8 });
191. 1 [
192. 1 'bind',
193. 1 'get',
194. 1 'run',
195. 1 'all',
196. 1 'each',
197. 1 'map',
198. 1 'reset',
199. 1 'finalize',
200. 8 ].forEach(function (name) {
201. 8 trace.extendTrace(Statement.prototype, name);
202. 8 });
203. 1 isVerbose = true;
204. 1 }
205. 1
206. 1 return this;
207. 1};
208. 2