Skip to content

Commit c5b2d78

Browse files
authored
TypeScript modules: Expose hash indices (#4233)
# Description of Changes This allows `.index('hash')`. # API and ABI breaking changes None # Expected complexity level and risk 1 # Testing Verified that it works using the keynote 2 benchmark.
1 parent 7677b54 commit c5b2d78

4 files changed

Lines changed: 82 additions & 11 deletions

File tree

crates/bindings-typescript/src/lib/indexes.ts

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type IndexOpts<AllowedCol extends string> = {
1212
name?: string;
1313
} & (
1414
| { algorithm: 'btree'; columns: readonly AllowedCol[] }
15+
| { algorithm: 'hash'; columns: readonly AllowedCol[] }
1516
| { algorithm: 'direct'; column: AllowedCol }
1617
);
1718

@@ -21,7 +22,7 @@ export type IndexOpts<AllowedCol extends string> = {
2122
export type UntypedIndex<AllowedCol extends string> = {
2223
name: string;
2324
unique?: boolean;
24-
algorithm: 'btree' | 'direct';
25+
algorithm: 'btree' | 'direct' | 'hash';
2526
columns: readonly AllowedCol[];
2627
};
2728

@@ -47,14 +48,17 @@ export type Indexes<
4748
};
4849

4950
/**
50-
* A type representing a database index, which can be either unique or ranged.
51+
* A type representing a database index,
52+
* which can either be unique or filter for a single value or range of values.
5153
*/
5254
export type Index<
5355
TableDef extends UntypedTableDef,
5456
I extends UntypedIndex<keyof TableDef['columns'] & string>,
5557
> = I['unique'] extends true
5658
? UniqueIndex<TableDef, I>
57-
: RangedIndex<TableDef, I>;
59+
: I['algorithm'] extends 'hash'
60+
? PointIndex<TableDef, I>
61+
: RangedIndex<TableDef, I>;
5862

5963
/**
6064
* A type representing a collection of read-only indexes defined on a table.
@@ -67,15 +71,18 @@ export type ReadonlyIndexes<
6771
};
6872

6973
/**
70-
* A type representing a read-only database index, which can be either unique or ranged.
74+
* A type representing a read-only database index,
75+
* which can be either unique, pointed, or ranged.
7176
* This type only exposes read-only operations.
7277
*/
7378
export type ReadonlyIndex<
7479
TableDef extends UntypedTableDef,
7580
I extends UntypedIndex<keyof TableDef['columns'] & string>,
7681
> = I['unique'] extends true
7782
? ReadonlyUniqueIndex<TableDef, I>
78-
: ReadonlyRangedIndex<TableDef, I>;
83+
: I['algorithm'] extends 'hash'
84+
? ReadonlyPointIndex<TableDef, I>
85+
: ReadonlyRangedIndex<TableDef, I>;
7986

8087
/**
8188
* A type representing a read-only unique index on a database table.
@@ -99,6 +106,29 @@ export interface UniqueIndex<
99106
update(colVal: Prettify<RowType<TableDef>>): Prettify<RowType<TableDef>>;
100107
}
101108

109+
/**
110+
* A type representing a read-only point index on a database table.
111+
*/
112+
export interface ReadonlyPointIndex<
113+
TableDef extends UntypedTableDef,
114+
I extends UntypedIndex<keyof TableDef['columns'] & string>,
115+
> {
116+
filter(
117+
point: IndexVal<TableDef, I>
118+
): IteratorObject<Prettify<RowType<TableDef>>, undefined>;
119+
}
120+
121+
/**
122+
* A type representing a point index on a database table.
123+
* Point indexes allow for exact match queries on the indexed columns.
124+
*/
125+
export interface PointIndex<
126+
TableDef extends UntypedTableDef,
127+
I extends UntypedIndex<keyof TableDef['columns'] & string>,
128+
> extends ReadonlyPointIndex<TableDef, I> {
129+
delete(point: IndexVal<TableDef, I>): number;
130+
}
131+
102132
/**
103133
* A type representing a read-only ranged index on a database table.
104134
*/
@@ -190,7 +220,7 @@ export type ColumnIndex<
190220
name: Name;
191221
unique: ColumnIsUnique<M>;
192222
columns: readonly [Name];
193-
algorithm: 'btree' | 'direct';
223+
algorithm: 'btree' | 'direct' | 'hash';
194224
} & (M extends {
195225
indexType: infer I extends NonNullable<IndexTypes>;
196226
}

crates/bindings-typescript/src/lib/table.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,9 @@ export function table<Row extends RowObj, const Opts extends TableOpts<Row>>(
341341
case 'btree':
342342
algorithm = RawIndexAlgorithm.BTree([id]);
343343
break;
344+
case 'hash':
345+
algorithm = RawIndexAlgorithm.Hash([id]);
346+
break;
344347
case 'direct':
345348
algorithm = RawIndexAlgorithm.Direct(id);
346349
break;
@@ -398,6 +401,12 @@ export function table<Row extends RowObj, const Opts extends TableOpts<Row>>(
398401
value: indexOpts.columns.map(c => colIds.get(c)!),
399402
};
400403
break;
404+
case 'hash':
405+
algorithm = {
406+
tag: 'Hash',
407+
value: indexOpts.columns.map(c => colIds.get(c)!),
408+
};
409+
break;
401410
case 'direct':
402411
algorithm = { tag: 'Direct', value: colIds.get(indexOpts.column)! };
403412
break;

crates/bindings-typescript/src/lib/type_builders.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2070,7 +2070,7 @@ export class UuidBuilder
20702070
* The type of index types that can be applied to a column.
20712071
* `undefined` is the default
20722072
*/
2073-
export type IndexTypes = 'btree' | 'direct' | undefined;
2073+
export type IndexTypes = 'btree' | 'direct' | 'hash' | undefined;
20742074

20752075
/**
20762076
* Metadata describing column constraints and index type

crates/bindings-typescript/src/server/runtime.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import BinaryWriter, { ResizableBuffer } from '../lib/binary_writer';
1818
import {
1919
type Index,
2020
type IndexVal,
21+
type PointIndex,
2122
type RangedIndex,
2223
type UniqueIndex,
2324
} from '../lib/indexes';
@@ -516,12 +517,15 @@ function makeTableView(
516517
const index_id = sys.index_id_from_name(indexDef.sourceName!);
517518

518519
let column_ids: number[];
520+
let isHashIndex = false;
519521
switch (indexDef.algorithm.tag) {
522+
case 'Hash':
523+
isHashIndex = true;
524+
column_ids = indexDef.algorithm.value;
525+
break;
520526
case 'BTree':
521527
column_ids = indexDef.algorithm.value;
522528
break;
523-
case 'Hash':
524-
throw new Error('impossible');
525529
case 'Direct':
526530
column_ids = [indexDef.algorithm.value];
527531
break;
@@ -649,7 +653,7 @@ function makeTableView(
649653
} as UniqueIndex<any, any>;
650654
} else if (serializeSinglePoint) {
651655
// numColumns == 1
652-
index = {
656+
const rawIndex = {
653657
filter: (range: any): IteratorObject<RowType<any>> => {
654658
const buf = LEAF_BUF;
655659
const point_len = serializeSinglePoint(buf, range);
@@ -669,7 +673,35 @@ function makeTableView(
669673
point_len
670674
);
671675
},
672-
} as RangedIndex<any, any>;
676+
};
677+
if (isHashIndex) {
678+
index = rawIndex as PointIndex<any, any>;
679+
} else {
680+
index = rawIndex as RangedIndex<any, any>;
681+
}
682+
} else if (isHashIndex) {
683+
// numColumns != 1
684+
index = {
685+
filter: (range: any[]): IteratorObject<RowType<any>> => {
686+
const buf = LEAF_BUF;
687+
const point_len = serializePoint(buf, range);
688+
const iter_id = sys.datastore_index_scan_point_bsatn(
689+
index_id,
690+
buf.buffer,
691+
point_len
692+
);
693+
return tableIterator(iter_id, deserializeRow);
694+
},
695+
delete: (range: any[]): u32 => {
696+
const buf = LEAF_BUF;
697+
const point_len = serializePoint(buf, range);
698+
return sys.datastore_delete_by_index_scan_point_bsatn(
699+
index_id,
700+
buf.buffer,
701+
point_len
702+
);
703+
},
704+
} as PointIndex<any, any>;
673705
} else {
674706
// numColumns != 1
675707
const serializeRange = (

0 commit comments

Comments
 (0)