-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtypedefs.js
488 lines (458 loc) · 31.7 KB
/
typedefs.js
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
'use strict';
const Stream = require('stream');
const exported = Object.freeze({
/**
* Module key used for the object namespace on errors and logging
*/
MOD_KEY: 'sqler',
/**
* Namespace on a `Manager` where SQL functions will be added
*/
NS: 'db',
/**
* Valid CRUD operation names
*/
CRUD_TYPES: Object.freeze(['CREATE', 'READ', 'UPDATE', 'DELETE']),
/**
* `RegExp` for capturing named bind parameter names within SQL
*/
POS_BINDS_REGEXP: /(?<!:):(\w+)(?=([^'\\]*(\\.|'([^'\\]*\\.)*[^'\\]*'))*[^']*$)/g,
/**
* `RegExp` for removing invalid chars from prepared function directory names
*/
FUNC_NAME_DIR_REGEXP: /[^0-9a-zA-Z]/g,
/**
* `RegExp` for removing invalid chars from prepared function file names
*/
FUNC_NAME_FILE_REGEXP: /[^0-9a-zA-Z\.]/g,
/**
* Separator for prepared function names (also used as the dir/filename replacement)
*/
FUNC_NAME_SEPARATOR: '_',
/**
* Event name that is emitted when a stream has prepared a statement.
* Listeners will receive a single argument that contains the {@link SQLERExecResults}.
*/
EVENT_STREAM_STATEMENT_PREPARED: 'sqler_stream_statement_prepared',
/**
* Event name that is emitted when a stream has unprepared a statement.
* Listeners will receive a single argument that contains the {@link SQLERExecResults}.
*/
EVENT_STREAM_STATEMENT_UPREPARED: 'sqler_stream_statement_unprepared',
/**
* Event name that is emitted when a stream has finished execution for a series of reads or writes included in a batch.
* Listeners will receive a single `Object[]` argument that contains the _raw_ results returned by each of the dialect SQL read or write executions.
*/
EVENT_STREAM_BATCH: 'sqler_stream_batch',
/**
* Event name that is emitted when a stream has committed a transaction.
* Listeners will receive a single `String` argument that contains the transaction ID returned by each of the dialect SQL read or write executions.
*/
EVENT_STREAM_COMMIT: 'sqler_stream_commit',
/**
* Event name that is emitted when a stream has rolled back a transaction.
* Listeners will receive a single `String` argument that contains the transaction ID returned by each of the dialect SQL read or write executions.
*/
EVENT_STREAM_ROLLBACK: 'sqler_stream_rollback',
/**
* Event name that is emitted when a stream has released or closed the connection used by the read or write stream (__managed by individual dialect implementations__).
* Listeners will __not__ receive any arguments.
*/
EVENT_STREAM_RELEASE: 'sqler_stream_release'
});
module.exports = exported;
/**
* Global type definitions used by `sqler`
* @namespace typedefs
*/
/**
* The `cache` client responsible for regulating the frequency in which a SQL file is read by a {@link Manager}.
* @typedef {Object} SQLERCache
* @property {Function} start An `async function()` that starts caching. This could be a `noop` or could start any background processing and/or capture of cached keys (depending on the type of
* implementation).
* @property {Function} stop An `async function()` that stops caching. This could be a `noop` or could stop any background processing and/or capture of cached keys (depending on the type of
* implementation).
* @property {Function} get An `async function(key)` that gets a corresponding SQL statement from cache using the specified _key_ to uniquily identify the SQL source (typically generated by a {@link Manager}).
* The returned _object_ will contain the following values when present (otherwise, returns _null_):
* - `item` - The cached SQL statement
* - `stored` - The timestamp indicating the time when the SQL statement was stored in cache
* - `ttl` - The timestamp indicating the remaining time left before the SQL statement will be removed from cache
* @property {Function} set An `async function(key, sql, ttlOverride)` that sets a SQL statement in cache, overriding the _time-to-live__ (in milliseconds) that may have been set by a {@link Manager}.
* @property {Function} drop An `async function(key)` that removes the specified key from cache
* @example
* // cache options can be different depending on the needs of the implementing cache
* const cacheOpts = {
* "expiresIn": 60000
* };
* // simple interval cache for illustration purposes
* const bank = { store: {}, handles: {} };
* const cache = {
* start: async () => {
* let cached, calTtl;
* for (let key in bank.handles) {
* clearInterval(bank.handles[key]);
* cached = bank.store.hasOwnProperty(key) ? bank.store[key] : null;
* calTtl = !cached|| isNaN(cached.ttl) ? cacheOpts.expiresIn : cached.ttl;
* bank.handles[key] = setInterval(() => delete bank.store[key], calTtl);
* }
* },
* stop: async () => {
* for (let key in bank.handles) {
* clearInterval(bank.handles[key]);
* }
* },
* get: async key => {
* const cached = bank.store.hasOwnProperty(key) ? bank.store[key] : null;
* if (cached) cached.ttl = Date.now() - cached.stored;
* return Promise.resolve(cached ? JSON.parse(JSON.stringify(cached)) : cached);
* },
* set: async (key, val, ttl) => {
* if (bank.handles[key]) clearInterval(bank.handles[key]);
* const calTtl = !ttl || isNaN(ttl) ? cacheOpts.expiresIn : ttl;
* bank.store[key] = { item: val, stored: Date.now(), ttl: calTtl };
* bank.handles[key] = setInterval(sql => delete bank.store[key], calTtl);
* return Promise.resolve();
* },
* drop: async () => {
* if (bank.handles[key]) {
* clearInterval(bank.handles[key]);
* delete bank.handles[key];
* }
* if (bank.store[key]) delete bank.store[key];
* }
* };
*
* // manager configuration
* const conf = {
* // other required conf options here
* "db": {
* "connections": [
* {
* // other required connection conf options here
* }
* ]
* }
* };
*
* const mgr = new Manager(conf, cache);
* await mgr.init();
* // use the manager to execute SQL files that will
* // be refreshed/re-read every 60 seconds
* // can also set the cache after Manager.init()
* const setCacheResults = await mgr.setCache(cache);
* @memberof typedefs
*/
/**
* Private options for global {@link Manager} use
* @typedef {Object} SQLERPrivateOptions
* @property {String} [username] The username to connect to the database
* @property {String} [password] The password to connect to the database
* @property {String} [host] The host to connect to for the database
* @property {String} [port] The port to connect to for the database (when not included in the host)
* @property {String} [protocol] The protocol to use when connecting to the database
* @property {String} [privatePath] The private path set by an originating {@link Manager} constructor (when not already set) that may be used by an implementing {@link Dialect} for private data use
* (e.g. `TNS` files, etc.)
* @memberof typedefs
*/
/**
* Configuration options for {@link Manager} use
* @typedef {Object} SQLERConfigurationOptions
* @property {String} [mainPath] Root directory starting point to look for SQL files (defaults to `require.main` path or `process.cwd()`)
* @property {String} [privatePath] Current working directory where generated files will be located (if any, defaults to `process.cwd()`)
* @property {Boolean} [debug] Truthy to turn on debugging
* @property {SQLERUniversalOptions} univ The {@link SQLERUniversalOptions}
* @property {Object} db The _public_ facing database configuration
* @property {Object} db.dialects An object that contains {@link Dialect} implementation details where each property name matches a dialect name and the value contains either the module class or a string
* that points to a {@link Dialect} implementation for the given dialect (e.g. `{ dialects: { 'oracle': 'sqler-oracle' } }`). When using a directory path the dialect path will be prefixed with
* `process.cwd()` before loading.
* @property {SQLERConnectionOptions[]} db.connections The connections options that will be used.
* @memberof typedefs
*/
/**
* The universal configuration that, for security and sharing purposes, remains external to an application
* @typedef {Object} SQLERUniversalOptions
* @property {Object} db The database options that contain _private_ sensitive configuration. Each property should correspond to a {@link SQLERPrivateOptions} instance and the property name should
* be linked to a {@link SQLERConnectionOptions} `id` within `conf.db.connections`. Each {@link SQLERPrivateOptions} instance will be used to connect to the underlying database
* (e.g. `{ db: myConnId: { host: "someDbhost.example.com", username: "someUser", password: "somePass" } }`)
* @memberof typedefs
*/
/**
* Options for connections used by {@link Manager}
* @typedef {Object} SQLERConnectionOptions
* @property {String} id Identifies the connection within a {@link SQLERPrivateOptions}
* @property {String} dialect The database dialect (e.g. mysql, mssql, oracle, etc.)
* @property {String} name The name given to the database used as the property name on the {@link Manager} to access generated SQL functions (e.g. `name = 'example'` would result in a SQL function
* connection container `manager.db.example`). The _name_ will also be used as the _cwd_ relative directory used when no dir is defined
* @property {String} [dir=name] The alternative dir where `*.sql` files will be found relative to `mainPath` passed into a {@link Manager} constructor. The directory path will be used as the basis
* for generating SQL statements from discovered SQL files. Each will be made accessible in the manager by name followed by an object for each name separated by period(s)
* within the file name with the last entry as the executable {@link SQLERPreparedFunction}. For example, a connection named "conn1" and a SQL file named "user.team.details.sql" will be accessible within the manager
* as "mgr.db.conn1.user.team.details()". But when `dir` is set to "myDir" the SQL files will be loaded from the "myDir" directory (relative to `mainPath`) instead of the default directory that matches the connection
* name "conn1".
* @property {Float} [version] A version that can be used for version substitutions within an SQL statement
* @property {String} [service] The service name defined by the underlying database (may be required depending on the implementing {@link Dialect}
* @property {Object} [binds] The global object that contains bind variable values that will be included in all SQL calls made under the connection for parameter `binds` if not overridden
* by individual "binds" passed into the {@link SQLERPreparedFunction}
* @property {Object} [substitutes] Key/value pairs that define global/static substitutions that will be made in prepared statements by replacing occurances of keys with corresponding values
* @property {String} [host] The database host override for a value specified in {@link SQLERPrivateOptions}
* @property {String} [port] The database port override for a value specified in {@link SQLERPrivateOptions}
* @property {String} [protocol] The database protocol override for a value specified in {@link SQLERPrivateOptions}
* @property {(Function | Boolean)} [dateFormatter] A `function(date)` that will be used to format bound dates into string values for {@link SQLERPreparedFunction} calls. Set to a truthy value to
* perform `date.toISOString()`. __Gets overridden by the same option set on {@link SQLERExecOptions}__.
* @property {Object} [driverOptions] Options passed directly into the {@link Dialect} driver
* @property {(Boolean | String[])} [log] When _logging_ is turned on for a given {@link Manager}, the specified tags will prefix the log output. Explicity set to `false` to disable
* connection _log_ level logging even if it is turned on via the {@link Manager}.
* @property {(Boolean | String[])} [logError] When _logging_ is turned on for a given {@link Manager}, the specified tags will prefix the error log output. Explicity set to `false` to disable
* connection _error_ level logging even if it is turned on via the {@link Manager}.
* @property {Object} [pool] The connection pool options (__overrides any `driverOptions` that may pertain the pool__)
* @property {Number} [pool.max] The maximum number of connections in the pool. When `pool.min` and `pool.max` are the same, `pool.increment` should typically be set to _zero_.
* (__overrides any `driverOptions` that may pertain the pool max__)
* @property {Number} [pool.min] The minumum number of connections in the pool. When `pool.min` and `pool.max` are the same, `pool.increment` should typically be set to _zero_.
* (__overrides any `driverOptions` that may pertain the pool min__)
* @property {Number} [pool.idle] The maximum time, in milliseconds, that a connection can be idle before being released (__overrides any `driverOptions` that may pertain the pool idle__)
* @property {Number} [pool.increment] The number of connections that are opened whenever a connection request exceeds the number of currently open connections.
* When `pool.min` and `pool.max` are the same, `pool.increment` should typically be set to _zero_.
* (__overrides any `driverOptions` that may pertain the pool increment__)
* @property {Number} [pool.timeout] The number of milliseconds that a connection request should wait in the queue before the request is terminated
* (__overrides any `driverOptions` that may pertain the pool timeout__)
* @property {String} [pool.alias] __When supported__, the alias of this pool in the connection pool cache (__overrides any `driverOptions` that may pertain the pool alias__)
* @memberof typedefs
*/
/**
* Options that are passed to generated {@link SQLERPreparedFunction}.
* __NOTE: Either `transaction.commit` or `trnasaction.rollback` must be invoked when `autoCommit` is _falsy_ and a valid `transactionId` is supplied to ensue underlying connections are
* completed and closed.__
* @typedef {Object} SQLERExecOptions
* @property {String} [name] A name to assign to the execution.
* @property {String} [type] The type of CRUD operation that is being executed (i.e. `CREATE`, `READ`, `UPDATE`, `DELETE`). __Mandatory only when the
* generated/prepared SQL function was generated from a SQL file that was not prefixed with a valid CRUD type.__
* @property {Number} [stream] A value `stream >= 0`, indicates that the execution will be streamed (ideal for large reads/writes). The resulting `rows` will contain either a
* [`stream.Readable[]`](https://nodejs.org/api/stream.html#stream_class_stream_readable) or a [`stream.Writable[]`](https://nodejs.org/api/stream.html#stream_class_stream_writable)
* (depending upon the `type`) instead of the default `Object[]` rows. When supported by the dialect, streams will be __batched__ using the indicated stream count as the batch size (a value of `0` is the
* same as a value of `1`).
* @property {Object} [binds={}] The key/value pair of binding parameters that will be bound in the SQL statement.
* @property {Boolean} [autoCommit=true] Truthy to perform a commits the transaction at the end of the prepared function execution. __NOTE: When falsy the underlying connection will remain open
* until the returned {@link SQLERExecResults} `commit` or `rollback` is called.__ [See AutoCommit](https://en.wikipedia.org/wiki/Autocommit) for more details.
* @property {String} [transactionId] A transaction ID returned from a prior call to `const tx = await manager.db.myConnectionName.beginTransaction(); options.transactionId = tx.id` that will be used when
* executing the {@link SQLERPreparedFunction}. The generated `transactionId` helps to isolate executions to a single open connection in order to prevent inadvertently making changes on database
* connections used by other transactions that may also be in progress. The `transactionId` is ignored when there is no transaction in progress with the specified `transactionId`.
* @property {Boolean} [prepareStatement] Truthy to generate or use an existing prepared statement for the SQL being executed via the {@link SQLERPreparedFunction}.
* Prepared statements _may_ help optimize SQL that is executed many times across the same connection with similar or different bind values.
* __Care must be taken not to drain the connection pool since the connection remains open until the SQL executions have completed and `unprepare` has been called on the {@link SQLERExecResults}.__
* returned from the {@link SQLERPreparedFunction} call.
* @property {(Function | Boolean)} [dateFormatter] A `function(date)` that will be used to format bound dates into string values for {@link SQLERPreparedFunction} calls. Set to a truthy value to
* perform `date.toISOString()`. __Overrides the same option set on {@link SQLERConnectionOptions}__.
* @property {Number} numOfPreparedFuncs The total number of {@link SQLERPreparedFunction}(s) that reside within the manager
* @property {Object} [driverOptions] Options that may override the {@link SQLERConnectionOptions} for `driverOptions` that may be passed into the {@link Manager} constructor
* @memberof typedefs
*/
// TODO : @property {String} [locale] The [BCP 47 language tag](https://tools.ietf.org/html/bcp47) locale that will be used for formatting dates contained in the `opts` bind variable values (when present)
/**
* Internally generated metadata that is passed into {@link Dialect.exec} by a {@link Manager} for determining SQL sources.
* @typedef {Object} SQLERExecMeta
* @property {String} name The composed name given to a given SQL file
* @property {String} path The path to the SQL file
* @memberof typedefs
*/
/**
* Options for handling any errors that occur during execution.
* @typedef {Object} SQLERExecErrorOptions
* @property {Function} [handler] A `function(error)` that will handle any errors thrown. The errors should contain a `sqler` property containing
* @property {Boolean} [includeBindValues] Truthy to include the bind parameter values `error.sqler`.
* @property {Boolean} [returnErrors] Truthy to return any errors that may occur. Otherwise, throw any errors that may occur.
* @memberof typedefs
*/
/**
* Prepared functions are auto-generated `async` functions that execute an SQL statement from an SQL file source.
* @async
* @callback SQLERPreparedFunction
* @param {SQLERExecOptions} [opts] The SQL execution options
* @param {String[]} [frags] Consists of any fragment segment names present in the SQL being executed that will be included in the final SQL statement. Any fragments present
* in the SQL source will be excluded from the final SQL statement when there is no matching fragment name.
* @param {(SQLERExecErrorOptions | Boolean)} [errorOpts] Either the error handling options or a boolean flag indicating that any errors that occur during execution should be returned in
* the {@link SQLERExecResults} rather then being thrown.
* @returns {SQLERExecResults} The execution results
* @memberof typedefs
*/
/**
* Results returned from invoking a {@link SQLERPreparedFunction}.
* @typedef {Object} SQLERExecResults
* @property {(Object[] | Stream.Readable[] | Stream.Writable[])} [rows] The execution array of model objects representing each row or `undefined` when executing a non-read SQL statement.
* When streaming the resulting `rows` will contain either a [`stream.Readable[]`](https://nodejs.org/api/stream.html#stream_class_stream_readable) or a
* [`stream.Writable[]`](https://nodejs.org/api/stream.html#stream_class_stream_writable) instead of the default `Object[]` rows.
* @property {Function} [unprepare] A no-argument _async_ function that unprepares an outstanding prepared statement. Will not be available when the {@link SQLERPreparedFunction} is called
* when the specified `prepareStatement` is _falsy_ on the {@link SQLERExecOptions} passed into the {@link SQLERPreparedFunction}. When a prepared statement is used in conjunction with a
* {@link SQLERTransaction} `transactionId` on the {@link SQLERExecOptions}, `unprepare` will be implicitly called when `transaction.commit` or `transaction.rollback` are called (of course,
* `unprepare` can still be explicitly called as well).
* __NOTE: A call to `unprepare` must be invoked when a `prepareStatement` is _truthy_ to ensue underlying statements and/or connections are completed and closed.__
* @property {Error} [error] Any caught error that occurred when a {@link SQLERPreparedFunction} was invoked with the `errorOpts` flag set to a _truthy_ value.
* @property {Object} raw The raw results from the execution (driver-specific execution results).
* @memberof typedefs
*/
/**
* Function that commits an outstanding transaction.
* @callback SQLERTransactionCommit
* @param {Boolean} [isRelease] When truthy, releases the connection back to the connection pool after a _commit_ has been performed.
* It's essential that connections be released back into the connection pool to ensure that there are enough available connections for other independent executions that use the same pool.
* @async
* @memberof typedefs
*/
/**
* Function that rolls back an outstanding transaction.
* @callback SQLERTransactionRollback
* @param {Boolean} [isRelease] When truthy, releases the connection back to the connection pool after a _rollback_ has been performed.
* It's essential that connections be released back into the connection pool to ensure that there are enough available connections for other independent executions that use the same pool.
* @async
* @memberof typedefs
*/
/**
* Transaction that symbolizes a unit of work performed within a {@link Manager} connection.
* @typedef {Object} SQLERTransaction
* @property {String} id The unique identifier for the transaction.
* @property {SQLERTransactionCommit} commit Rolls back the outstanding transaction.
* @property {SQLERTransactionRollback} rollback Commits the outstanding transaction.
* @property {Object} state The state of the transaction
* @property {Number} state.committed True when the transaction has been committed.
* @property {Number} state.rolledback True when the transaction has been rolledback.
* @property {Number} state.pending The number of pending SQL statements executed within the scope of the given transaction that have not been committed or rolledback.
* @property {Boolean} state.isReleased Truthy when the transaction has been released.
* @memberof typedefs
*/
/**
* Options for a {@link SQLERTransaction} that can be passed into a `manager.connectionName.beginTransaction(transactionDriverOptions)` function.
* @typedef {Object} SQLERTransactionOptions
* @memberof typedefs
*/
/**
* Options for operational methods on a {@link Manager} (e.g. {@link Manager.init}, {@link Manager.state}, {@link Manager.close}, etc.).
* @typedef {Object} SQLEROperationOptions
* @property {Object} [connections] An object that contains connection names as properties. Each optionally containing an object with `errorOpts` and/or `executeInSeries`
* that will override any global options set directly on the {@link SQLEROperationOptions}. For example, `opts.connections.myConnection.executeInseries` would override
* `opts.executeInSeries` for the connection named `myConnection`, but would use `opts.executeInSeries` for any other connections that ae not overridden.
* @property {Boolean} [executeInSeries] Set to truthy to execute the operation in series, otherwise executes operation in parallel.
* @property {(SQLERExecErrorOptions | Boolean)} [errorOpts] Set to truthy to return any errors. Otherise throw any errors as they are encountered. options can also be set instead.
* @memberof typedefs
*/
/**
* Results returned from invoking an operational method on a {@link Manager} (e.g. {@link Manager.init}, {@link Manager.state}, {@link Manager.close}, etc.).
* @typedef {Object} SQLEROperationResults
* @property {Object} result An object that contains a property name that matches each connection that was processed (the property value is the number of operations processed per connection).
* @property {Error[]} errors Any errors that may have occurred on the operational methods. Should only be populated when {@link SQLEROperationOptions} are used with a truthy value set on
* `errorOpts`. Each will contain meta properties set by [Asynchro](https://ugate.github.io/asynchro).
* @memberof typedefs
*/
/**
* Options that are used during initialization
* @typedef {Object} SQLERInitOptions
* @property {Number} numOfPreparedFuncs The total number of {@link SQLERPreparedFunction}(s) registered on the {@link Dialect}
* @memberof typedefs
*/
/**
* The current state of the managed {@link Dialect}
* @typedef {Object} SQLERState
* @property {Number} pending The number of transactions that are pending `commit` or `roolback` plus any prepared statements that are pending
* `unprepare`.
* @property {Object} [connections] The connection state
* @property {Number} [connections.count] The number of connections
* @property {Number} [connections.inUse] The number of connections that are in use
* @memberof typedefs
*/
/**
* A validation for validating interpolation used by a {@link SQLERInterpolateFunction}
* @callback SQLERInterpolateValidationFunction
* @param {String[]} srcPropNames Property path(s) to the value being validated (e.g. `source.my.path = 123` would equate to
* a invocation to `validator(['my','path'], 123)`).
* @param {*} srcPropValue The value being validated for interpolation
* @returns {Boolean} Flag indicating whether or not to include the interpolated property/value
* @memberof typedefs
*/
/**
* Interpolates values from a _source_ object to a _destination_ object.
* When a value is a string surrounded by `${}`, it will be assumed to be a interpolated property that resides on _another_ property on the `source`
* or an interpolated property on the `interpolator`.
* For example `source.someProp = '${SOME_VALUE}'` will be interpreted as `dest.someProp = dest.SOME_VALUE` when the `interpolator` is omitted and
* `dest.someProp = interpolator.SOME_VALUE` when an `interpolator` is specified.
* __Typically only used by implementing {@link Dialect} constructors within a {@link SQLERTrack}.__
* @callback SQLERInterpolateFunction
* @param {Object} dest The destination where the sources will be set (also the interpolated source when `interpolator` is omitted).
* @param {Object} source The source of the values to interpolate (e.g. {@link SQLERConnectionOptions}, {@link SQLERExecOptions}, etc.).
* @param {Object} [interpolator=dest] An alternative source to use for extracting interpolated values from.
* @param {SQLERInterpolateValidationFunction} [validator] A validation function for each property/value being interpolated to determine
* if it will be interolated.
* @param {Boolean} [onlyInterpolated] Truthy to indicate that the only values that will be set from the `source`/`interpolator` will be values that
* have been interpolated. __NOTE: Truthy values will not prevent `source`/`interpolator` objects from getting set on `dest`, just non-interpoalted
* property values will be skipped__ (i.e. property values that do not contain `${}` interpolation designations).
* @returns {Object} The passed destination
* @memberof typedefs
*/
/**
* Converts a SQL statement that contains named bind parameters into a SQL statement that contains unnamed/positional bind parameters (using `?`).
* Each bound parameter is pushed to the array in the position that corresponds to the position within the SQL statement.
* @callback SQLERPositionalBindsFunction
* @param {String} sql The SQL statement that contains the bind parameters
* @param {Object} bindsObject An object that contains the bind parameters as property names/values
* @param {Array} bindsArray The array that will be populated with the bind parameters
* @param {(String | Function)} [placeholder=?] Either a string value that will be used for the postional placeholder or a `function(name, index)` that
* returns a value that will be used as the positional placeholder.
* @returns {String} The converted SQL statement
* @throws {Error} Thrown when a bound parameter is not within the orgiginating SQL statement
* @memberof typedefs
*/
/**
* Expands _bind_ variables that contain an array of values when they appear in the SQL statement. For example, an SQL statement with a section that contains
* `IN (:someParam)` and _binds_ of `{ someParam: [1,2,3] }` would become `IN (:someParam, :someParam1, :someParam2)` with _binds_ of `{ someParam: 1, someParam1: 2, SomeParam2: 3 }`
* @callback SQLERBindExpansionFunction
* @param {String} sql The SQL to defragement
* @param {Object} [binds] An object that contains the SQL parameterized `binds` that will be used for parameterized array composition
* @returns {String} The defragmented SQL
* @memberof typedefs
*/
/**
* Processes a read batch of streamed objects for a particular dialect implementation.
* @async
* @callback SQLERStreamReader
* @param {Object[]} batch The batch of streamed objects based upon a predefined `stream` batch size in {@link SQLERExecOptions}.
* @returns {*} A value that will be emitted on a readable stream.
* @memberof typedefs
*/
/**
* Writes a batch of streamed objects for a particular dialect implementation and returns the raw results.
* @async
* @callback SQLERStreamWritter
* @param {Object[]} batch The batch of streamed objects based upon a predefined `stream` batch size in {@link SQLERExecOptions}.
* @returns {*} The _raw_ batch execution results from the dialect execution and will be emitted on a writable stream.
* @memberof typedefs
*/
/**
* Function that internally handles the specified {@link SQLERExecOptions} `stream` batch size and emits a batch event when the batch size
* threshold has been reached on a specified [`stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable).
* @callback SQLERStreamReadableProcessor
* @param {SQLERExecOptions} opts The execution options
* @param {Stream.Readable} readStream The readable stream that will produce the SQL results
* @param {SQLERStreamReader} [reader] The function that will process the batch read
* @returns {Stream.Readable} The readable stream that was passed
* @memberof typedefs
*/
/**
* Function that will generate a {@link Stream.Writable} that internally handles the specified {@link SQLERExecOptions} `stream` batch size and emits
* a batch event when the batch size threshold has been reached.
* @callback SQLERStreamWritable
* @param {SQLERExecOptions} opts The execution options
* @param {SQLERStreamWritter} writter The function that will process the batch write
* @returns {Stream.Writable} The writable stream that will handle the `sqler` internals
* @memberof typedefs
*/
/**
* A tracking mechanism that is shared between all {@link Dialect} implementations for a given {@link Manager}. A track provides a means to share
* data, etc. from one {@link Dialect} to another. Properties can also be _added_ by a {@link Dialect} for use in other {@link Dialect}s.
* __Typically only used by implementing {@link Dialect} constructors.__
* @typedef {Object} SQLERTrack
* @property {SQLERInterpolateFunction} interpolate An interpolation function that can be used by {@link Dialect} implementations to interpolate
* configuration option values from underlying drivers within a {@link Dialect} (immutable). The convenience of doing so negates the need for an
* application that uses a {@link Manager} to import/require a database driver just to access driver constants, etc.
* @property {SQLERPositionalBindsFunction} positionalBinds A function that will convert an SQL statement with named binds into positional binds.
* @property {SQLERBindExpansionFunction} bindExpansions A function that takes an SQL statement with named binds and expands the bind variables
* into an array of values when they appear in the SQL statement
* @property {SQLERStreamReadableProcessor} readable A function that uses a specified readable stream for batching large number of read executions.
* @property {SQLERStreamWritable} writable A function that will generate a writable stream for batching large number of write executions.
* @memberof typedefs
*/