Skip to content

Commit b626b39

Browse files
authored
MiraMonVector: Repeated field names/description improvements (#14517)
In a MiraMon vector layer, some fields are mandatory. For example, ID_GRAFIC is required for all layer types (points, arcs, and polygons), while other mandatory fields may exist depending on the specific layer type. A problem appeared when translating a MiraMon layer into another MiraMon layer, for example using ogr2ogr with an SQL query to select a subset of features. In these cases, if a field from the source layer had the same name as one of the mandatory fields, the source field was correctly renamed (for example, ID_GRAFIC became ID_GRAFIC2). However, when writing the metadata file (.rel) for the output layer, the renamed field information was lost and ID_GRAFIC was written twice. This issue has now been fixed with a simple rule: When a field name conflicts with one of the mandatory MiraMon fields, both the original field name and the renamed field name are preserved internally. The renamed field name is then correctly used when writing the metadata. Additionally, the field description is updated by appending " (previous)" to indicate its origin. This problem was discovered during MiraMon-to-MiraMon translations. From now on, these translations will correctly preserve field names and metadata consistency.
1 parent 609c185 commit b626b39

3 files changed

Lines changed: 133 additions & 9 deletions

File tree

autotest/ogr/ogr_miramon_vector.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,3 +1566,46 @@ def test_ogr_miramon_write_launder_layer_name(tmp_path):
15661566
match="Layer name 'not/allowed' laundered as 'not_allowed' for filename compatibility",
15671567
):
15681568
ds.CreateLayer("not/allowed", srs=srs, geom_type=ogr.wkbUnknown)
1569+
1570+
1571+
###############################################################################
1572+
1573+
1574+
def test_ogr_miramon_vector_sql_select_preserve_reserved_fields():
1575+
1576+
src_filename = "data/miramon/Polygons/SimplePolygons/SimplePolFile.pol"
1577+
1578+
import os
1579+
import tempfile
1580+
1581+
tmp_dir = tempfile.mkdtemp()
1582+
out_filename = os.path.join(tmp_dir, "selected.pol")
1583+
1584+
ds = ogr.Open(src_filename)
1585+
assert ds is not None
1586+
1587+
out_ds = gdal.VectorTranslate(
1588+
out_filename,
1589+
ds,
1590+
format="MiraMonVector",
1591+
SQLStatement="SELECT * FROM SimplePolFile WHERE ATT1 = 'C'",
1592+
)
1593+
1594+
assert out_ds is not None
1595+
1596+
out_ds = None
1597+
ds = None
1598+
1599+
rel_filename = out_filename[:-4] + "P.rel"
1600+
1601+
with open(rel_filename, "rt", encoding="latin1") as f:
1602+
rel_content = f.read()
1603+
1604+
assert rel_content.count("[TAULA_PRINCIPAL:ID_GRAFIC]") == 1
1605+
assert rel_content.count("[TAULA_PRINCIPAL:ID_GRAFIC2]") == 1
1606+
1607+
assert rel_content.count("[TAULA_PRINCIPAL:N_VERTEXS]") == 1
1608+
assert rel_content.count("[TAULA_PRINCIPAL:PERIMETRE]") == 1
1609+
assert rel_content.count("[TAULA_PRINCIPAL:AREA]") == 1
1610+
assert rel_content.count("[TAULA_PRINCIPAL:N_ARCS]") == 1
1611+
assert rel_content.count("[TAULA_PRINCIPAL:N_POLIG]") == 1

