/** * Internal method to create a call to a literal. Code outside this package should call one of the * type-specific methods such as {@link #makeDateLiteral(Calendar)}, {@link * #makeLiteral(boolean)}, {@link #makeLiteral(String)}. * * @param o Value of literal, must be appropriate for the type * @param type Type of literal * @param typeName SQL type of literal * @return Literal */ protected RexLiteral makeLiteral(Comparable o, RelDataType type, SqlTypeName typeName) { // All literals except NULL have NOT NULL types. type = typeFactory.createTypeWithNullability(type, o == null); if (typeName == SqlTypeName.CHAR) { // Character literals must have a charset and collation. Populate // from the type if necessary. assert o instanceof NlsString; NlsString nlsString = (NlsString) o; if ((nlsString.getCollation() == null) || (nlsString.getCharset() == null)) { assert type.getSqlTypeName() == SqlTypeName.CHAR; assert type.getCharset().name() != null; assert type.getCollation() != null; o = new NlsString(nlsString.getValue(), type.getCharset().name(), type.getCollation()); } } return new RexLiteral(o, type, typeName); }
public RelDataType createSqlType(RelDataTypeFactory typeFactory) { BitString bitString; switch (typeName) { case NULL: case BOOLEAN: RelDataType ret = typeFactory.createSqlType(typeName); ret = typeFactory.createTypeWithNullability(ret, null == value); return ret; case BINARY: bitString = (BitString) value; int bitCount = bitString.getBitCount(); return typeFactory.createSqlType(SqlTypeName.BINARY, bitCount / 8); case CHAR: NlsString string = (NlsString) value; Charset charset = string.getCharset(); if (null == charset) { charset = typeFactory.getDefaultCharset(); } SqlCollation collation = string.getCollation(); if (null == collation) { collation = SqlCollation.COERCIBLE; } RelDataType type = typeFactory.createSqlType(SqlTypeName.CHAR, string.getValue().length()); type = typeFactory.createTypeWithCharsetAndCollation(type, charset, collation); return type; case INTERVAL_YEAR_MONTH: case INTERVAL_DAY_TIME: SqlIntervalLiteral.IntervalValue intervalValue = (SqlIntervalLiteral.IntervalValue) value; return typeFactory.createSqlIntervalType(intervalValue.getIntervalQualifier()); case SYMBOL: return typeFactory.createSqlType(SqlTypeName.SYMBOL); case INTEGER: // handled in derived class case TIME: // handled in derived class case VARCHAR: // should never happen case VARBINARY: // should never happen default: throw Util.needToImplement(toString() + ", operand=" + value); } }
/** * Transforms this literal (which must be of type character) into a new one in which 4-digit * Unicode escape sequences have been replaced with the corresponding Unicode characters. * * @param unicodeEscapeChar escape character (e.g. backslash) for Unicode numeric sequences; 0 * implies no transformation * @return transformed literal */ public SqlLiteral unescapeUnicode(char unicodeEscapeChar) { if (unicodeEscapeChar == 0) { return this; } assert SqlTypeUtil.inCharFamily(getTypeName()); NlsString ns = (NlsString) value; String s = ns.getValue(); StringBuilder sb = new StringBuilder(); int n = s.length(); for (int i = 0; i < n; ++i) { char c = s.charAt(i); if (c == unicodeEscapeChar) { if (n > (i + 1)) { if (s.charAt(i + 1) == unicodeEscapeChar) { sb.append(unicodeEscapeChar); ++i; continue; } } if ((i + 5) > n) { throw SqlUtil.newContextException( getParserPosition(), RESOURCE.unicodeEscapeMalformed(i)); } final String u = s.substring(i + 1, i + 5); final int v; try { v = Integer.parseInt(u, 16); } catch (NumberFormatException ex) { throw SqlUtil.newContextException( getParserPosition(), RESOURCE.unicodeEscapeMalformed(i)); } sb.append((char) (v & 0xFFFF)); // skip hexits i += 4; } else { sb.append(c); } } ns = new NlsString(sb.toString(), ns.getCharsetName(), ns.getCollation()); return new SqlCharStringLiteral(ns, getParserPosition()); }
/** Returns an {@link NlsString} with spaces to make it at least a given length. */ private static NlsString padRight(NlsString s, int length) { if (s.getValue().length() >= length) { return s; } return s.copy(padRight(s.getValue(), length)); }