shes working

This commit is contained in:
2026-02-17 09:57:35 -05:00
parent d8a80bd728
commit a5a5d41e50
6 changed files with 79 additions and 31 deletions

View File

@@ -322,17 +322,25 @@ serialize_item_to_builder :: proc(b: ^strings.Builder, item: Item) {
serialize_attribute_value :: proc(b: ^strings.Builder, attr: Attribute_Value) {
switch v in attr {
case String:
fmt.sbprintf(b, `{"S":"%s"}`, string(v))
strings.write_string(b, `{"S":"`)
strings.write_string(b, string(v))
strings.write_string(b, `"}`)
case DDB_Number:
num_str := format_ddb_number(v)
fmt.sbprintf(b, `{"N":"%s"}`, num_str)
strings.write_string(b, `{"N":"`)
strings.write_string(b, num_str)
strings.write_string(b, `"}`)
case Binary:
fmt.sbprintf(b, `{"B":"%s"}`, string(v))
strings.write_string(b, `{"B":"`)
strings.write_string(b, string(v))
strings.write_string(b, `"}`)
case Bool:
fmt.sbprintf(b, `{"BOOL":%v}`, bool(v))
strings.write_string(b, `{"BOOL":`)
if bool(v) { strings.write_string(b, "true") } else { strings.write_string(b, "false") }
strings.write_string(b, "}")
case Null:
strings.write_string(b, `{"NULL":true}`)

View File

@@ -532,6 +532,10 @@ get_table_metadata :: proc(engine: ^Storage_Engine, table_name: string) -> (Tabl
return {}, .Serialization_Error
}
// table_name is not stored in the serialized blob (it IS the RocksDB key),
// so we populate it here from the argument we already have.
metadata.table_name = strings.clone(table_name, engine.allocator)
return metadata, .None
}

View File

@@ -532,9 +532,9 @@ update_item_batch :: proc(
}
defer item_destroy(&existing_item)
// Apply update plan
if !execute_update_plan(&existing_item, plan) {
return .Invalid_Key
// Apply update plan.
if exec_err := execute_update_plan(&existing_item, plan); exec_err != .None {
return .Validation_Error
}
// Encode updated item

View File

@@ -594,7 +594,23 @@ is_clause_keyword :: proc(tok: string) -> bool {
// Execute Update Plan — apply mutations to an Item (in-place)
// ============================================================================
execute_update_plan :: proc(item: ^Item, plan: ^Update_Plan) -> bool {
// Reasons an update plan can fail at execution time.
// All of these map to ValidationException at the HTTP layer.
Update_Exec_Error :: enum {
None,
// SET x = source +/- val: source attribute does not exist in the item
Operand_Not_Found,
// SET x = source +/- val: source or value attribute is not a Number
Operand_Not_Number,
// SET x = list_append(source, val): source attribute is not a List
Operand_Not_List,
// ADD path val: existing attribute is not a Number, String_Set, or Number_Set
Add_Type_Mismatch,
// ADD path val: value type does not match the existing set type
Add_Value_Type_Mismatch,
}
execute_update_plan :: proc(item: ^Item, plan: ^Update_Plan) -> Update_Exec_Error {
// Execute SET actions
for &action in plan.sets {
switch action.value_kind {
@@ -613,11 +629,11 @@ execute_update_plan :: proc(item: ^Item, plan: ^Update_Plan) -> bool {
if src, found := item[action.source]; found {
existing = src
} else {
return false // source attribute not found
return .Operand_Not_Found
}
result, add_ok := numeric_add(existing, action.value)
if !add_ok {
return false
return .Operand_Not_Number
}
if old, found := item[action.path]; found {
old_copy := old
@@ -632,11 +648,11 @@ execute_update_plan :: proc(item: ^Item, plan: ^Update_Plan) -> bool {
if src, found := item[action.source]; found {
existing = src
} else {
return false
return .Operand_Not_Found
}
result, sub_ok := numeric_subtract(existing, action.value)
if !sub_ok {
return false
return .Operand_Not_Number
}
if old, found := item[action.path]; found {
old_copy := old
@@ -664,7 +680,7 @@ execute_update_plan :: proc(item: ^Item, plan: ^Update_Plan) -> bool {
if l, is_list := src.(List); is_list {
existing_list = ([]Attribute_Value)(l)
} else {
return false
return .Operand_Not_List
}
} else {
existing_list = {}
@@ -674,7 +690,7 @@ execute_update_plan :: proc(item: ^Item, plan: ^Update_Plan) -> bool {
if l, is_list := action.value.(List); is_list {
append_list = ([]Attribute_Value)(l)
} else {
return false
return .Operand_Not_List
}
new_list := make([]Attribute_Value, len(existing_list) + len(append_list))
@@ -711,7 +727,7 @@ execute_update_plan :: proc(item: ^Item, plan: ^Update_Plan) -> bool {
case DDB_Number:
result, add_ok := numeric_add(existing, action.value)
if !add_ok {
return false
return .Operand_Not_Number
}
old_copy := existing
attr_value_destroy(&old_copy)
@@ -727,7 +743,7 @@ execute_update_plan :: proc(item: ^Item, plan: ^Update_Plan) -> bool {
delete_key(item, action.path)
item[strings.clone(action.path)] = String_Set(merged)
} else {
return false
return .Add_Value_Type_Mismatch
}
case DDB_Number_Set:
@@ -738,11 +754,11 @@ execute_update_plan :: proc(item: ^Item, plan: ^Update_Plan) -> bool {
delete_key(item, action.path)
item[strings.clone(action.path)] = DDB_Number_Set(merged)
} else {
return false
return .Add_Value_Type_Mismatch
}
case:
return false
return .Add_Type_Mismatch
}
} else {
// Attribute doesn't exist — create it
@@ -786,7 +802,7 @@ execute_update_plan :: proc(item: ^Item, plan: ^Update_Plan) -> bool {
}
}
return true
return .None
}
// ============================================================================

View File

@@ -73,14 +73,14 @@ update_item :: proc(
return nil, nil, .RocksDB_Error
}
// Apply update plan
if !execute_update_plan(&existing_item, plan) {
// Apply update plan.
if exec_err := execute_update_plan(&existing_item, plan); exec_err != .None {
item_destroy(&existing_item)
if old, has := old_item.?; has {
old_copy := old
item_destroy(&old_copy)
}
return nil, nil, .Invalid_Key
return nil, nil, .Validation_Error
}
// Validate key attributes are still present and correct type