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