6666import com .scalar .db .common .error .CoreError ;
6767import com .scalar .db .config .DatabaseConfig ;
6868import com .scalar .db .exception .storage .ExecutionException ;
69+ import com .scalar .db .io .BigIntColumn ;
70+ import com .scalar .db .io .BlobColumn ;
71+ import com .scalar .db .io .BooleanColumn ;
72+ import com .scalar .db .io .Column ;
73+ import com .scalar .db .io .DataType ;
74+ import com .scalar .db .io .DoubleColumn ;
75+ import com .scalar .db .io .FloatColumn ;
76+ import com .scalar .db .io .IntColumn ;
6977import com .scalar .db .io .Key ;
78+ import com .scalar .db .io .TextColumn ;
7079import com .scalar .db .schemaloader .SchemaLoader ;
7180import com .scalar .db .schemaloader .SchemaLoaderException ;
7281import com .scalar .db .service .StorageFactory ;
@@ -115,9 +124,6 @@ public class GenericContractEndToEndTest {
115124 private static final String ASSET_ID = "id" ;
116125 private static final String ASSET_AGE = "age" ;
117126 private static final String ASSET_OUTPUT = "output" ;
118- private static final String DATA_TYPE_INT = "INT" ;
119- private static final String DATA_TYPE_BIGINT = "BIGINT" ;
120- private static final String DATA_TYPE_TEXT = "TEXT" ;
121127
122128 private static final String JDBC_TRANSACTION_MANAGER = "jdbc" ;
123129 private static final String PROP_STORAGE = "scalardb.storage" ;
@@ -241,6 +247,17 @@ public class GenericContractEndToEndTest {
241247 private static final String SOME_COLUMN_NAME_2 = "version" ;
242248 private static final String SOME_COLUMN_NAME_3 = "status" ;
243249 private static final String SOME_COLUMN_NAME_4 = "registered_at" ;
250+ private static final String SOME_COLUMN_NAME_BOOLEAN = "column_boolean" ;
251+ private static final String SOME_COLUMN_NAME_BIGINT = "column_bigint" ;
252+ private static final String SOME_COLUMN_NAME_FLOAT = "column_float" ;
253+ private static final String SOME_COLUMN_NAME_DOUBLE = "column_double" ;
254+ private static final String SOME_COLUMN_NAME_TEXT = "column_text" ;
255+ private static final String SOME_COLUMN_NAME_BLOB = "column_blob" ;
256+ private static final boolean SOME_BOOLEAN_VALUE = false ;
257+ private static final long SOME_BIGINT_VALUE = BigIntColumn .MAX_VALUE ;
258+ private static final float SOME_FLOAT_VALUE = Float .MAX_VALUE ;
259+ private static final double SOME_DOUBLE_VALUE = Double .MAX_VALUE ;
260+ private static final byte [] SOME_BLOB_VALUE = {1 , 2 , 3 , 4 , 5 };
244261 private static final String SOME_COLLECTION_ID = "set" ;
245262 private static final ArrayNode SOME_DEFAULT_OBJECT_IDS =
246263 mapper .createArrayNode ().add ("object1" ).add ("object2" ).add ("object3" ).add ("object4" );
@@ -432,41 +449,80 @@ private void prepareCollection() {
432449 prepareCollection (clientService );
433450 }
434451
435- private JsonNode createColumn (String name , int value ) {
452+ private JsonNode createColumn (Column <?> column ) {
453+ ObjectNode jsonColumn =
454+ mapper
455+ .createObjectNode ()
456+ .put (COLUMN_NAME , column .getName ())
457+ .put (DATA_TYPE , column .getDataType ().name ());
458+
459+ switch (column .getDataType ()) {
460+ case BOOLEAN :
461+ jsonColumn .put (VALUE , column .getBooleanValue ());
462+ break ;
463+ case INT :
464+ jsonColumn .put (VALUE , column .getIntValue ());
465+ break ;
466+ case BIGINT :
467+ jsonColumn .put (VALUE , column .getBigIntValue ());
468+ break ;
469+ case FLOAT :
470+ jsonColumn .put (VALUE , column .getFloatValue ());
471+ break ;
472+ case DOUBLE :
473+ jsonColumn .put (VALUE , column .getDoubleValue ());
474+ break ;
475+ case TEXT :
476+ jsonColumn .put (VALUE , column .getTextValue ());
477+ break ;
478+ case BLOB :
479+ jsonColumn .put (VALUE , column .getBlobValueAsBytes ());
480+ break ;
481+ default :
482+ throw new IllegalArgumentException ("Invalid data type: " + column .getDataType ());
483+ }
484+
485+ return jsonColumn ;
486+ }
487+
488+ private JsonNode createNullColumn (String columnName , DataType dataType ) {
436489 return mapper
437490 .createObjectNode ()
438- .put (COLUMN_NAME , name )
439- .put (VALUE , value )
440- .put ( DATA_TYPE , DATA_TYPE_INT );
491+ .put (COLUMN_NAME , columnName )
492+ .put (DATA_TYPE , dataType . name () )
493+ .set ( VALUE , null );
441494 }
442495
443- private JsonNode createColumn ( String name , long value ) {
496+ private ArrayNode createColumns ( int status ) {
444497 return mapper
445- .createObjectNode ()
446- .put (COLUMN_NAME , name )
447- .put (VALUE , value )
448- .put (DATA_TYPE , DATA_TYPE_BIGINT );
498+ .createArrayNode ()
499+ .add (createColumn (IntColumn .of (SOME_COLUMN_NAME_3 , status )))
500+ .add (createColumn (BigIntColumn .of (SOME_COLUMN_NAME_4 , SOME_BIGINT_VALUE )))
501+ .add (createColumn (BooleanColumn .of (SOME_COLUMN_NAME_BOOLEAN , SOME_BOOLEAN_VALUE )))
502+ .add (createColumn (BigIntColumn .of (SOME_COLUMN_NAME_BIGINT , SOME_BIGINT_VALUE )))
503+ .add (createColumn (FloatColumn .of (SOME_COLUMN_NAME_FLOAT , SOME_FLOAT_VALUE )))
504+ .add (createColumn (DoubleColumn .of (SOME_COLUMN_NAME_DOUBLE , SOME_DOUBLE_VALUE )))
505+ .add (createColumn (BlobColumn .of (SOME_COLUMN_NAME_BLOB , SOME_BLOB_VALUE )));
449506 }
450507
451- private JsonNode createColumn ( String name , String value ) {
508+ private ArrayNode createNullColumns ( ) {
452509 return mapper
453- .createObjectNode ()
454- .put (COLUMN_NAME , name )
455- .put (VALUE , value )
456- .put (DATA_TYPE , DATA_TYPE_TEXT );
510+ .createArrayNode ()
511+ .add (createNullColumn (SOME_COLUMN_NAME_3 , DataType .INT ))
512+ .add (createNullColumn (SOME_COLUMN_NAME_4 , DataType .BIGINT ))
513+ .add (createNullColumn (SOME_COLUMN_NAME_BOOLEAN , DataType .BOOLEAN ))
514+ .add (createNullColumn (SOME_COLUMN_NAME_BIGINT , DataType .BIGINT ))
515+ .add (createNullColumn (SOME_COLUMN_NAME_FLOAT , DataType .FLOAT ))
516+ .add (createNullColumn (SOME_COLUMN_NAME_DOUBLE , DataType .DOUBLE ))
517+ .add (createNullColumn (SOME_COLUMN_NAME_TEXT , DataType .TEXT ))
518+ .add (createNullColumn (SOME_COLUMN_NAME_BLOB , DataType .BLOB ));
457519 }
458520
459- private JsonNode createFunctionArguments (
460- String objectId , String version , int status , long registeredAt ) {
521+ private ObjectNode createFunctionArguments (String objectId , String version , ArrayNode columns ) {
461522 ArrayNode partitionKey =
462- mapper .createArrayNode ().add (createColumn (SOME_COLUMN_NAME_1 , objectId ));
523+ mapper .createArrayNode ().add (createColumn (TextColumn . of ( SOME_COLUMN_NAME_1 , objectId ) ));
463524 ArrayNode clusteringKey =
464- mapper .createArrayNode ().add (createColumn (SOME_COLUMN_NAME_2 , version ));
465- ArrayNode columns =
466- mapper
467- .createArrayNode ()
468- .add (createColumn (SOME_COLUMN_NAME_3 , status ))
469- .add (createColumn (SOME_COLUMN_NAME_4 , registeredAt ));
525+ mapper .createArrayNode ().add (createColumn (TextColumn .of (SOME_COLUMN_NAME_2 , version )));
470526
471527 ObjectNode arguments = mapper .createObjectNode ();
472528 arguments .put (NAMESPACE , SOME_FUNCTION_NAMESPACE );
@@ -478,6 +534,14 @@ private JsonNode createFunctionArguments(
478534 return arguments ;
479535 }
480536
537+ private ObjectNode createFunctionArguments (String objectId , String version , int status ) {
538+ return createFunctionArguments (objectId , version , createColumns (status ));
539+ }
540+
541+ private ObjectNode createFunctionArgumentsWithNullColumns (String objectId , String version ) {
542+ return createFunctionArguments (objectId , version , createNullColumns ());
543+ }
544+
481545 private void addObjectsToCollection (
482546 GenericContractClientService clientService , String collectionId , ArrayNode objectIds ) {
483547 JsonNode arguments =
@@ -749,9 +813,8 @@ public void putObject_FunctionArgumentsGiven_ShouldPutRecordToFunctionTable()
749813 .put (OBJECT_ID , SOME_OBJECT_ID )
750814 .put (HASH_VALUE , SOME_HASH_VALUE_1 )
751815 .set (METADATA , SOME_METADATA_1 );
752- JsonNode functionArguments0 = createFunctionArguments (SOME_OBJECT_ID , SOME_VERSION_ID_0 , 0 , 1L );
753- JsonNode functionArguments1 =
754- createFunctionArguments (SOME_OBJECT_ID , SOME_VERSION_ID_1 , 1 , 1234567890123L );
816+ JsonNode functionArguments0 = createFunctionArguments (SOME_OBJECT_ID , SOME_VERSION_ID_0 , 0 );
817+ JsonNode functionArguments1 = createFunctionArguments (SOME_OBJECT_ID , SOME_VERSION_ID_1 , 1 );
755818 Scan scan =
756819 Scan .newBuilder ()
757820 .namespace (SOME_FUNCTION_NAMESPACE )
@@ -773,11 +836,63 @@ public void putObject_FunctionArgumentsGiven_ShouldPutRecordToFunctionTable()
773836 assertThat (results .get (0 ).getText (SOME_COLUMN_NAME_1 )).isEqualTo (SOME_OBJECT_ID );
774837 assertThat (results .get (0 ).getText (SOME_COLUMN_NAME_2 )).isEqualTo (SOME_VERSION_ID_0 );
775838 assertThat (results .get (0 ).getInt (SOME_COLUMN_NAME_3 )).isEqualTo (0 );
776- assertThat (results .get (0 ).getBigInt (SOME_COLUMN_NAME_4 )).isEqualTo (1L );
839+ assertThat (results .get (0 ).getBigInt (SOME_COLUMN_NAME_4 )).isEqualTo (SOME_BIGINT_VALUE );
840+ assertThat (results .get (0 ).getBoolean (SOME_COLUMN_NAME_BOOLEAN )).isEqualTo (SOME_BOOLEAN_VALUE );
841+ assertThat (results .get (0 ).getBigInt (SOME_COLUMN_NAME_BIGINT )).isEqualTo (SOME_BIGINT_VALUE );
842+ assertThat (results .get (0 ).getFloat (SOME_COLUMN_NAME_FLOAT )).isEqualTo (SOME_FLOAT_VALUE );
843+ assertThat (results .get (0 ).getDouble (SOME_COLUMN_NAME_DOUBLE )).isEqualTo (SOME_DOUBLE_VALUE );
844+ assertThat (results .get (0 ).getBlobAsBytes (SOME_COLUMN_NAME_BLOB )).isEqualTo (SOME_BLOB_VALUE );
777845 assertThat (results .get (1 ).getText (SOME_COLUMN_NAME_1 )).isEqualTo (SOME_OBJECT_ID );
778846 assertThat (results .get (1 ).getText (SOME_COLUMN_NAME_2 )).isEqualTo (SOME_VERSION_ID_1 );
779847 assertThat (results .get (1 ).getInt (SOME_COLUMN_NAME_3 )).isEqualTo (1 );
780- assertThat (results .get (1 ).getBigInt (SOME_COLUMN_NAME_4 )).isEqualTo (1234567890123L );
848+ assertThat (results .get (1 ).getBigInt (SOME_COLUMN_NAME_4 )).isEqualTo (SOME_BIGINT_VALUE );
849+ assertThat (results .get (1 ).getBoolean (SOME_COLUMN_NAME_BOOLEAN )).isEqualTo (SOME_BOOLEAN_VALUE );
850+ assertThat (results .get (1 ).getBigInt (SOME_COLUMN_NAME_BIGINT )).isEqualTo (SOME_BIGINT_VALUE );
851+ assertThat (results .get (1 ).getFloat (SOME_COLUMN_NAME_FLOAT )).isEqualTo (SOME_FLOAT_VALUE );
852+ assertThat (results .get (1 ).getDouble (SOME_COLUMN_NAME_DOUBLE )).isEqualTo (SOME_DOUBLE_VALUE );
853+ assertThat (results .get (1 ).getBlobAsBytes (SOME_COLUMN_NAME_BLOB )).isEqualTo (SOME_BLOB_VALUE );
854+ } catch (IOException e ) {
855+ throw new RuntimeException (e );
856+ }
857+ }
858+
859+ @ Test
860+ public void putObject_FunctionArgumentsWithNullColumnsGiven_ShouldPutRecordToFunctionTable ()
861+ throws ExecutionException {
862+ // Arrange
863+ JsonNode contractArguments =
864+ mapper
865+ .createObjectNode ()
866+ .put (OBJECT_ID , SOME_OBJECT_ID )
867+ .put (HASH_VALUE , SOME_HASH_VALUE_0 )
868+ .set (METADATA , SOME_METADATA_0 );
869+ JsonNode functionArguments =
870+ createFunctionArgumentsWithNullColumns (SOME_OBJECT_ID , SOME_VERSION_ID_0 );
871+ Scan scan =
872+ Scan .newBuilder ()
873+ .namespace (SOME_FUNCTION_NAMESPACE )
874+ .table (SOME_FUNCTION_TABLE )
875+ .partitionKey (Key .ofText (SOME_COLUMN_NAME_1 , SOME_OBJECT_ID ))
876+ .build ();
877+
878+ // Act
879+ clientService .executeContract (
880+ ID_OBJECT_PUT , contractArguments , ID_OBJECT_PUT_MUTABLE , functionArguments );
881+
882+ // Assert
883+ try (Scanner scanner = storage .scan (scan )) {
884+ List <Result > results = scanner .all ();
885+ assertThat (results ).hasSize (1 );
886+ assertThat (results .get (0 ).getText (SOME_COLUMN_NAME_1 )).isEqualTo (SOME_OBJECT_ID );
887+ assertThat (results .get (0 ).getText (SOME_COLUMN_NAME_2 )).isEqualTo (SOME_VERSION_ID_0 );
888+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_3 )).isTrue ();
889+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_4 )).isTrue ();
890+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_BOOLEAN )).isTrue ();
891+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_BIGINT )).isTrue ();
892+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_FLOAT )).isTrue ();
893+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_DOUBLE )).isTrue ();
894+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_TEXT )).isTrue ();
895+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_BLOB )).isTrue ();
781896 } catch (IOException e ) {
782897 throw new RuntimeException (e );
783898 }
@@ -800,7 +915,9 @@ public void putObject_FunctionArgumentsGiven_ShouldPutRecordToFunctionTable()
800915 .put (TABLE , "foo" )
801916 .set (
802917 PARTITION_KEY ,
803- mapper .createArrayNode ().add (createColumn (SOME_COLUMN_NAME_1 , SOME_OBJECT_ID )));
918+ mapper
919+ .createArrayNode ()
920+ .add (createColumn (TextColumn .of (SOME_COLUMN_NAME_1 , SOME_OBJECT_ID ))));
804921
805922 // Act Assert
806923 assertThatThrownBy (
@@ -832,8 +949,8 @@ public void putObject_FunctionArgumentsGiven_ShouldPutRecordToFunctionTable()
832949 .put (OBJECT_ID , SOME_OBJECT_ID )
833950 .put (HASH_VALUE , SOME_HASH_VALUE_1 )
834951 .set (METADATA , SOME_METADATA_1 );
835- JsonNode functionArguments0 = createFunctionArguments (SOME_OBJECT_ID , SOME_VERSION_ID_0 , 0 , 1L );
836- JsonNode functionArguments1 = createFunctionArguments (SOME_OBJECT_ID , SOME_VERSION_ID_0 , 1 , 1L );
952+ JsonNode functionArguments0 = createFunctionArguments (SOME_OBJECT_ID , SOME_VERSION_ID_0 , 0 );
953+ JsonNode functionArguments1 = createFunctionArguments (SOME_OBJECT_ID , SOME_VERSION_ID_0 , 1 );
837954 Put put =
838955 Put .newBuilder ()
839956 .namespace (SOME_FUNCTION_NAMESPACE )
0 commit comments