/** * Extracts the value from a literal. * * <p>Cases: * * <ul> * <li>If the node is a character literal, a chain of string literals, or a CAST of a character * literal, returns the value as a {@link NlsString}. * <li>If the node is a numeric literal, or a negated numeric literal, returns the value as a * {@link BigDecimal}. * <li>If the node is a {@link SqlIntervalQualifier}, returns its {@link TimeUnitRange}. * <li>If the node is INTERVAL_DAY_TIME in {@link SqlTypeFamily}, returns its sign multiplied by * its millisecond equivalent value * <li>If the node is INTERVAL_YEAR_MONTH in {@link SqlTypeFamily}, returns its sign multiplied * by its months equivalent value * <li>Otherwise the behavior is not specified. * </ul> */ public static Comparable value(SqlNode node) { if (node instanceof SqlLiteral) { SqlLiteral literal = (SqlLiteral) node; switch (literal.getTypeName().getFamily()) { case CHARACTER: return (NlsString) literal.value; case NUMERIC: return (BigDecimal) literal.value; case INTERVAL_YEAR_MONTH: final SqlIntervalLiteral.IntervalValue valMonth = (SqlIntervalLiteral.IntervalValue) literal.value; return valMonth.getSign() * SqlParserUtil.intervalToMonths(valMonth); case INTERVAL_DAY_TIME: final SqlIntervalLiteral.IntervalValue valTime = (SqlIntervalLiteral.IntervalValue) literal.value; return valTime.getSign() * SqlParserUtil.intervalToMillis(valTime); } } if (SqlUtil.isLiteralChain(node)) { assert node instanceof SqlCall; final SqlLiteral literal = SqlLiteralChainOperator.concatenateOperands((SqlCall) node); assert SqlTypeUtil.inCharFamily(literal.getTypeName()); return (NlsString) literal.value; } if (node instanceof SqlIntervalQualifier) { SqlIntervalQualifier qualifier = (SqlIntervalQualifier) node; return qualifier.timeUnitRange; } switch (node.getKind()) { case CAST: assert node instanceof SqlCall; return value(((SqlCall) node).operand(0)); case MINUS_PREFIX: assert node instanceof SqlCall; Comparable o = value(((SqlCall) node).operand(0)); if (o instanceof BigDecimal) { BigDecimal bigDecimal = (BigDecimal) o; return bigDecimal.negate(); } // fall through default: throw Util.newInternal("invalid literal: " + node); } }
public static SqlNumericLiteral createExactNumeric(String s, SqlParserPos pos) { BigDecimal value; int prec; int scale; int i = s.indexOf('.'); if ((i >= 0) && ((s.length() - 1) != i)) { value = SqlParserUtil.parseDecimal(s); scale = s.length() - i - 1; assert scale == value.scale() : s; prec = s.length() - 1; } else if ((i >= 0) && ((s.length() - 1) == i)) { value = SqlParserUtil.parseInteger(s.substring(0, i)); scale = 0; prec = s.length() - 1; } else { value = SqlParserUtil.parseInteger(s); scale = 0; prec = s.length(); } return new SqlNumericLiteral(value, prec, scale, true, pos); }
/** * Checks whether an exception matches the expected pattern. If <code> * sap</code> contains an error location, checks this too. * * @param ex Exception thrown * @param expectedMsgPattern Expected pattern * @param sap Query and (optional) position in query */ public static void checkEx( Throwable ex, String expectedMsgPattern, SqlParserUtil.StringAndPos sap) { if (null == ex) { if (expectedMsgPattern == null) { // No error expected, and no error happened. return; } else { throw new AssertionError( "Expected query to throw exception, " + "but it did not; query [" + sap.sql + "]; expected [" + expectedMsgPattern + "]"); } } Throwable actualException = ex; String actualMessage = actualException.getMessage(); int actualLine = -1; int actualColumn = -1; int actualEndLine = 100; int actualEndColumn = 99; // Search for an CalciteContextException somewhere in the stack. CalciteContextException ece = null; for (Throwable x = ex; x != null; x = x.getCause()) { if (x instanceof CalciteContextException) { ece = (CalciteContextException) x; break; } if (x.getCause() == x) { break; } } // Search for a SqlParseException -- with its position set -- somewhere // in the stack. SqlParseException spe = null; for (Throwable x = ex; x != null; x = x.getCause()) { if ((x instanceof SqlParseException) && (((SqlParseException) x).getPos() != null)) { spe = (SqlParseException) x; break; } if (x.getCause() == x) { break; } } if (ece != null) { actualLine = ece.getPosLine(); actualColumn = ece.getPosColumn(); actualEndLine = ece.getEndPosLine(); actualEndColumn = ece.getEndPosColumn(); if (ece.getCause() != null) { actualException = ece.getCause(); actualMessage = actualException.getMessage(); } } else if (spe != null) { actualLine = spe.getPos().getLineNum(); actualColumn = spe.getPos().getColumnNum(); actualEndLine = spe.getPos().getEndLineNum(); actualEndColumn = spe.getPos().getEndColumnNum(); if (spe.getCause() != null) { actualException = spe.getCause(); actualMessage = actualException.getMessage(); } } else { final String message = ex.getMessage(); if (message != null) { Matcher matcher = LINE_COL_TWICE_PATTERN.matcher(message); if (matcher.matches()) { actualLine = Integer.parseInt(matcher.group(1)); actualColumn = Integer.parseInt(matcher.group(2)); actualEndLine = Integer.parseInt(matcher.group(3)); actualEndColumn = Integer.parseInt(matcher.group(4)); actualMessage = matcher.group(5); } else { matcher = LINE_COL_PATTERN.matcher(message); if (matcher.matches()) { actualLine = Integer.parseInt(matcher.group(1)); actualColumn = Integer.parseInt(matcher.group(2)); } } } } if (null == expectedMsgPattern) { if (null != actualException) { actualException.printStackTrace(); fail( "Validator threw unexpected exception" + "; query [" + sap.sql + "]; exception [" + actualMessage + "]; class [" + actualException.getClass() + "]; pos [line " + actualLine + " col " + actualColumn + " thru line " + actualLine + " col " + actualColumn + "]"); } } else { if (null == actualException) { fail( "Expected validator to throw " + "exception, but it did not; query [" + sap.sql + "]; expected [" + expectedMsgPattern + "]"); } else { String sqlWithCarets; if ((actualColumn <= 0) || (actualLine <= 0) || (actualEndColumn <= 0) || (actualEndLine <= 0)) { if (sap.pos != null) { AssertionError e = new AssertionError( "Expected error to have position," + " but actual error did not: " + " actual pos [line " + actualLine + " col " + actualColumn + " thru line " + actualEndLine + " col " + actualEndColumn + "]"); e.initCause(actualException); throw e; } sqlWithCarets = sap.sql; } else { sqlWithCarets = SqlParserUtil.addCarets( sap.sql, actualLine, actualColumn, actualEndLine, actualEndColumn + 1); if (sap.pos == null) { throw new AssertionError( "Actual error had a position, but expected error" + " did not. Add error position carets to sql:\n" + sqlWithCarets); } } if (actualMessage != null) { actualMessage = Util.toLinux(actualMessage); } if ((actualMessage == null) || !actualMessage.matches(expectedMsgPattern)) { actualException.printStackTrace(); final String actualJavaRegexp = (actualMessage == null) ? "null" : TestUtil.quoteForJava(TestUtil.quotePattern(actualMessage)); fail( "Validator threw different " + "exception than expected; query [" + sap.sql + "];\n" + " expected pattern [" + expectedMsgPattern + "];\n" + " actual [" + actualMessage + "];\n" + " actual as java regexp [" + actualJavaRegexp + "]; pos [" + actualLine + " col " + actualColumn + " thru line " + actualEndLine + " col " + actualEndColumn + "]; sql [" + sqlWithCarets + "]"); } else if ((sap.pos != null) && ((actualLine != sap.pos.getLineNum()) || (actualColumn != sap.pos.getColumnNum()) || (actualEndLine != sap.pos.getEndLineNum()) || (actualEndColumn != sap.pos.getEndColumnNum()))) { fail( "Validator threw expected " + "exception [" + actualMessage + "];\nbut at pos [line " + actualLine + " col " + actualColumn + " thru line " + actualEndLine + " col " + actualEndColumn + "];\nsql [" + sqlWithCarets + "]"); } } } }
public static SqlNumericLiteral createApproxNumeric(String s, SqlParserPos pos) { BigDecimal value = SqlParserUtil.parseDecimal(s); return new SqlNumericLiteral(value, null, null, false, pos); }