@@ -38,11 +38,13 @@ class test_buffer_t
3838
3939 size_t add_relation (
4040 osmid_t rid,
41- std::initializer_list<osmium::builder::attr::member_type> members)
41+ std::initializer_list<osmium::builder::attr::member_type> members,
42+ std::initializer_list<std::pair<char const *, char const *>> tags)
4243 {
4344 using namespace osmium ::builder::attr;
4445 return osmium::builder::add_relation (
45- buf, _id (rid), _members (members.begin (), members.end ()));
46+ buf, _id (rid), _members (members.begin (), members.end ()),
47+ _tags (tags));
4648 }
4749
4850 size_t add_nodes (idlist_t const &ids)
@@ -77,9 +79,10 @@ class test_buffer_t
7779
7880 osmium::Relation &add_relation_and_get (
7981 osmid_t rid,
80- std::initializer_list<osmium::builder::attr::member_type> members)
82+ std::initializer_list<osmium::builder::attr::member_type> members,
83+ std::initializer_list<std::pair<char const *, char const *>> tags = {})
8184 {
82- return get<osmium::Relation>(add_relation (rid, members));
85+ return get<osmium::Relation>(add_relation (rid, members, tags ));
8386 }
8487
8588 osmium::WayNodeList &add_nodes_and_get (idlist_t const &nodes)
@@ -719,3 +722,260 @@ TEMPLATE_TEST_CASE("middle: add way with attributes", "", options_slim_default,
719722 mid->commit ();
720723 }
721724}
725+
726+ /* *
727+ * Check that the relation is in the mid with the right attributes and tags.
728+ * Does not check members.
729+ */
730+ static void check_relation (std::shared_ptr<middle_pgsql_t > const &mid,
731+ osmium::Relation const &orig_relation)
732+ {
733+ auto const mid_q = mid->get_query_instance ();
734+
735+ osmium::memory::Buffer outbuf{4096 , osmium::memory::Buffer::auto_grow::yes};
736+ REQUIRE (mid_q->relations_get (orig_relation.id (), outbuf));
737+ auto const &relation = outbuf.get <osmium::Relation>(0 );
738+
739+ osmium::CRC<osmium::CRC_zlib> orig_relation_crc;
740+ orig_relation_crc.update (orig_relation);
741+
742+ osmium::CRC<osmium::CRC_zlib> test_relation_crc;
743+ test_relation_crc.update (relation);
744+
745+ REQUIRE (orig_relation_crc ().checksum () == test_relation_crc ().checksum ());
746+ }
747+
748+ // / Return true if the relation with the specified id is not in the mid
749+ static bool no_relation (std::shared_ptr<middle_pgsql_t > const &mid, osmid_t id)
750+ {
751+ auto const mid_q = mid->get_query_instance ();
752+ osmium::memory::Buffer outbuf{4096 , osmium::memory::Buffer::auto_grow::yes};
753+ return !mid_q->relations_get (id, outbuf);
754+ }
755+
756+ TEMPLATE_TEST_CASE (" middle: add, delete and update relation" , " " ,
757+ options_slim_default, options_slim_dense_cache,
758+ options_flat_node_cache)
759+ {
760+ options_t options = TestType::options (db);
761+
762+ testing::cleanup::file_t flatnode_cleaner{
763+ options.flat_node_file .get_value_or (" " )};
764+
765+ // create some relations we'll use for the tests
766+ test_buffer_t buffer;
767+ using otype = osmium::item_type;
768+ auto const &relation30 = buffer.add_relation_and_get (
769+ 30 , {{otype::way, 10 , " outer" }, {otype::way, 11 , " inner" }},
770+ {{" type" , " multipolygon" }, {" name" , " Penguin Park" }});
771+
772+ auto const &relation31 =
773+ buffer.add_relation_and_get (31 , {{otype::node, 10 , " " }});
774+
775+ auto const &relation32 = buffer.add_relation_and_get (
776+ 32 , {{otype::relation, 39 , " " }}, {{" type" , " site" }});
777+
778+ auto const &relation30a = buffer.add_relation_and_get (
779+ 30 , {{otype::way, 10 , " outer" }, {otype::way, 11 , " outer" }},
780+ {{" type" , " multipolygon" }, {" name" , " Pigeon Park" }});
781+
782+ // Set up middle in "create" mode to get a cleanly initialized database and
783+ // add some relations. Does this in its own scope so that the mid is closed
784+ // properly.
785+ {
786+ auto mid = std::make_shared<middle_pgsql_t >(&options);
787+ mid->start ();
788+
789+ mid->relations_set (relation30);
790+ mid->relations_set (relation31);
791+ mid->flush ();
792+
793+ check_relation (mid, relation30);
794+ check_relation (mid, relation31);
795+
796+ mid->commit ();
797+ }
798+
799+ // From now on use append mode to not destroy the data we just added.
800+ options.append = true ;
801+
802+ SECTION (" Check that added relations are there and no others" )
803+ {
804+ auto mid = std::make_shared<middle_pgsql_t >(&options);
805+ mid->start ();
806+
807+ REQUIRE (no_relation (mid, 5 ));
808+ check_relation (mid, relation30);
809+ check_relation (mid, relation31);
810+ REQUIRE (no_relation (mid, 32 ));
811+
812+ mid->commit ();
813+ }
814+
815+ SECTION (" Delete existing and non-existing relation" )
816+ {
817+ {
818+ auto mid = std::make_shared<middle_pgsql_t >(&options);
819+ mid->start ();
820+
821+ mid->relations_delete (5 );
822+ mid->relations_delete (30 );
823+ mid->relations_delete (42 );
824+ mid->flush ();
825+
826+ REQUIRE (no_relation (mid, 5 ));
827+ REQUIRE (no_relation (mid, 30 ));
828+ check_relation (mid, relation31);
829+ REQUIRE (no_relation (mid, 42 ));
830+
831+ mid->commit ();
832+ }
833+ {
834+ // Check with a new mid
835+ auto mid = std::make_shared<middle_pgsql_t >(&options);
836+ mid->start ();
837+
838+ REQUIRE (no_relation (mid, 5 ));
839+ REQUIRE (no_relation (mid, 30 ));
840+ check_relation (mid, relation31);
841+ REQUIRE (no_relation (mid, 42 ));
842+
843+ mid->commit ();
844+ }
845+ }
846+
847+ SECTION (
848+ " Change (delete and set) existing relation and non-existing relation" )
849+ {
850+ {
851+ auto mid = std::make_shared<middle_pgsql_t >(&options);
852+ mid->start ();
853+
854+ mid->relations_delete (30 );
855+ mid->relations_set (relation30a);
856+ mid->relations_delete (32 );
857+ mid->relations_set (relation32);
858+ mid->flush ();
859+
860+ REQUIRE (no_relation (mid, 5 ));
861+ check_relation (mid, relation30a);
862+ check_relation (mid, relation31);
863+ check_relation (mid, relation32);
864+ REQUIRE (no_relation (mid, 42 ));
865+
866+ mid->commit ();
867+ }
868+ {
869+ // Check with a new mid
870+ auto mid = std::make_shared<middle_pgsql_t >(&options);
871+ mid->start ();
872+
873+ REQUIRE (no_relation (mid, 5 ));
874+ check_relation (mid, relation30a);
875+ check_relation (mid, relation31);
876+ check_relation (mid, relation32);
877+ REQUIRE (no_relation (mid, 42 ));
878+
879+ mid->commit ();
880+ }
881+ }
882+
883+ SECTION (" Add new relation" )
884+ {
885+ {
886+ auto mid = std::make_shared<middle_pgsql_t >(&options);
887+ mid->start ();
888+
889+ mid->relations_set (relation32);
890+ mid->flush ();
891+
892+ REQUIRE (no_relation (mid, 5 ));
893+ check_relation (mid, relation30);
894+ check_relation (mid, relation31);
895+ check_relation (mid, relation32);
896+ REQUIRE (no_relation (mid, 42 ));
897+
898+ mid->commit ();
899+ }
900+ {
901+ // Check with a new mid
902+ auto mid = std::make_shared<middle_pgsql_t >(&options);
903+ mid->start ();
904+
905+ REQUIRE (no_relation (mid, 5 ));
906+ check_relation (mid, relation30);
907+ check_relation (mid, relation31);
908+ check_relation (mid, relation32);
909+ REQUIRE (no_relation (mid, 42 ));
910+
911+ mid->commit ();
912+ }
913+ }
914+ }
915+
916+ TEMPLATE_TEST_CASE (" middle: add relation with attributes" , " " ,
917+ options_slim_default, options_slim_dense_cache,
918+ options_flat_node_cache)
919+ {
920+ options_t options = TestType::options (db);
921+
922+ SECTION (" with attributes" ) { options.extra_attributes = true ; }
923+ SECTION (" no attributes" ) { options.extra_attributes = false ; }
924+
925+ testing::cleanup::file_t flatnode_cleaner{
926+ options.flat_node_file .get_value_or (" " )};
927+
928+ // create some relations we'll use for the tests
929+ test_buffer_t buffer;
930+ using otype = osmium::item_type;
931+ auto &relation30 = buffer.add_relation_and_get (
932+ 30 , {{otype::way, 10 , " outer" }, {otype::way, 11 , " inner" }},
933+ {{" type" , " multipolygon" }, {" name" , " Penguin Park" }});
934+ relation30.set_version (123 );
935+ relation30.set_timestamp (1234567890 );
936+ relation30.set_changeset (456 );
937+ relation30.set_uid (789 );
938+
939+ // the same relation but with default attributes
940+ auto &relation30_no_attr = buffer.add_relation_and_get (
941+ 30 , {{otype::way, 10 , " outer" }, {otype::way, 11 , " inner" }},
942+ {{" type" , " multipolygon" }, {" name" , " Penguin Park" }});
943+
944+ // the same relation but with attributes in tags
945+ // the order of the tags is important here
946+ auto &relation30_attr_tags = buffer.add_relation_and_get (
947+ 30 , {{otype::way, 10 , " outer" }, {otype::way, 11 , " inner" }},
948+ {{" type" , " multipolygon" },
949+ {" name" , " Penguin Park" },
950+ {" osm_user" , " " },
951+ {" osm_uid" , " 789" },
952+ {" osm_version" , " 123" },
953+ {" osm_timestamp" , " 2009-02-13T23:31:30Z" },
954+ {" osm_changeset" , " 456" }});
955+
956+ {
957+ auto mid = std::make_shared<middle_pgsql_t >(&options);
958+ mid->start ();
959+
960+ mid->relations_set (relation30);
961+ mid->flush ();
962+
963+ check_relation (mid, options.extra_attributes ? relation30_attr_tags
964+ : relation30_no_attr);
965+
966+ mid->commit ();
967+ }
968+
969+ // From now on use append mode to not destroy the data we just added.
970+ options.append = true ;
971+
972+ {
973+ auto mid = std::make_shared<middle_pgsql_t >(&options);
974+ mid->start ();
975+
976+ check_relation (mid, options.extra_attributes ? relation30_attr_tags
977+ : relation30_no_attr);
978+
979+ mid->commit ();
980+ }
981+ }
0 commit comments