kern-orm 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{driver-error-Dx5R83Rp.mjs → database-t66EaIGE.mjs} +359 -177
- package/dist/{index-B1aH5Ht0.d.mts → index-2z5iTzXf.d.mts} +356 -23
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +273 -2
- package/dist/testing.d.mts +2 -2
- package/dist/testing.mjs +85 -58
- package/dist/types.d.mts +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { B as noOrder, C as toNode, D as isType, E as defineType, F as createNode, L as falseNode, N as defineGenericOperator, P as createList, S as toFunctionOperandNode, T as getBooleanType, U as trueNode, _ as isOperandSource, b as toCastValueNode, c as textOperators, d as orderingOperators, f as compare, g as isExpression, h as getType, k as equalityOperators, v as operandNode, x as toExpression, y as toBooleanExpression } from "./text-CIUxPWPl.mjs";
|
|
2
|
-
import { A as
|
|
2
|
+
import { A as toAggregateType, C as NotFoundError, D as countType, E as countProjection, F as or, I as combineNodes, M as and, N as isColumnValues, O as createAggregateCall, P as not, S as defineTable, T as ResultDecodeError, _ as matchColumn, a as toDriverError, b as createStatement, c as sql, d as from, f as requireDerived, g as orderBy, h as desc, i as QueryError, j as literal, k as createCountCall, l as defineSchema, m as asc, n as TransactionConnectionError, o as identifier, p as addTerms, r as ConnectionError, s as param, t as createDatabase, u as SelectQuery, v as many, w as RequiredRelationError, x as createTableFactory, y as one } from "./database-t66EaIGE.mjs";
|
|
3
3
|
// src/expression/constants.ts
|
|
4
4
|
/** Condition that always holds, such as for a branch of `and` built in code: `and(check, isAdmin ? TRUE : other)`. */
|
|
5
5
|
const TRUE = /* @__PURE__ */ toExpression(trueNode, /* @__PURE__ */ getBooleanType());
|
|
@@ -127,6 +127,277 @@ function readFilter(options, method) {
|
|
|
127
127
|
if (!isOperandSource(filter)) throw new TypeError(`The filter of ${method} must be an expression or a query of one Boolean value`);
|
|
128
128
|
return filter[operandNode]();
|
|
129
129
|
}
|
|
130
|
+
// src/execution/error-condition-codes.ts
|
|
131
|
+
/**
|
|
132
|
+
* Condition names of the SQLSTATE codes of PostgreSQL errors, by code: the codes of type `E` with a condition name, which PL/pgSQL takes in `EXCEPTION WHEN`, under the headings of their classes.
|
|
133
|
+
*
|
|
134
|
+
* A code that ends in `000` is the condition of its class.
|
|
135
|
+
* A few names have two codes, such as `null_value_not_allowed`.
|
|
136
|
+
*/
|
|
137
|
+
const conditionsByCode = {
|
|
138
|
+
"03000": "sql_statement_not_yet_complete",
|
|
139
|
+
"08000": "connection_exception",
|
|
140
|
+
"08003": "connection_does_not_exist",
|
|
141
|
+
"08006": "connection_failure",
|
|
142
|
+
"08001": "sqlclient_unable_to_establish_sqlconnection",
|
|
143
|
+
"08004": "sqlserver_rejected_establishment_of_sqlconnection",
|
|
144
|
+
"08007": "transaction_resolution_unknown",
|
|
145
|
+
"08P01": "protocol_violation",
|
|
146
|
+
"09000": "triggered_action_exception",
|
|
147
|
+
"0A000": "feature_not_supported",
|
|
148
|
+
"0B000": "invalid_transaction_initiation",
|
|
149
|
+
"0F000": "locator_exception",
|
|
150
|
+
"0F001": "invalid_locator_specification",
|
|
151
|
+
"0L000": "invalid_grantor",
|
|
152
|
+
"0LP01": "invalid_grant_operation",
|
|
153
|
+
"0P000": "invalid_role_specification",
|
|
154
|
+
"0Z000": "diagnostics_exception",
|
|
155
|
+
"0Z002": "stacked_diagnostics_accessed_without_active_handler",
|
|
156
|
+
"10608": "invalid_argument_for_xquery",
|
|
157
|
+
"20000": "case_not_found",
|
|
158
|
+
"21000": "cardinality_violation",
|
|
159
|
+
"22000": "data_exception",
|
|
160
|
+
"2202E": "array_subscript_error",
|
|
161
|
+
"22021": "character_not_in_repertoire",
|
|
162
|
+
"22008": "datetime_field_overflow",
|
|
163
|
+
"22012": "division_by_zero",
|
|
164
|
+
"22005": "error_in_assignment",
|
|
165
|
+
"2200B": "escape_character_conflict",
|
|
166
|
+
"22022": "indicator_overflow",
|
|
167
|
+
"22015": "interval_field_overflow",
|
|
168
|
+
"2201E": "invalid_argument_for_logarithm",
|
|
169
|
+
"22014": "invalid_argument_for_ntile_function",
|
|
170
|
+
"22016": "invalid_argument_for_nth_value_function",
|
|
171
|
+
"2201F": "invalid_argument_for_power_function",
|
|
172
|
+
"2201G": "invalid_argument_for_width_bucket_function",
|
|
173
|
+
"22018": "invalid_character_value_for_cast",
|
|
174
|
+
"22007": "invalid_datetime_format",
|
|
175
|
+
"22019": "invalid_escape_character",
|
|
176
|
+
"2200D": "invalid_escape_octet",
|
|
177
|
+
"22025": "invalid_escape_sequence",
|
|
178
|
+
"22P06": "nonstandard_use_of_escape_character",
|
|
179
|
+
"22010": "invalid_indicator_parameter_value",
|
|
180
|
+
"22023": "invalid_parameter_value",
|
|
181
|
+
"22013": "invalid_preceding_or_following_size",
|
|
182
|
+
"2201B": "invalid_regular_expression",
|
|
183
|
+
"2201W": "invalid_row_count_in_limit_clause",
|
|
184
|
+
"2201X": "invalid_row_count_in_result_offset_clause",
|
|
185
|
+
"2202H": "invalid_tablesample_argument",
|
|
186
|
+
"2202G": "invalid_tablesample_repeat",
|
|
187
|
+
"22009": "invalid_time_zone_displacement_value",
|
|
188
|
+
"2200C": "invalid_use_of_escape_character",
|
|
189
|
+
"2200G": "most_specific_type_mismatch",
|
|
190
|
+
"22004": "null_value_not_allowed",
|
|
191
|
+
"22002": "null_value_no_indicator_parameter",
|
|
192
|
+
"22003": "numeric_value_out_of_range",
|
|
193
|
+
"2200H": "sequence_generator_limit_exceeded",
|
|
194
|
+
"22026": "string_data_length_mismatch",
|
|
195
|
+
"22001": "string_data_right_truncation",
|
|
196
|
+
"22011": "substring_error",
|
|
197
|
+
"22027": "trim_error",
|
|
198
|
+
"22024": "unterminated_c_string",
|
|
199
|
+
"2200F": "zero_length_character_string",
|
|
200
|
+
"22P01": "floating_point_exception",
|
|
201
|
+
"22P02": "invalid_text_representation",
|
|
202
|
+
"22P03": "invalid_binary_representation",
|
|
203
|
+
"22P04": "bad_copy_file_format",
|
|
204
|
+
"22P05": "untranslatable_character",
|
|
205
|
+
"2200L": "not_an_xml_document",
|
|
206
|
+
"2200M": "invalid_xml_document",
|
|
207
|
+
"2200N": "invalid_xml_content",
|
|
208
|
+
"2200S": "invalid_xml_comment",
|
|
209
|
+
"2200T": "invalid_xml_processing_instruction",
|
|
210
|
+
"22030": "duplicate_json_object_key_value",
|
|
211
|
+
"22031": "invalid_argument_for_sql_json_datetime_function",
|
|
212
|
+
"22032": "invalid_json_text",
|
|
213
|
+
"22033": "invalid_sql_json_subscript",
|
|
214
|
+
"22034": "more_than_one_sql_json_item",
|
|
215
|
+
"22035": "no_sql_json_item",
|
|
216
|
+
"22036": "non_numeric_sql_json_item",
|
|
217
|
+
"22037": "non_unique_keys_in_a_json_object",
|
|
218
|
+
"22038": "singleton_sql_json_item_required",
|
|
219
|
+
"22039": "sql_json_array_not_found",
|
|
220
|
+
"2203A": "sql_json_member_not_found",
|
|
221
|
+
"2203B": "sql_json_number_not_found",
|
|
222
|
+
"2203C": "sql_json_object_not_found",
|
|
223
|
+
"2203D": "too_many_json_array_elements",
|
|
224
|
+
"2203E": "too_many_json_object_members",
|
|
225
|
+
"2203F": "sql_json_scalar_required",
|
|
226
|
+
"2203G": "sql_json_item_cannot_be_cast_to_target_type",
|
|
227
|
+
"23000": "integrity_constraint_violation",
|
|
228
|
+
"23001": "restrict_violation",
|
|
229
|
+
"23502": "not_null_violation",
|
|
230
|
+
"23503": "foreign_key_violation",
|
|
231
|
+
"23505": "unique_violation",
|
|
232
|
+
"23514": "check_violation",
|
|
233
|
+
"23P01": "exclusion_violation",
|
|
234
|
+
"24000": "invalid_cursor_state",
|
|
235
|
+
"25000": "invalid_transaction_state",
|
|
236
|
+
"25001": "active_sql_transaction",
|
|
237
|
+
"25002": "branch_transaction_already_active",
|
|
238
|
+
"25008": "held_cursor_requires_same_isolation_level",
|
|
239
|
+
"25003": "inappropriate_access_mode_for_branch_transaction",
|
|
240
|
+
"25004": "inappropriate_isolation_level_for_branch_transaction",
|
|
241
|
+
"25005": "no_active_sql_transaction_for_branch_transaction",
|
|
242
|
+
"25006": "read_only_sql_transaction",
|
|
243
|
+
"25007": "schema_and_data_statement_mixing_not_supported",
|
|
244
|
+
"25P01": "no_active_sql_transaction",
|
|
245
|
+
"25P02": "in_failed_sql_transaction",
|
|
246
|
+
"25P03": "idle_in_transaction_session_timeout",
|
|
247
|
+
"25P04": "transaction_timeout",
|
|
248
|
+
"26000": "invalid_sql_statement_name",
|
|
249
|
+
"27000": "triggered_data_change_violation",
|
|
250
|
+
"28000": "invalid_authorization_specification",
|
|
251
|
+
"28P01": "invalid_password",
|
|
252
|
+
"2B000": "dependent_privilege_descriptors_still_exist",
|
|
253
|
+
"2BP01": "dependent_objects_still_exist",
|
|
254
|
+
"2D000": "invalid_transaction_termination",
|
|
255
|
+
"2F000": "sql_routine_exception",
|
|
256
|
+
"2F005": "function_executed_no_return_statement",
|
|
257
|
+
"2F002": "modifying_sql_data_not_permitted",
|
|
258
|
+
"2F003": "prohibited_sql_statement_attempted",
|
|
259
|
+
"2F004": "reading_sql_data_not_permitted",
|
|
260
|
+
"34000": "invalid_cursor_name",
|
|
261
|
+
"38000": "external_routine_exception",
|
|
262
|
+
"38001": "containing_sql_not_permitted",
|
|
263
|
+
"38002": "modifying_sql_data_not_permitted",
|
|
264
|
+
"38003": "prohibited_sql_statement_attempted",
|
|
265
|
+
"38004": "reading_sql_data_not_permitted",
|
|
266
|
+
"39000": "external_routine_invocation_exception",
|
|
267
|
+
"39001": "invalid_sqlstate_returned",
|
|
268
|
+
"39004": "null_value_not_allowed",
|
|
269
|
+
"39P01": "trigger_protocol_violated",
|
|
270
|
+
"39P02": "srf_protocol_violated",
|
|
271
|
+
"39P03": "event_trigger_protocol_violated",
|
|
272
|
+
"3B000": "savepoint_exception",
|
|
273
|
+
"3B001": "invalid_savepoint_specification",
|
|
274
|
+
"3D000": "invalid_catalog_name",
|
|
275
|
+
"3F000": "invalid_schema_name",
|
|
276
|
+
"40000": "transaction_rollback",
|
|
277
|
+
"40002": "transaction_integrity_constraint_violation",
|
|
278
|
+
"40001": "serialization_failure",
|
|
279
|
+
"40003": "statement_completion_unknown",
|
|
280
|
+
"40P01": "deadlock_detected",
|
|
281
|
+
"42000": "syntax_error_or_access_rule_violation",
|
|
282
|
+
"42601": "syntax_error",
|
|
283
|
+
"42501": "insufficient_privilege",
|
|
284
|
+
"42846": "cannot_coerce",
|
|
285
|
+
"42803": "grouping_error",
|
|
286
|
+
"42P20": "windowing_error",
|
|
287
|
+
"42P19": "invalid_recursion",
|
|
288
|
+
"42830": "invalid_foreign_key",
|
|
289
|
+
"42602": "invalid_name",
|
|
290
|
+
"42622": "name_too_long",
|
|
291
|
+
"42939": "reserved_name",
|
|
292
|
+
"42804": "datatype_mismatch",
|
|
293
|
+
"42P18": "indeterminate_datatype",
|
|
294
|
+
"42P21": "collation_mismatch",
|
|
295
|
+
"42P22": "indeterminate_collation",
|
|
296
|
+
"42809": "wrong_object_type",
|
|
297
|
+
"428C9": "generated_always",
|
|
298
|
+
"42703": "undefined_column",
|
|
299
|
+
"42883": "undefined_function",
|
|
300
|
+
"42P01": "undefined_table",
|
|
301
|
+
"42P02": "undefined_parameter",
|
|
302
|
+
"42704": "undefined_object",
|
|
303
|
+
"42701": "duplicate_column",
|
|
304
|
+
"42P03": "duplicate_cursor",
|
|
305
|
+
"42P04": "duplicate_database",
|
|
306
|
+
"42723": "duplicate_function",
|
|
307
|
+
"42P05": "duplicate_prepared_statement",
|
|
308
|
+
"42P06": "duplicate_schema",
|
|
309
|
+
"42P07": "duplicate_table",
|
|
310
|
+
"42712": "duplicate_alias",
|
|
311
|
+
"42710": "duplicate_object",
|
|
312
|
+
"42702": "ambiguous_column",
|
|
313
|
+
"42725": "ambiguous_function",
|
|
314
|
+
"42P08": "ambiguous_parameter",
|
|
315
|
+
"42P09": "ambiguous_alias",
|
|
316
|
+
"42P10": "invalid_column_reference",
|
|
317
|
+
"42611": "invalid_column_definition",
|
|
318
|
+
"42P11": "invalid_cursor_definition",
|
|
319
|
+
"42P12": "invalid_database_definition",
|
|
320
|
+
"42P13": "invalid_function_definition",
|
|
321
|
+
"42P14": "invalid_prepared_statement_definition",
|
|
322
|
+
"42P15": "invalid_schema_definition",
|
|
323
|
+
"42P16": "invalid_table_definition",
|
|
324
|
+
"42P17": "invalid_object_definition",
|
|
325
|
+
"44000": "with_check_option_violation",
|
|
326
|
+
"53000": "insufficient_resources",
|
|
327
|
+
"53100": "disk_full",
|
|
328
|
+
"53200": "out_of_memory",
|
|
329
|
+
"53300": "too_many_connections",
|
|
330
|
+
"53400": "configuration_limit_exceeded",
|
|
331
|
+
"54000": "program_limit_exceeded",
|
|
332
|
+
"54001": "statement_too_complex",
|
|
333
|
+
"54011": "too_many_columns",
|
|
334
|
+
"54023": "too_many_arguments",
|
|
335
|
+
"55000": "object_not_in_prerequisite_state",
|
|
336
|
+
"55006": "object_in_use",
|
|
337
|
+
"55P02": "cant_change_runtime_param",
|
|
338
|
+
"55P03": "lock_not_available",
|
|
339
|
+
"55P04": "unsafe_new_enum_value_usage",
|
|
340
|
+
"57000": "operator_intervention",
|
|
341
|
+
"57014": "query_canceled",
|
|
342
|
+
"57P01": "admin_shutdown",
|
|
343
|
+
"57P02": "crash_shutdown",
|
|
344
|
+
"57P03": "cannot_connect_now",
|
|
345
|
+
"57P04": "database_dropped",
|
|
346
|
+
"57P05": "idle_session_timeout",
|
|
347
|
+
"58000": "system_error",
|
|
348
|
+
"58030": "io_error",
|
|
349
|
+
"58P01": "undefined_file",
|
|
350
|
+
"58P02": "duplicate_file",
|
|
351
|
+
"58P03": "file_name_too_long",
|
|
352
|
+
F0000: "config_file_error",
|
|
353
|
+
F0001: "lock_file_exists",
|
|
354
|
+
HV000: "fdw_error",
|
|
355
|
+
HV005: "fdw_column_name_not_found",
|
|
356
|
+
HV002: "fdw_dynamic_parameter_value_needed",
|
|
357
|
+
HV010: "fdw_function_sequence_error",
|
|
358
|
+
HV021: "fdw_inconsistent_descriptor_information",
|
|
359
|
+
HV024: "fdw_invalid_attribute_value",
|
|
360
|
+
HV007: "fdw_invalid_column_name",
|
|
361
|
+
HV008: "fdw_invalid_column_number",
|
|
362
|
+
HV004: "fdw_invalid_data_type",
|
|
363
|
+
HV006: "fdw_invalid_data_type_descriptors",
|
|
364
|
+
HV091: "fdw_invalid_descriptor_field_identifier",
|
|
365
|
+
HV00B: "fdw_invalid_handle",
|
|
366
|
+
HV00C: "fdw_invalid_option_index",
|
|
367
|
+
HV00D: "fdw_invalid_option_name",
|
|
368
|
+
HV090: "fdw_invalid_string_length_or_buffer_length",
|
|
369
|
+
HV00A: "fdw_invalid_string_format",
|
|
370
|
+
HV009: "fdw_invalid_use_of_null_pointer",
|
|
371
|
+
HV014: "fdw_too_many_handles",
|
|
372
|
+
HV001: "fdw_out_of_memory",
|
|
373
|
+
HV00P: "fdw_no_schemas",
|
|
374
|
+
HV00J: "fdw_option_name_not_found",
|
|
375
|
+
HV00K: "fdw_reply_handle",
|
|
376
|
+
HV00Q: "fdw_schema_not_found",
|
|
377
|
+
HV00R: "fdw_table_not_found",
|
|
378
|
+
HV00L: "fdw_unable_to_create_execution",
|
|
379
|
+
HV00M: "fdw_unable_to_create_reply",
|
|
380
|
+
HV00N: "fdw_unable_to_establish_connection",
|
|
381
|
+
P0000: "plpgsql_error",
|
|
382
|
+
P0001: "raise_exception",
|
|
383
|
+
P0002: "no_data_found",
|
|
384
|
+
P0003: "too_many_rows",
|
|
385
|
+
P0004: "assert_failure",
|
|
386
|
+
XX000: "internal_error",
|
|
387
|
+
XX001: "data_corrupted",
|
|
388
|
+
XX002: "index_corrupted"
|
|
389
|
+
};
|
|
390
|
+
// src/execution/error-condition.ts
|
|
391
|
+
/**
|
|
392
|
+
* Tells whether `error` is a `QueryError` of `condition`, including a `QueryError` of another copy of kern-orm.
|
|
393
|
+
*
|
|
394
|
+
* The condition of a class, such as `integrity_constraint_violation`, matches every error of its class, as in PL/pgSQL.
|
|
395
|
+
*/
|
|
396
|
+
function isQueryError(error, condition) {
|
|
397
|
+
if (!(error instanceof QueryError)) return false;
|
|
398
|
+
const conditions = conditionsByCode;
|
|
399
|
+
return conditions[error.code] === condition || conditions[`${error.code.slice(0, 2)}000`] === condition;
|
|
400
|
+
}
|
|
130
401
|
// src/query/reusable-expression.ts
|
|
131
402
|
function defineExpression(_table, expression) {
|
|
132
403
|
return expression;
|
|
@@ -157,4 +428,4 @@ const wordStart = /(?<=[\p{Ll}\p{N}])(?=\p{Lu})|(?<=\p{Lu})(?=\p{Lu}(?!s$)\p{Ll}
|
|
|
157
428
|
function toSnakeCase(key) {
|
|
158
429
|
return key.replace(wordStart, "_").toLowerCase();
|
|
159
430
|
}
|
|
160
|
-
export { ConnectionError, FALSE, NotFoundError, QueryError, RequiredRelationError, ResultDecodeError, TRUE, and, asc, avg, caseWhen, coalesce, compare, count, countDistinct, createDatabase, createStatement, createTableFactory, defineExpression, defineGenericOperator, defineHelper, defineSchema, defineTable, defineType, desc, equalityOperators, every, from, greatest, identifier, least, literal, many, matches, max, min, not, one, or, orderBy, orderingOperators, param, some, sql, stringAgg, sum, textOperators, toDriverError, toSnakeCase };
|
|
431
|
+
export { ConnectionError, FALSE, NotFoundError, QueryError, RequiredRelationError, ResultDecodeError, TRUE, TransactionConnectionError, and, asc, avg, caseWhen, coalesce, compare, count, countDistinct, createDatabase, createStatement, createTableFactory, defineExpression, defineGenericOperator, defineHelper, defineSchema, defineTable, defineType, desc, equalityOperators, every, from, greatest, identifier, isQueryError, least, literal, many, matches, max, min, not, one, or, orderBy, orderingOperators, param, some, sql, stringAgg, sum, textOperators, toDriverError, toSnakeCase };
|
package/dist/testing.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $ as TestHooks, J as OpenedTestFixture, Q as TestHelpers, Ui as Driver, X as TestFixture, Y as PendingTestFixture, Z as TestFixtureOptions, et as TestTransactionOptions, tt as createTestHelpers } from "./index-2z5iTzXf.mjs";
|
|
2
2
|
/** Options of `describeDriverContract`: how to create the driver under test. */
|
|
3
3
|
interface DriverContractOptions {
|
|
4
4
|
/** Creates a driver over a new client of the test database with `max` connections. */
|
|
@@ -23,4 +23,4 @@ interface DriverContractRunner extends TestHooks {
|
|
|
23
23
|
* They run in the empty database of its clients and leave it unchanged.
|
|
24
24
|
*/
|
|
25
25
|
export declare function describeDriverContract(options: DriverContractOptions, runner: DriverContractRunner): void;
|
|
26
|
-
export { type DriverContractOptions, type DriverContractRunner, type OpenedTestFixture, type PendingTestFixture, type TestFixture, type TestHelpers, type TestHooks, type TestTransactionOptions, createTestHelpers };
|
|
26
|
+
export { type DriverContractOptions, type DriverContractRunner, type OpenedTestFixture, type PendingTestFixture, type TestFixture, type TestFixtureOptions, type TestHelpers, type TestHooks, type TestTransactionOptions, createTestHelpers };
|
package/dist/testing.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as text, t as char } from "./text-CIUxPWPl.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { M as and, S as defineTable, b as createStatement, c as sql, i as QueryError, l as defineSchema, n as TransactionConnectionError, r as ConnectionError, s as param, t as createDatabase } from "./database-t66EaIGE.mjs";
|
|
3
3
|
import { _ as timestamptz, a as numeric, b as array, d as jsonb, f as enumOf, g as timestamp, h as time, i as integer, l as inet, m as interval, n as bigint, p as date, r as doublePrecision, t as uuid, v as boolean, y as bytea } from "./types-D3d35qR2.mjs";
|
|
4
4
|
import assert from "node:assert/strict";
|
|
5
5
|
// src/execution/testing.ts
|
|
@@ -9,11 +9,11 @@ function createTestHelpers(database, hooks) {
|
|
|
9
9
|
if (!coordinator.test) throw new Error("createTestHelpers requires a database created with test: true");
|
|
10
10
|
return {
|
|
11
11
|
testTransaction: (callback, options) => coordinator.testTransaction(callback, options),
|
|
12
|
-
useTestFixture(seed) {
|
|
12
|
+
useTestFixture(seed, options) {
|
|
13
13
|
let pending;
|
|
14
14
|
let fixture;
|
|
15
15
|
hooks.before(async () => {
|
|
16
|
-
const current = coordinator.startTestFixture(seed);
|
|
16
|
+
const current = coordinator.startTestFixture(seed, options);
|
|
17
17
|
pending = current;
|
|
18
18
|
try {
|
|
19
19
|
const opened = await current.fixture;
|
|
@@ -193,7 +193,6 @@ function describeDriverContract(options, runner) {
|
|
|
193
193
|
try {
|
|
194
194
|
const connection = await own.acquire();
|
|
195
195
|
const { runStatement, selectValue } = createStatementRunners(connection);
|
|
196
|
-
let failure;
|
|
197
196
|
try {
|
|
198
197
|
await runStatement("CREATE TEMP TABLE pg_order_test (id integer)");
|
|
199
198
|
await runStatement("BEGIN");
|
|
@@ -204,11 +203,8 @@ function describeDriverContract(options, runner) {
|
|
|
204
203
|
runStatement("ROLLBACK")
|
|
205
204
|
]);
|
|
206
205
|
assert.equal(await selectValue("SELECT count(*) FROM pg_order_test"), "0");
|
|
207
|
-
} catch (error) {
|
|
208
|
-
failure = { error };
|
|
209
|
-
throw error;
|
|
210
206
|
} finally {
|
|
211
|
-
await connection.release(
|
|
207
|
+
await connection.release();
|
|
212
208
|
}
|
|
213
209
|
} finally {
|
|
214
210
|
await own.close();
|
|
@@ -292,72 +288,103 @@ function describeDriverContract(options, runner) {
|
|
|
292
288
|
await single.close();
|
|
293
289
|
}
|
|
294
290
|
});
|
|
295
|
-
it("
|
|
296
|
-
const
|
|
291
|
+
it("returns a connection to the pool after PostgreSQL rejected its last statement outside a transaction", async () => {
|
|
292
|
+
const own = createDriver({ max: 1 });
|
|
297
293
|
try {
|
|
298
|
-
const connection = await
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
294
|
+
const connection = await own.acquire();
|
|
295
|
+
let pid;
|
|
296
|
+
try {
|
|
297
|
+
pid = await createStatementRunners(connection).selectValue("SELECT pg_backend_pid()");
|
|
298
|
+
await assert.rejects(connection.execute(createStatement("SELECT 1/0")), QueryError);
|
|
299
|
+
} finally {
|
|
300
|
+
await connection.release();
|
|
301
|
+
}
|
|
302
|
+
assert.equal(await createStatementRunners(own).selectValue("SELECT pg_backend_pid()"), pid);
|
|
303
303
|
} finally {
|
|
304
|
-
await
|
|
304
|
+
await own.close();
|
|
305
305
|
}
|
|
306
306
|
});
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
307
|
+
for (const [state, text] of [["an open", "SELECT 1"], ["a failed", "SELECT 1/0"]]) it(`does not return a connection in ${state} transaction to the pool`, async () => {
|
|
308
|
+
const own = createDriver({ max: 1 });
|
|
309
|
+
try {
|
|
310
|
+
const connection = await own.acquire();
|
|
310
311
|
try {
|
|
311
|
-
const connection = await driver.acquire();
|
|
312
312
|
await connection.execute(createStatement("BEGIN"));
|
|
313
313
|
await connection.execute(createStatement(text)).catch(() => {});
|
|
314
|
-
await connection.release({ error: /* @__PURE__ */ new Error("failure") });
|
|
315
|
-
await assert.rejects(driver.execute(createStatement("SAVEPOINT probe")), /transaction blocks/);
|
|
316
314
|
} finally {
|
|
317
|
-
await
|
|
315
|
+
await connection.release();
|
|
318
316
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
317
|
+
await assert.rejects(own.execute(createStatement("SAVEPOINT probe")), /transaction blocks/);
|
|
318
|
+
} finally {
|
|
319
|
+
await own.close();
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
describe("a statement on the pool that leaves a transaction open", () => {
|
|
323
|
+
const cases = [
|
|
324
|
+
[
|
|
325
|
+
"a statement",
|
|
326
|
+
(own) => own.execute(createStatement("BEGIN")),
|
|
327
|
+
ConnectionError
|
|
328
|
+
],
|
|
329
|
+
[
|
|
330
|
+
"a script",
|
|
331
|
+
(own) => own.executeScript("BEGIN; SELECT 1"),
|
|
332
|
+
ConnectionError
|
|
333
|
+
],
|
|
334
|
+
[
|
|
335
|
+
"a script that fails in the transaction",
|
|
336
|
+
(own) => own.executeScript("BEGIN; SELECT 1/0"),
|
|
337
|
+
Error
|
|
338
|
+
]
|
|
339
|
+
];
|
|
340
|
+
for (const [name, run, rejection] of cases) it(`rejects ${name} and leaves no transaction on the pool`, async () => {
|
|
341
|
+
const own = createDriver({ max: 2 });
|
|
342
|
+
const held = [];
|
|
323
343
|
try {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
await selectValueOnSingle("SELECT 1");
|
|
328
|
-
});
|
|
329
|
-
await assert.rejects(transaction, /Transaction rollback failed/);
|
|
330
|
-
assert.equal(await single.transaction(() => selectValueOnSingle("SELECT 'usable'")), "usable");
|
|
344
|
+
await assert.rejects(run(own), rejection);
|
|
345
|
+
for (let count = 0; count < 2; count++) held.push(await own.acquire());
|
|
346
|
+
for (const connection of held) await assert.rejects(connection.execute(createStatement("SAVEPOINT probe")), /transaction blocks/);
|
|
331
347
|
} finally {
|
|
332
|
-
await
|
|
348
|
+
await Promise.allSettled(held.map(async (connection) => connection.release()));
|
|
349
|
+
await own.close();
|
|
333
350
|
}
|
|
334
351
|
});
|
|
335
|
-
|
|
336
|
-
|
|
352
|
+
});
|
|
353
|
+
it("rejects a transaction whose connection is lost and keeps the pool usable", async () => {
|
|
354
|
+
const single = createDatabase({ driver: createDriver({ max: 1 }) });
|
|
355
|
+
const { selectValue: selectValueOnSingle } = createStatementRunners(single);
|
|
356
|
+
try {
|
|
357
|
+
const transaction = single.transaction(async () => {
|
|
358
|
+
const pid = await selectValueOnSingle("SELECT pg_backend_pid()");
|
|
359
|
+
await selectValue("SELECT pg_terminate_backend($1)", [pid]);
|
|
360
|
+
await selectValueOnSingle("SELECT 1");
|
|
361
|
+
});
|
|
362
|
+
await assert.rejects(transaction, (error) => error instanceof TransactionConnectionError && error.phase === "transaction");
|
|
363
|
+
assert.equal(await single.transaction(() => selectValueOnSingle("SELECT 'usable'")), "usable");
|
|
364
|
+
} finally {
|
|
365
|
+
await single.close();
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
it("rejects a statement of a transaction whose connection is lost with ConnectionError", async () => {
|
|
369
|
+
const own = createDriver({ max: 1 });
|
|
370
|
+
try {
|
|
371
|
+
const connection = await own.acquire();
|
|
372
|
+
const { runStatement, selectValue: selectValueOnConnection } = createStatementRunners(connection);
|
|
337
373
|
try {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
assert.equal(await selectValue("SELECT pg_terminate_backend($1, 5000)", [pid]), "t");
|
|
346
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
347
|
-
const error = await runStatement("INSERT INTO pg_lost_test VALUES (1)").catch((error) => error);
|
|
348
|
-
failure = { error };
|
|
349
|
-
assert.ok(error instanceof ConnectionError, `Expected ConnectionError, got ${String(error)}`);
|
|
350
|
-
} catch (error) {
|
|
351
|
-
failure ??= { error };
|
|
352
|
-
throw error;
|
|
353
|
-
} finally {
|
|
354
|
-
await connection.release(failure);
|
|
355
|
-
}
|
|
374
|
+
await runStatement("BEGIN");
|
|
375
|
+
await runStatement("CREATE TEMP TABLE pg_lost_test (id integer) ON COMMIT DROP");
|
|
376
|
+
const pid = await selectValueOnConnection("SELECT pg_backend_pid()");
|
|
377
|
+
assert.equal(await selectValue("SELECT pg_terminate_backend($1, 5000)", [pid]), "t");
|
|
378
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
379
|
+
const error = await runStatement("INSERT INTO pg_lost_test VALUES (1)").catch((error) => error);
|
|
380
|
+
assert.ok(error instanceof ConnectionError, `Expected ConnectionError, got ${String(error)}`);
|
|
356
381
|
} finally {
|
|
357
|
-
await
|
|
382
|
+
await connection.release();
|
|
358
383
|
}
|
|
359
|
-
}
|
|
360
|
-
|
|
384
|
+
} finally {
|
|
385
|
+
await own.close();
|
|
386
|
+
}
|
|
387
|
+
});
|
|
361
388
|
it("replaces an idle connection whose backend exited", async () => {
|
|
362
389
|
const own = createDriver({ max: 2 });
|
|
363
390
|
const held = [];
|
package/dist/types.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $r as EqualityOperators, A as AnyExpression, E as TextTypeOperators, Ji as BaseType, O as NumberTypeOperators, Qr as EqualityOperator, T as TextOperators, Xi as Type, da as OperatorDefinitions, ei as HasEquality, fa as GenericOperator, ii as ComparisonSignature, la as MergeOperators, ti as InSignature, ua as NoOperators } from "./index-2z5iTzXf.mjs";
|
|
2
2
|
/**
|
|
3
3
|
* Creates a one-dimensional array type of `element` values.
|
|
4
4
|
*
|