ClickHouse

Форк
0
/
insertPostgreSQLValue.cpp 
269 строк · 11.7 Кб
1
#include "insertPostgreSQLValue.h"
2

3
#if USE_LIBPQXX
4
#include <Columns/ColumnNullable.h>
5
#include <Columns/ColumnString.h>
6
#include <Columns/ColumnArray.h>
7
#include <Columns/ColumnsNumber.h>
8
#include <Columns/ColumnDecimal.h>
9
#include <DataTypes/IDataType.h>
10
#include <DataTypes/DataTypeNullable.h>
11
#include <DataTypes/DataTypeArray.h>
12
#include <DataTypes/DataTypeDateTime64.h>
13
#include <DataTypes/DataTypesDecimal.h>
14
#include <Interpreters/convertFieldToType.h>
15
#include <IO/ReadHelpers.h>
16
#include <IO/ReadBufferFromString.h>
17
#include <Common/assert_cast.h>
18
#include <pqxx/pqxx>
19

20

21
namespace DB
22
{
23

24
namespace ErrorCodes
25
{
26
    extern const int BAD_ARGUMENTS;
27
    extern const int NOT_IMPLEMENTED;
28
}
29

30

31
void insertDefaultPostgreSQLValue(IColumn & column, const IColumn & sample_column)
32
{
33
    column.insertFrom(sample_column, 0);
34
}
35

36

37
void insertPostgreSQLValue(
38
        IColumn & column, std::string_view value,
39
        ExternalResultDescription::ValueType type, DataTypePtr data_type,
40
        const std::unordered_map<size_t, PostgreSQLArrayInfo> & array_info, size_t idx)
41
{
42
    switch (type)
43
    {
44

45
        case ExternalResultDescription::ValueType::vtUInt8:
46
        {
47
            if (value == "t")
48
                assert_cast<ColumnUInt8 &>(column).insertValue(1);
49
            else if (value == "f")
50
                assert_cast<ColumnUInt8 &>(column).insertValue(0);
51
            else
52
                assert_cast<ColumnUInt8 &>(column).insertValue(pqxx::from_string<uint16_t>(value));
53
            break;
54
        }
55
        case ExternalResultDescription::ValueType::vtUInt16:
56
            assert_cast<ColumnUInt16 &>(column).insertValue(pqxx::from_string<uint16_t>(value));
57
            break;
58
        case ExternalResultDescription::ValueType::vtUInt32:
59
            assert_cast<ColumnUInt32 &>(column).insertValue(pqxx::from_string<uint32_t>(value));
60
            break;
61
        case ExternalResultDescription::ValueType::vtUInt64:
62
            assert_cast<ColumnUInt64 &>(column).insertValue(pqxx::from_string<uint64_t>(value));
63
            break;
64
        case ExternalResultDescription::ValueType::vtInt8:
65
            assert_cast<ColumnInt8 &>(column).insertValue(pqxx::from_string<int16_t>(value));
66
            break;
67
        case ExternalResultDescription::ValueType::vtInt16:
68
            assert_cast<ColumnInt16 &>(column).insertValue(pqxx::from_string<int16_t>(value));
69
            break;
70
        case ExternalResultDescription::ValueType::vtInt32:
71
            assert_cast<ColumnInt32 &>(column).insertValue(pqxx::from_string<int32_t>(value));
72
            break;
73
        case ExternalResultDescription::ValueType::vtInt64:
74
            assert_cast<ColumnInt64 &>(column).insertValue(pqxx::from_string<int64_t>(value));
75
            break;
76
        case ExternalResultDescription::ValueType::vtFloat32:
77
            assert_cast<ColumnFloat32 &>(column).insertValue(pqxx::from_string<float>(value));
78
            break;
79
        case ExternalResultDescription::ValueType::vtFloat64:
80
            assert_cast<ColumnFloat64 &>(column).insertValue(pqxx::from_string<double>(value));
81
            break;
82
        case ExternalResultDescription::ValueType::vtEnum8:
83
        case ExternalResultDescription::ValueType::vtEnum16:
84
        case ExternalResultDescription::ValueType::vtFixedString:
85
        case ExternalResultDescription::ValueType::vtString:
86
            assert_cast<ColumnString &>(column).insertData(value.data(), value.size());
87
            break;
88
        case ExternalResultDescription::ValueType::vtUUID:
89
            assert_cast<ColumnUUID &>(column).insertValue(parse<UUID>(value.data(), value.size()));
90
            break;
91
        case ExternalResultDescription::ValueType::vtDate:
92
            assert_cast<ColumnUInt16 &>(column).insertValue(UInt16{LocalDate{std::string(value)}.getDayNum()});
93
            break;
94
        case ExternalResultDescription::ValueType::vtDate32:
95
            assert_cast<ColumnInt32 &>(column).insertValue(Int32{LocalDate{std::string(value)}.getExtenedDayNum()});
96
            break;
97
        case ExternalResultDescription::ValueType::vtDateTime:
98
        {
99
            ReadBufferFromString in(value);
100
            time_t time = 0;
101
            readDateTimeText(time, in, assert_cast<const DataTypeDateTime *>(data_type.get())->getTimeZone());
102
            if (time < 0)
103
                time = 0;
104
            assert_cast<ColumnUInt32 &>(column).insertValue(static_cast<UInt32>(time));
105
            break;
106
        }
107
        case ExternalResultDescription::ValueType::vtDateTime64:
108
        {
109
            ReadBufferFromString in(value);
110
            DateTime64 time = 0;
111
            readDateTime64Text(time, 6, in, assert_cast<const DataTypeDateTime64 *>(data_type.get())->getTimeZone());
112
            assert_cast<DataTypeDateTime64::ColumnType &>(column).insertValue(time);
113
            break;
114
        }
115
        case ExternalResultDescription::ValueType::vtDecimal32: [[fallthrough]];
116
        case ExternalResultDescription::ValueType::vtDecimal64: [[fallthrough]];
117
        case ExternalResultDescription::ValueType::vtDecimal128: [[fallthrough]];
118
        case ExternalResultDescription::ValueType::vtDecimal256:
119
        {
120
            ReadBufferFromString istr(value);
121
            data_type->getDefaultSerialization()->deserializeWholeText(column, istr, FormatSettings{});
122
            break;
123
        }
124
        case ExternalResultDescription::ValueType::vtArray:
125
        {
126
            pqxx::array_parser parser{value};
127
            std::pair<pqxx::array_parser::juncture, std::string> parsed = parser.get_next();
128

129
            size_t dimension = 0, max_dimension = 0, expected_dimensions = array_info.at(idx).num_dimensions;
130
            const auto parse_value = array_info.at(idx).pqxx_parser;
131
            std::vector<Row> dimensions(expected_dimensions + 1);
132

133
            while (parsed.first != pqxx::array_parser::juncture::done)
134
            {
135
                if ((parsed.first == pqxx::array_parser::juncture::row_start) && (++dimension > expected_dimensions))
136
                    throw Exception(ErrorCodes::BAD_ARGUMENTS, "Got more dimensions than expected");
137

138
                else if (parsed.first == pqxx::array_parser::juncture::string_value)
139
                    dimensions[dimension].emplace_back(parse_value(parsed.second));
140

141
                else if (parsed.first == pqxx::array_parser::juncture::null_value)
142
                    dimensions[dimension].emplace_back(array_info.at(idx).default_value);
143

144
                else if (parsed.first == pqxx::array_parser::juncture::row_end)
145
                {
146
                    max_dimension = std::max(max_dimension, dimension);
147

148
                    --dimension;
149
                    if (dimension == 0)
150
                        break;
151

152
                    dimensions[dimension].emplace_back(Array(dimensions[dimension + 1].begin(), dimensions[dimension + 1].end()));
153
                    dimensions[dimension + 1].clear();
154
                }
155

156
                parsed = parser.get_next();
157
            }
158

159
            if (max_dimension < expected_dimensions)
160
                throw Exception(ErrorCodes::BAD_ARGUMENTS,
161
                        "Got less dimensions than expected. ({} instead of {})", max_dimension, expected_dimensions);
162

163
            assert_cast<ColumnArray &>(column).insert(Array(dimensions[1].begin(), dimensions[1].end()));
164
            break;
165
        }
166
        default:
167
            throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Unsupported value type");
168
    }
169
}
170

171

172
void preparePostgreSQLArrayInfo(
173
        std::unordered_map<size_t, PostgreSQLArrayInfo> & array_info, size_t column_idx, DataTypePtr data_type)
174
{
175
    const auto * array_type = typeid_cast<const DataTypeArray *>(data_type.get());
176
    auto nested = array_type->getNestedType();
177

178
    size_t count_dimensions = 1;
179
    while (isArray(nested))
180
    {
181
        ++count_dimensions;
182
        nested = typeid_cast<const DataTypeArray *>(nested.get())->getNestedType();
183
    }
184

185
    Field default_value = nested->getDefault();
186
    if (nested->isNullable())
187
        nested = static_cast<const DataTypeNullable *>(nested.get())->getNestedType();
188

189
    WhichDataType which(nested);
190
    std::function<Field(std::string & fields)> parser;
191

192
    if (which.isUInt8() || which.isUInt16())
193
        parser = [](std::string & field) -> Field { return pqxx::from_string<uint16_t>(field); };
194
    else if (which.isInt8() || which.isInt16())
195
        parser = [](std::string & field) -> Field { return pqxx::from_string<int16_t>(field); };
196
    else if (which.isUInt32())
197
        parser = [](std::string & field) -> Field { return pqxx::from_string<uint32_t>(field); };
198
    else if (which.isInt32())
199
        parser = [](std::string & field) -> Field { return pqxx::from_string<int32_t>(field); };
200
    else if (which.isUInt64())
201
        parser = [](std::string & field) -> Field { return pqxx::from_string<uint64_t>(field); };
202
    else if (which.isInt64())
203
        parser = [](std::string & field) -> Field { return pqxx::from_string<int64_t>(field); };
204
    else if (which.isFloat32())
205
        parser = [](std::string & field) -> Field { return pqxx::from_string<float>(field); };
206
    else if (which.isFloat64())
207
        parser = [](std::string & field) -> Field { return pqxx::from_string<double>(field); };
208
    else if (which.isUUID())
209
        parser = [](std::string & field) -> Field { return parse<UUID>(field); };
210
    else if (which.isString() || which.isFixedString())
211
        parser = [](std::string & field) -> Field { return field; };
212
    else if (which.isDate())
213
        parser = [](std::string & field) -> Field { return UInt16{LocalDate{field}.getDayNum()}; };
214
    else if (which.isDateTime())
215
        parser = [nested](std::string & field) -> Field
216
        {
217
            ReadBufferFromString in(field);
218
            time_t time = 0;
219
            readDateTimeText(time, in, assert_cast<const DataTypeDateTime *>(nested.get())->getTimeZone());
220
            if (time < 0)
221
                time = 0;
222
            return time;
223
        };
224
    else if (which.isDateTime64())
225
        parser = [nested](std::string & field) -> Field
226
        {
227
            ReadBufferFromString in(field);
228
            DateTime64 time = 0;
229
            readDateTime64Text(time, 6, in, assert_cast<const DataTypeDateTime64 *>(nested.get())->getTimeZone());
230
            if (time < 0)
231
                time = 0;
232
            return time;
233
        };
234
    else if (which.isDecimal32())
235
        parser = [nested](std::string & field) -> Field
236
        {
237
            const auto & type = typeid_cast<const DataTypeDecimal<Decimal32> *>(nested.get());
238
            DataTypeDecimal<Decimal32> res(getDecimalPrecision(*type), getDecimalScale(*type));
239
            return convertFieldToType(field, res);
240
        };
241
    else if (which.isDecimal64())
242
        parser = [nested](std::string & field) -> Field
243
        {
244
            const auto & type = typeid_cast<const DataTypeDecimal<Decimal64> *>(nested.get());
245
            DataTypeDecimal<Decimal64> res(getDecimalPrecision(*type), getDecimalScale(*type));
246
            return convertFieldToType(field, res);
247
        };
248
    else if (which.isDecimal128())
249
        parser = [nested](std::string & field) -> Field
250
        {
251
            const auto & type = typeid_cast<const DataTypeDecimal<Decimal128> *>(nested.get());
252
            DataTypeDecimal<Decimal128> res(getDecimalPrecision(*type), getDecimalScale(*type));
253
            return convertFieldToType(field, res);
254
        };
255
    else if (which.isDecimal256())
256
        parser = [nested](std::string & field) -> Field
257
        {
258
            const auto & type = typeid_cast<const DataTypeDecimal<Decimal256> *>(nested.get());
259
            DataTypeDecimal<Decimal256> res(getDecimalPrecision(*type), getDecimalScale(*type));
260
            return convertFieldToType(field, res);
261
        };
262
    else
263
        throw Exception(ErrorCodes::BAD_ARGUMENTS, "Type conversion to {} is not supported", nested->getName());
264

265
    array_info[column_idx] = {count_dimensions, default_value, parser};
266
}
267
}
268

269
#endif
270

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.