Skip to content

Commit 96c2073

Browse files
committed
Check condition on BLOB for selection operation
1 parent 23db591 commit 96c2073

File tree

6 files changed

+60
-69
lines changed

6 files changed

+60
-69
lines changed

core/src/main/java/com/scalar/db/common/CoreError.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -820,10 +820,10 @@ public enum CoreError implements ScalarDbError {
820820
"With Oracle, setting an ordering on a BLOB column when using a cross partition scan operation is not supported. Ordering: %s",
821821
"",
822822
""),
823-
JDBC_ORACLE_CROSS_PARTITION_SCAN_CONDITION_ON_BLOB_COLUMN_NOT_SUPPORTED(
823+
JDBC_ORACLE_SELECTION_CONDITION_ON_BLOB_COLUMN_NOT_SUPPORTED(
824824
Category.USER_ERROR,
825825
"0243",
826-
"With Oracle, setting a condition on a BLOB column when using a cross partition scan operation is not supported. Condition: %s",
826+
"With Oracle, setting a condition on a BLOB column when using a selection operation is not supported. Condition: %s",
827827
"",
828828
""),
829829

core/src/main/java/com/scalar/db/storage/jdbc/JdbcOperationChecker.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ protected void checkOrderingsForScanAll(ScanAll scanAll, TableMetadata metadata)
3131
@Override
3232
protected void checkConjunctions(Selection selection, TableMetadata metadata) {
3333
super.checkConjunctions(selection, metadata);
34-
if (selection instanceof ScanAll) {
35-
rdbEngine.throwIfCrossPartitionScanConditionOnBlobColumnNotSupported(
36-
(ScanAll) selection, metadata);
37-
}
34+
rdbEngine.throwIfConjunctionsOnBlobColumnNotSupported(selection.getConjunctions(), metadata);
3835
}
3936
}

core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineOracle.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.scalar.db.api.LikeExpression;
88
import com.scalar.db.api.Scan;
99
import com.scalar.db.api.ScanAll;
10+
import com.scalar.db.api.Selection.Conjunction;
1011
import com.scalar.db.api.TableMetadata;
1112
import com.scalar.db.common.CoreError;
1213
import com.scalar.db.exception.storage.ExecutionException;
@@ -27,6 +28,7 @@
2728
import java.time.OffsetDateTime;
2829
import java.util.ArrayList;
2930
import java.util.Optional;
31+
import java.util.Set;
3032
import java.util.stream.Collectors;
3133
import java.util.stream.Stream;
3234
import javax.annotation.Nullable;
@@ -472,19 +474,19 @@ public void throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported(
472474
}
473475

474476
@Override
475-
public void throwIfCrossPartitionScanConditionOnBlobColumnNotSupported(
476-
ScanAll scanAll, TableMetadata metadata) {
477+
public void throwIfConjunctionsOnBlobColumnNotSupported(
478+
Set<Conjunction> conjunctions, TableMetadata metadata) {
477479
Optional<ConditionalExpression> conditionalExpression =
478-
scanAll.getConjunctions().stream()
480+
conjunctions.stream()
479481
.flatMap(conjunction -> conjunction.getConditions().stream())
480482
.filter(
481483
condition ->
482484
metadata.getColumnDataType(condition.getColumn().getName()) == DataType.BLOB)
483485
.findFirst();
484486
if (conditionalExpression.isPresent()) {
485487
throw new UnsupportedOperationException(
486-
CoreError.JDBC_ORACLE_CROSS_PARTITION_SCAN_CONDITION_ON_BLOB_COLUMN_NOT_SUPPORTED
487-
.buildMessage(conditionalExpression.get()));
488+
CoreError.JDBC_ORACLE_SELECTION_CONDITION_ON_BLOB_COLUMN_NOT_SUPPORTED.buildMessage(
489+
conditionalExpression.get()));
488490
}
489491
}
490492

