Skip to content

Commit d42b01c

Browse files
authored
fix(api): improve SQL query result type handling and formatting (#22)
* add prompt to format SQL query properly * handle SQL types explicitly
1 parent c760c04 commit d42b01c

File tree

2 files changed

+58
-6
lines changed

2 files changed

+58
-6
lines changed

api/src/routes/mod.rs

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use axum::{
55
Json as RequestJson,
66
};
77
use serde_json::{json, Value};
8-
use sqlx::{PgPool, Row, Column};
8+
use sqlx::{PgPool, Row, Column, TypeInfo};
99

1010
use crate::models::{Car, QueryRequest, QueryResponse};
1111

@@ -75,12 +75,60 @@ pub async fn query(
7575
let mut map = serde_json::Map::new();
7676
for i in 0..row.len() {
7777
let column_name = row.column(i).name();
78-
let value: Option<Value> = row.try_get(i).ok();
79-
if let Some(v) = value {
80-
map.insert(column_name.to_string(), v);
78+
// Type info is used only in the fallback case
79+
80+
// Handle different data types explicitly
81+
let value = if let Ok(v) = row.try_get::<Option<i32>, _>(i) {
82+
match v {
83+
Some(val) => json!(val),
84+
None => Value::Null,
85+
}
86+
} else if let Ok(v) = row.try_get::<Option<i64>, _>(i) {
87+
match v {
88+
Some(val) => json!(val),
89+
None => Value::Null,
90+
}
91+
} else if let Ok(v) = row.try_get::<Option<f64>, _>(i) {
92+
match v {
93+
Some(val) => json!(val),
94+
None => Value::Null,
95+
}
96+
} else if let Ok(v) = row.try_get::<Option<String>, _>(i) {
97+
match v {
98+
Some(val) => json!(val),
99+
None => Value::Null,
100+
}
101+
} else if let Ok(v) = row.try_get::<Option<bool>, _>(i) {
102+
match v {
103+
Some(val) => json!(val),
104+
None => Value::Null,
105+
}
81106
} else {
82-
map.insert(column_name.to_string(), Value::Null);
83-
}
107+
// For any other types, try simpler approaches
108+
let type_info = row.column(i).type_info();
109+
let type_name = type_info.name();
110+
111+
// Try to decode as JSON value first (works for many types)
112+
if let Ok(v) = row.try_get::<Option<serde_json::Value>, _>(i) {
113+
match v {
114+
Some(val) => val,
115+
None => Value::Null,
116+
}
117+
} else {
118+
// Try to get as a string (most types can be represented as strings)
119+
if let Ok(v) = row.try_get::<Option<String>, _>(i) {
120+
match v {
121+
Some(s) => json!(s),
122+
None => Value::Null,
123+
}
124+
} else {
125+
// If all else fails, return the type name as a fallback
126+
json!(format!("Value of type: {}", type_name))
127+
}
128+
}
129+
};
130+
131+
map.insert(column_name.to_string(), value);
84132
}
85133
Value::Object(map)
86134
})

llm_engine/src/llm_processor.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ async fn call_llm_api(prompt: &str, model_name: &str) -> Result<String> {
8585
role: "system".to_string(),
8686
content: "You are a helpful assistant that translates natural language questions into SQL queries for a PostgreSQL database.".to_string(),
8787
},
88+
OpenAIMessage {
89+
role: "system".to_string(),
90+
content: "Format SQL queries in a single line, without backticks, and with a semi-colon at the end.".to_string(),
91+
},
8892
OpenAIMessage {
8993
role: "user".to_string(),
9094
content: prompt.to_string(),

0 commit comments

Comments
 (0)