fix cloned string cleanup
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
package dynamodb
|
package dynamodb
|
||||||
|
|
||||||
import "core:encoding/json"
|
import "core:encoding/json"
|
||||||
|
import "core:strings"
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Condition Evaluation Result
|
// Condition Evaluation Result
|
||||||
@@ -54,7 +55,7 @@ parse_condition_expression_string :: proc(request_body: []byte) -> (expr: string
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
expr = string(ce_str)
|
expr = strings.clone(string(ce_str))
|
||||||
ok = true
|
ok = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -88,6 +89,7 @@ evaluate_condition_expression :: proc(
|
|||||||
if !has_condition {
|
if !has_condition {
|
||||||
return .Passed // No condition → always pass
|
return .Passed // No condition → always pass
|
||||||
}
|
}
|
||||||
|
defer delete(condition_str)
|
||||||
|
|
||||||
// Parse the condition into a filter tree (same grammar as FilterExpression)
|
// Parse the condition into a filter tree (same grammar as FilterExpression)
|
||||||
filter_node, parse_ok := parse_filter_expression(condition_str, attr_names, attr_values)
|
filter_node, parse_ok := parse_filter_expression(condition_str, attr_names, attr_values)
|
||||||
|
|||||||
@@ -480,7 +480,7 @@ parse_key_condition_expression_string :: proc(request_body: []byte) -> (expr: st
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
expr = string(kce_str)
|
expr = strings.clone(string(kce_str))
|
||||||
ok = true
|
ok = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -488,6 +488,7 @@ parse_key_condition_expression_string :: proc(request_body: []byte) -> (expr: st
|
|||||||
// Convenience: parse a complete Query key condition from request body
|
// Convenience: parse a complete Query key condition from request body
|
||||||
parse_query_key_condition :: proc(request_body: []byte) -> (kc: Key_Condition, ok: bool) {
|
parse_query_key_condition :: proc(request_body: []byte) -> (kc: Key_Condition, ok: bool) {
|
||||||
expression := parse_key_condition_expression_string(request_body) or_return
|
expression := parse_key_condition_expression_string(request_body) or_return
|
||||||
|
defer delete(expression)
|
||||||
|
|
||||||
attr_names := parse_expression_attribute_names(request_body)
|
attr_names := parse_expression_attribute_names(request_body)
|
||||||
defer {
|
defer {
|
||||||
|
|||||||
@@ -817,7 +817,7 @@ parse_filter_expression_string :: proc(request_body: []byte) -> (expr: string, o
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
expr = string(fe_str)
|
expr = strings.clone(string(fe_str))
|
||||||
ok = true
|
ok = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -431,7 +431,7 @@ parse_table_name :: proc(request_body: []byte) -> (string, bool) {
|
|||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(table_name_str), true
|
return strings.clone(string(table_name_str)), true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse Item field from request body
|
// Parse Item field from request body
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ Cancellation_Reason :: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
transact_write_action_destroy :: proc(action: ^Transact_Write_Action) {
|
transact_write_action_destroy :: proc(action: ^Transact_Write_Action) {
|
||||||
|
delete(action.table_name)
|
||||||
|
if ce, has := action.condition_expr.?; has {
|
||||||
|
delete(ce)
|
||||||
|
}
|
||||||
if item, has := action.item.?; has {
|
if item, has := action.item.?; has {
|
||||||
item_copy := item
|
item_copy := item
|
||||||
item_destroy(&item_copy)
|
item_destroy(&item_copy)
|
||||||
@@ -618,8 +622,12 @@ Transact_Get_Result :: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
transact_get_action_destroy :: proc(action: ^Transact_Get_Action) {
|
transact_get_action_destroy :: proc(action: ^Transact_Get_Action) {
|
||||||
|
delete(action.table_name)
|
||||||
item_destroy(&action.key)
|
item_destroy(&action.key)
|
||||||
if proj, has := action.projection.?; has {
|
if proj, has := action.projection.?; has {
|
||||||
|
for path in proj {
|
||||||
|
delete(path)
|
||||||
|
}
|
||||||
delete(proj)
|
delete(proj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -930,7 +930,7 @@ parse_update_expression_string :: proc(request_body: []byte) -> (expr: string, o
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
expr = string(ue_str)
|
expr = strings.clone(string(ue_str))
|
||||||
ok = true
|
ok = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -939,24 +939,24 @@ parse_update_expression_string :: proc(request_body: []byte) -> (expr: string, o
|
|||||||
parse_return_values :: proc(request_body: []byte) -> string {
|
parse_return_values :: proc(request_body: []byte) -> string {
|
||||||
data, parse_err := json.parse(request_body, allocator = context.temp_allocator)
|
data, parse_err := json.parse(request_body, allocator = context.temp_allocator)
|
||||||
if parse_err != nil {
|
if parse_err != nil {
|
||||||
return "NONE"
|
return strings.clone("NONE")
|
||||||
}
|
}
|
||||||
defer json.destroy_value(data)
|
defer json.destroy_value(data)
|
||||||
|
|
||||||
root, root_ok := data.(json.Object)
|
root, root_ok := data.(json.Object)
|
||||||
if !root_ok {
|
if !root_ok {
|
||||||
return "NONE"
|
return strings.clone("NONE")
|
||||||
}
|
}
|
||||||
|
|
||||||
rv_val, found := root["ReturnValues"]
|
rv_val, found := root["ReturnValues"]
|
||||||
if !found {
|
if !found {
|
||||||
return "NONE"
|
return strings.clone("NONE")
|
||||||
}
|
}
|
||||||
|
|
||||||
rv_str, str_ok := rv_val.(json.String)
|
rv_str, str_ok := rv_val.(json.String)
|
||||||
if !str_ok {
|
if !str_ok {
|
||||||
return "NONE"
|
return strings.clone("NONE")
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(rv_str)
|
return strings.clone(string(rv_str))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ parse_index_name :: proc(request_body: []byte) -> Maybe(string) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(idx_str)
|
return strings.clone(string(idx_str))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
119
main.odin
119
main.odin
@@ -241,6 +241,7 @@ handle_describe_table :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_R
|
|||||||
make_error_response(response, .ValidationException, "Invalid request or missing TableName")
|
make_error_response(response, .ValidationException, "Invalid request or missing TableName")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer delete(table_name)
|
||||||
|
|
||||||
metadata, err := dynamodb.get_table_metadata(engine, table_name)
|
metadata, err := dynamodb.get_table_metadata(engine, table_name)
|
||||||
if err != .None {
|
if err != .None {
|
||||||
@@ -340,6 +341,7 @@ handle_put_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Request
|
|||||||
make_error_response(response, .ValidationException, "Invalid request or missing TableName")
|
make_error_response(response, .ValidationException, "Invalid request or missing TableName")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer delete(table_name)
|
||||||
|
|
||||||
item, item_ok := dynamodb.parse_item_from_request(request.body)
|
item, item_ok := dynamodb.parse_item_from_request(request.body)
|
||||||
if !item_ok {
|
if !item_ok {
|
||||||
@@ -349,8 +351,9 @@ handle_put_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Request
|
|||||||
defer dynamodb.item_destroy(&item)
|
defer dynamodb.item_destroy(&item)
|
||||||
|
|
||||||
// ---- ConditionExpression evaluation ----
|
// ---- ConditionExpression evaluation ----
|
||||||
_, has_condition := dynamodb.parse_condition_expression_string(request.body)
|
cond_str, has_condition := dynamodb.parse_condition_expression_string(request.body)
|
||||||
if has_condition {
|
if has_condition {
|
||||||
|
defer delete(cond_str)
|
||||||
// Parse shared expression attributes
|
// Parse shared expression attributes
|
||||||
attr_names := dynamodb.parse_expression_attribute_names(request.body)
|
attr_names := dynamodb.parse_expression_attribute_names(request.body)
|
||||||
defer {
|
defer {
|
||||||
@@ -468,9 +471,17 @@ handle_get_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Request
|
|||||||
|
|
||||||
if item_val, has_item := item.?; has_item {
|
if item_val, has_item := item.?; has_item {
|
||||||
defer dynamodb.item_destroy(&item_val)
|
defer dynamodb.item_destroy(&item_val)
|
||||||
item_json := dynamodb.serialize_item(item_val)
|
|
||||||
resp := fmt.aprintf(`{"Item":%s}`, item_json)
|
// Build response directly to avoid intermediate string allocations
|
||||||
response_set_body(response, transmute([]byte)resp)
|
builder := strings.builder_make(context.allocator)
|
||||||
|
defer strings.builder_destroy(&builder)
|
||||||
|
|
||||||
|
strings.write_string(&builder, `{"Item":`)
|
||||||
|
dynamodb.serialize_item_to_builder(&builder, item_val)
|
||||||
|
strings.write_string(&builder, `}`)
|
||||||
|
|
||||||
|
resp_body := strings.clone(strings.to_string(builder))
|
||||||
|
response_set_body(response, transmute([]byte)resp_body)
|
||||||
} else {
|
} else {
|
||||||
response_set_body(response, transmute([]byte)string("{}"))
|
response_set_body(response, transmute([]byte)string("{}"))
|
||||||
}
|
}
|
||||||
@@ -571,6 +582,7 @@ handle_update_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Requ
|
|||||||
make_error_response(response, .ValidationException, "Invalid request or missing TableName")
|
make_error_response(response, .ValidationException, "Invalid request or missing TableName")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer delete(table_name)
|
||||||
|
|
||||||
// Parse Key
|
// Parse Key
|
||||||
key_item, key_ok := dynamodb.parse_key_from_request(request.body)
|
key_item, key_ok := dynamodb.parse_key_from_request(request.body)
|
||||||
@@ -586,6 +598,7 @@ handle_update_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Requ
|
|||||||
make_error_response(response, .ValidationException, "Missing or invalid UpdateExpression")
|
make_error_response(response, .ValidationException, "Missing or invalid UpdateExpression")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer delete(update_expr)
|
||||||
|
|
||||||
// Parse ExpressionAttributeNames and ExpressionAttributeValues
|
// Parse ExpressionAttributeNames and ExpressionAttributeValues
|
||||||
attr_names := dynamodb.parse_expression_attribute_names(request.body)
|
attr_names := dynamodb.parse_expression_attribute_names(request.body)
|
||||||
@@ -661,6 +674,7 @@ handle_update_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Requ
|
|||||||
|
|
||||||
// Parse ReturnValues
|
// Parse ReturnValues
|
||||||
return_values := dynamodb.parse_return_values(request.body)
|
return_values := dynamodb.parse_return_values(request.body)
|
||||||
|
defer delete(return_values)
|
||||||
|
|
||||||
// Execute update
|
// Execute update
|
||||||
old_item, new_item, err := dynamodb.update_item(engine, table_name, key_item, &plan)
|
old_item, new_item, err := dynamodb.update_item(engine, table_name, key_item, &plan)
|
||||||
@@ -680,51 +694,59 @@ handle_update_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Requ
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build response based on ReturnValues
|
// Build response based on ReturnValues
|
||||||
|
builder := strings.builder_make(context.allocator)
|
||||||
|
defer strings.builder_destroy(&builder)
|
||||||
|
|
||||||
switch return_values {
|
switch return_values {
|
||||||
case "ALL_NEW":
|
case "ALL_NEW":
|
||||||
if new_val, has := new_item.?; has {
|
if new_val, has := new_item.?; has {
|
||||||
item_json := dynamodb.serialize_item(new_val)
|
strings.write_string(&builder, `{"Attributes":`)
|
||||||
resp := fmt.aprintf(`{"Attributes":%s}`, item_json)
|
dynamodb.serialize_item_to_builder(&builder, new_val)
|
||||||
response_set_body(response, transmute([]byte)resp)
|
strings.write_string(&builder, `}`)
|
||||||
} else {
|
} else {
|
||||||
response_set_body(response, transmute([]byte)string("{}"))
|
strings.write_string(&builder, `{}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "ALL_OLD":
|
case "ALL_OLD":
|
||||||
if old, has := old_item.?; has {
|
if old, has := old_item.?; has {
|
||||||
item_json := dynamodb.serialize_item(old)
|
strings.write_string(&builder, `{"Attributes":`)
|
||||||
resp := fmt.aprintf(`{"Attributes":%s}`, item_json)
|
dynamodb.serialize_item_to_builder(&builder, old)
|
||||||
response_set_body(response, transmute([]byte)resp)
|
strings.write_string(&builder, `}`)
|
||||||
} else {
|
} else {
|
||||||
response_set_body(response, transmute([]byte)string("{}"))
|
strings.write_string(&builder, `{}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "UPDATED_NEW":
|
case "UPDATED_NEW":
|
||||||
if new_val, has := new_item.?; has {
|
if new_val, has := new_item.?; has {
|
||||||
filtered := filter_updated_attributes(new_val, &plan)
|
filtered := filter_updated_attributes(new_val, &plan)
|
||||||
defer dynamodb.item_destroy(&filtered)
|
defer dynamodb.item_destroy(&filtered)
|
||||||
item_json := dynamodb.serialize_item(filtered)
|
|
||||||
resp := fmt.aprintf(`{"Attributes":%s}`, item_json)
|
strings.write_string(&builder, `{"Attributes":`)
|
||||||
response_set_body(response, transmute([]byte)resp)
|
dynamodb.serialize_item_to_builder(&builder, filtered)
|
||||||
|
strings.write_string(&builder, `}`)
|
||||||
} else {
|
} else {
|
||||||
response_set_body(response, transmute([]byte)string("{}"))
|
strings.write_string(&builder, `{}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "UPDATED_OLD":
|
case "UPDATED_OLD":
|
||||||
if old, has := old_item.?; has {
|
if old, has := old_item.?; has {
|
||||||
filtered := filter_updated_attributes(old, &plan)
|
filtered := filter_updated_attributes(old, &plan)
|
||||||
defer dynamodb.item_destroy(&filtered)
|
defer dynamodb.item_destroy(&filtered)
|
||||||
item_json := dynamodb.serialize_item(filtered)
|
|
||||||
resp := fmt.aprintf(`{"Attributes":%s}`, item_json)
|
strings.write_string(&builder, `{"Attributes":`)
|
||||||
response_set_body(response, transmute([]byte)resp)
|
dynamodb.serialize_item_to_builder(&builder, filtered)
|
||||||
|
strings.write_string(&builder, `}`)
|
||||||
} else {
|
} else {
|
||||||
response_set_body(response, transmute([]byte)string("{}"))
|
strings.write_string(&builder, `{}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
case:
|
case:
|
||||||
// "NONE" or default
|
// "NONE" or default
|
||||||
response_set_body(response, transmute([]byte)string("{}"))
|
strings.write_string(&builder, `{}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resp_body := strings.clone(strings.to_string(builder))
|
||||||
|
response_set_body(response, transmute([]byte)resp_body)
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_batch_write_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Request, response: ^HTTP_Response) {
|
handle_batch_write_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Request, response: ^HTTP_Response) {
|
||||||
@@ -872,7 +894,7 @@ handle_batch_write_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP
|
|||||||
}
|
}
|
||||||
|
|
||||||
append(&table_requests, dynamodb.Batch_Write_Table_Request{
|
append(&table_requests, dynamodb.Batch_Write_Table_Request{
|
||||||
table_name = string(table_name),
|
table_name = strings.clone(string(table_name)),
|
||||||
requests = requests[:],
|
requests = requests[:],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1010,7 +1032,7 @@ handle_batch_get_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_R
|
|||||||
}
|
}
|
||||||
|
|
||||||
append(&table_requests, dynamodb.Batch_Get_Table_Request{
|
append(&table_requests, dynamodb.Batch_Get_Table_Request{
|
||||||
table_name = string(table_name),
|
table_name = strings.clone(string(table_name)),
|
||||||
keys = keys[:],
|
keys = keys[:],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1037,7 +1059,9 @@ handle_batch_get_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_R
|
|||||||
defer dynamodb.batch_get_result_destroy(&result)
|
defer dynamodb.batch_get_result_destroy(&result)
|
||||||
|
|
||||||
// Build response
|
// Build response
|
||||||
builder := strings.builder_make()
|
builder := strings.builder_make(context.allocator)
|
||||||
|
defer strings.builder_destroy(&builder)
|
||||||
|
|
||||||
strings.write_string(&builder, `{"Responses":{`)
|
strings.write_string(&builder, `{"Responses":{`)
|
||||||
|
|
||||||
for table_result, ti in result.responses {
|
for table_result, ti in result.responses {
|
||||||
@@ -1050,8 +1074,7 @@ handle_batch_get_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_R
|
|||||||
if ii > 0 {
|
if ii > 0 {
|
||||||
strings.write_string(&builder, ",")
|
strings.write_string(&builder, ",")
|
||||||
}
|
}
|
||||||
item_json := dynamodb.serialize_item(item)
|
dynamodb.serialize_item_to_builder(&builder, item)
|
||||||
strings.write_string(&builder, item_json)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strings.write_string(&builder, "]")
|
strings.write_string(&builder, "]")
|
||||||
@@ -1069,8 +1092,7 @@ handle_batch_get_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_R
|
|||||||
if ki > 0 {
|
if ki > 0 {
|
||||||
strings.write_string(&builder, ",")
|
strings.write_string(&builder, ",")
|
||||||
}
|
}
|
||||||
key_json := dynamodb.serialize_item(key)
|
dynamodb.serialize_item_to_builder(&builder, key)
|
||||||
strings.write_string(&builder, key_json)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strings.write_string(&builder, "]}")
|
strings.write_string(&builder, "]}")
|
||||||
@@ -1078,7 +1100,8 @@ handle_batch_get_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_R
|
|||||||
|
|
||||||
strings.write_string(&builder, "}}")
|
strings.write_string(&builder, "}}")
|
||||||
|
|
||||||
resp_body := strings.to_string(builder)
|
// clone the god damn string
|
||||||
|
resp_body := strings.clone(strings.to_string(builder))
|
||||||
response_set_body(response, transmute([]byte)resp_body)
|
response_set_body(response, transmute([]byte)resp_body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1093,9 +1116,15 @@ handle_query :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Request, r
|
|||||||
make_error_response(response, .ValidationException, "Invalid request or missing TableName")
|
make_error_response(response, .ValidationException, "Invalid request or missing TableName")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer delete(table_name)
|
||||||
|
|
||||||
// Grab index name from request body
|
// Grab index name from request body
|
||||||
index_name := parse_index_name(request.body)
|
index_name := parse_index_name(request.body)
|
||||||
|
defer {
|
||||||
|
if idx, has := index_name.?; has {
|
||||||
|
delete(idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch table metadata early for ExclusiveStartKey parsing
|
// Fetch table metadata early for ExclusiveStartKey parsing
|
||||||
metadata, meta_err := dynamodb.get_table_metadata(engine, table_name)
|
metadata, meta_err := dynamodb.get_table_metadata(engine, table_name)
|
||||||
@@ -1300,9 +1329,15 @@ handle_scan :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Request, re
|
|||||||
make_error_response(response, .ValidationException, "Invalid request or missing TableName")
|
make_error_response(response, .ValidationException, "Invalid request or missing TableName")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer delete(table_name)
|
||||||
|
|
||||||
// Grab index name from request body
|
// Grab index name from request body
|
||||||
index_name := parse_index_name(request.body)
|
index_name := parse_index_name(request.body)
|
||||||
|
defer {
|
||||||
|
if idx, has := index_name.?; has {
|
||||||
|
delete(idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
metadata, meta_err := dynamodb.get_table_metadata(engine, table_name)
|
metadata, meta_err := dynamodb.get_table_metadata(engine, table_name)
|
||||||
if meta_err != .None {
|
if meta_err != .None {
|
||||||
@@ -1482,6 +1517,7 @@ apply_filter_to_items :: proc(
|
|||||||
if !has_filter {
|
if !has_filter {
|
||||||
return items, true
|
return items, true
|
||||||
}
|
}
|
||||||
|
defer delete(filter_expr)
|
||||||
|
|
||||||
filter_node, filter_ok := dynamodb.parse_filter_expression(filter_expr, attr_names, attr_values)
|
filter_node, filter_ok := dynamodb.parse_filter_expression(filter_expr, attr_names, attr_values)
|
||||||
if !filter_ok || filter_node == nil {
|
if !filter_ok || filter_node == nil {
|
||||||
@@ -1517,13 +1553,15 @@ write_items_response_with_pagination_ex :: proc(
|
|||||||
metadata: ^dynamodb.Table_Metadata,
|
metadata: ^dynamodb.Table_Metadata,
|
||||||
scanned_count: int,
|
scanned_count: int,
|
||||||
) {
|
) {
|
||||||
builder := strings.builder_make()
|
builder := strings.builder_make(context.allocator)
|
||||||
|
defer strings.builder_destroy(&builder)
|
||||||
|
|
||||||
strings.write_string(&builder, `{"Items":[`)
|
strings.write_string(&builder, `{"Items":[`)
|
||||||
|
|
||||||
|
// Use serialize_item_to_builder directly an NOT serialize_item
|
||||||
for item, i in items {
|
for item, i in items {
|
||||||
if i > 0 do strings.write_string(&builder, ",")
|
if i > 0 do strings.write_string(&builder, ",")
|
||||||
item_json := dynamodb.serialize_item(item)
|
dynamodb.serialize_item_to_builder(&builder, item)
|
||||||
strings.write_string(&builder, item_json)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strings.write_string(&builder, `],"Count":`)
|
strings.write_string(&builder, `],"Count":`)
|
||||||
@@ -1541,7 +1579,8 @@ write_items_response_with_pagination_ex :: proc(
|
|||||||
|
|
||||||
strings.write_string(&builder, "}")
|
strings.write_string(&builder, "}")
|
||||||
|
|
||||||
resp_body := strings.to_string(builder)
|
// We have to Clone the string before passing to response_set_body
|
||||||
|
resp_body := strings.clone(strings.to_string(builder))
|
||||||
response_set_body(response, transmute([]byte)resp_body)
|
response_set_body(response, transmute([]byte)resp_body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1561,13 +1600,15 @@ write_items_response_with_pagination :: proc(
|
|||||||
last_evaluated_key_binary: Maybe([]byte),
|
last_evaluated_key_binary: Maybe([]byte),
|
||||||
metadata: ^dynamodb.Table_Metadata,
|
metadata: ^dynamodb.Table_Metadata,
|
||||||
) {
|
) {
|
||||||
builder := strings.builder_make()
|
builder := strings.builder_make(context.allocator)
|
||||||
|
defer strings.builder_destroy(&builder)
|
||||||
|
|
||||||
strings.write_string(&builder, `{"Items":[`)
|
strings.write_string(&builder, `{"Items":[`)
|
||||||
|
|
||||||
|
// Use serialize_item_to_builder directly so we always get the correct response payload
|
||||||
for item, i in items {
|
for item, i in items {
|
||||||
if i > 0 do strings.write_string(&builder, ",")
|
if i > 0 do strings.write_string(&builder, ",")
|
||||||
item_json := dynamodb.serialize_item(item)
|
dynamodb.serialize_item_to_builder(&builder, item)
|
||||||
strings.write_string(&builder, item_json)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strings.write_string(&builder, `],"Count":`)
|
strings.write_string(&builder, `],"Count":`)
|
||||||
@@ -1575,20 +1616,18 @@ write_items_response_with_pagination :: proc(
|
|||||||
strings.write_string(&builder, `,"ScannedCount":`)
|
strings.write_string(&builder, `,"ScannedCount":`)
|
||||||
fmt.sbprintf(&builder, "%d", len(items))
|
fmt.sbprintf(&builder, "%d", len(items))
|
||||||
|
|
||||||
// Emit LastEvaluatedKey if the storage layer produced one
|
|
||||||
if binary_key, has_last := last_evaluated_key_binary.?; has_last {
|
if binary_key, has_last := last_evaluated_key_binary.?; has_last {
|
||||||
lek_json, lek_ok := dynamodb.serialize_last_evaluated_key(binary_key, metadata)
|
lek_json, lek_ok := dynamodb.serialize_last_evaluated_key(binary_key, metadata)
|
||||||
if lek_ok {
|
if lek_ok {
|
||||||
strings.write_string(&builder, `,"LastEvaluatedKey":`)
|
strings.write_string(&builder, `,"LastEvaluatedKey":`)
|
||||||
strings.write_string(&builder, lek_json)
|
strings.write_string(&builder, lek_json)
|
||||||
}
|
}
|
||||||
// If decoding fails we still return the items — just without a pagination token.
|
|
||||||
// The client will assume the scan/query is complete.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strings.write_string(&builder, "}")
|
strings.write_string(&builder, "}")
|
||||||
|
|
||||||
resp_body := strings.to_string(builder)
|
// We have to Clone the string before passing to response_set_body
|
||||||
|
resp_body := strings.clone(strings.to_string(builder))
|
||||||
response_set_body(response, transmute([]byte)resp_body)
|
response_set_body(response, transmute([]byte)resp_body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ parse_transact_put_action :: proc(
|
|||||||
if !tn_ok {
|
if !tn_ok {
|
||||||
return {}, false
|
return {}, false
|
||||||
}
|
}
|
||||||
action.table_name = string(tn_str)
|
action.table_name = strings.clone(string(tn_str))
|
||||||
|
|
||||||
// Item
|
// Item
|
||||||
item_val, item_found := obj["Item"]
|
item_val, item_found := obj["Item"]
|
||||||
@@ -301,7 +301,7 @@ parse_transact_key_action :: proc(
|
|||||||
if !tn_ok {
|
if !tn_ok {
|
||||||
return {}, false
|
return {}, false
|
||||||
}
|
}
|
||||||
action.table_name = string(tn_str)
|
action.table_name = strings.clone(string(tn_str))
|
||||||
|
|
||||||
// Key
|
// Key
|
||||||
key_val, key_found := obj["Key"]
|
key_val, key_found := obj["Key"]
|
||||||
@@ -335,7 +335,7 @@ parse_transact_update_action :: proc(
|
|||||||
if !tn_ok {
|
if !tn_ok {
|
||||||
return {}, false
|
return {}, false
|
||||||
}
|
}
|
||||||
action.table_name = string(tn_str)
|
action.table_name = strings.clone(string(tn_str))
|
||||||
|
|
||||||
// Key
|
// Key
|
||||||
key_val, key_found := obj["Key"]
|
key_val, key_found := obj["Key"]
|
||||||
@@ -483,7 +483,9 @@ handle_transact_get_items :: proc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build response
|
// Build response
|
||||||
builder := strings.builder_make()
|
builder := strings.builder_make(context.allocator)
|
||||||
|
defer strings.builder_destroy(&builder)
|
||||||
|
|
||||||
strings.write_string(&builder, `{"Responses":[`)
|
strings.write_string(&builder, `{"Responses":[`)
|
||||||
|
|
||||||
for maybe_item, i in result.items {
|
for maybe_item, i in result.items {
|
||||||
@@ -492,8 +494,9 @@ handle_transact_get_items :: proc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if item, has_item := maybe_item.?; has_item {
|
if item, has_item := maybe_item.?; has_item {
|
||||||
item_json := dynamodb.serialize_item(item)
|
strings.write_string(&builder, `{"Item":`)
|
||||||
fmt.sbprintf(&builder, `{{"Item":%s}}`, item_json)
|
dynamodb.serialize_item_to_builder(&builder, item)
|
||||||
|
strings.write_string(&builder, `}`)
|
||||||
} else {
|
} else {
|
||||||
strings.write_string(&builder, "{}")
|
strings.write_string(&builder, "{}")
|
||||||
}
|
}
|
||||||
@@ -501,7 +504,8 @@ handle_transact_get_items :: proc(
|
|||||||
|
|
||||||
strings.write_string(&builder, "]}")
|
strings.write_string(&builder, "]}")
|
||||||
|
|
||||||
resp_body := strings.to_string(builder)
|
// Clone the string or we gonna have issues again
|
||||||
|
resp_body := strings.clone(strings.to_string(builder))
|
||||||
response_set_body(response, transmute([]byte)resp_body)
|
response_set_body(response, transmute([]byte)resp_body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,7 +523,7 @@ parse_transact_get_action :: proc(obj: json.Object) -> (dynamodb.Transact_Get_Ac
|
|||||||
if !tn_ok {
|
if !tn_ok {
|
||||||
return {}, false
|
return {}, false
|
||||||
}
|
}
|
||||||
action.table_name = string(tn_str)
|
action.table_name = strings.clone(string(tn_str))
|
||||||
|
|
||||||
// Key
|
// Key
|
||||||
key_val, key_found := obj["Key"]
|
key_val, key_found := obj["Key"]
|
||||||
|
|||||||
Reference in New Issue
Block a user