core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineStrategy.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.scalar.db.api.LikeExpression;
44
import com.scalar.db.api.ScanAll;
5+
import com.scalar.db.api.Selection.Conjunction;
56
import com.scalar.db.api.TableMetadata;
67
import com.scalar.db.exception.storage.ExecutionException;
78
import com.scalar.db.io.DataType;
@@ -26,6 +27,7 @@
2627
import java.util.Collections;
2728
import java.util.List;
2829
import java.util.Map;
30+
import java.util.Set;
2931
import java.util.stream.Collectors;
3032
import javax.annotation.Nullable;
3133

@@ -313,14 +315,14 @@ default void throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported(
313315
ScanAll scanAll, TableMetadata metadata) {}
314316

315317
/**
316-
* Throws an exception if a cross-partition scan operation with a condition on a blob column is
317-
* specified and is not supported in the underlying storage.
318+
* Throws an exception if one of the conjunction targets a blob column and is not supported in the
319+
* underlying storage.
318320
*
319-
* @param scanAll the ScanAll operation
321+
* @param conjunctions a set of conjunction
320322
* @param metadata the table metadata
321-
* @throws UnsupportedOperationException if the ScanAll operation contains a condition on a blob
322-
* column, and it is not supported in the underlying storage
323+
* @throws UnsupportedOperationException if one of the conjunction targets a blob column, and it
324+
* is not supported in the underlying storage
323325
*/
324-
default void throwIfCrossPartitionScanConditionOnBlobColumnNotSupported(
325-
ScanAll scanAll, TableMetadata metadata) {}
326+
default void throwIfConjunctionsOnBlobColumnNotSupported(
327+
Set<Conjunction> conjunctions, TableMetadata metadata) {}
326328
}

core/src/test/java/com/scalar/db/storage/jdbc/JdbcOperationCheckerTest.java

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,21 @@
22

33
import static org.mockito.ArgumentMatchers.any;
44
import static org.mockito.Mockito.doThrow;
5-
import static org.mockito.Mockito.never;
5+
import static org.mockito.Mockito.mock;
66
import static org.mockito.Mockito.verify;
7+
import static org.mockito.Mockito.when;
78

9+
import com.google.common.collect.Sets;
810
import com.scalar.db.api.Scan;
911
import com.scalar.db.api.ScanAll;
12+
import com.scalar.db.api.Selection;
13+
import com.scalar.db.api.Selection.Conjunction;
1014
import com.scalar.db.api.TableMetadata;
1115
import com.scalar.db.common.StorageInfoProvider;
1216
import com.scalar.db.common.TableMetadataManager;
1317
import com.scalar.db.config.DatabaseConfig;
18+
import java.util.Collections;
19+
import java.util.Set;
1420
import org.assertj.core.api.Assertions;
1521
import org.junit.jupiter.api.BeforeEach;
1622
import org.junit.jupiter.api.Test;
@@ -25,6 +31,7 @@ public class JdbcOperationCheckerTest {
2531
@Mock private RdbEngineStrategy rdbEngine;
2632
@Mock private ScanAll scanAll;
2733
@Mock private Scan scan;
34+
@Mock private Selection selection;
2835
@Mock private TableMetadata tableMetadata;
2936
private JdbcOperationChecker operationChecker;
3037

@@ -68,42 +75,35 @@ public void checkOrderingsForScanAll_WhenAdditionalCheckThrows_ShouldPropagateEx
6875
}
6976

