Skip to content

Commit

Permalink
[gpkg] Ensure that mapping tables are inserted into gpkg_contents
Browse files Browse the repository at this point in the history
Fixes auto-created relationship mapping tables cannot be read
from gpkg
  • Loading branch information
nyalldawson authored and github-actions[bot] committed Feb 21, 2024
1 parent 1f350ba commit 63c1744
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 0 deletions.
10 changes: 10 additions & 0 deletions autotest/ogr/ogr_gpkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -7203,6 +7203,16 @@ def get_query_row_count(query):
== 1
)

# validate mapping table was created
assert get_query_row_count("SELECT * FROM 'origin_table_dest_table'") == 0
# validate mapping table is present in gpkg_contents
assert (
get_query_row_count(
"SELECT * FROM gpkg_contents WHERE table_name='origin_table_dest_table' AND data_type='attributes'"
)
== 1
)

lyr = ds.CreateLayer("origin_table2", geom_type=ogr.wkbNone)
fld_defn = ogr.FieldDefn("o_pkey", ogr.OFTInteger)
assert lyr.CreateField(fld_defn) == ogr.OGRERR_NONE
Expand Down
6 changes: 6 additions & 0 deletions doc/source/drivers/vector/gpkg.rst
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,12 @@ only be updated to change their base or related table fields, or the relationshi
table type. It is not permissible to change the base or related table itself, or the mapping
table details. If this is desired then a new relationship should be created instead.

Note that when a many-to-many relationship is created in a GeoPackage, GDAL will always
insert the mapping table into the gpkg_contents table. Formally this is not required
by the Related Tables Extension (instead, the table should only be listed in gpkgext_relations),
however failing to list the mapping table in gpkg_contents prevents it from being usable
in some other applications (e.g. ESRI software).

Dataset open options
--------------------

Expand Down
29 changes: 29 additions & 0 deletions ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9942,6 +9942,35 @@ bool GDALGeoPackageDataset::AddRelationship(
return false;
}

/*
* Strictly speaking we should NOT be inserting the mapping table into gpkg_contents.
* The related tables extension explicitly states that the mapping table should only be
* in the gpkgext_relations table and not in gpkg_contents. (See also discussion at
* https://github.com/opengeospatial/geopackage/issues/679).
*
* However, if we don't insert the mapping table into gpkg_contents then it is no longer
* visible to some clients (eg ESRI software only allows opening tables that are present
* in gpkg_contents). So we'll do this anyway, for maximum compatiblity and flexibility.
*
* More related discussion is at https://github.com/OSGeo/gdal/pull/9258
*/
pszSQL = sqlite3_mprintf(
"INSERT INTO gpkg_contents "
"(table_name,data_type,identifier,description,last_change,srs_id) "
"VALUES "
"('%q','attributes','%q','Mapping table for relationship between "
"%q and %q',%s,0)",
osMappingTableName.c_str(), /*table_name*/
osMappingTableName.c_str(), /*identifier*/
osLeftTableName.c_str(), /*description left table name*/
osRightTableName.c_str(), /*description right table name*/
GDALGeoPackageDataset::GetCurrentDateEscapedSQL().c_str());

// Note -- we explicitly ignore failures here, because hey, we aren't really
// supposed to be adding this table to gpkg_contents anyway!
(void)SQLCommand(hDB, pszSQL);
sqlite3_free(pszSQL);

pszSQL = sqlite3_mprintf(
"CREATE INDEX \"idx_%w_base_id\" ON \"%w\" (base_id);",
osMappingTableName.c_str(), osMappingTableName.c_str());
Expand Down

0 comments on commit 63c1744

Please sign in to comment.