.. 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.

.. default-domain:: cpp
.. highlight:: cpp

.. cpp:namespace:: arrow::csv

=================
Reading CSV files
=================

Arrow provides a fast CSV reader allowing ingestion of external data
as Arrow tables.

Basic usage
===========

A CSV file is read from a :class:`~arrow::io::InputStream`.

.. code-block:: cpp

   #include "arrow/csv/api.h"

   {
      // ...
      arrow::Status st;
      arrow::MemoryPool* pool = default_memory_pool();
      std::shared_ptr<arrow::io::InputStream> input = ...;

      auto read_options = arrow::csv::ReadOptions::Defaults();
      auto parse_options = arrow::csv::ParseOptions::Defaults();
      auto convert_options = arrow::csv::ConvertOptions::Defaults();

      // Instantiate TableReader from input stream and options
      std::shared_ptr<arrow::csv::TableReader> reader;
      st = arrow::csv::TableReader::Make(pool, input, read_options,
                                         parse_options, convert_options,
                                         &reader);
      if (!st.ok()) {
         // Handle TableReader instantiation error...
      }

      std::shared_ptr<arrow::Table> table;
      // Read table from CSV file
      st = reader->Read(&table);
      if (!st.ok()) {
         // Handle CSV read error
         // (for example a CSV syntax error or failed type conversion)
      }
   }

Column names
============

There are three possible ways to infer column names from the CSV file:

* By default, the column names are read from the first row in the CSV file
* If :member:`ReadOptions::column_names` is set, it forces the column
  names in the table to these values (the first row in the CSV file is
  read as data)
* If :member:`ReadOptions::autogenerate_column_names` is true, column names
  will be autogenerated with the pattern "f0", "f1"... (the first row in the
  CSV file is read as data)

Column selection
================

By default, Arrow reads all columns in the CSV file.  You can narrow the
selection of columns with the :member:`ConvertOptions::include_columns`
option.  If some columns in :member:`ConvertOptions::include_columns`
are missing from the CSV file, an error will be emitted unless
:member:`ConvertOptions::include_missing_columns` is true, in which case
the missing columns are assumed to contain all-null values.

Interaction with column names
-----------------------------

If both :member:`ReadOptions::column_names` and
:member:`ConvertOptions::include_columns` are specified,
the :member:`ReadOptions::column_names` are assumed to map to CSV columns,
and :member:`ConvertOptions::include_columns` is a subset of those column
names that will part of the Arrow Table.

Data types
==========

By default, the CSV reader infers the most appropriate data type for each
column.  Type inference considers the following data types, in order:

* Null
* Int64
* Boolean
* Timestamp (with seconds unit)
* Float64
* String
* Binary

It is possible to override type inference for select columns by setting
the :member:`ConvertOptions::column_types` option.  Explicit data types
can be chosen from the following list:

* Null
* All Integer types
* Float32 and Float64
* Decimal128
* Boolean
* Timestamp
* Binary and Large Binary
* String and Large String (with optional UTF8 input validation)
* Fixed-Size Binary

Other data types do not support conversion from CSV values and will error out.

Nulls
-----

Null values are recognized from the spellings stored in
:member:`ConvertOptions::null_values`.  The :func:`ConvertOptions::Defaults`
factory method will initialize a number of conventional null spellings such
as ``N/A``.

Performance
===========

By default, the CSV reader will parallelize reads in order to exploit all
CPU cores on your machine.  You can change this setting in
:member:`ReadOptions::use_threads`.  A reasonable expectation is at least
100 MB/s per core on a modern desktop machine (measured in source CSV bytes,
not target Arrow data bytes).
