use of org.apache.druid.segment.column.ColumnType in project druid by druid-io.
the class IndexedTableColumnSelectorFactory method columnCapabilities.
@Nullable
static ColumnCapabilities columnCapabilities(final IndexedTable table, final String columnName) {
final ColumnType valueType = table.rowSignature().getColumnType(columnName).orElse(null);
if (valueType != null) {
final ColumnCapabilitiesImpl capabilities = new ColumnCapabilitiesImpl().setType(valueType);
if (valueType.is(ValueType.STRING)) {
// IndexedTables are not _really_ dictionary-encoded, but we fake it using the row number as the dict. code.
capabilities.setDictionaryEncoded(true);
}
capabilities.setDictionaryValuesSorted(false);
capabilities.setDictionaryValuesUnique(false);
capabilities.setHasMultipleValues(false);
return capabilities;
} else {
return null;
}
}
use of org.apache.druid.segment.column.ColumnType in project druid by druid-io.
the class IndexIO method validateRowValues.
private static void validateRowValues(RowPointer rp1, IndexableAdapter adapter1, RowPointer rp2, IndexableAdapter adapter2) {
if (rp1.getTimestamp() != rp2.getTimestamp()) {
throw new SegmentValidationException("Timestamp mismatch. Expected %d found %d", rp1.getTimestamp(), rp2.getTimestamp());
}
final List<Object> dims1 = rp1.getDimensionValuesForDebug();
final List<Object> dims2 = rp2.getDimensionValuesForDebug();
if (dims1.size() != dims2.size()) {
throw new SegmentValidationException("Dim lengths not equal %s vs %s", dims1, dims2);
}
final List<String> dim1Names = adapter1.getDimensionNames();
final List<String> dim2Names = adapter2.getDimensionNames();
int dimCount = dims1.size();
for (int i = 0; i < dimCount; ++i) {
final String dim1Name = dim1Names.get(i);
final String dim2Name = dim2Names.get(i);
ColumnCapabilities capabilities1 = adapter1.getCapabilities(dim1Name);
ColumnCapabilities capabilities2 = adapter2.getCapabilities(dim2Name);
ColumnType dim1Type = capabilities1.toColumnType();
ColumnType dim2Type = capabilities2.toColumnType();
if (!Objects.equals(dim1Type, dim2Type)) {
throw new SegmentValidationException("Dim [%s] types not equal. Expected %d found %d", dim1Name, dim1Type, dim2Type);
}
Object vals1 = dims1.get(i);
Object vals2 = dims2.get(i);
if (isNullRow(vals1) ^ isNullRow(vals2)) {
throw notEqualValidationException(dim1Name, vals1, vals2);
}
boolean vals1IsList = vals1 instanceof List;
boolean vals2IsList = vals2 instanceof List;
if (vals1IsList ^ vals2IsList) {
if (vals1IsList) {
if (((List) vals1).size() != 1 || !Objects.equals(((List) vals1).get(0), vals2)) {
throw notEqualValidationException(dim1Name, vals1, vals2);
}
} else {
if (((List) vals2).size() != 1 || !Objects.equals(((List) vals2).get(0), vals1)) {
throw notEqualValidationException(dim1Name, vals1, vals2);
}
}
} else {
if (!Objects.equals(vals1, vals2)) {
throw notEqualValidationException(dim1Name, vals1, vals2);
}
}
}
}
use of org.apache.druid.segment.column.ColumnType in project druid by druid-io.
the class GroupByQueryEngineV2Test method testCanPushDownLimitForComplexSelector.
@Test
public void testCanPushDownLimitForComplexSelector() {
ColumnCapabilitiesImpl capabilities = new ColumnCapabilitiesImpl().setType(new ColumnType(ValueType.COMPLEX, "foo", null)).setHasBitmapIndexes(false).setHasMultipleValues(false).setDictionaryEncoded(false).setDictionaryValuesSorted(false).setDictionaryValuesUnique(false);
EasyMock.expect(factory.getColumnCapabilities(DIM)).andReturn(capabilities).once();
EasyMock.replay(factory);
Assert.assertTrue(GroupByQueryEngineV2.canPushDownLimit(factory, DIM));
EasyMock.verify(factory);
}
use of org.apache.druid.segment.column.ColumnType in project druid by druid-io.
the class DruidQuery method computeDimensions.
/**
* Returns dimensions corresponding to {@code aggregate.getGroupSet()}, in the same order.
*
* @param partialQuery partial query
* @param plannerContext planner context
* @param rowSignature source row signature
* @param virtualColumnRegistry re-usable virtual column references
*
* @return dimensions
*
* @throws CannotBuildQueryException if dimensions cannot be computed
*/
private static List<DimensionExpression> computeDimensions(final PartialDruidQuery partialQuery, final PlannerContext plannerContext, final RowSignature rowSignature, final VirtualColumnRegistry virtualColumnRegistry) {
final Aggregate aggregate = Preconditions.checkNotNull(partialQuery.getAggregate());
final List<DimensionExpression> dimensions = new ArrayList<>();
final String outputNamePrefix = Calcites.findUnusedPrefixForDigits("d", rowSignature.getColumnNames());
int outputNameCounter = 0;
for (int i : aggregate.getGroupSet()) {
// Dimension might need to create virtual columns. Avoid giving it a name that would lead to colliding columns.
final RexNode rexNode = Expressions.fromFieldAccess(rowSignature, partialQuery.getSelectProject(), i);
final DruidExpression druidExpression = Expressions.toDruidExpression(plannerContext, rowSignature, rexNode);
if (druidExpression == null) {
throw new CannotBuildQueryException(aggregate, rexNode);
}
final RelDataType dataType = rexNode.getType();
final ColumnType outputType = Calcites.getColumnTypeForRelDataType(dataType);
if (Types.isNullOr(outputType, ValueType.COMPLEX)) {
// Can't group on unknown or COMPLEX types.
plannerContext.setPlanningError("SQL requires a group-by on a column of type %s that is unsupported.", outputType);
throw new CannotBuildQueryException(aggregate, rexNode);
}
final String dimOutputName = outputNamePrefix + outputNameCounter++;
if (!druidExpression.isSimpleExtraction()) {
final String virtualColumn = virtualColumnRegistry.getOrCreateVirtualColumnForExpression(druidExpression, dataType);
dimensions.add(DimensionExpression.ofVirtualColumn(virtualColumn, dimOutputName, druidExpression, outputType));
} else {
dimensions.add(DimensionExpression.ofSimpleColumn(dimOutputName, druidExpression, outputType));
}
}
return dimensions;
}
use of org.apache.druid.segment.column.ColumnType in project druid by druid-io.
the class DruidSchema method buildDruidTable.
@VisibleForTesting
DruidTable buildDruidTable(final String dataSource) {
ConcurrentSkipListMap<SegmentId, AvailableSegmentMetadata> segmentsMap = segmentMetadataInfo.get(dataSource);
final Map<String, ColumnType> columnTypes = new TreeMap<>();
if (segmentsMap != null) {
for (AvailableSegmentMetadata availableSegmentMetadata : segmentsMap.values()) {
final RowSignature rowSignature = availableSegmentMetadata.getRowSignature();
if (rowSignature != null) {
for (String column : rowSignature.getColumnNames()) {
// Newer column types should override older ones.
final ColumnType columnType = rowSignature.getColumnType(column).orElseThrow(() -> new ISE("Encountered null type for column[%s]", column));
columnTypes.putIfAbsent(column, columnType);
}
}
}
}
final RowSignature.Builder builder = RowSignature.builder();
columnTypes.forEach(builder::add);
final TableDataSource tableDataSource;
// to be a GlobalTableDataSource instead of a TableDataSource, it must appear on all servers (inferred by existing
// in the segment cache, which in this case belongs to the broker meaning only broadcast segments live here)
// to be joinable, it must be possibly joinable according to the factory. we only consider broadcast datasources
// at this time, and isGlobal is currently strongly coupled with joinable, so only make a global table datasource
// if also joinable
final GlobalTableDataSource maybeGlobal = new GlobalTableDataSource(dataSource);
final boolean isJoinable = joinableFactory.isDirectlyJoinable(maybeGlobal);
final boolean isBroadcast = segmentManager.getDataSourceNames().contains(dataSource);
if (isBroadcast && isJoinable) {
tableDataSource = maybeGlobal;
} else {
tableDataSource = new TableDataSource(dataSource);
}
return new DruidTable(tableDataSource, builder.build(), null, isJoinable, isBroadcast);
}
Aggregations