@Override public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { // TODO: multi-byte characters Expression offsetExpression = getOffsetExpression(); if (!offsetExpression.evaluate(tuple, ptr)) { return false; } LongNative longNative = (LongNative) offsetExpression.getDataType().getNative(); int offset = (int) longNative.toLong(ptr); int length = -1; if (hasLengthExpression) { Expression lengthExpression = getLengthExpression(); if (!lengthExpression.evaluate(tuple, ptr)) { return false; } longNative = (LongNative) lengthExpression.getDataType().getNative(); length = (int) longNative.toLong(ptr); if (length <= 0) { return false; } } if (!getStrExpression().evaluate(tuple, ptr)) { return false; } try { boolean isCharType = getStrExpression().getDataType() == PDataType.CHAR; int strlen = isCharType ? ptr.getLength() : StringUtil.calculateUTF8Length(ptr.get(), ptr.getOffset(), ptr.getLength()); // Account for 1 versus 0-based offset offset = offset - (offset <= 0 ? 0 : 1); if (offset < 0) { // Offset < 0 means get from end offset = strlen + offset; } if (offset < 0 || offset >= strlen) { return false; } int maxLength = strlen - offset; length = length == -1 ? maxLength : Math.min(length, maxLength); int byteOffset = isCharType ? offset : StringUtil.getByteLengthForUtf8SubStr(ptr.get(), ptr.getOffset(), offset); int byteLength = isCharType ? length : StringUtil.getByteLengthForUtf8SubStr( ptr.get(), ptr.getOffset() + byteOffset, length); ptr.set(ptr.get(), ptr.getOffset() + byteOffset, byteLength); return true; } catch (UnsupportedEncodingException e) { return false; } }
/** * Get array of ColumnInfos that contain Column Name and its associated PDataType * * @param columns * @return * @throws SQLException */ private ColumnInfo[] generateColumnInfo(List<String> columns) throws SQLException { Map<String, Integer> columnNameToTypeMap = Maps.newLinkedHashMap(); DatabaseMetaData dbmd = conn.getMetaData(); // TODO: escape wildcard characters here because we don't want that behavior here String escapedTableName = StringUtil.escapeLike(tableName); String[] schemaAndTable = escapedTableName.split("\\."); ResultSet rs = null; try { rs = dbmd.getColumns( null, (schemaAndTable.length == 1 ? "" : schemaAndTable[0]), (schemaAndTable.length == 1 ? escapedTableName : schemaAndTable[1]), null); while (rs.next()) { columnNameToTypeMap.put( rs.getString(QueryUtil.COLUMN_NAME_POSITION), rs.getInt(QueryUtil.DATA_TYPE_POSITION)); } } finally { if (rs != null) { rs.close(); } } ColumnInfo[] columnType; if (columns == null) { int i = 0; columnType = new ColumnInfo[columnNameToTypeMap.size()]; for (Map.Entry<String, Integer> entry : columnNameToTypeMap.entrySet()) { columnType[i++] = new ColumnInfo(entry.getKey(), entry.getValue()); } } else { // Leave "null" as indication to skip b/c it doesn't exist columnType = new ColumnInfo[columns.size()]; for (int i = 0; i < columns.size(); i++) { String columnName = SchemaUtil.normalizeIdentifier(columns.get(i).trim()); Integer sqlType = columnNameToTypeMap.get(columnName); if (sqlType == null) { if (isStrict) { throw new SQLExceptionInfo.Builder(SQLExceptionCode.COLUMN_NOT_FOUND) .setColumnName(columnName) .setTableName(tableName) .build() .buildException(); } unfoundColumnCount++; } else { columnType[i] = new ColumnInfo(columnName, sqlType); } } if (unfoundColumnCount == columns.size()) { throw new SQLExceptionInfo.Builder(SQLExceptionCode.COLUMN_NOT_FOUND) .setColumnName(Arrays.toString(columns.toArray(new String[0]))) .setTableName(tableName) .build() .buildException(); } } return columnType; }
@Override public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { if (!getStringExpression().evaluate(tuple, ptr)) { return false; } if (ptr.getLength() == 0) { ptr.set(ByteUtil.EMPTY_BYTE_ARRAY); return true; } byte[] string = ptr.get(); int offset = ptr.getOffset(); int length = ptr.getLength(); ColumnModifier columnModifier = getColumnModifier(); int end = StringUtil.getFirstNonBlankCharIdxFromEnd(string, offset, length, columnModifier); if (end == offset - 1) { ptr.set(ByteUtil.EMPTY_BYTE_ARRAY); return true; } int head = StringUtil.getFirstNonBlankCharIdxFromStart(string, offset, length, columnModifier); ptr.set(string, head, end - head + 1); return true; }