Files
jormun-db/dynamodb/key_codec_gsi.odin
2026-02-16 02:15:15 -05:00

95 lines
2.7 KiB
Odin

// key_codec_gsi.odin — Additional key codec functions for GSI support
//
// These procedures complement key_codec.odin with prefix builders needed
// for GSI scanning and querying. They follow the same encoding conventions:
// [entity_type][varint_len][segment_bytes]...
//
// Add the contents of this file to key_codec.odin (or keep as a separate file
// in the dynamodb/ package).
package dynamodb
import "core:bytes"
// Build GSI index prefix for scanning all entries in a GSI:
// [gsi][table_name][index_name]
build_gsi_prefix :: proc(table_name: string, index_name: string) -> []byte {
buf: bytes.Buffer
bytes.buffer_init_allocator(&buf, 0, 256, context.allocator)
bytes.buffer_write_byte(&buf, u8(Entity_Type.GSI))
encode_varint(&buf, len(table_name))
bytes.buffer_write_string(&buf, table_name)
encode_varint(&buf, len(index_name))
bytes.buffer_write_string(&buf, index_name)
return bytes.buffer_to_bytes(&buf)
}
// Build GSI partition prefix for querying within a single partition:
// [gsi][table_name][index_name][pk_value]
build_gsi_partition_prefix :: proc(table_name: string, index_name: string, pk_value: []byte) -> []byte {
buf: bytes.Buffer
bytes.buffer_init_allocator(&buf, 0, 512, context.allocator)
bytes.buffer_write_byte(&buf, u8(Entity_Type.GSI))
encode_varint(&buf, len(table_name))
bytes.buffer_write_string(&buf, table_name)
encode_varint(&buf, len(index_name))
bytes.buffer_write_string(&buf, index_name)
encode_varint(&buf, len(pk_value))
bytes.buffer_write(&buf, pk_value)
return bytes.buffer_to_bytes(&buf)
}
// Decode a GSI key back into components
Decoded_GSI_Key :: struct {
table_name: string,
index_name: string,
pk_value: []byte,
sk_value: Maybe([]byte),
}
decode_gsi_key :: proc(key: []byte) -> (result: Decoded_GSI_Key, ok: bool) {
decoder := Key_Decoder{data = key, pos = 0}
entity_type := decoder_read_entity_type(&decoder) or_return
if entity_type != .GSI {
return {}, false
}
table_name_bytes := decoder_read_segment(&decoder) or_return
result.table_name = string(table_name_bytes)
index_name_bytes := decoder_read_segment(&decoder) or_return
result.index_name = string(index_name_bytes)
result.pk_value = decoder_read_segment(&decoder) or_return
if decoder_has_more(&decoder) {
sk := decoder_read_segment(&decoder) or_return
result.sk_value = sk
}
return result, true
}
// Build GSI prefix for deleting all GSI entries for a table (used by delete_table)
// [gsi][table_name]
build_gsi_table_prefix :: proc(table_name: string) -> []byte {
buf: bytes.Buffer
bytes.buffer_init_allocator(&buf, 0, 256, context.allocator)
bytes.buffer_write_byte(&buf, u8(Entity_Type.GSI))
encode_varint(&buf, len(table_name))
bytes.buffer_write_string(&buf, table_name)
return bytes.buffer_to_bytes(&buf)
}