Skip to content

Commit

Permalink
Merge pull request OSGeo#11169 from rouault/pg_FindFieldIndex
Browse files Browse the repository at this point in the history
 PG: implement OGRLayer::FindFieldIndex()
  • Loading branch information
rouault authored Oct 30, 2024
2 parents c8caae8 + 0c00065 commit fa27996
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 0 deletions.
21 changes: 21 additions & 0 deletions apps/ogr2ogr_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5391,10 +5391,31 @@ SetupTargetLayer::Setup(OGRLayer *poSrcLayer, const char *pszNewLayerName,
if (iDstField >= 0)
anMap[iField] = iDstField;
else
{
if (m_bExactFieldNameMatch)
{
const int iDstFieldCandidate = poDstLayer->FindFieldIndex(
poSrcFieldDefn->GetNameRef(), false);
if (iDstFieldCandidate >= 0)
{
CPLError(CE_Warning, CPLE_AppDefined,
"Source field '%s' could have been identified "
"with existing field '%s' of destination "
"layer '%s' if the -relaxedFieldNameMatch "
"option had been specified.",
poSrcFieldDefn->GetNameRef(),
poDstLayer->GetLayerDefn()
->GetFieldDefn(iDstFieldCandidate)
->GetNameRef(),
poDstLayer->GetName());
}
}

CPLDebug(
"GDALVectorTranslate",
"Skipping field '%s' not found in destination layer '%s'.",
poSrcFieldDefn->GetNameRef(), poDstLayer->GetName());
}
}
}

Expand Down
38 changes: 38 additions & 0 deletions autotest/ogr/ogr_pg.py
Original file line number Diff line number Diff line change
Expand Up @@ -6231,3 +6231,41 @@ def test_ogr_pg_empty_search_path(pg_ds):

finally:
ds.ExecuteSQL(f"ALTER ROLE {current_user} SET search_path = {old_search_path}")


###############################################################################
# Test appending to a layer where a field name was truncated to 63 characters.


@only_without_postgis
@gdaltest.enable_exceptions()
def test_ogr_pg_findfield(pg_ds):

src_ds = ogr.GetDriverByName("Memory").CreateDataSource("")
src_lyr = src_ds.CreateLayer("test_very_long_field_name")
src_lyr.CreateField(
ogr.FieldDefn(
"veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeryyyyyyyyyyyyyyyyyyyyyyloooooooooooooong"
)
)
f = ogr.Feature(src_lyr.GetLayerDefn())
f.SetField(0, "foo")
src_lyr.CreateFeature(f)

with gdal.quiet_errors():
gdal.VectorTranslate(pg_ds.GetDescription(), src_ds)

with gdal.quiet_errors():
gdal.VectorTranslate(pg_ds.GetDescription(), src_ds, accessMode="append")

lyr = pg_ds.GetLayerByName("test_very_long_field_name")
assert [f.GetField(0) for f in lyr] == ["foo", None]

with gdal.quiet_errors():
gdal.VectorTranslate(
pg_ds.GetDescription(),
src_ds,
accessMode="append",
relaxedFieldNameMatch=True,
)
assert [f.GetField(0) for f in lyr] == ["foo", None, "foo"]
2 changes: 2 additions & 0 deletions ogr/ogrsf_frmts/pg/ogr_pg.h
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,8 @@ class OGRPGTableLayer final : public OGRPGLayer
GDALProgressFunc pfnProgress,
void *pProgressData) override;

int FindFieldIndex(const char *pszFieldName, int bExactMatch) override;

// follow methods are not base class overrides
void SetLaunderFlag(int bFlag)
{
Expand Down
21 changes: 21 additions & 0 deletions ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4034,4 +4034,25 @@ OGRGeometryTypeCounter *OGRPGTableLayer::GetGeometryTypes(
return pasRet;
}

/************************************************************************/
/* FindFieldIndex() */
/************************************************************************/

int OGRPGTableLayer::FindFieldIndex(const char *pszFieldName, int bExactMatch)
{
const auto poLayerDefn = GetLayerDefn();
int iField = poLayerDefn->GetFieldIndex(pszFieldName);

if (!bExactMatch && iField < 0 && bLaunderColumnNames)
{
CPLErrorStateBackuper oErrorStateBackuper(CPLQuietErrorHandler);
char *pszSafeName =
OGRPGCommonLaunderName(pszFieldName, "PG", m_bUTF8ToASCII);
iField = poLayerDefn->GetFieldIndex(pszSafeName);
CPLFree(pszSafeName);
}

return iField;
}

#undef PQexec
5 changes: 5 additions & 0 deletions swig/include/python/gdal_python.i
Original file line number Diff line number Diff line change
Expand Up @@ -3051,6 +3051,7 @@ def VectorTranslateOptions(options=None, format=None,
coordinateOperation=None,
SQLStatement=None, SQLDialect=None, where=None, selectFields=None,
addFields=False,
relaxedFieldNameMatch=False,
forceNullable=False,
emptyStrAsNull=False,
spatFilter=None, spatSRS=None,
Expand Down Expand Up @@ -3117,6 +3118,8 @@ def VectorTranslateOptions(options=None, format=None,
addFields:
whether to add new fields found in source layers (to be used with
accessMode == 'append' or 'upsert')
relaxedFieldNameMatch:
Do field name matching between source and existing target layer in a more relaxed way if the target driver has an implementation for it.
forceNullable:
whether to drop NOT NULL constraints on newly created fields
emptyStrAsNull:
Expand Down Expand Up @@ -3263,6 +3266,8 @@ def VectorTranslateOptions(options=None, format=None,
raise Exception('unhandled accessMode')
if addFields:
new_options += ['-addfields']
if relaxedFieldNameMatch:
new_options += ['-relaxedFieldNameMatch']
if forceNullable:
new_options += ['-forceNullable']
if emptyStrAsNull:
Expand Down

0 comments on commit fa27996

Please sign in to comment.