auphong2707/dl4se-code-review-dataset huggingface dataset:
Source:
private void addNewElement(int hashPosition, Block block, int position) { elementType.appendTo(block, position, elementBlock); if (elementBlock.getSizeInBytes() - initialElementBlockSizeInBytes > FOUR_MEGABYTES) { throw new PrestoException( EXCEEDED_FUNCTION_MEMORY_LIMIT, format("The input to %s is too large. More than %s of memory is needed to hold the intermediate hash set.\n", functionName, MAX_FUNCTION_MEMORY)); } blockPositionByHash.set(hashPosition, elementBlock.getPositionCount() - 1); // increase capacity, if necessary START if (++size >= maxFill) { END rehash(); } } "++x >= y" does't seem to be used in Presto code base. I would just put `size++` right after line 156.

Target:
private void addNewElement(int hashPosition, Block block, int position) { elementType.appendTo(block, position, elementBlock); if (elementBlock.getSizeInBytes() - initialElementBlockSizeInBytes > FOUR_MEGABYTES) { throw new PrestoException( EXCEEDED_FUNCTION_MEMORY_LIMIT, format("The input to %s is too large. More than %s of memory is needed to hold the intermediate hash set.\n", functionName, MAX_FUNCTION_MEMORY)); } blockPositionByHash.set(hashPosition, elementBlock.getPositionCount() - 1); // increase capacity, if necessary size++; if (size >= maxFill) { rehash(); } }
Source:
public PlanNodeCostEstimate visitSpatialJoin(SpatialJoinNode node, Void context) { return calculateJoinCost( node, node.getLeft(), node.getRight(), START Objects.equals(node.getDistributionType(), SpatialJoinNode.DistributionType.REPLICATED)); END } `node.getDistributionType() == SpatialJoinNode.DistributionType.REPLICATED`

Target:
public PlanNodeCostEstimate visitSpatialJoin(SpatialJoinNode node, Void context) { return calculateJoinCost( node, node.getLeft(), node.getRight(), node.getDistributionType() == SpatialJoinNode.DistributionType.REPLICATED); }
Source:
private static boolean isSerdeSupported(Properties schema) { String serdeName = getDeserializerClassName(schema); START if (!SUPPORTED_SERDES.contains(serdeName)) { END return false; } return true; } `return SUPPORTED_SERDES.contains(serdeName);`

Target:
private static boolean isSerdeSupported(Properties schema) { String serdeName = getDeserializerClassName(schema); return SUPPORTED_SERDES.contains(serdeName); }
Source:
private static String buildColumns(List<HiveColumnHandle> columns) { if (columns == null || columns.isEmpty()) { return EMPTY_STRING; } START return columns.stream().map(HiveColumnHandle::getName).collect(Collectors.joining(",")); END } ``` return columns.stream() .map(HiveColumnHandle::getName) .collect(Collectors.joining(",")); ```

Target:
private static String buildColumns(List<HiveColumnHandle> columns) { if (columns == null || columns.isEmpty()) { return ""; } return columns.stream() .map(HiveColumnHandle::getName) .collect(Collectors.joining(",")); }
Source:
START S3SelectRecordCursor( END Configuration configuration, Path path, RecordReader recordReader, long totalBytes, Properties splitSchema, List<HiveColumnHandle> columns, DateTimeZone hiveStorageTimeZone, TypeManager typeManager) { super(configuration, path, recordReader, totalBytes, updateSplitSchema(splitSchema, columns), columns, hiveStorageTimeZone, typeManager); } Make this public, since the constructor is logically part of the public API for the class. Access is controlled at the class level. If we wanted to later make the class public, we wouldn't need to change the access of the constructor.

Target:
public S3SelectRecordCursor( Configuration configuration, Path path, RecordReader recordReader, long totalBytes, Properties splitSchema, List<HiveColumnHandle> columns, DateTimeZone hiveStorageTimeZone, TypeManager typeManager) { super(configuration, path, recordReader, totalBytes, updateSplitSchema(splitSchema, columns), columns, hiveStorageTimeZone, typeManager); }
Source:
public void setup(String host, int port, String databaseName, String awsAccessKey, String awsSecretKey, String writableBucket) { START checkArgument(!isNullOrEmpty(host), "Expected non empty host"); END checkArgument(!isNullOrEmpty(databaseName), "Expected non empty databaseName"); checkArgument(!isNullOrEmpty(awsAccessKey), "Expected non empty awsAccessKey"); checkArgument(!isNullOrEmpty(awsSecretKey), "Expected non empty awsSecretKey"); checkArgument(!isNullOrEmpty(writableBucket), "Expected non empty writableBucket"); super.setup(host, port, databaseName, awsAccessKey, awsSecretKey, writableBucket, true); } Remove all these `checkArgument` since they are performed in the parent classes. It is expected that whoever is using an argument will validate it as appropriate. If it's just being passed through, we generally leave it alone (rather than duplicating all the validations).

Target:
public void setup(String host, int port, String databaseName, String awsAccessKey, String awsSecretKey, String writableBucket) { super.setup(host, port, databaseName, awsAccessKey, awsSecretKey, writableBucket, true); }
Source:
public static boolean isCompressionCodecSupported(InputFormat inputFormat, Path path) { if (inputFormat instanceof TextInputFormat) { try { return getCompressionCodec((TextInputFormat) inputFormat, path) .map(codec -> (codec instanceof GzipCodec) || (codec instanceof BZip2Codec)) .orElse(true); } catch (IllegalAccessException e) { START LOG.error(e, "Failed to find compressionCodec for inputFormat: %s", inputFormat.getClass().getName()); END return false; } } return false; } We should never get `IllegalAccessException` as that's a bug (we forgot to call `setAccessible`) or something is wrong with the JVM. Let's catch it in `getCompressionCodec()` and rethrow as `RuntimeException` or `PrestoException(GENERIC_INTERNAL_ERROR, ...)`

Target:
public static boolean isCompressionCodecSupported(InputFormat inputFormat, Path path) { if (inputFormat instanceof TextInputFormat) { return getCompressionCodec((TextInputFormat) inputFormat, path) .map(codec -> (codec instanceof GzipCodec) || (codec instanceof BZip2Codec)) .orElse(true); } return false; }
Source:
public ElasticsearchTableHandle( @JsonProperty("schemaName") String schemaName, @JsonProperty("tableName") String tableName) { START this.schemaTableName = new SchemaTableName(requireNonNull(schemaName.toLowerCase(ENGLISH), "schemaName is null"), requireNonNull(tableName.toLowerCase(ENGLISH), "tableName is null")); END } This is hard to read, please move out the non-null checks.

Target:
public ElasticsearchTableHandle( @JsonProperty("schemaName") String schemaName, @JsonProperty("tableName") String tableName) { requireNonNull(schemaName, "schemaName is null"); requireNonNull(tableName, "tableName is null"); this.schemaTableName = new SchemaTableName(schemaName.toLowerCase(ENGLISH), tableName.toLowerCase(ENGLISH)); }
Source:
protected String toSqlType(Type type) { if (VARBINARY.equals(type)) { return "bytea"; } START else if (JSON.equals(type)) { END return "jsonb"; } return super.toSqlType(type); } `else` is rendudant

Target:
protected String toSqlType(Type type) { if (VARBINARY.equals(type)) { return "bytea"; } if (JSON.equals(type)) { return "jsonb"; } return super.toSqlType(type); }
Source:
public Signature getCoercion(Type fromType, Type toType) { try { return globalFunctionNamespace.getCoercion(fromType, toType); } START catch (PrestoException e) { END if (!(e instanceof OperatorNotFoundException)) { throw e; } } throw new OperatorNotFoundException(OperatorType.CAST, ImmutableList.of(fromType.getTypeSignature()), toType.getTypeSignature()); } I believe this can be simplified to ```java catch (OperatorNotFoundException e) { throw new OperatorNotFoundException(...); }

Target:
public Signature getCoercion(Type fromType, Type toType) { return getCoercion(fromType.getTypeSignature(), toType.getTypeSignature()); }
Source:
private static boolean isOperator(Signature signature) { for (OperatorType operator : OperatorType.values()) { START if (signature.getName().equals(FunctionUtils.mangleOperatorName(operator))) { END return true; } } return false; } static import

Target:
private static boolean isOperator(Signature signature) { for (OperatorType operator : OperatorType.values()) { if (signature.getName().equals(mangleOperatorName(operator))) { return true; } } return false; }
Source:
private FunctionRegistry createFunctionRegistry(TypeRegistry typeManager) { BlockEncodingManager blockEncodingManager = new BlockEncodingManager(typeManager); FeaturesConfig featuresConfig = new FeaturesConfig(); FunctionManager functionManager = new FunctionManager(typeManager, blockEncodingManager, featuresConfig); START return new FunctionRegistry(typeManager, blockEncodingManager, new FeaturesConfig(), functionManager); END } We create multiple `FeaturesConfig`s in this method (another one is created on L299).

Target:
private FunctionRegistry createFunctionRegistry(TypeRegistry typeManager) { BlockEncodingManager blockEncodingManager = new BlockEncodingManager(typeManager); FeaturesConfig featuresConfig = new FeaturesConfig(); FunctionManager functionManager = new FunctionManager(typeManager, blockEncodingManager, featuresConfig); return new FunctionRegistry(typeManager, blockEncodingManager, featuresConfig, functionManager); }
Source:
private ExecutionFailureInfo rewriteTransportFailure(ExecutionFailureInfo executionFailureInfo) { if (executionFailureInfo.getRemoteHost() != null && failureDetector.getState(executionFailureInfo.getRemoteHost()) == GONE) { return new ExecutionFailureInfo( executionFailureInfo.getType(), executionFailureInfo.getMessage(), executionFailureInfo.getCause(), executionFailureInfo.getSuppressed(), executionFailureInfo.getStack(), executionFailureInfo.getErrorLocation(), REMOTE_HOST_GONE.toErrorCode(), executionFailureInfo.getRemoteHost()); } START else { END return executionFailureInfo; } } unnecessary else

Target:
private ExecutionFailureInfo rewriteTransportFailure(ExecutionFailureInfo executionFailureInfo) { if (executionFailureInfo.getRemoteHost() == null || failureDetector.getState(executionFailureInfo.getRemoteHost()) != GONE) { return executionFailureInfo; } return new ExecutionFailureInfo( executionFailureInfo.getType(), executionFailureInfo.getMessage(), executionFailureInfo.getCause(), executionFailureInfo.getSuppressed(), executionFailureInfo.getStack(), executionFailureInfo.getErrorLocation(), REMOTE_HOST_GONE.toErrorCode(), executionFailureInfo.getRemoteHost()); }
Source:
public static int computeTruncatedLength(Slice slice, int offset, int length, int maxCodePointCount, boolean isCharType) { int truncatedLength = length; if (isCharType) { // truncate the characters and then remove the trailing white spaces START truncatedLength = byteCountWithoutTrailingSpace(slice, offset, length, maxCodePointCount); END } else if (maxCodePointCount >= 0 && length > maxCodePointCount) { truncatedLength = byteCount(slice, offset, length, maxCodePointCount); } return truncatedLength; } You can just return directly from here... which would make the else redundant (and return directly from the next block).

Target:
public static int computeTruncatedLength(Slice slice, int offset, int length, int maxCodePointCount, boolean isCharType) { if (isCharType) { // truncate the characters and then remove the trailing white spaces return byteCountWithoutTrailingSpace(slice, offset, length, maxCodePointCount); } if (maxCodePointCount >= 0 && length > maxCodePointCount) { return byteCount(slice, offset, length, maxCodePointCount); } return length; }
Source:
public static void main(String[] args) throws Throwable { // assure the benchmarks are valid before running BenchmarkData data = new BenchmarkData(); data.setup(); new BenchmarkDictionaryBlockGetSizeInBytes().getSizeInBytes(data); Options options = new OptionsBuilder() .verbosity(VerboseMode.NORMAL) START .warmupMode(WarmupMode.INDI) END .include(".*" + BenchmarkDictionaryBlockGetSizeInBytes.class.getSimpleName() + ".*") .build(); new Runner(options).run(); } `WarmupMode.INDI` is already the default warmup mode, so no need to specify it.

Target:
public static void main(String[] args) throws Throwable { // assure the benchmarks are valid before running BenchmarkData data = new BenchmarkData(); data.setup(); new BenchmarkDictionaryBlockGetSizeInBytes().getSizeInBytes(data); Options options = new OptionsBuilder() .verbosity(VerboseMode.NORMAL) .include(".*" + BenchmarkDictionaryBlockGetSizeInBytes.class.getSimpleName() + ".*") .build(); new Runner(options).run(); }
Source:
public int hashCode() { START return Objects.hash(storageFormat, location, bucketProperty, skewed, serdeParameters); END } can you have the fields in the same order here as in toString and equals? ie `skewed` is first there

Target:
public int hashCode() { return Objects.hash(skewed, storageFormat, location, bucketProperty, serdeParameters); }
Source:
public PolymorphicScalarFunctionBuilder choice(Function<ChoiceBuilder, ChoiceBuilder> choiceSpecification) { ChoiceBuilder choiceBuilder = new ChoiceBuilder(clazz, signature); choiceSpecification.apply(choiceBuilder); PolymorphicScalarFunctionChoice choice = choiceBuilder.build(); START choices.add(choice); END return this; } `choices.add(choiceBuilder.build());`

Target:
public PolymorphicScalarFunctionBuilder choice(Function<ChoiceBuilder, ChoiceBuilder> choiceSpecification) { ChoiceBuilder choiceBuilder = new ChoiceBuilder(clazz, signature); choiceSpecification.apply(choiceBuilder); choices.add(choiceBuilder.build()); return this; }
Source:
public PolymorphicScalarFunctionChoice build() { if (argumentProperties.isEmpty()) { START argumentProperties = Collections.nCopies(signature.getArgumentTypes().size(), valueTypeArgumentProperty(RETURN_NULL_ON_NULL)); END } return new PolymorphicScalarFunctionChoice(nullableResult, argumentProperties, methodsGroups); } static import `nCopies`

Target:
public PolymorphicScalarFunctionChoice build() { return new PolymorphicScalarFunctionChoice(nullableResult, argumentProperties, methodsGroups.build()); }
Source:
public PolymorphicScalarFunctionChoice build() { START if (argumentProperties == null || argumentProperties.isEmpty()) { END argumentProperties = nCopies(signature.getArgumentTypes().size(), valueTypeArgumentProperty(RETURN_NULL_ON_NULL)); } return new PolymorphicScalarFunctionChoice(nullableResult, argumentProperties, methodsGroups.build()); } I recommend removing ` || argumentProperties.isEmpty()`. I believe that makes more sense from a semantic perspective. Logically, `argumentProperties` should not be populated if it is set (even if empty). Even though it wouldn't hurt here because repopulating it will still yield an empty list, it's confusing and arguably incorrect.

Target:
public PolymorphicScalarFunctionChoice build() { return new PolymorphicScalarFunctionChoice(nullableResult, argumentProperties, methodsGroups.build()); }
Source:
private void assertMultiPoint(String expectedWkt, String... pointWkts) { START assertFunction(format("ST_MultiPoint(array[%s])", ImmutableList.copyOf(pointWkts).stream() END .map(wkt -> wkt.equalsIgnoreCase("null") ? "null" : format("ST_GeometryFromText('%s')", wkt)) .collect(Collectors.joining(","))), GEOMETRY, expectedWkt); } The formatting is off. It's really hard to read and figure out what lines up with what.

Target:
private void assertMultiPoint(String expectedWkt, String... pointWkts) { assertFunction( format( "ST_MultiPoint(array[%s])", Arrays.stream(pointWkts) .map(wkt -> wkt == null ? "null" : format("ST_GeometryFromText('%s')", wkt)) .collect(Collectors.joining(","))), GEOMETRY, expectedWkt); }
Source:
public ConnectorBucketNodeMap getBucketNodeMap(ConnectorTransactionHandle transactionHandle, ConnectorSession session, ConnectorPartitioningHandle partitioningHandle) { Set<Node> nodes = nodeManager.getRequiredWorkerNodes(); START checkState(!nodes.isEmpty(), "No TPCH nodes available"); END // Split the data using split and skew by the number of nodes available. return createBucketNodeMap(toIntExact((long)nodes.size() * splitsPerNode)); } `nodeManager.getRequiredWorkerNodes();` never returns an empty set

Target:
public ConnectorBucketNodeMap getBucketNodeMap(ConnectorTransactionHandle transactionHandle, ConnectorSession session, ConnectorPartitioningHandle partitioningHandle) { Set<Node> nodes = nodeManager.getRequiredWorkerNodes(); // Split the data using split and skew by the number of nodes available. return createBucketNodeMap(toIntExact((long) nodes.size() * splitsPerNode)); }
Source:
public void onLifespanFinished(Iterable<Lifespan> newlyCompletedDriverGroups) { checkState(initialScheduled); START SettableFuture<?> newDriverGroupReady = this.newDriverGroupReady; END synchronized (this) { for (Lifespan newlyCompletedDriverGroup : newlyCompletedDriverGroups) { checkArgument(!newlyCompletedDriverGroup.isTaskWide()); recentlyCompletedDriverGroups.add(newlyCompletedDriverGroup); } } newDriverGroupReady.set(null); } I'm pretty sure that the setting of this local variable must happen within the synchronized block, and maybe at the old location the set was happening (not sure about the state machine), otherwise, you may observe an old stale value. Also, I'd merge this change into the commit that creates these classes.

Target:
public void onLifespanFinished(Iterable<Lifespan> newlyCompletedDriverGroups) { checkState(initialScheduled); SettableFuture<?> newDriverGroupReady; synchronized (this) { for (Lifespan newlyCompletedDriverGroup : newlyCompletedDriverGroups) { checkArgument(!newlyCompletedDriverGroup.isTaskWide()); recentlyCompletedDriverGroups.add(newlyCompletedDriverGroup); } newDriverGroupReady = this.newDriverGroupReady; } newDriverGroupReady.set(null); }
Source:
public ConnectorBucketNodeMap getBucketNodeMap(ConnectorTransactionHandle transactionHandle, ConnectorSession session, ConnectorPartitioningHandle partitioningHandle) { // create one bucket per node START return createBucketNodeMap( END nodeManager.getRequiredWorkerNodes().size(), value -> { throw new PrestoException(NOT_SUPPORTED, "Black hole connector does not supported distributed reads"); }); } consider making this change in the commit that introduced `ConnectorBucketNodeMap`

Target:
public ConnectorBucketNodeMap getBucketNodeMap(ConnectorTransactionHandle transactionHandle, ConnectorSession session, ConnectorPartitioningHandle partitioningHandle) { // create one bucket per node return createBucketNodeMap(nodeManager.getRequiredWorkerNodes().size()); }
Source:
START public QuantileDigestAggregationFunction(TypeSignature... typeSignatures) END { super(NAME, ImmutableList.of(comparableTypeParameter("V")), ImmutableList.of(), parseTypeSignature("qdigest(V)"), ImmutableList.copyOf(typeSignatures)); } make this private

Target:
private QuantileDigestAggregationFunction(TypeSignature... typeSignatures) { super( NAME, ImmutableList.of(comparableTypeParameter("V")), ImmutableList.of(), parseTypeSignature("qdigest(V)"), ImmutableList.copyOf(typeSignatures)); }
Source:
START protected Optional<PlanNodeStatsEstimate> visitNotExpression(NotExpression node, Void context) END { if (node.getValue() instanceof IsNullPredicate) { return process(new IsNotNullPredicate(((IsNullPredicate) node.getValue()).getValue())); } return process(node.getValue()).map(estimate -> differenceInStats(input, estimate)); } Why not get rid of `Optional` here either (as in `ComparisonCalculator`)?

Target:
protected PlanNodeStatsEstimate visitNotExpression(NotExpression node, Void context) { if (node.getValue() instanceof IsNullPredicate) { return process(new IsNotNullPredicate(((IsNullPredicate) node.getValue()).getValue())); } return differenceInStats(input, process(node.getValue())); }
Source:
public ThriftIndexHandle( @JsonProperty("schemaTableName") SchemaTableName schemaTableName, @JsonProperty("tupleDomain") TupleDomain<ColumnHandle> tupleDomain) { this.schemaTableName = requireNonNull(schemaTableName, "schemaTableName is null"); this.tupleDomain = requireNonNull(tupleDomain, "tupleDomain is null"); START this.session = Optional.empty(); END } Is this only used on workers?

Target:
public ThriftIndexHandle( @JsonProperty("schemaTableName") SchemaTableName schemaTableName, @JsonProperty("tupleDomain") TupleDomain<ColumnHandle> tupleDomain) { this(schemaTableName, tupleDomain, Optional.empty()); }
Source:
public MemoryEstimate visitIndexJoin(IndexJoinNode node, EstimationContext context) { PlanCostEstimate sourcesCost = context.sourcesCosts.stream() .reduce(PlanCostEstimate.zero(), CachingCostProvider::addSiblingsCost); return new MemoryEstimate( START sourcesCost.getMaxMemory(), END context.localMaxMemory + sourcesCost.getMaxMemoryWhenOutputting()); } can you explain this?

Target:
public MemoryEstimate visitIndexJoin(IndexJoinNode node, EstimationContext context) { PlanCostEstimate sourcesCost = context.sourcesCosts.stream() .reduce(PlanCostEstimate.zero(), CachingCostProvider::addSiblingsCost); return new MemoryEstimate( sourcesCost.getMaxMemoryWhenOutputting(), context.localMaxMemory + sourcesCost.getMaxMemoryWhenOutputting()); }
Source:
START List<Page> generateTestData() END { List<Type> typesArray = new ArrayList<>(); int currentPartitionIdentifier = 1; typesArray.add(BIGINT); typesArray.add(BIGINT); typesArray.add(BIGINT); typesArray.add(BIGINT); RowPagesBuilder pagesBuilder = buildPages(currentPartitionIdentifier, typesArray); return pagesBuilder.build(); } Private?

Target:
private List<Page> generateTestData() { List<Type> typesArray = new ArrayList<>(); int currentPartitionIdentifier = 1; typesArray.add(BIGINT); typesArray.add(BIGINT); typesArray.add(BIGINT); typesArray.add(BIGINT); RowPagesBuilder pagesBuilder = buildPages(currentPartitionIdentifier, typesArray); return pagesBuilder.build(); }
Source:
public boolean equals(Object o) { START new RuntimeException("partitioningHandle equals").printStackTrace(); END if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } HivePartitionHandle that = (HivePartitionHandle) o; return bucket == that.bucket; } I imagine this was leftover from debugging?

Target:
public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } HivePartitionHandle that = (HivePartitionHandle) o; return bucket == that.bucket; }
Source:
public void abort() { // rollback and close try (Connection connection = this.connection; PreparedStatement statement = this.statement) { connection.rollback(); } catch (SQLException e) { throw new PrestoException(JDBC_ERROR, e); } finally { try { START jdbcClient.rollbackCreateTable(handle); END } catch (Exception e) { log.warn(e, format("Failed to cleanup temporary table: %s", handle.getTemporaryTableName())); } } } why is this needed if whole transaction is rollbacked, then table should be dropped as well, am I right? Also `JdbcPageSink` has not created this table, it looks fishy that it drops this.

Target:
public void abort() { // rollback and close try (Connection connection = this.connection; PreparedStatement statement = this.statement) { connection.rollback(); } catch (SQLException e) { throw new PrestoException(JDBC_ERROR, e); } }
Source:
private static Connector createTestSessionConnector() { return new Connector() { @Override public ConnectorTransactionHandle beginTransaction(IsolationLevel isolationLevel, boolean readOnly) { return new ConnectorTransactionHandle() {}; } @Override public ConnectorMetadata getMetadata(ConnectorTransactionHandle transaction) { START return new TestingConnectorMetadata(new SystemTablesMetadata(new ConnectorId("test_session_connector"), END new StaticSystemTablesProvider(ImmutableSet.of()))); } @Override public ConnectorSplitManager getSplitManager() { throw new UnsupportedOperationException(); } }; } Why do we need to wrap it in a TestingConnectorMetadata (which seems do nothing but call the delegated connectorMetadata).

Target:
private static Connector createTestSessionConnector() { return new Connector() { @Override public ConnectorTransactionHandle beginTransaction(IsolationLevel isolationLevel, boolean readOnly) { return new ConnectorTransactionHandle() {}; } @Override public ConnectorMetadata getMetadata(ConnectorTransactionHandle transaction) { return new SystemTablesMetadata(new ConnectorId("test_session_connector"), new StaticSystemTablesProvider(ImmutableSet.of())); } @Override public ConnectorSplitManager getSplitManager() { throw new UnsupportedOperationException(); } }; }
Source:
private static Statement parseFormatted(SqlParser sqlParser, ParsingOptions parsingOptions, String sql, Node tree) { try { return sqlParser.createStatement(sql, parsingOptions); } catch (ParsingException e) { String error = format("failed to parse formatted SQL: %s\nerror: %s\ntree: %s", sql, e.getMessage(), tree); START throw new AssertionError(error, e); END } } I would inline error. Up to you.

Target:
private static Statement parseFormatted(SqlParser sqlParser, ParsingOptions parsingOptions, String sql, Node tree) { try { return sqlParser.createStatement(sql, parsingOptions); } catch (ParsingException e) { throw new AssertionError(format("failed to parse formatted SQL: %s\nerror: %s\ntree: %s", sql, e.getMessage(), tree), e); } }
Source:
public void createTable(ConnectorSession session, ConnectorTableMetadata tableMetadata, boolean ignoreExisting) { JdbcOutputTableHandle handle = jdbcClient.beginCreateTable(tableMetadata, ignoreExisting); finishCreateTable(session, handle, emptyList(), emptyList()); START } END If we fail to finish (rename) the table, we leave a temp table behind. Am i right?

Target:
public void createTable(ConnectorSession session, ConnectorTableMetadata tableMetadata, boolean ignoreExisting) { jdbcClient.createTable(tableMetadata); }
Source:
public void createTable(ConnectorSession session, ConnectorTableMetadata tableMetadata, boolean ignoreExisting) START { END JdbcOutputTableHandle handle = jdbcClient.beginCreateTable(tableMetadata); finishCreateTable(session, handle, emptyList(), emptyList()); } We probably had the JDBC connector before INSERT support, so creating an empty table would not have been useful. But I don't remember for sure. The shorter answer is that no one needed it.

Target:
public void createTable(ConnectorSession session, ConnectorTableMetadata tableMetadata, boolean ignoreExisting) { jdbcClient.createTable(tableMetadata); }
Source:
public void createTable(ConnectorTableMetadata tableMetadata) { try { createTable(tableMetadata, tableMetadata.getTable().getTableName()); } catch (SQLException e) { if (DUPLICATE_TABLE_SQLSTATE.equals(e.getSQLState())) { throw new PrestoException(ALREADY_EXISTS, e); } START else { END throw new PrestoException(JDBC_ERROR, e); } } } Nit: else is redundant

Target:
public void createTable(ConnectorTableMetadata tableMetadata) { try { createTable(tableMetadata, tableMetadata.getTable().getTableName()); } catch (SQLException e) { if (DUPLICATE_TABLE_SQLSTATE.equals(e.getSQLState())) { throw new PrestoException(ALREADY_EXISTS, e); } throw new PrestoException(JDBC_ERROR, e); } }
Source:
SymbolStatistics(String symbolName, SymbolStatsEstimate estimate) { START this.symbol = new Symbol(symbolName); END this.estimate = estimate; } `this(new Symbol(symbolName), estimate)`

Target:
SymbolStatistics(String symbolName, SymbolStatsEstimate estimate) { this(new Symbol(symbolName), estimate); }
Source:
public final void readFully(long position, byte[] buffer, int bufferOffset, int bufferLength) { readBytes += bufferLength; long readStart = System.nanoTime(); readInternal(position, buffer, bufferOffset, bufferLength); long currentReadTimeNanos = System.nanoTime() - readStart; readTimeNanos += currentReadTimeNanos; START stats.readDataBytesPerSecond(bufferLength, currentReadTimeNanos); END } That’s simpler, for sure. But there’s no benefit to using StopWatch and having a dependency on external code in this case when the alternative is trivial.

Target:
public final void readFully(long position, byte[] buffer, int bufferOffset, int bufferLength) { readBytes += bufferLength; long start = System.nanoTime(); readInternal(position, buffer, bufferOffset, bufferLength); long currentReadTimeNanos = System.nanoTime() - start; readTimeNanos += currentReadTimeNanos; stats.readDataBytesPerSecond(bufferLength, currentReadTimeNanos); }
Source:
private <T> T runWithHandle(ThrowingSupplier<T> supplier) throws TException { try { T t = supplier.get(); START responseHandle.success(); END return t; } catch (TException e) { responseHandle.failed(e); throw e; } } nit: move this after `catch`, so that `.success()` failure doesn't trigger `failed()` ``` T t; try { t = supplier.get(); } catch (TException e) { responseHandle.failed(e); throw e; } responseHandle.success(); return t; ```

Target:
private <T> T runWithHandle(ThrowingSupplier<T> supplier) throws TException { T t; try { t = supplier.get(); } catch (TException e) { responseHandle.failed(e); throw e; } responseHandle.success(); return t; }
Source:
public PlanNodeStatsEstimate( @JsonProperty("outputRowCount") double outputRowCount, @JsonProperty("symbolStatistics") Map<Symbol, SymbolStatsEstimate> symbolStatistics) { START checkArgument(isNaN(outputRowCount) || outputRowCount >= 0, "outputRowCount cannot be negative"); END this.outputRowCount = outputRowCount; this.symbolStatistics = HashTreePMap.from(requireNonNull(symbolStatistics, "symbolStatistics is null")); } nit: Just do `this(outputRowCount, HashTreePMap.from(requireNonNull(symbolStatistics, "symbolStatistics is null")))` to avoud copy pasting the argument checks

Target:
public PlanNodeStatsEstimate( @JsonProperty("outputRowCount") double outputRowCount, @JsonProperty("symbolStatistics") Map<Symbol, SymbolStatsEstimate> symbolStatistics) { this(outputRowCount, HashTreePMap.from(requireNonNull(symbolStatistics, "symbolStatistics is null"))); }
Source:
private PlanNodeCostEstimate calculateCumulativeCost(PlanNode node) { PlanNodeCostEstimate localCosts = costCalculator.calculateCost(node, statsProvider, noLookup(), session, types); PlanNodeCostEstimate sourcesCost = node.getSources().stream() .map(this::getCumulativeCost) .reduce(ZERO_COST, PlanNodeCostEstimate::add); START PlanNodeCostEstimate cumulativeCost = localCosts.add(sourcesCost); END return cumulativeCost; } Inline

Target:
private PlanNodeCostEstimate calculateCumulativeCost(PlanNode node) { PlanNodeCostEstimate sourcesCost = node.getSources().stream() .map(this::getCumulativeCost) .reduce(ZERO_COST, PlanNodeCostEstimate::add); return costCalculator.calculateCost(node, statsProvider, session, types).add(sourcesCost); }
Source:
public void doesNotFire() { RuleApplication ruleApplication = applyRule(); if (ruleApplication.wasRuleApplied()) { fail(String.format( "Expected %s to not fire for:\n%s", rule.getClass().getName(), START inTransaction(session -> textLogicalPlan(plan, ruleApplication.types, metadata.getFunctionRegistry(), new StatsAndCosts(ImmutableMap.of(), ImmutableMap.of()), session, 2)))); END } } `StatsAndCosts.empty()`

Target:
public void doesNotFire() { RuleApplication ruleApplication = applyRule(); if (ruleApplication.wasRuleApplied()) { fail(String.format( "Expected %s to not fire for:\n%s", rule.getClass().getName(), inTransaction(session -> textLogicalPlan(plan, ruleApplication.types, metadata.getFunctionRegistry(), StatsAndCosts.empty(), session, 2)))); } }
Source:
private PlanNodeCostEstimate calculateCumulativeCost(PlanNode node) { START PlanNodeCostEstimate localCosts = costCalculator.calculateCost(node, statsProvider, session, types); END PlanNodeCostEstimate sourcesCost = node.getSources().stream() .map(this::getCumulativeCost) .reduce(ZERO_COST, PlanNodeCostEstimate::add); PlanNodeCostEstimate cumulativeCost = costCalculator.calculateCost(node, statsProvider, session, types).add(sourcesCost); return cumulativeCost; } Remove this

Target:
private PlanNodeCostEstimate calculateCumulativeCost(PlanNode node) { PlanNodeCostEstimate sourcesCost = node.getSources().stream() .map(this::getCumulativeCost) .reduce(ZERO_COST, PlanNodeCostEstimate::add); return costCalculator.calculateCost(node, statsProvider, session, types).add(sourcesCost); }
Source:
private PlanNodeCostEstimate calculateCumulativeCost(PlanNode node) { PlanNodeCostEstimate sourcesCost = node.getSources().stream() .map(this::getCumulativeCost) .reduce(ZERO_COST, PlanNodeCostEstimate::add); START PlanNodeCostEstimate cumulativeCost = costCalculator.calculateCost(node, statsProvider, noLookup(), session, types).add(sourcesCost); END return cumulativeCost; } inline this

Target:
private PlanNodeCostEstimate calculateCumulativeCost(PlanNode node) { PlanNodeCostEstimate sourcesCost = node.getSources().stream() .map(this::getCumulativeCost) .reduce(ZERO_COST, PlanNodeCostEstimate::add); return costCalculator.calculateCost(node, statsProvider, session, types).add(sourcesCost); }
Source:
public static Slice stConvexHull(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { OGCGeometry geometry = deserialize(input); if (geometry.isEmpty()) { return input; } if (GeometryType.getForEsriGeometryType(geometry.geometryType()) == POINT) { return input; } START OGCGeometry convexHull = geometry.convexHull(); END return serialize(convexHull); } nit: inline this variable

Target:
public static Slice stConvexHull(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { OGCGeometry geometry = deserialize(input); if (geometry.isEmpty()) { return input; } if (GeometryType.getForEsriGeometryType(geometry.geometryType()) == POINT) { return input; } return serialize(geometry.convexHull()); }
Source:
public void testDefaultAcl() throws Exception { Configuration config = new Configuration(); try (PrestoS3FileSystem fs = new PrestoS3FileSystem()) { MockAmazonS3 s3 = new MockAmazonS3(); String expectedBucketName = "test-bucket"; fs.initialize(new URI("s3n://" + expectedBucketName + "/"), config); fs.setS3Client(s3); START FSDataOutputStream stream = fs.create(new Path("s3n://test-bucket/test")); END stream.close(); assertEquals(CannedAccessControlList.Private, s3.getAcl()); } } You can also do ``` try (FSDataOutputStream stream = fs.create(new Path("s3n://test-bucket/test"))) { assertEquals(CannedAccessControlList.Private, s3.getAcl()); } ```

Target:
public void testDefaultAcl() throws Exception { Configuration config = new Configuration(); try (PrestoS3FileSystem fs = new PrestoS3FileSystem()) { MockAmazonS3 s3 = new MockAmazonS3(); String expectedBucketName = "test-bucket"; fs.initialize(new URI("s3n://" + expectedBucketName + "/"), config); fs.setS3Client(s3); try (FSDataOutputStream stream = fs.create(new Path("s3n://test-bucket/test"))) { // initiate an upload by creating a stream & closing it immediately } assertEquals(CannedAccessControlList.Private, s3.getAcl()); } }
Source:
private static Iterable<Slice> getGeometrySlicesFromBlock(Block block) { requireNonNull(block, "block is null"); return () -> new Iterator<Slice>() { private final int blockPositionCount = block.getPositionCount(); private int iteratorPosition; @Override public boolean hasNext() { START return iteratorPosition != blockPositionCount; END } @Override public Slice next() { if (!hasNext()) { throw new NoSuchElementException("Slices have been consumed"); } return GEOMETRY.getSlice(block, iteratorPosition++); } }; } Why not call `block.getPositionCount()` here instead of having a `final` variable? Does it make any diff in perf?

Target:
private static Iterable<Slice> getGeometrySlicesFromBlock(Block block) { requireNonNull(block, "block is null"); return () -> new Iterator<Slice>() { private int iteratorPosition; @Override public boolean hasNext() { return iteratorPosition != block.getPositionCount(); } @Override public Slice next() { if (!hasNext()) { throw new NoSuchElementException("Slices have been consumed"); } return GEOMETRY.getSlice(block, iteratorPosition++); } }; }
Source:
private String randomTwoChoices() { // Randomly pick 2 different candidates and select the less loaded one int randomPosition = ThreadLocalRandom.current().nextInt(activeNodes.size()); int randomOffset = ThreadLocalRandom.current().nextInt(1, activeNodes.size()); String candidate1 = activeNodes.get(randomPosition); String candidate2 = activeNodes.get((randomPosition + randomOffset) % activeNodes.size()); START if (nodeBucketCounts.get(candidate2) < nodeBucketCounts.get(candidate1)) { END candidate1 = candidate2; } return candidate1; } I think this would be a bit easier to read as ```java return (nodeBucketCounts.get(candidate1) <= nodeBucketCounts.get(candidate2)) ? candidate1 : candidate2; ``` The assignment looks strange

Target:
private String randomTwoChoices() { // Purely random choices can overload unlucky node while selecting the least loaded one based on stale // local information can overload the previous idle node. Here we randomly pick 2 nodes and select the // less loaded one. This prevents those issues and renders good enough load balance. int randomPosition = ThreadLocalRandom.current().nextInt(activeNodes.size()); int randomOffset = ThreadLocalRandom.current().nextInt(1, activeNodes.size()); String candidate1 = activeNodes.get(randomPosition); String candidate2 = activeNodes.get((randomPosition + randomOffset) % activeNodes.size()); return (nodeBucketCounts.get(candidate1) <= nodeBucketCounts.get(candidate2)) ? candidate1 : candidate2; }
Source:
public int getBufferedBytes() { START return toIntExact((rowCount * otherColumnsBytesPerRow) + END dictionaryColumns.stream() .mapToLong(TestDictionaryColumn::getBufferedBytes) .sum()); } Consider making the method return long instead

Target:
public long getBufferedBytes() { return (long) rowCount * otherColumnsBytesPerRow + dictionaryColumns.stream() .mapToLong(TestDictionaryColumn::getBufferedBytes) .sum(); }
Source:
public List<? extends Node> getChildren() { return ImmutableList.<Node>builder() START .addAll(properties).build(); END } - what about the `table`? - move `.build()` to separate line

Target:
public List<? extends Node> getChildren() { return properties; }
Source:
YieldingIterator(WorkProcessor<T> processor) START { END this.processor = requireNonNull(processor, "processorParameter is null"); } `@Nullable` `private`

Target:
private YieldingIterator(WorkProcessor<T> processor) { this.processor = requireNonNull(processor, "processorParameter is null"); }
Source:
ProcessWorkProcessor(WorkProcessor.Process<T> process) { this.process = requireNonNull(process, "process is null"); START } END no need for Optional, it wouldn't make the code more readable. What about NEEDS_MORE_DATA as the initial state? (i don't insist)

Target:
private ProcessWorkProcessor(WorkProcessor.Process<T> process) { this.process = requireNonNull(process, "process is null"); }
Source:
START public void getSetBits(int batchSize, boolean[] vector) END throws IOException { for (int i = 0; i < batchSize; i++) { vector[i] = nextBit(); } } Tough call. I'd say if we don't need it now, then let's not add it. We can always throw it in later.

Target:
public int getSetBits(int batchSize, boolean[] vector) throws IOException { int count = 0; for (int i = 0; i < batchSize; i++) { vector[i] = nextBit(); count += vector[i] ? 1 : 0; } return count; }
Source:
private static RowGroupStatistics buildActualRowGroupStatistics(int rowGroupIndex, Map<StreamId, List<RowGroupIndex>> actualRowGroupStatistics) { return new RowGroupStatistics( BOTH, actualRowGroupStatistics.entrySet() .stream() START .collect(Collectors.toMap((entry) -> entry.getKey().getColumn(), (entry) -> entry.getValue().get(rowGroupIndex).getColumnStatistics()))); END } nit: Just write `entry -> ...`

Target:
private static RowGroupStatistics buildActualRowGroupStatistics(int rowGroupIndex, Map<StreamId, List<RowGroupIndex>> actualRowGroupStatistics) { return new RowGroupStatistics( BOTH, actualRowGroupStatistics.entrySet() .stream() .collect(Collectors.toMap(entry -> entry.getKey().getColumn(), entry -> entry.getValue().get(rowGroupIndex).getColumnStatistics()))); }
Source:
private boolean isSchemaAccessible(CatalogSchemaName schema) { START Set<String> schemas = ImmutableSet.of(schema.getSchemaName()); END schemas = accessControl.filterSchemas(session.getRequiredTransactionId(), session.getIdentity(), schema.getCatalogName(), schemas); return schemas.contains(schema.getSchemaName()) && metadata.schemaExists(session, schema); } inline

Target:
private boolean isSchemaAccessible(CatalogSchemaName schema) { return metadata.schemaExists(session, schema) && filterSchemas(schema.getCatalogName(), ImmutableSet.of(schema.getSchemaName())).contains(schema.getSchemaName()); }
Source:
START public void forEach(MultimapAggregationStateConsumer consumer) END { BlockBuilder keyBlockBuilder = keyBlockBuilders.get(getGroupId()); BlockBuilder valueBlockBuilder = valueBlockBuilders.get(getGroupId()); for (int i = 0; !isEmpty() && keyBlockBuilder != null && i < keyBlockBuilder.getPositionCount(); i++) { consumer.accept(keyBlockBuilder, valueBlockBuilder, i); } } I would just write: ```java BlockBuilder keyBlockBuilder = keyBlockBuilders.get(getGroupId()); BlockBuilder valueBlockBuilder = valueBlockBuilders.get(getGroupId()); if (keyBlockBuilder == null) { return; } for (int i = 0; i < keyBlockBuilder.getPositionCount(); i++) { consumer.accept(keyBlockBuilder, valueBlockBuilder, i); } ``` In general, for global checks such as `keyBlockBuilder != null`, do it outsize the loop instead of check it per loop. It makes logic clear.

Target:
public void forEach(MultimapAggregationStateConsumer consumer) { BlockBuilder keyBlockBuilder = keyBlockBuilders.get(getGroupId()); BlockBuilder valueBlockBuilder = valueBlockBuilders.get(getGroupId()); if (keyBlockBuilder == null) { return; } for (int i = 0; i < keyBlockBuilder.getPositionCount(); i++) { consumer.accept(keyBlockBuilder, valueBlockBuilder, i); } }
Source:
public void serialize(MultimapAggregationState state, BlockBuilder out) { if (state.isEmpty()) { out.appendNull(); } START else { END BlockBuilder entryBuilder = out.beginBlockEntry(); state.forEach((keyBlock, valueBlock, position) -> { BlockBuilder rowBlockBuilder = entryBuilder.beginBlockEntry(); valueType.appendTo(valueBlock, position, rowBlockBuilder); keyType.appendTo(keyBlock, position, rowBlockBuilder); entryBuilder.closeEntry(); }); out.closeEntry(); } } nit: you can `return` in the `if` block and get rid of this else.

Target:
public void serialize(MultimapAggregationState state, BlockBuilder out) { if (state.isEmpty()) { out.appendNull(); return; } BlockBuilder entryBuilder = out.beginBlockEntry(); state.forEach((keyBlock, valueBlock, position) -> { BlockBuilder rowBlockBuilder = entryBuilder.beginBlockEntry(); valueType.appendTo(valueBlock, position, rowBlockBuilder); keyType.appendTo(keyBlock, position, rowBlockBuilder); entryBuilder.closeEntry(); }); out.closeEntry(); }
Source:
public SingleMultimapAggregationState(Type keyType, Type valueType) { this.keyType = requireNonNull(keyType); this.valueType = requireNonNull(valueType); START keyBlockBuilder = this.keyType.createBlockBuilder(null, EXPECTED_ENTRIES, expectedValueSize(keyType, EXPECTED_ENTRY_SIZE)); END valueBlockBuilder = this.valueType.createBlockBuilder(null, EXPECTED_ENTRIES, expectedValueSize(valueType, EXPECTED_ENTRY_SIZE)); } nit: do `keyType.createBlockBuilder` instead of `this.keyType.xxxx`

Target:
public SingleMultimapAggregationState(Type keyType, Type valueType) { this.keyType = requireNonNull(keyType); this.valueType = requireNonNull(valueType); keyBlockBuilder = keyType.createBlockBuilder(null, EXPECTED_ENTRIES, expectedValueSize(keyType, EXPECTED_ENTRY_SIZE)); valueBlockBuilder = valueType.createBlockBuilder(null, EXPECTED_ENTRIES, expectedValueSize(valueType, EXPECTED_ENTRY_SIZE)); }
Source:
START public PlanNodeStatsEstimate calculateStats(PlanNode node, StatsProvider sourceStats, Lookup lookup, Session session, TypeProvider types) END { if (node instanceof RemoteSourceNode) { return calculateRemoteSourceStats((RemoteSourceNode) node, sourceStats, lookup, session, types); } return delegate.calculateStats(node, sourceStats, lookup, session, types); } move it to the top, just below the constructor

Target:
public PlanNodeStatsEstimate calculateStats(PlanNode node, StatsProvider sourceStats, Lookup lookup, Session session, TypeProvider types) { if (node instanceof RemoteSourceNode) { return calculateRemoteSourceStats((RemoteSourceNode) node, sourceStats); } return delegate.calculateStats(node, sourceStats, lookup, session, types); }
Source:
private PlanNodeStatsEstimate calculateRemoteSourceStats(RemoteSourceNode node, StatsProvider statsProvider) { PlanNodeStatsEstimate estimate = null; for (PlanFragment sourceFragment : sourceProvider.getSourceFragments(node)) { START PlanNodeStatsEstimate sourceStatsWithMappedSymbols = mapToOutputSymbols(statsProvider.getStats(sourceFragment.getRoot()), sourceFragment.getPartitioningScheme().getOutputLayout(), node.getOutputSymbols()); END if (estimate != null) { addStatsAndMaxDistinctValues(estimate, sourceStatsWithMappedSymbols); } else { estimate = sourceStatsWithMappedSymbols; } } verify(estimate != null, "estimate is null"); return estimate; } Maybe `FragmentedPlanSourceProvider::getSources` for `RemoteSourceNode` should return nodes with output symbols already mapped? That way you wouldn't need to map symbols here.

Target:
private PlanNodeStatsEstimate calculateRemoteSourceStats(RemoteSourceNode node, StatsProvider statsProvider) { PlanNodeStatsEstimate estimate = null; for (PlanFragment sourceFragment : sourceProvider.getSourceFragments(node)) { PlanNodeStatsEstimate sourceStatsWithMappedSymbols = mapToOutputSymbols(statsProvider.getStats(sourceFragment.getRoot()), sourceFragment.getPartitioningScheme().getOutputLayout(), node.getOutputSymbols()); if (estimate != null) { estimate = addStatsAndMaxDistinctValues(estimate, sourceStatsWithMappedSymbols); } else { estimate = sourceStatsWithMappedSymbols; } } verify(estimate != null, "estimate is null"); return estimate; }
Source:
public ConnectorTransactionHandle create() { long transactionId = metadata.nextTransactionId(); long commitId = metadata.getCurrentCommitId(); Transaction transaction = new Transaction(metadata, transactionId, commitId); RaptorTransactionHandle handle = new RaptorTransactionHandle(transactionId, commitId); transactions.put(handle, transaction); return handle; START } END Let me describe a potential data race here. Let's verify together whether it's a real issue. The race happens when some logics jump in after line 44 and before line 48, the time series is: thread2 called beginTransaction, get CurrentCommitId == 1 thread1 metadata.getCurrentCommitId(); get CurrentCommitId==1 thread2 execute, finish commit, update CurrentCommitId=2, exit fully CommitCleaner threadxx called oldestActiveCommitId, since transactions is empty, CurrentCommitId==2, it gets oldestActiveCommitId == 2 thread1 called transactions.put(handle, transaction); Then this enters a unsafe state, since oldestActiveCommitId is actually 1, but CommitCleaner get 2.

Target:
public synchronized ConnectorTransactionHandle create() { long transactionId = metadata.nextTransactionId(); long commitId = metadata.getCurrentCommitId(); Transaction transaction = new Transaction(metadata, transactionId, commitId); RaptorTransactionHandle handle = new RaptorTransactionHandle(transactionId, commitId); transactions.put(handle, transaction); return handle; }
Source:
private static void deleteChunks(ShardWriterDao dao, long commitId, long tableId, Set<Long> chunkIds) { int rows = dao.deleteChunks(commitId, chunkIds); verifyMetadata(rows == chunkIds.size(), "Wrong row count %s for delete of %s chunks", rows, chunkIds.size()); rows = dao.deleteIndexChunks(chunkIndexTable(tableId), chunkIds); START verifyMetadata(rows == chunkIds.size(), "Wrong row count %s for delete of %s index chunks", rows, chunkIds.size()); END } Here we delete all, instead of setting end_commit_id. The following 2 cases may be issues: 1 ChunkSupplier.java line 105, getBucketChunks. called by RaptorSplitManager.getSplits(), the only place for presto to get chunks. If it can be called twice in a transaction, not good. But if only called once, maybe fine. 2 DatabaseMetadataWriter.recover line 205 dao.rollbackDeletedIndexChunks(chunkIndexTable(tableId), commitId); filters end_commit_id. So the rollback of delete, only rollback chunks, but index are not, then index is less then chunks.

Target:
private static void deleteChunks(ShardWriterDao dao, long commitId, long tableId, Set<Long> chunkIds) { int rows = dao.deleteChunks(commitId, chunkIds); verifyMetadata(rows == chunkIds.size(), "Wrong row count %s for delete of %s chunks", rows, chunkIds.size()); rows = dao.deleteIndexChunks(chunkIndexTable(tableId), commitId, chunkIds); verifyMetadata(rows == chunkIds.size(), "Wrong row count %s for delete of %s index chunks", rows, chunkIds.size()); }