-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
SQLiteDatabase.ts
165 lines (139 loc) · 4.1 KB
/
SQLiteDatabase.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import SQLite from 'react-native-sqlite-storage';
import { ConsoleLogger as Logger } from '@aws-amplify/core';
import { PersistentModel } from '@aws-amplify/datastore';
import { DB_NAME } from '../common/constants';
import { CommonSQLiteDatabase, ParameterizedStatement } from '../common/types';
const logger = new Logger('SQLiteDatabase');
SQLite.enablePromise(true);
if (Logger.LOG_LEVEL === 'DEBUG') {
SQLite.DEBUG(true);
}
/*
Note:
I purposely avoided using arrow functions () => {} in this class,
Because I ran into issues with them in some of the SQLite method callbacks
Also, even though the SQLite library is promisified, certain operations
only work correctly with callbacks. Specifically, any time you need to
get the result of an `executeSql` command inside of a transaction
(see the batchQuery method below)
*/
class SQLiteDatabase implements CommonSQLiteDatabase {
private db: SQLite.SQLiteDatabase;
public async init(): Promise<void> {
// only open database once.
if (!this.db) {
this.db = await SQLite.openDatabase({
name: DB_NAME,
location: 'default',
});
}
}
public async createSchema(statements: string[]): Promise<void> {
return await this.executeStatements(statements);
}
public async clear(): Promise<void> {
await this.closeDB();
logger.debug('Deleting database');
await SQLite.deleteDatabase({ name: DB_NAME, location: 'default' });
logger.debug('Database deleted');
}
public async get<T extends PersistentModel>(
statement: string,
params: (string | number)[]
): Promise<T> {
const results: T[] = await this.getAll(statement, params);
return results[0];
}
public async getAll<T extends PersistentModel>(
statement: string,
params: (string | number)[]
): Promise<T[]> {
const [resultSet] = await this.db.executeSql(statement, params);
const result =
resultSet &&
resultSet.rows &&
resultSet.rows.length &&
resultSet.rows.raw &&
resultSet.rows.raw();
return result || [];
}
public async save(
statement: string,
params: (string | number)[]
): Promise<void> {
await this.db.executeSql(statement, params);
}
public async batchQuery<T = any>(
queryParameterizedStatements: Set<ParameterizedStatement>
): Promise<T[]> {
const results = [];
await this.db.readTransaction(tx => {
for (const [statement, params] of queryParameterizedStatements) {
tx.executeSql(
statement,
params,
(_, res) => {
results.push(res.rows.raw()[0]);
},
logger.warn
);
}
});
return results;
}
public async batchSave(
saveParameterizedStatements: Set<ParameterizedStatement>,
deleteParameterizedStatements?: Set<ParameterizedStatement>
): Promise<void> {
await this.db.transaction(tx => {
for (const [statement, params] of saveParameterizedStatements) {
tx.executeSql(statement, params);
}
});
if (deleteParameterizedStatements) {
await this.db.transaction(tx => {
for (const [statement, params] of deleteParameterizedStatements) {
tx.executeSql(statement, params);
}
});
}
}
public async selectAndDelete<T = any>(
queryParameterizedStatement: ParameterizedStatement,
deleteParameterizedStatement: ParameterizedStatement
): Promise<T[]> {
let results: T[] = [];
const [queryStatement, queryParams] = queryParameterizedStatement;
const [deleteStatement, deleteParams] = deleteParameterizedStatement;
await this.db.transaction(tx => {
tx.executeSql(
queryStatement,
queryParams,
(_, res) => {
results = res.rows.raw();
},
logger.warn
);
tx.executeSql(deleteStatement, deleteParams, () => {}, logger.warn);
});
return results;
}
private async executeStatements(statements: string[]): Promise<void> {
await this.db.transaction(tx => {
for (const statement of statements) {
tx.executeSql(statement);
}
});
}
private async closeDB() {
if (this.db) {
logger.debug('Closing Database');
await this.db.close();
logger.debug('Database closed');
this.db = undefined;
}
}
}
export default SQLiteDatabase;