Skip to content

Commit d83f8bb

Browse files
committed
Fix to get column value
1 parent 41ee0a2 commit d83f8bb

File tree

7 files changed

+103
-48
lines changed

7 files changed

+103
-48
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct User {
1616
fn main() -> crossdb::Result<()> {
1717
let mut conn = crossdb::Connection::open_with_memory()?;
1818

19-
conn.execute("CREATE TABLE IF NOT EXISTS users(id INT, name CHAR(255), age TINYINT);")?;
19+
conn.execute("CREATE TABLE IF NOT EXISTS users(id INT, name VARCHAR, age TINYINT);")?;
2020
let stmt = conn.prepare("INSERT INTO users (id, name, age) values (?, ?, ?);")?;
2121

2222
stmt.execute((1, "Alex", 18))?;

src/column.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub enum DataType {
5252
}
5353

5454
impl DataType {
55-
unsafe fn from_meta(ptr: *mut xdb_res_t, col: u16) -> Self {
55+
unsafe fn from_res(ptr: *mut xdb_res_t, col: u16) -> Self {
5656
let t = xdb_column_type(ptr, col);
5757
match Self::from_repr(t) {
5858
Some(t) => t,
@@ -76,7 +76,7 @@ impl Columns {
7676
.to_str()
7777
.unwrap()
7878
.to_string();
79-
let datatype = DataType::from_meta(ptr, i);
79+
let datatype = DataType::from_res(ptr, i);
8080
columns.push(Column::new(name, datatype));
8181
}
8282
}

src/de.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,6 @@ impl<'de> Deserializer<'de> for ValueDeserializer<'de> {
8383
{
8484
match *self.0 {
8585
Value::Null => visitor.visit_none(),
86-
Value::I8(v) => visitor.visit_i8(v),
87-
Value::I16(v) => visitor.visit_i16(v),
8886
Value::I32(v) => visitor.visit_i32(v),
8987
Value::I64(v) => visitor.visit_i64(v),
9088
Value::F32(v) => visitor.visit_f32(v),
@@ -141,13 +139,13 @@ mod tests {
141139
de(&Value::Null, None::<i8>);
142140
de(&Value::Null, None::<String>);
143141

144-
de(&Value::I8(1), 1i8);
145-
de(&Value::I8(1), Some(1i8));
146-
de(&Value::I8(1), Some(1_u128));
142+
de(&Value::I32(1), 1_i32);
143+
de(&Value::I32(1), Some(1_i32));
144+
de(&Value::I32(1), Some(1_u128));
147145

148-
de(&Value::I16(1), 1i16);
149-
de(&Value::I16(1), Some(1i16));
150-
de(&Value::I16(1), Some(1_u128));
146+
de(&Value::I64(1), 1_i16);
147+
de(&Value::I64(1), Some(1_i16));
148+
de(&Value::I64(1), Some(1_u128));
151149

152150
de(&Value::String("Hello"), String::from("Hello"));
153151
de(&Value::String("Hello"), Some(String::from("Hello")));

src/lib.rs

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub use value::Value;
2828
use crossdb_sys::*;
2929
use lru::LruCache;
3030
use serde::de::{value::Error as DeError, DeserializeOwned};
31-
use std::ffi::{c_void, CStr, CString};
31+
use std::ffi::{CStr, CString};
3232
use std::fmt::Display;
3333
use std::num::NonZeroUsize;
3434
use std::slice::from_raw_parts;
@@ -187,17 +187,69 @@ impl Query {
187187

188188
fn inner_fetch_row_values(&mut self) -> Option<Vec<Value<'_>>> {
189189
unsafe {
190-
let row: *mut c_void = xdb_fetch_row(self.ptr);
190+
let row = xdb_fetch_row(self.ptr);
191191
if row.is_null() {
192192
return None;
193193
}
194194
let count = self.columns.len();
195195
let mut values = Vec::with_capacity(count);
196-
let iter = from_raw_parts(row, count).iter().enumerate();
197-
for (i, ptr) in iter {
198-
values.push(Value::from_ptr(ptr, self.columns.datatype(i)));
196+
for i in 0..count {
197+
let v = Value::from_ptr(self.ptr, row, i as u16, self.columns.datatype(i));
198+
values.push(v);
199199
}
200200
Some(values)
201201
}
202202
}
203203
}
204+
205+
#[cfg(test)]
206+
mod tests {
207+
use super::*;
208+
209+
#[test]
210+
fn test_query() {
211+
let mut conn = Connection::open_with_memory().unwrap();
212+
213+
conn.execute("CREATE TABLE IF NOT EXISTS users(id INT, name VARCHAR(255), age TINYINT);")
214+
.unwrap();
215+
let stmt = conn
216+
.prepare("INSERT INTO users (id, name, age) values (?, ?, ?);")
217+
.unwrap();
218+
219+
stmt.execute((1, "Alex", 18)).unwrap();
220+
stmt.execute((2, "Thorne", 22)).unwrap();
221+
stmt.execute((3, "Ryder", 36)).unwrap();
222+
223+
let mut query = conn.query("SELECT * FROM users;").unwrap();
224+
225+
assert_eq!(query.row_count(), 3);
226+
assert_eq!(query.column_count(), 3);
227+
228+
assert_eq!(query.columns.name(0), "id");
229+
assert_eq!(query.columns.datatype(0), DataType::Int);
230+
assert_eq!(query.columns.name(1), "name");
231+
assert_eq!(query.columns.datatype(1), DataType::VChar);
232+
assert_eq!(query.columns.name(2), "age");
233+
assert_eq!(query.columns.datatype(2), DataType::TinyInt);
234+
235+
let row1 = query.fetch_row().unwrap();
236+
assert_eq!(row1.get(0), &Value::I32(1));
237+
// assert_eq!(row1.get(1), &Value::String("Alex"));
238+
assert_eq!(row1.get(2), &Value::I32(18));
239+
240+
let row2 = query.fetch_row().unwrap();
241+
assert_eq!(row2.get(0), &Value::I32(2));
242+
// assert_eq!(row2.get(1), &Value::String("Thorne"));
243+
assert_eq!(row2.get(2), &Value::I32(22));
244+
245+
let row3 = query.fetch_row().unwrap();
246+
assert_eq!(row3.get(0), &Value::I32(3));
247+
// assert_eq!(row3.get(1), &Value::String("Ryder"));
248+
assert_eq!(row3.get(2), &Value::I32(36));
249+
250+
assert!(query.fetch_row().is_none());
251+
252+
let affected_rows = conn.execute("DELETE FROM users;").unwrap();
253+
assert_eq!(affected_rows, 3);
254+
}
255+
}

src/row.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
use crate::{de::RowDeserializer, Columns, Result, Value};
22
use serde::de::{value::Error as DeError, DeserializeOwned};
3+
use std::fmt::Debug;
34

4-
#[derive(Debug)]
55
pub struct Row<'a> {
66
pub(crate) columns: Columns,
77
pub(crate) values: Vec<Value<'a>>,
88
}
99

10+
impl Debug for Row<'_> {
11+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12+
f.debug_tuple("Row").field(&self.values).finish()
13+
}
14+
}
15+
1016
impl Row<'_> {
1117
pub fn columns(&self) -> Columns {
1218
self.columns.clone()

src/value.rs

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
use crate::*;
22
use cidr::{IpInet, Ipv4Inet, Ipv6Inet};
33
use mac_address::MacAddress;
4-
use std::ffi::c_char;
54
use std::net::{Ipv4Addr, Ipv6Addr};
6-
use std::ptr::read;
75

86
#[derive(Debug, Clone, PartialEq)]
97
pub enum Value<'a> {
108
Null,
11-
I8(i8),
12-
I16(i16),
139
I32(i32),
1410
I64(i64),
1511
F32(f32),
@@ -27,8 +23,6 @@ impl Display for Value<'_> {
2723
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2824
match self {
2925
Value::Null => write!(f, "NULL"),
30-
Value::I8(v) => write!(f, "{}", v),
31-
Value::I16(v) => write!(f, "{}", v),
3226
Value::I32(v) => write!(f, "{}", v),
3327
Value::I64(v) => write!(f, "{}", v),
3428
Value::F32(v) => write!(f, "{}", v),
@@ -44,57 +38,62 @@ impl Display for Value<'_> {
4438
}
4539

4640
impl Value<'_> {
47-
pub(crate) unsafe fn from_ptr(ptr: *const c_void, t: DataType) -> Self {
48-
if ptr.is_null() {
41+
pub(crate) unsafe fn from_ptr(
42+
res: *mut xdb_res_t,
43+
row: *mut xdb_row_t,
44+
i: u16,
45+
t: DataType,
46+
) -> Self {
47+
if xdb_column_null(res, row, i) {
4948
return Self::Null;
5049
}
5150
match t {
5251
DataType::Null => Self::Null,
53-
DataType::TinyInt => Self::I8(read(ptr as *const i8)),
52+
DataType::TinyInt => Self::I32(xdb_column_int(res, row, i)),
53+
DataType::SmallInt => Self::I32(xdb_column_int(res, row, i)),
54+
DataType::Int => Self::I32(xdb_column_int(res, row, i)),
55+
DataType::BigInt => Self::I64(xdb_column_int64(res, row, i)),
5456
DataType::UTinyInt => todo!(),
55-
DataType::SmallInt => Self::I16(read(ptr as *const i16)),
5657
DataType::USmallInt => todo!(),
57-
DataType::Int => Self::I32(read(ptr as *const i32)),
5858
DataType::UInt => todo!(),
59-
DataType::BigInt => Self::I64(read(ptr as *const i64)),
6059
DataType::UBigInt => todo!(),
61-
DataType::Float => Self::F32(read(ptr as *const f32)),
62-
DataType::Double => Self::F64(read(ptr as *const f64)),
63-
DataType::Timestamp => Self::Timestamp(read(ptr as *const i64)),
60+
DataType::Float => Self::F32(xdb_column_float(res, row, i)),
61+
DataType::Double => Self::F64(xdb_column_double(res, row, i)),
62+
DataType::Timestamp => Self::Timestamp(xdb_column_int64(res, row, i)),
6463
DataType::Char | DataType::VChar => {
65-
let str = CStr::from_ptr(ptr as *const c_char).to_str().unwrap();
64+
let ptr = xdb_column_str(res, row, i);
65+
let str = CStr::from_ptr(ptr).to_str().unwrap();
6666
Self::String(str)
6767
}
6868
DataType::Binary | DataType::VBinary => {
69-
let len = read((ptr as *const u8).offset(-2) as *const u16);
69+
let mut len = 0_i32;
70+
let ptr = xdb_column_blob(res, row, i, &mut len);
71+
if len <= 0 {
72+
return Self::Null;
73+
}
7074
let data = from_raw_parts(ptr as *const u8, len as usize);
7175
Self::Binary(data)
7276
}
73-
DataType::Bool => Self::Bool(*(ptr as *const i8) == 1),
77+
DataType::Bool => Self::Bool(xdb_column_bool(res, row, i)),
7478
DataType::Inet => {
75-
let bytes = from_raw_parts(ptr as *const u8, 18);
76-
let mask = bytes[0];
77-
let family = bytes[1];
78-
match family {
79+
let inet = *xdb_column_inet(res, row, i);
80+
match inet.family {
7981
4 => {
8082
let mut buf = [0; 4];
81-
buf.copy_from_slice(&bytes[2..6]);
82-
let net = Ipv4Inet::new(Ipv4Addr::from(buf), mask).unwrap();
83+
buf.copy_from_slice(&inet.addr[0..4]);
84+
let net = Ipv4Inet::new(Ipv4Addr::from(buf), inet.mask).unwrap();
8385
Self::Inet(IpInet::V4(net))
8486
}
8587
6 => {
86-
let mut buf = [0; 16];
87-
buf.copy_from_slice(&bytes[2..18]);
88-
let net = Ipv6Inet::new(Ipv6Addr::from(buf), mask).unwrap();
88+
let net = Ipv6Inet::new(Ipv6Addr::from(inet.addr), inet.mask).unwrap();
8989
Self::Inet(IpInet::V6(net))
9090
}
9191
_ => unreachable!(),
9292
}
9393
}
9494
DataType::Mac => {
95-
let bytes = from_raw_parts(ptr as *const u8, 6);
96-
let address =
97-
MacAddress::new([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]]);
95+
let mac = *xdb_column_mac(res, row, i);
96+
let address = MacAddress::new(mac.addr);
9897
Self::Mac(address)
9998
}
10099
DataType::Array => todo!(),

0 commit comments

Comments
 (0)