gdal icon indicating copy to clipboard operation
gdal copied to clipboard

Python bindings: fix issues with None bounds for ogr.CreateRangeFieldDomain() and ogr.CreateRangeFieldDomainDateTime()

Open rouault opened this issue 6 months ago • 6 comments

Fixes #12564

rouault avatar Jun 15 '25 12:06 rouault

Coverage Status

coverage: 71.065% (+0.002%) from 71.063% when pulling 2d359f9befdf94a19ecac9b7919b42bc83af1ca3 on rouault:fix_12564 into c340e3766e42ef6cdd7345de0de3c3ad7d6632b1 on OSGeo:master.

coveralls avatar Jun 15 '25 13:06 coveralls

Thanks!

ctoney avatar Jun 15 '25 15:06 ctoney

BTW, there is possibly an issue with OpenFileGDB when adding a range domain with psMin or psMax as nullptr. I was making a Python reproducer when I ran into the issues with None bounds.

This succeeds in C++ with OpenFileGDB on a OFTDateTime field, with nullptr for psMax:

        OGRFieldDomainH hFldDom = nullptr;
        hFldDom = OGR_RangeFldDomain_Create(domain_name.c_str(),
                                            description.c_str(),
                                            eFieldType, eFieldSubType,
                                            min_is_null ? nullptr : &sMin,
                                            min_is_inclusive,
                                            max_is_null ? nullptr : &sMax,
                                            max_is_inclusive);

        if (hFldDom != nullptr) {
            OGR_FldDomain_SetSplitPolicy(hFldDom, eOFDSP);
            OGR_FldDomain_SetMergePolicy(hFldDom, eOFDMP);
            char *pszFailureReason = nullptr;
            ret = GDALDatasetAddFieldDomain(hDS, hFldDom, &pszFailureReason);
            if (pszFailureReason != nullptr) {
                Rcpp::Rcout << pszFailureReason << std::endl;
                VSIFree(pszFailureReason);
            }
            OGR_FldDomain_Destroy(hFldDom);
        }

The created domain can then be set successfully when adding a field:

// ...
        if (domain_name != "") {
            OGR_Fld_SetDomainName(hFieldDefn, domain_name.c_str());

// ...

        if (OGR_L_CreateField(hLayer, hFieldDefn, TRUE) == OGRERR_NONE)
            ret = true;

// ...

At that point, ogrinfo reports the domain name associated with the field. However, the field domain is not included in the list of names returned by GDALDatasetGetFieldDomainNames(), nor can it be retrieved with GDALDatasetGetFieldDomain().

Otherwise, all is fine for a domain when both min and max DateTimes are given in OGR_RangeFldDomain_Create().

Should we be able to create a DateTime range domain with a min date but no max date? I wasn't able to find a test case for that in autotest.

The Python reproducer would be as follows, but unconfirmed so far due to the None issue for max:

from osgeo import gdal
from osgeo import ogr

dsn = "dt_domains.gdb"

ds = gdal.GetDriverByName("OpenFileGDB").Create(dsn, 0, 0, 0, gdal.GDT_Unknown)

lyr = ds.CreateLayer("test", geom_type=ogr.wkbNone)

domain1 = ogr.CreateRangeFieldDomainDateTime(
    "datetime_range1",
    "datetime 2000-01-01 to 2100-01-01",
    "2000-01-01T00:00:00Z",
    True,
    "2100-01-01T00:00:00Z",
    True)

ds.AddFieldDomain(domain1)

fld_defn1 = ogr.FieldDefn("fld1", ogr.OFTDateTime)
fld_defn1.SetDomainName("datetime_range1")
lyr.CreateField(fld_defn1)

domain2 = ogr.CreateRangeFieldDomainDateTime(
    "datetime_range_inf_max",
    "datetime min 2000-01-01 no max",
    "2000-01-01T00:00:00Z",
    True,
    None,
    True)

ds.AddFieldDomain(domain2)

fld_defn2 = ogr.FieldDefn("fld2", ogr.OFTDateTime)
fld_defn2.SetDomainName("datetime_range_inf_max")
lyr.CreateField(fld_defn2)

ds = None

ds = ogr.Open(dsn)

### Should we get both domain names reported here?
ds.GetFieldDomainNames()

ds.GetFieldDomain("datetime_range_inf_max")  # None?

ds = None

ctoney avatar Jun 15 '25 18:06 ctoney

@nyalldawson Do you know if Esri ArcGIS Pro allows to create range domains with only the minimum or maximum value? My impression of the online doc is that both min and max are required, but couldn't find a very clear answer

rouault avatar Jun 15 '25 19:06 rouault

Do you know if Esri ArcGIS Pro allows to create range domains with only the minimum or maximum value?

I figured out that by trying with GDAL 3.10 with the FileGDB SDK. If trying to create a range domain without min or max, it emits an error. I've added a commit to the OpenFileGDB driver to refuse creating such domain.

rouault avatar Jun 16 '25 10:06 rouault

Thanks for confirming and the fast reply.

ctoney avatar Jun 16 '25 15:06 ctoney