Skip to content

Commit ce48940

Browse files
committed
Use nested Maps for parameters
1 parent 4cbaaea commit ce48940

File tree

1 file changed

+32
-5
lines changed

1 file changed

+32
-5
lines changed

packages/react-pg/src/ReactPostgres.js

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {Wakeable} from 'shared/ReactTypes';
1111

1212
import {unstable_getCacheForType} from 'react';
1313
import {Pool as PostgresPool} from 'pg';
14+
import {prepareValue} from 'pg/lib/utils';
1415

1516
const Pending = 0;
1617
const Resolved = 1;
@@ -73,16 +74,42 @@ export function Pool(options: mixed) {
7374
};
7475
}
7576

77+
function getInnerMap(
78+
outerMap: Map<string, mixed>,
79+
query: string,
80+
values?: Array<mixed>,
81+
) {
82+
if (values == null || values.length === 0) {
83+
return [outerMap, query];
84+
}
85+
// If we have parameters, each becomes as a nesting layer for Maps.
86+
// We want to find (or create as needed) the innermost Map, and return that.
87+
let innerMap = outerMap;
88+
let key = query;
89+
for (let i = 0; i < values.length; i++) {
90+
let nextMap = innerMap.get(key);
91+
if (nextMap === undefined) {
92+
nextMap = new Map();
93+
innerMap.set(key, nextMap);
94+
}
95+
innerMap = nextMap;
96+
// Postgres bindings convert everything to strings:
97+
// https://node-postgres.com/features/queries#parameterized-query
98+
// We reuse their algorithm instead of reimplementing.
99+
key = prepareValue(values[i]);
100+
}
101+
return [innerMap, key];
102+
}
103+
76104
Pool.prototype.query = function(query: string, values?: Array<mixed>) {
77105
const pool = this.pool;
78-
const map = unstable_getCacheForType(this.createResultMap);
79-
// TODO: Is this sufficient? What about more complex types?
80-
const key = JSON.stringify({query, values});
81-
let entry = map.get(key);
106+
const outerMap = unstable_getCacheForType(this.createResultMap);
107+
const [innerMap, key] = getInnerMap(outerMap, query, values);
108+
let entry = innerMap.get(key);
82109
if (!entry) {
83110
const thenable = pool.query(query, values);
84111
entry = toResult(thenable);
85-
map.set(key, entry);
112+
innerMap.set(key, entry);
86113
}
87114
return readResult(entry);
88115
};

0 commit comments

Comments
 (0)