diff --git a/crates/bindings-typescript/package.json b/crates/bindings-typescript/package.json index 7b83e8e1c4f..f0ac3bb8901 100644 --- a/crates/bindings-typescript/package.json +++ b/crates/bindings-typescript/package.json @@ -1,6 +1,6 @@ { "name": "spacetimedb", - "version": "1.11.2", + "version": "1.11.4", "description": "API and ABI bindings for the SpacetimeDB TypeScript module library", "homepage": "https://github.com/clockworklabs/SpacetimeDB#readme", "bugs": { diff --git a/crates/bindings-typescript/src/server/runtime.ts b/crates/bindings-typescript/src/server/runtime.ts index 4d426d2b527..f18362aa08b 100644 --- a/crates/bindings-typescript/src/server/runtime.ts +++ b/crates/bindings-typescript/src/server/runtime.ts @@ -1,6 +1,5 @@ import * as _syscalls1_0 from 'spacetime:sys@1.0'; import * as _syscalls1_2 from 'spacetime:sys@1.2'; -import * as _syscalls1_3 from 'spacetime:sys@1.3'; import type { ModuleHooks, u16, u32 } from 'spacetime:sys@1.0'; import { AlgebraicType, ProductType } from '../lib/algebraic_type'; @@ -51,9 +50,7 @@ import ViewResultHeader from '../lib/autogen/view_result_header_type'; const { freeze } = Object; -export const sys = freeze( - wrapSyscalls(_syscalls1_0, _syscalls1_2, _syscalls1_3) -); +export const sys = freeze(wrapSyscalls(_syscalls1_0, _syscalls1_2)); export function parseJsonObject(json: string): JsonObject { let value: unknown; @@ -272,8 +269,10 @@ export const hooks: ModuleHooks = { return writer.getBuffer(); }, __call_reducer__(reducerId, sender, connId, timestamp, argsBuf) { - const argsType = MODULE_DEF.reducers[reducerId].params; - const args = ProductType.deserializeValue( + const argsType = AlgebraicType.Product( + MODULE_DEF.reducers[reducerId].params + ); + const args = AlgebraicType.deserializeValue( new BinaryReader(argsBuf), argsType, MODULE_DEF.typespace @@ -547,6 +546,8 @@ function makeTableView( prefix: any[], prefix_elems: number ) => { + if (prefix_elems > numColumns - 1) + throw new TypeError('too many elements in prefix'); for (let i = 0; i < prefix_elems; i++) { const elemType = indexType.value.elements[i].algebraicType; AlgebraicType.serializeValue(writer, elemType, prefix[i], typespace); @@ -554,23 +555,6 @@ function makeTableView( return writer; }; - const serializePoint = (colVal: any[]): Uint8Array => { - const writer = new BinaryWriter(baseSize); - serializePrefix(writer, colVal, numColumns); - return writer.getBuffer(); - }; - - const singleElement = - numColumns === 1 ? indexType.value.elements[0].algebraicType : null; - - const serializeSinglePoint = - singleElement && - ((colVal: any): Uint8Array => { - const writer = new BinaryWriter(baseSize); - AlgebraicType.serializeValue(writer, singleElement, colVal, typespace); - return writer.getBuffer(); - }); - type IndexScanArgs = [ prefix: Uint8Array, prefix_elems: u16, @@ -579,53 +563,33 @@ function makeTableView( ]; let index: Index; - if (isUnique && serializeSinglePoint) { - // numColumns == 1, unique index - index = { - find: (colVal: IndexVal): RowType | null => { - const point = serializeSinglePoint(colVal); - const iter = tableIterator( - sys.datastore_index_scan_point_bsatn(index_id, point), - rowType - ); - const { value, done } = iter.next(); - if (done) return null; - if (!iter.next().done) - throw new Error( - '`datastore_index_scan_range_bsatn` on unique field cannot return >1 rows' - ); - return value; - }, - delete: (colVal: IndexVal): boolean => { - const point = serializeSinglePoint(colVal); - const num = sys.datastore_delete_by_index_scan_point_bsatn( - index_id, - point - ); - return num > 0; - }, - update: (row: RowType): RowType => { - const writer = new BinaryWriter(baseSize); - AlgebraicType.serializeValue(writer, rowType, row, typespace); - const ret_buf = sys.datastore_update_bsatn( - table_id, - index_id, - writer.getBuffer() - ); - integrateGeneratedColumns?.(row, ret_buf); - return row; - }, - } as UniqueIndex; - } else if (isUnique) { - // numColumns != 1, unique index + if (isUnique) { + const serializeBound = (colVal: any[]): IndexScanArgs => { + if (colVal.length !== numColumns) + throw new TypeError('wrong number of elements'); + + const writer = new BinaryWriter(baseSize + 1); + const prefix_elems = numColumns - 1; + serializePrefix(writer, colVal, prefix_elems); + const rstartOffset = writer.offset; + writer.writeU8(0); + AlgebraicType.serializeValue( + writer, + indexType.value.elements[numColumns - 1].algebraicType, + colVal[numColumns - 1], + typespace + ); + const buffer = writer.getBuffer(); + const prefix = buffer.slice(0, rstartOffset); + const rstart = buffer.slice(rstartOffset); + return [prefix, prefix_elems, rstart, rstart]; + }; index = { find: (colVal: IndexVal): RowType | null => { - if (colVal.length !== numColumns) { - throw new TypeError('wrong number of elements'); - } - const point = serializePoint(colVal); + if (numColumns === 1) colVal = [colVal]; + const args = serializeBound(colVal); const iter = tableIterator( - sys.datastore_index_scan_point_bsatn(index_id, point), + sys.datastore_index_scan_range_bsatn(index_id, ...args), rowType ); const { value, done } = iter.next(); @@ -637,13 +601,11 @@ function makeTableView( return value; }, delete: (colVal: IndexVal): boolean => { - if (colVal.length !== numColumns) - throw new TypeError('wrong number of elements'); - - const point = serializePoint(colVal); - const num = sys.datastore_delete_by_index_scan_point_bsatn( + if (numColumns === 1) colVal = [colVal]; + const args = serializeBound(colVal); + const num = sys.datastore_delete_by_index_scan_range_bsatn( index_id, - point + ...args ); return num > 0; }, @@ -659,26 +621,7 @@ function makeTableView( return row; }, } as UniqueIndex; - } else if (serializeSinglePoint) { - // numColumns == 1 - index = { - filter: (range: any): IteratorObject> => { - const point = serializeSinglePoint(range); - return tableIterator( - sys.datastore_index_scan_point_bsatn(index_id, point), - rowType - ); - }, - delete: (range: any): u32 => { - const point = serializeSinglePoint(range); - return sys.datastore_delete_by_index_scan_point_bsatn( - index_id, - point - ); - }, - } as RangedIndex; } else { - // numColumns != 1 const serializeRange = (range: any[]): IndexScanArgs => { if (range.length > numColumns) throw new TypeError('too many elements'); @@ -717,35 +660,21 @@ function makeTableView( return [prefix, prefix_elems, rstart, rend]; }; index = { - filter: (range: any[]): IteratorObject> => { - if (range.length === numColumns) { - const point = serializePoint(range); - return tableIterator( - sys.datastore_index_scan_point_bsatn(index_id, point), - rowType - ); - } else { - const args = serializeRange(range); - return tableIterator( - sys.datastore_index_scan_range_bsatn(index_id, ...args), - rowType - ); - } + filter: (range: any): IteratorObject> => { + if (numColumns === 1) range = [range]; + const args = serializeRange(range); + return tableIterator( + sys.datastore_index_scan_range_bsatn(index_id, ...args), + rowType + ); }, - delete: (range: any[]): u32 => { - if (range.length === numColumns) { - const point = serializePoint(range); - return sys.datastore_delete_by_index_scan_point_bsatn( - index_id, - point - ); - } else { - const args = serializeRange(range); - return sys.datastore_delete_by_index_scan_range_bsatn( - index_id, - ...args - ); - } + delete: (range: any): u32 => { + if (numColumns === 1) range = [range]; + const args = serializeRange(range); + return sys.datastore_delete_by_index_scan_range_bsatn( + index_id, + ...args + ); }, } as RangedIndex; } diff --git a/crates/bindings-typescript/src/server/sys.d.ts b/crates/bindings-typescript/src/server/sys.d.ts index f3480b5d186..07c5c7ac609 100644 --- a/crates/bindings-typescript/src/server/sys.d.ts +++ b/crates/bindings-typescript/src/server/sys.d.ts @@ -100,15 +100,3 @@ declare module 'spacetime:sys@1.2' { export function procedure_abort_mut_tx(); } - -declare module 'spacetime:sys@1.3' { - export function datastore_index_scan_point_bsatn( - index_id: u32, - point: Uint8Array - ): u32; - - export function datastore_delete_by_index_scan_point_bsatn( - index_id: u32, - point: Uint8Array - ): u32; -} diff --git a/crates/core/src/host/v8/syscall/mod.rs b/crates/core/src/host/v8/syscall/mod.rs index ed7fa8f4cb2..1719f3ffe66 100644 --- a/crates/core/src/host/v8/syscall/mod.rs +++ b/crates/core/src/host/v8/syscall/mod.rs @@ -57,7 +57,6 @@ fn resolve_sys_module_inner<'scope>( (1, 0) => Ok(v1::sys_v1_0(scope)), (1, 1) => Ok(v1::sys_v1_1(scope)), (1, 2) => Ok(v1::sys_v1_2(scope)), - (1, 3) => Ok(v1::sys_v1_3(scope)), _ => Err(TypeError(format!( "Could not import {spec:?}, likely because this module was built for a newer version of SpacetimeDB.\n\ It requires sys module v{major}.{minor}, but that version is not supported by the database." diff --git a/crates/core/src/host/v8/syscall/v1.rs b/crates/core/src/host/v8/syscall/v1.rs index 1022f452501..588fd16a86e 100644 --- a/crates/core/src/host/v8/syscall/v1.rs +++ b/crates/core/src/host/v8/syscall/v1.rs @@ -150,23 +150,6 @@ pub(super) fn sys_v1_2<'scope>(scope: &mut PinScope<'scope, '_>) -> Local<'scope ) } -pub(super) fn sys_v1_3<'scope>(scope: &mut PinScope<'scope, '_>) -> Local<'scope, Module> { - create_synthetic_module!( - scope, - "spacetime:sys@1.2", - ( - with_sys_result_ret, - AbiCall::DatastoreIndexScanPointBsatn, - datastore_index_scan_point_bsatn - ), - ( - with_sys_result_ret, - AbiCall::DatastoreDeleteByIndexScanPointBsatn, - datastore_delete_by_index_scan_point_bsatn - ), - ) -} - /// Registers a function in `module` /// where the function has `name` and does `body`. fn register_module_fun( @@ -1711,35 +1694,3 @@ fn procedure_commit_mut_tx(scope: &mut PinScope<'_, '_>, _args: FunctionCallback Ok(()) } - -fn datastore_index_scan_point_bsatn( - scope: &mut PinScope<'_, '_>, - args: FunctionCallbackArguments<'_>, -) -> SysCallResult { - let index_id: IndexId = deserialize_js(scope, args.get(0))?; - let point: &[u8] = deserialize_js(scope, args.get(1))?; - - let env = get_env(scope)?; - - // Find the relevant rows. - let chunks = env - .instance_env - .datastore_index_scan_point_bsatn_chunks(&mut env.chunk_pool, index_id, point)?; - - // Insert the encoded + concatenated rows into a new buffer and return its id. - Ok(env.iters.insert(chunks.into_iter()).0) -} - -fn datastore_delete_by_index_scan_point_bsatn( - scope: &mut PinScope<'_, '_>, - args: FunctionCallbackArguments<'_>, -) -> SysCallResult { - let index_id: IndexId = deserialize_js(scope, args.get(0))?; - let point: &[u8] = deserialize_js(scope, args.get(1))?; - - // Delete the relevant rows. - let count = get_env(scope)? - .instance_env - .datastore_delete_by_index_scan_point_bsatn(index_id, point)?; - Ok(count) -}