% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/gdalvector.R
\name{GDALVector-class}
\alias{GDALVector-class}
\alias{Rcpp_GDALVector}
\alias{Rcpp_GDALVector-class}
\alias{GDALVector}
\title{Class encapsulating a vector layer in a GDAL dataset}
\arguments{
\item{dsn}{Character string containing the data source name (DSN), usually a
filename or database connection string.}

\item{layer}{Character string containing the name of a layer within the
data source. May also be given as an SQL SELECT statement to be executed
against the data source, defining a layer as the result set.}

\item{read_only}{Logical scalar. \code{TRUE} to open the layer read-only (the
default), or \code{FALSE} to open with write access.}

\item{open_options}{Optional character vector of \code{NAME=VALUE} pairs
specifying dataset open options.}

\item{spatial_filter}{Optional character string containing a geometry in
Well Known Text (WKT) format which represents a spatial filter.}

\item{dialect}{Optional character string to control the statement dialect
when SQL is used to define the layer. By default, the OGR SQL engine will
be used, except for RDBMS drivers that will use their dedicated SQL engine,
unless \code{"OGRSQL"} is explicitly passed as the dialect. The \code{"SQLITE"}
dialect can also be used.}
}
\value{
An object of class \code{GDALVector}, which contains pointers to the
opened layer and the GDAL dataset that owns it. Class methods that operate
on the layer are described in Details, along with a set of writable fields
for per-object settings. Values may be assigned to the class fields as
needed during the lifetime of the object (i.e., by regular \code{<-} or
\code{=} assignment).
}
\description{
\code{GDALVector} provides an interface for accessing a vector layer in a GDAL
dataset and calling methods on the underlying \code{OGRLayer} object.
An object of class \code{GDALVector} persists an open connection to the dataset,
and exposes methods to:
\itemize{
\item retrieve layer information
\item set attribute and spatial filters
\item set a list of ignored or selected columns
\item traverse and read feature data by traditional row-based cursor, including
an analog of \code{DBI::dbFetch()}
\item read via column-oriented Arrow Array stream
\item write new features in a layer
\item edit/overwrite existing features
\item upsert
\item delete features
\item perform data manipulation within transactions.
}

\code{GDALVector} is a C++ class exposed directly to \R (via \code{RCPP_EXPOSED_CLASS}).
Fields and methods of the class are accessed using the \code{$} operator. \strong{Note
that all arguments to class methods are required and must be given in the
order documented.} Most \code{GDALVector} methods take zero or one argument, so
this is usually not an issue. Class constructors are the main exception.
Naming the arguments is optional but may be preferred for readability.
}
\section{Usage (see Details)}{


\if{html}{\out{<div class="sourceCode">}}\preformatted{## Constructors
# for single-layer file formats such as shapefile
lyr <- new(GDALVector, dsn)
# specifying the layer name, or SQL statement defining the layer
lyr <- new(GDALVector, dsn, layer)
# for update access
lyr <- new(GDALVector, dsn, layer, read_only = FALSE)
# using dataset open options
lyr <- new(GDALVector, dsn, layer, read_only, open_options)
# setting a spatial filter and/or specifying the SQL dialect
lyr <- new(GDALVector, dsn, layer, read_only, open_options, spatial_filter, dialect)

## Read/write fields (per-object settings)
lyr$defaultGeomColName
lyr$returnGeomAs
lyr$promoteToMulti
lyr$convertToLinear
lyr$wkbByteOrder
lyr$arrowStreamOptions
lyr$writeArrowBatchOptions
lyr$quiet
lyr$transactionsForce

## Methods
lyr$open(read_only)
lyr$isOpen()
lyr$isReadOnly()
lyr$getDsn()
lyr$getFileList()
lyr$info()
lyr$getDriverShortName()
lyr$getDriverLongName()

lyr$getName()
lyr$getFieldNames()
lyr$testCapability()
lyr$getFIDColumn()
lyr$getGeomType()
lyr$getGeometryColumn()
lyr$getSpatialRef()
lyr$bbox()
lyr$getLayerDefn()
lyr$getFieldDomain(domain_name)

lyr$setAttributeFilter(query)
lyr$getAttributeFilter()
lyr$setIgnoredFields(fields)
lyr$setSelectedFields(fields)
lyr$getIgnoredFields()

lyr$setSpatialFilter(wkt)
lyr$setSpatialFilterRect(bbox)
lyr$getSpatialFilter()
lyr$clearSpatialFilter()

lyr$getFeatureCount()
lyr$getNextFeature()
lyr$setNextByIndex(i)
lyr$getFeature(fid)
lyr$resetReading()
lyr$fetch(n)

lyr$getArrowStream()
lyr$releaseArrowStream()
lyr$writeArrowBatch(df)

lyr$setFeature(feature)
lyr$createFeature(feature)
lyr$batchCreateFeature(feature_set)
lyr$upsertFeature(feature)
lyr$getLastWriteFID()
lyr$deleteFeature(fid)
lyr$syncToDisk()

lyr$startTransaction()
lyr$commitTransaction()
lyr$rollbackTransaction()

lyr$getMetadata()
lyr$setMetadata(metadata)
lyr$getMetadataItem(mdi_name)

lyr$close()
}\if{html}{\out{</div>}}
}

