]> git.proxmox.com Git - ceph.git/blame - ceph/src/arrow/cpp/src/arrow/dbi/hiveserver2/util.cc
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / cpp / src / arrow / dbi / hiveserver2 / util.cc
CommitLineData
1d09f67e
TL
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18#include "arrow/dbi/hiveserver2/util.h"
19
20#include <algorithm>
21#include <memory>
22#include <sstream>
23#include <vector>
24
25#include "arrow/dbi/hiveserver2/columnar_row_set.h"
26#include "arrow/dbi/hiveserver2/thrift_internal.h"
27
28#include "arrow/dbi/hiveserver2/TCLIService.h"
29#include "arrow/dbi/hiveserver2/TCLIService_types.h"
30
31#include "arrow/status.h"
32
33namespace hs2 = apache::hive::service::cli::thrift;
34using std::unique_ptr;
35
36namespace arrow {
37namespace hiveserver2 {
38
39// PrintResults
40namespace {
41
42const char kNullSymbol[] = "NULL";
43const char kTrueSymbol[] = "true";
44const char kFalseSymbol[] = "false";
45
46struct PrintInfo {
47 // The PrintInfo takes ownership of the Column ptr.
48 PrintInfo(Column* c, size_t m) : column(c), max_size(m) {}
49
50 unique_ptr<Column> column;
51 size_t max_size;
52};
53
54// Adds a horizontal line of '-'s, with '+'s at the column breaks.
55static void AddTableBreak(std::ostream& out, std::vector<PrintInfo>* columns) {
56 for (size_t i = 0; i < columns->size(); ++i) {
57 out << "+";
58 for (size_t j = 0; j < (*columns)[i].max_size + 2; ++j) {
59 out << "-";
60 }
61 }
62 out << "+\n";
63}
64
65// Returns the number of spaces needed to display n, i.e. the number of digits n has,
66// plus 1 if n is negative.
67static size_t NumSpaces(int64_t n) {
68 if (n < 0) {
69 return 1 + NumSpaces(-n);
70 } else if (n < 10) {
71 return 1;
72 } else {
73 return 1 + NumSpaces(n / 10);
74 }
75}
76
77// Returns the max size needed to display a column of integer type.
78template <typename T>
79static size_t GetIntMaxSize(T* column, const std::string& column_name) {
80 size_t max_size = column_name.size();
81 for (int i = 0; i < column->length(); ++i) {
82 if (!column->IsNull(i)) {
83 max_size = std::max(max_size, NumSpaces(column->data()[i]));
84 } else {
85 max_size = std::max(max_size, sizeof(kNullSymbol));
86 }
87 }
88 return max_size;
89}
90
91} // namespace
92
93void Util::PrintResults(const Operation* op, std::ostream& out) {
94 unique_ptr<ColumnarRowSet> results;
95 bool has_more_rows = true;
96 while (has_more_rows) {
97 Status s = op->Fetch(&results, &has_more_rows);
98 if (!s.ok()) {
99 out << s.ToString();
100 return;
101 }
102
103 std::vector<ColumnDesc> column_descs;
104 s = op->GetResultSetMetadata(&column_descs);
105
106 if (!s.ok()) {
107 out << s.ToString();
108 return;
109 } else if (column_descs.size() == 0) {
110 out << "No result set to print.\n";
111 return;
112 }
113
114 std::vector<PrintInfo> columns;
115 for (int i = 0; i < static_cast<int>(column_descs.size()); i++) {
116 const std::string column_name = column_descs[i].column_name();
117 switch (column_descs[i].type()->type_id()) {
118 case ColumnType::TypeId::BOOLEAN: {
119 BoolColumn* bool_col = results->GetBoolCol(i).release();
120
121 // The largest symbol is length 4 unless there is a FALSE, then is it
122 // kFalseSymbol.size() = 5.
123 size_t max_size = std::max(column_name.size(), sizeof(kTrueSymbol));
124 for (int j = 0; j < bool_col->length(); ++j) {
125 if (!bool_col->IsNull(j) && !bool_col->data()[j]) {
126 max_size = std::max(max_size, sizeof(kFalseSymbol));
127 break;
128 }
129 }
130
131 columns.emplace_back(bool_col, max_size);
132 break;
133 }
134 case ColumnType::TypeId::TINYINT: {
135 ByteColumn* byte_col = results->GetByteCol(i).release();
136 columns.emplace_back(byte_col, GetIntMaxSize(byte_col, column_name));
137 break;
138 }
139 case ColumnType::TypeId::SMALLINT: {
140 Int16Column* int16_col = results->GetInt16Col(i).release();
141 columns.emplace_back(int16_col, GetIntMaxSize(int16_col, column_name));
142 break;
143 }
144 case ColumnType::TypeId::INT: {
145 Int32Column* int32_col = results->GetInt32Col(i).release();
146 columns.emplace_back(int32_col, GetIntMaxSize(int32_col, column_name));
147 break;
148 }
149 case ColumnType::TypeId::BIGINT: {
150 Int64Column* int64_col = results->GetInt64Col(i).release();
151 columns.emplace_back(int64_col, GetIntMaxSize(int64_col, column_name));
152 break;
153 }
154 case ColumnType::TypeId::STRING: {
155 unique_ptr<StringColumn> string_col = results->GetStringCol(i);
156
157 size_t max_size = column_name.size();
158 for (int j = 0; j < string_col->length(); ++j) {
159 if (!string_col->IsNull(j)) {
160 max_size = std::max(max_size, string_col->data()[j].size());
161 } else {
162 max_size = std::max(max_size, sizeof(kNullSymbol));
163 }
164 }
165
166 columns.emplace_back(string_col.release(), max_size);
167 break;
168 }
169 case ColumnType::TypeId::BINARY:
170 columns.emplace_back(results->GetBinaryCol(i).release(), column_name.size());
171 break;
172 default: {
173 out << "Unrecognized ColumnType = " << column_descs[i].type()->ToString();
174 }
175 }
176 }
177
178 AddTableBreak(out, &columns);
179 for (size_t i = 0; i < columns.size(); ++i) {
180 out << "| " << column_descs[i].column_name() << " ";
181
182 int padding =
183 static_cast<int>(columns[i].max_size - column_descs[i].column_name().size());
184 while (padding > 0) {
185 out << " ";
186 --padding;
187 }
188 }
189 out << "|\n";
190 AddTableBreak(out, &columns);
191
192 for (int i = 0; i < columns[0].column->length(); ++i) {
193 for (size_t j = 0; j < columns.size(); ++j) {
194 std::stringstream value;
195
196 if (columns[j].column->IsNull(i)) {
197 value << kNullSymbol;
198 } else {
199 switch (column_descs[j].type()->type_id()) {
200 case ColumnType::TypeId::BOOLEAN:
201 if (reinterpret_cast<BoolColumn*>(columns[j].column.get())->data()[i]) {
202 value << kTrueSymbol;
203 } else {
204 value << kFalseSymbol;
205 }
206 break;
207 case ColumnType::TypeId::TINYINT:
208 // The cast prevents us from printing this as a char.
209 value << static_cast<int16_t>(
210 reinterpret_cast<ByteColumn*>(columns[j].column.get())->data()[i]);
211 break;
212 case ColumnType::TypeId::SMALLINT:
213 value << reinterpret_cast<Int16Column*>(columns[j].column.get())->data()[i];
214 break;
215 case ColumnType::TypeId::INT:
216 value << reinterpret_cast<Int32Column*>(columns[j].column.get())->data()[i];
217 break;
218 case ColumnType::TypeId::BIGINT:
219 value << reinterpret_cast<Int64Column*>(columns[j].column.get())->data()[i];
220 break;
221 case ColumnType::TypeId::STRING:
222 value
223 << reinterpret_cast<StringColumn*>(columns[j].column.get())->data()[i];
224 break;
225 case ColumnType::TypeId::BINARY:
226 value
227 << reinterpret_cast<BinaryColumn*>(columns[j].column.get())->data()[i];
228 break;
229 default:
230 value << "unrecognized type";
231 break;
232 }
233 }
234
235 std::string value_str = value.str();
236 out << "| " << value_str << " ";
237 int padding = static_cast<int>(columns[j].max_size - value_str.size());
238 while (padding > 0) {
239 out << " ";
240 --padding;
241 }
242 }
243 out << "|\n";
244 }
245 AddTableBreak(out, &columns);
246 }
247}
248
249} // namespace hiveserver2
250} // namespace arrow