blob: 7b8a4e55cec8bd9d4c8b568a9a6e78e8a37de026 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en" data-content_root="" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Introduction &#8212; Apache Arrow v21.0.0</title>
<script data-cfasync="false">
document.documentElement.dataset.mode = localStorage.getItem("mode") || "";
document.documentElement.dataset.theme = localStorage.getItem("theme") || "";
</script>
<!--
this give us a css class that will be invisible only if js is disabled
-->
<noscript>
<style>
.pst-js-only { display: none !important; }
</style>
</noscript>
<!-- Loaded before other Sphinx assets -->
<link href="../_static/styles/theme.css?digest=8878045cc6db502f8baf" rel="stylesheet" />
<link href="../_static/styles/pydata-sphinx-theme.css?digest=8878045cc6db502f8baf" rel="stylesheet" />
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css" />
<link rel="stylesheet" type="text/css" href="../_static/sphinx-design.4cbf315f70debaebd550c87a6162cf0f.min.css" />
<link rel="stylesheet" type="text/css" href="../_static/theme_overrides.css" />
<!-- So that users can add custom icons -->
<script src="../_static/scripts/fontawesome.js?digest=8878045cc6db502f8baf"></script>
<!-- Pre-loaded scripts that we'll load fully later -->
<link rel="preload" as="script" href="../_static/scripts/bootstrap.js?digest=8878045cc6db502f8baf" />
<link rel="preload" as="script" href="../_static/scripts/pydata-sphinx-theme.js?digest=8878045cc6db502f8baf" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<script src="../_static/clipboard.min.js"></script>
<script src="../_static/copybutton.js"></script>
<script src="../_static/design-tabs.js"></script>
<script>DOCUMENTATION_OPTIONS.pagename = 'format/Intro';</script>
<script>
DOCUMENTATION_OPTIONS.theme_version = '0.16.1';
DOCUMENTATION_OPTIONS.theme_switcher_json_url = '/docs/_static/versions.json';
DOCUMENTATION_OPTIONS.theme_switcher_version_match = '';
DOCUMENTATION_OPTIONS.show_version_warning_banner =
false;
</script>
<link rel="canonical" href="https://arrow.apache.org/docs/format/Intro.html" />
<link rel="icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Arrow Columnar Format" href="Columnar.html" />
<link rel="prev" title="Specifications" href="index.html" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="docsearch:language" content="en"/>
<meta name="docsearch:version" content="21.0.0" />
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/* We explicitly disable cookie tracking to avoid privacy issues */
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '20']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body data-bs-spy="scroll" data-bs-target=".bd-toc-nav" data-offset="180" data-bs-root-margin="0px 0px -60%" data-default-mode="">
<div id="pst-skip-link" class="skip-link d-print-none"><a href="#main-content">Skip to main content</a></div>
<div id="pst-scroll-pixel-helper"></div>
<button type="button" class="btn rounded-pill" id="pst-back-to-top">
<i class="fa-solid fa-arrow-up"></i>Back to top</button>
<dialog id="pst-search-dialog">
<form class="bd-search d-flex align-items-center"
action="../search.html"
method="get">
<i class="fa-solid fa-magnifying-glass"></i>
<input type="search"
class="form-control"
name="q"
placeholder="Search the docs ..."
aria-label="Search the docs ..."
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"/>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd>K</kbd></span>
</form>
</dialog>
<div class="pst-async-banner-revealer d-none">
<aside id="bd-header-version-warning" class="d-none d-print-none" aria-label="Version warning"></aside>
</div>
<header class="bd-header navbar navbar-expand-lg bd-navbar d-print-none">
<div class="bd-header__inner bd-page-width">
<button class="pst-navbar-icon sidebar-toggle primary-toggle" aria-label="Site navigation">
<span class="fa-solid fa-bars"></span>
</button>
<div class=" navbar-header-items__start">
<div class="navbar-item">
<a class="navbar-brand logo" href="../index.html">
<img src="../_static/arrow.png" class="logo__image only-light" alt="Apache Arrow v21.0.0 - Home"/>
<img src="../_static/arrow-dark.png" class="logo__image only-dark pst-js-only" alt="Apache Arrow v21.0.0 - Home"/>
</a></div>
</div>
<div class=" navbar-header-items">
<div class="me-auto navbar-header-items__center">
<div class="navbar-item">
<nav>
<ul class="bd-navbar-elements navbar-nav">
<li class="nav-item current active">
<a class="nav-link nav-internal" href="index.html">
Specifications
</a>
</li>
<li class="nav-item ">
<a class="nav-link nav-internal" href="../developers/index.html">
Development
</a>
</li>
<li class="nav-item ">
<a class="nav-link nav-internal" href="../implementations.html">
Implementations
</a>
</li>
</ul>
</nav></div>
</div>
<div class="navbar-header-items__end">
<div class="navbar-item navbar-persistent--container">
<button class="btn search-button-field search-button__button pst-js-only" title="Search" aria-label="Search" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="fa-solid fa-magnifying-glass"></i>
<span class="search-button__default-text">Search</span>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd class="kbd-shortcut__modifier">K</kbd></span>
</button>
</div>
<div class="navbar-item"><div class="kapa-ai-bot">
<script
async
src="https://widget.kapa.ai/kapa-widget.bundle.js"
data-website-id="9db461d5-ac77-4b3f-a5c5-75efa78339d2"
data-project-name="Apache Arrow"
data-project-color="#000000"
data-project-logo="https://arrow.apache.org/img/arrow-logo_chevrons_white-txt_black-bg.png"
data-modal-disclaimer="This is a custom LLM with access to all [Arrow documentation](https://arrow.apache.org/docs/). Please include the language you are using in your question, e.g., Python, C++, Java, R, etc."
data-consent-required="true"
data-user-analytics-cookie-enabled="false"
data-consent-screen-disclaimer="By clicking &quot;I agree, let's chat&quot;, you consent to the use of the AI assistant in accordance with kapa.ai's [Privacy Policy](https://www.kapa.ai/content/privacy-policy). This service uses reCAPTCHA, which requires your consent to Google's [Privacy Policy](https://policies.google.com/privacy) and [Terms of Service](https://policies.google.com/terms). By proceeding, you explicitly agree to both kapa.ai's and Google's privacy policies."
></script>
</div>
</div>
<div class="navbar-item">
<div class="version-switcher__container dropdown pst-js-only">
<button id="pst-version-switcher-button-2"
type="button"
class="version-switcher__button btn btn-sm dropdown-toggle"
data-bs-toggle="dropdown"
aria-haspopup="listbox"
aria-controls="pst-version-switcher-list-2"
aria-label="Version switcher list"
>
Choose version <!-- this text may get changed later by javascript -->
<span class="caret"></span>
</button>
<div id="pst-version-switcher-list-2"
class="version-switcher__menu dropdown-menu list-group-flush py-0"
role="listbox" aria-labelledby="pst-version-switcher-button-2">
<!-- dropdown will be populated by javascript on page load -->
</div>
</div></div>
<div class="navbar-item">
<button class="btn btn-sm nav-link pst-navbar-icon theme-switch-button pst-js-only" aria-label="Color mode" data-bs-title="Color mode" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="theme-switch fa-solid fa-sun fa-lg" data-mode="light" title="Light"></i>
<i class="theme-switch fa-solid fa-moon fa-lg" data-mode="dark" title="Dark"></i>
<i class="theme-switch fa-solid fa-circle-half-stroke fa-lg" data-mode="auto" title="System Settings"></i>
</button></div>
<div class="navbar-item"><ul class="navbar-icon-links"
aria-label="Icon Links">
<li class="nav-item">
<a href="https://github.com/apache/arrow" title="GitHub" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-square-github fa-lg" aria-hidden="true"></i>
<span class="sr-only">GitHub</span></a>
</li>
<li class="nav-item">
<a href="https://www.linkedin.com/company/apache-arrow/" title="LinkedIn" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-linkedin fa-lg" aria-hidden="true"></i>
<span class="sr-only">LinkedIn</span></a>
</li>
<li class="nav-item">
<a href="https://bsky.app/profile/arrow.apache.org" title="BlueSky" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-bluesky fa-lg" aria-hidden="true"></i>
<span class="sr-only">BlueSky</span></a>
</li>
</ul></div>
</div>
</div>
<div class="navbar-persistent--mobile">
<button class="btn search-button-field search-button__button pst-js-only" title="Search" aria-label="Search" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="fa-solid fa-magnifying-glass"></i>
<span class="search-button__default-text">Search</span>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd class="kbd-shortcut__modifier">K</kbd></span>
</button>
</div>
<button class="pst-navbar-icon sidebar-toggle secondary-toggle" aria-label="On this page">
<span class="fa-solid fa-outdent"></span>
</button>
</div>
</header>
<div class="bd-container">
<div class="bd-container__inner bd-page-width">
<dialog id="pst-primary-sidebar-modal"></dialog>
<div id="pst-primary-sidebar" class="bd-sidebar-primary bd-sidebar">
<div class="sidebar-header-items sidebar-primary__section">
<div class="sidebar-header-items__center">
<div class="navbar-item">
<nav>
<ul class="bd-navbar-elements navbar-nav">
<li class="nav-item current active">
<a class="nav-link nav-internal" href="index.html">
Specifications
</a>
</li>
<li class="nav-item ">
<a class="nav-link nav-internal" href="../developers/index.html">
Development
</a>
</li>
<li class="nav-item ">
<a class="nav-link nav-internal" href="../implementations.html">
Implementations
</a>
</li>
</ul>
</nav></div>
</div>
<div class="sidebar-header-items__end">
<div class="navbar-item"><div class="kapa-ai-bot">
<script
async
src="https://widget.kapa.ai/kapa-widget.bundle.js"
data-website-id="9db461d5-ac77-4b3f-a5c5-75efa78339d2"
data-project-name="Apache Arrow"
data-project-color="#000000"
data-project-logo="https://arrow.apache.org/img/arrow-logo_chevrons_white-txt_black-bg.png"
data-modal-disclaimer="This is a custom LLM with access to all [Arrow documentation](https://arrow.apache.org/docs/). Please include the language you are using in your question, e.g., Python, C++, Java, R, etc."
data-consent-required="true"
data-user-analytics-cookie-enabled="false"
data-consent-screen-disclaimer="By clicking &quot;I agree, let's chat&quot;, you consent to the use of the AI assistant in accordance with kapa.ai's [Privacy Policy](https://www.kapa.ai/content/privacy-policy). This service uses reCAPTCHA, which requires your consent to Google's [Privacy Policy](https://policies.google.com/privacy) and [Terms of Service](https://policies.google.com/terms). By proceeding, you explicitly agree to both kapa.ai's and Google's privacy policies."
></script>
</div>
</div>
<div class="navbar-item">
<div class="version-switcher__container dropdown pst-js-only">
<button id="pst-version-switcher-button-3"
type="button"
class="version-switcher__button btn btn-sm dropdown-toggle"
data-bs-toggle="dropdown"
aria-haspopup="listbox"
aria-controls="pst-version-switcher-list-3"
aria-label="Version switcher list"
>
Choose version <!-- this text may get changed later by javascript -->
<span class="caret"></span>
</button>
<div id="pst-version-switcher-list-3"
class="version-switcher__menu dropdown-menu list-group-flush py-0"
role="listbox" aria-labelledby="pst-version-switcher-button-3">
<!-- dropdown will be populated by javascript on page load -->
</div>
</div></div>
<div class="navbar-item">
<button class="btn btn-sm nav-link pst-navbar-icon theme-switch-button pst-js-only" aria-label="Color mode" data-bs-title="Color mode" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="theme-switch fa-solid fa-sun fa-lg" data-mode="light" title="Light"></i>
<i class="theme-switch fa-solid fa-moon fa-lg" data-mode="dark" title="Dark"></i>
<i class="theme-switch fa-solid fa-circle-half-stroke fa-lg" data-mode="auto" title="System Settings"></i>
</button></div>
<div class="navbar-item"><ul class="navbar-icon-links"
aria-label="Icon Links">
<li class="nav-item">
<a href="https://github.com/apache/arrow" title="GitHub" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-square-github fa-lg" aria-hidden="true"></i>
<span class="sr-only">GitHub</span></a>
</li>
<li class="nav-item">
<a href="https://www.linkedin.com/company/apache-arrow/" title="LinkedIn" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-linkedin fa-lg" aria-hidden="true"></i>
<span class="sr-only">LinkedIn</span></a>
</li>
<li class="nav-item">
<a href="https://bsky.app/profile/arrow.apache.org" title="BlueSky" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-bluesky fa-lg" aria-hidden="true"></i>
<span class="sr-only">BlueSky</span></a>
</li>
</ul></div>
</div>
</div>
<div class="sidebar-primary-items__start sidebar-primary__section">
<div class="sidebar-primary-item">
<nav class="bd-docs-nav bd-links"
aria-label="Section Navigation">
<p class="bd-links__title" role="heading" aria-level="1">Section Navigation</p>
<div class="bd-toc-item navbar-nav"><ul class="current nav bd-sidenav">
<li class="toctree-l1 current active"><a class="current reference internal" href="#">Introduction</a></li>
<li class="toctree-l1"><a class="reference internal" href="Columnar.html">Arrow Columnar Format</a></li>
<li class="toctree-l1"><a class="reference internal" href="Versioning.html">Format Versioning and Stability</a></li>
<li class="toctree-l1"><a class="reference internal" href="Changing.html">Changing the Apache Arrow Format Specification</a></li>
<li class="toctree-l1"><a class="reference internal" href="CanonicalExtensions.html">Canonical Extension Types</a></li>
<li class="toctree-l1"><a class="reference internal" href="Other.html">Other Data Structures</a></li>
<li class="toctree-l1 has-children"><a class="reference internal" href="CDataInterface.html">The Arrow C data interface</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul>
<li class="toctree-l2"><a class="reference internal" href="CDataInterface/PyCapsuleInterface.html">The Arrow PyCapsule Interface</a></li>
</ul>
</details></li>
<li class="toctree-l1"><a class="reference internal" href="CStreamInterface.html">The Arrow C stream interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="CDeviceDataInterface.html">The Arrow C Device data interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="StatisticsSchema.html">Statistics schema</a></li>
<li class="toctree-l1"><a class="reference internal" href="DissociatedIPC.html">Dissociated IPC Protocol</a></li>
<li class="toctree-l1"><a class="reference internal" href="Flight.html">Arrow Flight RPC</a></li>
<li class="toctree-l1"><a class="reference internal" href="FlightSql.html">Arrow Flight SQL</a></li>
<li class="toctree-l1"><a class="reference internal" href="ADBC.html">ADBC: Arrow Database Connectivity</a></li>
<li class="toctree-l1"><a class="reference internal" href="Integration.html">Integration Testing</a></li>
<li class="toctree-l1"><a class="reference internal" href="Glossary.html">Glossary</a></li>
</ul>
</div>
</nav></div>
</div>
<div class="sidebar-primary-items__end sidebar-primary__section">
<div class="sidebar-primary-item">
<div id="ethical-ad-placement"
class="flat"
data-ea-publisher="readthedocs"
data-ea-type="readthedocs-sidebar"
data-ea-manual="true">
</div></div>
</div>
</div>
<main id="main-content" class="bd-main" role="main">
<div class="bd-content">
<div class="bd-article-container">
<div class="bd-header-article d-print-none">
<div class="header-article-items header-article__inner">
<div class="header-article-items__start">
<div class="header-article-item">
<nav aria-label="Breadcrumb" class="d-print-none">
<ul class="bd-breadcrumbs">
<li class="breadcrumb-item breadcrumb-home">
<a href="../index.html" class="nav-link" aria-label="Home">
<i class="fa-solid fa-home"></i>
</a>
</li>
<li class="breadcrumb-item"><a href="index.html" class="nav-link">Specifications</a></li>
<li class="breadcrumb-item active" aria-current="page"><span class="ellipsis">Introduction</span></li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div id="searchbox"></div>
<article class="bd-article">
<section id="introduction">
<h1>Introduction<a class="headerlink" href="#introduction" title="Permalink to this heading">#</a></h1>
<p>Apache Arrow was born from the need for a set of standards around
tabular data representation and interchange between systems.
The adoption of these standards reduces computing costs of data
serialization/deserialization and implementation costs across
systems implemented in different programming languages.</p>
<p>The Apache Arrow specification can be implemented in any programming
language but official implementations for many languages are available.
An implementation consists of format definitions using the constructs
offered by the language and common in-memory data processing algorithms
(e.g. slicing and concatenating). Users can extend and use the utilities
provided by the Apache Arrow implementation in their programming
language of choice. Some implementations are further ahead and feature a
vast set of algorithms for in-memory analytical data processing. More detail
about how implementations differ can be found on the <a class="reference internal" href="../status.html"><span class="doc">Implementation Status</span></a> page.</p>
<p>Apart from this initial vision, Arrow has grown to also develop a
multi-language collection of libraries for solving problems related to
in-memory analytical data processing. This covers topics like:</p>
<ul class="simple">
<li><p>Zero-copy shared memory and RPC-based data movement</p></li>
<li><p>Reading and writing file formats (like CSV, <a class="reference external" href="https://orc.apache.org/">Apache ORC</a>, and <a class="reference external" href="https://parquet.apache.org/">Apache Parquet</a>)</p></li>
<li><p>In-memory analytics and query processing</p></li>
</ul>
<section id="arrow-columnar-format">
<h2>Arrow Columnar Format<a class="headerlink" href="#arrow-columnar-format" title="Permalink to this heading">#</a></h2>
<p>Apache Arrow focuses on tabular data. For an example, let’s consider
we have data that can be organized into a table:</p>
<figure class="align-default" id="id1">
<a class="reference internal image-reference" href="../_images/columnar-diagram_1.svg"><img alt="Diagram with tabular data of 4 rows and columns." height="217" src="../_images/columnar-diagram_1.svg" width="483" /></a>
<figcaption>
<p><span class="caption-text">Diagram of a tabular data structure.</span><a class="headerlink" href="#id1" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
<p>Tabular data can be represented in memory using a row-based format or a
column-based format. The row-based format stores data row-by-row, meaning the rows
are adjacent in the computer memory:</p>
<figure class="align-default" id="id2">
<img alt="Tabular data being structured row by row in computer memory." src="../_images/columnar-diagram_2.svg" /><figcaption>
<p><span class="caption-text">Tabular data being saved in memory row by row.</span><a class="headerlink" href="#id2" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
<p>In a columnar format, the data is organized column-by-column instead.
This organization makes analytical operations like filtering, grouping,
aggregations and others, more efficient thanks to memory locality.
When processing the data, the memory locations accessed by the CPU tend
to be near one another. By keeping the data contiguous in memory, it also
enables vectorization of the computations. Most modern CPUs have
<a class="reference external" href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">SIMD instructions</a> (a single instruction that operates on multiple values at
once) enabling parallel processing and execution of operations on vector data
using a single CPU instruction.</p>
<p>Apache Arrow is solving this exact problem. It is the specification that
uses the columnar layout.</p>
<figure class="align-default" id="id3">
<img alt="Tabular data being structured column by column in computer memory." src="../_images/columnar-diagram_3.svg" /><figcaption>
<p><span class="caption-text">The same tabular data being saved in memory column by column.</span><a class="headerlink" href="#id3" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
<p>Each column is called an <strong>Array</strong> in Arrow terminology. Arrays can be of
different data types and the way their values are stored in memory varies among
the data types. The specification of how these values are arranged in memory is
what we call a <strong>physical memory layout</strong>. One contiguous region of memory that
stores data for arrays is called a <strong>Buffer</strong>. An array consists of one or more
buffers.</p>
<p>Next sections give an introduction to Arrow Columnar Format explaining the
different physical layouts. The full specification of the format can be found
at <a class="reference internal" href="Columnar.html#format-columnar"><span class="std std-ref">Arrow Columnar Format</span></a>.</p>
</section>
<section id="support-for-null-values">
<h2>Support for Null Values<a class="headerlink" href="#support-for-null-values" title="Permalink to this heading">#</a></h2>
<p>Arrow supports missing values or “nulls” for all data types: any value
in an array may be semantically null, whether primitive or nested data type.</p>
<p>In Arrow, a dedicated buffer, known as the validity (or “null”) bitmap,
is used alongside the data indicating whether each value in the array is
null or not: a value of 1 means that the value is not-null (“valid”), whereas
a value of 0 indicates that the value is null.</p>
<p>This validity bitmap is optional: if there are no missing values in
the array the buffer does not need to be allocated (as in the example
column 1 in the diagram below).</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>We read validity bitmaps right-to-left within a group of 8 bits due to
<a class="reference external" href="https://en.wikipedia.org/wiki/Bit_numbering">least-significant bit numbering</a>
being used.</p>
<p>This is also how we have represented the validity bitmaps in the
diagrams included in this document.</p>
</div>
</section>
<section id="primitive-layouts">
<h2>Primitive Layouts<a class="headerlink" href="#primitive-layouts" title="Permalink to this heading">#</a></h2>
<section id="fixed-size-primitive-layout">
<h3>Fixed Size Primitive Layout<a class="headerlink" href="#fixed-size-primitive-layout" title="Permalink to this heading">#</a></h3>
<p>A primitive column represents an array of values where each value
has the same physical size measured in bytes. Data types that use the
fixed size primitive layout are, for example, signed and unsigned
integer data types, floating point numbers, boolean, decimal and temporal
data types.</p>
<figure class="align-default" id="id4">
<img alt="Diagram is showing the difference between the primitive data type presented in a Table and the data actually stored in computer memory." src="../_images/primitive-diagram.svg" /><figcaption>
<p><span class="caption-text">Physical layout diagram for primitive data types.</span><a class="headerlink" href="#id4" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The boolean data type is represented with a primitive layout where the
values are encoded in bits instead of bytes. That means the physical
layout includes a values bitmap buffer and possibly a validity bitmap
buffer.</p>
<figure class="align-default" id="id5">
<img alt="Diagram is showing the difference between the boolean data type presented in a Table and the data actually stored in computer memory." src="../_images/bool-diagram.svg" /><figcaption>
<p><span class="caption-text">Physical layout diagram for boolean data type.</span><a class="headerlink" href="#id5" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Arrow also has a concept of Null data type where all values are null. In
this case no buffers are allocated.</p>
</div>
</section>
<section id="variable-length-binary-and-string">
<h3>Variable length binary and string<a class="headerlink" href="#variable-length-binary-and-string" title="Permalink to this heading">#</a></h3>
<p>In contrast to the fixed size primitive layout, the variable length layout
allows representing an array where each element can have a variable size
in bytes. This layout is used for binary and string data.</p>
<p>The bytes of all elements in a binary or string column are stored together
consecutively in a single buffer or region of memory. To know where each element
of the column starts and ends, the physical layout also includes integer offsets.
The offsets buffer is always one element longer than the array.
The last two offsets define the start and the end of the last
binary/string element.</p>
<p>Binary and string data types share the same physical layout. The only
difference between them is that a string-typed array is assumed to contain
valid UTF-8 string data.</p>
<p>The difference between binary/string and large binary/string is in the offset
data type. In the first case that is int32 and in the second it is int64.</p>
<p>The limitation of data types using 32 bit offsets is that they have a maximum size of
2GB per array. One can still use the non-large variants for bigger data, but
then multiple chunks are needed.</p>
<figure class="align-default" id="id6">
<img alt="Diagram is showing the difference between the variable length string data type presented in a Table and the data actually stored in computer memory." src="../_images/var-string-diagram.svg" /><figcaption>
<p><span class="caption-text">Physical layout diagram for variable length string data types.</span><a class="headerlink" href="#id6" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
</section>
<section id="variable-length-binary-and-string-view">
<h3>Variable length binary and string view<a class="headerlink" href="#variable-length-binary-and-string-view" title="Permalink to this heading">#</a></h3>
<p>This layout is an alternative for the variable length binary layout and is adapted
from TU Munich’s <a class="reference external" href="https://umbra-db.com/">UmbraDB</a> and is similar to the string layout used in <a class="reference external" href="https://duckdb.com">DuckDB</a> and
<a class="reference external" href="https://velox-lib.io/">Velox</a> (and sometimes also called “German strings”).</p>
<p>The main difference to the classical binary and string layout is the views buffer.
It includes the length of the string, and then either its characters appearing
inline (for small strings) or only the first 4 bytes of the string and an offset into
one of the potentially several data buffers. Because it uses an offset and length to refer
to the data buffer, the bytes of all elements do not need to be stored
consecutively in a single buffer. This enables out of order writing of
variable length elements into the array.</p>
<p>These properties are important for efficient string processing. The prefix
enables a profitable fast path for string comparisons, which are frequently
determined within the first four bytes. Selecting elements is a simple “gather”
operation on the fixed-width views buffer and does not need to rewrite the
values buffers.</p>
<figure class="align-default" id="id7">
<img alt="Diagram is showing the difference between the variable length string view data type presented in a Table and the data actually stored in computer memory." src="../_images/var-string-view-diagram.svg" /><figcaption>
<p><span class="caption-text">Physical layout diagram for variable length string view data type.</span><a class="headerlink" href="#id7" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
</section>
</section>
<section id="nested-layouts">
<h2>Nested Layouts<a class="headerlink" href="#nested-layouts" title="Permalink to this heading">#</a></h2>
<p>Nested data types introduce the concept of parent and child arrays. They express
relationships between physical value arrays in a nested data type structure.</p>
<p>Nested data types depend on one or more other child data types. For instance, List
is a nested data type (parent) that has one child (the data type of the values in
the list).</p>
<section id="list">
<h3>List<a class="headerlink" href="#list" title="Permalink to this heading">#</a></h3>
<p>The list data type enables representing an array where each element is a sequence
of elements of the same data type. The layout is similar to variable-size binary
or string layout as it has an offsets buffer to define where the sequence of values
for each element starts and ends, with all the values being stored consecutively
in a values child array.</p>
<p>The offsets in the list data type are int32 while in the large list the offsets
are int64.</p>
<figure class="align-default" id="id8">
<img alt="Diagram is showing the difference between the variable size list data type presented in a Table and the data actually stored in computer memory." src="../_images/var-list-diagram.svg" /><figcaption>
<p><span class="caption-text">Physical layout diagram for variable size list data type.</span><a class="headerlink" href="#id8" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
</section>
<section id="fixed-size-list">
<h3>Fixed Size List<a class="headerlink" href="#fixed-size-list" title="Permalink to this heading">#</a></h3>
<p>Fixed-size list is a special case of variable-size list where each column slot
contains a fixed size sequence meaning all lists are the same size and so the
offset buffer is no longer needed.</p>
<figure class="align-default" id="id9">
<img alt="Diagram is showing the difference between the fixed size list data type presented in a Table and the data actually stored in computer memory." src="../_images/fixed-list-diagram.svg" /><figcaption>
<p><span class="caption-text">Physical layout diagram for fixed size list data type.</span><a class="headerlink" href="#id9" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
</section>
<section id="list-view">
<h3>List View<a class="headerlink" href="#list-view" title="Permalink to this heading">#</a></h3>
<p>In contrast to the list type, list view type also has a size buffer together
with an offset buffer. The offsets continue to indicate the start of each
element but size is now saved in a separate size buffer. This allows
out-of-order offsets as the sizes aren’t derived from the consecutive
offsets anymore.</p>
<figure class="align-default" id="id10">
<img alt="Diagram is showing the difference between the variable size list view data type presented in a Table and the data actually stored in computer memory." src="../_images/var-list-view-diagram.svg" /><figcaption>
<p><span class="caption-text">Physical layout diagram for variable size list view data type.</span><a class="headerlink" href="#id10" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
</section>
<section id="struct">
<h3>Struct<a class="headerlink" href="#struct" title="Permalink to this heading">#</a></h3>
<p>A struct is a nested data type parameterized by an ordered sequence of fields
(a data type and a name).</p>
<ul class="simple">
<li><p>There is one child array for each field</p></li>
<li><p>Child arrays are independent and need not be adjacent to each other in
memory. They only need to have the same length.</p></li>
</ul>
<p>One can think of an individual struct field as a key-value pair where the
key is the field name and the child array its values. The field (key) is
saved in the schema and the values of a specific field (key) are saved in
the child array.</p>
<figure class="align-default" id="id11">
<img alt="Diagram is showing the difference between the struct data type presented in a Table and the data actually stored in computer memory." src="../_images/struct-diagram.svg" /><figcaption>
<p><span class="caption-text">Physical layout diagram for struct data type.</span><a class="headerlink" href="#id11" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
</section>
<section id="map">
<h3>Map<a class="headerlink" href="#map" title="Permalink to this heading">#</a></h3>
<p>The Map data type represents nested data where each value is a variable number of
key-value pairs. Its physical representation is the same as a list of <code class="docutils literal notranslate"><span class="pre">{key,</span> <span class="pre">value}</span></code>
structs.</p>
<p>The difference between the struct and map data types is that a struct holds the key
in the schema, requiring keys to be strings, and the values are stored in the
child arrays,
one for each field. There can be multiple keys and therefore multiple child arrays.
The map, on the other hand, has one child array holding all the different keys (that
thus all need to be of the same data type, but not necessarily strings) and a second
child array holding all the values. The values need to be of the same data type; however,
the data type doesn’t have to match that of the keys.</p>
<p>Also, the map stores the struct in a list and needs an offset as the list is
variable shape.</p>
<figure class="align-default" id="id12">
<img alt="Diagram is showing the difference between the map data type presented in a Table and the data actually stored in computer memory." src="../_images/map-diagram.svg" /><figcaption>
<p><span class="caption-text">Physical layout diagram for map data type.</span><a class="headerlink" href="#id12" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
</section>
<section id="union">
<h3>Union<a class="headerlink" href="#union" title="Permalink to this heading">#</a></h3>
<p>The union is a nested data type where each slot in the union has a value with a data type
chosen from a subset of possible Arrow data types. That means that a union array represents
a mixed-type array. Unlike other data types, unions do not have their own validity bitmap
and the nullness is determined by the child arrays.</p>
<p>Arrow defines two distinct union data types, “dense” and “sparse”.</p>
<section id="dense-union">
<h4>Dense Union<a class="headerlink" href="#dense-union" title="Permalink to this heading">#</a></h4>
<p>A Dense Union has one child array for each data type present in the mixed-type array and
two buffers of its own:</p>
<ul class="simple">
<li><p><strong>Types buffer:</strong> holds data type id for each slot of the array. Data type id is
frequently the index of the child array; however, the relationship between data type
ID and the child index is a parameter of the data type.</p></li>
<li><p><strong>Offsets buffer:</strong> holds relative offset into the respective child array for each
array slot.</p></li>
</ul>
<figure class="align-default" id="id13">
<img alt="Diagram is showing the difference between the dense union data type presented in a Table and the data actually stored in computer memory." src="../_images/dense-union-diagram.svg" /><figcaption>
<p><span class="caption-text">Physical layout diagram for dense union data type.</span><a class="headerlink" href="#id13" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
</section>
<section id="sparse-union">
<h4>Sparse union<a class="headerlink" href="#sparse-union" title="Permalink to this heading">#</a></h4>
<p>A sparse union has the same structure as a dense union, with the omission of the offsets
buffer. In this case, the child arrays are each equal in length to the length of the union.</p>
<figure class="align-default" id="id14">
<img alt="Diagram is showing the difference between the sparse union data type presented in a Table and the data actually stored in computer memory." src="../_images/sparse-union-diagram.svg" /><figcaption>
<p><span class="caption-text">Physical layout diagram for sparse union data type.</span><a class="headerlink" href="#id14" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
</section>
</section>
</section>
<section id="dictionary-encoded-layout">
<h2>Dictionary Encoded Layout<a class="headerlink" href="#dictionary-encoded-layout" title="Permalink to this heading">#</a></h2>
<p>Dictionary encoding can be effective when one has data with many repeated values.
The values are represented by integers referencing a dictionary usually consisting of
unique values.</p>
<figure class="align-default" id="id15">
<img alt="Diagram is showing the difference between the dictionary data type presented in a Table and the data actually stored in computer memory." src="../_images/dictionary-diagram.svg" /><figcaption>
<p><span class="caption-text">Physical layout diagram for dictionary data type.</span><a class="headerlink" href="#id15" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
</section>
<section id="run-end-encoded-layout">
<h2>Run-End Encoded Layout<a class="headerlink" href="#run-end-encoded-layout" title="Permalink to this heading">#</a></h2>
<p>Run-end encoding is well-suited for representing data containing sequences of the
same value. These sequences are called runs. A run-end encoded array has no buffers
of its own, but has two child arrays:</p>
<ul class="simple">
<li><p><strong>Run ends array:</strong> holds the index in the array where each run ends. The number
of run ends is the same as the length of its parent array.</p></li>
<li><p><strong>Values array:</strong> the actual values without repetitions (together with null values).</p></li>
</ul>
<p>Note that nulls of the parent array are strictly represented in the values array.</p>
<figure class="align-default" id="id16">
<img alt="Diagram is showing the difference between the run-end encoded data type presented in a Table and the data actually stored in computer memory." src="../_images/ree-diagram.svg" /><figcaption>
<p><span class="caption-text">Physical layout diagram for run-end encoded data type.</span><a class="headerlink" href="#id16" title="Permalink to this image">#</a></p>
</figcaption>
</figure>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<p>Table of all Arrow <a class="reference internal" href="Columnar.html#data-types"><span class="std std-ref">Data Types</span></a>.</p>
</div>
</section>
<section id="overview-of-arrow-terminology">
<h2>Overview of Arrow Terminology<a class="headerlink" href="#overview-of-arrow-terminology" title="Permalink to this heading">#</a></h2>
<p><strong>Physical layout</strong>
A specification for how to represent values of an array in memory.</p>
<p><strong>Buffer</strong>
A contiguous region of memory with a given length in bytes. Buffers are used to store data
for arrays. Sometimes we use the notion of number of elements in a buffer which can only be
used if we know the data type of the array that wraps this specific buffer.</p>
<p><strong>Array</strong>
A contiguous, one-dimensional sequence of values with known length where all values have the
same data type. An array consists of zero or more buffers.</p>
<p><strong>Chunked Array</strong>
A discontiguous, one-dimensional sequence of values with known length where all values have
the same data type. Consists of zero or more arrays, the “chunks”.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Chunked Array is a concept specific to certain implementations such as Arrow C++ and PyArrow.</p>
</div>
<p><strong>RecordBatch</strong>
A contiguous, two-dimensional data structure which consists of an ordered collection of arrays
of the same length.</p>
<p><strong>Schema</strong>
An ordered collection of fields that communicates all the data types of an object
like a RecordBatch or Table. Schemas can contain optional key/value metadata.</p>
<p><strong>Field</strong>
A Field includes a field name, a data type, a nullability flag and
optional key-value metadata for a specific column in a RecordBatch.</p>
<p><strong>Table</strong>
A discontiguous, two-dimensional chunk of data consisting of an ordered collection of Chunked
Arrays. All Chunked Arrays have the same length, but may have different types. Different columns
may be chunked differently.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Table is a concept specific to certain implementations such as Arrow C++ and PyArrow. In Java
implementation, for example, a Table is not a collection of Chunked Arrays but a collection of
RecordBatches.</p>
</div>
<img alt="A graphical representation of an Arrow Table and a Record Batch, with structure as described in text above." src="../_images/tables-versus-record-batches.svg" /><div class="admonition seealso">
<p class="admonition-title">See also</p>
<p>The <a class="reference internal" href="Glossary.html#glossary"><span class="std std-ref">Glossary</span></a> for more terms.</p>
</div>
</section>
<section id="extension-types">
<h2>Extension Types<a class="headerlink" href="#extension-types" title="Permalink to this heading">#</a></h2>
<p>In case the system or application needs to extend standard Arrow data types with
custom semantics, this is enabled by defining extension types.</p>
<p>Examples of an extension type are <a class="reference internal" href="CanonicalExtensions.html#uuid-extension"><span class="std std-ref">UUID</span></a> or
<a class="reference internal" href="CanonicalExtensions.html#fixed-shape-tensor-extension"><span class="std std-ref">Fixed shape tensor</span></a> extension type.</p>
<p>Extension types can be defined by annotating any of the built-in Arrow data types
(the “storage type”) with a custom type name and optional serialized representation
(<code class="docutils literal notranslate"><span class="pre">'ARROW:extension:name'</span></code> and <code class="docutils literal notranslate"><span class="pre">'ARROW:extension:metadata'</span></code> keys in the Field
metadata structure).</p>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<p>The <a class="reference internal" href="Columnar.html#format-metadata-extension-types"><span class="std std-ref">Extension Types</span></a> documentation.</p>
</div>
<section id="canonical-extension-types">
<h3>Canonical Extension Types<a class="headerlink" href="#canonical-extension-types" title="Permalink to this heading">#</a></h3>
<p>It is beneficial to share the definitions of well-known extension types so as to
improve interoperability between different systems integrating Arrow columnar data.
For this reason canonical extension types are defined in Arrow itself.</p>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<p>The <a class="reference internal" href="CanonicalExtensions.html#format-canonical-extensions"><span class="std std-ref">Canonical Extension Types</span></a> documentation.</p>
</div>
</section>
<section id="community-extension-types">
<h3>Community Extension Types<a class="headerlink" href="#community-extension-types" title="Permalink to this heading">#</a></h3>
<p>These are Arrow extension types that have been established as standards within specific
domain areas.</p>
<p>Example:</p>
<ul class="simple">
<li><p><a class="reference external" href="https://geoarrow.org">GeoArrow</a>: A collection of Arrow extension types for representing vector geometries</p></li>
</ul>
</section>
</section>
<section id="sharing-arrow-data">
<h2>Sharing Arrow data<a class="headerlink" href="#sharing-arrow-data" title="Permalink to this heading">#</a></h2>
<p>Arrow memory layout is meant to be a universal standard for representing tabular data in memory,
not tied to a specific implementation. The Arrow standard defines two protocols for
well-defined and unambiguous communication of Arrow data between applications:</p>
<ul class="simple">
<li><p>Protocol to share Arrow data between processes or over the network is called <a class="reference internal" href="Columnar.html#format-ipc"><span class="std std-ref">Serialization and Interprocess Communication (IPC)</span></a>.
The specification for sharing data is called IPC message format which defines how Arrow
array or record batch buffers are stacked together to be serialized and deserialized.</p></li>
<li><p>To share Arrow data in the same process <a class="reference internal" href="CDataInterface.html#c-data-interface"><span class="std std-ref">The Arrow C data interface</span></a> is used, meant for sharing
the same buffer zero-copy in memory between different libraries within the same process.</p></li>
</ul>
</section>
</section>
</article>
<footer class="prev-next-footer d-print-none">
<div class="prev-next-area">
<a class="left-prev"
href="index.html"
title="previous page">
<i class="fa-solid fa-angle-left"></i>
<div class="prev-next-info">
<p class="prev-next-subtitle">previous</p>
<p class="prev-next-title">Specifications</p>
</div>
</a>
<a class="right-next"
href="Columnar.html"
title="next page">
<div class="prev-next-info">
<p class="prev-next-subtitle">next</p>
<p class="prev-next-title">Arrow Columnar Format</p>
</div>
<i class="fa-solid fa-angle-right"></i>
</a>
</div>
</footer>
</div>
<dialog id="pst-secondary-sidebar-modal"></dialog>
<div id="pst-secondary-sidebar" class="bd-sidebar-secondary bd-toc"><div class="sidebar-secondary-items sidebar-secondary__inner">
<div class="sidebar-secondary-item">
<div
id="pst-page-navigation-heading-2"
class="page-toc tocsection onthispage">
<i class="fa-solid fa-list"></i> On this page
</div>
<nav class="bd-toc-nav page-toc" aria-labelledby="pst-page-navigation-heading-2">
<ul class="visible nav section-nav flex-column">
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#arrow-columnar-format">Arrow Columnar Format</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#support-for-null-values">Support for Null Values</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#primitive-layouts">Primitive Layouts</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#fixed-size-primitive-layout">Fixed Size Primitive Layout</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#variable-length-binary-and-string">Variable length binary and string</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#variable-length-binary-and-string-view">Variable length binary and string view</a></li>
</ul>
</li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#nested-layouts">Nested Layouts</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#list">List</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#fixed-size-list">Fixed Size List</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#list-view">List View</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#struct">Struct</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#map">Map</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#union">Union</a><ul class="nav section-nav flex-column">
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#dense-union">Dense Union</a></li>
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#sparse-union">Sparse union</a></li>
</ul>
</li>
</ul>
</li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#dictionary-encoded-layout">Dictionary Encoded Layout</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#run-end-encoded-layout">Run-End Encoded Layout</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#overview-of-arrow-terminology">Overview of Arrow Terminology</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#extension-types">Extension Types</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#canonical-extension-types">Canonical Extension Types</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#community-extension-types">Community Extension Types</a></li>
</ul>
</li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#sharing-arrow-data">Sharing Arrow data</a></li>
</ul>
</nav></div>
<div class="sidebar-secondary-item">
<div class="tocsection editthispage">
<a href="https://github.com/apache/arrow/edit/main/docs/source/format/Intro.rst">
<i class="fa-solid fa-pencil"></i>
Edit on GitHub
</a>
</div>
</div>
</div></div>
</div>
<footer class="bd-footer-content">
</footer>
</main>
</div>
</div>
<!-- Scripts loaded after <body> so the DOM is not blocked -->
<script defer src="../_static/scripts/bootstrap.js?digest=8878045cc6db502f8baf"></script>
<script defer src="../_static/scripts/pydata-sphinx-theme.js?digest=8878045cc6db502f8baf"></script>
<footer class="bd-footer">
<div class="bd-footer__inner bd-page-width">
<div class="footer-items__start">
<div class="footer-item">
<p class="copyright">
© Copyright 2016-2025 Apache Software Foundation.
Apache Arrow, Arrow, Apache, the Apache feather logo, and the Apache Arrow project logo are either registered trademarks or trademarks of The Apache Software Foundation in the United States and other countries.
<br/>
</p>
</div>
<div class="footer-item">
<p class="sphinx-version">
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 6.2.0.
<br/>
</p>
</div>
</div>
<div class="footer-items__end">
<div class="footer-item">
<p class="theme-version">
<!-- # L10n: Setting the PST URL as an argument as this does not need to be localized -->
Built with the <a href="https://pydata-sphinx-theme.readthedocs.io/en/stable/index.html">PyData Sphinx Theme</a> 0.16.1.
</p></div>
</div>
</div>
</footer>
</body>
</html>