@@ -18,39 +18,78 @@ struct TempPath : fs::path {
1818 }
1919};
2020
21- constexpr size_t SAMPLE_ROWS = 0 ;
22- [[nodiscard]] TempPath write_sample (vx_session *session, fs::path &&path) {
23- REQUIRE (path.is_absolute ());
21+ // StructArray { age: u8, height: u16? }
22+ [[nodiscard]] const vx_dtype *sample_dtype () {
2423 vx_struct_fields_builder *builder = vx_struct_fields_builder_new ();
2524
26- {
27- constexpr auto col1 = " col1" sv;
28- const vx_string *col1_name = vx_string_new (col1.data (), col1.size ());
29- const vx_dtype *col1_dtype = vx_dtype_new_primitive (PTYPE_U8, false );
30- vx_struct_fields_builder_add_field (builder, col1_name, col1_dtype);
25+ constexpr auto age = " age" sv;
26+ const vx_string *age_name = vx_string_new (age.data (), age.size ());
27+ const vx_dtype *age_type = vx_dtype_new_primitive (PTYPE_U8, false );
28+ vx_struct_fields_builder_add_field (builder, age_name, age_type);
29+
30+ constexpr auto height = " height" sv;
31+ const vx_string *height_name = vx_string_new (height.data (), height.size ());
32+ const vx_dtype *height_type = vx_dtype_new_primitive (PTYPE_U16, true );
33+ vx_struct_fields_builder_add_field (builder, height_name, height_type);
34+
35+ vx_struct_fields *fields = vx_struct_fields_builder_finalize (builder);
36+ return vx_dtype_new_struct (fields, false );
37+ }
38+
39+ constexpr size_t SAMPLE_ROWS = 100 ;
40+ [[nodiscard]] const vx_array *sample_array () {
41+ vx_validity validity = {};
42+ validity.type = VX_VALIDITY_NON_NULLABLE;
43+
44+ vx_struct_column_builder *builder = vx_struct_column_builder_new (&validity, SAMPLE_ROWS);
45+
46+ vx_error *error = nullptr ;
47+
48+ std::vector<uint8_t > age_buffer;
49+ for (uint8_t age = 0 ; age < SAMPLE_ROWS; ++age) {
50+ age_buffer.push_back (age);
3151 }
32- {
33- constexpr auto col2 = " col2" sv;
34- const vx_string *col2_name = vx_string_new (col2.data (), col2.size ());
35- const vx_dtype *col2_dtype = vx_dtype_new_utf8 (true );
36- vx_struct_fields_builder_add_field (builder, col2_name, col2_dtype);
52+ const vx_array *age_array =
53+ vx_array_new_primitive (PTYPE_U8, age_buffer.data (), age_buffer.size (), &validity, &error);
54+ require_no_error (error);
55+
56+ vx_struct_column_builder_add_field (builder, " age" , age_array, &error);
57+ require_no_error (error);
58+ vx_array_free (age_array);
59+
60+ std::vector<uint16_t > height_buffer;
61+ for (uint16_t height = 0 ; height < SAMPLE_ROWS; ++height) {
62+ height_buffer.push_back (1 + rand () % (height + 1 ));
3763 }
64+ validity.type = VX_VALIDITY_ALL_VALID;
65+ const vx_array *height_array =
66+ vx_array_new_primitive (PTYPE_U16, height_buffer.data (), height_buffer.size (), &validity, &error);
67+ require_no_error (error);
3868
39- vx_struct_fields *fields = vx_struct_fields_builder_finalize (builder);
40- const vx_dtype *file_dtype = vx_dtype_new_struct (fields, false );
69+ vx_struct_column_builder_add_field (builder, " height" , height_array, &error);
70+ require_no_error (error);
71+ vx_array_free (height_array);
72+
73+ const vx_array *array = vx_struct_column_builder_finalize (builder, &error);
74+ require_no_error (error);
75+ return array;
76+ }
77+
78+ [[nodiscard]] TempPath write_sample (vx_session *session, fs::path &&path) {
79+ REQUIRE (path.is_absolute ());
80+
81+ const vx_dtype *dtype = sample_dtype ();
4182
4283 vx_error *error = nullptr ;
43- vx_array_sink *sink = vx_array_sink_open_file (session, path.c_str (), file_dtype , &error);
84+ vx_array_sink *sink = vx_array_sink_open_file (session, path.c_str (), dtype , &error);
4485 REQUIRE (sink != nullptr );
4586 require_no_error (error);
46- vx_dtype_free (file_dtype );
87+ vx_dtype_free (dtype );
4788
48- for (size_t i = 0 ; i < SAMPLE_ROWS; ++i) {
49- // const vx_array* array = vx_array_new_primitive();
50- // vx_array_sink_push(sink, array, &error);
51- // require_no_error(error);
52- // vx_array_free(array);
53- }
89+ const vx_array *array = sample_array ();
90+ vx_array_sink_push (sink, array, &error);
91+ require_no_error (error);
92+ vx_array_free (array);
5493
5594 vx_array_sink_close (sink, &error);
5695 require_no_error (error);
@@ -110,6 +149,12 @@ TEST_CASE("Creating datasources", "[datasource]") {
110149 vx_session_free (session);
111150}
112151
152+ TEST_CASE (" Write file" , " [datasource]" ) {
153+ vx_session *session = vx_session_new ();
154+ TempPath path = write_sample (session, fs::current_path () / " write-file.vortex" );
155+ vx_session_free (session);
156+ }
157+
113158TEST_CASE (" Write file and read back types" , " [datasource]" ) {
114159 vx_session *session = vx_session_new ();
115160 TempPath path = write_sample (session, fs::current_path () / " write-read-types.vortex" );
@@ -142,43 +187,143 @@ TEST_CASE("Write file and read back types", "[datasource]") {
142187 REQUIRE (vx_dtype_get_variant (col1_dtype) == DTYPE_PRIMITIVE);
143188 REQUIRE (vx_dtype_primitive_ptype (col1_dtype) == PTYPE_U8);
144189 REQUIRE_FALSE (vx_dtype_is_nullable (col1_dtype));
145- REQUIRE (to_string_view (col1_name) == " col1 " );
190+ REQUIRE (to_string_view (col1_name) == " age " );
146191 vx_dtype_free (col1_dtype);
147192
148193 const vx_dtype *col2_dtype = vx_struct_fields_field_dtype (fields, 1 );
149194 const vx_string *col2_name = vx_struct_fields_field_name (fields, 1 );
150195
151- REQUIRE (vx_dtype_get_variant (col2_dtype) == DTYPE_UTF8);
196+ REQUIRE (vx_dtype_get_variant (col2_dtype) == DTYPE_PRIMITIVE);
197+ REQUIRE (vx_dtype_primitive_ptype (col2_dtype) == PTYPE_U16);
152198 REQUIRE (vx_dtype_is_nullable (col2_dtype));
153- REQUIRE (to_string_view (col2_name) == " col2 " );
199+ REQUIRE (to_string_view (col2_name) == " height " );
154200 vx_dtype_free (col2_dtype);
155201
156202 vx_data_source_free (ds);
157203}
158204
159- // TEST_CASE("Write file and read back", "[datasource]") {
160- // vx_session *session = vx_session_new();
161- // TempPath path = write_sample(session, fs::current_path() / "write-read.vortex");
162- // vx_error *error = nullptr;
163- //
164- // vx_data_source_options ds_options = {};
165- // ds_options.files = path.c_str();
166- //
167- // const vx_data_source *ds = vx_data_source_new(session, &ds_options, &error);
168- // require_no_error(error);
169- // REQUIRE(ds != nullptr);
170- //
171- // vx_scan *scan = vx_data_source_scan(ds, nullptr, nullptr, &error);
172- // require_no_error(error);
173- // REQUIRE(scan != nullptr);
174- // vx_scan_free(scan);
175- //
176- // vx_scan_options scan_options = {};
177- // scan = vx_data_source_scan(ds, &scan_options, nullptr, &error);
178- // require_no_error(error);
179- // REQUIRE(scan != nullptr);
180- // vx_scan_free(scan);
181- //
182- // vx_data_source_free(ds);
183- // vx_session_free(session);
184- // }
205+ void verify_sample_array (const vx_array *array) {
206+ REQUIRE (vx_array_len (array) == SAMPLE_ROWS);
207+ REQUIRE (vx_array_has_dtype (array, DTYPE_STRUCT));
208+
209+ const vx_struct_fields *fields = vx_dtype_struct_dtype (vx_array_dtype (array));
210+ size_t len = vx_struct_fields_nfields (fields);
211+ REQUIRE (len == 2 );
212+
213+ const vx_dtype *age_dtype = vx_struct_fields_field_dtype (fields, 0 );
214+ REQUIRE (vx_dtype_get_variant (age_dtype) == DTYPE_PRIMITIVE);
215+ REQUIRE (vx_dtype_primitive_ptype (age_dtype) == PTYPE_U8);
216+ vx_dtype_free (age_dtype);
217+ const vx_string *age_name = vx_struct_fields_field_name (fields, 0 );
218+ REQUIRE (to_string_view (age_name) == " age" );
219+
220+ const vx_dtype *height_dtype = vx_struct_fields_field_dtype (fields, 1 );
221+ REQUIRE (vx_dtype_get_variant (height_dtype) == DTYPE_PRIMITIVE);
222+ REQUIRE (vx_dtype_primitive_ptype (height_dtype) == PTYPE_U16);
223+ vx_dtype_free (height_dtype);
224+ const vx_string *height_name = vx_struct_fields_field_name (fields, 1 );
225+ REQUIRE (to_string_view (height_name) == " height" );
226+
227+ vx_error *error = nullptr ;
228+ vx_validity validity = {};
229+ vx_array_get_validity (array, &validity, &error);
230+ require_no_error (error);
231+ REQUIRE (validity.type == VX_VALIDITY_NON_NULLABLE);
232+
233+ const vx_array *age_field = vx_array_get_field (array, 0 , &error);
234+ require_no_error (error);
235+ REQUIRE (vx_array_has_dtype (age_field, DTYPE_PRIMITIVE));
236+ REQUIRE (vx_dtype_primitive_ptype (vx_array_dtype (age_field)) == PTYPE_U8);
237+ REQUIRE (vx_array_len (age_field) == SAMPLE_ROWS);
238+ for (size_t i = 0 ; i < SAMPLE_ROWS; ++i) {
239+ REQUIRE (vx_array_get_u8 (age_field, i) == i);
240+ }
241+ vx_array_free (age_field);
242+
243+ const vx_array *height_field = vx_array_get_field (array, 1 , &error);
244+ require_no_error (error);
245+ REQUIRE (vx_array_has_dtype (height_field, DTYPE_PRIMITIVE));
246+ REQUIRE (vx_dtype_primitive_ptype (vx_array_dtype (height_field)) == PTYPE_U16);
247+ REQUIRE (vx_array_len (height_field) == SAMPLE_ROWS);
248+ for (size_t i = 0 ; i < SAMPLE_ROWS; ++i) {
249+ REQUIRE (vx_array_get_u16 (height_field, i) > 0 );
250+ }
251+ vx_array_free (height_field);
252+
253+ REQUIRE (vx_array_get_field (array, 2 , &error) == nullptr );
254+ REQUIRE (error != nullptr );
255+ vx_error_free (error);
256+ }
257+
258+ TEST_CASE (" Requesting scans" , " [datasource]" ) {
259+ vx_session *session = vx_session_new ();
260+ TempPath path = write_sample (session, fs::current_path () / " write-file2.vortex" );
261+
262+ vx_data_source_options ds_options = {};
263+ ds_options.files = path.c_str ();
264+
265+ vx_error *error = nullptr ;
266+ const vx_data_source *ds = vx_data_source_new (session, &ds_options, &error);
267+ require_no_error (error);
268+ REQUIRE (ds != nullptr );
269+
270+ vx_scan *scan = vx_data_source_scan (ds, nullptr , nullptr , &error);
271+ require_no_error (error);
272+ REQUIRE (scan != nullptr );
273+ vx_scan_free (scan);
274+
275+ vx_scan_options options = {};
276+ options.max_threads = 1 ;
277+ scan = vx_data_source_scan (ds, &options, nullptr , &error);
278+ require_no_error (error);
279+ REQUIRE (scan != nullptr );
280+ vx_scan_free (scan);
281+
282+ vx_data_source_free (ds);
283+ vx_session_free (session);
284+ }
285+
286+ TEST_CASE (" Basic scan" , " [datasource]" ) {
287+ vx_session *session = vx_session_new ();
288+ TempPath path = write_sample (session, fs::current_path () / " basic-scan.vortex" );
289+ vx_error *error = nullptr ;
290+
291+ vx_data_source_options ds_options = {};
292+ ds_options.files = path.c_str ();
293+
294+ const vx_data_source *ds = vx_data_source_new (session, &ds_options, &error);
295+ require_no_error (error);
296+ REQUIRE (ds != nullptr );
297+
298+ vx_scan *scan = vx_data_source_scan (ds, nullptr , nullptr , &error);
299+ require_no_error (error);
300+ REQUIRE (scan != nullptr );
301+
302+ vx_partition *partition = vx_scan_next (scan, &error);
303+ require_no_error (error);
304+
305+ vx_estimate estimate = {};
306+ vx_partition_row_count (partition, &estimate, &error);
307+ require_no_error (error);
308+ REQUIRE (estimate.type == VX_ESTIMATE_EXACT);
309+ REQUIRE (estimate.estimate == SAMPLE_ROWS);
310+
311+ REQUIRE (vx_scan_next (scan, &error) == nullptr );
312+ require_no_error (error);
313+
314+ const vx_array *array = vx_partition_next (partition, &error);
315+ require_no_error (error);
316+ REQUIRE (array != nullptr );
317+
318+ REQUIRE (vx_partition_next (partition, &error) == nullptr );
319+ require_no_error (error);
320+
321+ verify_sample_array (array);
322+
323+ vx_array_free (array);
324+ vx_partition_free (partition);
325+ vx_scan_free (scan);
326+
327+ vx_data_source_free (ds);
328+ vx_session_free (session);
329+ }
0 commit comments