Skip to content
This repository has been archived by the owner on Jul 11, 2021. It is now read-only.

Commit

Permalink
fix bug when different returns types are product for the same column,…
Browse files Browse the repository at this point in the history
… which is possible using the JSON1 module
  • Loading branch information
Simone Mosciatti committed Dec 23, 2017
1 parent 5824666 commit e3b2134
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 22 deletions.
17 changes: 1 addition & 16 deletions src/community_statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ use std::ffi::{CString, CStr};
use sqlite::ffi;

use sqlite::StatementTrait;
use sqlite::{SQLite3Error, Cursor, EntityType, RawConnection,
SQLiteOK};
use sqlite::{SQLite3Error, Cursor, RawConnection, SQLiteOK};
use sqlite::generate_sqlite3_error;

#[cfg(feature = "pro")]
Expand Down Expand Up @@ -163,23 +162,9 @@ impl<'a> StatementTrait<'a> for Statement<'a> {
unsafe {
ffi::sqlite3_column_count(self.stmt)
} as i32;
let mut types: Vec<EntityType> = Vec::new();
for i in 0..n_columns {
types.push(match unsafe {
ffi::sqlite3_column_type(self.stmt, i)
} {
ffi::SQLITE_INTEGER => EntityType::Integer,
ffi::SQLITE_FLOAT => EntityType::Float,
ffi::SQLITE_TEXT => EntityType::Text,
ffi::SQLITE_BLOB => EntityType::Blob,
ffi::SQLITE_NULL => EntityType::Null,
_ => EntityType::Null,
})
}
Ok(Cursor::RowsCursor {
stmt: self,
num_columns: n_columns,
types: types,
previous_status: ffi::SQLITE_ROW,
to_replicate: self.to_replicate(),
modified_rows: 0,
Expand Down
29 changes: 24 additions & 5 deletions src/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ pub enum Cursor<'a> {
},
RowsCursor {
num_columns: i32,
types: Vec<EntityType>,
previous_status: i32,
stmt: &'a Statement<'a>,
modified_rows: i32,
Expand Down Expand Up @@ -221,6 +220,20 @@ impl<'a> FromIterator<Cursor<'a>> for Cursor<'a> {
}
}

fn get_entity_type(stmt: *mut ffi::sqlite3_stmt,
i: i32)
-> EntityType {
let entity_type = unsafe { ffi::sqlite3_column_type(stmt, i) };
match entity_type {
ffi::SQLITE_INTEGER => EntityType::Integer,
ffi::SQLITE_FLOAT => EntityType::Float,
ffi::SQLITE_TEXT => EntityType::Text,
ffi::SQLITE_BLOB => EntityType::Blob,
ffi::SQLITE_NULL => EntityType::Null,
_ => EntityType::Null,

}
}

impl<'a> Iterator for Cursor<'a> {
type Item = Row;
Expand All @@ -243,42 +256,48 @@ impl<'a> Iterator for Cursor<'a> {
Cursor::RowsCursor {
ref stmt,
num_columns,
ref types,
ref mut previous_status,
..
} => {
match *previous_status {
ffi::SQLITE_ROW => {
let mut result = vec![];
for i in 0..num_columns {
let entity_value = match types[i as
usize] {
let entity_value = match get_entity_type(stmt.get_raw_stmt(), i) {
EntityType::Integer => {
let value =
unsafe {
ffi::sqlite3_column_int(stmt.get_raw_stmt(), i)
};
debug!("Got integer: {:?}",
value);
Entity::Integer { int: value }
}
EntityType::Float => {
let value = unsafe {
ffi::sqlite3_column_double(stmt.get_raw_stmt(), i)
};
debug!("Got float: {:?}", value);
Entity::Float { float: value }
}
EntityType::Text => {
let value = unsafe {
CStr::from_ptr(ffi::sqlite3_column_text(stmt.get_raw_stmt(), i) as *const i8).to_string_lossy().into_owned()
};
debug!("Got text: {:?}", value);
Entity::Text { text: value }
}
EntityType::Blob => {
let value = unsafe {
CStr::from_ptr(ffi::sqlite3_column_blob(stmt.get_raw_stmt(), i) as *const i8).to_string_lossy().into_owned()
};
debug!("Got blob: {:?}", value);
Entity::Blob { blob: value }
}
EntityType::Null => Entity::Null {},
EntityType::Null => {
debug!("Got null");
Entity::Null {}
}
};
result.push(entity_value);
}
Expand Down
14 changes: 13 additions & 1 deletion test/correctness/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,19 @@ def test_multi_insert_same_statement(self):
COMMIT;""")
self.assertEquals(done, ["DONE", 6L])


class TestJSON(TestRediSQLWithExec):
def test_multiple_insert_on_different_types(self):
with DB(self.client, "H"):
with Table(self.client, "j1", "(A text, B int)", key = "H"):
done = self.exec_naked("REDISQL.EXEC", "H", """BEGIN;
INSERT INTO j1 VALUES ('{\"foo\" : \"bar\"}', 1);
INSERT INTO j1 VALUES ('{\"foo\" : 3}', 2);
INSERT INTO j1 VALUES ('{\"foo\" : [1, 2, 3]}', 3);
INSERT INTO j1 VALUES ('{\"foo\" : {\"baz\" : [1, 2, 3]}}', 4);
COMMIT;""")
self.assertEquals(done, ["DONE", 4L])
result = self.exec_naked("REDISQL.EXEC", "H", "SELECT json_extract(A, '$.foo') FROM j1 ORDER BY B;")
self.assertEquals(result, [["bar"], [3], ["[1,2,3]"], ['{"baz":[1,2,3]}']])


class TestStatements(TestRediSQLWithExec):
Expand Down

0 comments on commit e3b2134

Please sign in to comment.