/
SqliteConnection.ts
110 lines (88 loc) · 2.74 KB
/
SqliteConnection.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import { ensureDir, readFile } from 'fs-extra';
import { dirname } from 'path';
import { Config } from 'knex';
import { AbstractSqlConnection } from './AbstractSqlConnection';
export class SqliteConnection extends AbstractSqlConnection {
async connect(): Promise<void> {
await ensureDir(dirname(this.config.get('dbName')!));
this.client = this.createKnexClient(this.getPatchedDialect());
await this.client.raw('pragma foreign_keys = on');
}
getDefaultClientUrl(): string {
return '';
}
getClientUrl(): string {
return '';
}
async loadFile(path: string): Promise<void> {
const conn = await this.client.client.acquireConnection();
await conn.exec((await readFile(path)).toString());
await this.client.client.releaseConnection(conn);
}
protected getKnexOptions(type: string): Config {
return {
client: type,
connection: {
filename: this.config.get('dbName'),
},
useNullAsDefault: true,
};
}
protected transformRawResult<T>(res: any, method: 'all' | 'get' | 'run'): T {
if (method === 'get') {
return res[0];
}
if (method === 'all') {
return res;
}
return {
insertId: res.lastID,
affectedRows: res.changes,
} as unknown as T;
}
/**
* monkey patch knex' sqlite dialect so it returns inserted id when doing raw insert query
*/
private getPatchedDialect() {
const dialect = require('knex/lib/dialects/sqlite3/index.js');
const processResponse = dialect.prototype.processResponse;
dialect.prototype.processResponse = (obj: any, runner: any) => {
if (obj.method === 'raw' && obj.sql.trim().match('^insert into|update|delete')) {
return obj.context;
}
return processResponse(obj, runner);
};
dialect.prototype._query = (connection: any, obj: any) => {
const callMethod = this.getCallMethod(obj);
return new Promise((resolve: any, reject: any) => {
/* istanbul ignore if */
if (!connection || !connection[callMethod]) {
return reject(new Error(`Error calling ${callMethod} on connection.`));
}
connection[callMethod](obj.sql, obj.bindings, function (this: any, err: any, response: any) {
if (err) {
return reject(err);
}
obj.response = response;
obj.context = this;
return resolve(obj);
});
});
};
return dialect;
}
private getCallMethod(obj: any): string {
if (obj.method === 'raw' && obj.sql.trim().match('^insert into|update|delete')) {
return 'run';
}
switch (obj.method) {
case 'insert':
case 'update':
case 'counter':
case 'del':
return 'run';
default:
return 'all';
}
}
}