| 173 | } |
| 174 | |
| 175 | void SchemaEvolution::buildSafePPDConversionMap(const Type* readType, const Type* fileType) { |
| 176 | if (readType == nullptr || !isPrimitive(readType) || fileType == nullptr || |
| 177 | !isPrimitive(fileType)) { |
| 178 | return; |
| 179 | } |
| 180 | |
| 181 | bool isSafe = false; |
| 182 | if (readType == fileType) { |
| 183 | // short cut for same type |
| 184 | isSafe = true; |
| 185 | } else if (readType->getKind() == DECIMAL && fileType->getKind() == DECIMAL) { |
| 186 | // for decimals alone do equality check to not mess up with precision change |
| 187 | if (fileType->getPrecision() == readType_->getPrecision() && |
| 188 | fileType->getScale() == readType_->getScale()) { |
| 189 | isSafe = true; |
| 190 | } |
| 191 | } else { |
| 192 | // only integer and string evolutions are safe |
| 193 | // byte -> short -> int -> long |
| 194 | // string <-> char <-> varchar |
| 195 | // NOTE: Float to double evolution is not safe as floats are stored as |
| 196 | // doubles in ORC's internal index, but when doing predicate evaluation |
| 197 | // for queries like "select * from orc_float where f = 74.72" the constant |
| 198 | // on the filter is converted from string -> double so the precisions will |
| 199 | // be different and the comparison will fail. |
| 200 | // Soon, we should convert all sargs that compare equality between floats |
| 201 | // or doubles to range predicates. |
| 202 | // Similarly string -> char and varchar -> char and vice versa is impossible |
| 203 | // as ORC stores char with padded spaces in its internal index. |
| 204 | switch (fileType->getKind()) { |
| 205 | case BYTE: { |
| 206 | if (readType_->getKind() == SHORT || readType_->getKind() == INT || |
| 207 | readType_->getKind() == LONG) { |
| 208 | isSafe = true; |
| 209 | } |
| 210 | break; |
| 211 | } |
| 212 | case SHORT: { |
| 213 | if (readType_->getKind() == INT || readType_->getKind() == LONG) { |
| 214 | isSafe = true; |
| 215 | } |
| 216 | break; |
| 217 | } |
| 218 | case INT: { |
| 219 | if (readType_->getKind() == LONG) { |
| 220 | isSafe = true; |
| 221 | } |
| 222 | break; |
| 223 | } |
| 224 | case STRING: { |
| 225 | if (readType_->getKind() == VARCHAR) { |
| 226 | isSafe = true; |
| 227 | } |
| 228 | break; |
| 229 | } |
| 230 | case VARCHAR: { |
| 231 | if (readType_->getKind() == STRING) { |
| 232 | isSafe = true; |
nothing calls this directly
no test coverage detected