fix storage issues
This commit is contained in:
@@ -485,41 +485,131 @@ parse_limit :: proc(request_body: []byte) -> int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Parse ExclusiveStartKey from request body as binary key bytes
|
||||
// Returns nil if not present
|
||||
parse_exclusive_start_key :: proc(request_body: []byte) -> Maybe([]byte) {
|
||||
// ============================================================================
|
||||
// ExclusiveStartKey Parsing (Pagination Input)
|
||||
//
|
||||
// Parse ExclusiveStartKey from request body. Requires key_schema so we can
|
||||
// validate and extract the key, then convert it to a binary storage key.
|
||||
// Returns the binary key bytes that can be passed straight to scan/query.
|
||||
// Returns nil (not an error) when the field is absent.
|
||||
// ============================================================================
|
||||
|
||||
parse_exclusive_start_key :: proc(
|
||||
request_body: []byte,
|
||||
table_name: string,
|
||||
key_schema: []Key_Schema_Element,
|
||||
) -> (result: Maybe([]byte), ok: bool) {
|
||||
data, parse_err := json.parse(request_body, allocator = context.temp_allocator)
|
||||
if parse_err != nil {
|
||||
return nil
|
||||
return nil, true // no ESK is fine
|
||||
}
|
||||
defer json.destroy_value(data)
|
||||
|
||||
root, ok := data.(json.Object)
|
||||
if !ok {
|
||||
return nil
|
||||
root, root_ok := data.(json.Object)
|
||||
if !root_ok {
|
||||
return nil, true
|
||||
}
|
||||
|
||||
key_val, found := root["ExclusiveStartKey"]
|
||||
esk_val, found := root["ExclusiveStartKey"]
|
||||
if !found {
|
||||
return nil
|
||||
return nil, true // absent → no pagination, that's ok
|
||||
}
|
||||
|
||||
// Parse as Item first
|
||||
key_item, item_ok := parse_item_from_value(key_val)
|
||||
// Parse ExclusiveStartKey as a DynamoDB Item
|
||||
key_item, item_ok := parse_item_from_value(esk_val)
|
||||
if !item_ok {
|
||||
return nil
|
||||
return nil, false // present but malformed → real error
|
||||
}
|
||||
defer item_destroy(&key_item)
|
||||
|
||||
// Convert to binary key bytes (this will be done by the storage layer)
|
||||
// For now, just return nil - the storage layer will handle the conversion
|
||||
return nil
|
||||
// Validate and extract key struct using schema
|
||||
key_struct, key_ok := key_from_item(key_item, key_schema)
|
||||
if !key_ok {
|
||||
return nil, false // missing required key attributes
|
||||
}
|
||||
defer key_destroy(&key_struct)
|
||||
|
||||
// Get raw byte values
|
||||
key_values, kv_ok := key_get_values(&key_struct)
|
||||
if !kv_ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Build binary storage key
|
||||
binary_key := build_data_key(table_name, key_values.pk, key_values.sk)
|
||||
result = binary_key
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
// Serialize a Key as ExclusiveStartKey for response
|
||||
serialize_last_evaluated_key :: proc(key: Key) -> string {
|
||||
item := key_to_item(key, {}) // Empty key_schema since we don't need validation here
|
||||
// ============================================================================
|
||||
// LastEvaluatedKey Generation (Pagination Output)
|
||||
//
|
||||
// Decode a binary storage key back into a DynamoDB JSON fragment suitable
|
||||
// for the "LastEvaluatedKey" field in scan/query responses.
|
||||
//
|
||||
// Steps:
|
||||
// 1. Decode the binary key → table_name, pk_bytes, sk_bytes
|
||||
// 2. Look up attribute types from metadata (S/N/B)
|
||||
// 3. Build a Key struct with correctly-typed AttributeValues
|
||||
// 4. Convert Key → Item → DynamoDB JSON string
|
||||
// ============================================================================
|
||||
|
||||
// Build a Key struct from a binary storage key using metadata for type info.
|
||||
// This mirrors the Zig buildKeyFromBinaryWithTypes helper.
|
||||
build_key_from_binary_with_types :: proc(
|
||||
binary_key: []byte,
|
||||
metadata: ^Table_Metadata,
|
||||
) -> (key: Key, ok: bool) {
|
||||
decoder := Key_Decoder{data = binary_key, pos = 0}
|
||||
|
||||
// Skip entity type byte
|
||||
_ = decoder_read_entity_type(&decoder) or_return
|
||||
|
||||
// Skip table name segment
|
||||
_ = decoder_read_segment_borrowed(&decoder) or_return
|
||||
|
||||
// Read partition key bytes
|
||||
pk_bytes := decoder_read_segment_borrowed(&decoder) or_return
|
||||
|
||||
// Read sort key bytes if present
|
||||
sk_bytes: Maybe([]byte) = nil
|
||||
if decoder_has_more(&decoder) {
|
||||
sk := decoder_read_segment_borrowed(&decoder) or_return
|
||||
sk_bytes = sk
|
||||
}
|
||||
|
||||
// Get PK attribute type from metadata
|
||||
pk_name := table_metadata_get_partition_key_name(metadata).? or_return
|
||||
pk_type := table_metadata_get_attribute_type(metadata, pk_name).? or_return
|
||||
|
||||
pk_attr := build_attribute_value_with_type(pk_bytes, pk_type)
|
||||
|
||||
// Build SK attribute if present
|
||||
sk_attr: Maybe(Attribute_Value) = nil
|
||||
if sk, has_sk := sk_bytes.?; has_sk {
|
||||
sk_name := table_metadata_get_sort_key_name(metadata).? or_return
|
||||
sk_type := table_metadata_get_attribute_type(metadata, sk_name).? or_return
|
||||
sk_attr = build_attribute_value_with_type(sk, sk_type)
|
||||
}
|
||||
|
||||
return Key{pk = pk_attr, sk = sk_attr}, true
|
||||
}
|
||||
|
||||
// Serialize a binary storage key as a LastEvaluatedKey JSON fragment.
|
||||
// Returns a string like: {"pk":{"S":"val"},"sk":{"N":"42"}}
|
||||
serialize_last_evaluated_key :: proc(
|
||||
binary_key: []byte,
|
||||
metadata: ^Table_Metadata,
|
||||
) -> (result: string, ok: bool) {
|
||||
key, key_ok := build_key_from_binary_with_types(binary_key, metadata)
|
||||
if !key_ok {
|
||||
return "", false
|
||||
}
|
||||
defer key_destroy(&key)
|
||||
|
||||
item := key_to_item(key, metadata.key_schema)
|
||||
defer item_destroy(&item)
|
||||
|
||||
return serialize_item(item)
|
||||
return serialize_item(item), true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user