95 lines
2.7 KiB
Odin
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)
|
|
}
|