forked from typeorm/typeorm
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSqliteQueryRunner.ts
More file actions
108 lines (95 loc) · 4.81 KB
/
SqliteQueryRunner.ts
File metadata and controls
108 lines (95 loc) · 4.81 KB
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
import {ObjectLiteral} from "../../common/ObjectLiteral";
import {QueryRunnerAlreadyReleasedError} from "../../error/QueryRunnerAlreadyReleasedError";
import {OrmUtils} from "../../util/OrmUtils";
import {InsertResult} from "../InsertResult";
import {QueryFailedError} from "../../error/QueryFailedError";
import {AbstractSqliteQueryRunner} from "../sqlite-abstract/AbstractSqliteQueryRunner";
import {SqliteDriver} from "./SqliteDriver";
/**
* Runs queries on a single sqlite database connection.
*
* Does not support compose primary keys with autoincrement field.
* todo: need to throw exception for this case.
*/
export class SqliteQueryRunner extends AbstractSqliteQueryRunner {
/**
* Database driver used by connection.
*/
driver: SqliteDriver;
// -------------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------------
constructor(driver: SqliteDriver) {
super(driver);
this.driver = driver;
this.connection = driver.connection;
}
/**
* Executes a given SQL query.
*/
query(query: string, parameters?: any[]): Promise<any> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
return new Promise<any[]>(async (ok, fail) => {
const databaseConnection = await this.connect();
this.driver.connection.logger.logQuery(query, parameters, this);
const queryStartTime = +new Date();
databaseConnection.all(query, parameters, (err: any, result: any) => {
// log slow queries if maxQueryExecution time is set
const maxQueryExecutionTime = this.driver.connection.options.maxQueryExecutionTime;
const queryEndTime = +new Date();
const queryExecutionTime = queryEndTime - queryStartTime;
if (maxQueryExecutionTime && queryExecutionTime > maxQueryExecutionTime)
this.driver.connection.logger.logQuerySlow(queryExecutionTime, query, parameters, this);
if (err) {
this.driver.connection.logger.logQueryError(err, query, parameters, this);
fail(new QueryFailedError(query, parameters, err));
} else {
ok(result);
}
});
});
}
/**
* Insert a new row with given values into the given table.
* Returns value of the generated column if given and generate column exist in the table.
*/
async insert(tableName: string, keyValues: ObjectLiteral): Promise<InsertResult> {
const keys = Object.keys(keyValues);
const columns = keys.map(key => `"${key}"`).join(", ");
const values = keys.map((key, index) => "$" + (index + 1)).join(",");
const generatedColumns = this.connection.hasMetadata(tableName) ? this.connection.getMetadata(tableName).generatedColumns : [];
const sql = columns.length > 0 ? (`INSERT INTO "${tableName}"(${columns}) VALUES (${values})`) : `INSERT INTO "${tableName}" DEFAULT VALUES`;
const parameters = keys.map(key => keyValues[key]);
return new Promise<InsertResult>(async (ok, fail) => {
this.driver.connection.logger.logQuery(sql, parameters, this);
const __this = this;
const databaseConnection = await this.connect();
databaseConnection.run(sql, parameters, function (err: any): void {
if (err) {
__this.driver.connection.logger.logQueryError(err, sql, parameters, this);
fail(err);
} else {
const generatedMap = generatedColumns.reduce((map, generatedColumn) => {
const value = generatedColumn.isPrimary && generatedColumn.generationStrategy === "increment" && this["lastID"] ? this["lastID"] : keyValues[generatedColumn.databaseName];
if (!value) return map;
return OrmUtils.mergeDeep(map, generatedColumn.createValueMap(value));
}, {} as ObjectLiteral);
ok({
result: undefined,
generatedMap: Object.keys(generatedMap).length > 0 ? generatedMap : undefined
});
}
});
});
}
// -------------------------------------------------------------------------
// Protected Methods
// -------------------------------------------------------------------------
/**
* Parametrizes given object of values. Used to create column=value queries.
*/
protected parametrize(objectLiteral: ObjectLiteral, startIndex: number = 0): string[] {
return Object.keys(objectLiteral).map((key, index) => `"${key}"` + "=$" + (startIndex + index + 1));
}
}