Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,18 @@ void ensureLockConflictAreProperlyHandledForImplicitTransactions() {
.check();
}

@Test
void ensureLiteralsInValueAreCorrectlyCoerced() {
sql("CREATE TABLE test (id INT PRIMARY KEY, val REAL)");
sql("INSERT INTO test VALUES (1, 1), (2, NULL), (3, 3)");

assertQuery("SELECT * FROM test")
.returns(1, 1.0F)
.returns(2, null)
.returns(3, 3.0F)
.check();
}

private static Stream<Arguments> decimalLimits() {
return Stream.of(
arguments(SqlTypeName.BIGINT.getName(), Long.MAX_VALUE, Long.MIN_VALUE),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ public synchronized CompletableFuture<Void> startAsync(ComponentContext componen
tableFunctionRegistry,
clockService,
killCommandHandler,
new ExpressionFactoryImpl<>(
new ExpressionFactoryImpl(
Commons.typeFactory(), COMPILED_EXPRESSIONS_CACHE_SIZE, CACHE_FACTORY
),
EXECUTION_SERVICE_SHUTDOWN_TIMEOUT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public DynamicPartitionProvider(
/** {@inheritDoc} */
@Override
public List<PartitionWithConsistencyToken> getPartitions(ExecutionContext<RowT> ctx) {
ExpressionFactory<RowT> expressionFactory = ctx.expressionFactory();
ExpressionFactory expressionFactory = ctx.expressionFactory();

return PartitionPruningPredicate.prunePartitions(ctx, columns, table, expressionFactory, assignments, nodeName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public class ExecutionContext<RowT> implements DataContext {

private final RowHandler<RowT> handler;

private final ExpressionFactory<RowT> expressionFactory;
private final ExpressionFactory expressionFactory;

private final AtomicBoolean cancelFlag = new AtomicBoolean();

Expand Down Expand Up @@ -131,7 +131,7 @@ public class ExecutionContext<RowT> implements DataContext {
* @param topologyVersion Topology version the query was mapped on.
*/
public ExecutionContext(
ExpressionFactory<RowT> expressionFactory,
ExpressionFactory expressionFactory,
QueryTaskExecutor executor,
ExecutionId executionId,
InternalClusterNode localNode,
Expand Down Expand Up @@ -237,7 +237,7 @@ public RowHandler<RowT> rowHandler() {
/**
* Get expression factory.
*/
public ExpressionFactory<RowT> expressionFactory() {
public ExpressionFactory expressionFactory() {
return expressionFactory;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public class ExecutionServiceImpl<RowT> implements ExecutionService, LogicalTopo

private final KillCommandHandler killCommandHandler;

private final ExpressionFactory<RowT> expressionFactory;
private final ExpressionFactory expressionFactory;

/**
* Constructor.
Expand Down Expand Up @@ -215,7 +215,7 @@ public ExecutionServiceImpl(
ImplementorFactory<RowT> implementorFactory,
ClockService clockService,
KillCommandHandler killCommandHandler,
ExpressionFactory<RowT> expressionFactory,
ExpressionFactory expressionFactory,
long shutdownTimeout
) {
this.localNode = topSrvc.localMember();
Expand Down Expand Up @@ -270,7 +270,7 @@ public static <RowT> ExecutionServiceImpl<RowT> create(
TableFunctionRegistry tableFunctionRegistry,
ClockService clockService,
KillCommandHandler killCommandHandler,
ExpressionFactory<RowT> expressionFactory,
ExpressionFactory expressionFactory,
long shutdownTimeout
) {
return new ExecutionServiceImpl<>(
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.apache.calcite.rel.RelFieldCollation;
import org.apache.calcite.rel.RelFieldCollation.Direction;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.ignite.internal.sql.engine.exec.ExecutionContext;
import org.apache.ignite.internal.sql.engine.exec.RowHandler;
import org.jetbrains.annotations.Nullable;

Expand All @@ -34,54 +35,56 @@ class ComparatorImplementor {
* Implements comparator {@link SqlComparator} from given collation.
*
* @param collation The collation to implement comparator from.
* @param <RowT> The type of the execution row.
* @return An implementation of comparator.
* @see SqlComparator
*/
<RowT> SqlComparator<RowT> implement(RelCollation collation) {
SqlComparator implement(RelCollation collation) {
assert collation != null && !nullOrEmpty(collation.getFieldCollations()) : collation;

return (context, r1, r2) -> {
RowHandler<RowT> hnd = context.rowHandler();
List<RelFieldCollation> collations = collation.getFieldCollations();
return new SqlComparator() {
@Override
public <RowT> int compare(ExecutionContext<RowT> context, RowT r1, RowT r2) {
RowHandler<RowT> hnd = context.rowHandler();
List<RelFieldCollation> collations = collation.getFieldCollations();

int colsCountRow1 = hnd.columnCount(r1);
int colsCountRow2 = hnd.columnCount(r2);
int colsCountRow1 = hnd.columnCount(r1);
int colsCountRow2 = hnd.columnCount(r2);

// The index range condition can contain the prefix of the index columns (not all index columns).
int maxCols = Math.min(Math.max(colsCountRow1, colsCountRow2), collations.size());
// The index range condition can contain the prefix of the index columns (not all index columns).
int maxCols = Math.min(Math.max(colsCountRow1, colsCountRow2), collations.size());

for (int i = 0; i < maxCols; i++) {
RelFieldCollation field = collations.get(i);
boolean ascending = field.direction == Direction.ASCENDING;
for (int i = 0; i < maxCols; i++) {
RelFieldCollation field = collations.get(i);
boolean ascending = field.direction == Direction.ASCENDING;

if (i == colsCountRow1) {
// There is no more values in first row.
return ascending ? -1 : 1;
}
if (i == colsCountRow1) {
// There is no more values in first row.
return ascending ? -1 : 1;
}

if (i == colsCountRow2) {
// There is no more values in second row.
return ascending ? 1 : -1;
}
if (i == colsCountRow2) {
// There is no more values in second row.
return ascending ? 1 : -1;
}

int fieldIdx = field.getFieldIndex();
int fieldIdx = field.getFieldIndex();

Object c1 = hnd.get(fieldIdx, r1);
Object c2 = hnd.get(fieldIdx, r2);
Object c1 = hnd.get(fieldIdx, r1);
Object c2 = hnd.get(fieldIdx, r2);

int nullComparison = field.nullDirection.nullComparison;
int nullComparison = field.nullDirection.nullComparison;

int res = ascending
? compare(c1, c2, nullComparison)
: compare(c2, c1, -nullComparison);
int res = ascending
? ComparatorImplementor.compare(c1, c2, nullComparison)
: ComparatorImplementor.compare(c2, c1, -nullComparison);

if (res != 0) {
return res;
if (res != 0) {
return res;
}
}
}

return 0;
return 0;
}
};
}

Expand All @@ -97,11 +100,10 @@ <RowT> SqlComparator<RowT> implement(RelCollation collation) {
* @param left The collation of the left side of the join.
* @param right The collation of the right side of the join.
* @param equalNulls Bit set of the fields in provided collations which must threat NULLs as equal.
* @param <RowT> The type of the execution row.
* @return An implementation of comparator.
* @see SqlComparator
*/
<RowT> SqlComparator<RowT> implement(List<RelFieldCollation> left, List<RelFieldCollation> right, ImmutableBitSet equalNulls) {
SqlComparator implement(List<RelFieldCollation> left, List<RelFieldCollation> right, ImmutableBitSet equalNulls) {
if (nullOrEmpty(left) || nullOrEmpty(right) || left.size() != right.size()) {
throw new IllegalArgumentException("Both inputs should be non-empty and have the same size: left="
+ (left != null ? left.size() : "null") + ", right=" + (right != null ? right.size() : "null"));
Expand All @@ -118,39 +120,42 @@ <RowT> SqlComparator<RowT> implement(List<RelFieldCollation> left, List<RelField
}
}

return (context, r1, r2) -> {
boolean hasNulls = false;
RowHandler<RowT> hnd = context.rowHandler();
return new SqlComparator() {
@Override
public <RowT> int compare(ExecutionContext<RowT> context, RowT r1, RowT r2) {
boolean hasNulls = false;
RowHandler<RowT> hnd = context.rowHandler();

for (int i = 0; i < left.size(); i++) {
RelFieldCollation leftField = left.get(i);
RelFieldCollation rightField = right.get(i);
for (int i = 0; i < left.size(); i++) {
RelFieldCollation leftField = left.get(i);
RelFieldCollation rightField = right.get(i);

int leftIdx = leftField.getFieldIndex();
int rightIdx = rightField.getFieldIndex();
int leftIdx = leftField.getFieldIndex();
int rightIdx = rightField.getFieldIndex();

Object c1 = hnd.get(leftIdx, r1);
Object c2 = hnd.get(rightIdx, r2);
Object c1 = hnd.get(leftIdx, r1);
Object c2 = hnd.get(rightIdx, r2);

if (!equalNulls.get(leftIdx) && c1 == null && c2 == null) {
hasNulls = true;
continue;
}
if (!equalNulls.get(leftIdx) && c1 == null && c2 == null) {
hasNulls = true;
continue;
}

int nullComparison = leftField.nullDirection.nullComparison;
int nullComparison = leftField.nullDirection.nullComparison;

int res = leftField.direction == RelFieldCollation.Direction.ASCENDING
? compare(c1, c2, nullComparison)
: compare(c2, c1, -nullComparison);
int res = leftField.direction == RelFieldCollation.Direction.ASCENDING
? ComparatorImplementor.compare(c1, c2, nullComparison)
: ComparatorImplementor.compare(c2, c1, -nullComparison);

if (res != 0) {
return res;
if (res != 0) {
return res;
}
}
}

// If compared rows contain NULLs, they shouldn't be treated as equals, since NULL <> NULL in SQL.
// Expect for cases with IS NOT DISTINCT
return hasNulls ? 1 : 0;
// If compared rows contain NULLs, they shouldn't be treated as equals, since NULL <> NULL in SQL.
// Expect for cases with IS NOT DISTINCT
return hasNulls ? 1 : 0;
}
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.apache.calcite.rel.RelFieldCollation;
import org.apache.calcite.rel.core.AggregateCall;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.ignite.internal.sql.engine.exec.exp.agg.AccumulatorsFactory;
Expand All @@ -33,8 +32,8 @@
/**
* Expression factory.
*/
public interface ExpressionFactory<RowT> {
AccumulatorsFactory<RowT> accumulatorsFactory(
public interface ExpressionFactory {
<RowT> AccumulatorsFactory<RowT> accumulatorsFactory(
AggregateType type,
List<AggregateCall> calls,
RelDataType rowType
Expand All @@ -46,7 +45,7 @@ AccumulatorsFactory<RowT> accumulatorsFactory(
* @param collations Collations.
* @return Row comparator.
*/
SqlComparator<RowT> comparator(RelCollation collations);
SqlComparator comparator(RelCollation collations);

/**
* Creates a comparator for different rows by given field collations. Mainly used for merge join rows comparison. Note: Both list has to
Expand All @@ -58,7 +57,7 @@ AccumulatorsFactory<RowT> accumulatorsFactory(
* @param equalNulls Bitset with null comparison strategy, use in case of NOT DISTINCT FROM syntax.
* @return Rows comparator.
*/
SqlComparator<RowT> comparator(List<RelFieldCollation> left, List<RelFieldCollation> right, ImmutableBitSet equalNulls);
SqlComparator comparator(List<RelFieldCollation> left, List<RelFieldCollation> right, ImmutableBitSet equalNulls);

/**
* Creates a Filter predicate.
Expand All @@ -67,7 +66,7 @@ AccumulatorsFactory<RowT> accumulatorsFactory(
* @param rowType Input row type.
* @return Filter predicate.
*/
SqlPredicate<RowT> predicate(RexNode filter, RelDataType rowType);
SqlPredicate predicate(RexNode filter, RelDataType rowType);

/**
* Creates a Filter predicate.
Expand All @@ -77,7 +76,7 @@ AccumulatorsFactory<RowT> accumulatorsFactory(
* @param firstRowSize Size of the first (left) row. Used to adjust index and route request to a proper row.
* @return Filter predicate.
*/
SqlJoinPredicate<RowT> joinPredicate(RexNode filter, RelDataType rowType, int firstRowSize);
SqlJoinPredicate joinPredicate(RexNode filter, RelDataType rowType, int firstRowSize);

/**
* Creates a Project function. Resulting function returns a row with different fields, fields order, fields types, etc.
Expand All @@ -86,7 +85,7 @@ AccumulatorsFactory<RowT> accumulatorsFactory(
* @param inputRowType Input row type.
* @return Project function.
*/
SqlProjection<RowT> project(List<RexNode> projects, RelDataType inputRowType);
SqlProjection project(List<RexNode> projects, RelDataType inputRowType);

/**
* Creates a Project function. Resulting function returns a row with different fields, fields order, fields types, etc.
Expand All @@ -96,24 +95,15 @@ AccumulatorsFactory<RowT> accumulatorsFactory(
* @param firstRowSize Size of the first (left) row. Used to adjust index and route request to a proper row.
* @return Project function.
*/
SqlJoinProjection<RowT> joinProject(List<RexNode> projects, RelDataType rowType, int firstRowSize);

/**
* Creates a Values relational node rows source.
*
* @param values Values.
* @param rowType Output row type.
* @return Values relational node rows source.
*/
SqlScalar<RowT, List<RowT>> values(List<List<RexLiteral>> values, RelDataType rowType);
SqlJoinProjection joinProject(List<RexNode> projects, RelDataType rowType, int firstRowSize);

/**
* Creates row from RexNodes.
*
* @param values Values.
* @return Row.
*/
SqlRowProvider<RowT> rowSource(List<RexNode> values);
SqlRowProvider rowSource(List<RexNode> values);

/**
* Creates iterable search bounds tuples (lower row/upper row) by search bounds expressions.
Expand All @@ -122,14 +112,14 @@ AccumulatorsFactory<RowT> accumulatorsFactory(
* @param rowType Row type.
* @param comparator Comparator to return bounds in particular order.
*/
SqlScalar<RowT, RangeIterable<RowT>> ranges(
SqlRangeConditionsProvider ranges(
List<SearchBounds> searchBounds,
RelDataType rowType,
@Nullable SqlComparator<RowT> comparator
@Nullable SqlComparator comparator
);

/**
* Executes expression.
*/
<T> SqlScalar<RowT, T> scalar(RexNode node);
<T> SqlScalar<T> scalar(RexNode node);
}
Loading