| 217 | namespace impala { |
| 218 | |
| 219 | void FinalizePartitionedColumnStats(const TTableSchema& col_stats_schema, |
| 220 | const vector<TPartitionStats>& existing_part_stats, |
| 221 | const vector<vector<string>>& expected_partitions, const TRowSet& rowset, |
| 222 | int32_t num_partition_cols, TAlterTableUpdateStatsParams* params) { |
| 223 | // The rowset should have the following schema: for every column in the source table, |
| 224 | // seven columns are produced, one row per partition. |
| 225 | // <ndv buckets>, <num nulls>, <max width>, <avg width>, <count rows>, |
| 226 | // <num trues>, <num falses>, <low value>, <high value> |
| 227 | static const int COLUMNS_PER_STAT = 9; |
| 228 | |
| 229 | const int num_cols = |
| 230 | (col_stats_schema.columns.size() - num_partition_cols) / COLUMNS_PER_STAT; |
| 231 | unordered_set<vector<string>> seen_partitions; |
| 232 | vector<PerColumnStats> stats(num_cols); |
| 233 | |
| 234 | if (rowset.rows.size() > 0) { |
| 235 | DCHECK_GE(rowset.rows[0].colVals.size(), COLUMNS_PER_STAT); |
| 236 | params->__isset.partition_stats = true; |
| 237 | for (const TRow& col_stats_row: rowset.rows) { |
| 238 | // The last few columns are partition columns that the results are grouped by, and |
| 239 | // so uniquely identify the partition that these stats belong to. |
| 240 | vector<string> partition_key_vals; |
| 241 | partition_key_vals.reserve(col_stats_row.colVals.size()); |
| 242 | for (int j = num_cols * COLUMNS_PER_STAT; j < col_stats_row.colVals.size(); ++j) { |
| 243 | stringstream ss; |
| 244 | PrintTColumnValue(col_stats_row.colVals[j], &ss); |
| 245 | partition_key_vals.push_back(ss.str()); |
| 246 | } |
| 247 | seen_partitions.insert(partition_key_vals); |
| 248 | |
| 249 | TPartitionStats* part_stat = ¶ms->partition_stats[partition_key_vals]; |
| 250 | part_stat->__isset.intermediate_col_stats = true; |
| 251 | for (int i = 0; i < num_cols * COLUMNS_PER_STAT; i += COLUMNS_PER_STAT) { |
| 252 | PerColumnStats* stat = &stats[i / COLUMNS_PER_STAT]; |
| 253 | const string& ndv = col_stats_row.colVals[i].stringVal.value; |
| 254 | int64_t num_rows = col_stats_row.colVals[i + 4].i64Val.value; |
| 255 | double avg_width = col_stats_row.colVals[i + 3].doubleVal.value; |
| 256 | int32_t max_width = col_stats_row.colVals[i + 2].i32Val.value; |
| 257 | int64_t num_nulls = col_stats_row.colVals[i + 1].i64Val.value; |
| 258 | int64_t num_trues = col_stats_row.colVals[i + 5].i64Val.value; |
| 259 | int64_t num_falses = col_stats_row.colVals[i + 6].i64Val.value; |
| 260 | TColumnValueHive low_value = col_stats_row.colVals[i + 7]; |
| 261 | TColumnValueHive high_value = col_stats_row.colVals[i + 8]; |
| 262 | |
| 263 | impala::TColumnValue low_value_impala = |
| 264 | ConvertToTColumnValue(col_stats_schema.columns[i + 7], low_value); |
| 265 | impala::TColumnValue high_value_impala = |
| 266 | ConvertToTColumnValue(col_stats_schema.columns[i + 8], high_value); |
| 267 | |
| 268 | VLOG(3) << "Updated statistics for column=[" |
| 269 | << col_stats_schema.columns[i].columnName << "]," << " statistics={" |
| 270 | << ndv << "," << num_rows << "," << avg_width << "," << num_trues |
| 271 | << "," << max_width << "," << num_nulls << "," << num_falses |
| 272 | << PrintTColumnValue(low_value_impala) << "," |
| 273 | << PrintTColumnValue(high_value_impala) << "}"; |
| 274 | stat->Update(ndv, num_rows, avg_width, max_width, num_nulls, num_trues, |
| 275 | num_falses, low_value_impala, high_value_impala); |
| 276 |
no test coverage detected