| 78 | |
| 79 | template<typename T> |
| 80 | Block PostgreSQLBlockInputStream<T>::readImpl() |
| 81 | { |
| 82 | /// Check if pqxx::stream_from is finished |
| 83 | if (!stream || !(*stream)) |
| 84 | return Block(); |
| 85 | |
| 86 | MutableColumns columns = description.sample_block.cloneEmptyColumns(); |
| 87 | size_t num_rows = 0; |
| 88 | |
| 89 | while (true) |
| 90 | { |
| 91 | const std::vector<pqxx::zview> * row{stream->read_row()}; |
| 92 | |
| 93 | /// row is nullptr if pqxx::stream_from is finished |
| 94 | if (!row) |
| 95 | break; |
| 96 | |
| 97 | for (const auto idx : collections::range(0, row->size())) |
| 98 | { |
| 99 | const auto & sample = description.sample_block.getByPosition(idx); |
| 100 | |
| 101 | /// if got NULL type, then pqxx::zview will return nullptr in c_str() |
| 102 | if ((*row)[idx].c_str()) |
| 103 | { |
| 104 | if (description.types[idx].second) |
| 105 | { |
| 106 | ColumnNullable & column_nullable = assert_cast<ColumnNullable &>(*columns[idx]); |
| 107 | const auto & data_type = assert_cast<const DataTypeNullable &>(*sample.type); |
| 108 | |
| 109 | insertPostgreSQLValue( |
| 110 | column_nullable.getNestedColumn(), (*row)[idx], |
| 111 | description.types[idx].first, data_type.getNestedType(), array_info, idx); |
| 112 | |
| 113 | column_nullable.getNullMapData().emplace_back(0); |
| 114 | } |
| 115 | else |
| 116 | { |
| 117 | insertPostgreSQLValue( |
| 118 | *columns[idx], (*row)[idx], description.types[idx].first, sample.type, array_info, idx); |
| 119 | } |
| 120 | } |
| 121 | else |
| 122 | { |
| 123 | insertDefaultPostgreSQLValue(*columns[idx], *sample.column); |
| 124 | } |
| 125 | |
| 126 | } |
| 127 | |
| 128 | if (++num_rows == max_block_size) |
| 129 | break; |
| 130 | } |
| 131 | |
| 132 | return description.sample_block.cloneWithColumns(std::move(columns)); |
| 133 | } |
| 134 | |
| 135 | |
| 136 | template<typename T> |
nothing calls this directly
no test coverage detected