diff --git a/r/DESCRIPTION b/r/DESCRIPTION index e247ef856bb16..0ef5f55fc0652 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -55,6 +55,7 @@ Collate: 'array.R' 'buffer.R' 'dictionary.R' + 'feather.R' 'io.R' 'memory_pool.R' 'message.R' diff --git a/r/NAMESPACE b/r/NAMESPACE index 755453c2db147..46d40e1a50e1d 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -14,6 +14,12 @@ S3method(buffer,numeric) S3method(buffer,raw) S3method(buffer_reader,"arrow::Buffer") S3method(buffer_reader,default) +S3method(feather_table_reader,"arrow::io::RandomAccessFile") +S3method(feather_table_reader,"arrow::ipc::feather::TableReader") +S3method(feather_table_reader,character) +S3method(feather_table_reader,default) +S3method(feather_table_reader,fs_path) +S3method(feather_table_writer,"arrow::io::OutputStream") S3method(fixed_size_buffer_writer,"arrow::Buffer") S3method(fixed_size_buffer_writer,default) S3method(length,"arrow::Array") @@ -51,6 +57,13 @@ S3method(record_batch_stream_reader,raw) S3method(write_arrow,"arrow::RecordBatch") S3method(write_arrow,"arrow::Table") S3method(write_arrow,data.frame) +S3method(write_feather,"arrow::RecordBatch") +S3method(write_feather,data.frame) +S3method(write_feather,default) +S3method(write_feather_RecordBatch,"arrow::io::OutputStream") +S3method(write_feather_RecordBatch,character) +S3method(write_feather_RecordBatch,default) +S3method(write_feather_RecordBatch,fs_path) S3method(write_record_batch,"arrow::io::OutputStream") S3method(write_record_batch,"arrow::ipc::RecordBatchWriter") S3method(write_record_batch,character) @@ -78,6 +91,8 @@ export(date32) export(date64) export(decimal) export(dictionary) +export(feather_table_reader) +export(feather_table_writer) export(file_open) export(file_output_stream) export(fixed_size_buffer_writer) @@ -96,6 +111,7 @@ export(mock_output_stream) export(null) export(print.integer64) export(read_arrow) +export(read_feather) export(read_message) export(read_record_batch) export(read_schema) @@ -118,6 +134,8 @@ export(uint64) export(uint8) export(utf8) export(write_arrow) +export(write_feather) +export(write_feather_RecordBatch) export(write_record_batch) export(write_table) importFrom(R6,R6Class) diff --git a/r/R/RcppExports.R b/r/R/RcppExports.R index 3811c5d316186..ec8756bf9464f 100644 --- a/r/R/RcppExports.R +++ b/r/R/RcppExports.R @@ -369,6 +369,66 @@ DictionaryType__ordered <- function(type) { .Call(`_arrow_DictionaryType__ordered`, type) } +ipc___feather___TableWriter__SetDescription <- function(writer, description) { + invisible(.Call(`_arrow_ipc___feather___TableWriter__SetDescription`, writer, description)) +} + +ipc___feather___TableWriter__SetNumRows <- function(writer, num_rows) { + invisible(.Call(`_arrow_ipc___feather___TableWriter__SetNumRows`, writer, num_rows)) +} + +ipc___feather___TableWriter__Append <- function(writer, name, values) { + invisible(.Call(`_arrow_ipc___feather___TableWriter__Append`, writer, name, values)) +} + +ipc___feather___TableWriter__Finalize <- function(writer) { + invisible(.Call(`_arrow_ipc___feather___TableWriter__Finalize`, writer)) +} + +ipc___feather___TableWriter__Open <- function(stream) { + .Call(`_arrow_ipc___feather___TableWriter__Open`, stream) +} + +ipc___TableWriter__RecordBatch__WriteFeather <- function(writer, batch) { + invisible(.Call(`_arrow_ipc___TableWriter__RecordBatch__WriteFeather`, writer, batch)) +} + +ipc___feather___TableReader__GetDescription <- function(reader) { + .Call(`_arrow_ipc___feather___TableReader__GetDescription`, reader) +} + +ipc___feather___TableReader__HasDescription <- function(reader) { + .Call(`_arrow_ipc___feather___TableReader__HasDescription`, reader) +} + +ipc___feather___TableReader__version <- function(reader) { + .Call(`_arrow_ipc___feather___TableReader__version`, reader) +} + +ipc___feather___TableReader__num_rows <- function(reader) { + .Call(`_arrow_ipc___feather___TableReader__num_rows`, reader) +} + +ipc___feather___TableReader__num_columns <- function(reader) { + .Call(`_arrow_ipc___feather___TableReader__num_columns`, reader) +} + +ipc___feather___TableReader__GetColumnName <- function(reader, i) { + .Call(`_arrow_ipc___feather___TableReader__GetColumnName`, reader, i) +} + +ipc___feather___TableReader__GetColumn <- function(reader, i) { + .Call(`_arrow_ipc___feather___TableReader__GetColumn`, reader, i) +} + +ipc___feather___TableReader__Read <- function(reader) { + .Call(`_arrow_ipc___feather___TableReader__Read`, reader) +} + +ipc___feather___TableReader__Open <- function(stream) { + .Call(`_arrow_ipc___feather___TableReader__Open`, stream) +} + Field__initialize <- function(name, type, nullable = TRUE) { .Call(`_arrow_Field__initialize`, name, type, nullable) } diff --git a/r/R/feather.R b/r/R/feather.R new file mode 100644 index 0000000000000..c36c571bd4bd4 --- /dev/null +++ b/r/R/feather.R @@ -0,0 +1,160 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +#' @include R6.R + +`arrow::ipc::feather::TableWriter` <- R6Class("arrow::ipc::feather::TableWriter", inherit = `arrow::Object`, + public = list( + SetDescription = function(description) ipc___feather___TableWriter__SetDescription(self, description), + SetNumRows = function(num_rows) ipc___feather___TableWriter__SetNumRows(self, num_rows), + Append = function(name, values) ipc___feather___TableWriter__Append(self, name, values), + Finalize = function() ipc___feather___TableWriter__Finalize(self) + ) +) + +`arrow::ipc::feather::TableReader` <- R6Class("arrow::ipc::feather::TableReader", inherit = `arrow::Object`, + public = list( + GetDescription = function() ipc___feather___TableReader__GetDescription(self), + HasDescription = function() ipc__feather___TableReader__HasDescription(self), + version = function() ipc___feather___TableReader__version(self), + num_rows = function() ipc___feather___TableReader__num_rows(self), + num_columns = function() ipc___feather___TableReader__num_columns(self), + GetColumnName = function(i) ipc___feather___TableReader__GetColumnName(self, i), + GetColumn = function(i) shared_ptr(`arrow::Column`, ipc___feather___TableReader__GetColumn(self, i)), + Read = function() shared_ptr(`arrow::Table`, ipc___feather___TableReader__Read(self)) + ) +) + +#' Create TableWriter that writes into a stream +#' +#' @param stream an OutputStream +#' +#' @export +feather_table_writer <- function(stream) { + UseMethod("feather_table_writer") +} + +#' @export +`feather_table_writer.arrow::io::OutputStream` <- function(stream){ + unique_ptr(`arrow::ipc::feather::TableWriter`, ipc___feather___TableWriter__Open(stream)) +} + +#' Write data in the feather format +#' +#' @param data frame or arrow::RecordBatch +#' @param stream A file path or an arrow::io::OutputStream +#' +#' @export +write_feather <- function(data, stream) { + UseMethod("write_feather", data) +} + +#' @export +write_feather.default <- function(data, stream) { + stop("unsupported") +} + +#' @export +write_feather.data.frame <- function(data, stream) { + write_feather(record_batch(data), stream) +} + +#' @method write_feather arrow::RecordBatch +#' @export +`write_feather.arrow::RecordBatch` <- function(data, stream) { + write_feather_RecordBatch(data, stream) +} + +#' @rdname write_feather +#' @export +write_feather_RecordBatch <- function(data, stream) { + UseMethod("write_feather_RecordBatch", stream) +} + +#' @export +#' @method write_feather_RecordBatch default +`write_feather_RecordBatch.default` <- function(data, stream) { + stop("unsupported") +} + +#' @export +#' @method write_feather_RecordBatch character +`write_feather_RecordBatch.character` <- function(data, stream) { + `write_feather_RecordBatch.fs_path`(data, fs::path_abs(stream)) +} + +#' @export +#' @method write_feather_RecordBatch fs_path +`write_feather_RecordBatch.fs_path` <- function(data, stream) { + file_stream <- close_on_exit(file_output_stream(stream)) + `write_feather_RecordBatch.arrow::io::OutputStream`(data, file_stream) +} + +#' @export +#' @method write_feather_RecordBatch arrow::io::OutputStream +`write_feather_RecordBatch.arrow::io::OutputStream` <- function(data, stream) { + ipc___TableWriter__RecordBatch__WriteFeather(feather_table_writer(stream), data) +} + +#' A arrow::ipc::feather::TableReader to read from a file +#' +#' @param file A file path, arrow::io::RandomAccessFile +#' @param mmap Is the file memory mapped (applicable to the character and fs_path methods) +#' @param ... extra parameters +#' +#' @export +feather_table_reader <- function(file, mmap = TRUE, ...){ + UseMethod("feather_table_reader") +} + +#' @export +feather_table_reader.default <- function(file, mmap = TRUE, ...) { + stop("unsupported") +} + +#' @export +feather_table_reader.character <- function(file, mmap = TRUE, ...) { + feather_table_reader(fs::path_abs(file), mmap = mmap, ...) +} + +#' @export +feather_table_reader.fs_path <- function(file, mmap = TRUE, ...) { + stream <- if(isTRUE(mmap)) mmap_open(file, ...) else file_open(file, ...) + feather_table_reader(stream) +} + +#' @export +`feather_table_reader.arrow::io::RandomAccessFile` <- function(file, mmap = TRUE, ...){ + unique_ptr(`arrow::ipc::feather::TableReader`, ipc___feather___TableReader__Open(file)) +} + +#' @export +`feather_table_reader.arrow::ipc::feather::TableReader` <- function(file, mmap = TRUE, ...){ + file +} + +#' Read a feather file +#' +#' @param file a arrow::ipc::feather::TableReader or whatever the [feather_table_reader()] function can handle +#' @param ... additional parameters +#' +#' @return an arrow::Table +#' +#' @export +read_feather <- function(file, ...){ + feather_table_reader(file, ...)$Read() +} diff --git a/r/man/feather_table_reader.Rd b/r/man/feather_table_reader.Rd new file mode 100644 index 0000000000000..fb1c53429f860 --- /dev/null +++ b/r/man/feather_table_reader.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/feather.R +\name{feather_table_reader} +\alias{feather_table_reader} +\title{A arrow::ipc::feather::TableReader to read from a file} +\usage{ +feather_table_reader(file, mmap = TRUE, ...) +} +\arguments{ +\item{file}{A file path, arrow::io::RandomAccessFile} + +\item{mmap}{Is the file memory mapped (applicable to the character and fs_path methods)} + +\item{...}{extra parameters} +} +\description{ +A arrow::ipc::feather::TableReader to read from a file +} diff --git a/r/man/feather_table_writer.Rd b/r/man/feather_table_writer.Rd new file mode 100644 index 0000000000000..36035aca12090 --- /dev/null +++ b/r/man/feather_table_writer.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/feather.R +\name{feather_table_writer} +\alias{feather_table_writer} +\title{Create TableWriter that writes into a stream} +\usage{ +feather_table_writer(stream) +} +\arguments{ +\item{stream}{an OutputStream} +} +\description{ +Create TableWriter that writes into a stream +} diff --git a/r/man/read_feather.Rd b/r/man/read_feather.Rd new file mode 100644 index 0000000000000..e86b86b99e9e2 --- /dev/null +++ b/r/man/read_feather.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/feather.R +\name{read_feather} +\alias{read_feather} +\title{Read a feather file} +\usage{ +read_feather(file, ...) +} +\arguments{ +\item{file}{a arrow::ipc::feather::TableReader or whatever the \code{\link[=feather_table_reader]{feather_table_reader()}} function can handle} + +\item{...}{additional parameters} +} +\value{ +an arrow::Table +} +\description{ +Read a feather file +} diff --git a/r/man/write_feather.Rd b/r/man/write_feather.Rd new file mode 100644 index 0000000000000..f29554affd865 --- /dev/null +++ b/r/man/write_feather.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/feather.R +\name{write_feather} +\alias{write_feather} +\alias{write_feather_RecordBatch} +\title{Write data in the feather format} +\usage{ +write_feather(data, stream) + +write_feather_RecordBatch(data, stream) +} +\arguments{ +\item{data}{frame or arrow::RecordBatch} + +\item{stream}{A file path or an arrow::io::OutputStream} +} +\description{ +Write data in the feather format +} diff --git a/r/src/RcppExports.cpp b/r/src/RcppExports.cpp index 79ee497660a50..21f00339aff0c 100644 --- a/r/src/RcppExports.cpp +++ b/r/src/RcppExports.cpp @@ -1022,6 +1022,173 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// ipc___feather___TableWriter__SetDescription +void ipc___feather___TableWriter__SetDescription(const std::unique_ptr& writer, const std::string& description); +RcppExport SEXP _arrow_ipc___feather___TableWriter__SetDescription(SEXP writerSEXP, SEXP descriptionSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::unique_ptr& >::type writer(writerSEXP); + Rcpp::traits::input_parameter< const std::string& >::type description(descriptionSEXP); + ipc___feather___TableWriter__SetDescription(writer, description); + return R_NilValue; +END_RCPP +} +// ipc___feather___TableWriter__SetNumRows +void ipc___feather___TableWriter__SetNumRows(const std::unique_ptr& writer, int64_t num_rows); +RcppExport SEXP _arrow_ipc___feather___TableWriter__SetNumRows(SEXP writerSEXP, SEXP num_rowsSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::unique_ptr& >::type writer(writerSEXP); + Rcpp::traits::input_parameter< int64_t >::type num_rows(num_rowsSEXP); + ipc___feather___TableWriter__SetNumRows(writer, num_rows); + return R_NilValue; +END_RCPP +} +// ipc___feather___TableWriter__Append +void ipc___feather___TableWriter__Append(const std::unique_ptr& writer, const std::string& name, const std::shared_ptr& values); +RcppExport SEXP _arrow_ipc___feather___TableWriter__Append(SEXP writerSEXP, SEXP nameSEXP, SEXP valuesSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::unique_ptr& >::type writer(writerSEXP); + Rcpp::traits::input_parameter< const std::string& >::type name(nameSEXP); + Rcpp::traits::input_parameter< const std::shared_ptr& >::type values(valuesSEXP); + ipc___feather___TableWriter__Append(writer, name, values); + return R_NilValue; +END_RCPP +} +// ipc___feather___TableWriter__Finalize +void ipc___feather___TableWriter__Finalize(const std::unique_ptr& writer); +RcppExport SEXP _arrow_ipc___feather___TableWriter__Finalize(SEXP writerSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::unique_ptr& >::type writer(writerSEXP); + ipc___feather___TableWriter__Finalize(writer); + return R_NilValue; +END_RCPP +} +// ipc___feather___TableWriter__Open +std::unique_ptr ipc___feather___TableWriter__Open(const std::shared_ptr& stream); +RcppExport SEXP _arrow_ipc___feather___TableWriter__Open(SEXP streamSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::shared_ptr& >::type stream(streamSEXP); + rcpp_result_gen = Rcpp::wrap(ipc___feather___TableWriter__Open(stream)); + return rcpp_result_gen; +END_RCPP +} +// ipc___TableWriter__RecordBatch__WriteFeather +void ipc___TableWriter__RecordBatch__WriteFeather(const std::unique_ptr& writer, const std::shared_ptr& batch); +RcppExport SEXP _arrow_ipc___TableWriter__RecordBatch__WriteFeather(SEXP writerSEXP, SEXP batchSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::unique_ptr& >::type writer(writerSEXP); + Rcpp::traits::input_parameter< const std::shared_ptr& >::type batch(batchSEXP); + ipc___TableWriter__RecordBatch__WriteFeather(writer, batch); + return R_NilValue; +END_RCPP +} +// ipc___feather___TableReader__GetDescription +std::string ipc___feather___TableReader__GetDescription(const std::unique_ptr& reader); +RcppExport SEXP _arrow_ipc___feather___TableReader__GetDescription(SEXP readerSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::unique_ptr& >::type reader(readerSEXP); + rcpp_result_gen = Rcpp::wrap(ipc___feather___TableReader__GetDescription(reader)); + return rcpp_result_gen; +END_RCPP +} +// ipc___feather___TableReader__HasDescription +bool ipc___feather___TableReader__HasDescription(const std::unique_ptr& reader); +RcppExport SEXP _arrow_ipc___feather___TableReader__HasDescription(SEXP readerSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::unique_ptr& >::type reader(readerSEXP); + rcpp_result_gen = Rcpp::wrap(ipc___feather___TableReader__HasDescription(reader)); + return rcpp_result_gen; +END_RCPP +} +// ipc___feather___TableReader__version +int ipc___feather___TableReader__version(const std::unique_ptr& reader); +RcppExport SEXP _arrow_ipc___feather___TableReader__version(SEXP readerSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::unique_ptr& >::type reader(readerSEXP); + rcpp_result_gen = Rcpp::wrap(ipc___feather___TableReader__version(reader)); + return rcpp_result_gen; +END_RCPP +} +// ipc___feather___TableReader__num_rows +int64_t ipc___feather___TableReader__num_rows(const std::unique_ptr& reader); +RcppExport SEXP _arrow_ipc___feather___TableReader__num_rows(SEXP readerSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::unique_ptr& >::type reader(readerSEXP); + rcpp_result_gen = Rcpp::wrap(ipc___feather___TableReader__num_rows(reader)); + return rcpp_result_gen; +END_RCPP +} +// ipc___feather___TableReader__num_columns +int64_t ipc___feather___TableReader__num_columns(const std::unique_ptr& reader); +RcppExport SEXP _arrow_ipc___feather___TableReader__num_columns(SEXP readerSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::unique_ptr& >::type reader(readerSEXP); + rcpp_result_gen = Rcpp::wrap(ipc___feather___TableReader__num_columns(reader)); + return rcpp_result_gen; +END_RCPP +} +// ipc___feather___TableReader__GetColumnName +std::string ipc___feather___TableReader__GetColumnName(const std::unique_ptr& reader, int i); +RcppExport SEXP _arrow_ipc___feather___TableReader__GetColumnName(SEXP readerSEXP, SEXP iSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::unique_ptr& >::type reader(readerSEXP); + Rcpp::traits::input_parameter< int >::type i(iSEXP); + rcpp_result_gen = Rcpp::wrap(ipc___feather___TableReader__GetColumnName(reader, i)); + return rcpp_result_gen; +END_RCPP +} +// ipc___feather___TableReader__GetColumn +std::shared_ptr ipc___feather___TableReader__GetColumn(const std::unique_ptr& reader, int i); +RcppExport SEXP _arrow_ipc___feather___TableReader__GetColumn(SEXP readerSEXP, SEXP iSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::unique_ptr& >::type reader(readerSEXP); + Rcpp::traits::input_parameter< int >::type i(iSEXP); + rcpp_result_gen = Rcpp::wrap(ipc___feather___TableReader__GetColumn(reader, i)); + return rcpp_result_gen; +END_RCPP +} +// ipc___feather___TableReader__Read +std::shared_ptr ipc___feather___TableReader__Read(const std::unique_ptr& reader); +RcppExport SEXP _arrow_ipc___feather___TableReader__Read(SEXP readerSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::unique_ptr& >::type reader(readerSEXP); + rcpp_result_gen = Rcpp::wrap(ipc___feather___TableReader__Read(reader)); + return rcpp_result_gen; +END_RCPP +} +// ipc___feather___TableReader__Open +std::unique_ptr ipc___feather___TableReader__Open(const std::shared_ptr& stream); +RcppExport SEXP _arrow_ipc___feather___TableReader__Open(SEXP streamSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::shared_ptr& >::type stream(streamSEXP); + rcpp_result_gen = Rcpp::wrap(ipc___feather___TableReader__Open(stream)); + return rcpp_result_gen; +END_RCPP +} // Field__initialize std::shared_ptr Field__initialize(const std::string& name, const std::shared_ptr& type, bool nullable); RcppExport SEXP _arrow_Field__initialize(SEXP nameSEXP, SEXP typeSEXP, SEXP nullableSEXP) { @@ -1911,6 +2078,21 @@ static const R_CallMethodDef CallEntries[] = { {"_arrow_DictionaryType__name", (DL_FUNC) &_arrow_DictionaryType__name, 1}, {"_arrow_DictionaryType__dictionary", (DL_FUNC) &_arrow_DictionaryType__dictionary, 1}, {"_arrow_DictionaryType__ordered", (DL_FUNC) &_arrow_DictionaryType__ordered, 1}, + {"_arrow_ipc___feather___TableWriter__SetDescription", (DL_FUNC) &_arrow_ipc___feather___TableWriter__SetDescription, 2}, + {"_arrow_ipc___feather___TableWriter__SetNumRows", (DL_FUNC) &_arrow_ipc___feather___TableWriter__SetNumRows, 2}, + {"_arrow_ipc___feather___TableWriter__Append", (DL_FUNC) &_arrow_ipc___feather___TableWriter__Append, 3}, + {"_arrow_ipc___feather___TableWriter__Finalize", (DL_FUNC) &_arrow_ipc___feather___TableWriter__Finalize, 1}, + {"_arrow_ipc___feather___TableWriter__Open", (DL_FUNC) &_arrow_ipc___feather___TableWriter__Open, 1}, + {"_arrow_ipc___TableWriter__RecordBatch__WriteFeather", (DL_FUNC) &_arrow_ipc___TableWriter__RecordBatch__WriteFeather, 2}, + {"_arrow_ipc___feather___TableReader__GetDescription", (DL_FUNC) &_arrow_ipc___feather___TableReader__GetDescription, 1}, + {"_arrow_ipc___feather___TableReader__HasDescription", (DL_FUNC) &_arrow_ipc___feather___TableReader__HasDescription, 1}, + {"_arrow_ipc___feather___TableReader__version", (DL_FUNC) &_arrow_ipc___feather___TableReader__version, 1}, + {"_arrow_ipc___feather___TableReader__num_rows", (DL_FUNC) &_arrow_ipc___feather___TableReader__num_rows, 1}, + {"_arrow_ipc___feather___TableReader__num_columns", (DL_FUNC) &_arrow_ipc___feather___TableReader__num_columns, 1}, + {"_arrow_ipc___feather___TableReader__GetColumnName", (DL_FUNC) &_arrow_ipc___feather___TableReader__GetColumnName, 2}, + {"_arrow_ipc___feather___TableReader__GetColumn", (DL_FUNC) &_arrow_ipc___feather___TableReader__GetColumn, 2}, + {"_arrow_ipc___feather___TableReader__Read", (DL_FUNC) &_arrow_ipc___feather___TableReader__Read, 1}, + {"_arrow_ipc___feather___TableReader__Open", (DL_FUNC) &_arrow_ipc___feather___TableReader__Open, 1}, {"_arrow_Field__initialize", (DL_FUNC) &_arrow_Field__initialize, 3}, {"_arrow_Field__ToString", (DL_FUNC) &_arrow_Field__ToString, 1}, {"_arrow_Field__name", (DL_FUNC) &_arrow_Field__name, 1}, diff --git a/r/src/arrow_types.h b/r/src/arrow_types.h index 723fbd8f4713a..dbb48b3da8df6 100644 --- a/r/src/arrow_types.h +++ b/r/src/arrow_types.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/r/src/feather.cpp b/r/src/feather.cpp new file mode 100644 index 0000000000000..7b84deefadb9c --- /dev/null +++ b/r/src/feather.cpp @@ -0,0 +1,130 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include "arrow_types.h" + +using namespace Rcpp; + +// ---------- TableWriter + +// [[Rcpp::export]] +void ipc___feather___TableWriter__SetDescription( + const std::unique_ptr& writer, + const std::string& description) { + writer->SetDescription(description); +} + +// [[Rcpp::export]] +void ipc___feather___TableWriter__SetNumRows( + const std::unique_ptr& writer, int64_t num_rows) { + writer->SetNumRows(num_rows); +} + +// [[Rcpp::export]] +void ipc___feather___TableWriter__Append( + const std::unique_ptr& writer, + const std::string& name, const std::shared_ptr& values) { + STOP_IF_NOT_OK(writer->Append(name, *values)); +} + +// [[Rcpp::export]] +void ipc___feather___TableWriter__Finalize( + const std::unique_ptr& writer) { + STOP_IF_NOT_OK(writer->Finalize()); +} + +// [[Rcpp::export]] +std::unique_ptr ipc___feather___TableWriter__Open( + const std::shared_ptr& stream) { + std::unique_ptr writer; + STOP_IF_NOT_OK(arrow::ipc::feather::TableWriter::Open(stream, &writer)); + return writer; +} + +// [[Rcpp::export]] +void ipc___TableWriter__RecordBatch__WriteFeather( + const std::unique_ptr& writer, + const std::shared_ptr& batch) { + writer->SetNumRows(batch->num_rows()); + + for (int i = 0; i < batch->num_columns(); i++) { + STOP_IF_NOT_OK(writer->Append(batch->column_name(i), *batch->column(i))); + } + STOP_IF_NOT_OK(writer->Finalize()); +} + +// ----------- TableReader + +// [[Rcpp::export]] +std::string ipc___feather___TableReader__GetDescription( + const std::unique_ptr& reader) { + return reader->GetDescription(); +} + +// [[Rcpp::export]] +bool ipc___feather___TableReader__HasDescription( + const std::unique_ptr& reader) { + return reader->HasDescription(); +} + +// [[Rcpp::export]] +int ipc___feather___TableReader__version( + const std::unique_ptr& reader) { + return reader->version(); +} + +// [[Rcpp::export]] +int64_t ipc___feather___TableReader__num_rows( + const std::unique_ptr& reader) { + return reader->num_rows(); +} + +// [[Rcpp::export]] +int64_t ipc___feather___TableReader__num_columns( + const std::unique_ptr& reader) { + return reader->num_columns(); +} + +// [[Rcpp::export]] +std::string ipc___feather___TableReader__GetColumnName( + const std::unique_ptr& reader, int i) { + return reader->GetColumnName(i); +} + +// [[Rcpp::export]] +std::shared_ptr ipc___feather___TableReader__GetColumn( + const std::unique_ptr& reader, int i) { + std::shared_ptr column; + STOP_IF_NOT_OK(reader->GetColumn(i, &column)); + return column; +} + +// [[Rcpp::export]] +std::shared_ptr ipc___feather___TableReader__Read( + const std::unique_ptr& reader) { + std::shared_ptr table; + STOP_IF_NOT_OK(reader->Read(&table)); + return table; +} + +// [[Rcpp::export]] +std::unique_ptr ipc___feather___TableReader__Open( + const std::shared_ptr& stream) { + std::unique_ptr reader; + STOP_IF_NOT_OK(arrow::ipc::feather::TableReader::Open(stream, &reader)); + return reader; +} diff --git a/r/src/field.cpp b/r/src/field.cpp index 417694c1aff1d..146525b4317bd 100644 --- a/r/src/field.cpp +++ b/r/src/field.cpp @@ -17,8 +17,6 @@ #include "arrow_types.h" -// [[Rcpp::plugins(cpp11)]] - using namespace Rcpp; // [[Rcpp::export]] diff --git a/r/tests/testthat/test-feather.R b/r/tests/testthat/test-feather.R new file mode 100644 index 0000000000000..f6d9bee581d66 --- /dev/null +++ b/r/tests/testthat/test-feather.R @@ -0,0 +1,58 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +context("Feather") + +test_that("feather read/write round trip", { + tib <- tibble::tibble(x = 1:10, y = rnorm(10), z = letters[1:10]) + + tf1 <- local_tempfile() + write_feather(tib, tf1) + expect_true(fs::file_exists(tf1)) + + tf2 <- fs::path_abs(local_tempfile()) + write_feather(tib, tf2) + expect_true(fs::file_exists(tf2)) + + tf3 <- local_tempfile() + stream <- close_on_exit(file_output_stream(tf3)) + write_feather(tib, stream) + expect_true(fs::file_exists(tf3)) + + tab1 <- read_feather(tf1) + expect_is(tab1, "arrow::Table") + + tab2 <- read_feather(tf2) + expect_is(tab2, "arrow::Table") + + tab3 <- read_feather(tf3) + expect_is(tab3, "arrow::Table") + + # reading directly from arrow::io::MemoryMappedFile + tab4 <- read_feather(mmap_open(tf3)) + expect_is(tab4, "arrow::Table") + + # reading directly from arrow::io::ReadableFile + tab5 <- read_feather(file_open(tf3)) + expect_is(tab5, "arrow::Table") + + expect_equal(tib, as_tibble(tab1)) + expect_equal(tib, as_tibble(tab2)) + expect_equal(tib, as_tibble(tab3)) + expect_equal(tib, as_tibble(tab4)) + expect_equal(tib, as_tibble(tab5)) +})