private PCharArray() { super("CHAR ARRAY", PDataType.ARRAY_TYPE_BASE + PChar.INSTANCE.getSqlType(), PhoenixArray.class, null, 29); }
@Override public void coerceBytes(ImmutableBytesWritable ptr, Object o, PDataType actualType, Integer actualMaxLength, Integer actualScale, SortOrder actualModifier, Integer desiredMaxLength, Integer desiredScale, SortOrder expectedModifier) { if (o != null && actualType.equals(PVarchar.INSTANCE) && ((String)o).length() != ptr.getLength()) { throw newIllegalDataException("CHAR types may only contain single byte characters (" + o + ")"); } super.coerceBytes(ptr, o, actualType, actualMaxLength, actualScale, actualModifier, desiredMaxLength, desiredScale, expectedModifier); if (ptr.getLength() > 0 && desiredMaxLength != null && desiredMaxLength > ptr.getLength()) { pad(ptr, desiredMaxLength, expectedModifier); } }
@Override public boolean isSizeCompatible(ImmutableBytesWritable ptr, Object value, PDataType srcType, SortOrder sortOrder, Integer maxLength, Integer scale, Integer desiredMaxLength, Integer desiredScale) { if (ptr.getLength() != 0 && desiredMaxLength != null) { if (maxLength == null) { if (value != null && srcType == INSTANCE) { // Use value if provided maxLength = ((String)value).length(); } else { this.coerceBytes(ptr, value, srcType, maxLength, scale, sortOrder, desiredMaxLength, desiredScale, sortOrder, true); maxLength = ptr.getLength(); // Only single byte characters } } return maxLength <= desiredMaxLength; } return true; }
@Override public Object toObject(Object object, PDataType actualType) { if (equalsAny(actualType, PVarchar.INSTANCE, this)) { String s = (String) object; return s == null || s.length() > 0 ? s : null; } return throwConstraintViolationException(actualType,this); }
@Override public Object toObject(byte[] bytes, int offset, int length, PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) { if (length == 0) { return null; } if (!actualType.isCoercibleTo(this)) { throwConstraintViolationException(actualType, this); } length = StringUtil.getUnpaddedCharLength(bytes, offset, length, sortOrder); if (sortOrder == SortOrder.DESC) { bytes = SortOrder.invert(bytes, offset, length); offset = 0; } // TODO: UTF-8 decoder that will invert as it decodes String s = Bytes.toString(bytes, offset, length); if (length != s.length()) { throw newIllegalDataException("CHAR types may only contain single byte characters (" + s + ")"); } return s; }
@Test public void testMultipleNonEqualitiesPkColumn() throws SQLException { String tenantId = "000000000000001"; String keyPrefix = "002"; String query = "select * from atable where organization_id >= '" + tenantId + "' AND substr(entity_id,1,3) > '" + keyPrefix + "'"; StatementContext context = compileStatement(query); Scan scan = context.getScan(); assertNotNull(scan.getFilter()); // assertArrayEquals(PVarchar.INSTANCE.toBytes(tenantId), scan.getStartRow()); assertArrayEquals( ByteUtil.concat(PChar.INSTANCE.toBytes(tenantId), PChar.INSTANCE.toBytes( PChar.INSTANCE.pad( PChar.INSTANCE.toObject(ByteUtil.nextKey(PChar.INSTANCE.toBytes(keyPrefix))), 15))), scan.getStartRow()); assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow()); }
@Override public int toBytes(Object object, byte[] bytes, int offset) { if (object == null) { throw newIllegalDataException(this + " may not be null"); } int len = PVarchar.INSTANCE.toBytes(object, bytes, offset); if (len != ((String) object).length()) { throw newIllegalDataException("CHAR types may only contain single byte characters (" + object + ")"); } return len; }
protected void initAvgGroupTable(Connection conn, String tableName, String tableProps) throws SQLException { PreparedStatement stmt = conn.prepareStatement("CREATE TABLE " + tableName + " (k1 char(1) not null, k2 integer not null, constraint pk primary key (k1,k2)) " + tableProps + " split on (?,?,?)"); stmt.setBytes(1, ByteUtil.concat(PChar.INSTANCE.toBytes("a"), PInteger.INSTANCE.toBytes(3))); stmt.setBytes(2, ByteUtil.concat(PChar.INSTANCE.toBytes("j"), PInteger.INSTANCE.toBytes(3))); stmt.setBytes(3, ByteUtil.concat(PChar.INSTANCE.toBytes("n"), PInteger.INSTANCE.toBytes(3))); stmt.execute(); conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a', 1)"); conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a', 2)"); conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a', 3)"); conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('a', 6)"); conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('b', 5)"); conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('j', 1)"); conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('j', 2)"); conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('j', 3)"); conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('j', 10)"); conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('n', 1)"); conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('n', 2)"); conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('n', 3)"); conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('n', 2)"); conn.commit(); }
@Override public boolean isCoercibleTo(PDataType targetType) { return equalsAny(targetType, this, PVarchar.INSTANCE, PBinary.INSTANCE, PVarbinary.INSTANCE); }
private static KeyRange getKeyRange(byte[] lowerRange, boolean lowerInclusive, byte[] upperRange, boolean upperInclusive) { return PChar.INSTANCE.getKeyRange(lowerRange, lowerInclusive, upperRange, upperInclusive); }
PChar.INSTANCE.getKeyRange(Bytes.toBytes("a"), true, Bytes.toBytes("a"), true),},{ PChar.INSTANCE.getKeyRange(Bytes.toBytes("1"), true, Bytes.toBytes("1"), true),},{ PChar.INSTANCE.getKeyRange(Bytes.toBytes("A"), true, Bytes.toBytes("A"), true),}}, new int[] {1,1,1}, PChar.INSTANCE.toBytes("a1A"), Bound.LOWER )); PChar.INSTANCE.getKeyRange(Bytes.toBytes("a"), true, Bytes.toBytes("b"), true),},{ PChar.INSTANCE.getKeyRange(Bytes.toBytes("1"), true, Bytes.toBytes("2"), true),},{ PChar.INSTANCE.getKeyRange(Bytes.toBytes("A"), true, Bytes.toBytes("B"), true),}}, new int[] {1,1,1}, PChar.INSTANCE.toBytes("a1A"), Bound.LOWER )); PChar.INSTANCE.getKeyRange(Bytes.toBytes("a"), true, Bytes.toBytes("a"), true),},{ PChar.INSTANCE.getKeyRange(Bytes.toBytes("1"), true, Bytes.toBytes("2"), true),},{ PChar.INSTANCE.getKeyRange(Bytes.toBytes("A"), true, Bytes.toBytes("A"), true),}}, new int[] {1,1,1}, PChar.INSTANCE.toBytes("a1A"), Bound.LOWER )); PChar.INSTANCE.getKeyRange(Bytes.toBytes("a"), false, Bytes.toBytes("b"), true),},{ PChar.INSTANCE.getKeyRange(Bytes.toBytes("1"), false, Bytes.toBytes("2"), true),},{ PChar.INSTANCE.getKeyRange(Bytes.toBytes("A"), false, Bytes.toBytes("B"), true),}}, new int[] {1,1,1}, PChar.INSTANCE.toBytes("b2B"),
break; case CHAR: isCastable = PChar.INSTANCE.isCastableTo(targetColumn.getPDataType()); break; case VARCHAR: isCastable = PChar.INSTANCE.isCastableTo(targetColumn.getPDataType()); break; case DATETIME:
@Override public Object toObject(Object object, PDataType actualType) { if (equalsAny(actualType, PVarchar.INSTANCE, this)) { String s = (String) object; return s == null || s.length() > 0 ? s : null; } return throwConstraintViolationException(actualType,this); }
@Override public Object toObject(byte[] bytes, int offset, int length, PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) { if (length == 0) { return null; } if (!actualType.isCoercibleTo(this)) { throwConstraintViolationException(actualType, this); } length = StringUtil.getUnpaddedCharLength(bytes, offset, length, sortOrder); if (sortOrder == SortOrder.DESC) { bytes = SortOrder.invert(bytes, offset, length); offset = 0; } // TODO: UTF-8 decoder that will invert as it decodes String s = Bytes.toString(bytes, offset, length); if (length != s.length()) { throw newIllegalDataException("CHAR types may only contain single byte characters (" + s + ")"); } return s; }
@Override public byte[] toBytes(Object object) { if (object == null) { return ByteUtil.EMPTY_BYTE_ARRAY; } byte[] b = PVarchar.INSTANCE.toBytes(object); if (b.length != ((String) object).length()) { throw newIllegalDataException("CHAR types may only contain single byte characters (" + object + ")"); } return b; }
@Test public void testUsingRVCFullyQualifiedInClause() throws Exception { String firstOrgId = "000000000000001"; String secondOrgId = "000000000000009"; String firstParentId = "000000000000011"; String secondParentId = "000000000000021"; String query = "select * from atable where (organization_id, entity_id) IN ((?, ?), (?, ?))"; List<Object> binds = Arrays.<Object>asList(firstOrgId, firstParentId, secondOrgId, secondParentId); StatementContext context = compileStatement(query, binds); Scan scan = context.getScan(); Filter filter = scan.getFilter(); assertTrue(filter instanceof SkipScanFilter); List<List<KeyRange>> skipScanRanges = Collections.singletonList(Arrays.asList( KeyRange.getKeyRange(ByteUtil.concat(PChar.INSTANCE.toBytes(firstOrgId), PChar.INSTANCE.toBytes(firstParentId))), KeyRange.getKeyRange(ByteUtil.concat(PChar.INSTANCE.toBytes(secondOrgId), PChar.INSTANCE.toBytes(secondParentId))))); assertEquals(skipScanRanges, context.getScanRanges().getRanges()); assertArrayEquals(ByteUtil.concat(PChar.INSTANCE.toBytes(firstOrgId), PChar.INSTANCE.toBytes(firstParentId)), scan.getStartRow()); assertArrayEquals(ByteUtil.concat(PChar.INSTANCE.toBytes(secondOrgId), PChar.INSTANCE.toBytes(secondParentId), QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow()); }
@Override public boolean isCoercibleTo(PDataType targetType) { return equalsAny(targetType, this, PVarchar.INSTANCE, PBinary.INSTANCE, PVarbinary.INSTANCE); }
private static KeyRange newKeyRange(byte[] lowerRange, byte[] upperRange) { return PChar.INSTANCE.getKeyRange(lowerRange, true, upperRange, false); }
@Test public void testOrSameColRangeExpression() throws SQLException { String query = "select * from atable where substr(organization_id,1,3) = ? or organization_id LIKE 'foo%'"; List<Object> binds = Arrays.<Object>asList("00D"); StatementContext context = compileStatement(query, binds); Scan scan = context.getScan(); Filter filter = scan.getFilter(); assertNotNull(filter); assertTrue(filter instanceof SkipScanFilter); ScanRanges scanRanges = context.getScanRanges(); assertNotNull(scanRanges); List<List<KeyRange>> ranges = scanRanges.getRanges(); assertEquals(1,ranges.size()); List<List<KeyRange>> expectedRanges = Collections.singletonList(Arrays.asList( PChar.INSTANCE.getKeyRange( StringUtil.padChar(PChar.INSTANCE.toBytes("00D"),15), true, StringUtil.padChar(ByteUtil.nextKey(PChar.INSTANCE.toBytes("00D")),15), false), PChar.INSTANCE.getKeyRange( StringUtil.padChar(PChar.INSTANCE.toBytes("foo"),15), true, StringUtil.padChar(ByteUtil.nextKey(PChar.INSTANCE.toBytes("foo")),15), false))); assertEquals(expectedRanges, ranges); }