\section{Details}{

\subsection{Constructors}{

\code{new(GDALVector, dsn)}\cr
The first layer by index is assumed if the \code{layer} argument is omitted, so
this form of the constructor might be used for single-layer formats like
shapefile.

\code{new(GDALVector, dsn, layer)}\cr
Constructor specifying the name of a layer to open. The \code{layer} argument
may also be given as an SQL SELECT statement to define a layer as the result
set.

\code{new(GDALVector, dsn, layer, read_only)}\cr
Constructor specifying read/write access (\code{read_only = TRUE|FALSE}).
The \code{layer} argument is required in this form of the constructor, but may be
given as empty string (\code{""}), in which case the first layer by index will be
assumed.

\code{new(GDALVector, dsn, layer, read_only, open_options)}\cr
Constructor specifying dataset open options as a character vector of
\code{NAME=VALUE} pairs.

\code{new(GDALVector, dsn, layer, read_only, open_options, spatial_filter, dialect))}\cr
Constructor to specify a spatial filter and/or SQL dialect. All arguments
are required in this form of the constructor, but \code{open_options} may be
\code{NULL}, and \code{spatial_filter} or \code{dialect} may be an empty string (\code{""}).
}

\subsection{Read/write fields}{

\code{$defaultGeomColName}\cr
Character string specifying a name to use for returned columns when the
geometry column name in the source layer is empty, like with shapefiles etc.
Defaults to \code{"geom"}.

\code{$returnGeomAs}\cr
Character string specifying the return format of feature geometries.
Must be one of \code{WKB} (the default), \code{WKB_ISO}, \code{WKT}, \code{WKT_ISO}, \code{BBOX}, or
\code{NONE}.
Using \code{WKB}/\code{WKT} exports as 99-402 extended dimension (Z) types for Point,
LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon and
GeometryCollection. For other geometry types, it is equivalent to using
\code{WKB_ISO}/\code{WKT_ISO} (see \url{https://libgeos.org/specifications/wkb/}).
Using \code{BBOX} exports as a list of numeric vectors, each of length 4 with
values \verb{xmin, ymin, xmax, ymax}. If an empty geometry is encountered these
values will be \code{NA_real_} in the corresponding location.
Using \code{NONE} will result in no geometry value being present in the feature
returned.

\code{$promoteToMulti}\cr
A logical value specifying whether to automatically promote geometries from
Polygon to MultiPolygon, Point to MultiPoint, or LineString to
MultiLineString during read operations (i.e., with methods
\code{$getFeature()}, \code{$getNextFeature()}, \code{$fetch()}).
Defaults to \code{FALSE}. Setting to \code{TRUE} may be useful when reading from
layers such as shapefiles that mix Polygons and MultiPolygons.

\code{$convertToLinear}\cr
A logical value specifying whether to convert non-linear geometry types into
linear geometry types by approximating them (i.e., during read operations
with methods \code{$getFeature()}, \code{$getNextFeature()},
\code{$fetch()}). Defaults to \code{FALSE}. If set to \code{TRUE}, handled conversions
are:
\itemize{
\item wkbCurvePolygon -> wkbPolygon
\item wkbCircularString -> wkbLineString
\item wkbCompoundCurve -> wkbLineString
\item wkbMultiSurface -> wkbMultiPolygon
\item wkbMultiCurve -> wkbMultiLineString
}

\code{$wkbByteOrder}\cr
Character string specifying the byte order for WKB geometries.
Must be either \code{LSB} (Least Significant Byte first, the default) or
\code{MSB} (Most Significant Byte first).

\code{$arrowStreamOptions}\cr
Character vector of \code{"NAME=VALUE"} pairs giving options used by the
\code{$getArrowStream()} method (see below). The available options may be
driver and GDAL version specific. Options available as of GDAL 3.8 are
listed below. For more information about options for Arrow stream, see
the GDAL API documentation for
\href{https://gdal.org/en/stable/api/vector_c_api.html#_CPPv420OGR_L_GetArrowStream9OGRLayerHP16ArrowArrayStreamPPc}{OGR_L_GetArrowStream()}.
\itemize{
\item \code{INCLUDE_FID=YES/NO}. Defaults to \code{YES}.
\item \code{MAX_FEATURES_IN_BATCH=integer}. Maximum number of features to retrieve in
an ArrowArray batch. Defaults to \code{65536}.
\item \verb{TIMEZONE=unknown/UTC/(+|:)HH:MM} or any other value supported by
Arrow (GDAL >= 3.8).
\item \code{GEOMETRY_METADATA_ENCODING=OGC/GEOARROW} (GDAL >= 3.8). The GDAL default is
\code{OGC} if not specified.
\item \code{GEOMETRY_ENCODING=WKB} (Arrow/Parquet drivers). To force a fallback to the
generic implementation when the native geometry encoding is not WKB.
Otherwise the geometry will be returned with its native Arrow encoding
(possibly using GeoArrow encoding).
}

\code{$writeArrowBatchOptions}\cr
Character vector of \code{"NAME=VALUE"} pairs giving options used by the
\code{$writeArrowBatch()} method (see below). The available options may be
driver and GDAL version specific. For more information, see the GDAL API
documentation for
\href{https://gdal.org/en/latest/api/vector_c_api.html#_CPPv421OGR_L_WriteArrowBatch9OGRLayerHPK11ArrowSchemaP10ArrowArray12CSLConstList}{OGR_L_WriteArrowBatch()}.
\itemize{
\item \code{FID=name}. Name of the FID column in the data frame. If not provided,
\code{GetFIDColumn()} is used to determine it. The column must be of type
\code{integer} or \code{integer64}.
\item \code{IF_FID_NOT_PRESERVED=NOTHING/ERROR/WARNING}. Action to perform when the
input FID is not preserved in the output layer. The default is \code{NOTHING}.
Setting it to \code{ERROR} will cause the function to error out. Setting it to
\code{WARNING} will cause the function to emit a warning but continue its
processing.
\item \code{IF_FIELD_NOT_PRESERVED=ERROR/WARNING}. (since GDAL 3.9) Action to perform
when the input field value is not preserved in the output layer. The default
is \code{WARNING}, which will cause the function to emit a warning but continue
its processing. Setting it to \code{ERROR} will cause the function to error out if
a lossy conversion is detected.
\item \code{GEOMETRY_NAME=name}. Name of the geometry column. If not provided,
\code{GetGeometryColumn()} is used. The corresponding data frame column must be
a list column containing \code{raw} vectors of WKB.
}

\code{$quiet}\cr
A logical value, \code{FALSE} by default. Set to \code{TRUE} to suppress various
messages and warnings.

\code{$transactionsForce}\cr
A logical value, \code{FALSE} by default. Affects the behavior of attempted
transactions on the layer (see the \code{$startTransaction()} method below).
By default, only "efficient" transactions will be attempted. Some drivers
may offer an emulation of transactions, but sometimes with significant
overhead, in which case the user must explicitly allow for such an
emulation by first setting \code{$transactionsForce <- TRUE}.
}

\subsection{Methods}{

\code{$open(read_only)}\cr
(Re-)opens the vector layer on the existing DSN. Use this method to
open a layer that has been closed using \code{$close()}. May be used to
re-open a layer with a different read/write access (\code{read_only} set to
\code{TRUE} or \code{FALSE}). The method will first close an open dataset, so it is
not required to call \code{$close()} explicitly in this case.
No return value, called for side effects.

\code{$isOpen()}\cr
Returns a \code{logical} value indicating whether the vector dataset is open.

\code{$isReadOnly()}\cr
Returns a logical value, \code{TRUE} if the vector dataset has read-only access
or \code{FALSE} if it is writable.

\code{$getDsn()}\cr
Returns a character string containing the \code{dsn} associated with this
\code{GDALVector} object (\code{dsn} originally used to open the layer).

\code{$getFileList()}\cr
Returns a character vector of files believed to be part of the data source.
If it returns an empty string (\code{""}) it means there is believed to be no
local file system files associated with the dataset (e.g., a virtual file
system). The returned filenames will normally be relative or absolute
paths depending on the path used to originally open the dataset.

\code{$info()}\cr
Prints information about the vector layer to the console (no
return value, called for that side effect only).
For non-SQL DSN/layer, calls \code{\link[=ogrinfo]{ogrinfo()}} passing the command options
\code{cl_arg = c("-so", "-nomd")}, and for layers open with a SQL statement,
calls \code{\link[=ogrinfo]{ogrinfo()}} passing the command options
\verb{cl_arg = c("-so", "-nomd", "-sql", <statement>)}.

\code{$getDriverShortName()}\cr
Returns the short name of the vector format driver.

\code{$getDriverLongName()}\cr
Returns the long name of the vector format driver.

\code{$getName()}\cr
Returns the layer name.

\code{$getFieldNames()}\cr
Returns a character vector of the layer's field names.

\code{$testCapability()}\cr
Tests whether the layer supports named capabilities based on the current
read/write access. Returns a list of capabilities with values \code{TRUE} or
\code{FALSE}. The returned list contains the following named elements:
\code{RandomRead}, \code{SequentialWrite}, \code{RandomWrite}, \code{UpsertFeature},
\code{FastSpatialFilter}, \code{FastFeatureCount}, \code{FastGetExtent},
\code{FastSetNextByIndex}, \code{FastGetArrowStream}, \code{FastWriteArrowBatch},
\code{CreateField}, \code{CreateGeomField}, \code{DeleteField}, \code{ReorderFields},
\code{AlterFieldDefn}, \code{AlterGeomFieldDefn}, \code{DeleteFeature}, \code{StringsAsUTF8},
\code{Transactions}, \code{CurveGeometries}.
Note that some layer capabilities are GDAL version dependent and may not
be listed if not supported by the GDAL version currently in use.
(See the GDAL documentation for
\href{https://gdal.org/en/stable/api/vector_c_api.html#_CPPv420OGR_L_TestCapability9OGRLayerHPKc}{\code{OGR_L_TestCapability()}}.)

\code{$getFIDColumn()}\cr
Returns the name of the underlying database column being used as the FID
column, or empty string (\code{""}) if not supported.

\code{$getGeomType()}\cr
Returns the well known name of the layer geometry type as character string.
For layers with multiple geometry fields, this method only returns the
geometry type of the first geometry column. For other columns, use
\code{$getLayerDefn()}. For layers without any geometry field, this method
returns \code{"NONE"}.

\code{$getGeometryColumn()}\cr
Returns he name of the underlying database column being used as the geometry
column, or an empty string (\code{""}) if not supported.
For layers with multiple geometry fields, this method only returns the
name of the first geometry column. For other columns, use method
\code{$getLayerDefn()}.

\code{$getSpatialRef()}\cr
Returns a WKT string containing the spatial reference system for this layer,
or empty string (\code{""}) if no spatial reference exists.

\code{$bbox()}\cr
Returns a numeric vector of length four containing the bounding box
for this layer (xmin, ymin, xmax, ymax). Note that \code{bForce = true} is set in
the underlying API call to \code{OGR_L_GetExtent()}, so the entire layer may be
scanned to compute a minimum bounding rectangle (see \code{FastGetExtent} in the
list returned by \code{$testCapability()}). Depending on the format driver,
a spatial filter may or may not be taken into account, so it is safer to
call \code{$bbox()} without setting a spatial filter.

\code{$getLayerDefn()}\cr
Returns a list containing the OGR feature class definition for this layer
(a.k.a. layer definition). The list contains zero or more attribute field
definitions, along with one or more geometry field definitions.
See \link{ogr_define} for details of the field and feature class definitions.

\code{$getFieldDomain(domain_name)}\cr
Returns a list containing the definition of the OGR field domain with the
passed \code{domain_name}, or \code{NULL} if \code{domain_name} is not found.
See \link{ogr_define} for specification of the list containing a field domain
definition.
Some formats support the use of field domains which describe the valid values
that can be stored in a given attribute field, e.g., coded values that are
present in a specified enumeration, values constrained to a specified
range, or values that must match a specified pattern.
See
\url{https://gdal.org/en/stable/user/vector_data_model.html#field-domains}.
Requires GDAL >= 3.3.

\code{$setAttributeFilter(query)}\cr
Sets an attribute query string to be used when fetching features via the
\code{$getNextFeature()} or \code{$fetch()} methods.
Only features for which \code{query} evaluates as true will be returned.
The query string should be in the format of an SQL WHERE clause, described
in the \href{https://gdal.org/en/stable/user/ogr_sql_dialect.html#where}{"WHERE"}
section of the OGR SQL dialect documentation (e.g.,
\code{"population > 1000000 and population < 5000000"}, where \code{population} is an
attribute in the layer).
In some cases (RDBMS backed drivers, SQLite, GeoPackage) the native
capabilities of the database may be used to to interpret the WHERE clause,
in which case the capabilities will be broader than those of OGR SQL.
Note that installing a query string will generally result in resetting the
current reading position (as with \code{$resetReading()} described below).
The \code{query} parameter may be set to empty string (\code{""}) to clear the current
attribute filter.

\code{$getAttributeFilter()}\cr
Returns the attribute query string currently in use, or empty string (\code{""})
if an attribute filter is not set.

\code{$setIgnoredFields(fields)}\cr
Set which fields can be omitted when retrieving features from the layer.
The \code{fields} argument is a character vector of field names. Passing an
empty string (\code{""}) for \code{fields} will reset to no ignored fields.
If the format driver supports this functionality (testable using
\code{$testCapability()$IgnoreFields}), it will not fetch the specified
fields in subsequent calls to \code{$getFeature()} / \code{$getNextFeature()}
/ \code{$fetch()}, and thus save some processing time and/or bandwidth.
Besides field names of the layer, the following special fields can be passed:
\code{"OGR_GEOMETRY"} to ignore geometry and \code{"OGR_STYLE"} to ignore layer style.
By default, no fields are ignored. Note that fields that are used in an
attribute filter should generally not be set as ignored fields, as most
drivers (such as those relying on the OGR SQL engine) will be unable to
correctly evaluate the attribute filter. No return value, called for side
effects.

\code{$setSelectedFields(fields)}\cr
Set which fields will be included when retrieving features from the layer.
The \code{fields} argument is a character vector of field names. Passing an
empty string (\code{""}) for \code{fields} will reset to no ignored fields.
See the \code{$setIgnoredFields()} method above for more information. The
data source must provide IgnoreFields capability in order to set selected
fields. Note that geometry fields, if desired, must be specified when setting
selected fields, either by including named geometry field(s) or the special
field \code{"OGR_GEOMETRY"} in the \code{fields} argument.
No return value, called for side effects.

\code{$getIgnoredFields()}\cr
Returns a character vector containing the list of currently ignored fields,
or an empty vector (\code{character(0)}) if no fields are currently set to
ignored (or if the format driver does not support ignored fields).

\code{$setSpatialFilter(wkt)}\cr
Sets a new spatial filter from a geometry in WKT format. This method sets
the geometry to be used as a spatial filter when fetching features via the
\code{$getNextFeature()} or \code{$fetch()} methods. Only features that
geometrically intersect the filter geometry will be returned. Currently this
test may be inaccurately implemented (depending on the vector format driver),
but it is guaranteed that all features whose envelope overlaps the envelope
of the spatial filter will be returned. This can result in more shapes being
returned that should strictly be the case.
\code{wkt} is a character string containing a WKT geometry in the same coordinate
system as the layer. An empty string (\code{""}) may be passed indicating that
the current spatial filter should be cleared, but no new one instituted.

\code{$setSpatialFilterRect(bbox)}\cr
Sets a new rectangular spatial filter. This method sets a rectangle to be
used as a spatial filter when fetching features via the
\code{$getNextFeature()} or \code{$fetch()} methods.
Only features that geometrically intersect the given rectangle will be
returned.
\code{bbox} is a numeric vector of length four containing xmin, ymin, xmax, ymax
in the same coordinate system as the layer as a whole (as returned by
\code{$getSpatialRef()}).

\code{$getSpatialFilter()}\cr
Returns the current spatial filter geometry as a WKT string, or empty string
(\code{""}) if a spatial filter is not set.

\code{$clearSpatialFilter()}\cr
Clears a spatial filter that was set with \code{$setSpatialFilterRect()}.
No return value, called for that side effect.

\code{$getFeatureCount()}\cr
Returns the number of features in the layer. For dynamic databases the count
may not be exact. This method forces a count in the underlying API call
(i.e., \code{bForce = TRUE} in the call to \code{OGR_L_GetFeatureCount()}). Note that
some vector drivers will actually scan the entire layer once to count
features. The \code{FastFeatureCount} element in the list returned by
the \code{$testCapability()} method can be checked if this might be a
concern.
The number of features returned takes into account the spatial and/or
attribute filters. Some driver implementations of this method may alter the
read cursor of the layer.

\code{$getNextFeature()}\cr
Fetch the next available feature from this layer. Only features matching the
current spatial and/or attribute filter (if defined) will be returned.
This method implements sequential access to the features of a layer.
The \code{$resetReading()} method can be used to start at the beginning
again.
Returns a list with the unique feature identifier (FID), the attribute and
geometry field names, and their values. The returned list carries the
\code{OGRFeature} class attribute with S3 methods for for \code{print()} and \code{plot()}.
\code{NULL} is returned if no more features are available.

\code{$setNextByIndex(i)}\cr
Moves the read cursor to feature \code{i} in the current result set
(with 0-based indexing).
This method allows positioning of a layer such that a call to
\code{$getNextFeature()} or \code{$fetch()} will read the requested
feature(s), where \code{i} is an absolute index into the current result set.
So, setting \code{i = 3} would mean the next feature read with
\code{$getNextFeature()} would have been the fourth feature read if
sequential reading took place from the beginning of the layer, including
accounting for spatial and attribute filters.
This method is not implemented efficiently by all vector format drivers. The
default implementation simply resets reading to the beginning and then calls
\code{GetNextFeature()} \code{i} times.
To determine if fast seeking is available on the current layer, check
the \code{FastSetNextByIndex} element in the list returned by the
\code{$testCapability()} method. No return value, called for side effect.

\code{$getFeature(fid)}\cr
Returns a feature by its identifier. The value of \code{fid} must be a numeric
value, optionally carrying the \code{bit64::integer64} class attribute.
Success or failure of this operation is unaffected by any spatial or
attribute filters that may be in effect.
The \code{RandomRead} element in the list returned by \code{$testCapability()} can
be checked to establish if this layer supports efficient random access
reading; however, the call should always work if the feature exists since a
fallback implementation just scans all the features in the layer looking for
the desired feature. Returns a list with the unique feature identifier (FID),
the attribute and geometry field names, and their values, or \code{NULL} on
failure. Note that sequential reads (with \code{$getNextFeature()}) are
generally considered interrupted by a call to \code{$getFeature()}.

\code{$resetReading()}\cr
Reset feature reading to start on the first feature. No return value, called
for that side effect.

\code{$fetch(n)}\cr
Fetches the next \code{n} features from the layer and returns them as a data
frame. This allows retrieving the entire set of features, one page of
features at a time, or the remaining features (from the current cursor
position). Returns a data frame with as many rows as features were fetched,
and as many columns as attribute plus geometry fields in the result set,
even if the result is a single value or has one or zero rows.
The returned data frame carries the \code{OGRFeatureSet} class attribute with S3
methods for for \code{print()} and \code{plot()}.

This method is an analog of
\href{https://dbi.r-dbi.org/reference/dbFetch.html}{\code{DBI::dbFetch()}}.

The \code{n} argument is the maximum number of features to retrieve per fetch
given as \code{integer} or \code{numeric} but assumed to be a whole number (will
be truncated). Use \code{n = -1} or \code{n = Inf} to retrieve all pending features
(resets reading to the first feature).
Otherwise, \code{$fetch()} can be called multiple times to perform forward
paging from the current cursor position. Passing \code{n = NA} is also supported
and returns the remaining features.
Fetching zero features is possible to retrieve the structure of the feature
set as a data frame (columns fully typed).

OGR field types are returned as the following \R types (type-specific \code{NA}
for OGR NULL values):
\itemize{
\item \strong{OFTInteger}: \code{integer} value
\item \strong{OFTInteger subtype OFSTBoolean}: \code{logical} value
\item \strong{OFTIntegerList}: vector of \code{integer} (list column)
\item \strong{OFTInteger64}: \code{numeric} value carrying the \code{"integer64"} class
attribute
\item \strong{OFTInteger64 subtype OFSTBoolean}: \code{logical} value
\item \strong{OFTInteger64List}: vector of \code{bit64::integer64} (list column)
\item \strong{OFTReal}: \code{numeric} value
\item \strong{OFTRealList}: vector of \code{numeric} (list column)
\item \strong{OFTString}: \code{character} string
\item \strong{OFTStringList}: vector of \code{character} strings (list column)
\item \strong{OFTDate}: \code{numeric} value of class \code{"Date"}
\item \strong{OFTDateTime}: \code{numeric} value of class \code{"POSIXct"} (millisecond
accuracy)
\item \strong{OFTTime}: \code{character} string (\code{"HH:MM:SS"})
\item \strong{OFTBinary}: \code{raw} vector (list column, \code{NULL} entries for OGR NULL
values)
}

Geometries are not returned if the field \code{returnGeomAs} is set to \code{NONE}.
Omitting the geometries may be beneficial for performance and memory usage
when access only to feature attributes is needed. Geometries are returned
as \code{raw} vectors in a data frame list column when \code{returnGeomAs} is set to
\code{WKB} (the default) or \code{WKB_ISO}, or as \code{character} strings when
\code{returnGeomAs} is set to one of \code{WKT} or \code{WKT_ISO}.

Note that \code{$getFeatureCount()} is called internally when fetching the
full feature set or all remaining features (but not for a page of features).

\code{$getArrowStream()}\cr
Returns a \code{nanoarrow_array_stream} object exposing an Arrow C stream on the
layer (requires GDAL >= 3.6).
The writable field \code{$arrowStreamOptions} can be used to set options
before calling this method (see above). An error is raised if an array stream
on the layer cannot be obtained.
Generally, only one ArrowArrayStream can be active at a time on a given
layer (i.e., the last active one must be explicitly released before a next
one is asked). Changing attribute or spatial filters, ignored columns,
modifying the schema or using \code{$resetReading()} /
\code{$getNextFeature()} while using an ArrowArrayStream is strongly
discouraged and may lead to unexpected results. As a rule of thumb, no
OGRLayer methods that affect the state of a layer should be called on the
layer while an ArrowArrayStream on it is active. Methods available on the
stream object are: \code{$get_schema()}, \code{$get_next()} and
\code{$release()} (see Examples).

The stream should be released once reading is complete. Calling the release
method as soon as you can after consuming a stream is recommended by the
\pkg{nanoarrow} documentation.

See also the \code{$testCapability()} method above to check whether the
format driver provides a specialized implementation (\code{FastGetArrowStream}),
as opposed to the (slower) default implementation. Note however that
specialized implementations may fallback to the default when attribute or
spatial filters are in use.
(See the GDAL documentation for
\href{https://gdal.org/en/stable/api/vector_c_api.html#_CPPv420OGR_L_GetArrowStream9OGRLayerHP16ArrowArrayStreamPPc}{\code{OGR_L_GetArrowStream()}}.)

\code{$releaseArrowStream()}\cr
Releases the Arrow C stream returned by \code{$getArrowStream()} and clears
the \code{nanoarrow_array_stream} object (if GDAL >= 3.6, otherwise does nothing).
This is equivalent to calling the \code{$release()} method on the
\code{nanoarrow_array_stream} object. No return value, called for side effects.

\code{$writeArrowBatch(df)}\cr
Writes a batch of rows from a data frame. This is similar to the
\verb{$batchCreateFeature()} method described below, but uses GDAL's Arrow C
stream interface for column oriented write when supported by the format
driver. The column names and data types of the input data frame must be
compatible with the layer schema. Geometry columns must be list columns
containing \code{raw} vectors of WKB. The writable field
\verb{$writeArrowBatchOptions} can be used to set options before calling this
method (see above). Returns a \code{logical} value, \code{TRUE} indicating success.
This method and \verb{$createFeature()} / \verb{$batchCreateFeature()} are mutually
exclusive in the same session.

\code{$setFeature(feature)}\cr
Rewrites/replaces an existing feature. This method writes a feature based on
the feature id within the input feature. The \code{feature} argument is a named
list of fields and their values, and must include a \code{FID} element
referencing the existing feature to rewrite. The \code{RandomWrite} element in
the list returned by \code{$testCapability()} can be checked to establish if
this layer supports random access writing via \code{$setFeature()}.
The way omitted fields in the passed \code{feature} are processed is driver
dependent:
\itemize{
\item SQL-based drivers which implement set feature through SQL UPDATE will skip
unset fields, and thus the content of the existing feature will be
preserved.
\item The shapefile driver will write a NULL value in the DBF file.
\item The GeoJSON driver will take into account unset fields to remove the
corresponding JSON member.
}

Returns logical \code{TRUE} upon successful completion, or \code{FALSE} if setting the
feature did not succeed. The FID of the last feature written to the layer
may be obtained with the method \code{$getLastWriteFID()} (see below).
To set a feature, but create it if it doesn't exist see the
\code{$upsertFeature()} method.

\code{$createFeature(feature)}\cr
Creates and writes a new feature within the layer. The \code{feature} argument is
a named list of fields and their values (might be one row of a data frame).
The passed feature is written to the layer as a new feature, rather than
overwriting an existing one. If the feature has a \code{FID} element with other
than \code{NA} (i.e., a numeric value, optionally carrying the \code{bit64::integer64}
class attribute and assumed to be a whole number), then the format
driver may use that as the feature id of the new feature, but not
necessarily. The FID of the last feature written to the layer may be
obtained with the method \code{$getLastWriteFID()} (see below).
Returns logical \code{TRUE} upon successful completion, or \code{FALSE} if creating
the feature did not succeed. To create a feature, but set it if it already
exists see the \code{$upsertFeature()} method.

\code{$batchCreateFeature(feature_set)}\cr
Batch version of \code{$createFeature()}. Creates and writes a batch of new
features within the layer from input passed as a data frame in the
\code{feature_set} argument. Column names in the data frame must match field
names of the layer and have compatible data types. The specifications
listed above under the \code{$fetch()} method generally apply to input data
types for writing, but integers may be passed as 'numeric', and
the 'integer64' class attribute is not strictly required on 'numeric'
input if it is not needed for the data being passed to an OFTInteger64
field.
Returns a logical vector of length equal to the number of input features
(rows of the data frame), with \code{TRUE} indicating success for the feature at
that row index, or \code{FALSE} if writing the feature failed.
It is recommended to use transactions when batch writing features to a
layer (see \code{$startTransaction()} below). This will generally give large
performance benefit with data sources that provide efficient transaction
support (e.g., RDBMS-based sources such as GeoPackage and PostGIS). In
addition, the return value of \code{$batchCreateFeature()} can be checked,
and the transaction optionally committed or rolled back based on results of
the operation across the full set of input features.

\code{$upsertFeature(feature)}\cr
Rewrites/replaces an existing feature or creates a new feature within the
layer. This method will write a feature to the layer, based on the feature
id within the input feature. The \code{feature} argument is a named list of
fields and their values (might be one row of a data frame), potentially
including a \code{FID} element referencing an existing feature to rewrite. If
the feature id doesn't exist a new feature will be written. Otherwise, the
existing feature will be rewritten.
The \code{UpsertFeature} element in the list returned by \code{$testCapability()}
can be checked to determine if this layer supports upsert writing. See
\code{$setFeature()} above for a description of how omitted fields in the
passed feature are processed.
Returns logical \code{TRUE} upon successful completion, or \code{FALSE} if upsert did
not succeed. Requires GDAL >= 3.6.

\code{$getLastWriteFID()}\cr
Returns the FID of the last feature written (either newly created or updated
existing). \code{NULL} is returned if no features have been written in the layer.
Note that OGRNullFID (\code{-1}) may be returned after writing a feature in some
formats. This is the case if a FID has not been assigned yet, and generally
does not indicate an error (e.g., formats that do not store a persistent FID
and assign FIDs upon a sequential read operation). The returned FID is a
numeric value carrying the \code{bit64::integer64} class attribute.

\code{$deleteFeature(fid)}\cr
Deletes a feature from the layer. The feature with the indicated feature ID
is deleted from the layer if supported by the format driver. The value of
\code{fid} must be a numeric value, optionally carrying the \code{bit64::integer64}
class attribute (should be a whole number, will be truncated).
The \code{DeleteFeature} element in the list returned by \code{$testCapability()}
can be checked to establish if this layer has delete feature capability.
Returns logical \code{TRUE} if the operation succeeds, or \code{FALSE} on failure.

\code{$syncToDisk()}\cr
Flushes pending changes to disk. This call is intended to force the layer to
flush any pending writes to disk, and leave the disk file in a consistent
state. It would not normally have any effect on read-only datasources. Some
formats do not implement this method, and will still return no error. An
error is only returned if an error occurs while attempting to flush to disk.
In any event, you should always close any opened datasource with
\code{$close()} which will ensure all data is correctly flushed. Returns
logical \code{TRUE} if no error occurs (even if nothing is done) or \code{FALSE} on
error.

\code{$startTransaction()}\cr
Creates a transaction if supported by the vector data source. By default,
only "efficient" transactions will be attempted. See the writable field
\code{$transactionsForce} above, which must be set to \code{TRUE} to allow for
emulated transactions. These are supported by some drivers but with
potentially significant overhead. The function \code{ogr_ds_test_cap()} can be
used to determine whether a vector data source supports efficient or
emulated transactions.

All changes done after the start of the transaction are definitely applied
in the data source if \code{$commitTransaction()} is called. They can be
canceled by calling \code{$rollbackTransaction()} instead.
Nested transactions are not supported. Transactions are implemented at the
dataset level, so multiple \code{GDALVector} objects using the same data source
should not have transactions active at the same time.

In case \code{$startTransaction()} fails, neither \code{$commitTransaction()}
nor \code{$rollbackTransaction()} should be called.
If an error occurs after a successful \code{$startTransaction()}, the whole
transaction may or may not be implicitly canceled, depending on the format
driver (e.g., the PostGIS driver will cancel it, SQLite/GPKG will not). In
any case, in the event of an error, an explicit call to
\code{$rollbackTransaction()} should be done to keep things balanced.

Returns logical \code{TRUE} if the transaction is created, or \code{FALSE} on failure.

\code{$commitTransaction()}\cr
Commits a transaction if supported by the vector data source.
Returns a logical value, \code{TRUE} if the transaction is successfully committed.
Returns \code{FALSE} if no transaction is active, or the rollback fails, or if the
data source does not support transactions.
Depending on the format driver, this may or may not abort layer sequential
reading that may be active.

\code{$rollbackTransaction()}\cr
Rolls back a data source to its state before the start of the current
transaction, if transactions are supported by the data source.
Returns a logical value, \code{TRUE} if the transaction is successfully rolled
back. Returns \code{FALSE} if no transaction is active, or the rollback fails,
or if the data source does not support transactions.

\code{$getMetadata()}\cr
Returns a character vector of all metadata \code{NAME=VALUE} pairs for the
layer or empty string (\code{""}) if there are no metadata items.

\code{$setMetadata(metadata)}\cr
Sets metadata on the layer if the format supports it. The \code{metadata}
argument is given as a character vector of \code{NAME=VALUE} pairs.
Returns logical \code{TRUE} on success or \code{FALSE} if metadata could
not be set.

\code{$getMetadataItem(mdi_name)}\cr
Returns the value of a specific metadata item named \code{mdi_name}, or empty
string (\code{""}) if no matching item is found.

\code{$close()}\cr
Closes the vector dataset (no return value, called for side effects).
Calling \code{$close()} results in proper cleanup, and flushing of any
pending writes.
The \code{GDALVector} object is still available after calling \code{$close()}.
The layer can be re-opened on the existing \code{dsn} with
\code{$open(read_only = TRUE|FALSE)}.
}
}

\examples{
## MTBS fire perimeters in Yellowstone National Park 1984-2022
f <- system.file("extdata/ynp_fires_1984_2022.gpkg", package = "gdalraster")

## copy to a temporary file that is writeable
dsn <- file.path(tempdir(), basename(f))
file.copy(f, dsn)

(lyr <- new(GDALVector, dsn, "mtbs_perims"))

str(lyr)

## dataset info
lyr$getDriverShortName()
lyr$getDriverLongName()
lyr$getFileList()

## layer info
lyr$getName()
lyr$getGeomType()
lyr$getGeometryColumn()
lyr$getFIDColumn()
lyr$getSpatialRef()
lyr$bbox()

## layer capabilities
lyr$testCapability()

## re-open with write access
lyr$open(read_only = FALSE)
lyr$testCapability()$SequentialWrite
lyr$testCapability()$RandomWrite

## feature class definition - a list of field names and their definitions
defn <- lyr$getLayerDefn()
names(defn)
str(defn)

## default value of the read/write field 'returnGeomAs'
lyr$returnGeomAs

lyr$getFeatureCount()

## sequential read cursor
# a single feature returned as a named list of fields and their values:
(feat <- lyr$getNextFeature())

## set an attribute filter
lyr$setAttributeFilter("ig_year = 2020")
lyr$getFeatureCount()

feat <- lyr$getNextFeature()
plot(feat)

## NULL when no more features are available
lyr$getNextFeature()

## reset reading to the start
lyr$resetReading()
lyr$getNextFeature()

## clear the attribute filter
lyr$setAttributeFilter("")
lyr$getFeatureCount()

## set a spatial filter
## get the bounding box of the largest 1988 fire and use as spatial filter
## first set a temporary attribute filter to do the lookup
lyr$setAttributeFilter("ig_year = 1988 ORDER BY burn_bnd_ac DESC")
(feat <- lyr$getNextFeature())

bbox <- g_wk2wk(feat$geom) |> bbox_from_wkt()

## set spatial filter on the full layer
lyr$setAttributeFilter("")  # clears the attribute filter
lyr$setSpatialFilterRect(bbox)
lyr$getFeatureCount()

## fetch in chunks and return as data frame (class OGRFeatureSet)
feat_set <- lyr$fetch(20)
head(feat_set)
plot(feat_set)

## the next chunk
feat_set <- lyr$fetch(20)
nrow(feat_set)

## no features remaining
feat_set <- lyr$fetch(20)
nrow(feat_set)
str(feat_set)  # 0-row data frame with columns fully typed

## or, fetch all pending features from the beginning
feat_set <- lyr$fetch(-1)  # resets reading to the first feature
nrow(feat_set)
plot(feat_set)

lyr$clearSpatialFilter()
lyr$getFeatureCount()

lyr$close()

## simple example of feature write methods showing use of various data types
## create and write to a new layer in a GeoPackage data source
dsn2 <- tempfile(fileext = ".gpkg")

## define a feature class
defn <- ogr_def_layer("POINT", srs = epsg_to_wkt(4326))

## add field definitions
defn$unique_int <- ogr_def_field("OFTInteger", is_nullable = FALSE,
                                 is_unique = TRUE)
defn$bool_data <- ogr_def_field("OFTInteger", fld_subtype = "OFSTBoolean")
defn$large_ints <- ogr_def_field("OFTInteger64")
defn$doubles <- ogr_def_field("OFTReal")
defn$strings <- ogr_def_field("OFTString", fld_width = 50)
defn$dates <- ogr_def_field("OFTDate")
defn$dt_modified <- ogr_def_field("OFTDateTime",
                                  default_value = "CURRENT_TIMESTAMP")
defn$blobs <- ogr_def_field("OFTBinary")

lyr <- ogr_ds_create("GPKG", dsn2, "test_layer", layer_defn = defn,
                     return_obj = TRUE)

# lyr$getLayerDefn() |> str()

## define a feature to write
feat1 <- list()
# $FID is omitted since it is assigned when written (could also be NA)
# $dt_modified is omitted since a default timestamp is defined on the field
feat1$unique_int <- 1001
feat1$bool_data <- TRUE
# pass a string to as.integer64() since the value is too large to be
# represented exactly as an R numeric value (i.e., double)
feat1$large_ints <- bit64::as.integer64("90071992547409910")
feat1$doubles <- 1.234
feat1$strings <- "A test string"
feat1$dates <- as.Date("2025-01-01")
feat1$blobs <- charToRaw("A binary object")
feat1$geom <- "POINT (1 1)"  # can be a WKT string or raw vector of WKB

## create as a new feature in the layer
lyr$createFeature(feat1)

## get the assigned FID
lyr$getLastWriteFID()

## attempt to re-write the same feature fails due to the unique constraint
lyr$createFeature(feat1)

feat2 <- list()
feat2$unique_int <- 1002
feat2$bool_data <- FALSE
feat2$large_ints <- bit64::as.integer64("90071992547409920")
feat2$doubles <- 2.345
feat2$strings <- "A test string 2"
feat2$dates <- as.Date("2024-01-02")
feat2$blobs <- charToRaw("A binary object 2")
feat2$geom <- "POINT (2 2)"

lyr$createFeature(feat2)
lyr$getLastWriteFID()

## close and re-open as a read-only layer
lyr$open(read_only = TRUE)

lyr$getFeatureCount()
feat_set <- lyr$fetch(-1)  # -1 to fetch all features from the beginning
str(feat_set)

## edit an existing feature, e.g., feat <- lyr$getFeature(2)
## here we copy a row of the data frame returned by lyr$fetch() above
feat <- feat_set[2,]
str(feat)

Sys.sleep(1)  # to ensure a timestamp difference

feat$bool_data <- TRUE
feat$strings <- paste(feat$strings, "- edited")
feat$dt_modified <- Sys.time()
feat$geom <- "POINT (2.001 2.001)"

lyr$open(read_only = FALSE)

## lyr$setFeature() re-writes the feature identified by the $FID element
lyr$setFeature(feat)

lyr$open(read_only = TRUE)
lyr$getFeatureCount()

lyr$returnGeomAs <- "WKT"
feat_set <- lyr$fetch(-1)
str(feat_set)

lyr$close()

## Arrow array stream exposed as a nanoarrow_array_stream object
## requires GDAL >= 3.6
if (gdal_version_num() >= gdal_compute_version(3, 6, 0)) {

  sql <- "SELECT incid_name, geom from mtbs_perims LIMIT 5"
  lyr <- new(GDALVector, dsn, sql)

  stream <- lyr$getArrowStream()

  # disable a warning for the example that can be safely ignored here
  options(nanoarrow.warn_unregistered_extension = FALSE)

  # pull all the batches into a data frame
  d <- as.data.frame(stream)

  # the geometry column is a list column of WKB raw vectors, which can be
  # passed to the Geometry API g_*() functions, e.g.,
  g_centroid(d$geom) |> print()

  # release the stream when finished
  stream$release()

  lyr$close()
}
\dontshow{unlink(dsn)}
\dontshow{unlink(dsn2)}
}
\seealso{
\link{ogr_define}, \link{ogr_manage}, \code{\link[=ogr2ogr]{ogr2ogr()}}, \code{\link[=ogrinfo]{ogrinfo()}}

GDAL vector format descriptions:\cr
\url{https://gdal.org/en/stable/drivers/vector/index.html}

GDAL-supported SQL dialects:\cr
\url{https://gdal.org/en/stable/user/ogr_sql_sqlite_dialect.html}

GDAL Vector API documentation:\cr
\url{https://gdal.org/en/stable/api/index.html}
}
