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,88 @@ 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 createColumn (String columnName , DataType dataType , String value ) {
436489 return mapper
437490 .createObjectNode ()
438- .put (COLUMN_NAME , name )
491+ .put (COLUMN_NAME , columnName )
439492 .put (VALUE , value )
440- .put (DATA_TYPE , DATA_TYPE_INT );
493+ .put (DATA_TYPE , dataType . name () );
441494 }
442495
443- private JsonNode createColumn (String name , long value ) {
496+ private JsonNode createNullColumn (String columnName , DataType dataType ) {
444497 return mapper
445498 .createObjectNode ()
446- .put (COLUMN_NAME , name )
447- .put (VALUE , value )
448- .put ( DATA_TYPE , DATA_TYPE_BIGINT );
499+ .put (COLUMN_NAME , columnName )
500+ .put (DATA_TYPE , dataType . name () )
501+ .set ( VALUE , null );
449502 }
450503
451- private JsonNode createColumn ( String name , String value ) {
504+ private ArrayNode createColumns ( int status ) {
452505 return mapper
453- .createObjectNode ()
454- .put (COLUMN_NAME , name )
455- .put (VALUE , value )
456- .put (DATA_TYPE , DATA_TYPE_TEXT );
506+ .createArrayNode ()
507+ .add (createColumn (IntColumn .of (SOME_COLUMN_NAME_3 , status )))
508+ .add (createColumn (BigIntColumn .of (SOME_COLUMN_NAME_4 , SOME_BIGINT_VALUE )))
509+ .add (createColumn (BooleanColumn .of (SOME_COLUMN_NAME_BOOLEAN , SOME_BOOLEAN_VALUE )))
510+ .add (createColumn (BigIntColumn .of (SOME_COLUMN_NAME_BIGINT , SOME_BIGINT_VALUE )))
511+ .add (createColumn (FloatColumn .of (SOME_COLUMN_NAME_FLOAT , SOME_FLOAT_VALUE )))
512+ .add (createColumn (DoubleColumn .of (SOME_COLUMN_NAME_DOUBLE , SOME_DOUBLE_VALUE )))
513+ .add (createColumn (BlobColumn .of (SOME_COLUMN_NAME_BLOB , SOME_BLOB_VALUE )));
514+ }
515+
516+ private ArrayNode createNullColumns () {
517+ return mapper
518+ .createArrayNode ()
519+ .add (createNullColumn (SOME_COLUMN_NAME_3 , DataType .INT ))
520+ .add (createNullColumn (SOME_COLUMN_NAME_4 , DataType .BIGINT ))
521+ .add (createNullColumn (SOME_COLUMN_NAME_BOOLEAN , DataType .BOOLEAN ))
522+ .add (createNullColumn (SOME_COLUMN_NAME_BIGINT , DataType .BIGINT ))
523+ .add (createNullColumn (SOME_COLUMN_NAME_FLOAT , DataType .FLOAT ))
524+ .add (createNullColumn (SOME_COLUMN_NAME_DOUBLE , DataType .DOUBLE ))
525+ .add (createNullColumn (SOME_COLUMN_NAME_TEXT , DataType .TEXT ))
526+ .add (createNullColumn (SOME_COLUMN_NAME_BLOB , DataType .BLOB ));
457527 }
458528
459- private JsonNode createFunctionArguments (
460- String objectId , String version , int status , long registeredAt ) {
529+ private ObjectNode createFunctionArguments (String objectId , String version , ArrayNode columns ) {
461530 ArrayNode partitionKey =
462- mapper .createArrayNode ().add (createColumn (SOME_COLUMN_NAME_1 , objectId ));
531+ mapper .createArrayNode ().add (createColumn (TextColumn . of ( SOME_COLUMN_NAME_1 , objectId ) ));
463532 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 ));
533+ mapper .createArrayNode ().add (createColumn (TextColumn .of (SOME_COLUMN_NAME_2 , version )));
470534
471535 ObjectNode arguments = mapper .createObjectNode ();
472536 arguments .put (NAMESPACE , SOME_FUNCTION_NAMESPACE );
@@ -478,6 +542,14 @@ private JsonNode createFunctionArguments(
478542 return arguments ;
479543 }
480544
545+ private ObjectNode createFunctionArguments (String objectId , String version , int status ) {
546+ return createFunctionArguments (objectId , version , createColumns (status ));
547+ }
548+
549+ private ObjectNode createFunctionArgumentsWithNullColumns (String objectId , String version ) {
550+ return createFunctionArguments (objectId , version , createNullColumns ());
551+ }
552+
481553 private void addObjectsToCollection (
482554 GenericContractClientService clientService , String collectionId , ArrayNode objectIds ) {
483555 JsonNode arguments =
@@ -749,9 +821,8 @@ public void putObject_FunctionArgumentsGiven_ShouldPutRecordToFunctionTable()
749821 .put (OBJECT_ID , SOME_OBJECT_ID )
750822 .put (HASH_VALUE , SOME_HASH_VALUE_1 )
751823 .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 );
824+ JsonNode functionArguments0 = createFunctionArguments (SOME_OBJECT_ID , SOME_VERSION_ID_0 , 0 );
825+ JsonNode functionArguments1 = createFunctionArguments (SOME_OBJECT_ID , SOME_VERSION_ID_1 , 1 );
755826 Scan scan =
756827 Scan .newBuilder ()
757828 .namespace (SOME_FUNCTION_NAMESPACE )
@@ -773,11 +844,63 @@ public void putObject_FunctionArgumentsGiven_ShouldPutRecordToFunctionTable()
773844 assertThat (results .get (0 ).getText (SOME_COLUMN_NAME_1 )).isEqualTo (SOME_OBJECT_ID );
774845 assertThat (results .get (0 ).getText (SOME_COLUMN_NAME_2 )).isEqualTo (SOME_VERSION_ID_0 );
775846 assertThat (results .get (0 ).getInt (SOME_COLUMN_NAME_3 )).isEqualTo (0 );
776- assertThat (results .get (0 ).getBigInt (SOME_COLUMN_NAME_4 )).isEqualTo (1L );
847+ assertThat (results .get (0 ).getBigInt (SOME_COLUMN_NAME_4 )).isEqualTo (SOME_BIGINT_VALUE );
848+ assertThat (results .get (0 ).getBoolean (SOME_COLUMN_NAME_BOOLEAN )).isEqualTo (SOME_BOOLEAN_VALUE );
849+ assertThat (results .get (0 ).getBigInt (SOME_COLUMN_NAME_BIGINT )).isEqualTo (SOME_BIGINT_VALUE );
850+ assertThat (results .get (0 ).getFloat (SOME_COLUMN_NAME_FLOAT )).isEqualTo (SOME_FLOAT_VALUE );
851+ assertThat (results .get (0 ).getDouble (SOME_COLUMN_NAME_DOUBLE )).isEqualTo (SOME_DOUBLE_VALUE );
852+ assertThat (results .get (0 ).getBlobAsBytes (SOME_COLUMN_NAME_BLOB )).isEqualTo (SOME_BLOB_VALUE );
777853 assertThat (results .get (1 ).getText (SOME_COLUMN_NAME_1 )).isEqualTo (SOME_OBJECT_ID );
778854 assertThat (results .get (1 ).getText (SOME_COLUMN_NAME_2 )).isEqualTo (SOME_VERSION_ID_1 );
779855 assertThat (results .get (1 ).getInt (SOME_COLUMN_NAME_3 )).isEqualTo (1 );
780- assertThat (results .get (1 ).getBigInt (SOME_COLUMN_NAME_4 )).isEqualTo (1234567890123L );
856+ assertThat (results .get (1 ).getBigInt (SOME_COLUMN_NAME_4 )).isEqualTo (SOME_BIGINT_VALUE );
857+ assertThat (results .get (1 ).getBoolean (SOME_COLUMN_NAME_BOOLEAN )).isEqualTo (SOME_BOOLEAN_VALUE );
858+ assertThat (results .get (1 ).getBigInt (SOME_COLUMN_NAME_BIGINT )).isEqualTo (SOME_BIGINT_VALUE );
859+ assertThat (results .get (1 ).getFloat (SOME_COLUMN_NAME_FLOAT )).isEqualTo (SOME_FLOAT_VALUE );
860+ assertThat (results .get (1 ).getDouble (SOME_COLUMN_NAME_DOUBLE )).isEqualTo (SOME_DOUBLE_VALUE );
861+ assertThat (results .get (1 ).getBlobAsBytes (SOME_COLUMN_NAME_BLOB )).isEqualTo (SOME_BLOB_VALUE );
862+ } catch (IOException e ) {
863+ throw new RuntimeException (e );
864+ }
865+ }
866+
867+ @ Test
868+ public void putObject_FunctionArgumentsWithNullColumnsGiven_ShouldPutRecordToFunctionTable ()
869+ throws ExecutionException {
870+ // Arrange
871+ JsonNode contractArguments =
872+ mapper
873+ .createObjectNode ()
874+ .put (OBJECT_ID , SOME_OBJECT_ID )
875+ .put (HASH_VALUE , SOME_HASH_VALUE_0 )
876+ .set (METADATA , SOME_METADATA_0 );
877+ JsonNode functionArguments =
878+ createFunctionArgumentsWithNullColumns (SOME_OBJECT_ID , SOME_VERSION_ID_0 );
879+ Scan scan =
880+ Scan .newBuilder ()
881+ .namespace (SOME_FUNCTION_NAMESPACE )
882+ .table (SOME_FUNCTION_TABLE )
883+ .partitionKey (Key .ofText (SOME_COLUMN_NAME_1 , SOME_OBJECT_ID ))
884+ .build ();
885+
886+ // Act
887+ clientService .executeContract (
888+ ID_OBJECT_PUT , contractArguments , ID_OBJECT_PUT_MUTABLE , functionArguments );
889+
890+ // Assert
891+ try (Scanner scanner = storage .scan (scan )) {
892+ List <Result > results = scanner .all ();
893+ assertThat (results ).hasSize (1 );
894+ assertThat (results .get (0 ).getText (SOME_COLUMN_NAME_1 )).isEqualTo (SOME_OBJECT_ID );
895+ assertThat (results .get (0 ).getText (SOME_COLUMN_NAME_2 )).isEqualTo (SOME_VERSION_ID_0 );
896+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_3 )).isTrue ();
897+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_4 )).isTrue ();
898+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_BOOLEAN )).isTrue ();
899+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_BIGINT )).isTrue ();
900+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_FLOAT )).isTrue ();
901+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_DOUBLE )).isTrue ();
902+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_TEXT )).isTrue ();
903+ assertThat (results .get (0 ).isNull (SOME_COLUMN_NAME_BLOB )).isTrue ();
781904 } catch (IOException e ) {
782905 throw new RuntimeException (e );
783906 }
@@ -800,7 +923,9 @@ public void putObject_FunctionArgumentsGiven_ShouldPutRecordToFunctionTable()
800923 .put (TABLE , "foo" )
801924 .set (
802925 PARTITION_KEY ,
803- mapper .createArrayNode ().add (createColumn (SOME_COLUMN_NAME_1 , SOME_OBJECT_ID )));
926+ mapper
927+ .createArrayNode ()
928+ .add (createColumn (TextColumn .of (SOME_COLUMN_NAME_1 , SOME_OBJECT_ID ))));
804929
805930 // Act Assert
806931 assertThatThrownBy (
@@ -832,8 +957,8 @@ public void putObject_FunctionArgumentsGiven_ShouldPutRecordToFunctionTable()
832957 .put (OBJECT_ID , SOME_OBJECT_ID )
833958 .put (HASH_VALUE , SOME_HASH_VALUE_1 )
834959 .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 );
960+ JsonNode functionArguments0 = createFunctionArguments (SOME_OBJECT_ID , SOME_VERSION_ID_0 , 0 );
961+ JsonNode functionArguments1 = createFunctionArguments (SOME_OBJECT_ID , SOME_VERSION_ID_0 , 1 );
837962 Put put =
838963 Put .newBuilder ()
839964 .namespace (SOME_FUNCTION_NAMESPACE )
0 commit comments