@@ -771,6 +771,26 @@ cdef apply_geometry_filter(OGRLayerH ogr_layer, wkb):
771771 OGR_G_DestroyGeometry(ogr_geometry)
772772
773773
774+ cdef apply_skip_features(OGRLayerH ogr_layer, int skip_features):
775+ """ Applies skip_features to layer.
776+
777+ Parameters
778+ ----------
779+ ogr_layer : pointer to open OGR layer
780+ wskip_features : int
781+ """
782+ err = OGR_L_SetNextByIndex(ogr_layer, skip_features)
783+ # GDAL can raise an error (depending on the format) for out-of-bound index,
784+ # but `validate_feature_range()` should ensure we only pass a valid number
785+ if err != OGRERR_NONE:
786+ try :
787+ check_last_error()
788+ except CPLE_BaseError as exc:
789+ raise ValueError (str (exc))
790+
791+ raise ValueError (f" Applying {skip_features=} raised an error" )
792+
793+
774794cdef validate_feature_range(
775795 OGRLayerH ogr_layer, int skip_features = 0 , int max_features = 0
776796):
@@ -793,9 +813,9 @@ cdef validate_feature_range(
793813 return 0 , 0
794814
795815 if skip_features >= feature_count:
796- skip_features = feature_count
816+ return 0 , 0
797817
798- elif max_features == 0 :
818+ if max_features == 0 :
799819 num_features = feature_count - skip_features
800820
801821 elif max_features > feature_count:
@@ -973,7 +993,7 @@ cdef get_features(
973993 OGR_L_ResetReading(ogr_layer)
974994
975995 if skip_features > 0 :
976- OGR_L_SetNextByIndex (ogr_layer, skip_features)
996+ apply_skip_features (ogr_layer, skip_features)
977997
978998 if return_fids:
979999 fid_data = np.empty(shape = (num_features), dtype = np.int64)
@@ -1148,7 +1168,7 @@ cdef get_bounds(OGRLayerH ogr_layer, int skip_features, int num_features):
11481168 OGR_L_ResetReading(ogr_layer)
11491169
11501170 if skip_features > 0 :
1151- OGR_L_SetNextByIndex (ogr_layer, skip_features)
1171+ apply_skip_features (ogr_layer, skip_features)
11521172
11531173 fid_data = np.empty(shape = (num_features), dtype = np.int64)
11541174 fid_view = fid_data[:]
@@ -1668,6 +1688,13 @@ def ogr_open_arrow(
16681688 elif mask is not None :
16691689 apply_geometry_filter(ogr_layer, mask)
16701690
1691+ # Limit feature range to available range (cannot use logic of
1692+ # `validate_feature_range` because max_features is not supported)
1693+ if skip_features > 0 :
1694+ feature_count = get_feature_count(ogr_layer, 1 )
1695+ if skip_features >= feature_count:
1696+ skip_features = feature_count
1697+
16711698 # Limit to specified columns
16721699 if ignored_fields:
16731700 for field in ignored_fields:
@@ -1704,9 +1731,11 @@ def ogr_open_arrow(
17041731 if not OGR_L_GetArrowStream(ogr_layer, stream, options):
17051732 raise RuntimeError (" Failed to open ArrowArrayStream from Layer" )
17061733
1707- if skip_features:
1734+ if skip_features > 0 :
17081735 # only supported for GDAL >= 3.8.0; have to do this after getting
17091736 # the Arrow stream
1737+ # use `OGR_L_SetNextByIndex` directly and not `apply_skip_features`
1738+ # to ignore errors in case skip_features == feature_count
17101739 OGR_L_SetNextByIndex(ogr_layer, skip_features)
17111740
17121741 if use_pyarrow:
0 commit comments