
io.trino.testing.MaterializedResult Maven / Gradle / Ivy
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.trino.testing;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import io.airlift.slice.Slices;
import io.trino.Session;
import io.trino.client.StatementStats;
import io.trino.client.Warning;
import io.trino.spi.Page;
import io.trino.spi.PageBuilder;
import io.trino.spi.block.ArrayBlockBuilder;
import io.trino.spi.block.Block;
import io.trino.spi.block.BlockBuilder;
import io.trino.spi.block.MapBlockBuilder;
import io.trino.spi.block.RowBlockBuilder;
import io.trino.spi.connector.ConnectorPageSource;
import io.trino.spi.connector.ConnectorSession;
import io.trino.spi.type.ArrayType;
import io.trino.spi.type.CharType;
import io.trino.spi.type.LongTimestamp;
import io.trino.spi.type.MapType;
import io.trino.spi.type.RowType;
import io.trino.spi.type.SqlDate;
import io.trino.spi.type.SqlDecimal;
import io.trino.spi.type.SqlTime;
import io.trino.spi.type.SqlTimeWithTimeZone;
import io.trino.spi.type.SqlTimestamp;
import io.trino.spi.type.SqlTimestampWithTimeZone;
import io.trino.spi.type.TimeType;
import io.trino.spi.type.TimeWithTimeZoneType;
import io.trino.spi.type.TimeZoneKey;
import io.trino.spi.type.TimestampType;
import io.trino.spi.type.Type;
import io.trino.spi.type.VarcharType;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.OffsetTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static io.trino.spi.type.BigintType.BIGINT;
import static io.trino.spi.type.BooleanType.BOOLEAN;
import static io.trino.spi.type.DateTimeEncoding.packDateTimeWithZone;
import static io.trino.spi.type.DateTimeEncoding.packTimeWithTimeZone;
import static io.trino.spi.type.DateType.DATE;
import static io.trino.spi.type.DoubleType.DOUBLE;
import static io.trino.spi.type.IntegerType.INTEGER;
import static io.trino.spi.type.RealType.REAL;
import static io.trino.spi.type.SmallintType.SMALLINT;
import static io.trino.spi.type.TimestampWithTimeZoneType.TIMESTAMP_TZ_MILLIS;
import static io.trino.spi.type.Timestamps.PICOSECONDS_PER_NANOSECOND;
import static io.trino.spi.type.Timestamps.roundDiv;
import static io.trino.spi.type.TinyintType.TINYINT;
import static io.trino.spi.type.VarbinaryType.VARBINARY;
import static io.trino.type.JsonType.JSON;
import static java.lang.Float.floatToRawIntBits;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
public class MaterializedResult
implements Iterable
{
public static final int DEFAULT_PRECISION = 5;
private final List rows;
private final List types;
private final List columnNames;
private final Map setSessionProperties;
private final Set resetSessionProperties;
private final Optional updateType;
private final OptionalLong updateCount;
private final List warnings;
private final Optional statementStats;
public MaterializedResult(List rows, List extends Type> types)
{
this(rows, types, Optional.empty());
}
public MaterializedResult(List rows, List extends Type> types, Optional> columnNames)
{
this(rows, types, columnNames.orElse(ImmutableList.of()), ImmutableMap.of(), ImmutableSet.of(), Optional.empty(), OptionalLong.empty(), ImmutableList.of(), Optional.empty());
}
public MaterializedResult(
List rows,
List extends Type> types,
List columnNames,
Map setSessionProperties,
Set resetSessionProperties,
Optional updateType,
OptionalLong updateCount,
List warnings,
Optional statementStats)
{
this.rows = ImmutableList.copyOf(requireNonNull(rows, "rows is null"));
this.types = ImmutableList.copyOf(requireNonNull(types, "types is null"));
this.columnNames = ImmutableList.copyOf(requireNonNull(columnNames, "columnNames is null"));
this.setSessionProperties = ImmutableMap.copyOf(requireNonNull(setSessionProperties, "setSessionProperties is null"));
this.resetSessionProperties = ImmutableSet.copyOf(requireNonNull(resetSessionProperties, "resetSessionProperties is null"));
this.updateType = requireNonNull(updateType, "updateType is null");
this.updateCount = requireNonNull(updateCount, "updateCount is null");
this.warnings = requireNonNull(warnings, "warnings is null");
this.statementStats = requireNonNull(statementStats, "statementStats is null");
}
public int getRowCount()
{
return rows.size();
}
@Override
public Iterator iterator()
{
return rows.iterator();
}
public List getMaterializedRows()
{
return rows;
}
public List getTypes()
{
return types;
}
public List getColumnNames()
{
checkState(!columnNames.isEmpty(), "Column names are unknown");
return columnNames;
}
public Map getSetSessionProperties()
{
return setSessionProperties;
}
public Set getResetSessionProperties()
{
return resetSessionProperties;
}
public Optional getUpdateType()
{
return updateType;
}
public OptionalLong getUpdateCount()
{
return updateCount;
}
public List getWarnings()
{
return warnings;
}
public Optional getStatementStats()
{
return statementStats;
}
@Override
public boolean equals(Object obj)
{
if (obj == this) {
return true;
}
if ((obj == null) || (getClass() != obj.getClass())) {
return false;
}
MaterializedResult o = (MaterializedResult) obj;
return Objects.equals(types, o.types) &&
Objects.equals(rows, o.rows) &&
Objects.equals(setSessionProperties, o.setSessionProperties) &&
Objects.equals(resetSessionProperties, o.resetSessionProperties) &&
Objects.equals(updateType, o.updateType) &&
Objects.equals(updateCount, o.updateCount);
}
@Override
public int hashCode()
{
return Objects.hash(rows, types, setSessionProperties, resetSessionProperties, updateType, updateCount);
}
@Override
public String toString()
{
return toStringHelper(this)
.add("rows", rows)
.add("types", types)
.add("setSessionProperties", setSessionProperties)
.add("resetSessionProperties", resetSessionProperties)
.add("updateType", updateType.orElse(null))
.add("updateCount", updateCount.isPresent() ? updateCount.getAsLong() : null)
.omitNullValues()
.toString();
}
public MaterializedResult exceptColumns(String... columnNamesToExclude)
{
validateIfColumnsPresent(columnNamesToExclude);
checkArgument(columnNamesToExclude.length > 0, "At least one column must be excluded");
checkArgument(columnNamesToExclude.length < getColumnNames().size(), "All columns cannot be excluded");
return projected(((Predicate) Set.of(columnNamesToExclude)::contains).negate());
}
public MaterializedResult project(String... columnNamesToInclude)
{
validateIfColumnsPresent(columnNamesToInclude);
checkArgument(columnNamesToInclude.length > 0, "At least one column must be projected");
return projected(Set.of(columnNamesToInclude)::contains);
}
private void validateIfColumnsPresent(String... columns)
{
Set columnNames = ImmutableSet.copyOf(getColumnNames());
for (String column : columns) {
checkArgument(columnNames.contains(column), "[%s] column is not present in %s".formatted(column, columnNames));
}
}
private MaterializedResult projected(Predicate columnFilter)
{
List columnNames = getColumnNames();
Map columnsIndexToNameMap = new HashMap<>();
for (int i = 0; i < columnNames.size(); i++) {
String columnName = columnNames.get(i);
if (columnFilter.test(columnName)) {
columnsIndexToNameMap.put(i, columnName);
}
}
return new MaterializedResult(
getMaterializedRows().stream()
.map(row -> new MaterializedRow(
row.getPrecision(),
columnsIndexToNameMap.keySet().stream()
.map(row::getField)
.collect(toList()))) // values are nullable
.collect(toImmutableList()),
columnsIndexToNameMap.keySet().stream()
.map(getTypes()::get)
.collect(toImmutableList()));
}
public Stream
© 2015 - 2025 Weber Informatics LLC | Privacy Policy