Repository: duckdb/duckdb (language: python)

Issue:
C API - Cannot get named parameter type
### What happens?

When using [named parameters](https://duckdb.org/docs/sql/query_syntax/prepared_statements.html#named-parameters-parameter), `duckdb_param_type` always returns `Invalid`. Works fine for other types of parameters.


### To Reproduce


```c
state = duckdb_open(NULL, &db);
state = duckdb_connect(db, &connection);

state = duckdb_prepare(connection, "CREATE TABLE person (name VARCHAR, age BIGINT);", &preparedStatement);
state = duckdb_execute_prepared(preparedStatement, &result);

state = duckdb_prepare(connection, "INSERT INTO person VALUES ('Alice', 37), ('Ana', 35), ('Bob', 41), ('Bea', 25);", &preparedStatement);
state = duckdb_execute_prepared(preparedStatement, &result);

state = duckdb_prepare(connection, "Select * from person where age=$age;", &preparedStatement);

//paramType is Invalid. Works fine if I use positional or auto-incremented parameters.
auto paramType = duckdb_param_type(preparedStatement, 1);
```

### OS:

Windows 11 x64

### DuckDB Version:

1.1.3

### DuckDB Client:

C Api

### Hardware:

_No response_

### Full Name:

Giorgi Dalakishvili

### Affiliation:

Personal

### What is the latest build you tested with? If possible, we recommend testing with the latest nightly build.

I have tested with a stable release

### Did you include all relevant data sets for reproducing the issue?

Not applicable - the reproduction does not require a data set

### Did you include all code required to reproduce the issue?

- [X] Yes, I have

### Did you include all relevant configuration (e.g., CPU architecture, Python version, Linux distribution) to reproduce the issue?

- [X] Yes, I have


Discussion / hints:
I looked into this a little while ago, and noticed that the code path for `duckdb_param_type` [converts the provided index directly to a string](https://github.com/duckdb/duckdb/blob/448b46937fcafdc789b053536d093ef22b9105b5/src/main/capi/prepared-c.cpp#L143), without using the `named_param_map` as is done [elsewhere](https://github.com/duckdb/duckdb/blob/448b46937fcafdc789b053536d093ef22b9105b5/src/main/capi/prepared-c.cpp#L104). This seems likely to be the problem.

Fix patch:
diff --git a/src/main/capi/prepared-c.cpp b/src/main/capi/prepared-c.cpp
index 0b8ba116a808..a065f41a5350 100644
--- a/src/main/capi/prepared-c.cpp
+++ b/src/main/capi/prepared-c.cpp
@@ -139,8 +139,14 @@ duckdb_logical_type duckdb_param_logical_type(duckdb_prepared_statement prepared
 	if (!wrapper || !wrapper->statement || wrapper->statement->HasError()) {
 		return nullptr;
 	}
+
+	auto identifier = duckdb_parameter_name_internal(prepared_statement, param_idx);
+	if (identifier == duckdb::string()) {
+		return nullptr;
+	}
+
 	LogicalType param_type;
-	auto identifier = std::to_string(param_idx);
+
 	if (wrapper->statement->data->TryGetType(identifier, param_type)) {
 		return reinterpret_cast<duckdb_logical_type>(new LogicalType(param_type));
 	}


Test patch:
diff --git a/test/api/capi/test_capi_prepared.cpp b/test/api/capi/test_capi_prepared.cpp
index 1f07cdb74f07..bddc23f9d919 100644
--- a/test/api/capi/test_capi_prepared.cpp
+++ b/test/api/capi/test_capi_prepared.cpp
@@ -351,6 +351,13 @@ TEST_CASE("Test prepared statements with named parameters in C API", "[capi]") {
 	status = duckdb_bind_parameter_index(stmt, &parameter_index, "my_val");
 	REQUIRE(status == DuckDBSuccess);
 
+	REQUIRE(duckdb_param_type(stmt, 1) == DUCKDB_TYPE_BIGINT);
+
+	auto logical_type = duckdb_param_logical_type(stmt, 1);
+	REQUIRE(logical_type);
+	REQUIRE(duckdb_get_type_id(logical_type) == DUCKDB_TYPE_BIGINT);
+	duckdb_destroy_logical_type(&logical_type);
+
 	idx_t param_count = duckdb_nparams(stmt);
 	duckdb::vector<string> names;
 	for (idx_t i = 0; i < param_count; i++) {