frmts/miramon_common/mm_gdal_driver_structs.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,15 @@ struct MiraMonRecord
355355
struct MiraMonDataBaseField
356356
{
357357
char pszFieldName[MM_MAX_LON_FIELD_NAME_DBF + 1];
358+
// A layer, when translated to MiraMon cannot have some
359+
// specific field names (ID_GRAFIC, for instance).
360+
// If pszFieldName is modified because of it
361+
// we need to keep it somewhere in order to write metadata.
362+
char pszFieldModifName[MM_MAX_LON_FIELD_NAME_DBF + 1];
358363
char pszFieldDescription[MM_MAX_BYTES_FIELD_DESC + 1];
364+
// In the case of a modified field name, we also need
365+
// to keep the description somewhere in order to write metadata.
366+
char pszFieldModifDescription[MM_MAX_BYTES_FIELD_DESC + 1];
359367
enum FieldType eFieldType; // See enum FieldType
360368
GUInt32 nFieldSize; // MM_MAX_BYTES_IN_A_FIELD_EXT as maximum
361369
GUInt32 nNumberOfDecimals; // MM_MAX_BYTES_IN_A_FIELD_EXT as maximum

ogr/ogrsf_frmts/miramon/mm_wrlayr.c

Lines changed: 82 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5615,21 +5615,50 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD)
56155615
// For each field of the databes
56165616
for (nIField = 0; nIField < hMMMD->pLayerDB->nNFields; nIField++)
56175617
{
5618-
VSIFPrintfL(pF, LineReturn "[%s:%s]" LineReturn,
5619-
SECTION_TAULA_PRINCIPAL,
5620-
hMMMD->pLayerDB->pFields[nIField].pszFieldName);
5618+
bool bModifiedFieldName = false;
5619+
if (*hMMMD->pLayerDB->pFields[nIField].pszFieldModifName != '\0')
5620+
bModifiedFieldName = true;
5621+
5622+
// If exists a modified name we need to document that one.
5623+
VSIFPrintfL(
5624+
pF, LineReturn "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5625+
bModifiedFieldName
5626+
? hMMMD->pLayerDB->pFields[nIField].pszFieldModifName
5627+
: hMMMD->pLayerDB->pFields[nIField].pszFieldName);
56215628

56225629
if (!MMIsEmptyString(
56235630
hMMMD->pLayerDB->pFields[nIField].pszFieldDescription) &&
56245631
!MMIsEmptyString(
56255632
hMMMD->pLayerDB->pFields[nIField].pszFieldName))
56265633
{
5627-
MMWrite_ANSI_MetadataKeyDescriptor(
5628-
hMMMD, pF,
5629-
hMMMD->pLayerDB->pFields[nIField].pszFieldDescription,
5630-
hMMMD->pLayerDB->pFields[nIField].pszFieldDescription,
5631-
hMMMD->pLayerDB->pFields[nIField].pszFieldDescription,
5632-
CPL_ENC_UTF8);
5634+
if (bModifiedFieldName)
5635+
{
5636+
MMWrite_ANSI_MetadataKeyDescriptor(
5637+
hMMMD, pF,
5638+
hMMMD->pLayerDB->pFields[nIField]
5639+
.pszFieldModifDescription,
5640+
hMMMD->pLayerDB->pFields[nIField]
5641+
.pszFieldModifDescription,
5642+
hMMMD->pLayerDB->pFields[nIField]
5643+
.pszFieldModifDescription,
5644+
CPL_ENC_UTF8);
5645+
}
5646+
else
5647+
{
5648+
MMWrite_ANSI_MetadataKeyDescriptor(
5649+
hMMMD, pF,
5650+
hMMMD->pLayerDB->pFields[nIField].pszFieldDescription,
5651+
hMMMD->pLayerDB->pFields[nIField].pszFieldDescription,
5652+
hMMMD->pLayerDB->pFields[nIField].pszFieldDescription,
5653+
CPL_ENC_UTF8);
5654+
}
5655+
}
5656+
5657+
if (bModifiedFieldName &&
5658+
EQUAL(szMMNomCampIdGraficDefecte,
5659+
hMMMD->pLayerDB->pFields[nIField].pszFieldName))
5660+
{
5661+
VSIFPrintfL(pF, "TractamentVariable=Ordinal" LineReturn);
56335662
}
56345663

56355664
// Exception in a particular case: "altura" is a catalan word that means
@@ -6068,6 +6097,50 @@ int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
60686097
MM_DuplicateFieldDBXP(pBD_XP->pField + nIField, &MMField);
60696098
MM_ModifyFieldNameAndDescriptorIfPresentBD_XP(
60706099
pBD_XP->pField + nIField, pBD_XP, FALSE, 0);
6100+
6101+
if (!EQUAL(pBD_XP->pField[nIField].FieldName,
6102+
hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6103+
.pszFieldName))
6104+
{
6105+
// We need to preserve the final given name to write
6106+
// metadata with the modified new name.
6107+
strcpy(hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6108+
.pszFieldModifName,
6109+
pBD_XP->pField[nIField].FieldName);
6110+
6111+
strcpy(
6112+
hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6113+
.pszFieldModifDescription,
6114+
pBD_XP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE]);
6115+
6116+
// In this case we are going to use also the modified description in metadata
6117+
switch (hMiraMonLayer->nMMLanguage)
6118+
{
6119+
case MM_CAT_LANGUAGE:
6120+
CPLStrlcat(
6121+
hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6122+
.pszFieldModifDescription,
6123+
" (previ)", MM_MAX_BYTES_FIELD_DESC + 1);
6124+
break;
6125+
case MM_SPA_LANGUAGE:
6126+
CPLStrlcat(
6127+
hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6128+
.pszFieldModifDescription,
6129+
" (previo)", MM_MAX_BYTES_FIELD_DESC + 1);
6130+
break;
6131+
default:
6132+
case MM_ENG_LANGUAGE:
6133+
CPLStrlcat(
6134+
hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6135+
.pszFieldModifDescription,
6136+
" (previous)", MM_MAX_BYTES_FIELD_DESC + 1);
6137+
break;
6138+
}
6139+
}
6140+
else
6141+
*hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6142+
.pszFieldModifName = '\0';
6143+
60716144
if (pBD_XP->pField[nIField].FieldType == 'F')
60726145
pBD_XP->pField[nIField].FieldType = 'N';
60736146
}

0 commit comments

Comments
 (0)