@prairielearn/postgres 4.0.1 → 4.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @prairielearn/postgres
2
2
 
3
+ ## 4.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 56a813a: Add `execute` and `executeRow` helpers that don't return the actual values from a query.
8
+
3
9
  ## 4.0.1
4
10
 
5
11
  ### Patch Changes
@@ -53,6 +53,8 @@ export declare const runInTransactionAsync: <T>(fn: (client: import("pg").defaul
53
53
  /**
54
54
  * Executes a query with the specified parameters.
55
55
  *
56
+ * @deprecated Use {@link execute} instead.
57
+ *
56
58
  * Using the return value of this function directly is not recommended. Instead, use
57
59
  * {@link queryRows}, {@link queryRow}, or {@link queryOptionalRow}.
58
60
  */
@@ -61,7 +63,7 @@ export declare const queryAsync: (sql: string, params: QueryParams) => Promise<i
61
63
  * Executes a query with the specified parameters. Errors if the query does
62
64
  * not return exactly one row.
63
65
  *
64
- * @deprecated Use {@link queryRow} instead.
66
+ * @deprecated Use {@link executeRow} or {@link queryRow} instead.
65
67
  */
66
68
  export declare const queryOneRowAsync: (sql: string, params: QueryParams) => Promise<import("pg").default.QueryResult>;
67
69
  /**
@@ -158,6 +160,14 @@ export declare const callOptionalRow: {
158
160
  <Model extends import("zod").ZodTypeAny>(sql: string, model: Model): Promise<import("zod").TypeOf<Model> | null>;
159
161
  <Model extends import("zod").ZodTypeAny>(sql: string, params: any[], model: Model): Promise<import("zod").TypeOf<Model> | null>;
160
162
  };
163
+ /**
164
+ * Executes a query with the specified parameters. Returns the number of rows affected.
165
+ */
166
+ export declare const execute: (sql: string, params?: QueryParams) => Promise<number>;
167
+ /**
168
+ * Executes a query with the specified parameter, and errors if the query doesn't return exactly one row.
169
+ */
170
+ export declare const executeRow: (sql: string, params?: QueryParams) => Promise<void>;
161
171
  /**
162
172
  * Returns an {@link CursorIterator} that can be used to iterate over the
163
173
  * results of the query in batches, which is useful for large result sets.
@@ -169,7 +179,7 @@ export declare const queryCursor: <Model extends import("zod").ZodTypeAny>(sql:
169
179
  *
170
180
  * @param schema The schema name to use (can be "null" to unset the search path)
171
181
  */
172
- export declare const setSearchSchema: (schema: string) => Promise<void>;
182
+ export declare const setSearchSchema: (schema: string | null) => Promise<void>;
173
183
  /**
174
184
  * Get the schema that is currently used for the search path.
175
185
  *
@@ -64,6 +64,8 @@ export const runInTransactionAsync = defaultPool.runInTransactionAsync.bind(defa
64
64
  /**
65
65
  * Executes a query with the specified parameters.
66
66
  *
67
+ * @deprecated Use {@link execute} instead.
68
+ *
67
69
  * Using the return value of this function directly is not recommended. Instead, use
68
70
  * {@link queryRows}, {@link queryRow}, or {@link queryOptionalRow}.
69
71
  */
@@ -72,7 +74,7 @@ export const queryAsync = defaultPool.queryAsync.bind(defaultPool);
72
74
  * Executes a query with the specified parameters. Errors if the query does
73
75
  * not return exactly one row.
74
76
  *
75
- * @deprecated Use {@link queryRow} instead.
77
+ * @deprecated Use {@link executeRow} or {@link queryRow} instead.
76
78
  */
77
79
  export const queryOneRowAsync = defaultPool.queryOneRowAsync.bind(defaultPool);
78
80
  /**
@@ -151,6 +153,14 @@ export const callRow = defaultPool.callRow.bind(defaultPool);
151
153
  * or a single row that conforms to the given Zod schema.
152
154
  */
153
155
  export const callOptionalRow = defaultPool.callOptionalRow.bind(defaultPool);
156
+ /**
157
+ * Executes a query with the specified parameters. Returns the number of rows affected.
158
+ */
159
+ export const execute = defaultPool.execute.bind(defaultPool);
160
+ /**
161
+ * Executes a query with the specified parameter, and errors if the query doesn't return exactly one row.
162
+ */
163
+ export const executeRow = defaultPool.executeRow.bind(defaultPool);
154
164
  /**
155
165
  * Returns an {@link CursorIterator} that can be used to iterate over the
156
166
  * results of the query in batches, which is useful for large result sets.
@@ -1 +1 @@
1
- {"version":3,"file":"default-pool.js","sourceRoot":"","sources":["../src/default-pool.ts"],"names":[],"mappings":"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","sourcesContent":["import { type CursorIterator, PostgresPool, type QueryParams } from './pool.js';\n\nconst defaultPool = new PostgresPool();\nexport { defaultPool, type CursorIterator, type QueryParams };\n\n// We re-expose all functions from the default pool here to account for the\n// default case of a shared global pool of clients. If someone want to create\n// their own pool, we expose the `PostgresPool` class.\n//\n// Note that we explicitly bind all functions to `defaultPool`. This ensures\n// that they'll be invoked with the correct `this` context, specifically when\n// this module is imported as `import * as db from '...'` and that import is\n// subsequently transformed by Babel to `interopRequireWildcard(...)`.\n\n// VSCode currently doesn't allow for us to use `inheritDoc` to inherit the\n// documentation from the `PostgresPool` class. We mirror the documentation\n// here for *async methods* in VSCode intellisense.\n\n/**\n * Creates a new connection pool and attempts to connect to the database.\n */\nexport const initAsync = defaultPool.initAsync.bind(defaultPool);\n/**\n * Closes the connection pool.\n */\nexport const closeAsync = defaultPool.closeAsync.bind(defaultPool);\n/**\n * Gets a new client from the connection pool. The caller MUST call `release()` to\n * release the client, whether or not errors occurred while using\n * `client`. The client can call `done(truthy_value)` to force\n * destruction of the client, but this should not be used except in\n * unusual circumstances.\n */\nexport const getClientAsync = defaultPool.getClientAsync.bind(defaultPool);\n\n/**\n * Performs a query with the given client.\n */\nexport const queryWithClientAsync = defaultPool.queryWithClientAsync.bind(defaultPool);\n\n/**\n * Performs a query with the given client. Errors if the query returns more\n * than one row.\n */\nexport const queryWithClientOneRowAsync = defaultPool.queryWithClientOneRowAsync.bind(defaultPool);\n\n/**\n * Performs a query with the given client. Errors if the query returns more\n * than one row.\n */\nexport const queryWithClientZeroOrOneRowAsync =\n defaultPool.queryWithClientZeroOrOneRowAsync.bind(defaultPool);\n/**\n * Rolls back the current transaction for the given client.\n */\nexport const rollbackWithClientAsync = defaultPool.rollbackWithClientAsync.bind(defaultPool);\nexport const beginTransactionAsync = defaultPool.beginTransactionAsync.bind(defaultPool);\n/**\n * Commits the transaction if err is null, otherwise rollbacks the transaction.\n * Also releases the client.\n */\nexport const endTransactionAsync = defaultPool.endTransactionAsync.bind(defaultPool);\n/**\n * Runs the specified function inside of a transaction. The function will\n * receive a database client as an argument, but it can also make queries\n * as usual, and the correct client will be used automatically.\n *\n * The transaction will be rolled back if the function throws an error, and\n * will be committed otherwise.\n */\nexport const runInTransactionAsync = defaultPool.runInTransactionAsync.bind(defaultPool);\n/**\n * Executes a query with the specified parameters.\n *\n * Using the return value of this function directly is not recommended. Instead, use\n * {@link queryRows}, {@link queryRow}, or {@link queryOptionalRow}.\n */\nexport const queryAsync = defaultPool.queryAsync.bind(defaultPool);\n/**\n * Executes a query with the specified parameters. Errors if the query does\n * not return exactly one row.\n *\n * @deprecated Use {@link queryRow} instead.\n */\nexport const queryOneRowAsync = defaultPool.queryOneRowAsync.bind(defaultPool);\n/**\n * Executes a query with the specified parameters. Errors if the query\n * returns more than one row.\n *\n * @deprecated Use {@link queryOptionalRow} instead.\n */\nexport const queryZeroOrOneRowAsync = defaultPool.queryZeroOrOneRowAsync.bind(defaultPool);\n/**\n * Calls the given sproc with the specified parameters.\n *\n * @deprecated Use {@link callRows} instead.\n */\nexport const callAsync = defaultPool.callAsync.bind(defaultPool);\n/**\n * Calls the given sproc with the specified parameters. Errors if the\n * sproc does not return exactly one row.\n *\n * @deprecated Use {@link callRow} instead.\n */\nexport const callOneRowAsync = defaultPool.callOneRowAsync.bind(defaultPool);\n/**\n * Calls the given sproc with the specified parameters. Errors if the\n * sproc returns more than one row.\n *\n * @deprecated Use {@link callOptionalRow} instead.\n */\nexport const callZeroOrOneRowAsync = defaultPool.callZeroOrOneRowAsync.bind(defaultPool);\n/**\n * Calls a sproc with the specified parameters using a specific client.\n */\nexport const callWithClientAsync = defaultPool.callWithClientAsync.bind(defaultPool);\n/**\n * Calls a sproc with the specified parameters using a specific client.\n * Errors if the sproc does not return exactly one row.\n */\nexport const callWithClientOneRowAsync = defaultPool.callWithClientOneRowAsync.bind(defaultPool);\n/**\n * Calls a sproc with the specified parameters using a specific client.\n * Errors if the sproc returns more than one row.\n */\nexport const callWithClientZeroOrOneRowAsync =\n defaultPool.callWithClientZeroOrOneRowAsync.bind(defaultPool);\n/**\n * Executes a query with the specified parameters. Returns an array of rows\n * that conform to the given Zod schema.\n *\n * If the query returns a single column, the return value will be a list of column values.\n */\nexport const queryRows = defaultPool.queryRows.bind(defaultPool);\n/**\n * Executes a query with the specified parameters. Returns exactly one row that conforms to the given Zod schema.\n *\n * If the query returns a single column, the return value will be the column value itself.\n */\nexport const queryRow = defaultPool.queryRow.bind(defaultPool);\n/**\n * Executes a query with the specified parameters. Returns either null or a\n * single row that conforms to the given Zod schema, and errors otherwise.\n *\n * If the query returns a single column, the return value will be the column value itself.\n */\nexport const queryOptionalRow = defaultPool.queryOptionalRow.bind(defaultPool);\n/**\n * Calls the given sproc with the specified parameters.\n * Errors if the sproc does not return anything.\n */\nexport const callRows = defaultPool.callRows.bind(defaultPool);\n/**\n * Calls the given sproc with the specified parameters.\n * Returns exactly one row from the sproc that conforms to the given Zod schema.\n */\nexport const callRow = defaultPool.callRow.bind(defaultPool);\n/**\n * Calls the given sproc with the specified parameters. Returns either null\n * or a single row that conforms to the given Zod schema.\n */\nexport const callOptionalRow = defaultPool.callOptionalRow.bind(defaultPool);\n/**\n * Returns an {@link CursorIterator} that can be used to iterate over the\n * results of the query in batches, which is useful for large result sets.\n * Each row will be parsed by the given Zod schema.\n */\nexport const queryCursor = defaultPool.queryCursor.bind(defaultPool);\n/**\n * Set the schema to use for the search path.\n *\n * @param schema The schema name to use (can be \"null\" to unset the search path)\n */\nexport const setSearchSchema = defaultPool.setSearchSchema.bind(defaultPool);\n/**\n * Get the schema that is currently used for the search path.\n *\n * @returns schema in use (may be `null` to indicate no schema)\n */\nexport const getSearchSchema = defaultPool.getSearchSchema.bind(defaultPool);\n/**\n * Generate, set, and return a random schema name.\n *\n * @param prefix The prefix of the new schema, only the first 28 characters will be used (after lowercasing).\n * @returns The randomly-generated search schema.\n */\nexport const setRandomSearchSchemaAsync = defaultPool.setRandomSearchSchemaAsync.bind(defaultPool);\n"]}
1
+ {"version":3,"file":"default-pool.js","sourceRoot":"","sources":["../src/default-pool.ts"],"names":[],"mappings":"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","sourcesContent":["import { type CursorIterator, PostgresPool, type QueryParams } from './pool.js';\n\nconst defaultPool = new PostgresPool();\nexport { defaultPool, type CursorIterator, type QueryParams };\n\n// We re-expose all functions from the default pool here to account for the\n// default case of a shared global pool of clients. If someone want to create\n// their own pool, we expose the `PostgresPool` class.\n//\n// Note that we explicitly bind all functions to `defaultPool`. This ensures\n// that they'll be invoked with the correct `this` context, specifically when\n// this module is imported as `import * as db from '...'` and that import is\n// subsequently transformed by Babel to `interopRequireWildcard(...)`.\n\n// VSCode currently doesn't allow for us to use `inheritDoc` to inherit the\n// documentation from the `PostgresPool` class. We mirror the documentation\n// here for *async methods* in VSCode intellisense.\n\n/**\n * Creates a new connection pool and attempts to connect to the database.\n */\nexport const initAsync = defaultPool.initAsync.bind(defaultPool);\n/**\n * Closes the connection pool.\n */\nexport const closeAsync = defaultPool.closeAsync.bind(defaultPool);\n/**\n * Gets a new client from the connection pool. The caller MUST call `release()` to\n * release the client, whether or not errors occurred while using\n * `client`. The client can call `done(truthy_value)` to force\n * destruction of the client, but this should not be used except in\n * unusual circumstances.\n */\nexport const getClientAsync = defaultPool.getClientAsync.bind(defaultPool);\n\n/**\n * Performs a query with the given client.\n */\nexport const queryWithClientAsync = defaultPool.queryWithClientAsync.bind(defaultPool);\n\n/**\n * Performs a query with the given client. Errors if the query returns more\n * than one row.\n */\nexport const queryWithClientOneRowAsync = defaultPool.queryWithClientOneRowAsync.bind(defaultPool);\n\n/**\n * Performs a query with the given client. Errors if the query returns more\n * than one row.\n */\nexport const queryWithClientZeroOrOneRowAsync =\n defaultPool.queryWithClientZeroOrOneRowAsync.bind(defaultPool);\n/**\n * Rolls back the current transaction for the given client.\n */\nexport const rollbackWithClientAsync = defaultPool.rollbackWithClientAsync.bind(defaultPool);\nexport const beginTransactionAsync = defaultPool.beginTransactionAsync.bind(defaultPool);\n/**\n * Commits the transaction if err is null, otherwise rollbacks the transaction.\n * Also releases the client.\n */\nexport const endTransactionAsync = defaultPool.endTransactionAsync.bind(defaultPool);\n/**\n * Runs the specified function inside of a transaction. The function will\n * receive a database client as an argument, but it can also make queries\n * as usual, and the correct client will be used automatically.\n *\n * The transaction will be rolled back if the function throws an error, and\n * will be committed otherwise.\n */\nexport const runInTransactionAsync = defaultPool.runInTransactionAsync.bind(defaultPool);\n/**\n * Executes a query with the specified parameters.\n *\n * @deprecated Use {@link execute} instead.\n *\n * Using the return value of this function directly is not recommended. Instead, use\n * {@link queryRows}, {@link queryRow}, or {@link queryOptionalRow}.\n */\nexport const queryAsync = defaultPool.queryAsync.bind(defaultPool);\n/**\n * Executes a query with the specified parameters. Errors if the query does\n * not return exactly one row.\n *\n * @deprecated Use {@link executeRow} or {@link queryRow} instead.\n */\nexport const queryOneRowAsync = defaultPool.queryOneRowAsync.bind(defaultPool);\n/**\n * Executes a query with the specified parameters. Errors if the query\n * returns more than one row.\n *\n * @deprecated Use {@link queryOptionalRow} instead.\n */\nexport const queryZeroOrOneRowAsync = defaultPool.queryZeroOrOneRowAsync.bind(defaultPool);\n/**\n * Calls the given sproc with the specified parameters.\n *\n * @deprecated Use {@link callRows} instead.\n */\nexport const callAsync = defaultPool.callAsync.bind(defaultPool);\n/**\n * Calls the given sproc with the specified parameters. Errors if the\n * sproc does not return exactly one row.\n *\n * @deprecated Use {@link callRow} instead.\n */\nexport const callOneRowAsync = defaultPool.callOneRowAsync.bind(defaultPool);\n/**\n * Calls the given sproc with the specified parameters. Errors if the\n * sproc returns more than one row.\n *\n * @deprecated Use {@link callOptionalRow} instead.\n */\nexport const callZeroOrOneRowAsync = defaultPool.callZeroOrOneRowAsync.bind(defaultPool);\n/**\n * Calls a sproc with the specified parameters using a specific client.\n */\nexport const callWithClientAsync = defaultPool.callWithClientAsync.bind(defaultPool);\n/**\n * Calls a sproc with the specified parameters using a specific client.\n * Errors if the sproc does not return exactly one row.\n */\nexport const callWithClientOneRowAsync = defaultPool.callWithClientOneRowAsync.bind(defaultPool);\n/**\n * Calls a sproc with the specified parameters using a specific client.\n * Errors if the sproc returns more than one row.\n */\nexport const callWithClientZeroOrOneRowAsync =\n defaultPool.callWithClientZeroOrOneRowAsync.bind(defaultPool);\n/**\n * Executes a query with the specified parameters. Returns an array of rows\n * that conform to the given Zod schema.\n *\n * If the query returns a single column, the return value will be a list of column values.\n */\nexport const queryRows = defaultPool.queryRows.bind(defaultPool);\n/**\n * Executes a query with the specified parameters. Returns exactly one row that conforms to the given Zod schema.\n *\n * If the query returns a single column, the return value will be the column value itself.\n */\nexport const queryRow = defaultPool.queryRow.bind(defaultPool);\n/**\n * Executes a query with the specified parameters. Returns either null or a\n * single row that conforms to the given Zod schema, and errors otherwise.\n *\n * If the query returns a single column, the return value will be the column value itself.\n */\nexport const queryOptionalRow = defaultPool.queryOptionalRow.bind(defaultPool);\n/**\n * Calls the given sproc with the specified parameters.\n * Errors if the sproc does not return anything.\n */\nexport const callRows = defaultPool.callRows.bind(defaultPool);\n/**\n * Calls the given sproc with the specified parameters.\n * Returns exactly one row from the sproc that conforms to the given Zod schema.\n */\nexport const callRow = defaultPool.callRow.bind(defaultPool);\n/**\n * Calls the given sproc with the specified parameters. Returns either null\n * or a single row that conforms to the given Zod schema.\n */\nexport const callOptionalRow = defaultPool.callOptionalRow.bind(defaultPool);\n\n/**\n * Executes a query with the specified parameters. Returns the number of rows affected.\n */\nexport const execute = defaultPool.execute.bind(defaultPool);\n\n/**\n * Executes a query with the specified parameter, and errors if the query doesn't return exactly one row.\n */\nexport const executeRow = defaultPool.executeRow.bind(defaultPool);\n\n/**\n * Returns an {@link CursorIterator} that can be used to iterate over the\n * results of the query in batches, which is useful for large result sets.\n * Each row will be parsed by the given Zod schema.\n */\nexport const queryCursor = defaultPool.queryCursor.bind(defaultPool);\n/**\n * Set the schema to use for the search path.\n *\n * @param schema The schema name to use (can be \"null\" to unset the search path)\n */\nexport const setSearchSchema = defaultPool.setSearchSchema.bind(defaultPool);\n/**\n * Get the schema that is currently used for the search path.\n *\n * @returns schema in use (may be `null` to indicate no schema)\n */\nexport const getSearchSchema = defaultPool.getSearchSchema.bind(defaultPool);\n/**\n * Generate, set, and return a random schema name.\n *\n * @param prefix The prefix of the new schema, only the first 28 characters will be used (after lowercasing).\n * @returns The randomly-generated search schema.\n */\nexport const setRandomSearchSchemaAsync = defaultPool.setRandomSearchSchemaAsync.bind(defaultPool);\n"]}
package/dist/error.js CHANGED
@@ -6,7 +6,7 @@ export function formatQueryWithErrorPosition(query, position) {
6
6
  if (nextNewline < 0)
7
7
  nextNewline = query.length;
8
8
  const gap = ' '.repeat(Math.max(0, position - prevNewline - 1));
9
- return (query.substring(0, nextNewline) +
9
+ return (query.slice(0, nextNewline) +
10
10
  '\n' +
11
11
  gap +
12
12
  '^\n' +
@@ -14,6 +14,6 @@ export function formatQueryWithErrorPosition(query, position) {
14
14
  '|\n' +
15
15
  gap +
16
16
  '+ ERROR POSITION SHOWN ABOVE\n' +
17
- query.substring(nextNewline));
17
+ query.slice(nextNewline));
18
18
  }
19
19
  //# sourceMappingURL=error.js.map
package/dist/error.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,4BAA4B,CAAC,KAAa,EAAE,QAAmC;IAC7F,IAAI,QAAQ,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IAEnC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IACvE,IAAI,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAChD,IAAI,WAAW,GAAG,CAAC;QAAE,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC;IAChD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC;IAChE,OAAO,CACL,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,WAAW,CAAC;QAC/B,IAAI;QACJ,GAAG;QACH,KAAK;QACL,GAAG;QACH,KAAK;QACL,GAAG;QACH,gCAAgC;QAChC,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAC7B,CAAC;AACJ,CAAC","sourcesContent":["export function formatQueryWithErrorPosition(query: string, position: number | null | undefined) {\n if (position == null) return query;\n\n const prevNewline = Math.max(0, query.lastIndexOf('\\n', position) + 1);\n let nextNewline = query.indexOf('\\n', position);\n if (nextNewline < 0) nextNewline = query.length;\n const gap = ' '.repeat(Math.max(0, position - prevNewline - 1));\n return (\n query.substring(0, nextNewline) +\n '\\n' +\n gap +\n '^\\n' +\n gap +\n '|\\n' +\n gap +\n '+ ERROR POSITION SHOWN ABOVE\\n' +\n query.substring(nextNewline)\n );\n}\n"]}
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,4BAA4B,CAAC,KAAa,EAAE,QAAmC;IAC7F,IAAI,QAAQ,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IAEnC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IACvE,IAAI,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAChD,IAAI,WAAW,GAAG,CAAC;QAAE,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC;IAChD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC;IAChE,OAAO,CACL,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC;QAC3B,IAAI;QACJ,GAAG;QACH,KAAK;QACL,GAAG;QACH,KAAK;QACL,GAAG;QACH,gCAAgC;QAChC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CACzB,CAAC;AACJ,CAAC","sourcesContent":["export function formatQueryWithErrorPosition(query: string, position: number | null | undefined) {\n if (position == null) return query;\n\n const prevNewline = Math.max(0, query.lastIndexOf('\\n', position) + 1);\n let nextNewline = query.indexOf('\\n', position);\n if (nextNewline < 0) nextNewline = query.length;\n const gap = ' '.repeat(Math.max(0, position - prevNewline - 1));\n return (\n query.slice(0, nextNewline) +\n '\\n' +\n gap +\n '^\\n' +\n gap +\n '|\\n' +\n gap +\n '+ ERROR POSITION SHOWN ABOVE\\n' +\n query.slice(nextNewline)\n );\n}\n"]}
package/dist/pool.d.ts CHANGED
@@ -80,11 +80,18 @@ export declare class PostgresPool {
80
80
  runInTransactionAsync<T>(fn: (client: pg.PoolClient) => Promise<T>): Promise<T>;
81
81
  /**
82
82
  * Executes a query with the specified parameters.
83
+ *
84
+ * @deprecated Use {@link execute} instead.
85
+ *
86
+ * Using the return value of this function directly is not recommended. Instead, use
87
+ * {@link queryRows}, {@link queryRow}, or {@link queryOptionalRow}.
83
88
  */
84
89
  queryAsync(sql: string, params: QueryParams): Promise<QueryResult>;
85
90
  /**
86
91
  * Executes a query with the specified parameters. Errors if the query does
87
92
  * not return exactly one row.
93
+ *
94
+ * @deprecated Use {@link executeRow} or {@link queryRow} instead.
88
95
  */
89
96
  queryOneRowAsync(sql: string, params: QueryParams): Promise<pg.QueryResult>;
90
97
  /**
@@ -132,6 +139,14 @@ export declare class PostgresPool {
132
139
  callRow<Model extends z.ZodTypeAny>(sql: string, params: any[], model: Model): Promise<z.infer<Model>>;
133
140
  callOptionalRow<Model extends z.ZodTypeAny>(sql: string, model: Model): Promise<z.infer<Model> | null>;
134
141
  callOptionalRow<Model extends z.ZodTypeAny>(sql: string, params: any[], model: Model): Promise<z.infer<Model> | null>;
142
+ /**
143
+ * Executes a query with the specified parameters. Returns the number of rows affected.
144
+ */
145
+ execute(sql: string, params?: QueryParams): Promise<number>;
146
+ /**
147
+ * Executes a query with the specified parameter, and errors if the query doesn't return exactly one row.
148
+ */
149
+ executeRow(sql: string, params?: QueryParams): Promise<void>;
135
150
  /**
136
151
  * Returns a {@link Cursor} for the given query. The cursor can be used to
137
152
  * read results in batches, which is useful for large result sets.
@@ -149,7 +164,7 @@ export declare class PostgresPool {
149
164
  *
150
165
  * @param schema The schema name to use (can be "null" to unset the search path)
151
166
  */
152
- setSearchSchema(schema: string): Promise<void>;
167
+ setSearchSchema(schema: string | null): Promise<void>;
153
168
  /**
154
169
  * Get the schema that is currently used for the search path.
155
170
  *
package/dist/pool.js CHANGED
@@ -12,7 +12,7 @@ const lastQueryMap = new WeakMap();
12
12
  const searchSchemaMap = new WeakMap();
13
13
  function addDataToError(err, data) {
14
14
  err.data = {
15
- ...(err.data ?? {}),
15
+ ...err.data,
16
16
  ...data,
17
17
  };
18
18
  return err;
@@ -31,9 +31,9 @@ export class PostgresError extends Error {
31
31
  function debugString(s) {
32
32
  if (typeof s !== 'string')
33
33
  return 'NOT A STRING';
34
- s = s.replace(/\n/g, '\\n');
34
+ s = s.replaceAll('\n', '\\n');
35
35
  if (s.length > 78)
36
- s = s.substring(0, 75) + '...';
36
+ s = s.slice(0, 75) + '...';
37
37
  s = '"' + s + '"';
38
38
  return s;
39
39
  }
@@ -89,14 +89,14 @@ function paramsToArray(sql, params, errorOnUnusedParameters) {
89
89
  paramsArray.push(params[v]);
90
90
  }
91
91
  }
92
- processedSql += remainingSql.substring(0, result.index) + map[v];
93
- remainingSql = remainingSql.substring(result.index + result[0].length);
92
+ processedSql += remainingSql.slice(0, result.index) + map[v];
93
+ remainingSql = remainingSql.slice(result.index + result[0].length);
94
94
  }
95
95
  processedSql += remainingSql;
96
96
  remainingSql = '';
97
97
  if (errorOnUnusedParameters) {
98
98
  const difference = _.difference(Object.keys(params), Object.keys(map));
99
- if (difference.length) {
99
+ if (difference.length > 0) {
100
100
  throw new Error(`Unused parameters in SQL query: ${JSON.stringify(difference)}`);
101
101
  }
102
102
  }
@@ -402,6 +402,11 @@ export class PostgresPool {
402
402
  }
403
403
  /**
404
404
  * Executes a query with the specified parameters.
405
+ *
406
+ * @deprecated Use {@link execute} instead.
407
+ *
408
+ * Using the return value of this function directly is not recommended. Instead, use
409
+ * {@link queryRows}, {@link queryRow}, or {@link queryOptionalRow}.
405
410
  */
406
411
  async queryAsync(sql, params) {
407
412
  debug('query()', 'sql:', debugString(sql));
@@ -420,6 +425,8 @@ export class PostgresPool {
420
425
  /**
421
426
  * Executes a query with the specified parameters. Errors if the query does
422
427
  * not return exactly one row.
428
+ *
429
+ * @deprecated Use {@link executeRow} or {@link queryRow} instead.
423
430
  */
424
431
  async queryOneRowAsync(sql, params) {
425
432
  debug('queryOneRow()', 'sql:', debugString(sql));
@@ -457,7 +464,7 @@ export class PostgresPool {
457
464
  async callAsync(functionName, params) {
458
465
  debug('call()', 'function:', functionName);
459
466
  debug('call()', 'params:', debugParams(params));
460
- const placeholders = params.map((_, v) => '$' + (v + 1)).join();
467
+ const placeholders = params.map((_, v) => '$' + (v + 1)).join(',');
461
468
  const sql = `SELECT * FROM ${escapeIdentifier(functionName)}(${placeholders});`;
462
469
  const result = await this.queryAsync(sql, params);
463
470
  debug('call() success', 'rowCount:', result.rowCount);
@@ -503,7 +510,7 @@ export class PostgresPool {
503
510
  async callWithClientAsync(client, functionName, params) {
504
511
  debug('callWithClient()', 'function:', functionName);
505
512
  debug('callWithClient()', 'params:', debugParams(params));
506
- const placeholders = params.map((_, v) => '$' + (v + 1)).join();
513
+ const placeholders = params.map((_, v) => '$' + (v + 1)).join(',');
507
514
  const sql = `SELECT * FROM ${escapeIdentifier(functionName)}(${placeholders})`;
508
515
  const result = await this.queryWithClientAsync(client, sql, params);
509
516
  debug('callWithClient() success', 'rowCount:', result.rowCount);
@@ -652,6 +659,25 @@ export class PostgresPool {
652
659
  return model.parse(results.rows[0]);
653
660
  }
654
661
  }
662
+ /**
663
+ * Executes a query with the specified parameters. Returns the number of rows affected.
664
+ */
665
+ async execute(sql, params = {}) {
666
+ const result = await this.queryAsync(sql, params);
667
+ return result.rowCount ?? 0;
668
+ }
669
+ /**
670
+ * Executes a query with the specified parameter, and errors if the query doesn't return exactly one row.
671
+ */
672
+ async executeRow(sql, params = {}) {
673
+ const rowCount = await this.execute(sql, params);
674
+ if (rowCount !== 1) {
675
+ throw new PostgresError('Incorrect rowCount: ' + rowCount, {
676
+ sql,
677
+ sqlParams: params,
678
+ });
679
+ }
680
+ }
655
681
  /**
656
682
  * Returns a {@link Cursor} for the given query. The cursor can be used to
657
683
  * read results in batches, which is useful for large result sets.
@@ -768,7 +794,7 @@ export class PostgresPool {
768
794
  */
769
795
  async setRandomSearchSchemaAsync(prefix) {
770
796
  // truncated prefix (max 28 characters)
771
- const truncPrefix = prefix.substring(0, 28);
797
+ const truncPrefix = prefix.slice(0, 28);
772
798
  // timestamp in format YYYY-MM-DDTHH:MM:SS.SSSZ (guaranteed to not exceed 27 characters in the spec)
773
799
  const timestamp = new Date().toISOString();
774
800
  // random 6-character suffix to avoid clashes (approx 2 billion possible values)
package/dist/pool.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"pool.js","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,OAAO,MAAM,OAAO,CAAC;AAC5B,OAAO,CAAC,MAAM,QAAQ,CAAC;AACvB,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,EAAE,EAAoB,MAAM,IAAI,CAAC;AAC1C,OAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,MAAM,KAAK,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;AAChD,MAAM,YAAY,GAAG,IAAI,OAAO,EAAyB,CAAC;AAC1D,MAAM,eAAe,GAAG,IAAI,OAAO,EAAyB,CAAC;AAE7D,SAAS,cAAc,CAAC,GAAU,EAAE,IAAyB;IAC1D,GAAW,CAAC,IAAI,GAAG;QAClB,GAAG,CAAE,GAAW,CAAC,IAAI,IAAI,EAAE,CAAC;QAC5B,GAAG,IAAI;KACR,CAAC;IACF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,OAAO,aAAc,SAAQ,KAAK;IAC/B,IAAI,CAAsB;IAEjC,YAAY,OAAe,EAAE,IAAyB;QACpD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,CAAS;IAC5B,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,cAAc,CAAC;IACjD,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC5B,IAAI,CAAC,CAAC,MAAM,GAAG,EAAE;QAAE,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC;IAClD,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;IAClB,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,MAAmB;IACtC,IAAI,CAAC,CAAC;IACN,IAAI,CAAC;QACH,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,CAAC,GAAG,uBAAuB,CAAC;IAC9B,CAAC;IACD,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CACpB,GAAW,EACX,MAAmB,EACnB,uBAAgC;IAEhC,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IACrE,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,YAAY,EAAE,GAAG;YACjB,WAAW,EAAE,MAAM;SACpB,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,IAAI,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,EAAE,GAAG,oBAAoB,CAAC;IAChC,IAAI,MAAM,CAAC;IACX,IAAI,YAAY,GAAG,EAAE,CAAC;IACtB,IAAI,YAAY,GAAG,GAAG,CAAC;IACvB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,IAAI,WAAW,GAAU,EAAE,CAAC;IAC5B,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACjD,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAChB,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;YAC/D,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7B,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;gBACrF,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;gBAC5B,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9C,CAAC;iBAAM,CAAC;gBACN,OAAO,EAAE,CAAC;gBACV,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,OAAO,CAAC;gBACvB,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;QACD,YAAY,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACjE,YAAY,GAAG,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACzE,CAAC;IACD,YAAY,IAAI,YAAY,CAAC;IAC7B,YAAY,GAAG,EAAE,CAAC;IAClB,IAAI,uBAAuB,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACvE,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IACD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;AACvC,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,UAAkB;IAC1C,sEAAsE;IACtE,mDAAmD;IACnD,sDAAsD;IACtD,kEAAkE;IAClE,OAAO,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,YAAY,CAAC,GAAU,EAAE,GAAW,EAAE,MAAmB;IAChE,qEAAqE;IACrE,eAAe;IACf,MAAM,QAAQ,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;IAE5B,4EAA4E;IAC5E,oBAAoB;IACpB,QAAQ,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IAE/B,MAAM,gBAAgB,GAAG,GAAG,YAAY,aAAa,IAAI,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC;IAE9E,OAAO,cAAc,CAAC,GAAG,EAAE;QACzB,QAAQ;QACR,2EAA2E;QAC3E,0EAA0E;QAC1E,eAAe;QACf,GAAG,EAAE,gBAAgB,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG;QAC5E,SAAS,EAAE,MAAM;KAClB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,OAAO,YAAY;IACvB,oDAAoD;IAC5C,IAAI,GAAmB,IAAI,CAAC;IACpC;;;;;OAKG;IACK,SAAS,GAAG,IAAI,iBAAiB,EAAiB,CAAC;IACnD,YAAY,GAAkB,IAAI,CAAC;IAC3C,gEAAgE;IACxD,WAAW,GAAG,CAAC,CAAC;IAChB,uBAAuB,GAAG,KAAK,CAAC;IAExC;;OAEG;IACH,KAAK,CAAC,SAAS,CACb,QAA4B,EAC5B,gBAA+D;QAE/D,IAAI,CAAC,uBAAuB,GAAG,QAAQ,CAAC,uBAAuB,IAAI,KAAK,CAAC;QACzE,IAAI,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,GAAG,EAAE,MAAM;YACzC,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC3C,gBAAgB,CAAC,cAAc,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,EAAE;YACjC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACzB,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC3C,gBAAgB,CAAC,cAAc,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;YAC/D,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;YAChC,sEAAsE;YACtE,oEAAoE;YACpE,oEAAoE;YACpE,yEAAyE;YACzE,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,oEAAoE;QACpE,wCAAwC;QACxC,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACrD,OAAO,UAAU,IAAI,aAAa,CAAC,MAAM,EAAE,CAAC;YAC1C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACzC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjB,OAAO;YACT,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,IAAI,UAAU,KAAK,aAAa,CAAC,MAAM,EAAE,CAAC;oBACxC,MAAM,IAAI,KAAK,CACb,uCAAuC,aAAa,CAAC,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,CACvF,CAAC;gBACJ,CAAC;gBAED,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;gBAC1C,UAAU,EAAE,CAAC;gBACb,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,OAAO;QACvB,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,cAAc;QAClB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QAED,wEAAwE;QACxE,sBAAsB;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAExE,yEAAyE;QACzE,sEAAsE;QACtE,sEAAsE;QACtE,wEAAwE;QACxE,8BAA8B;QAC9B,EAAE;QACF,8DAA8D;QAC9D,kEAAkE;QAClE,wEAAwE;QACxE,mEAAmE;QACnE,qEAAqE;QACrE,gDAAgD;QAChD,EAAE;QACF,4EAA4E;QAC5E,4EAA4E;QAC5E,kEAAkE;QAClE,yEAAyE;QACzE,+CAA+C;QAC/C,MAAM,kBAAkB,GAAG,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACvD,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,IAAI,kBAAkB,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC;YAC1E,MAAM,gBAAgB,GAAG,sBAAsB,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC;YAC5F,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC;YAChE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjB,MAAM,GAAG,CAAC;YACZ,CAAC;YACD,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QACjD,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,oBAAoB,CACxB,MAAqB,EACrB,GAAW,EACX,MAAmB;QAEnB,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;QACtB,KAAK,CAAC,mBAAmB,EAAE,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QACrD,KAAK,CAAC,mBAAmB,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3D,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC/F,IAAI,CAAC;YACH,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YACvC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;YAC7D,KAAK,CAAC,2BAA2B,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;YACjE,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,MAAM,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,0BAA0B,CAC9B,MAAqB,EACrB,GAAW,EACX,MAAmB;QAEnB,KAAK,CAAC,yBAAyB,EAAE,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3D,KAAK,CAAC,yBAAyB,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QACpE,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,aAAa,CAAC,uBAAuB,MAAM,CAAC,QAAQ,EAAE,EAAE;gBAChE,GAAG;gBACH,SAAS,EAAE,MAAM;gBACjB,MAAM;aACP,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,iCAAiC,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gCAAgC,CACpC,MAAqB,EACrB,GAAW,EACX,MAAmB;QAEnB,KAAK,CAAC,+BAA+B,EAAE,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QACjE,KAAK,CAAC,+BAA+B,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QACvE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QACpE,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,aAAa,CAAC,uBAAuB,MAAM,CAAC,QAAQ,EAAE,EAAE;gBAChE,GAAG;gBACH,SAAS,EAAE,MAAM;gBACjB,MAAM;aACP,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,uCAAuC,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7E,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,uBAAuB,CAAC,MAAqB;QACjD,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC9B,uDAAuD;QACvD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC/B,sEAAsE;YACtE,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,SAAS,EAAE,CAAC;gBAC5C,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,CAAC;QACH,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,8DAA8D;YAC9D,qEAAqE;YACrE,qEAAqE;YACrE,qEAAqE;YACrE,yBAAyB;YACzB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,qBAAqB;QACzB,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,EAAE,EAAE,CAAC,CAAC;YAClE,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,mBAAmB,CAAC,MAAqB,EAAE,GAA6B;QAC5E,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAC1B,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;YAC7C,CAAC;YAAC,OAAO,WAAgB,EAAE,CAAC;gBAC1B,MAAM,cAAc,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;YACxE,CAAC;YAED,qEAAqE;YACrE,2EAA2E;YAC3E,4EAA4E;YAC5E,MAAM,cAAc,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACrD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;YACxD,CAAC;oBAAS,CAAC;gBACT,0EAA0E;gBAC1E,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,SAAS,EAAE,CAAC;oBAC5C,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,qBAAqB,CAAI,EAAyC;QACtE,kFAAkF;QAClF,mDAAmD;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;QACzC,MAAM,mBAAmB,GAAG,MAAM,KAAK,SAAS,CAAC;QACjD,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC,CAAC;QAEzE,IAAI,MAAS,CAAC;QACd,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACpF,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBACzB,2EAA2E;gBAC3E,uDAAuD;gBACvD,MAAM,IAAI,CAAC,mBAAmB,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;YACzD,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACzB,0EAA0E;YAC1E,6CAA6C;YAC7C,EAAE;YACF,yEAAyE;YACzE,wEAAwE;YACxE,iDAAiD;YACjD,MAAM,IAAI,CAAC,mBAAmB,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,GAAW,EAAE,MAAmB;QAC/C,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,KAAK,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC3C,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAC9D,CAAC;gBAAS,CAAC;YACT,qDAAqD;YACrD,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,SAAS,EAAE,CAAC;gBAC5C,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CAAC,GAAW,EAAE,MAAmB;QACrD,KAAK,CAAC,eAAe,EAAE,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QACjD,KAAK,CAAC,eAAe,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAClD,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,aAAa,CAAC,uBAAuB,MAAM,CAAC,QAAQ,EAAE,EAAE;gBAChE,GAAG;gBACH,SAAS,EAAE,MAAM;aAClB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,uBAAuB,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7D,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,sBAAsB,CAAC,GAAW,EAAE,MAAmB;QAC3D,KAAK,CAAC,qBAAqB,EAAE,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,KAAK,CAAC,qBAAqB,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAClD,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,aAAa,CAAC,uBAAuB,MAAM,CAAC,QAAQ,EAAE,EAAE;gBAChE,GAAG;gBACH,SAAS,EAAE,MAAM;aAClB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,6BAA6B,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACnE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,YAAoB,EAAE,MAAa;QACjD,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;QAC3C,KAAK,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QAChD,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAChE,MAAM,GAAG,GAAG,iBAAiB,gBAAgB,CAAC,YAAY,CAAC,IAAI,YAAY,IAAI,CAAC;QAChF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAClD,KAAK,CAAC,gBAAgB,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,YAAoB,EAAE,MAAa;QACvD,KAAK,CAAC,cAAc,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;QACjD,KAAK,CAAC,cAAc,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAC1D,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,aAAa,CAAC,sBAAsB,GAAG,MAAM,CAAC,QAAQ,EAAE;gBAChE,YAAY;gBACZ,SAAS,EAAE,MAAM;aAClB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,sBAAsB,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5D,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,qBAAqB,CAAC,YAAoB,EAAE,MAAa;QAC7D,KAAK,CAAC,oBAAoB,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;QACvD,KAAK,CAAC,oBAAoB,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAC1D,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,aAAa,CAAC,sBAAsB,GAAG,MAAM,CAAC,QAAQ,EAAE;gBAChE,YAAY;gBACZ,SAAS,EAAE,MAAM;aAClB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,4BAA4B,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAClE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,mBAAmB,CACvB,MAAqB,EACrB,YAAoB,EACpB,MAAa;QAEb,KAAK,CAAC,kBAAkB,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;QACrD,KAAK,CAAC,kBAAkB,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1D,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAChE,MAAM,GAAG,GAAG,iBAAiB,gBAAgB,CAAC,YAAY,CAAC,IAAI,YAAY,GAAG,CAAC;QAC/E,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QACpE,KAAK,CAAC,0BAA0B,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,yBAAyB,CAC7B,MAAqB,EACrB,YAAoB,EACpB,MAAa;QAEb,KAAK,CAAC,wBAAwB,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;QAC3D,KAAK,CAAC,wBAAwB,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QAChE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;QAC5E,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,aAAa,CAAC,sBAAsB,GAAG,MAAM,CAAC,QAAQ,EAAE;gBAChE,YAAY;gBACZ,SAAS,EAAE,MAAM;aAClB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,gCAAgC,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,+BAA+B,CACnC,MAAqB,EACrB,YAAoB,EACpB,MAAa;QAEb,KAAK,CAAC,8BAA8B,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;QACjE,KAAK,CAAC,8BAA8B,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QACtE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;QAC5E,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,aAAa,CAAC,sBAAsB,GAAG,MAAM,CAAC,QAAQ,EAAE;gBAChE,YAAY;gBACZ,SAAS,EAAE,MAAM;aAClB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,sCAAsC,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5E,OAAO,MAAM,CAAC;IAChB,CAAC;IAQD;;;;;OAKG;IACH,KAAK,CAAC,SAAS,CACb,GAAW,EACX,cAAmC,EACnC,UAAkB;QAElB,MAAM,MAAM,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAE,cAA8B,CAAC;QAC/E,MAAM,KAAK,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAE,cAAwB,CAAC,CAAC,CAAC,UAAU,CAAC;QAChF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACnD,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;YAC3D,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAQD;;;;OAIG;IACH,KAAK,CAAC,QAAQ,CACZ,GAAW,EACX,cAAmC,EACnC,UAAkB;QAElB,MAAM,MAAM,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAE,cAA8B,CAAC;QAC/E,MAAM,KAAK,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAE,cAAwB,CAAC,CAAC,CAAC,UAAU,CAAC;QAChF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACzD,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC1C,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAWD;;;;;OAKG;IACH,KAAK,CAAC,gBAAgB,CACpB,GAAW,EACX,cAAmC,EACnC,UAAkB;QAElB,MAAM,MAAM,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAE,cAA8B,CAAC;QAC/E,MAAM,KAAK,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAE,cAAwB,CAAC,CAAC,CAAC,UAAU,CAAC;QAChF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC/D,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;aAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC1C,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAQD;;;OAGG;IACH,KAAK,CAAC,QAAQ,CACZ,GAAW,EACX,cAA6B,EAC7B,UAAkB;QAElB,MAAM,MAAM,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAE,cAAwB,CAAC;QACzE,MAAM,KAAK,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAE,cAAwB,CAAC,CAAC,CAAC,UAAU,CAAC;QAChF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAClD,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;YAC3D,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAQD;;;OAGG;IACH,KAAK,CAAC,OAAO,CACX,GAAW,EACX,cAA6B,EAC7B,UAAkB;QAElB,MAAM,MAAM,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAE,cAAwB,CAAC;QACzE,MAAM,KAAK,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAE,cAAwB,CAAC,CAAC,CAAC,UAAU,CAAC;QAChF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACxD,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC1C,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAWD;;;OAGG;IACH,KAAK,CAAC,eAAe,CACnB,GAAW,EACX,cAA6B,EAC7B,UAAkB;QAElB,MAAM,MAAM,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAE,cAAwB,CAAC;QACzE,MAAM,KAAK,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAE,cAAwB,CAAC,CAAC,CAAC,UAAU,CAAC;QAChF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC9D,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;aAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC1C,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,qBAAqB,CACjC,MAAqB,EACrB,GAAW,EACX,MAAmB;QAEnB,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;QACtB,KAAK,CAAC,yBAAyB,EAAE,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3D,KAAK,CAAC,yBAAyB,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QACjE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC/F,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QACvC,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAW,CACf,GAAW,EACX,MAAmB,EACnB,KAAY;QAEZ,OAAO,IAAI,CAAC,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAC/B,GAAW,EACX,MAAmB,EACnB,KAAa;QAEb,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAErE,IAAI,aAAa,GAAG,KAAK,CAAC;QAC1B,MAAM,QAAQ,GAAmC;YAC/C,KAAK,CAAC,CAAC,OAAO,CAAC,SAAiB;gBAC9B,iEAAiE;gBACjE,oCAAoC;gBACpC,IAAI,aAAa,EAAE,CAAC;oBAClB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;gBACrD,CAAC;gBACD,aAAa,GAAG,IAAI,CAAC;gBAErB,IAAI,CAAC;oBACH,OAAO,IAAI,EAAE,CAAC;wBACZ,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;wBAC1C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;4BACtB,MAAM;wBACR,CAAC;wBAED,IAAI,KAAK,EAAE,CAAC;4BACV,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;wBACnC,CAAC;6BAAM,CAAC;4BACN,MAAM,IAAI,CAAC;wBACb,CAAC;oBACH,CAAC;gBACH,CAAC;gBAAC,OAAO,GAAQ,EAAE,CAAC;oBAClB,MAAM,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;gBACvC,CAAC;wBAAS,CAAC;oBACT,IAAI,CAAC;wBACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;oBACvB,CAAC;4BAAS,CAAC;wBACT,MAAM,CAAC,OAAO,EAAE,CAAC;oBACnB,CAAC;gBACH,CAAC;YACH,CAAC;YACD,MAAM,CAAC,SAAiB;gBACtB,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC;oBAC9B,kBAAkB,EAAE,IAAI;oBACxB,kBAAkB,EAAE,IAAI;oBACxB,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ;wBAClC,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;4BACxB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;wBACjB,CAAC;wBACD,QAAQ,EAAE,CAAC;oBACb,CAAC;iBACF,CAAC,CAAC;gBAEH,2DAA2D;gBAC3D,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;gBAC9C,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC;gBAE5D,sEAAsE;gBACtE,4EAA4E;gBAC5E,qEAAqE;gBACrE,uEAAuE;gBACvE,uEAAuE;gBACvE,uDAAuD;gBACvD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;oBACtB,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACzB,CAAC,CAAC,CAAC;gBAEH,OAAO,IAAI,CAAC;YACd,CAAC;SACF,CAAC;QACF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,eAAe,CAAC,MAAc;QAClC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC;YAC3B,OAAO;QACT,CAAC;QAED,MAAM,IAAI,CAAC,UAAU,CAAC,+BAA+B,gBAAgB,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACrF,4FAA4F;QAC5F,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC;IAC7B,CAAC;IAED;;;;OAIG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,0BAA0B,CAAC,MAAc;QAC7C,uCAAuC;QACvC,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5C,oGAAoG;QACpG,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,gFAAgF;QAChF,MAAM,KAAK,GAAG,sCAAsC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;aACrC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;aAC1D,IAAI,CAAC,EAAE,CAAC,CAAC;QAEZ,0EAA0E;QAC1E,oDAAoD;QACpD,wFAAwF;QACxF,MAAM,MAAM,GAAG,GAAG,WAAW,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;QACvD,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QACnC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,6CAA6C;IAC7C,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,IAAI,EAAE,UAAU,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,sCAAsC;IACtC,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,0EAA0E;IAC1E,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,IAAI,EAAE,YAAY,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,wEAAwE;IACxE,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF","sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks';\nimport { Readable, Transform } from 'node:stream';\n\nimport debugfn from 'debug';\nimport _ from 'lodash';\nimport multipipe from 'multipipe';\nimport pg, { type QueryResult } from 'pg';\nimport Cursor from 'pg-cursor';\nimport { DatabaseError } from 'pg-protocol';\nimport { z } from 'zod';\n\nexport type QueryParams = Record<string, any> | any[];\n\nexport interface CursorIterator<T> {\n iterate: (batchSize: number) => AsyncGenerator<T[]>;\n stream: (batchSize: number) => NodeJS.ReadWriteStream;\n}\n\nexport interface PostgresPoolConfig extends pg.PoolConfig {\n errorOnUnusedParameters?: boolean;\n}\n\nconst debug = debugfn('@prairielearn/postgres');\nconst lastQueryMap = new WeakMap<pg.PoolClient, string>();\nconst searchSchemaMap = new WeakMap<pg.PoolClient, string>();\n\nfunction addDataToError(err: Error, data: Record<string, any>): Error {\n (err as any).data = {\n ...((err as any).data ?? {}),\n ...data,\n };\n return err;\n}\n\nexport class PostgresError extends Error {\n public data: Record<string, any>;\n\n constructor(message: string, data: Record<string, any>) {\n super(message);\n this.data = data;\n this.name = 'PostgresError';\n }\n}\n\n/**\n * Formats a string for debugging.\n */\nfunction debugString(s: string): string {\n if (typeof s !== 'string') return 'NOT A STRING';\n s = s.replace(/\\n/g, '\\\\n');\n if (s.length > 78) s = s.substring(0, 75) + '...';\n s = '\"' + s + '\"';\n return s;\n}\n\n/**\n * Formats a set of params for debugging.\n */\nfunction debugParams(params: QueryParams): string {\n let s;\n try {\n s = JSON.stringify(params);\n } catch {\n s = 'CANNOT JSON STRINGIFY';\n }\n return debugString(s);\n}\n\n/**\n * Given an SQL string and params, creates an array of params and an SQL string\n * with any named dollar-sign placeholders replaced with parameters.\n */\nfunction paramsToArray(\n sql: string,\n params: QueryParams,\n errorOnUnusedParameters: boolean,\n): { processedSql: string; paramsArray: any } {\n if (typeof sql !== 'string') throw new Error('SQL must be a string');\n if (Array.isArray(params)) {\n return {\n processedSql: sql,\n paramsArray: params,\n };\n }\n if (params == null || typeof params !== 'object') {\n throw new Error('params must be array or object');\n }\n\n const re = /\\$([-_a-zA-Z0-9]+)/;\n let result;\n let processedSql = '';\n let remainingSql = sql;\n let nParams = 0;\n const map: Record<string, string> = {};\n let paramsArray: any[] = [];\n while ((result = re.exec(remainingSql)) !== null) {\n const v = result[1];\n if (!(v in map)) {\n if (!(v in params)) throw new Error(`Missing parameter: ${v}`);\n if (Array.isArray(params[v])) {\n map[v] = 'ARRAY[' + params[v].map((_, n) => '$' + (n + nParams + 1)).join(',') + ']';\n nParams += params[v].length;\n paramsArray = paramsArray.concat(params[v]);\n } else {\n nParams++;\n map[v] = '$' + nParams;\n paramsArray.push(params[v]);\n }\n }\n processedSql += remainingSql.substring(0, result.index) + map[v];\n remainingSql = remainingSql.substring(result.index + result[0].length);\n }\n processedSql += remainingSql;\n remainingSql = '';\n if (errorOnUnusedParameters) {\n const difference = _.difference(Object.keys(params), Object.keys(map));\n if (difference.length) {\n throw new Error(`Unused parameters in SQL query: ${JSON.stringify(difference)}`);\n }\n }\n return { processedSql, paramsArray };\n}\n\n/**\n * Escapes the given identifier for use in an SQL query. Useful for preventing\n * SQL injection.\n */\nfunction escapeIdentifier(identifier: string): string {\n // Note that as of 2021-06-29 escapeIdentifier() is undocumented. See:\n // https://github.com/brianc/node-postgres/pull/396\n // https://github.com/brianc/node-postgres/issues/1978\n // https://www.postgresql.org/docs/current/sql-syntax-lexical.html\n return pg.Client.prototype.escapeIdentifier(identifier);\n}\n\nfunction enhanceError(err: Error, sql: string, params: QueryParams): Error {\n // Copy the error so we don't end up with a circular reference in the\n // final error.\n const sqlError = { ...err };\n\n // `message` is a non-enumerable property, so we need to copy it manually to\n // the error object.\n sqlError.message = err.message;\n\n const errorHasPosition = err instanceof DatabaseError && err.position != null;\n\n return addDataToError(err, {\n sqlError,\n // If the error has a `position` field, we need to use the processed source\n // (where e.g. `$foobar` has been replaced with `$1`) so that the position\n // is accurate.\n sql: errorHasPosition ? paramsToArray(sql, params, false).processedSql : sql,\n sqlParams: params,\n });\n}\n\nexport class PostgresPool {\n /** The pool from which clients will be acquired. */\n private pool: pg.Pool | null = null;\n /**\n * We use this to propagate the client associated with the current transaction\n * to any nested queries. In the past, we had some nasty bugs associated with\n * the fact that we tried to acquire new clients inside of transactions, which\n * ultimately lead to a deadlock.\n */\n private alsClient = new AsyncLocalStorage<pg.PoolClient>();\n private searchSchema: string | null = null;\n /** Tracks the total number of queries executed by this pool. */\n private _queryCount = 0;\n private errorOnUnusedParameters = false;\n\n /**\n * Creates a new connection pool and attempts to connect to the database.\n */\n async initAsync(\n pgConfig: PostgresPoolConfig,\n idleErrorHandler: (error: Error, client: pg.PoolClient) => void,\n ): Promise<void> {\n this.errorOnUnusedParameters = pgConfig.errorOnUnusedParameters ?? false;\n this.pool = new pg.Pool(pgConfig);\n this.pool.on('error', function (err, client) {\n const lastQuery = lastQueryMap.get(client);\n idleErrorHandler(addDataToError(err, { lastQuery }), client);\n });\n this.pool.on('connect', (client) => {\n client.on('error', (err) => {\n const lastQuery = lastQueryMap.get(client);\n idleErrorHandler(addDataToError(err, { lastQuery }), client);\n });\n });\n this.pool.on('remove', (client) => {\n // This shouldn't be necessary, as `pg` currently allows clients to be\n // garbage collected after they're removed. However, if `pg` someday\n // starts reusing client objects across difference connections, this\n // will ensure that we re-set the search path when the client reconnects.\n searchSchemaMap.delete(client);\n });\n\n // Attempt to connect to the database so that we can fail quickly if\n // something isn't configured correctly.\n let retryCount = 0;\n const retryTimeouts = [500, 1000, 2000, 5000, 10000];\n while (retryCount <= retryTimeouts.length) {\n try {\n const client = await this.pool.connect();\n client.release();\n return;\n } catch (err: any) {\n if (retryCount === retryTimeouts.length) {\n throw new Error(\n `Could not connect to Postgres after ${retryTimeouts.length} attempts: ${err.message}`,\n );\n }\n\n const timeout = retryTimeouts[retryCount];\n retryCount++;\n await new Promise((resolve) => setTimeout(resolve, timeout));\n }\n }\n }\n\n /**\n * Closes the connection pool.\n */\n async closeAsync(): Promise<void> {\n if (!this.pool) return;\n await this.pool.end();\n this.pool = null;\n }\n\n /**\n * Gets a new client from the connection pool. The caller MUST call `release()` to\n * release the client, whether or not errors occurred while using\n * `client`. The client can call `done(truthy_value)` to force\n * destruction of the client, but this should not be used except in\n * unusual circumstances.\n */\n async getClientAsync(): Promise<pg.PoolClient> {\n if (!this.pool) {\n throw new Error('Connection pool is not open');\n }\n\n // If we're inside a transaction, we'll reuse the same client to avoid a\n // potential deadlock.\n const client = this.alsClient.getStore() ?? (await this.pool.connect());\n\n // If we're configured to use a particular schema, we'll store whether or\n // not the search path has already been configured for this particular\n // client. If we acquire a client and it's already had its search path\n // set, we can avoid setting it again since the search path will persist\n // for the life of the client.\n //\n // We do this check for each call to `getClient` instead of on\n // `pool.connect` so that we don't have to be really careful about\n // destroying old clients that were created before `setSearchSchema` was\n // called. Instead, we'll just check if the search path matches the\n // currently-desired schema, and if it's a mismatch (or doesn't exist\n // at all), we re-set it for the current client.\n //\n // Note that this accidentally supports changing the search_path on the fly,\n // although that's not something we currently do (or would be likely to do).\n // It does NOT support clearing the existing search schema - e.g.,\n // `setSearchSchema(null)` would not work as you expect. This is fine, as\n // that's not something we ever do in practice.\n const clientSearchSchema = searchSchemaMap.get(client);\n if (this.searchSchema != null && clientSearchSchema !== this.searchSchema) {\n const setSearchPathSql = `SET search_path TO ${escapeIdentifier(this.searchSchema)},public`;\n try {\n await this.queryWithClientAsync(client, setSearchPathSql, {});\n } catch (err) {\n client.release();\n throw err;\n }\n searchSchemaMap.set(client, this.searchSchema);\n }\n\n return client;\n }\n\n /**\n * Performs a query with the given client.\n */\n async queryWithClientAsync(\n client: pg.PoolClient,\n sql: string,\n params: QueryParams,\n ): Promise<pg.QueryResult> {\n this._queryCount += 1;\n debug('queryWithClient()', 'sql:', debugString(sql));\n debug('queryWithClient()', 'params:', debugParams(params));\n const { processedSql, paramsArray } = paramsToArray(sql, params, this.errorOnUnusedParameters);\n try {\n lastQueryMap.set(client, processedSql);\n const result = await client.query(processedSql, paramsArray);\n debug('queryWithClient() success', 'rowCount:', result.rowCount);\n return result;\n } catch (err: any) {\n throw enhanceError(err, sql, params);\n }\n }\n\n /**\n * Performs a query with the given client. Errors if the query returns more\n * than one row.\n */\n async queryWithClientOneRowAsync(\n client: pg.PoolClient,\n sql: string,\n params: QueryParams,\n ): Promise<pg.QueryResult> {\n debug('queryWithClientOneRow()', 'sql:', debugString(sql));\n debug('queryWithClientOneRow()', 'params:', debugParams(params));\n const result = await this.queryWithClientAsync(client, sql, params);\n if (result.rowCount !== 1) {\n throw new PostgresError(`Incorrect rowCount: ${result.rowCount}`, {\n sql,\n sqlParams: params,\n result,\n });\n }\n debug('queryWithClientOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Performs a query with the given client. Errors if the query returns more\n * than one row.\n */\n async queryWithClientZeroOrOneRowAsync(\n client: pg.PoolClient,\n sql: string,\n params: QueryParams,\n ): Promise<QueryResult> {\n debug('queryWithClientZeroOrOneRow()', 'sql:', debugString(sql));\n debug('queryWithClientZeroOrOneRow()', 'params:', debugParams(params));\n const result = await this.queryWithClientAsync(client, sql, params);\n if (result.rowCount == null || result.rowCount > 1) {\n throw new PostgresError(`Incorrect rowCount: ${result.rowCount}`, {\n sql,\n sqlParams: params,\n result,\n });\n }\n debug('queryWithClientZeroOrOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Rolls back the current transaction for the given client.\n */\n async rollbackWithClientAsync(client: pg.PoolClient) {\n debug('rollbackWithClient()');\n // From https://node-postgres.com/features/transactions\n try {\n await client.query('ROLLBACK');\n // Only release the client if we weren't already inside a transaction.\n if (this.alsClient.getStore() === undefined) {\n client.release();\n }\n } catch (err: any) {\n // If there was a problem rolling back the query, something is\n // seriously messed up. Return the error to the release() function to\n // close & remove this client from the pool. If you leave a client in\n // the pool with an unaborted transaction, weird and hard to diagnose\n // problems might happen.\n client.release(err);\n }\n }\n\n /**\n * Begins a new transaction.\n */\n async beginTransactionAsync(): Promise<pg.PoolClient> {\n debug('beginTransaction()');\n const client = await this.getClientAsync();\n try {\n await this.queryWithClientAsync(client, 'START TRANSACTION;', {});\n return client;\n } catch (err) {\n await this.rollbackWithClientAsync(client);\n throw err;\n }\n }\n\n /**\n * Commits the transaction if err is null, otherwise rollbacks the transaction.\n * Also releases the client.\n */\n async endTransactionAsync(client: pg.PoolClient, err: Error | null | undefined) {\n debug('endTransaction()');\n if (err) {\n try {\n await this.rollbackWithClientAsync(client);\n } catch (rollbackErr: any) {\n throw addDataToError(rollbackErr, { prevErr: err, rollback: 'fail' });\n }\n\n // Even though we successfully rolled back the transaction, there was\n // still an error in the first place that necessitated a rollback. Re-throw\n // that error here so that everything downstream of here will know about it.\n throw addDataToError(err, { rollback: 'success' });\n } else {\n try {\n await this.queryWithClientAsync(client, 'COMMIT', {});\n } finally {\n // Only release the client if we aren't nested inside another transaction.\n if (this.alsClient.getStore() === undefined) {\n client.release();\n }\n }\n }\n }\n\n /**\n * Runs the specified function inside of a transaction. The function will\n * receive a database client as an argument, but it can also make queries\n * as usual, and the correct client will be used automatically.\n *\n * The transaction will be rolled back if the function throws an error, and\n * will be committed otherwise.\n */\n async runInTransactionAsync<T>(fn: (client: pg.PoolClient) => Promise<T>): Promise<T> {\n // Check if we're already inside a transaction. If so, we won't start another one,\n // as Postgres doesn't support nested transactions.\n const client = this.alsClient.getStore();\n const isNestedTransaction = client !== undefined;\n const transactionClient = client ?? (await this.beginTransactionAsync());\n\n let result: T;\n try {\n result = await this.alsClient.run(transactionClient, () => fn(transactionClient));\n } catch (err: any) {\n if (!isNestedTransaction) {\n // If we're inside another transaction, we assume that the root transaction\n // will catch this error and roll back the transaction.\n await this.endTransactionAsync(transactionClient, err);\n }\n throw err;\n }\n\n if (!isNestedTransaction) {\n // If we're inside another transaction; don't commit it prematurely. Allow\n // the root transaction to commit it instead.\n //\n // Note that we don't invoke `endTransactionAsync` inside the `try` block\n // because we don't want an error thrown by it to trigger *another* call\n // to `endTransactionAsync` in the `catch` block.\n await this.endTransactionAsync(transactionClient, null);\n }\n\n return result;\n }\n\n /**\n * Executes a query with the specified parameters.\n */\n async queryAsync(sql: string, params: QueryParams): Promise<QueryResult> {\n debug('query()', 'sql:', debugString(sql));\n debug('query()', 'params:', debugParams(params));\n const client = await this.getClientAsync();\n try {\n return await this.queryWithClientAsync(client, sql, params);\n } finally {\n // Only release if we aren't nested in a transaction.\n if (this.alsClient.getStore() === undefined) {\n client.release();\n }\n }\n }\n\n /**\n * Executes a query with the specified parameters. Errors if the query does\n * not return exactly one row.\n */\n async queryOneRowAsync(sql: string, params: QueryParams): Promise<pg.QueryResult> {\n debug('queryOneRow()', 'sql:', debugString(sql));\n debug('queryOneRow()', 'params:', debugParams(params));\n const result = await this.queryAsync(sql, params);\n if (result.rowCount !== 1) {\n throw new PostgresError(`Incorrect rowCount: ${result.rowCount}`, {\n sql,\n sqlParams: params,\n });\n }\n debug('queryOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Executes a query with the specified parameters. Errors if the query\n * returns more than one row.\n */\n async queryZeroOrOneRowAsync(sql: string, params: QueryParams): Promise<pg.QueryResult> {\n debug('queryZeroOrOneRow()', 'sql:', debugString(sql));\n debug('queryZeroOrOneRow()', 'params:', debugParams(params));\n const result = await this.queryAsync(sql, params);\n if (result.rowCount == null || result.rowCount > 1) {\n throw new PostgresError(`Incorrect rowCount: ${result.rowCount}`, {\n sql,\n sqlParams: params,\n });\n }\n debug('queryZeroOrOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Calls the given sproc with the specified parameters.\n */\n async callAsync(functionName: string, params: any[]): Promise<pg.QueryResult> {\n debug('call()', 'function:', functionName);\n debug('call()', 'params:', debugParams(params));\n const placeholders = params.map((_, v) => '$' + (v + 1)).join();\n const sql = `SELECT * FROM ${escapeIdentifier(functionName)}(${placeholders});`;\n const result = await this.queryAsync(sql, params);\n debug('call() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Calls the given sproc with the specified parameters. Errors if the\n * sproc does not return exactly one row.\n */\n async callOneRowAsync(functionName: string, params: any[]): Promise<pg.QueryResult> {\n debug('callOneRow()', 'function:', functionName);\n debug('callOneRow()', 'params:', debugParams(params));\n const result = await this.callAsync(functionName, params);\n if (result.rowCount !== 1) {\n throw new PostgresError('Incorrect rowCount: ' + result.rowCount, {\n functionName,\n sqlParams: params,\n });\n }\n debug('callOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Calls the given sproc with the specified parameters. Errors if the\n * sproc returns more than one row.\n */\n async callZeroOrOneRowAsync(functionName: string, params: any[]): Promise<pg.QueryResult> {\n debug('callZeroOrOneRow()', 'function:', functionName);\n debug('callZeroOrOneRow()', 'params:', debugParams(params));\n const result = await this.callAsync(functionName, params);\n if (result.rowCount == null || result.rowCount > 1) {\n throw new PostgresError('Incorrect rowCount: ' + result.rowCount, {\n functionName,\n sqlParams: params,\n });\n }\n debug('callZeroOrOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Calls a sproc with the specified parameters using a specific client.\n */\n async callWithClientAsync(\n client: pg.PoolClient,\n functionName: string,\n params: any[],\n ): Promise<pg.QueryResult> {\n debug('callWithClient()', 'function:', functionName);\n debug('callWithClient()', 'params:', debugParams(params));\n const placeholders = params.map((_, v) => '$' + (v + 1)).join();\n const sql = `SELECT * FROM ${escapeIdentifier(functionName)}(${placeholders})`;\n const result = await this.queryWithClientAsync(client, sql, params);\n debug('callWithClient() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Calls a sproc with the specified parameters using a specific client.\n * Errors if the sproc does not return exactly one row.\n */\n async callWithClientOneRowAsync(\n client: pg.PoolClient,\n functionName: string,\n params: any[],\n ): Promise<pg.QueryResult> {\n debug('callWithClientOneRow()', 'function:', functionName);\n debug('callWithClientOneRow()', 'params:', debugParams(params));\n const result = await this.callWithClientAsync(client, functionName, params);\n if (result.rowCount !== 1) {\n throw new PostgresError('Incorrect rowCount: ' + result.rowCount, {\n functionName,\n sqlParams: params,\n });\n }\n debug('callWithClientOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Calls a function with the specified parameters using a specific client.\n * Errors if the sproc returns more than one row.\n */\n async callWithClientZeroOrOneRowAsync(\n client: pg.PoolClient,\n functionName: string,\n params: any[],\n ): Promise<pg.QueryResult> {\n debug('callWithClientZeroOrOneRow()', 'function:', functionName);\n debug('callWithClientZeroOrOneRow()', 'params:', debugParams(params));\n const result = await this.callWithClientAsync(client, functionName, params);\n if (result.rowCount == null || result.rowCount > 1) {\n throw new PostgresError('Incorrect rowCount: ' + result.rowCount, {\n functionName,\n sqlParams: params,\n });\n }\n debug('callWithClientZeroOrOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n async queryRows<Model extends z.ZodTypeAny>(sql: string, model: Model): Promise<z.infer<Model>[]>;\n async queryRows<Model extends z.ZodTypeAny>(\n sql: string,\n params: QueryParams,\n model: Model,\n ): Promise<z.infer<Model>[]>;\n /**\n * Executes a query with the specified parameters. Returns an array of rows\n * that conform to the given Zod schema.\n *\n * If the query returns a single column, the return value will be a list of column values.\n */\n async queryRows<Model extends z.ZodTypeAny>(\n sql: string,\n paramsOrSchema: QueryParams | Model,\n maybeModel?: Model,\n ) {\n const params = maybeModel === undefined ? {} : (paramsOrSchema as QueryParams);\n const model = maybeModel === undefined ? (paramsOrSchema as Model) : maybeModel;\n const results = await this.queryAsync(sql, params);\n if (results.fields.length === 1) {\n const columnName = results.fields[0].name;\n const rawData = results.rows.map((row) => row[columnName]);\n return z.array(model).parse(rawData);\n } else {\n return z.array(model).parse(results.rows);\n }\n }\n\n async queryRow<Model extends z.ZodTypeAny>(sql: string, model: Model): Promise<z.infer<Model>>;\n async queryRow<Model extends z.ZodTypeAny>(\n sql: string,\n params: QueryParams,\n model: Model,\n ): Promise<z.infer<Model>>;\n /**\n * Executes a query with the specified parameters. Returns exactly one row that conforms to the given Zod schema.\n *\n * If the query returns a single column, the return value will be the column value itself.\n */\n async queryRow<Model extends z.ZodTypeAny>(\n sql: string,\n paramsOrSchema: QueryParams | Model,\n maybeModel?: Model,\n ) {\n const params = maybeModel === undefined ? {} : (paramsOrSchema as QueryParams);\n const model = maybeModel === undefined ? (paramsOrSchema as Model) : maybeModel;\n const results = await this.queryOneRowAsync(sql, params);\n if (results.fields.length === 1) {\n const columnName = results.fields[0].name;\n return model.parse(results.rows[0][columnName]);\n } else {\n return model.parse(results.rows[0]);\n }\n }\n\n async queryOptionalRow<Model extends z.ZodTypeAny>(\n sql: string,\n model: Model,\n ): Promise<z.infer<Model> | null>;\n async queryOptionalRow<Model extends z.ZodTypeAny>(\n sql: string,\n params: QueryParams,\n model: Model,\n ): Promise<z.infer<Model> | null>;\n /**\n * Executes a query with the specified parameters. Returns either null or a\n * single row that conforms to the given Zod schema, and errors otherwise.\n *\n * If the query returns a single column, the return value will be the column value itself.\n */\n async queryOptionalRow<Model extends z.ZodTypeAny>(\n sql: string,\n paramsOrSchema: QueryParams | Model,\n maybeModel?: Model,\n ) {\n const params = maybeModel === undefined ? {} : (paramsOrSchema as QueryParams);\n const model = maybeModel === undefined ? (paramsOrSchema as Model) : maybeModel;\n const results = await this.queryZeroOrOneRowAsync(sql, params);\n if (results.rows.length === 0) {\n return null;\n } else if (results.fields.length === 1) {\n const columnName = results.fields[0].name;\n return model.parse(results.rows[0][columnName]);\n } else {\n return model.parse(results.rows[0]);\n }\n }\n\n async callRows<Model extends z.ZodTypeAny>(sql: string, model: Model): Promise<z.infer<Model>[]>;\n async callRows<Model extends z.ZodTypeAny>(\n sql: string,\n params: any[],\n model: Model,\n ): Promise<z.infer<Model>[]>;\n /**\n * Calls the given sproc with the specified parameters.\n * Errors if the sproc does not return anything.\n */\n async callRows<Model extends z.ZodTypeAny>(\n sql: string,\n paramsOrSchema: any[] | Model,\n maybeModel?: Model,\n ) {\n const params = maybeModel === undefined ? [] : (paramsOrSchema as any[]);\n const model = maybeModel === undefined ? (paramsOrSchema as Model) : maybeModel;\n const results = await this.callAsync(sql, params);\n if (results.fields.length === 1) {\n const columnName = results.fields[0].name;\n const rawData = results.rows.map((row) => row[columnName]);\n return z.array(model).parse(rawData);\n } else {\n return z.array(model).parse(results.rows);\n }\n }\n\n async callRow<Model extends z.ZodTypeAny>(sql: string, model: Model): Promise<z.infer<Model>>;\n async callRow<Model extends z.ZodTypeAny>(\n sql: string,\n params: any[],\n model: Model,\n ): Promise<z.infer<Model>>;\n /**\n * Calls the given sproc with the specified parameters.\n * Returns exactly one row from the sproc that conforms to the given Zod schema.\n */\n async callRow<Model extends z.ZodTypeAny>(\n sql: string,\n paramsOrSchema: any[] | Model,\n maybeModel?: Model,\n ) {\n const params = maybeModel === undefined ? [] : (paramsOrSchema as any[]);\n const model = maybeModel === undefined ? (paramsOrSchema as Model) : maybeModel;\n const results = await this.callOneRowAsync(sql, params);\n if (results.fields.length === 1) {\n const columnName = results.fields[0].name;\n return model.parse(results.rows[0][columnName]);\n } else {\n return model.parse(results.rows[0]);\n }\n }\n\n async callOptionalRow<Model extends z.ZodTypeAny>(\n sql: string,\n model: Model,\n ): Promise<z.infer<Model> | null>;\n async callOptionalRow<Model extends z.ZodTypeAny>(\n sql: string,\n params: any[],\n model: Model,\n ): Promise<z.infer<Model> | null>;\n /**\n * Calls the given sproc with the specified parameters. Returns either null\n * or a single row that conforms to the given Zod schema.\n */\n async callOptionalRow<Model extends z.ZodTypeAny>(\n sql: string,\n paramsOrSchema: any[] | Model,\n maybeModel?: Model,\n ) {\n const params = maybeModel === undefined ? [] : (paramsOrSchema as any[]);\n const model = maybeModel === undefined ? (paramsOrSchema as Model) : maybeModel;\n const results = await this.callZeroOrOneRowAsync(sql, params);\n if (results.rows.length === 0) {\n return null;\n } else if (results.fields.length === 1) {\n const columnName = results.fields[0].name;\n return model.parse(results.rows[0][columnName]);\n } else {\n return model.parse(results.rows[0]);\n }\n }\n\n /**\n * Returns a {@link Cursor} for the given query. The cursor can be used to\n * read results in batches, which is useful for large result sets.\n */\n private async queryCursorWithClient(\n client: pg.PoolClient,\n sql: string,\n params: QueryParams,\n ): Promise<Cursor> {\n this._queryCount += 1;\n debug('queryCursorWithClient()', 'sql:', debugString(sql));\n debug('queryCursorWithClient()', 'params:', debugParams(params));\n const { processedSql, paramsArray } = paramsToArray(sql, params, this.errorOnUnusedParameters);\n lastQueryMap.set(client, processedSql);\n return client.query(new Cursor(processedSql, paramsArray));\n }\n\n /**\n * Returns an {@link CursorIterator} that can be used to iterate over the\n * results of the query in batches, which is useful for large result sets.\n * Each row will be parsed by the given Zod schema.\n */\n async queryCursor<Model extends z.ZodTypeAny>(\n sql: string,\n params: QueryParams,\n model: Model,\n ): Promise<CursorIterator<z.infer<Model>>> {\n return this.queryCursorInternal(sql, params, model);\n }\n\n private async queryCursorInternal<Model extends z.ZodTypeAny>(\n sql: string,\n params: QueryParams,\n model?: Model,\n ): Promise<CursorIterator<z.infer<Model>>> {\n const client = await this.getClientAsync();\n const cursor = await this.queryCursorWithClient(client, sql, params);\n\n let iterateCalled = false;\n const iterator: CursorIterator<z.infer<Model>> = {\n async *iterate(batchSize: number) {\n // Safety check: if someone calls iterate multiple times, they're\n // definitely doing something wrong.\n if (iterateCalled) {\n throw new Error('iterate() called multiple times');\n }\n iterateCalled = true;\n\n try {\n while (true) {\n const rows = await cursor.read(batchSize);\n if (rows.length === 0) {\n break;\n }\n\n if (model) {\n yield z.array(model).parse(rows);\n } else {\n yield rows;\n }\n }\n } catch (err: any) {\n throw enhanceError(err, sql, params);\n } finally {\n try {\n await cursor.close();\n } finally {\n client.release();\n }\n }\n },\n stream(batchSize: number) {\n const transform = new Transform({\n readableObjectMode: true,\n writableObjectMode: true,\n transform(chunk, _encoding, callback) {\n for (const row of chunk) {\n this.push(row);\n }\n callback();\n },\n });\n\n // TODO: use native `node:stream#compose` once it's stable.\n const generator = iterator.iterate(batchSize);\n const pipe = multipipe(Readable.from(generator), transform);\n\n // When the underlying stream is closed, we need to make sure that the\n // cursor is also closed. We do this by calling `return()` on the generator,\n // which will trigger its `finally` block, which will in turn release\n // the client and close the cursor. The fact that the stream is already\n // closed by this point means that someone reading from the stream will\n // never actually see the `null` value that's returned.\n pipe.once('close', () => {\n generator.return(null);\n });\n\n return pipe;\n },\n };\n return iterator;\n }\n\n /**\n * Set the schema to use for the search path.\n *\n * @param schema The schema name to use (can be \"null\" to unset the search path)\n */\n async setSearchSchema(schema: string) {\n if (schema == null) {\n this.searchSchema = schema;\n return;\n }\n\n await this.queryAsync(`CREATE SCHEMA IF NOT EXISTS ${escapeIdentifier(schema)}`, {});\n // We only set searchSchema after CREATE to avoid the above query() call using searchSchema.\n this.searchSchema = schema;\n }\n\n /**\n * Get the schema that is currently used for the search path.\n *\n * @returns schema in use (may be `null` to indicate no schema)\n */\n getSearchSchema(): string | null {\n return this.searchSchema;\n }\n\n /**\n * Generate, set, and return a random schema name.\n *\n * @param prefix The prefix of the new schema, only the first 28 characters will be used (after lowercasing).\n * @returns The randomly-generated search schema.\n */\n async setRandomSearchSchemaAsync(prefix: string): Promise<string> {\n // truncated prefix (max 28 characters)\n const truncPrefix = prefix.substring(0, 28);\n // timestamp in format YYYY-MM-DDTHH:MM:SS.SSSZ (guaranteed to not exceed 27 characters in the spec)\n const timestamp = new Date().toISOString();\n // random 6-character suffix to avoid clashes (approx 2 billion possible values)\n const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');\n const suffix = Array.from({ length: 6 })\n .map(() => chars[Math.floor(Math.random() * chars.length)])\n .join('');\n\n // Schema is guaranteed to have length at most 63 (= 28 + 1 + 27 + 1 + 6),\n // which is the default PostgreSQL identifier limit.\n // Note that this schema name will need quoting because of characters like ':', '-', etc\n const schema = `${truncPrefix}_${timestamp}_${suffix}`;\n await this.setSearchSchema(schema);\n return schema;\n }\n\n /** The number of established connections. */\n get totalCount() {\n return this.pool?.totalCount ?? 0;\n }\n\n /** The number of idle connections. */\n get idleCount() {\n return this.pool?.idleCount ?? 0;\n }\n\n /** The number of queries waiting for a connection to become available. */\n get waitingCount() {\n return this.pool?.waitingCount ?? 0;\n }\n\n /** The total number of queries that have been executed by this pool. */\n get queryCount() {\n return this._queryCount;\n }\n}\n"]}
1
+ {"version":3,"file":"pool.js","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"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","sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks';\nimport { Readable, Transform } from 'node:stream';\n\nimport debugfn from 'debug';\nimport _ from 'lodash';\nimport multipipe from 'multipipe';\nimport pg, { type QueryResult } from 'pg';\nimport Cursor from 'pg-cursor';\nimport { DatabaseError } from 'pg-protocol';\nimport { z } from 'zod';\n\nexport type QueryParams = Record<string, any> | any[];\n\nexport interface CursorIterator<T> {\n iterate: (batchSize: number) => AsyncGenerator<T[]>;\n stream: (batchSize: number) => NodeJS.ReadWriteStream;\n}\n\nexport interface PostgresPoolConfig extends pg.PoolConfig {\n errorOnUnusedParameters?: boolean;\n}\n\nconst debug = debugfn('@prairielearn/postgres');\nconst lastQueryMap = new WeakMap<pg.PoolClient, string>();\nconst searchSchemaMap = new WeakMap<pg.PoolClient, string>();\n\nfunction addDataToError(err: Error, data: Record<string, any>): Error {\n (err as any).data = {\n ...(err as any).data,\n ...data,\n };\n return err;\n}\n\nexport class PostgresError extends Error {\n public data: Record<string, any>;\n\n constructor(message: string, data: Record<string, any>) {\n super(message);\n this.data = data;\n this.name = 'PostgresError';\n }\n}\n\n/**\n * Formats a string for debugging.\n */\nfunction debugString(s: string): string {\n if (typeof s !== 'string') return 'NOT A STRING';\n s = s.replaceAll('\\n', '\\\\n');\n if (s.length > 78) s = s.slice(0, 75) + '...';\n s = '\"' + s + '\"';\n return s;\n}\n\n/**\n * Formats a set of params for debugging.\n */\nfunction debugParams(params: QueryParams): string {\n let s;\n try {\n s = JSON.stringify(params);\n } catch {\n s = 'CANNOT JSON STRINGIFY';\n }\n return debugString(s);\n}\n\n/**\n * Given an SQL string and params, creates an array of params and an SQL string\n * with any named dollar-sign placeholders replaced with parameters.\n */\nfunction paramsToArray(\n sql: string,\n params: QueryParams,\n errorOnUnusedParameters: boolean,\n): { processedSql: string; paramsArray: any } {\n if (typeof sql !== 'string') throw new Error('SQL must be a string');\n if (Array.isArray(params)) {\n return {\n processedSql: sql,\n paramsArray: params,\n };\n }\n if (params == null || typeof params !== 'object') {\n throw new Error('params must be array or object');\n }\n\n const re = /\\$([-_a-zA-Z0-9]+)/;\n let result;\n let processedSql = '';\n let remainingSql = sql;\n let nParams = 0;\n const map: Record<string, string> = {};\n let paramsArray: any[] = [];\n while ((result = re.exec(remainingSql)) !== null) {\n const v = result[1];\n if (!(v in map)) {\n if (!(v in params)) throw new Error(`Missing parameter: ${v}`);\n if (Array.isArray(params[v])) {\n map[v] = 'ARRAY[' + params[v].map((_, n) => '$' + (n + nParams + 1)).join(',') + ']';\n nParams += params[v].length;\n paramsArray = paramsArray.concat(params[v]);\n } else {\n nParams++;\n map[v] = '$' + nParams;\n paramsArray.push(params[v]);\n }\n }\n processedSql += remainingSql.slice(0, result.index) + map[v];\n remainingSql = remainingSql.slice(result.index + result[0].length);\n }\n processedSql += remainingSql;\n remainingSql = '';\n if (errorOnUnusedParameters) {\n const difference = _.difference(Object.keys(params), Object.keys(map));\n if (difference.length > 0) {\n throw new Error(`Unused parameters in SQL query: ${JSON.stringify(difference)}`);\n }\n }\n return { processedSql, paramsArray };\n}\n\n/**\n * Escapes the given identifier for use in an SQL query. Useful for preventing\n * SQL injection.\n */\nfunction escapeIdentifier(identifier: string): string {\n // Note that as of 2021-06-29 escapeIdentifier() is undocumented. See:\n // https://github.com/brianc/node-postgres/pull/396\n // https://github.com/brianc/node-postgres/issues/1978\n // https://www.postgresql.org/docs/current/sql-syntax-lexical.html\n return pg.Client.prototype.escapeIdentifier(identifier);\n}\n\nfunction enhanceError(err: Error, sql: string, params: QueryParams): Error {\n // Copy the error so we don't end up with a circular reference in the\n // final error.\n const sqlError = { ...err };\n\n // `message` is a non-enumerable property, so we need to copy it manually to\n // the error object.\n sqlError.message = err.message;\n\n const errorHasPosition = err instanceof DatabaseError && err.position != null;\n\n return addDataToError(err, {\n sqlError,\n // If the error has a `position` field, we need to use the processed source\n // (where e.g. `$foobar` has been replaced with `$1`) so that the position\n // is accurate.\n sql: errorHasPosition ? paramsToArray(sql, params, false).processedSql : sql,\n sqlParams: params,\n });\n}\n\nexport class PostgresPool {\n /** The pool from which clients will be acquired. */\n private pool: pg.Pool | null = null;\n /**\n * We use this to propagate the client associated with the current transaction\n * to any nested queries. In the past, we had some nasty bugs associated with\n * the fact that we tried to acquire new clients inside of transactions, which\n * ultimately lead to a deadlock.\n */\n private alsClient = new AsyncLocalStorage<pg.PoolClient>();\n private searchSchema: string | null = null;\n /** Tracks the total number of queries executed by this pool. */\n private _queryCount = 0;\n private errorOnUnusedParameters = false;\n\n /**\n * Creates a new connection pool and attempts to connect to the database.\n */\n async initAsync(\n pgConfig: PostgresPoolConfig,\n idleErrorHandler: (error: Error, client: pg.PoolClient) => void,\n ): Promise<void> {\n this.errorOnUnusedParameters = pgConfig.errorOnUnusedParameters ?? false;\n this.pool = new pg.Pool(pgConfig);\n this.pool.on('error', function (err, client) {\n const lastQuery = lastQueryMap.get(client);\n idleErrorHandler(addDataToError(err, { lastQuery }), client);\n });\n this.pool.on('connect', (client) => {\n client.on('error', (err) => {\n const lastQuery = lastQueryMap.get(client);\n idleErrorHandler(addDataToError(err, { lastQuery }), client);\n });\n });\n this.pool.on('remove', (client) => {\n // This shouldn't be necessary, as `pg` currently allows clients to be\n // garbage collected after they're removed. However, if `pg` someday\n // starts reusing client objects across difference connections, this\n // will ensure that we re-set the search path when the client reconnects.\n searchSchemaMap.delete(client);\n });\n\n // Attempt to connect to the database so that we can fail quickly if\n // something isn't configured correctly.\n let retryCount = 0;\n const retryTimeouts = [500, 1000, 2000, 5000, 10000];\n while (retryCount <= retryTimeouts.length) {\n try {\n const client = await this.pool.connect();\n client.release();\n return;\n } catch (err: any) {\n if (retryCount === retryTimeouts.length) {\n throw new Error(\n `Could not connect to Postgres after ${retryTimeouts.length} attempts: ${err.message}`,\n );\n }\n\n const timeout = retryTimeouts[retryCount];\n retryCount++;\n await new Promise((resolve) => setTimeout(resolve, timeout));\n }\n }\n }\n\n /**\n * Closes the connection pool.\n */\n async closeAsync(): Promise<void> {\n if (!this.pool) return;\n await this.pool.end();\n this.pool = null;\n }\n\n /**\n * Gets a new client from the connection pool. The caller MUST call `release()` to\n * release the client, whether or not errors occurred while using\n * `client`. The client can call `done(truthy_value)` to force\n * destruction of the client, but this should not be used except in\n * unusual circumstances.\n */\n async getClientAsync(): Promise<pg.PoolClient> {\n if (!this.pool) {\n throw new Error('Connection pool is not open');\n }\n\n // If we're inside a transaction, we'll reuse the same client to avoid a\n // potential deadlock.\n const client = this.alsClient.getStore() ?? (await this.pool.connect());\n\n // If we're configured to use a particular schema, we'll store whether or\n // not the search path has already been configured for this particular\n // client. If we acquire a client and it's already had its search path\n // set, we can avoid setting it again since the search path will persist\n // for the life of the client.\n //\n // We do this check for each call to `getClient` instead of on\n // `pool.connect` so that we don't have to be really careful about\n // destroying old clients that were created before `setSearchSchema` was\n // called. Instead, we'll just check if the search path matches the\n // currently-desired schema, and if it's a mismatch (or doesn't exist\n // at all), we re-set it for the current client.\n //\n // Note that this accidentally supports changing the search_path on the fly,\n // although that's not something we currently do (or would be likely to do).\n // It does NOT support clearing the existing search schema - e.g.,\n // `setSearchSchema(null)` would not work as you expect. This is fine, as\n // that's not something we ever do in practice.\n const clientSearchSchema = searchSchemaMap.get(client);\n if (this.searchSchema != null && clientSearchSchema !== this.searchSchema) {\n const setSearchPathSql = `SET search_path TO ${escapeIdentifier(this.searchSchema)},public`;\n try {\n await this.queryWithClientAsync(client, setSearchPathSql, {});\n } catch (err) {\n client.release();\n throw err;\n }\n searchSchemaMap.set(client, this.searchSchema);\n }\n\n return client;\n }\n\n /**\n * Performs a query with the given client.\n */\n async queryWithClientAsync(\n client: pg.PoolClient,\n sql: string,\n params: QueryParams,\n ): Promise<pg.QueryResult> {\n this._queryCount += 1;\n debug('queryWithClient()', 'sql:', debugString(sql));\n debug('queryWithClient()', 'params:', debugParams(params));\n const { processedSql, paramsArray } = paramsToArray(sql, params, this.errorOnUnusedParameters);\n try {\n lastQueryMap.set(client, processedSql);\n const result = await client.query(processedSql, paramsArray);\n debug('queryWithClient() success', 'rowCount:', result.rowCount);\n return result;\n } catch (err: any) {\n throw enhanceError(err, sql, params);\n }\n }\n\n /**\n * Performs a query with the given client. Errors if the query returns more\n * than one row.\n */\n async queryWithClientOneRowAsync(\n client: pg.PoolClient,\n sql: string,\n params: QueryParams,\n ): Promise<pg.QueryResult> {\n debug('queryWithClientOneRow()', 'sql:', debugString(sql));\n debug('queryWithClientOneRow()', 'params:', debugParams(params));\n const result = await this.queryWithClientAsync(client, sql, params);\n if (result.rowCount !== 1) {\n throw new PostgresError(`Incorrect rowCount: ${result.rowCount}`, {\n sql,\n sqlParams: params,\n result,\n });\n }\n debug('queryWithClientOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Performs a query with the given client. Errors if the query returns more\n * than one row.\n */\n async queryWithClientZeroOrOneRowAsync(\n client: pg.PoolClient,\n sql: string,\n params: QueryParams,\n ): Promise<QueryResult> {\n debug('queryWithClientZeroOrOneRow()', 'sql:', debugString(sql));\n debug('queryWithClientZeroOrOneRow()', 'params:', debugParams(params));\n const result = await this.queryWithClientAsync(client, sql, params);\n if (result.rowCount == null || result.rowCount > 1) {\n throw new PostgresError(`Incorrect rowCount: ${result.rowCount}`, {\n sql,\n sqlParams: params,\n result,\n });\n }\n debug('queryWithClientZeroOrOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Rolls back the current transaction for the given client.\n */\n async rollbackWithClientAsync(client: pg.PoolClient) {\n debug('rollbackWithClient()');\n // From https://node-postgres.com/features/transactions\n try {\n await client.query('ROLLBACK');\n // Only release the client if we weren't already inside a transaction.\n if (this.alsClient.getStore() === undefined) {\n client.release();\n }\n } catch (err: any) {\n // If there was a problem rolling back the query, something is\n // seriously messed up. Return the error to the release() function to\n // close & remove this client from the pool. If you leave a client in\n // the pool with an unaborted transaction, weird and hard to diagnose\n // problems might happen.\n client.release(err);\n }\n }\n\n /**\n * Begins a new transaction.\n */\n async beginTransactionAsync(): Promise<pg.PoolClient> {\n debug('beginTransaction()');\n const client = await this.getClientAsync();\n try {\n await this.queryWithClientAsync(client, 'START TRANSACTION;', {});\n return client;\n } catch (err) {\n await this.rollbackWithClientAsync(client);\n throw err;\n }\n }\n\n /**\n * Commits the transaction if err is null, otherwise rollbacks the transaction.\n * Also releases the client.\n */\n async endTransactionAsync(client: pg.PoolClient, err: Error | null | undefined) {\n debug('endTransaction()');\n if (err) {\n try {\n await this.rollbackWithClientAsync(client);\n } catch (rollbackErr: any) {\n throw addDataToError(rollbackErr, { prevErr: err, rollback: 'fail' });\n }\n\n // Even though we successfully rolled back the transaction, there was\n // still an error in the first place that necessitated a rollback. Re-throw\n // that error here so that everything downstream of here will know about it.\n throw addDataToError(err, { rollback: 'success' });\n } else {\n try {\n await this.queryWithClientAsync(client, 'COMMIT', {});\n } finally {\n // Only release the client if we aren't nested inside another transaction.\n if (this.alsClient.getStore() === undefined) {\n client.release();\n }\n }\n }\n }\n\n /**\n * Runs the specified function inside of a transaction. The function will\n * receive a database client as an argument, but it can also make queries\n * as usual, and the correct client will be used automatically.\n *\n * The transaction will be rolled back if the function throws an error, and\n * will be committed otherwise.\n */\n async runInTransactionAsync<T>(fn: (client: pg.PoolClient) => Promise<T>): Promise<T> {\n // Check if we're already inside a transaction. If so, we won't start another one,\n // as Postgres doesn't support nested transactions.\n const client = this.alsClient.getStore();\n const isNestedTransaction = client !== undefined;\n const transactionClient = client ?? (await this.beginTransactionAsync());\n\n let result: T;\n try {\n result = await this.alsClient.run(transactionClient, () => fn(transactionClient));\n } catch (err: any) {\n if (!isNestedTransaction) {\n // If we're inside another transaction, we assume that the root transaction\n // will catch this error and roll back the transaction.\n await this.endTransactionAsync(transactionClient, err);\n }\n throw err;\n }\n\n if (!isNestedTransaction) {\n // If we're inside another transaction; don't commit it prematurely. Allow\n // the root transaction to commit it instead.\n //\n // Note that we don't invoke `endTransactionAsync` inside the `try` block\n // because we don't want an error thrown by it to trigger *another* call\n // to `endTransactionAsync` in the `catch` block.\n await this.endTransactionAsync(transactionClient, null);\n }\n\n return result;\n }\n\n /**\n * Executes a query with the specified parameters.\n *\n * @deprecated Use {@link execute} instead.\n *\n * Using the return value of this function directly is not recommended. Instead, use\n * {@link queryRows}, {@link queryRow}, or {@link queryOptionalRow}.\n */\n async queryAsync(sql: string, params: QueryParams): Promise<QueryResult> {\n debug('query()', 'sql:', debugString(sql));\n debug('query()', 'params:', debugParams(params));\n const client = await this.getClientAsync();\n try {\n return await this.queryWithClientAsync(client, sql, params);\n } finally {\n // Only release if we aren't nested in a transaction.\n if (this.alsClient.getStore() === undefined) {\n client.release();\n }\n }\n }\n\n /**\n * Executes a query with the specified parameters. Errors if the query does\n * not return exactly one row.\n *\n * @deprecated Use {@link executeRow} or {@link queryRow} instead.\n */\n async queryOneRowAsync(sql: string, params: QueryParams): Promise<pg.QueryResult> {\n debug('queryOneRow()', 'sql:', debugString(sql));\n debug('queryOneRow()', 'params:', debugParams(params));\n const result = await this.queryAsync(sql, params);\n if (result.rowCount !== 1) {\n throw new PostgresError(`Incorrect rowCount: ${result.rowCount}`, {\n sql,\n sqlParams: params,\n });\n }\n debug('queryOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Executes a query with the specified parameters. Errors if the query\n * returns more than one row.\n */\n async queryZeroOrOneRowAsync(sql: string, params: QueryParams): Promise<pg.QueryResult> {\n debug('queryZeroOrOneRow()', 'sql:', debugString(sql));\n debug('queryZeroOrOneRow()', 'params:', debugParams(params));\n const result = await this.queryAsync(sql, params);\n if (result.rowCount == null || result.rowCount > 1) {\n throw new PostgresError(`Incorrect rowCount: ${result.rowCount}`, {\n sql,\n sqlParams: params,\n });\n }\n debug('queryZeroOrOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Calls the given sproc with the specified parameters.\n */\n async callAsync(functionName: string, params: any[]): Promise<pg.QueryResult> {\n debug('call()', 'function:', functionName);\n debug('call()', 'params:', debugParams(params));\n const placeholders = params.map((_, v) => '$' + (v + 1)).join(',');\n const sql = `SELECT * FROM ${escapeIdentifier(functionName)}(${placeholders});`;\n const result = await this.queryAsync(sql, params);\n debug('call() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Calls the given sproc with the specified parameters. Errors if the\n * sproc does not return exactly one row.\n */\n async callOneRowAsync(functionName: string, params: any[]): Promise<pg.QueryResult> {\n debug('callOneRow()', 'function:', functionName);\n debug('callOneRow()', 'params:', debugParams(params));\n const result = await this.callAsync(functionName, params);\n if (result.rowCount !== 1) {\n throw new PostgresError('Incorrect rowCount: ' + result.rowCount, {\n functionName,\n sqlParams: params,\n });\n }\n debug('callOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Calls the given sproc with the specified parameters. Errors if the\n * sproc returns more than one row.\n */\n async callZeroOrOneRowAsync(functionName: string, params: any[]): Promise<pg.QueryResult> {\n debug('callZeroOrOneRow()', 'function:', functionName);\n debug('callZeroOrOneRow()', 'params:', debugParams(params));\n const result = await this.callAsync(functionName, params);\n if (result.rowCount == null || result.rowCount > 1) {\n throw new PostgresError('Incorrect rowCount: ' + result.rowCount, {\n functionName,\n sqlParams: params,\n });\n }\n debug('callZeroOrOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Calls a sproc with the specified parameters using a specific client.\n */\n async callWithClientAsync(\n client: pg.PoolClient,\n functionName: string,\n params: any[],\n ): Promise<pg.QueryResult> {\n debug('callWithClient()', 'function:', functionName);\n debug('callWithClient()', 'params:', debugParams(params));\n const placeholders = params.map((_, v) => '$' + (v + 1)).join(',');\n const sql = `SELECT * FROM ${escapeIdentifier(functionName)}(${placeholders})`;\n const result = await this.queryWithClientAsync(client, sql, params);\n debug('callWithClient() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Calls a sproc with the specified parameters using a specific client.\n * Errors if the sproc does not return exactly one row.\n */\n async callWithClientOneRowAsync(\n client: pg.PoolClient,\n functionName: string,\n params: any[],\n ): Promise<pg.QueryResult> {\n debug('callWithClientOneRow()', 'function:', functionName);\n debug('callWithClientOneRow()', 'params:', debugParams(params));\n const result = await this.callWithClientAsync(client, functionName, params);\n if (result.rowCount !== 1) {\n throw new PostgresError('Incorrect rowCount: ' + result.rowCount, {\n functionName,\n sqlParams: params,\n });\n }\n debug('callWithClientOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n /**\n * Calls a function with the specified parameters using a specific client.\n * Errors if the sproc returns more than one row.\n */\n async callWithClientZeroOrOneRowAsync(\n client: pg.PoolClient,\n functionName: string,\n params: any[],\n ): Promise<pg.QueryResult> {\n debug('callWithClientZeroOrOneRow()', 'function:', functionName);\n debug('callWithClientZeroOrOneRow()', 'params:', debugParams(params));\n const result = await this.callWithClientAsync(client, functionName, params);\n if (result.rowCount == null || result.rowCount > 1) {\n throw new PostgresError('Incorrect rowCount: ' + result.rowCount, {\n functionName,\n sqlParams: params,\n });\n }\n debug('callWithClientZeroOrOneRow() success', 'rowCount:', result.rowCount);\n return result;\n }\n\n async queryRows<Model extends z.ZodTypeAny>(sql: string, model: Model): Promise<z.infer<Model>[]>;\n async queryRows<Model extends z.ZodTypeAny>(\n sql: string,\n params: QueryParams,\n model: Model,\n ): Promise<z.infer<Model>[]>;\n /**\n * Executes a query with the specified parameters. Returns an array of rows\n * that conform to the given Zod schema.\n *\n * If the query returns a single column, the return value will be a list of column values.\n */\n async queryRows<Model extends z.ZodTypeAny>(\n sql: string,\n paramsOrSchema: QueryParams | Model,\n maybeModel?: Model,\n ) {\n const params = maybeModel === undefined ? {} : (paramsOrSchema as QueryParams);\n const model = maybeModel === undefined ? (paramsOrSchema as Model) : maybeModel;\n const results = await this.queryAsync(sql, params);\n if (results.fields.length === 1) {\n const columnName = results.fields[0].name;\n const rawData = results.rows.map((row) => row[columnName]);\n return z.array(model).parse(rawData);\n } else {\n return z.array(model).parse(results.rows);\n }\n }\n\n async queryRow<Model extends z.ZodTypeAny>(sql: string, model: Model): Promise<z.infer<Model>>;\n async queryRow<Model extends z.ZodTypeAny>(\n sql: string,\n params: QueryParams,\n model: Model,\n ): Promise<z.infer<Model>>;\n /**\n * Executes a query with the specified parameters. Returns exactly one row that conforms to the given Zod schema.\n *\n * If the query returns a single column, the return value will be the column value itself.\n */\n async queryRow<Model extends z.ZodTypeAny>(\n sql: string,\n paramsOrSchema: QueryParams | Model,\n maybeModel?: Model,\n ) {\n const params = maybeModel === undefined ? {} : (paramsOrSchema as QueryParams);\n const model = maybeModel === undefined ? (paramsOrSchema as Model) : maybeModel;\n const results = await this.queryOneRowAsync(sql, params);\n if (results.fields.length === 1) {\n const columnName = results.fields[0].name;\n return model.parse(results.rows[0][columnName]);\n } else {\n return model.parse(results.rows[0]);\n }\n }\n\n async queryOptionalRow<Model extends z.ZodTypeAny>(\n sql: string,\n model: Model,\n ): Promise<z.infer<Model> | null>;\n async queryOptionalRow<Model extends z.ZodTypeAny>(\n sql: string,\n params: QueryParams,\n model: Model,\n ): Promise<z.infer<Model> | null>;\n /**\n * Executes a query with the specified parameters. Returns either null or a\n * single row that conforms to the given Zod schema, and errors otherwise.\n *\n * If the query returns a single column, the return value will be the column value itself.\n */\n async queryOptionalRow<Model extends z.ZodTypeAny>(\n sql: string,\n paramsOrSchema: QueryParams | Model,\n maybeModel?: Model,\n ) {\n const params = maybeModel === undefined ? {} : (paramsOrSchema as QueryParams);\n const model = maybeModel === undefined ? (paramsOrSchema as Model) : maybeModel;\n const results = await this.queryZeroOrOneRowAsync(sql, params);\n if (results.rows.length === 0) {\n return null;\n } else if (results.fields.length === 1) {\n const columnName = results.fields[0].name;\n return model.parse(results.rows[0][columnName]);\n } else {\n return model.parse(results.rows[0]);\n }\n }\n\n async callRows<Model extends z.ZodTypeAny>(sql: string, model: Model): Promise<z.infer<Model>[]>;\n async callRows<Model extends z.ZodTypeAny>(\n sql: string,\n params: any[],\n model: Model,\n ): Promise<z.infer<Model>[]>;\n /**\n * Calls the given sproc with the specified parameters.\n * Errors if the sproc does not return anything.\n */\n async callRows<Model extends z.ZodTypeAny>(\n sql: string,\n paramsOrSchema: any[] | Model,\n maybeModel?: Model,\n ) {\n const params = maybeModel === undefined ? [] : (paramsOrSchema as any[]);\n const model = maybeModel === undefined ? (paramsOrSchema as Model) : maybeModel;\n const results = await this.callAsync(sql, params);\n if (results.fields.length === 1) {\n const columnName = results.fields[0].name;\n const rawData = results.rows.map((row) => row[columnName]);\n return z.array(model).parse(rawData);\n } else {\n return z.array(model).parse(results.rows);\n }\n }\n\n async callRow<Model extends z.ZodTypeAny>(sql: string, model: Model): Promise<z.infer<Model>>;\n async callRow<Model extends z.ZodTypeAny>(\n sql: string,\n params: any[],\n model: Model,\n ): Promise<z.infer<Model>>;\n /**\n * Calls the given sproc with the specified parameters.\n * Returns exactly one row from the sproc that conforms to the given Zod schema.\n */\n async callRow<Model extends z.ZodTypeAny>(\n sql: string,\n paramsOrSchema: any[] | Model,\n maybeModel?: Model,\n ) {\n const params = maybeModel === undefined ? [] : (paramsOrSchema as any[]);\n const model = maybeModel === undefined ? (paramsOrSchema as Model) : maybeModel;\n const results = await this.callOneRowAsync(sql, params);\n if (results.fields.length === 1) {\n const columnName = results.fields[0].name;\n return model.parse(results.rows[0][columnName]);\n } else {\n return model.parse(results.rows[0]);\n }\n }\n\n async callOptionalRow<Model extends z.ZodTypeAny>(\n sql: string,\n model: Model,\n ): Promise<z.infer<Model> | null>;\n async callOptionalRow<Model extends z.ZodTypeAny>(\n sql: string,\n params: any[],\n model: Model,\n ): Promise<z.infer<Model> | null>;\n /**\n * Calls the given sproc with the specified parameters. Returns either null\n * or a single row that conforms to the given Zod schema.\n */\n async callOptionalRow<Model extends z.ZodTypeAny>(\n sql: string,\n paramsOrSchema: any[] | Model,\n maybeModel?: Model,\n ) {\n const params = maybeModel === undefined ? [] : (paramsOrSchema as any[]);\n const model = maybeModel === undefined ? (paramsOrSchema as Model) : maybeModel;\n const results = await this.callZeroOrOneRowAsync(sql, params);\n if (results.rows.length === 0) {\n return null;\n } else if (results.fields.length === 1) {\n const columnName = results.fields[0].name;\n return model.parse(results.rows[0][columnName]);\n } else {\n return model.parse(results.rows[0]);\n }\n }\n\n /**\n * Executes a query with the specified parameters. Returns the number of rows affected.\n */\n async execute(sql: string, params: QueryParams = {}): Promise<number> {\n const result = await this.queryAsync(sql, params);\n return result.rowCount ?? 0;\n }\n\n /**\n * Executes a query with the specified parameter, and errors if the query doesn't return exactly one row.\n */\n async executeRow(sql: string, params: QueryParams = {}) {\n const rowCount = await this.execute(sql, params);\n if (rowCount !== 1) {\n throw new PostgresError('Incorrect rowCount: ' + rowCount, {\n sql,\n sqlParams: params,\n });\n }\n }\n\n /**\n * Returns a {@link Cursor} for the given query. The cursor can be used to\n * read results in batches, which is useful for large result sets.\n */\n private async queryCursorWithClient(\n client: pg.PoolClient,\n sql: string,\n params: QueryParams,\n ): Promise<Cursor> {\n this._queryCount += 1;\n debug('queryCursorWithClient()', 'sql:', debugString(sql));\n debug('queryCursorWithClient()', 'params:', debugParams(params));\n const { processedSql, paramsArray } = paramsToArray(sql, params, this.errorOnUnusedParameters);\n lastQueryMap.set(client, processedSql);\n return client.query(new Cursor(processedSql, paramsArray));\n }\n\n /**\n * Returns an {@link CursorIterator} that can be used to iterate over the\n * results of the query in batches, which is useful for large result sets.\n * Each row will be parsed by the given Zod schema.\n */\n async queryCursor<Model extends z.ZodTypeAny>(\n sql: string,\n params: QueryParams,\n model: Model,\n ): Promise<CursorIterator<z.infer<Model>>> {\n return this.queryCursorInternal(sql, params, model);\n }\n\n private async queryCursorInternal<Model extends z.ZodTypeAny>(\n sql: string,\n params: QueryParams,\n model?: Model,\n ): Promise<CursorIterator<z.infer<Model>>> {\n const client = await this.getClientAsync();\n const cursor = await this.queryCursorWithClient(client, sql, params);\n\n let iterateCalled = false;\n const iterator: CursorIterator<z.infer<Model>> = {\n async *iterate(batchSize: number) {\n // Safety check: if someone calls iterate multiple times, they're\n // definitely doing something wrong.\n if (iterateCalled) {\n throw new Error('iterate() called multiple times');\n }\n iterateCalled = true;\n\n try {\n while (true) {\n const rows = await cursor.read(batchSize);\n if (rows.length === 0) {\n break;\n }\n\n if (model) {\n yield z.array(model).parse(rows);\n } else {\n yield rows;\n }\n }\n } catch (err: any) {\n throw enhanceError(err, sql, params);\n } finally {\n try {\n await cursor.close();\n } finally {\n client.release();\n }\n }\n },\n stream(batchSize: number) {\n const transform = new Transform({\n readableObjectMode: true,\n writableObjectMode: true,\n transform(chunk, _encoding, callback) {\n for (const row of chunk) {\n this.push(row);\n }\n callback();\n },\n });\n\n // TODO: use native `node:stream#compose` once it's stable.\n const generator = iterator.iterate(batchSize);\n const pipe = multipipe(Readable.from(generator), transform);\n\n // When the underlying stream is closed, we need to make sure that the\n // cursor is also closed. We do this by calling `return()` on the generator,\n // which will trigger its `finally` block, which will in turn release\n // the client and close the cursor. The fact that the stream is already\n // closed by this point means that someone reading from the stream will\n // never actually see the `null` value that's returned.\n pipe.once('close', () => {\n generator.return(null);\n });\n\n return pipe;\n },\n };\n return iterator;\n }\n\n /**\n * Set the schema to use for the search path.\n *\n * @param schema The schema name to use (can be \"null\" to unset the search path)\n */\n async setSearchSchema(schema: string | null) {\n if (schema == null) {\n this.searchSchema = schema;\n return;\n }\n\n await this.queryAsync(`CREATE SCHEMA IF NOT EXISTS ${escapeIdentifier(schema)}`, {});\n // We only set searchSchema after CREATE to avoid the above query() call using searchSchema.\n this.searchSchema = schema;\n }\n\n /**\n * Get the schema that is currently used for the search path.\n *\n * @returns schema in use (may be `null` to indicate no schema)\n */\n getSearchSchema(): string | null {\n return this.searchSchema;\n }\n\n /**\n * Generate, set, and return a random schema name.\n *\n * @param prefix The prefix of the new schema, only the first 28 characters will be used (after lowercasing).\n * @returns The randomly-generated search schema.\n */\n async setRandomSearchSchemaAsync(prefix: string): Promise<string> {\n // truncated prefix (max 28 characters)\n const truncPrefix = prefix.slice(0, 28);\n // timestamp in format YYYY-MM-DDTHH:MM:SS.SSSZ (guaranteed to not exceed 27 characters in the spec)\n const timestamp = new Date().toISOString();\n // random 6-character suffix to avoid clashes (approx 2 billion possible values)\n const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');\n const suffix = Array.from({ length: 6 })\n .map(() => chars[Math.floor(Math.random() * chars.length)])\n .join('');\n\n // Schema is guaranteed to have length at most 63 (= 28 + 1 + 27 + 1 + 6),\n // which is the default PostgreSQL identifier limit.\n // Note that this schema name will need quoting because of characters like ':', '-', etc\n const schema = `${truncPrefix}_${timestamp}_${suffix}`;\n await this.setSearchSchema(schema);\n return schema;\n }\n\n /** The number of established connections. */\n get totalCount() {\n return this.pool?.totalCount ?? 0;\n }\n\n /** The number of idle connections. */\n get idleCount() {\n return this.pool?.idleCount ?? 0;\n }\n\n /** The number of queries waiting for a connection to become available. */\n get waitingCount() {\n return this.pool?.waitingCount ?? 0;\n }\n\n /** The total number of queries that have been executed by this pool. */\n get queryCount() {\n return this._queryCount;\n }\n}\n"]}
@@ -31,7 +31,7 @@ async function createDatabase(options, { dropExistingDatabase = true, configureP
31
31
  max: 10,
32
32
  idleTimeoutMillis: 30000,
33
33
  errorOnUnusedParameters: true,
34
- ...(options.poolConfig ?? {}),
34
+ ...options.poolConfig,
35
35
  }, (err) => {
36
36
  throw err;
37
37
  });
@@ -1 +1 @@
1
- {"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import pg from 'pg';\n\nimport * as defaultPool from './default-pool.js';\n\nconst POSTGRES_USER = 'postgres';\nconst POSTGRES_HOST = 'localhost';\nconst POSTGRES_DATABASE = 'postgres';\n\nexport interface PostgresTestUtilsOptions {\n database: string;\n user?: string;\n host?: string;\n poolConfig?: Pick<pg.PoolConfig, 'max' | 'idleTimeoutMillis'>;\n defaultDatabase?: string;\n prepareAfterReset?: (client: pg.Client) => Promise<void>;\n}\n\ninterface CreateDatabaseOptions {\n dropExistingDatabase?: boolean;\n database?: string;\n templateDatabase?: string;\n configurePool?: boolean;\n prepare?: (client: pg.Client) => Promise<void>;\n}\n\ninterface DropDatabaseOptions {\n database?: string;\n force?: boolean;\n closePool?: boolean;\n}\n\nasync function createDatabase(\n options: PostgresTestUtilsOptions,\n {\n dropExistingDatabase = true,\n configurePool = true,\n database,\n templateDatabase,\n prepare,\n }: CreateDatabaseOptions = {},\n): Promise<void> {\n const client = new pg.Client({\n ...getPoolConfig(options),\n database: options.defaultDatabase ?? POSTGRES_DATABASE,\n });\n await client.connect();\n\n const escapedDatabase = client.escapeIdentifier(\n database ?? getDatabaseNameForCurrentMochaWorker(options.database),\n );\n if (dropExistingDatabase ?? true) {\n await client.query(`DROP DATABASE IF EXISTS ${escapedDatabase}`);\n }\n\n if (templateDatabase) {\n const escapedTemplateDatabase = client.escapeIdentifier(templateDatabase);\n await client.query(`CREATE DATABASE ${escapedDatabase} TEMPLATE ${escapedTemplateDatabase}`);\n } else {\n await client.query(`CREATE DATABASE ${escapedDatabase}`);\n }\n\n await client.end();\n\n await prepare?.(client);\n\n if (configurePool) {\n await defaultPool.initAsync(\n {\n user: options.user ?? POSTGRES_USER,\n host: options.host ?? POSTGRES_HOST,\n database: getDatabaseNameForCurrentMochaWorker(options.database),\n // Offer sensible default, but these can be overridden by `options.poolConfig`.\n max: 10,\n idleTimeoutMillis: 30000,\n errorOnUnusedParameters: true,\n ...(options.poolConfig ?? {}),\n },\n (err) => {\n throw err;\n },\n );\n }\n}\n\nasync function resetDatabase(options: PostgresTestUtilsOptions): Promise<void> {\n const client = new pg.Client(getPoolConfig(options));\n await client.connect();\n await client.query(`\n DO\n $func$\n BEGIN\n EXECUTE (\n SELECT 'TRUNCATE TABLE ' || string_agg(oid::regclass::text, ', ') || ' RESTART IDENTITY CASCADE'\n FROM pg_class\n WHERE relkind = 'r'\n AND relnamespace = 'public'::regnamespace\n );\n END\n $func$;\n `);\n await options.prepareAfterReset?.(client);\n await client.end();\n}\n\nasync function dropDatabase(\n options: PostgresTestUtilsOptions,\n { closePool = true, force = false, database }: DropDatabaseOptions = {},\n): Promise<void> {\n if (closePool) {\n await defaultPool.closeAsync();\n }\n\n const databaseName = database ?? getDatabaseNameForCurrentMochaWorker(options.database);\n if ('PL_KEEP_TEST_DB' in process.env && !force) {\n // eslint-disable-next-line no-console\n console.log(`PL_KEEP_TEST_DB environment variable set, not dropping database ${databaseName}`);\n return;\n }\n\n const client = new pg.Client({\n ...getPoolConfig(options),\n database: options.defaultDatabase ?? POSTGRES_DATABASE,\n });\n await client.connect();\n await client.query(`DROP DATABASE IF EXISTS ${client.escapeIdentifier(databaseName)}`);\n await client.end();\n}\n\nfunction getDatabaseNameForCurrentMochaWorker(namespace: string): string {\n const workerId = process.env.MOCHA_WORKER_ID ?? process.env.VITEST_POOL_ID ?? '1';\n return `${namespace}_${workerId}`;\n}\n\nfunction getPoolConfig(options: PostgresTestUtilsOptions): pg.PoolConfig {\n return {\n user: options.user ?? POSTGRES_USER,\n host: options.host ?? POSTGRES_HOST,\n database: getDatabaseNameForCurrentMochaWorker(options.database),\n };\n}\n\nexport interface PostgresTestUtils {\n createDatabase: (options?: CreateDatabaseOptions) => Promise<void>;\n resetDatabase: () => Promise<void>;\n dropDatabase: (options?: DropDatabaseOptions) => Promise<void>;\n getDatabaseNameForCurrentMochaWorker: () => string;\n getPoolConfig: () => pg.PoolConfig;\n}\n\nexport function makePostgresTestUtils(options: PostgresTestUtilsOptions): PostgresTestUtils {\n return {\n createDatabase: (createOptions?: CreateDatabaseOptions) =>\n createDatabase(options, createOptions),\n resetDatabase: () => resetDatabase(options),\n dropDatabase: (dropOptions?: DropDatabaseOptions) => dropDatabase(options, dropOptions),\n getDatabaseNameForCurrentMochaWorker: () =>\n getDatabaseNameForCurrentMochaWorker(options.database),\n getPoolConfig: () => getPoolConfig(options),\n };\n}\n"]}
1
+ {"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import pg from 'pg';\n\nimport * as defaultPool from './default-pool.js';\n\nconst POSTGRES_USER = 'postgres';\nconst POSTGRES_HOST = 'localhost';\nconst POSTGRES_DATABASE = 'postgres';\n\nexport interface PostgresTestUtilsOptions {\n database: string;\n user?: string;\n host?: string;\n poolConfig?: Pick<pg.PoolConfig, 'max' | 'idleTimeoutMillis'>;\n defaultDatabase?: string;\n prepareAfterReset?: (client: pg.Client) => Promise<void>;\n}\n\ninterface CreateDatabaseOptions {\n dropExistingDatabase?: boolean;\n database?: string;\n templateDatabase?: string;\n configurePool?: boolean;\n prepare?: (client: pg.Client) => Promise<void>;\n}\n\ninterface DropDatabaseOptions {\n database?: string;\n force?: boolean;\n closePool?: boolean;\n}\n\nasync function createDatabase(\n options: PostgresTestUtilsOptions,\n {\n dropExistingDatabase = true,\n configurePool = true,\n database,\n templateDatabase,\n prepare,\n }: CreateDatabaseOptions = {},\n): Promise<void> {\n const client = new pg.Client({\n ...getPoolConfig(options),\n database: options.defaultDatabase ?? POSTGRES_DATABASE,\n });\n await client.connect();\n\n const escapedDatabase = client.escapeIdentifier(\n database ?? getDatabaseNameForCurrentMochaWorker(options.database),\n );\n if (dropExistingDatabase ?? true) {\n await client.query(`DROP DATABASE IF EXISTS ${escapedDatabase}`);\n }\n\n if (templateDatabase) {\n const escapedTemplateDatabase = client.escapeIdentifier(templateDatabase);\n await client.query(`CREATE DATABASE ${escapedDatabase} TEMPLATE ${escapedTemplateDatabase}`);\n } else {\n await client.query(`CREATE DATABASE ${escapedDatabase}`);\n }\n\n await client.end();\n\n await prepare?.(client);\n\n if (configurePool) {\n await defaultPool.initAsync(\n {\n user: options.user ?? POSTGRES_USER,\n host: options.host ?? POSTGRES_HOST,\n database: getDatabaseNameForCurrentMochaWorker(options.database),\n // Offer sensible default, but these can be overridden by `options.poolConfig`.\n max: 10,\n idleTimeoutMillis: 30000,\n errorOnUnusedParameters: true,\n ...options.poolConfig,\n },\n (err) => {\n throw err;\n },\n );\n }\n}\n\nasync function resetDatabase(options: PostgresTestUtilsOptions): Promise<void> {\n const client = new pg.Client(getPoolConfig(options));\n await client.connect();\n await client.query(`\n DO\n $func$\n BEGIN\n EXECUTE (\n SELECT 'TRUNCATE TABLE ' || string_agg(oid::regclass::text, ', ') || ' RESTART IDENTITY CASCADE'\n FROM pg_class\n WHERE relkind = 'r'\n AND relnamespace = 'public'::regnamespace\n );\n END\n $func$;\n `);\n await options.prepareAfterReset?.(client);\n await client.end();\n}\n\nasync function dropDatabase(\n options: PostgresTestUtilsOptions,\n { closePool = true, force = false, database }: DropDatabaseOptions = {},\n): Promise<void> {\n if (closePool) {\n await defaultPool.closeAsync();\n }\n\n const databaseName = database ?? getDatabaseNameForCurrentMochaWorker(options.database);\n if ('PL_KEEP_TEST_DB' in process.env && !force) {\n // eslint-disable-next-line no-console\n console.log(`PL_KEEP_TEST_DB environment variable set, not dropping database ${databaseName}`);\n return;\n }\n\n const client = new pg.Client({\n ...getPoolConfig(options),\n database: options.defaultDatabase ?? POSTGRES_DATABASE,\n });\n await client.connect();\n await client.query(`DROP DATABASE IF EXISTS ${client.escapeIdentifier(databaseName)}`);\n await client.end();\n}\n\nfunction getDatabaseNameForCurrentMochaWorker(namespace: string): string {\n const workerId = process.env.MOCHA_WORKER_ID ?? process.env.VITEST_POOL_ID ?? '1';\n return `${namespace}_${workerId}`;\n}\n\nfunction getPoolConfig(options: PostgresTestUtilsOptions): pg.PoolConfig {\n return {\n user: options.user ?? POSTGRES_USER,\n host: options.host ?? POSTGRES_HOST,\n database: getDatabaseNameForCurrentMochaWorker(options.database),\n };\n}\n\nexport interface PostgresTestUtils {\n createDatabase: (options?: CreateDatabaseOptions) => Promise<void>;\n resetDatabase: () => Promise<void>;\n dropDatabase: (options?: DropDatabaseOptions) => Promise<void>;\n getDatabaseNameForCurrentMochaWorker: () => string;\n getPoolConfig: () => pg.PoolConfig;\n}\n\nexport function makePostgresTestUtils(options: PostgresTestUtilsOptions): PostgresTestUtils {\n return {\n createDatabase: (createOptions?: CreateDatabaseOptions) =>\n createDatabase(options, createOptions),\n resetDatabase: () => resetDatabase(options),\n dropDatabase: (dropOptions?: DropDatabaseOptions) => dropDatabase(options, dropOptions),\n getDatabaseNameForCurrentMochaWorker: () =>\n getDatabaseNameForCurrentMochaWorker(options.database),\n getPoolConfig: () => getPoolConfig(options),\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prairielearn/postgres",
3
- "version": "4.0.1",
3
+ "version": "4.1.0",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -72,6 +72,8 @@ export const runInTransactionAsync = defaultPool.runInTransactionAsync.bind(defa
72
72
  /**
73
73
  * Executes a query with the specified parameters.
74
74
  *
75
+ * @deprecated Use {@link execute} instead.
76
+ *
75
77
  * Using the return value of this function directly is not recommended. Instead, use
76
78
  * {@link queryRows}, {@link queryRow}, or {@link queryOptionalRow}.
77
79
  */
@@ -80,7 +82,7 @@ export const queryAsync = defaultPool.queryAsync.bind(defaultPool);
80
82
  * Executes a query with the specified parameters. Errors if the query does
81
83
  * not return exactly one row.
82
84
  *
83
- * @deprecated Use {@link queryRow} instead.
85
+ * @deprecated Use {@link executeRow} or {@link queryRow} instead.
84
86
  */
85
87
  export const queryOneRowAsync = defaultPool.queryOneRowAsync.bind(defaultPool);
86
88
  /**
@@ -160,6 +162,17 @@ export const callRow = defaultPool.callRow.bind(defaultPool);
160
162
  * or a single row that conforms to the given Zod schema.
161
163
  */
162
164
  export const callOptionalRow = defaultPool.callOptionalRow.bind(defaultPool);
165
+
166
+ /**
167
+ * Executes a query with the specified parameters. Returns the number of rows affected.
168
+ */
169
+ export const execute = defaultPool.execute.bind(defaultPool);
170
+
171
+ /**
172
+ * Executes a query with the specified parameter, and errors if the query doesn't return exactly one row.
173
+ */
174
+ export const executeRow = defaultPool.executeRow.bind(defaultPool);
175
+
163
176
  /**
164
177
  * Returns an {@link CursorIterator} that can be used to iterate over the
165
178
  * results of the query in batches, which is useful for large result sets.
package/src/error.ts CHANGED
@@ -6,7 +6,7 @@ export function formatQueryWithErrorPosition(query: string, position: number | n
6
6
  if (nextNewline < 0) nextNewline = query.length;
7
7
  const gap = ' '.repeat(Math.max(0, position - prevNewline - 1));
8
8
  return (
9
- query.substring(0, nextNewline) +
9
+ query.slice(0, nextNewline) +
10
10
  '\n' +
11
11
  gap +
12
12
  '^\n' +
@@ -14,6 +14,6 @@ export function formatQueryWithErrorPosition(query: string, position: number | n
14
14
  '|\n' +
15
15
  gap +
16
16
  '+ ERROR POSITION SHOWN ABOVE\n' +
17
- query.substring(nextNewline)
17
+ query.slice(nextNewline)
18
18
  );
19
19
  }
package/src/pool.ts CHANGED
@@ -26,7 +26,7 @@ const searchSchemaMap = new WeakMap<pg.PoolClient, string>();
26
26
 
27
27
  function addDataToError(err: Error, data: Record<string, any>): Error {
28
28
  (err as any).data = {
29
- ...((err as any).data ?? {}),
29
+ ...(err as any).data,
30
30
  ...data,
31
31
  };
32
32
  return err;
@@ -47,8 +47,8 @@ export class PostgresError extends Error {
47
47
  */
48
48
  function debugString(s: string): string {
49
49
  if (typeof s !== 'string') return 'NOT A STRING';
50
- s = s.replace(/\n/g, '\\n');
51
- if (s.length > 78) s = s.substring(0, 75) + '...';
50
+ s = s.replaceAll('\n', '\\n');
51
+ if (s.length > 78) s = s.slice(0, 75) + '...';
52
52
  s = '"' + s + '"';
53
53
  return s;
54
54
  }
@@ -107,14 +107,14 @@ function paramsToArray(
107
107
  paramsArray.push(params[v]);
108
108
  }
109
109
  }
110
- processedSql += remainingSql.substring(0, result.index) + map[v];
111
- remainingSql = remainingSql.substring(result.index + result[0].length);
110
+ processedSql += remainingSql.slice(0, result.index) + map[v];
111
+ remainingSql = remainingSql.slice(result.index + result[0].length);
112
112
  }
113
113
  processedSql += remainingSql;
114
114
  remainingSql = '';
115
115
  if (errorOnUnusedParameters) {
116
116
  const difference = _.difference(Object.keys(params), Object.keys(map));
117
- if (difference.length) {
117
+ if (difference.length > 0) {
118
118
  throw new Error(`Unused parameters in SQL query: ${JSON.stringify(difference)}`);
119
119
  }
120
120
  }
@@ -453,6 +453,11 @@ export class PostgresPool {
453
453
 
454
454
  /**
455
455
  * Executes a query with the specified parameters.
456
+ *
457
+ * @deprecated Use {@link execute} instead.
458
+ *
459
+ * Using the return value of this function directly is not recommended. Instead, use
460
+ * {@link queryRows}, {@link queryRow}, or {@link queryOptionalRow}.
456
461
  */
457
462
  async queryAsync(sql: string, params: QueryParams): Promise<QueryResult> {
458
463
  debug('query()', 'sql:', debugString(sql));
@@ -471,6 +476,8 @@ export class PostgresPool {
471
476
  /**
472
477
  * Executes a query with the specified parameters. Errors if the query does
473
478
  * not return exactly one row.
479
+ *
480
+ * @deprecated Use {@link executeRow} or {@link queryRow} instead.
474
481
  */
475
482
  async queryOneRowAsync(sql: string, params: QueryParams): Promise<pg.QueryResult> {
476
483
  debug('queryOneRow()', 'sql:', debugString(sql));
@@ -510,7 +517,7 @@ export class PostgresPool {
510
517
  async callAsync(functionName: string, params: any[]): Promise<pg.QueryResult> {
511
518
  debug('call()', 'function:', functionName);
512
519
  debug('call()', 'params:', debugParams(params));
513
- const placeholders = params.map((_, v) => '$' + (v + 1)).join();
520
+ const placeholders = params.map((_, v) => '$' + (v + 1)).join(',');
514
521
  const sql = `SELECT * FROM ${escapeIdentifier(functionName)}(${placeholders});`;
515
522
  const result = await this.queryAsync(sql, params);
516
523
  debug('call() success', 'rowCount:', result.rowCount);
@@ -563,7 +570,7 @@ export class PostgresPool {
563
570
  ): Promise<pg.QueryResult> {
564
571
  debug('callWithClient()', 'function:', functionName);
565
572
  debug('callWithClient()', 'params:', debugParams(params));
566
- const placeholders = params.map((_, v) => '$' + (v + 1)).join();
573
+ const placeholders = params.map((_, v) => '$' + (v + 1)).join(',');
567
574
  const sql = `SELECT * FROM ${escapeIdentifier(functionName)}(${placeholders})`;
568
575
  const result = await this.queryWithClientAsync(client, sql, params);
569
576
  debug('callWithClient() success', 'rowCount:', result.rowCount);
@@ -787,6 +794,27 @@ export class PostgresPool {
787
794
  }
788
795
  }
789
796
 
797
+ /**
798
+ * Executes a query with the specified parameters. Returns the number of rows affected.
799
+ */
800
+ async execute(sql: string, params: QueryParams = {}): Promise<number> {
801
+ const result = await this.queryAsync(sql, params);
802
+ return result.rowCount ?? 0;
803
+ }
804
+
805
+ /**
806
+ * Executes a query with the specified parameter, and errors if the query doesn't return exactly one row.
807
+ */
808
+ async executeRow(sql: string, params: QueryParams = {}) {
809
+ const rowCount = await this.execute(sql, params);
810
+ if (rowCount !== 1) {
811
+ throw new PostgresError('Incorrect rowCount: ' + rowCount, {
812
+ sql,
813
+ sqlParams: params,
814
+ });
815
+ }
816
+ }
817
+
790
818
  /**
791
819
  * Returns a {@link Cursor} for the given query. The cursor can be used to
792
820
  * read results in batches, which is useful for large result sets.
@@ -895,7 +923,7 @@ export class PostgresPool {
895
923
  *
896
924
  * @param schema The schema name to use (can be "null" to unset the search path)
897
925
  */
898
- async setSearchSchema(schema: string) {
926
+ async setSearchSchema(schema: string | null) {
899
927
  if (schema == null) {
900
928
  this.searchSchema = schema;
901
929
  return;
@@ -923,7 +951,7 @@ export class PostgresPool {
923
951
  */
924
952
  async setRandomSearchSchemaAsync(prefix: string): Promise<string> {
925
953
  // truncated prefix (max 28 characters)
926
- const truncPrefix = prefix.substring(0, 28);
954
+ const truncPrefix = prefix.slice(0, 28);
927
955
  // timestamp in format YYYY-MM-DDTHH:MM:SS.SSSZ (guaranteed to not exceed 27 characters in the spec)
928
956
  const timestamp = new Date().toISOString();
929
957
  // random 6-character suffix to avoid clashes (approx 2 billion possible values)
package/src/test-utils.ts CHANGED
@@ -73,7 +73,7 @@ async function createDatabase(
73
73
  max: 10,
74
74
  idleTimeoutMillis: 30000,
75
75
  errorOnUnusedParameters: true,
76
- ...(options.poolConfig ?? {}),
76
+ ...options.poolConfig,
77
77
  },
78
78
  (err) => {
79
79
  throw err;