Skip to content

Commit b9cbd6b

Browse files
authored
Merge branch 'master' into feat/data-loader/export-trn
2 parents 2138113 + 88914f1 commit b9cbd6b

File tree

10 files changed

+2321
-291
lines changed

10 files changed

+2321
-291
lines changed

core/src/main/java/com/scalar/db/api/ConditionBuilder.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,23 @@ public static ConditionalExpression buildConditionalExpression(
135135
return new ConditionalExpression(column, operator);
136136
}
137137

138+
/**
139+
* Builds a like expression with the specified column, operator, and escape character.
140+
*
141+
* <p>This method is primarily for internal use. Breaking changes can and will be introduced to
142+
* this method. Users should not depend on it.
143+
*
144+
* @param column a target text column used to compare
145+
* @param operator an operator used to compare the target column. The operator must be either LIKE
146+
* or NOT_LIKE.
147+
* @param escape an escape character for the like operator
148+
* @return a conditional expression
149+
*/
150+
public static ConditionalExpression buildLikeExpression(
151+
TextColumn column, Operator operator, String escape) {
152+
return new LikeExpression(column, operator, escape);
153+
}
154+
138155
/**
139156
* Returns a builder object for a condition expression for PutIf/DeleteIf
140157
*
@@ -352,6 +369,7 @@ public ConditionalExpression isNotEqualToBlob(byte[] value) {
352369
public ConditionalExpression isNotEqualToBlob(ByteBuffer value) {
353370
return new ConditionalExpression(columnName, value, Operator.NE);
354371
}
372+
355373
/**
356374
* Creates a 'not equal' conditional expression for a DATE value.
357375
*
@@ -391,6 +409,7 @@ public ConditionalExpression isNotEqualToTimestamp(LocalDateTime value) {
391409
public ConditionalExpression isNotEqualToTimestampTZ(Instant value) {
392410
return new ConditionalExpression(TimestampTZColumn.of(columnName, value), Operator.NE);
393411
}
412+
394413
/**
395414
* Creates a 'greater than' conditional expression for a BOOLEAN value.
396415
*
@@ -590,6 +609,7 @@ public ConditionalExpression isGreaterThanOrEqualToBlob(byte[] value) {
590609
public ConditionalExpression isGreaterThanOrEqualToBlob(ByteBuffer value) {
591610
return new ConditionalExpression(columnName, value, Operator.GTE);
592611
}
612+
593613
/**
594614
* Creates a 'greater than or equal' conditional expression for a DATE value.
595615
*
@@ -709,6 +729,7 @@ public ConditionalExpression isLessThanBlob(byte[] value) {
709729
public ConditionalExpression isLessThanBlob(ByteBuffer value) {
710730
return new ConditionalExpression(columnName, value, Operator.LT);
711731
}
732+
712733
/**
713734
* Creates a 'less than' conditional expression for a DATE value.
714735
*
@@ -748,6 +769,7 @@ public ConditionalExpression isLessThanTimestamp(LocalDateTime value) {
748769
public ConditionalExpression isLessThanTimestampTZ(Instant value) {
749770
return new ConditionalExpression(TimestampTZColumn.of(columnName, value), Operator.LT);
750771
}
772+
751773
/**
752774
* Creates a 'less than or equal' conditional expression for a BOOLEAN value.
753775
*
@@ -1029,6 +1051,7 @@ public ConditionalExpression isNotNullText() {
10291051
public ConditionalExpression isNotNullBlob() {
10301052
return new ConditionalExpression(BlobColumn.ofNull(columnName), Operator.IS_NOT_NULL);
10311053
}
1054+
10321055
/**
10331056
* Creates an 'is not null' conditional expression for a DATE value.
10341057
*

core/src/main/java/com/scalar/db/api/LikeExpression.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ public class LikeExpression extends ConditionalExpression {
1616
* Constructs a {@code LikeExpression} with the specified column and operator. For the escape
1717
* character, the default one ("\", i.e., backslash) is used.
1818
*
19-
* @param column a target column used to compare
20-
* @param operator an operator used to compare the target column
19+
* @param column a target text column used to compare
20+
* @param operator an operator used to compare the target text column. The operator must be either
21+
* LIKE or NOT_LIKE.
2122
*/
2223
LikeExpression(TextColumn column, Operator operator) {
2324
this(column, operator, DEFAULT_ESCAPE_CHAR);
@@ -28,8 +29,9 @@ public class LikeExpression extends ConditionalExpression {
2829
* The escape character must be a string of a single character or an empty string. If an empty
2930
* string is specified, the escape character is disabled.
3031
*
31-
* @param column a target column used to compare
32-
* @param operator an operator used to compare the target column
32+
* @param column a target text column used to compare
33+
* @param operator an operator used to compare the target text column. The operator must be either
34+
* LIKE or NOT_LIKE.
3335
* @param escape an escape character for the like operator
3436
*/
3537
LikeExpression(TextColumn column, Operator operator, String escape) {
@@ -75,6 +77,11 @@ private void check(String pattern, Operator operator, String escape) {
7577
}
7678
}
7779

80+
@Override
81+
public TextColumn getColumn() {
82+
return (TextColumn) super.getColumn();
83+
}
84+
7885
/**
7986
* Returns the escape character for LIKE operator.
8087
*

core/src/main/java/com/scalar/db/transaction/consensuscommit/AbstractMutationComposer.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
import com.google.common.annotations.VisibleForTesting;
44
import com.google.common.collect.ImmutableList;
55
import com.scalar.db.api.Mutation;
6+
import com.scalar.db.api.PutBuilder;
7+
import com.scalar.db.api.TableMetadata;
8+
import com.scalar.db.io.DataType;
69
import java.util.ArrayList;
710
import java.util.List;
11+
import java.util.Set;
812
import javax.annotation.concurrent.NotThreadSafe;
913

1014
@NotThreadSafe
@@ -34,4 +38,50 @@ public AbstractMutationComposer(String id, TransactionTableMetadataManager table
3438
public List<Mutation> get() {
3539
return ImmutableList.copyOf(mutations);
3640
}
41+
42+
static void setBeforeImageColumnsToNull(
43+
PutBuilder.Buildable putBuilder,
44+
Set<String> beforeImageColumnNames,
45+
TableMetadata tableMetadata) {
46+
for (String beforeImageColumnName : beforeImageColumnNames) {
47+
DataType columnDataType = tableMetadata.getColumnDataType(beforeImageColumnName);
48+
switch (columnDataType) {
49+
case BOOLEAN:
50+
putBuilder.booleanValue(beforeImageColumnName, null);
51+
break;
52+
case INT:
53+
putBuilder.intValue(beforeImageColumnName, null);
54+
break;
55+
case BIGINT:
56+
putBuilder.bigIntValue(beforeImageColumnName, null);
57+
break;
58+
case FLOAT:
59+
putBuilder.floatValue(beforeImageColumnName, null);
60+
break;
61+
case DOUBLE:
62+
putBuilder.doubleValue(beforeImageColumnName, null);
63+
break;
64+
case TEXT:
65+
putBuilder.textValue(beforeImageColumnName, null);
66+
break;
67+
case BLOB:
68+
putBuilder.blobValue(beforeImageColumnName, (byte[]) null);
69+
break;
70+
case DATE:
71+
putBuilder.dateValue(beforeImageColumnName, null);
72+
break;
73+
case TIME:
74+
putBuilder.timeValue(beforeImageColumnName, null);
75+
break;
76+
case TIMESTAMP:
77+
putBuilder.timestampValue(beforeImageColumnName, null);
78+
break;
79+
case TIMESTAMPTZ:
80+
putBuilder.timestampTZValue(beforeImageColumnName, null);
81+
break;
82+
default:
83+
throw new AssertionError("Unknown data type: " + columnDataType);
84+
}
85+
}
86+
}
3787
}

core/src/main/java/com/scalar/db/transaction/consensuscommit/CommitMutationComposer.java

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,29 @@
11
package com.scalar.db.transaction.consensuscommit;
22

33
import static com.scalar.db.api.ConditionalExpression.Operator;
4+
import static com.scalar.db.transaction.consensuscommit.Attribute.COMMITTED_AT;
45
import static com.scalar.db.transaction.consensuscommit.Attribute.ID;
56
import static com.scalar.db.transaction.consensuscommit.Attribute.STATE;
67
import static com.scalar.db.transaction.consensuscommit.Attribute.toIdValue;
78
import static com.scalar.db.transaction.consensuscommit.Attribute.toStateValue;
89

910
import com.google.common.annotations.VisibleForTesting;
11+
import com.scalar.db.api.ConditionBuilder;
1012
import com.scalar.db.api.ConditionalExpression;
1113
import com.scalar.db.api.Consistency;
1214
import com.scalar.db.api.Delete;
1315
import com.scalar.db.api.DeleteIf;
1416
import com.scalar.db.api.Mutation;
1517
import com.scalar.db.api.Operation;
1618
import com.scalar.db.api.Put;
17-
import com.scalar.db.api.PutIf;
19+
import com.scalar.db.api.PutBuilder;
1820
import com.scalar.db.api.Selection;
21+
import com.scalar.db.api.TableMetadata;
1922
import com.scalar.db.api.TransactionState;
2023
import com.scalar.db.exception.storage.ExecutionException;
2124
import com.scalar.db.io.Key;
2225
import com.scalar.db.util.ScalarDbUtils;
26+
import java.util.LinkedHashSet;
2327
import java.util.Optional;
2428
import javax.annotation.Nullable;
2529
import javax.annotation.concurrent.NotThreadSafe;
@@ -82,17 +86,33 @@ private void add(Selection base, @Nullable TransactionResult result) throws Exec
8286

8387
private Put composePut(Operation base, @Nullable TransactionResult result)
8488
throws ExecutionException {
85-
return new Put(getPartitionKey(base, result), getClusteringKey(base, result).orElse(null))
86-
.forNamespace(base.forNamespace().get())
87-
.forTable(base.forTable().get())
88-
.withConsistency(Consistency.LINEARIZABLE)
89-
.withCondition(
90-
new PutIf(
91-
new ConditionalExpression(ID, toIdValue(id), Operator.EQ),
92-
new ConditionalExpression(
93-
STATE, toStateValue(TransactionState.PREPARED), Operator.EQ)))
94-
.withValue(Attribute.toCommittedAtValue(current))
95-
.withValue(Attribute.toStateValue(TransactionState.COMMITTED));
89+
PutBuilder.Buildable putBuilder =
90+
Put.newBuilder()
91+
.namespace(base.forNamespace().get())
92+
.table(base.forTable().get())
93+
.partitionKey(getPartitionKey(base, result))
94+
.condition(
95+
ConditionBuilder.putIf(ConditionBuilder.column(ID).isEqualToText(id))
96+
.and(
97+
ConditionBuilder.column(STATE)
98+
.isEqualToInt(TransactionState.PREPARED.get()))
99+
.build())
100+
.bigIntValue(COMMITTED_AT, current)
101+
.intValue(STATE, TransactionState.COMMITTED.get())
102+
.consistency(Consistency.LINEARIZABLE);
103+
getClusteringKey(base, result).ifPresent(putBuilder::clusteringKey);
104+
105+
// Set before image columns to null
106+
if (result != null) {
107+
TransactionTableMetadata transactionTableMetadata =
108+
tableMetadataManager.getTransactionTableMetadata(base);
109+
LinkedHashSet<String> beforeImageColumnNames =
110+
transactionTableMetadata.getBeforeImageColumnNames();
111+
TableMetadata tableMetadata = transactionTableMetadata.getTableMetadata();
112+
setBeforeImageColumnsToNull(putBuilder, beforeImageColumnNames, tableMetadata);
113+
}
114+
115+
return putBuilder.build();
96116
}
97117

98118
private Delete composeDelete(Operation base, @Nullable TransactionResult result)

0 commit comments

Comments
 (0)