Skip to content

Commit

Permalink
Backport to branch(3) : Refactor ConcatenationVisitor to use ColumnVi…
Browse files Browse the repository at this point in the history
…sitor (#2269)

Co-authored-by: Vincent Guilpain <[email protected]>
  • Loading branch information
feeblefakie and Torch3333 authored Oct 1, 2024
1 parent 745df17 commit d3d6571
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 83 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.scalar.db.storage.cosmos;

import com.scalar.db.io.BigIntValue;
import com.scalar.db.io.BlobValue;
import com.scalar.db.io.BooleanValue;
import com.scalar.db.io.DoubleValue;
import com.scalar.db.io.FloatValue;
import com.scalar.db.io.IntValue;
import com.scalar.db.io.TextValue;
import com.scalar.db.io.ValueVisitor;
import com.scalar.db.io.BigIntColumn;
import com.scalar.db.io.BlobColumn;
import com.scalar.db.io.BooleanColumn;
import com.scalar.db.io.ColumnVisitor;
import com.scalar.db.io.DoubleColumn;
import com.scalar.db.io.FloatColumn;
import com.scalar.db.io.IntColumn;
import com.scalar.db.io.TextColumn;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
Expand All @@ -19,88 +19,94 @@
* @author Yuji Ito
*/
@NotThreadSafe
public class ConcatenationVisitor implements ValueVisitor {
private final List<String> values;
public class ConcatenationVisitor implements ColumnVisitor {
private final List<String> columns;

public ConcatenationVisitor() {
values = new ArrayList<>();
columns = new ArrayList<>();
}

public String build() {
// TODO What if the string or blob value includes `:`?
return String.join(":", values);
// TODO What if the string or blob column includes `:`?
return String.join(":", columns);
}

/**
* Sets the specified {@code BooleanValue} to the key string
* Sets the specified {@code BooleanColumn} to the key string
*
* @param value a {@code BooleanValue} to be set
* @param column a {@code BooleanColumn} to be set
*/
@Override
public void visit(BooleanValue value) {
values.add(String.valueOf(value.get()));
public void visit(BooleanColumn column) {
assert !column.hasNullValue();
columns.add(String.valueOf(column.getBooleanValue()));
}

/**
* Sets the specified {@code IntValue} to the key string
* Sets the specified {@code IntColumn} to the key string
*
* @param value a {@code IntValue} to be set
* @param column a {@code IntColumn} to be set
*/
@Override
public void visit(IntValue value) {
values.add(String.valueOf(value.get()));
public void visit(IntColumn column) {
assert !column.hasNullValue();
columns.add(String.valueOf(column.getIntValue()));
}

/**
* Sets the specified {@code BigIntValue} to the key string
* Sets the specified {@code BigIntColumn} to the key string
*
* @param value a {@code BigIntValue} to be set
* @param column a {@code BigIntColumn} to be set
*/
@Override
public void visit(BigIntValue value) {
values.add(String.valueOf(value.get()));
public void visit(BigIntColumn column) {
assert !column.hasNullValue();
columns.add(String.valueOf(column.getBigIntValue()));
}

/**
* Sets the specified {@code FloatValue} to the key string
* Sets the specified {@code FloatColumn} to the key string
*
* @param value a {@code FloatValue} to be set
* @param column a {@code FloatColumn} to be set
*/
@Override
public void visit(FloatValue value) {
values.add(String.valueOf(value.get()));
public void visit(FloatColumn column) {
assert !column.hasNullValue();
columns.add(String.valueOf(column.getFloatValue()));
}

/**
* Sets the specified {@code DoubleValue} to the key string
* Sets the specified {@code DoubleColumn} to the key string
*
* @param value a {@code DoubleValue} to be set
* @param column a {@code DoubleColumn} to be set
*/
@Override
public void visit(DoubleValue value) {
values.add(String.valueOf(value.get()));
public void visit(DoubleColumn column) {
assert !column.hasNullValue();
columns.add(String.valueOf(column.getDoubleValue()));
}

/**
* Sets the specified {@code TextValue} to the key string
* Sets the specified {@code TextColumn} to the key string
*
* @param value a {@code TextValue} to be set
* @param column a {@code TextColumn} to be set
*/
@Override
public void visit(TextValue value) {
value.get().ifPresent(values::add);
public void visit(TextColumn column) {
assert !column.hasNullValue();
column.getValue().ifPresent(columns::add);
}

/**
* Sets the specified {@code BlobValue} to the key string
* Sets the specified {@code BlobColumn} to the key string
*
* @param value a {@code BlobValue} to be set
* @param column a {@code BlobColumn} to be set
*/
@Override
public void visit(BlobValue value) {
public void visit(BlobColumn column) {
assert !column.hasNullValue();
// Use Base64 encoding
value
.get()
.ifPresent(b -> values.add(Base64.getUrlEncoder().withoutPadding().encodeToString(b)));
columns.add(
Base64.getUrlEncoder().withoutPadding().encodeToString(column.getBlobValueAsBytes()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.google.common.collect.Streams;
import com.scalar.db.api.Operation;
import com.scalar.db.api.TableMetadata;
import com.scalar.db.io.Column;
import com.scalar.db.io.Value;
import java.util.HashMap;
import java.util.Map;
Expand Down Expand Up @@ -47,8 +48,8 @@ public Operation getOperation() {

@Nonnull
public String getConcatenatedPartitionKey() {
Map<String, Value<?>> keyMap = new HashMap<>();
operation.getPartitionKey().get().forEach(v -> keyMap.put(v.getName(), v));
Map<String, Column<?>> keyMap = new HashMap<>();
operation.getPartitionKey().getColumns().forEach(c -> keyMap.put(c.getName(), c));

ConcatenationVisitor visitor = new ConcatenationVisitor();
metadata.getPartitionKeyNames().forEach(name -> keyMap.get(name).accept(visitor));
Expand All @@ -63,9 +64,11 @@ public PartitionKey getCosmosPartitionKey() {

@Nonnull
public String getId() {
Map<String, Value<?>> keyMap = new HashMap<>();
operation.getPartitionKey().get().forEach(v -> keyMap.put(v.getName(), v));
operation.getClusteringKey().ifPresent(k -> k.get().forEach(v -> keyMap.put(v.getName(), v)));
Map<String, Column<?>> keyMap = new HashMap<>();
operation.getPartitionKey().getColumns().forEach(c -> keyMap.put(c.getName(), c));
operation
.getClusteringKey()
.ifPresent(k -> k.getColumns().forEach(c -> keyMap.put(c.getName(), c)));

ConcatenationVisitor visitor = new ConcatenationVisitor();
Streams.concat(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,35 @@

import static org.assertj.core.api.Assertions.assertThat;

import com.scalar.db.io.BigIntColumn;
import com.scalar.db.io.BigIntValue;
import com.scalar.db.io.BlobValue;
import com.scalar.db.io.BooleanValue;
import com.scalar.db.io.DoubleValue;
import com.scalar.db.io.FloatValue;
import com.scalar.db.io.IntValue;
import com.scalar.db.io.TextValue;
import com.scalar.db.io.BlobColumn;
import com.scalar.db.io.BooleanColumn;
import com.scalar.db.io.DoubleColumn;
import com.scalar.db.io.FloatColumn;
import com.scalar.db.io.IntColumn;
import com.scalar.db.io.TextColumn;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class ConcatenationVisitorTest {
private static final boolean ANY_BOOLEAN = false;
private static final BooleanValue ANY_BOOLEAN_VALUE =
new BooleanValue("any_boolean", ANY_BOOLEAN);
private static final BooleanColumn ANY_BOOLEAN_COLUMN =
BooleanColumn.of("any_boolean", ANY_BOOLEAN);
private static final int ANY_INT = Integer.MIN_VALUE;
private static final IntValue ANY_INT_VALUE = new IntValue("any_int", ANY_INT);
private static final IntColumn ANY_INT_COLUMN = IntColumn.of("any_int", ANY_INT);
private static final long ANY_BIGINT = BigIntValue.MAX_VALUE;
private static final BigIntValue ANY_BIGINT_VALUE = new BigIntValue("any_bigint", ANY_BIGINT);
private static final BigIntColumn ANY_BIGINT_COLUMN = BigIntColumn.of("any_bigint", ANY_BIGINT);
private static final float ANY_FLOAT = Float.MIN_NORMAL;
private static final FloatValue ANY_FLOAT_VALUE = new FloatValue("any_float", ANY_FLOAT);
private static final FloatColumn ANY_FLOAT_COLUMN = FloatColumn.of("any_float", ANY_FLOAT);
private static final double ANY_DOUBLE = Double.MIN_NORMAL;
private static final DoubleValue ANY_DOUBLE_VALUE = new DoubleValue("any_double", ANY_DOUBLE);
private static final DoubleColumn ANY_DOUBLE_COLUMN = DoubleColumn.of("any_double", ANY_DOUBLE);
private static final String ANY_TEXT = "test";
private static final TextValue ANY_TEXT_VALUE = new TextValue("any_text", ANY_TEXT);
private static final TextColumn ANY_TEXT_COLUMN = TextColumn.of("any_text", ANY_TEXT);
private static final byte[] ANY_BLOB = "scalar".getBytes(StandardCharsets.UTF_8);
private static final BlobValue ANY_BLOB_VALUE = new BlobValue("any_blob", ANY_BLOB);
private static final BlobColumn ANY_BLOB_COLUMN = BlobColumn.of("any_blob", ANY_BLOB);
private ConcatenationVisitor visitor;

@BeforeEach
Expand All @@ -40,13 +41,13 @@ public void setUp() {
@Test
public void build_AllTypesGiven_ShouldBuildString() {
// Act
visitor.visit(ANY_BOOLEAN_VALUE);
visitor.visit(ANY_INT_VALUE);
visitor.visit(ANY_BIGINT_VALUE);
visitor.visit(ANY_FLOAT_VALUE);
visitor.visit(ANY_DOUBLE_VALUE);
visitor.visit(ANY_TEXT_VALUE);
visitor.visit(ANY_BLOB_VALUE);
visitor.visit(ANY_BOOLEAN_COLUMN);
visitor.visit(ANY_INT_COLUMN);
visitor.visit(ANY_BIGINT_COLUMN);
visitor.visit(ANY_FLOAT_COLUMN);
visitor.visit(ANY_DOUBLE_COLUMN);
visitor.visit(ANY_TEXT_COLUMN);
visitor.visit(ANY_BLOB_COLUMN);
String actual = visitor.build();

// Assert
Expand All @@ -63,63 +64,63 @@ public void build_AllTypesGiven_ShouldBuildString() {
}

@Test
public void visit_BooleanValueAcceptCalled_ShouldBuildBooleanAsString() {
public void visit_BooleanColumnAcceptCalled_ShouldBuildBooleanAsString() {
// Act
ANY_BOOLEAN_VALUE.accept(visitor);
ANY_BOOLEAN_COLUMN.accept(visitor);

// Assert
assertThat(visitor.build()).isEqualTo(String.valueOf(ANY_BOOLEAN));
}

@Test
public void visit_IntValueAcceptCalled_ShouldBuildIntAsString() {
public void visit_IntColumnAcceptCalled_ShouldBuildIntAsString() {
// Act
ANY_INT_VALUE.accept(visitor);
ANY_INT_COLUMN.accept(visitor);

// Assert
assertThat(visitor.build()).isEqualTo(String.valueOf(ANY_INT));
}

@Test
public void visit_BigIntValueAcceptCalled_ShouldBuildBigIntAsString() {
public void visit_BigIntColumnAcceptCalled_ShouldBuildBigIntAsString() {
// Act
ANY_BIGINT_VALUE.accept(visitor);
ANY_BIGINT_COLUMN.accept(visitor);

// Assert
assertThat(visitor.build()).isEqualTo(String.valueOf(ANY_BIGINT));
}

@Test
public void visit_FloatValueAcceptCalled_ShouldBuildFloatAsString() {
public void visit_FloatColumnAcceptCalled_ShouldBuildFloatAsString() {
// Act
ANY_FLOAT_VALUE.accept(visitor);
ANY_FLOAT_COLUMN.accept(visitor);

// Assert
assertThat(visitor.build()).isEqualTo(String.valueOf(ANY_FLOAT));
}

@Test
public void visit_DoubleValueAcceptCalled_ShouldBuildDoubleAsString() {
public void visit_DoubleColumnAcceptCalled_ShouldBuildDoubleAsString() {
// Act
ANY_DOUBLE_VALUE.accept(visitor);
ANY_DOUBLE_COLUMN.accept(visitor);

// Assert
assertThat(visitor.build()).isEqualTo(String.valueOf(ANY_DOUBLE));
}

@Test
public void visit_TextValueAcceptCalled_ShouldBuildText() {
public void visit_TextColumnAcceptCalled_ShouldBuildText() {
// Act
ANY_TEXT_VALUE.accept(visitor);
ANY_TEXT_COLUMN.accept(visitor);

// Assert
assertThat(visitor.build()).isEqualTo(ANY_TEXT);
}

@Test
public void visit_BlobValueAcceptCalled_ShouldBuildBlobAsString() {
public void visit_BlobColumnAcceptCalled_ShouldBuildBlobAsString() {
// Act
ANY_BLOB_VALUE.accept(visitor);
ANY_BLOB_COLUMN.accept(visitor);

// Assert
assertThat(visitor.build())
Expand Down

0 comments on commit d3d6571

Please sign in to comment.