mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-30 06:24:21 +01:00
Merge 'bindings/rust: Add Statement.columns() support' from Timo Kösters
This PR adds the statement.columns() function, inspired from Rusqlite: h ttps://docs.rs/rusqlite/latest/rusqlite/struct.Statement.html#method.col umns Note that the rusqlite documentation says > If associated DB schema can be altered concurrently, you should make sure that current statement has already been stepped once before calling this method. Do we have this requirement as well? The first commit is just the rust binding. The second commit implements the column name for the rowid column. Closes #1376
This commit is contained in:
@@ -138,7 +138,7 @@ pub extern "system" fn Java_tech_turso_core_LimboStatement_columns<'local>(
|
||||
|
||||
for i in 0..num_columns {
|
||||
let column_name = stmt.stmt.get_column_name(i);
|
||||
let str = env.new_string(column_name.as_str()).unwrap();
|
||||
let str = env.new_string(column_name.into_owned()).unwrap();
|
||||
env.set_object_array_element(&obj_arr, i as i32, str)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -190,6 +190,39 @@ impl Statement {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn columns(&self) -> Vec<Column> {
|
||||
let stmt = self.inner.lock().unwrap();
|
||||
|
||||
let n = stmt.num_columns();
|
||||
|
||||
let mut cols = Vec::with_capacity(n);
|
||||
|
||||
for i in 0..n {
|
||||
let name = stmt.get_column_name(i).into_owned();
|
||||
cols.push(Column {
|
||||
name,
|
||||
decl_type: None, // TODO
|
||||
});
|
||||
}
|
||||
|
||||
cols
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Column {
|
||||
name: String,
|
||||
decl_type: Option<String>,
|
||||
}
|
||||
|
||||
impl Column {
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn decl_type(&self) -> Option<&str> {
|
||||
self.decl_type.as_deref()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoValue {
|
||||
|
||||
@@ -591,7 +591,7 @@ impl Statement {
|
||||
self.program.result_columns.len()
|
||||
}
|
||||
|
||||
pub fn get_column_name(&self, idx: usize) -> Cow<String> {
|
||||
pub fn get_column_name(&self, idx: usize) -> Cow<str> {
|
||||
let column = &self.program.result_columns[idx];
|
||||
match column.name(&self.program.table_references) {
|
||||
Some(name) => Cow::Borrowed(name),
|
||||
|
||||
@@ -34,13 +34,26 @@ pub struct ResultSetColumn {
|
||||
}
|
||||
|
||||
impl ResultSetColumn {
|
||||
pub fn name<'a>(&'a self, tables: &'a [TableReference]) -> Option<&'a String> {
|
||||
pub fn name<'a>(&'a self, tables: &'a [TableReference]) -> Option<&'a str> {
|
||||
if let Some(alias) = &self.alias {
|
||||
return Some(alias);
|
||||
}
|
||||
match &self.expr {
|
||||
ast::Expr::Column { table, column, .. } => {
|
||||
tables[*table].columns()[*column].name.as_ref()
|
||||
tables[*table].columns()[*column].name.as_deref()
|
||||
}
|
||||
ast::Expr::RowId { table, .. } => {
|
||||
// If there is a rowid alias column, use its name
|
||||
if let Table::BTree(table) = &tables[*table].table {
|
||||
if let Some(rowid_alias_column) = table.get_rowid_alias_column() {
|
||||
if let Some(name) = &rowid_alias_column.1.name {
|
||||
return Some(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no rowid alias, use "rowid".
|
||||
Some("rowid")
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
@@ -465,7 +478,7 @@ impl TableReference {
|
||||
plan.result_columns
|
||||
.iter()
|
||||
.map(|rc| Column {
|
||||
name: rc.name(&plan.table_references).map(String::clone),
|
||||
name: rc.name(&plan.table_references).map(String::from),
|
||||
ty: Type::Text, // FIXME: infer proper type
|
||||
ty_str: "TEXT".to_string(),
|
||||
is_rowid_alias: false,
|
||||
|
||||
@@ -120,16 +120,16 @@ mod tests {
|
||||
|
||||
let columns = stmt.num_columns();
|
||||
assert_eq!(columns, 3);
|
||||
assert_eq!(stmt.get_column_name(0), "foo".into());
|
||||
assert_eq!(stmt.get_column_name(1), "bar".into());
|
||||
assert_eq!(stmt.get_column_name(2), "baz".into());
|
||||
assert_eq!(stmt.get_column_name(0), "foo");
|
||||
assert_eq!(stmt.get_column_name(1), "bar");
|
||||
assert_eq!(stmt.get_column_name(2), "baz");
|
||||
|
||||
let stmt = conn.prepare("select foo, bar from test;")?;
|
||||
|
||||
let columns = stmt.num_columns();
|
||||
assert_eq!(columns, 2);
|
||||
assert_eq!(stmt.get_column_name(0), "foo".into());
|
||||
assert_eq!(stmt.get_column_name(1), "bar".into());
|
||||
assert_eq!(stmt.get_column_name(0), "foo");
|
||||
assert_eq!(stmt.get_column_name(1), "bar");
|
||||
|
||||
let stmt = conn.prepare("delete from test;")?;
|
||||
let columns = stmt.num_columns();
|
||||
|
||||
Reference in New Issue
Block a user