flesh out the query stuff

This commit is contained in:
2026-02-15 15:04:43 -05:00
parent 94296ae925
commit 7a2f26b75d
5 changed files with 917 additions and 23 deletions

View File

@@ -258,12 +258,15 @@ handle_describe_table :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_R
}
handle_list_tables :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Request, response: ^HTTP_Response) {
_ = request // Not using request body for ListTables
_ = request
tables := dynamodb.list_tables(engine)
// list_tables returns []string which may be empty, not an error
tables, err := dynamodb.list_tables(engine)
if err != .None {
make_error_response(response, .InternalServerError, "Failed to list tables")
return
}
// tables are owned by engine allocator — just read them, don't free
// Build response
builder := strings.builder_make()
strings.write_string(&builder, `{"TableNames":[`)
@@ -390,11 +393,77 @@ handle_delete_item :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Requ
// ============================================================================
handle_query :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Request, response: ^HTTP_Response) {
_ = engine
_ = request
// For now, return not implemented
// TODO: Implement KeyConditionExpression parsing and query logic
make_error_response(response, .ValidationException, "Query operation not yet implemented")
table_name, ok := dynamodb.parse_table_name(request.body)
if !ok {
make_error_response(response, .ValidationException, "Invalid request or missing TableName")
return
}
// Parse KeyConditionExpression
kc, kc_ok := dynamodb.parse_query_key_condition(request.body)
if !kc_ok {
make_error_response(response, .ValidationException, "Missing or invalid KeyConditionExpression")
return
}
defer dynamodb.key_condition_destroy(&kc)
// Extract partition key bytes
pk_bytes, pk_ok := dynamodb.key_condition_get_pk_bytes(&kc)
if !pk_ok {
make_error_response(response, .ValidationException, "Invalid partition key type")
return
}
// Clone pk_bytes so it survives kc cleanup (kc borrows from the parsed value)
pk_owned := make([]byte, len(pk_bytes))
copy(pk_owned, pk_bytes)
defer delete(pk_owned)
// Parse Limit
limit := dynamodb.parse_limit(request.body)
if limit == 0 {
limit = 100
}
// TODO: Parse ExclusiveStartKey properly (requires metadata for type info)
exclusive_start_key: Maybe([]byte) = nil
result, err := dynamodb.query(engine, table_name, pk_owned, exclusive_start_key, limit)
if err != .None {
#partial switch err {
case .Table_Not_Found:
make_error_response(response, .ResourceNotFoundException, "Table not found")
case:
make_error_response(response, .InternalServerError, "Query failed")
}
return
}
defer dynamodb.query_result_destroy(&result)
// Build response
builder := strings.builder_make()
strings.write_string(&builder, `{"Items":[`)
for item, i in result.items {
if i > 0 do strings.write_string(&builder, ",")
item_json := dynamodb.serialize_item(item)
strings.write_string(&builder, item_json)
}
strings.write_string(&builder, `],"Count":`)
fmt.sbprintf(&builder, "%d", len(result.items))
strings.write_string(&builder, `,"ScannedCount":`)
fmt.sbprintf(&builder, "%d", len(result.items))
// TODO: Add LastEvaluatedKey when pagination is fully wired
if last_key, has_last := result.last_evaluated_key.?; has_last {
_ = last_key
}
strings.write_string(&builder, "}")
resp_body := strings.to_string(builder)
response_set_body(response, transmute([]byte)resp_body)
}
handle_scan :: proc(engine: ^dynamodb.Storage_Engine, request: ^HTTP_Request, response: ^HTTP_Response) {