-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstatement.ts
More file actions
159 lines (145 loc) · 6.24 KB
/
Copy pathstatement.ts
File metadata and controls
159 lines (145 loc) · 6.24 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
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
/**
* statement.ts
*/
import { popCallback } from './utilities'
import { Database } from './database'
import { ErrorCallback, RowCallback, RowsCallback, RowCountCallback, ResultsCallback, SQLiteCloudCommand } from './types'
/**
* A statement generated by Database.prepare used to prepare SQL with ? bindings.
*
* SCSP protocol does not support named placeholders yet.
*/
export class Statement<T> {
constructor(database: Database, sql: string, ...params: any[]) {
this._database = database
this._sql = sql
this.bind(...params)
}
/** Statement belongs to this database */
private _database: Database
/** The SQL statement with ? binding placeholders */
private _sql: string
/** The SQL statement with binding values applied */
private _preparedSql: SQLiteCloudCommand = { query: '' }
/**
* Binds parameters to the prepared statement and calls the callback when done
* or when an error occurs. The function returns the Statement object to allow
* for function chaining. The first and only argument to the callback is null
* when binding was successful. Binding parameters with this function completely
* resets the statement object and row cursor and removes all previously bound
* parameters, if any.
*
* In SQLiteCloud the statement is prepared on the database server and binding errors
* are raised on execution time.
*/
public bind(...params: any[]): this {
const { args, callback } = popCallback<ErrorCallback>(params)
this._preparedSql = { query: this._sql, parameters: args }
if (callback) {
callback.call(this, null)
}
return this
}
/**
* Binds parameters and executes the statement. The function returns the Statement object to
* allow for function chaining. If you specify bind parameters, they will be bound to the statement
* before it is executed. Note that the bindings and the row cursor are reset when you specify
* even a single bind parameter. The callback behavior is identical to the Database#run method
* with the difference that the statement will not be finalized after it is run. This means you
* can run it multiple times.
*/
public run(callback?: ResultsCallback<T>): this
public run(params: any, callback?: ResultsCallback<T>): this
public run(...params: any[]): this {
const { args, callback } = popCallback<ResultsCallback>(params || [])
if (args?.length > 0) {
// apply new bindings then execute
this.bind(...args, () => {
const query = this._preparedSql.query || ''
const parametes: any = [...(this._preparedSql.parameters ?? [])]
this._database.run(query, ...parametes, callback)
})
} else {
// execute prepared sql with same bindings
const query = this._preparedSql.query || ''
const parametes: any = [...(this._preparedSql.parameters ?? [])]
this._database.run(query, ...parametes, callback)
}
return this
}
/**
* Binds parameters, executes the statement and retrieves the first result row.
* The function returns the Statement object to allow for function chaining.
* The parameters are the same as the Statement#run function, with the following differences:
* The signature of the callback is function(err, row) {}. If the result set is empty,
* the second parameter is undefined, otherwise it is an object containing the values
* for the first row.
*/
public get(callback?: RowCallback<T>): this
public get(params: any, callback?: RowCallback<T>): this
public get(...params: any[]): this {
const { args, callback } = popCallback<RowCallback>(params || [])
if (args?.length > 0) {
// apply new bindings then execute
this.bind(...args, () => {
const query = this._preparedSql.query || ''
const parametes: any = [...(this._preparedSql.parameters ?? [])]
this._database.get(query, ...parametes, callback)
})
} else {
// execute prepared sql with same bindings
const query = this._preparedSql.query || ''
const parametes: any = [...(this._preparedSql.parameters ?? [])]
this._database.get(query, ...parametes, callback)
}
return this
}
/**
* Binds parameters, executes the statement and calls the callback with
* all result rows. The function returns the Statement object to allow
* for function chaining. The parameters are the same as the Statement#run function
*/
public all(callback?: RowsCallback<T>): this
public all(params: any, callback?: RowsCallback<T>): this
public all(...params: any[]): this {
const { args, callback } = popCallback<RowsCallback>(params || [])
if (args?.length > 0) {
// apply new bindings then execute
this.bind(...args, () => {
const query = this._preparedSql.query || ''
const parametes: any = [...(this._preparedSql.parameters ?? [])]
this._database.all(query, ...parametes, callback)
})
} else {
// execute prepared sql with same bindings
const query = this._preparedSql.query || ''
const parametes: any = [...(this._preparedSql.parameters ?? [])]
this._database.all(query, ...parametes, callback)
}
return this
}
/**
* Binds parameters, executes the statement and calls the callback for each result row.
* The function returns the Statement object to allow for function chaining. Parameters
* are the same as the Database#each function.
*/
public each(callback?: RowCallback<T>, complete?: RowCountCallback): this
public each(params: any, callback?: RowCallback<T>, complete?: RowCountCallback): this
public each(...params: any[]): this {
const { args, callback, complete } = popCallback<RowCallback<T>>(params)
if (args?.length > 0) {
// apply new bindings then execute
this.bind(...args, () => {
const query = this._preparedSql.query || ''
const parametes: any = [...(this._preparedSql.parameters ?? []), ...[callback, complete as RowCountCallback]]
this._database.each(query, ...parametes)
})
} else {
// execute prepared sql with same bindings
const query = this._preparedSql.query || ''
const parametes: any = [...(this._preparedSql.parameters ?? []), ...[callback, complete as RowCountCallback]]
this._database.each(query, ...parametes)
}
return this
}
}