@@ -2,11 +2,13 @@ import type postgres from 'postgres';
22import { stringify , type JSONValue } from './bigint-json.js' ;
33import { h64 } from './xxhash.js' ;
44
5- export type ColumnType = { typeOid : number } ;
6- export type RowKeyType = Record < string , ColumnType > ;
7- export type RowKey = Record < string , postgres . SerializableParameter < JSONValue > > ;
5+ export type ColumnType = { readonly typeOid : number } ;
6+ export type RowKeyType = Readonly < Record < string , ColumnType > > ;
7+ export type RowKey = Readonly <
8+ Record < string , postgres . SerializableParameter < JSONValue > >
9+ > ;
810
9- export type RowID = { schema : string ; table : string ; rowKey : RowKey } ;
11+ export type RowID = Readonly < { schema : string ; table : string ; rowKey : RowKey } > ;
1012
1113// Aliased for documentation purposes when dealing with full rows vs row keys.
1214// The actual structure of the objects is the same.
@@ -27,6 +29,8 @@ function tuples(key: RowKey) {
2729 . flat ( ) ;
2830}
2931
32+ const rowIDHashes = new WeakMap < RowID , string > ( ) ;
33+
3034/**
3135 * A RowIDHash is a 128-bit column-order-agnostic hash of the schema, table name, and
3236 * column name / value tuples of a row key. It serves as a compact identifier for
@@ -40,14 +44,21 @@ function tuples(key: RowKey) {
4044 * The hash is encoded in `base36`, with the maximum 128-bit value being 25 characters long.
4145 */
4246export function rowIDHash ( id : RowID ) : string {
47+ let hash = rowIDHashes . get ( id ) ;
48+ if ( hash ) {
49+ return hash ;
50+ }
51+
4352 const str = stringify ( [ id . schema , id . table , ...tuples ( id . rowKey ) ] ) ;
4453
4554 // xxhash only computes 64-bit values. Run it on the forward and reverse string
4655 // to get better collision resistance.
4756 const forward = h64 ( str ) ;
4857 const backward = h64 ( reverse ( str ) ) ;
4958 const full = ( forward << 64n ) + backward ;
50- return full . toString ( 36 ) ;
59+ hash = full . toString ( 36 ) ;
60+ rowIDHashes . set ( id , hash ) ;
61+ return hash ;
5162}
5263
5364function reverse ( str : string ) : string {
0 commit comments