7077
@Test
71-
public void checkConjunctions_WithScanAll_ShouldInvokeAdditionalCheckOnRdbEngine() {
78+
public void checkConjunctions_ShouldInvokeAdditionalCheckOnRdbEngine() {
7279
// Arrange
7380
// Act
74-
operationChecker.checkConjunctions(scanAll, tableMetadata);
81+
Conjunction conjunction1 = mock(Conjunction.class);
82+
Conjunction conjunction2 = mock(Conjunction.class);
83+
Set<Conjunction> conjunctions = Sets.newHashSet(conjunction1, conjunction2);
84+
when(selection.getConjunctions()).thenReturn(conjunctions);
85+
operationChecker.checkConjunctions(selection, tableMetadata);
7586

7687
// Assert
77-
verify(rdbEngine)
78-
.throwIfCrossPartitionScanConditionOnBlobColumnNotSupported(scanAll, tableMetadata);
88+
verify(rdbEngine).throwIfConjunctionsOnBlobColumnNotSupported(conjunctions, tableMetadata);
7989
}
8090

8191
@Test
82-
public void checkConjunctions_WithScan_ShouldNotInvokeAdditionalCheckOnRdbEngine() {
83-
// Arrange
84-
// Act
85-
operationChecker.checkConjunctions(scan, tableMetadata);
86-
87-
// Assert
88-
verify(rdbEngine, never())
89-
.throwIfCrossPartitionScanConditionOnBlobColumnNotSupported(any(), any());
90-
}
91-
92-
@Test
93-
public void checkConjunctions_WithScanAll_WhenAdditionalCheckThrows_ShouldPropagateException() {
92+
public void checkConjunctions_WhenAdditionalCheckThrows_ShouldPropagateException() {
9493
// Arrange
9594
Exception exception = new RuntimeException();
9695
doThrow(exception)
9796
.when(rdbEngine)
98-
.throwIfCrossPartitionScanConditionOnBlobColumnNotSupported(
99-
any(ScanAll.class), any(TableMetadata.class));
97+
.throwIfConjunctionsOnBlobColumnNotSupported(any(), any(TableMetadata.class));
98+
Set<Conjunction> conjunctions = Collections.emptySet();
99+
when(selection.getConjunctions()).thenReturn(conjunctions);
100100

101101
// Act
102-
Assertions.assertThatThrownBy(() -> operationChecker.checkConjunctions(scanAll, tableMetadata))
102+
Assertions.assertThatThrownBy(
103+
() -> operationChecker.checkConjunctions(selection, tableMetadata))
103104
.isEqualTo(exception);
104105

105106
// Assert
106-
verify(rdbEngine)
107-
.throwIfCrossPartitionScanConditionOnBlobColumnNotSupported(scanAll, tableMetadata);
107+
verify(rdbEngine).throwIfConjunctionsOnBlobColumnNotSupported(conjunctions, tableMetadata);
108108
}
109109
}

core/src/test/java/com/scalar/db/storage/jdbc/RdbEngineOracleTest.java

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.scalar.db.api.Scan;
1111
import com.scalar.db.api.Scan.Ordering.Order;
1212
import com.scalar.db.api.ScanAll;
13+
import com.scalar.db.api.Selection.Conjunction;
1314
import com.scalar.db.api.TableMetadata;
1415
import com.scalar.db.io.DataType;
1516
import java.util.Arrays;
@@ -153,60 +154,50 @@ void createTableInternalSqlsAfterCreateTable_GivenDifferentClusteringOrders_Shou
153154

154155
@Test
155156
public void
156-
throwIfCrossPartitionScanConditionOnBlobColumnNotSupported_WithoutBlobCondition_ShouldNotThrowException() {
157+
throwIfConjunctionsOnBlobColumnNotSupported_WithoutBlobCondition_ShouldNotThrowException() {
157158
// Arrange
158159
TableMetadata metadata = mock(TableMetadata.class);
159-
ScanAll scanAll =
160-
(ScanAll)
161-
Scan.newBuilder()
162-
.namespace("ns")
163-
.table("tbl")
164-
.all()
165-
.where(ConditionBuilder.column("int_column").isEqualToInt(10))
166-
.and(ConditionBuilder.column("text_column").isEqualToText("value"))
167-
.build();
160+
java.util.Set<Conjunction> conjunctions =
161+
java.util.Collections.singleton(
162+
Conjunction.of(
163+
ConditionBuilder.column("int_column").isEqualToInt(10),
164+
ConditionBuilder.column("text_column").isEqualToText("value")));
168165

169166
when(metadata.getColumnDataType("int_column")).thenReturn(DataType.INT);
170167
when(metadata.getColumnDataType("text_column")).thenReturn(DataType.TEXT);
171168

172169
// Act & Assert
173170
assertThatCode(
174171
() ->
175-
rdbEngineOracle.throwIfCrossPartitionScanConditionOnBlobColumnNotSupported(
176-
scanAll, metadata))
172+
rdbEngineOracle.throwIfConjunctionsOnBlobColumnNotSupported(conjunctions, metadata))
177173
.doesNotThrowAnyException();
178174
}
179175

180176
@Test
181177
public void
182-
throwIfCrossPartitionScanConditionOnBlobColumnNotSupported_WithNoConditions_ShouldNotThrowException() {
178+
throwIfConjunctionsOnBlobColumnNotSupported_WithNoConditions_ShouldNotThrowException() {
183179
// Arrange
184180
TableMetadata metadata = mock(TableMetadata.class);
185-
ScanAll scanAll = (ScanAll) Scan.newBuilder().namespace("ns").table("tbl").all().build();
186181

187182
// Act & Assert
188183
assertThatCode(
189184
() ->
190-
rdbEngineOracle.throwIfCrossPartitionScanConditionOnBlobColumnNotSupported(
191-
scanAll, metadata))
185+
rdbEngineOracle.throwIfConjunctionsOnBlobColumnNotSupported(
186+
java.util.Collections.emptySet(), metadata))
192187
.doesNotThrowAnyException();
193188
}
194189

195190
@Test
196191
public void
197-
throwIfCrossPartitionScanConditionOnBlobColumnNotSupported_WithMixedConditions_ShouldThrowWhenBlobPresent() {
192+
throwIfConjunctionsOnBlobColumnNotSupported_WithMixedConditions_ShouldThrowWhenBlobPresent() {
198193
// Arrange
199194
TableMetadata metadata = mock(TableMetadata.class);
200-
ScanAll scanAll =
201-
(ScanAll)
202-
Scan.newBuilder()
203-
.namespace("ns")
204-
.table("tbl")
205-
.all()
206-
.where(ConditionBuilder.column("int_column").isGreaterThanInt(100))
207-
.and(ConditionBuilder.column("blob_column").isNotEqualToBlob(new byte[] {5, 6}))
208-
.and(ConditionBuilder.column("text_column").isEqualToText("test"))
209-
.build();
195+
java.util.Set<Conjunction> conjunctions =
196+
java.util.Collections.singleton(
197+
Conjunction.of(
198+
ConditionBuilder.column("int_column").isGreaterThanInt(100),
199+
ConditionBuilder.column("blob_column").isNotEqualToBlob(new byte[] {5, 6}),
200+
ConditionBuilder.column("text_column").isEqualToText("test")));
210201

211202
when(metadata.getColumnDataType("int_column")).thenReturn(DataType.INT);
212203
when(metadata.getColumnDataType("blob_column")).thenReturn(DataType.BLOB);
@@ -215,8 +206,7 @@ void createTableInternalSqlsAfterCreateTable_GivenDifferentClusteringOrders_Shou
215206
// Act & Assert
216207
assertThatThrownBy(
217208
() ->
218-
rdbEngineOracle.throwIfCrossPartitionScanConditionOnBlobColumnNotSupported(
219-
scanAll, metadata))
209+
rdbEngineOracle.throwIfConjunctionsOnBlobColumnNotSupported(conjunctions, metadata))
220210
.isInstanceOf(UnsupportedOperationException.class)
221211
.hasMessageContaining("blob_column");
222212
}

0 commit comments

Comments
 (0)