1
+ // ===----------------------------------------------------------------------===//
2
+ //
3
+ // Peloton
4
+ //
5
+ // csv_scan_test.cpp
6
+ //
7
+ // Identification: test/codegen/csv_scan_test.cpp
8
+ //
9
+ // Copyright (c) 2015-2018, Carnegie Mellon University Database Group
10
+ //
11
+ // ===----------------------------------------------------------------------===//
12
+
13
+ #include " codegen/testing_codegen_util.h"
14
+
15
+ #include " codegen/util/csv_scanner.h"
16
+ #include " common/timer.h"
17
+ #include " util/file_util.h"
18
+
19
+ namespace peloton {
20
+ namespace test {
21
+
22
+ class CSVScanTest : public PelotonCodeGenTest {};
23
+
24
+ using CallbackFn =
25
+ std::function<void (const codegen::util::CSVScanner::Column *)>;
26
+
27
+ struct State {
28
+ codegen::util::CSVScanner *scanner;
29
+ CallbackFn callback;
30
+ };
31
+
32
+ struct TempFileHandle {
33
+ std::string name;
34
+ TempFileHandle (std::string _name) : name(_name) {}
35
+ ~TempFileHandle () { boost::filesystem::remove (name); }
36
+ };
37
+
38
+ void CSVRowCallback (void *s) {
39
+ auto *state = reinterpret_cast <State *>(s);
40
+ state->callback (state->scanner ->GetColumns ());
41
+ }
42
+
43
+ void IterateAsCSV (const std::vector<std::string> &rows,
44
+ const std::vector<codegen::type::Type> &col_types,
45
+ CallbackFn callback, char delimiter = ' ,' ) {
46
+ std::string csv_data;
47
+ for (uint32_t i = 0 ; i < rows.size (); i++) {
48
+ csv_data.append (rows[i]).append (" \n " );
49
+ }
50
+
51
+ // Write the contents into a temporary file
52
+ TempFileHandle fh{FileUtil::WriteTempFile (csv_data, " " , " tmp" )};
53
+
54
+ // The memory pool
55
+ auto &pool = *TestingHarness::GetInstance ().GetTestingPool ();
56
+
57
+ // The client-state
58
+ State state = {.scanner = nullptr , .callback = callback};
59
+
60
+ // The scanner
61
+ codegen::util::CSVScanner scanner{
62
+ pool, fh.name , col_types.data (), static_cast <uint32_t >(col_types.size ()),
63
+ CSVRowCallback, reinterpret_cast <void *>(&state), delimiter};
64
+
65
+ state.scanner = &scanner;
66
+
67
+ // Iterate!
68
+ scanner.Produce ();
69
+ }
70
+
71
+ TEST_F (CSVScanTest, SimpleNumericScan) {
72
+ // Create a temporary CSV file
73
+ std::vector<std::string> rows = {" 1,2,3.0,4" , " 4,5,6.0,7" , " 8,9,10.0,11" };
74
+ std::vector<codegen::type::Type> types = {{type::TypeId::INTEGER, false },
75
+ {type::TypeId::INTEGER, false },
76
+ {type::TypeId::DECIMAL, false },
77
+ {type::TypeId::INTEGER, false }};
78
+
79
+ uint32_t rows_read = 0 ;
80
+ IterateAsCSV (rows, types, [&rows_read, &types](
81
+ const codegen::util::CSVScanner::Column *cols) {
82
+ rows_read++;
83
+ for (uint32_t i = 0 ; i < types.size (); i++) {
84
+ EXPECT_FALSE (cols[i].is_null );
85
+ EXPECT_GT (cols[i].len , 0 );
86
+ }
87
+ });
88
+
89
+ // Check
90
+ EXPECT_EQ (rows.size (), rows_read);
91
+ }
92
+
93
+ TEST_F (CSVScanTest, MixedStringScan) {
94
+ // Create a temporary CSV file
95
+ std::vector<std::string> rows = {" 1,2,3,test" , " 4,5,6,\" test\" " ,
96
+ " 8,9,10,\" test\n newline\n inquote\" " };
97
+ std::vector<codegen::type::Type> types = {{type::TypeId::INTEGER, false },
98
+ {type::TypeId::INTEGER, false },
99
+ {type::TypeId::INTEGER, false },
100
+ {type::TypeId::VARCHAR, false }};
101
+
102
+ uint32_t rows_read = 0 ;
103
+ IterateAsCSV (rows, types, [&rows_read, &types](
104
+ const codegen::util::CSVScanner::Column *cols) {
105
+ rows_read++;
106
+ for (uint32_t i = 0 ; i < types.size (); i++) {
107
+ EXPECT_FALSE (cols[i].is_null );
108
+ EXPECT_GT (cols[i].len , 0 );
109
+ }
110
+ });
111
+
112
+ // Check
113
+ EXPECT_EQ (rows.size (), rows_read);
114
+ }
115
+
116
+ } // namespace test
117
+ } // namespace peloton
0 commit comments