libduckdb_sys_queryscript/
lib.rs1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4#![allow(deref_nullptr)]
5#![allow(improper_ctypes)]
6
7#[allow(clippy::all)]
8mod bindings {
9 include!(concat!(env!("OUT_DIR"), "/bindgen.rs"));
10}
11#[allow(clippy::all)]
12pub use bindings::*;
13
14pub const DuckDBError: duckdb_state = duckdb_state_DuckDBError;
15pub const DuckDBSuccess: duckdb_state = duckdb_state_DuckDBSuccess;
16
17pub use self::error::*;
18mod error;
19
20#[cfg(test)]
21mod tests {
22 use super::*;
23 use std::convert::TryFrom;
24 use std::ffi::{CStr, CString};
25 use std::mem;
26 use std::os::raw::c_char;
27 use std::ptr;
28
29 use arrow::array::{Array, ArrayData, Int32Array, StructArray};
30 use arrow::datatypes::DataType;
31 use arrow::ffi::{ArrowArray, FFI_ArrowArray, FFI_ArrowSchema};
32
33 unsafe fn print_int_result(mut result: duckdb_result) {
34 for i in 0..duckdb_column_count(&mut result) {
35 print!(
36 "{} ",
37 CStr::from_ptr(duckdb_column_name(&mut result, i)).to_string_lossy()
38 );
39 }
40 println!();
41 for row_idx in 0..duckdb_row_count(&mut result) {
43 for col_idx in 0..duckdb_column_count(&mut result) {
44 let val = duckdb_value_int32(&mut result, col_idx, row_idx);
45 print!("{val} ");
46 }
47 println!();
48 }
49 }
50
51 #[test]
52 fn test_query_arrow() {
53 unsafe {
54 let mut db: duckdb_database = ptr::null_mut();
56 let mut con: duckdb_connection = ptr::null_mut();
57 if duckdb_open(ptr::null_mut(), &mut db) != duckdb_state_DuckDBSuccess {
58 panic!("duckdb_open error")
59 }
60 if duckdb_connect(db, &mut con) != duckdb_state_DuckDBSuccess {
61 panic!("duckdb_connect error")
62 }
63 let sql = CString::new("CREATE TABLE integers(i INTEGER, j INTEGER);").unwrap();
65 if duckdb_query(con, sql.as_ptr() as *const c_char, ptr::null_mut()) != duckdb_state_DuckDBSuccess {
66 panic!("CREATE TABLE error")
67 }
68
69 let sql = CString::new("INSERT INTO integers VALUES (3, 4), (5, 6), (7, NULL);").unwrap();
71 let mut result: duckdb_arrow = ptr::null_mut();
72 if duckdb_query_arrow(con, sql.as_ptr() as *const c_char, &mut result) != duckdb_state_DuckDBSuccess {
73 panic!("INSERT error")
74 }
75 assert_eq!(duckdb_arrow_rows_changed(result), 3);
76 duckdb_destroy_arrow(&mut result);
77
78 let mut result: duckdb_arrow = ptr::null_mut();
80 let sql = CString::new("select i, j from integers order by i desc").unwrap();
81 if duckdb_query_arrow(con, sql.as_ptr() as *const c_char, &mut result) != duckdb_state_DuckDBSuccess {
82 panic!("SELECT error")
83 }
84 assert_eq!(duckdb_arrow_row_count(result), 3);
85 assert_eq!(duckdb_arrow_column_count(result), 2);
86
87 let mut arrays = FFI_ArrowArray::empty();
88 let mut schema = FFI_ArrowSchema::empty();
89 if duckdb_query_arrow_schema(
90 result,
91 &mut std::ptr::addr_of_mut!(schema) as *mut _ as *mut duckdb_arrow_schema,
92 ) != duckdb_state_DuckDBSuccess
93 {
94 panic!("SELECT error")
95 }
96 if duckdb_query_arrow_array(
97 result,
98 &mut std::ptr::addr_of_mut!(arrays) as *mut _ as *mut duckdb_arrow_array,
99 ) != duckdb_state_DuckDBSuccess
100 {
101 panic!("SELECT error")
102 }
103 let arrow_array = ArrowArray::new(arrays, schema);
104 let array_data = ArrayData::try_from(arrow_array).expect("ok");
105 let struct_array = StructArray::from(array_data);
106 assert_eq!(struct_array.len(), 3);
107 assert_eq!(struct_array.columns().len(), 2);
108 assert_eq!(struct_array.column(0).data_type(), &DataType::Int32);
109 assert_eq!(struct_array.column(1).data_type(), &DataType::Int32);
110 let arr_i = struct_array.column(0).as_any().downcast_ref::<Int32Array>().unwrap();
111 assert_eq!(arr_i.value(0), 7);
112 assert_eq!(arr_i.value(1), 5);
113 assert_eq!(arr_i.value(2), 3);
114 let arr_j = struct_array.column(1).as_any().downcast_ref::<Int32Array>().unwrap();
115 assert!(arr_j.is_null(0));
116 assert_eq!(arr_j.value(1), 6);
117 assert_eq!(arr_j.value(2), 4);
118
119 let mut arrays: duckdb_arrow_array = ptr::null_mut();
120 if duckdb_query_arrow_array(result, &mut arrays) != duckdb_state_DuckDBSuccess {
121 panic!("SELECT error")
122 }
123 assert!(arrays.is_null());
124 duckdb_destroy_arrow(&mut result);
125 duckdb_disconnect(&mut con);
126 duckdb_close(&mut db);
127 }
128 }
129
130 #[test]
131 fn basic_api_usage() {
132 unsafe {
133 let mut db: duckdb_database = ptr::null_mut();
135 let mut con: duckdb_connection = ptr::null_mut();
136 if duckdb_open(ptr::null_mut(), &mut db) != duckdb_state_DuckDBSuccess {
137 panic!("duckdb_open error")
138 }
139 if duckdb_connect(db, &mut con) != duckdb_state_DuckDBSuccess {
140 panic!("duckdb_connect error")
141 }
142 let sql = CString::new("CREATE TABLE integers(i INTEGER, j INTEGER);").unwrap();
144 if duckdb_query(con, sql.as_ptr() as *const c_char, ptr::null_mut()) != duckdb_state_DuckDBSuccess {
145 panic!("CREATE TABLE error")
146 }
147 let sql = CString::new("INSERT INTO integers VALUES (3, 4), (5, 6), (7, NULL);").unwrap();
149 if duckdb_query(con, sql.as_ptr() as *const c_char, ptr::null_mut()) != duckdb_state_DuckDBSuccess {
150 panic!("INSERT error")
151 }
152 let mut result: duckdb_result = mem::zeroed();
154 let sql = CString::new("select * from integers").unwrap();
155 if duckdb_query(con, sql.as_ptr() as *const c_char, &mut result) != duckdb_state_DuckDBSuccess {
156 panic!(
157 "SELECT error: {}",
158 CStr::from_ptr(duckdb_result_error(&mut result)).to_string_lossy()
159 )
160 }
161 assert_eq!(duckdb_row_count(&mut result), 3);
162 assert_eq!(duckdb_column_count(&mut result), 2);
163 print_int_result(result);
164 duckdb_destroy_result(&mut result);
165
166 let mut stmt: duckdb_prepared_statement = ptr::null_mut();
168 let sql = CString::new("select * from integers where i>?").unwrap();
169 if duckdb_prepare(con, sql.as_ptr() as *const c_char, &mut stmt) != duckdb_state_DuckDBSuccess {
170 panic!("Prepare error");
171 }
172 if duckdb_bind_int32(stmt, 1, 4) != duckdb_state_DuckDBSuccess {
173 panic!("Bind params error");
174 }
175 if duckdb_execute_prepared(stmt, &mut result) != duckdb_state_DuckDBSuccess {
176 panic!("Execute prepared error");
177 }
178 assert_eq!(duckdb_row_count(&mut result), 2);
179 assert_eq!(duckdb_column_count(&mut result), 2);
180 print_int_result(result);
181 duckdb_destroy_result(&mut result);
182
183 if duckdb_bind_int32(stmt, 1, 5) != duckdb_state_DuckDBSuccess {
185 panic!("Bind params error");
186 }
187 if duckdb_execute_prepared(stmt, &mut result) != duckdb_state_DuckDBSuccess {
188 panic!("Execute prepared error");
189 }
190 assert_eq!(duckdb_row_count(&mut result), 1);
191 assert_eq!(duckdb_column_count(&mut result), 2);
192 print_int_result(result);
193 duckdb_destroy_result(&mut result);
194 duckdb_destroy_prepare(&mut stmt);
195
196 duckdb_disconnect(&mut con);
198 duckdb_close(&mut db);
199 }
200 }
201}