()
| 314 | } |
| 315 | |
| 316 | private void analyze() throws AnalysisException { |
| 317 | Preconditions.checkNotNull(type_); |
| 318 | if (type_.isComplexType()) { |
| 319 | throw new AnalysisException( |
| 320 | "Unsupported cast to complex type: " + type_.toSql()); |
| 321 | } |
| 322 | |
| 323 | boolean twoStepCastNeeded = |
| 324 | type_.getPrimitiveType() == PrimitiveType.CHAR && |
| 325 | children_.get(0).getType().getPrimitiveType() != PrimitiveType.STRING && |
| 326 | children_.get(0).getType().getPrimitiveType() != PrimitiveType.CHAR; |
| 327 | if (twoStepCastNeeded) { |
| 328 | // Back end functions only exist to cast string types to CHAR, there is not a cast |
| 329 | // for every type since it is redundant with STRING. Casts to go through 2 casts: |
| 330 | // (1) cast to string, to stringify the value |
| 331 | // (2) cast to CHAR, to truncate or pad with spaces |
| 332 | CastExpr tostring = CastExpr.createImplicit(ScalarType.STRING, children_.get(0), |
| 333 | castFormat_, compatibility_); |
| 334 | tostring.analyze(); |
| 335 | children_.set(0, tostring); |
| 336 | } |
| 337 | |
| 338 | if (null != castFormat_ && !twoStepCastNeeded) { |
| 339 | if (!(type_.isDateOrTimeType() && getChild(0).getType().isStringType()) && |
| 340 | !(type_.isStringType() && getChild(0).getType().isDateOrTimeType())) { |
| 341 | // FORMAT clause works only for casting between date types and string types |
| 342 | throw new AnalysisException("FORMAT clause is not applicable from " + |
| 343 | getChild(0).getType() + " to " + type_); |
| 344 | } |
| 345 | if (castFormat_.isEmpty()) { |
| 346 | throw new AnalysisException("FORMAT clause can't be empty"); |
| 347 | } |
| 348 | } |
| 349 | |
| 350 | if (children_.get(0) instanceof NumericLiteral && type_.isFloatingPointType()) { |
| 351 | // Special case casting a decimal literal to a floating point number. The decimal |
| 352 | // literal can be interpreted as either and we want to avoid casts since that can |
| 353 | // result in loss of accuracy. However, if 'type_' is FLOAT and the value does not |
| 354 | // fit in a FLOAT, we do not do an unchecked conversion |
| 355 | // ('NumericLiteral.explicitlyCastToFloat()') here but let the conversion fail in |
| 356 | // the BE. |
| 357 | NumericLiteral child = (NumericLiteral) children_.get(0); |
| 358 | final boolean isOverflow = NumericLiteral.isOverflow(child.getValue(), type_); |
| 359 | if (type_.isScalarType(PrimitiveType.FLOAT)) { |
| 360 | if (!isOverflow) { |
| 361 | ((NumericLiteral)children_.get(0)).explicitlyCastToFloat(type_); |
| 362 | } |
| 363 | } else { |
| 364 | Preconditions.checkState(type_.isScalarType(PrimitiveType.DOUBLE)); |
| 365 | Preconditions.checkState(!isOverflow); |
| 366 | ((NumericLiteral)children_.get(0)).explicitlyCastToFloat(type_); |
| 367 | } |
| 368 | } |
| 369 | |
| 370 | if (children_.get(0).getType().isNull()) { |
| 371 | // Make sure BE never sees TYPE_NULL |
| 372 | uncheckedCastChild(type_, 0); |
| 373 | } |
no test coverage detected