blob: bab9de0e63978dd51f6a46e5579a394fce65bae2 [file] [log] [blame]
Ian Maxon444ca1b2017-08-25 11:41:41 -07001<!DOCTYPE html>
2<!--
Ian Maxonf9dfc032017-09-14 21:37:24 +02003 | Generated by Apache Maven Doxia at 2017-09-14
Ian Maxon444ca1b2017-08-25 11:41:41 -07004 | Rendered using Apache Maven Fluido Skin 1.3.0
5-->
6<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7 <head>
8 <meta charset="UTF-8" />
9 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
Ian Maxonf9dfc032017-09-14 21:37:24 +020010 <meta name="Date-Revision-yyyymmdd" content="20170914" />
Ian Maxon444ca1b2017-08-25 11:41:41 -070011 <meta http-equiv="Content-Language" content="en" />
12 <title>AsterixDB &#x2013; CSV Support in AsterixDB</title>
13 <link rel="stylesheet" href="./css/apache-maven-fluido-1.3.0.min.css" />
14 <link rel="stylesheet" href="./css/site.css" />
15 <link rel="stylesheet" href="./css/print.css" media="print" />
16
17
18 <script type="text/javascript" src="./js/apache-maven-fluido-1.3.0.min.js"></script>
19
20
21
Ian Maxon444ca1b2017-08-25 11:41:41 -070022
Ian Maxon444ca1b2017-08-25 11:41:41 -070023
24 </head>
25 <body class="topBarDisabled">
26
27
28
29
30 <div class="container-fluid">
31 <div id="banner">
32 <div class="pull-left">
33 <a href="./" id="bannerLeft">
34 <img src="images/asterixlogo.png" alt="AsterixDB"/>
35 </a>
36 </div>
37 <div class="pull-right"> </div>
38 <div class="clear"><hr/></div>
39 </div>
40
41 <div id="breadcrumbs">
42 <ul class="breadcrumb">
43
44
Ian Maxonf9dfc032017-09-14 21:37:24 +020045 <li id="publishDate">Last Published: 2017-09-14</li>
Ian Maxon444ca1b2017-08-25 11:41:41 -070046
47
48
Ian Maxonf9dfc032017-09-14 21:37:24 +020049 <li id="projectVersion" class="pull-right">Version: 0.9.2</li>
Ian Maxon444ca1b2017-08-25 11:41:41 -070050
51 <li class="divider pull-right">|</li>
52
53 <li class="pull-right"> <a href="index.html" title="Documentation Home">
54 Documentation Home</a>
55 </li>
56
57 </ul>
58 </div>
59
60
61 <div class="row-fluid">
62 <div id="leftColumn" class="span3">
63 <div class="well sidebar-nav">
64
65
66 <ul class="nav nav-list">
67 <li class="nav-header">Get Started - Installation</li>
68
69 <li>
70
71 <a href="ncservice.html" title="Option 1: using NCService">
72 <i class="none"></i>
73 Option 1: using NCService</a>
74 </li>
75
76 <li>
77
78 <a href="ansible.html" title="Option 2: using Ansible">
79 <i class="none"></i>
80 Option 2: using Ansible</a>
81 </li>
82
83 <li>
84
85 <a href="aws.html" title="Option 3: using Amazon Web Services">
86 <i class="none"></i>
87 Option 3: using Amazon Web Services</a>
88 </li>
89
90 <li>
91
92 <a href="yarn.html" title="Option 4: using YARN">
93 <i class="none"></i>
94 Option 4: using YARN</a>
95 </li>
96
97 <li>
98
99 <a href="install.html" title="Option 5: using Managix (deprecated)">
100 <i class="none"></i>
101 Option 5: using Managix (deprecated)</a>
102 </li>
103 <li class="nav-header">AsterixDB Primer</li>
104
105 <li>
106
107 <a href="sqlpp/primer-sqlpp.html" title="Option 1: using SQL++">
108 <i class="none"></i>
109 Option 1: using SQL++</a>
110 </li>
111
112 <li>
113
114 <a href="aql/primer.html" title="Option 2: using AQL">
115 <i class="none"></i>
116 Option 2: using AQL</a>
117 </li>
118 <li class="nav-header">Data Model</li>
119
120 <li>
121
122 <a href="datamodel.html" title="The Asterix Data Model">
123 <i class="none"></i>
124 The Asterix Data Model</a>
125 </li>
126 <li class="nav-header">Queries - SQL++</li>
127
128 <li>
129
130 <a href="sqlpp/manual.html" title="The SQL++ Query Language">
131 <i class="none"></i>
132 The SQL++ Query Language</a>
133 </li>
134
135 <li>
136
137 <a href="sqlpp/builtins.html" title="Builtin Functions">
138 <i class="none"></i>
139 Builtin Functions</a>
140 </li>
141 <li class="nav-header">Queries - AQL</li>
142
143 <li>
144
145 <a href="aql/manual.html" title="The Asterix Query Language (AQL)">
146 <i class="none"></i>
147 The Asterix Query Language (AQL)</a>
148 </li>
149
150 <li>
151
152 <a href="aql/builtins.html" title="Builtin Functions">
153 <i class="none"></i>
154 Builtin Functions</a>
155 </li>
156 <li class="nav-header">API/SDK</li>
157
158 <li>
159
160 <a href="api.html" title="HTTP API">
161 <i class="none"></i>
162 HTTP API</a>
163 </li>
164
165 <li class="active">
166
167 <a href="#"><i class="none"></i>CSV Output</a>
168 </li>
169 <li class="nav-header">Advanced Features</li>
170
171 <li>
172
173 <a href="aql/fulltext.html" title="Support of Full-text Queries">
174 <i class="none"></i>
175 Support of Full-text Queries</a>
176 </li>
177
178 <li>
179
180 <a href="aql/externaldata.html" title="Accessing External Data">
181 <i class="none"></i>
182 Accessing External Data</a>
183 </li>
184
185 <li>
186
187 <a href="feeds/tutorial.html" title="Support for Data Ingestion">
188 <i class="none"></i>
189 Support for Data Ingestion</a>
190 </li>
191
192 <li>
193
194 <a href="udf.html" title="User Defined Functions">
195 <i class="none"></i>
196 User Defined Functions</a>
197 </li>
198
199 <li>
200
201 <a href="aql/filters.html" title="Filter-Based LSM Index Acceleration">
202 <i class="none"></i>
203 Filter-Based LSM Index Acceleration</a>
204 </li>
205
206 <li>
207
208 <a href="aql/similarity.html" title="Support of Similarity Queries">
209 <i class="none"></i>
210 Support of Similarity Queries</a>
211 </li>
212 </ul>
213
214
215
216 <hr class="divider" />
217
218 <div id="poweredBy">
219 <div class="clear"></div>
220 <div class="clear"></div>
221 <div class="clear"></div>
222 <a href="./" title="AsterixDB" class="builtBy">
223 <img class="builtBy" alt="AsterixDB" src="images/asterixlogo.png" />
224 </a>
225 </div>
226 </div>
227 </div>
228
229
230 <div id="bodyColumn" class="span9" >
231
232 <!-- ! Licensed to the Apache Software Foundation (ASF) under one
233 ! or more contributor license agreements. See the NOTICE file
234 ! distributed with this work for additional information
235 ! regarding copyright ownership. The ASF licenses this file
236 ! to you under the Apache License, Version 2.0 (the
237 ! "License"); you may not use this file except in compliance
238 ! with the License. You may obtain a copy of the License at
239 !
240 ! http://www.apache.org/licenses/LICENSE-2.0
241 !
242 ! Unless required by applicable law or agreed to in writing,
243 ! software distributed under the License is distributed on an
244 ! "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
245 ! KIND, either express or implied. See the License for the
246 ! specific language governing permissions and limitations
247 ! under the License.
248 ! --><h1>CSV Support in AsterixDB</h1>
249<div class="section">
250<h2><a name="Introduction_-_Defining_a_datatype_for_CSV"></a>Introduction - Defining a datatype for CSV</h2>
251<p>AsterixDB supports the CSV format for both data input and query result output. In both cases, the structure of the CSV data must be defined using a named ADM object datatype. The CSV format, limitations, and MIME type are defined by <a class="externalLink" href="https://tools.ietf.org/html/rfc4180">RFC 4180</a>.</p>
252<p>CSV is not as expressive as the full Asterix Data Model, meaning that not all data which can be represented in ADM can also be represented as CSV. So the form of this datatype is limited. First, obviously it may not contain any nested objects or lists, as CSV has no way to represent nested data structures. All fields in the object type must be primitive. Second, the set of supported primitive types is limited to numerics (<tt>int8</tt>, <tt>int16</tt>, <tt>int32</tt>, <tt>int64</tt>, <tt>float</tt>, <tt>double</tt>) and <tt>string</tt>. On output, a few additional primitive types (<tt>boolean</tt>, datetime types) are supported and will be represented as strings.</p>
253<p>For the purposes of this document, we will use the following dataverse and datatype definitions:</p>
254
255<div class="source">
256<div class="source">
257<pre>drop dataverse csv if exists;
258create dataverse csv;
259use dataverse csv;
260
261create type &quot;csv_type&quot; as closed {
262 &quot;id&quot;: int32,
263 &quot;money&quot;: float,
264 &quot;name&quot;: string
265};
266
267create dataset &quot;csv_set&quot; (&quot;csv_type&quot;) primary key &quot;id&quot;;
268</pre></div></div>
269<p>Note: There is no explicit restriction against using an open datatype for CSV purposes, and you may have optional fields in the datatype (eg., <tt>id: int32?</tt>). However, the CSV format itself is rigid, so using either of these datatype features introduces possible failure modes on output which will be discussed below.</p></div>
270<div class="section">
271<h2><a name="CSV_Input"></a>CSV Input</h2>
272<p>CSV data may be loaded into a dataset using the normal &#x201c;load dataset&#x201d; mechanisms, utilizing the builtin &#x201c;delimited-text&#x201d; format. See <a href="aql/externaldata.html">Accessing External Data</a> for more details. Note that comma is the default value for the &#x201c;delimiter&#x201d; parameter, so it does not need to be explicitly specified.</p>
273<p>In this case, the datatype used to interpret the CSV data is the datatype associated with the dataset being loaded. So, to load a file that we have stored locally on the NC into our example dataset:</p>
274
275<div class="source">
276<div class="source">
277<pre>use dataverse csv;
278
279load dataset &quot;csv_set&quot; using localfs
280((&quot;path&quot;=&quot;127.0.0.1:///tmp/my_sample.csv&quot;),
281 (&quot;format&quot;=&quot;delimited-text&quot;));
282</pre></div></div>
283<p>So, if the file <tt>/tmp/my_sample.csv</tt> contained</p>
284
285<div class="source">
286<div class="source">
287<pre>1,18.50,&quot;Peter Krabnitz&quot;
2882,74.50,&quot;Jesse Stevens&quot;
289</pre></div></div>
290<p>then the preceding query would load it into the dataset <tt>csv_set</tt>.</p>
291<p>If your CSV file has a header (that is, the first line contains a set of field names, rather than actual data), you can instruct Asterix to ignore this header by adding the parameter <tt>&quot;header&quot;=&quot;true&quot;</tt>, eg.</p>
292
293<div class="source">
294<div class="source">
295<pre>load dataset &quot;csv_set&quot; using localfs
296((&quot;path&quot;=&quot;127.0.0.1:///tmp/my_header_sample.csv&quot;),
297 (&quot;format&quot;=&quot;delimited-text&quot;),
298 (&quot;header&quot;=&quot;true&quot;));
299</pre></div></div>
300<p>CSV data may also be loaded from HDFS; see <a href="aql/externaldata.html">Accessing External Data</a> for details. However please note that CSV files on HDFS cannot have headers. Attempting to specify &#x201c;header&#x201d;=&#x201c;true&#x201d; when reading from HDFS could result in non-header lines of data being skipped as well.</p></div>
301<div class="section">
302<h2><a name="CSV_Output"></a>CSV Output</h2>
303<p>Any query may be rendered as CSV when using AsterixDB&#x2019;s HTTP interface. To do so, there are two steps required: specify the object type which defines the schema of your CSV, and request that Asterix use the CSV output format.</p>
304<div class="section">
305<div class="section">
306<h4><a name="Output_Object_Type"></a>Output Object Type</h4>
307<p>Background: The result of any AQL query is an unordered list of <i>instances</i>, where each <i>instance</i> is an instance of an AQL datatype. When requesting CSV output, there are some restrictions on the legal datatypes in this unordered list due to the limited expressability of CSV:</p>
308
309<ol style="list-style-type: decimal">
310
311<li>Each instance must be of a object type.</li>
312
313<li>Each instance must be of the <i>same</i> object type.</li>
314
315<li>The object type must conform to the content and type restrictions mentioned in the introduction.</li>
316</ol>
317<p>While it would be possible to structure your query to cast all result instances to a given type, it is not necessary. AQL offers a built-in feature which will automatically cast all top-level instances in the result to a specified named ADM object type. To enable this feature, use a <tt>set</tt> statement prior to the query to set the parameter <tt>output-record-type</tt> to the name of an ADM type. This type must have already been defined in the current dataverse.</p>
318<p>For example, the following request will ensure that all result instances are cast to the <tt>csv_type</tt> type declared earlier:</p>
319
320<div class="source">
321<div class="source">
322<pre>use dataverse csv;
323set output-record-type &quot;csv_type&quot;;
324
325for $n in dataset &quot;csv_set&quot; return $n;
326</pre></div></div>
327<p>In this case the casting is redundant since by definition every value in <tt>csv_set</tt> is already of type <tt>csv_type</tt>. But consider a more complex query where the result values are created by joining fields from different underlying datasets, etc.</p>
328<p>Two notes about <tt>output-record-type</tt>:</p>
329
330<ol style="list-style-type: decimal">
331
332<li>This feature is not strictly related to CSV; it may be used with any output formats (in which case, any object datatype may be specified, not subject to the limitations specified in the introduction of this page).</li>
333
334<li>When the CSV output format is requested, <tt>output-record-type</tt> is in fact required, not optional. This is because the type is used to determine the field names for the CSV header and to ensure that the ordering of fields in the output is consistent (which is obviously vital for the CSV to make any sense).</li>
335</ol></div>
336<div class="section">
337<h4><a name="Request_the_CSV_Output_Format"></a>Request the CSV Output Format</h4>
338<p>When sending requests to the Asterix HTTP API, Asterix decides what format to use for rendering the results in one of two ways:</p>
339
340<ul>
341
342<li>
343<p>A HTTP query parameter named &#x201c;output&#x201d;, which must be set to one of the following values: <tt>JSON</tt>, <tt>CSV</tt>, or <tt>ADM</tt>.</p></li>
344
345<li>
346<p>Based on the <a class="externalLink" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1"><tt>Accept</tt> HTTP header</a></p></li>
347</ul>
348<p>By default, Asterix will produce JSON output. To select CSV output, pass the parameter <tt>output=CSV</tt>, or set the <tt>Accept</tt> header on your request to the MIME type <tt>text/csv</tt>. The details of how to accomplish this will of course depend on what tools you are using to contact the HTTP API. Here is an example from a Unix shell prompt using the command-line utility &#x201c;curl&#x201d; and specifying the &quot;output query parameter:</p>
349
350<div class="source">
351<div class="source">
352<pre>curl -G &quot;http://localhost:19002/query&quot; \
353 --data-urlencode 'output=CSV' \
354 --data-urlencode 'query=use dataverse csv;
355 set output-record-type &quot;csv_type&quot;;
356 for $n in dataset csv_set return $n;'
357</pre></div></div>
358<p>Alternately, the same query using the <tt>Accept</tt> header:</p>
359
360<div class="source">
361<div class="source">
362<pre>curl -G -H &quot;Accept: text/csv&quot; &quot;http://localhost:19002/query&quot; \
363 --data-urlencode 'query=use dataverse csv;
364 set output-record-type &quot;csv_type&quot;;
365 for $n in dataset csv_set return $n;'
366</pre></div></div>
367<p>Similarly, a trivial Java program to execute the above sample query and selecting CSV output via the <tt>Accept</tt> header would be:</p>
368
369<div class="source">
370<div class="source">
371<pre>import java.net.HttpURLConnection;
372import java.net.URL;
373import java.net.URLEncoder;
374import java.io.BufferedReader;
375import java.io.InputStream;
376import java.io.InputStreamReader;
377
378public class AsterixExample {
379 public static void main(String[] args) throws Exception {
380 String query = &quot;use dataverse csv; &quot; +
381 &quot;set output-record-type \&quot;csv_type\&quot;;&quot; +
382 &quot;for $n in dataset csv_set return $n&quot;;
383 URL asterix = new URL(&quot;http://localhost:19002/query?query=&quot; +
384 URLEncoder.encode(query, &quot;UTF-8&quot;));
385 HttpURLConnection conn = (HttpURLConnection) asterix.openConnection();
386 conn.setRequestProperty(&quot;Accept&quot;, &quot;text/csv&quot;);
387 BufferedReader result = new BufferedReader
388 (new InputStreamReader(conn.getInputStream()));
389 String line;
390 while ((line = result.readLine()) != null) {
391 System.out.println(line);
392 }
393 result.close();
394 }
395}
396</pre></div></div>
397<p>For either of the above examples, the output would be:</p>
398
399<div class="source">
400<div class="source">
401<pre>1,18.5,&quot;Peter Krabnitz&quot;
4022,74.5,&quot;Jesse Stevens&quot;
403</pre></div></div>
404<p>assuming you had already run the previous examples to create the dataverse and populate the dataset.</p></div>
405<div class="section">
406<h4><a name="Outputting_CSV_with_a_Header"></a>Outputting CSV with a Header</h4>
407<p>By default, AsterixDB will produce CSV results with no header line. If you want a header, you may explicitly request it in one of two ways:</p>
408
409<ul>
410
411<li>
412<p>By passing the HTTP query parameter &#x201c;header&#x201d; with the value &#x201c;present&#x201d;</p></li>
413
414<li>
415<p>By specifying the MIME type {{text/csv; header=present}} in your HTTP Accept: header. This is consistent with RFC 4180.</p></li>
416</ul></div>
417<div class="section">
418<h4><a name="Issues_with_open_datatypes_and_optional_fields"></a>Issues with open datatypes and optional fields</h4>
419<p>As mentioned earlier, CSV is a rigid format. It cannot express objects with different numbers of fields, which ADM allows through both open datatypes and optional fields.</p>
420<p>If your output object type contains optional fields, this will not result in any errors. If the output data of a query does not contain values for an optional field, this will be represented in CSV as <tt>null</tt>.</p>
421<p>If your output object type is open, this will also not result in any errors. If the output data of a query contains any open fields, the corresponding rows in the resulting CSV will contain more comma-separated values than the others. On each such row, the data from the closed fields in the type will be output first in the normal order, followed by the data from the open fields in an arbitrary order.</p>
422<p>According to RFC 4180 this is not strictly valid CSV (Section 2, rule 4, &#x201c;Each line <i>should</i> contain the same number of fields throughout the file&#x201d;). Hence it will likely not be handled consistently by all CSV processors. Some may throw a parsing error. If you attempt to load this data into AsterixDB later using <tt>load dataset</tt>, the extra fields will be silently ignored. For this reason it is recommended that you use only closed datatypes as output object types. AsterixDB allows to use an open object type only to support cases where the type already exists for other parts of your application.</p></div></div></div>
423 </div>
424 </div>
425 </div>
426
427 <hr/>
428
429 <footer>
430 <div class="container-fluid">
431 <div class="row span12">Copyright &copy; 2017
432 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
433 All Rights Reserved.
434
435 </div>
436
437 <?xml version="1.0" encoding="UTF-8"?>
438<div class="row-fluid">Apache AsterixDB, AsterixDB, Apache, the Apache
439 feather logo, and the Apache AsterixDB project logo are either
440 registered trademarks or trademarks of The Apache Software
441 Foundation in the United States and other countries.
442 All other marks mentioned may be trademarks or registered
443 trademarks of their respective owners.</div>
444
445
446 </div>
447 </footer>
448 </body>
449</html>