@@ -649,6 +649,66 @@ static GglError notify_nested_key(GglList *key_path, GglObjVec key_ids) {
649649 return return_err ;
650650}
651651
652+ GglError ggconfig_write_empty_map (GglList * key_path ) {
653+ if (config_initialized == false) {
654+ GGL_LOGE ("Database not initialized" );
655+ return GGL_ERR_FAILURE ;
656+ }
657+
658+ sqlite3_exec (config_database , "BEGIN TRANSACTION" , NULL , NULL , NULL );
659+ GGL_LOGT (
660+ "Starting transaction to write an empty map to key %s" ,
661+ print_key_path (key_path )
662+ );
663+
664+ GglObject ids_array [GGL_MAX_OBJECT_DEPTH ];
665+ GglObjVec ids = { .list = { .items = ids_array , .len = 0 },
666+ .capacity = GGL_MAX_OBJECT_DEPTH };
667+ int64_t last_key_id ;
668+ GglError err = get_key_ids (key_path , & ids );
669+ if (err == GGL_ERR_NOENTRY ) {
670+ ids .list .len = 0 ; // Reset the ids vector to be populated fresh
671+ err = create_key_path (key_path , & ids );
672+ if (err != GGL_ERR_OK ) {
673+ sqlite3_exec (config_database , "ROLLBACK" , NULL , NULL , NULL );
674+ return err ;
675+ }
676+ sqlite3_exec (config_database , "END TRANSACTION" , NULL , NULL , NULL );
677+ return GGL_ERR_OK ;
678+ }
679+ if (err != GGL_ERR_OK ) {
680+ GGL_LOGE (
681+ "Failed to get key ids for key path %s with error %s" ,
682+ print_key_path (key_path ),
683+ ggl_strerror (err )
684+ );
685+ sqlite3_exec (config_database , "ROLLBACK" , NULL , NULL , NULL );
686+ return err ;
687+ }
688+
689+ last_key_id = ids .list .items [ids .list .len - 1 ].i64 ;
690+
691+ bool value_is_present ;
692+ err = value_is_present_for_key (last_key_id , & value_is_present );
693+ if (err != GGL_ERR_OK ) {
694+ sqlite3_exec (config_database , "ROLLBACK" , NULL , NULL , NULL );
695+ return err ;
696+ }
697+ if (value_is_present ) {
698+ GGL_LOGW (
699+ "Value already present for key %s with id %" PRId64
700+ ", so an empty map can not be merged. Failing request." ,
701+ print_key_path (key_path ),
702+ last_key_id
703+ );
704+ sqlite3_exec (config_database , "ROLLBACK" , NULL , NULL , NULL );
705+ return GGL_ERR_FAILURE ;
706+ }
707+
708+ sqlite3_exec (config_database , "END TRANSACTION" , NULL , NULL , NULL );
709+ return GGL_ERR_OK ;
710+ }
711+
652712GglError ggconfig_write_value_at_key (
653713 GglList * key_path , GglBuffer * value , int64_t timestamp
654714) {
@@ -729,8 +789,20 @@ GglError ggconfig_write_value_at_key(
729789 return GGL_ERR_FAILURE ;
730790 }
731791
732- // we now know that the key already exists and does not have a child.
733- // Therefore, it stores a value currently.
792+ bool value_is_present ;
793+ err = value_is_present_for_key (last_key_id , & value_is_present );
794+ if (err != GGL_ERR_OK ) {
795+ return err ;
796+ }
797+ if (!value_is_present ) {
798+ GGL_LOGW (
799+ "Key %s with id %" PRId64 " is an empty map, so it can not have a "
800+ "value written to it. Failing request." ,
801+ print_key_path (key_path ),
802+ last_key_id
803+ );
804+ return GGL_ERR_FAILURE ;
805+ }
734806
735807 int64_t existing_timestamp ;
736808 err = value_get_timestamp (last_key_id , & existing_timestamp );
@@ -859,15 +931,17 @@ static GglError read_key_recursive(
859931 while (sqlite3_step (read_children_stmt ) == SQLITE_ROW ) {
860932 children_count ++ ;
861933 }
862- if (children_count == 0 ) {
863- GGL_LOGE ("no value or children keys found for key id %" PRId64 , key_id );
864- return GGL_ERR_FAILURE ;
865- }
866- GGL_LOGD (
934+ GGL_LOGT (
867935 "the number of children keys for key id %" PRId64 " is %zd" ,
868936 key_id ,
869937 children_count
870938 );
939+ if (children_count == 0 ) {
940+ value -> type = GGL_TYPE_MAP ;
941+ value -> map .len = 0 ;
942+ GGL_LOGT ("value read: empty map for key id %" PRId64 , key_id );
943+ return GGL_ERR_OK ;
944+ }
871945
872946 // create the kvs for the children
873947 GglKV * kv_buffer = GGL_ALLOCN (alloc , GglKV , children_count );
0 commit comments