Merge "Merge commit 'aa7ff7b' from 'gerrit/mad-hatter'"
diff --git a/asterixdb/asterix-app/data/csv/empty.csv b/asterixdb/asterix-app/data/csv/empty.csv
index 3f2ff2d..e69de29 100644
--- a/asterixdb/asterix-app/data/csv/empty.csv
+++ b/asterixdb/asterix-app/data/csv/empty.csv
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/asterixdb/asterix-app/data/csv/empty_lines.csv b/asterixdb/asterix-app/data/csv/empty_lines.csv
new file mode 100644
index 0000000..3f2ff2d
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/empty_lines.csv
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/asterixdb/asterix-app/data/csv/error1_line_num.csv b/asterixdb/asterix-app/data/csv/error1_line_num.csv
new file mode 100644
index 0000000..34bcee9
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/error1_line_num.csv
@@ -0,0 +1,3 @@
+1,"good","recommend"
+
+2,"bad" ,"not recommend"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/csv/error2_line_num.csv b/asterixdb/asterix-app/data/csv/error2_line_num.csv
new file mode 100644
index 0000000..0f1286f
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/error2_line_num.csv
@@ -0,0 +1,5 @@
+1,"good","recommend"
+2,"bad and
+not so good and
+bad" ,"not recommend"
+3,"good","recommend"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/csv/header/h_invalid_values.csv b/asterixdb/asterix-app/data/csv/header/h_invalid_values.csv
new file mode 100644
index 0000000..1ec6140
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/header/h_invalid_values.csv
@@ -0,0 +1,13 @@
+bigint_t,nullable_bigint_t,double_t,nullable_double_t,str_t,nullable_str_t,boolean_t,nullable_boolean_t
+163a,12,33.4,16.1,"text","text",true,false
+1.22,12,33.4,16.1,"text","text",true,false
+999999999999999999999999999999999,12,33.4,16.1,"text","text",true,false
+1234,12,non-double,16.1,"text","text",true,false
+1234 ,12, 15.1,16.1,"fine","fine",TRUE,false
+1234,12,15.1,16.1,"text","text",non-boolean,false
+1234,12,15.1,16.1,"fine","fine", true,false
+1234,12,15.1,16.1,"text", "quote-not-at-beginning",true,false
+1234,\N,15.1,\N,\N,\N,true,\N
+\N,12,15.1,16.1,"text","text",true,false
+1234,12,\N,16.1,"text","text",true,false
+1234,12,15.1,16.1,"text","text",\N,false
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/csv/header/h_mul_rec.csv b/asterixdb/asterix-app/data/csv/header/h_mul_rec.csv
new file mode 100644
index 0000000..23d0bcd
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/header/h_mul_rec.csv
@@ -0,0 +1,4 @@
+f1,f2,f3,f4
+1,2,3,"str"
+4,5,6,"rts"
+7,8,9,"srt"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/csv/header/h_mul_rec_with_ln.csv b/asterixdb/asterix-app/data/csv/header/h_mul_rec_with_ln.csv
new file mode 100644
index 0000000..3ea2987
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/header/h_mul_rec_with_ln.csv
@@ -0,0 +1,4 @@
+f1,f2,f3,f4
+1,2,3,"str"
+4,5,6,"rts"
+7,8,9,"srt"
diff --git a/asterixdb/asterix-app/data/csv/header/h_one_rec.csv b/asterixdb/asterix-app/data/csv/header/h_one_rec.csv
new file mode 100644
index 0000000..236141c
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/header/h_one_rec.csv
@@ -0,0 +1,2 @@
+f1,f2,f3,f4
+1,2,3,"str"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/csv/header/h_one_rec_with_ln.csv b/asterixdb/asterix-app/data/csv/header/h_one_rec_with_ln.csv
new file mode 100644
index 0000000..83b19b3
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/header/h_one_rec_with_ln.csv
@@ -0,0 +1,2 @@
+f1,f2,f3,f4
+1,2,3,"str"
diff --git a/asterixdb/asterix-app/data/csv/header/h_only.csv b/asterixdb/asterix-app/data/csv/header/h_only.csv
new file mode 100644
index 0000000..7988898
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/header/h_only.csv
@@ -0,0 +1 @@
+f1,f2,f3,f4
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/csv/header/h_only_with_ln.csv b/asterixdb/asterix-app/data/csv/header/h_only_with_ln.csv
new file mode 100644
index 0000000..33ddfb1
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/header/h_only_with_ln.csv
@@ -0,0 +1 @@
+f1,f2,f3,f4
diff --git a/asterixdb/asterix-app/data/csv/no_header/no_h_missing_fields.csv b/asterixdb/asterix-app/data/csv/no_header/no_h_missing_fields.csv
new file mode 100644
index 0000000..8dbe35c
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/no_header/no_h_missing_fields.csv
@@ -0,0 +1,3 @@
+1,2,3,"str"
+4,5,6
+7,8,9,"srt"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/csv/no_header/no_h_mul_rec.csv b/asterixdb/asterix-app/data/csv/no_header/no_h_mul_rec.csv
new file mode 100644
index 0000000..85abbfb
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/no_header/no_h_mul_rec.csv
@@ -0,0 +1,3 @@
+1,2,3,"str"
+4,5,6,"rts"
+7,8,9,"srt"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/csv/no_header/no_h_mul_rec_with_ln.csv b/asterixdb/asterix-app/data/csv/no_header/no_h_mul_rec_with_ln.csv
new file mode 100644
index 0000000..e20e795
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/no_header/no_h_mul_rec_with_ln.csv
@@ -0,0 +1,3 @@
+1,2,3,"str"
+4,5,6,"rts"
+7,8,9,"srt"
diff --git a/asterixdb/asterix-app/data/csv/no_header/no_h_no_closing_q.csv b/asterixdb/asterix-app/data/csv/no_header/no_h_no_closing_q.csv
new file mode 100644
index 0000000..abefcf7
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/no_header/no_h_no_closing_q.csv
@@ -0,0 +1 @@
+1,2,3,"5
diff --git a/asterixdb/asterix-app/data/csv/no_header/no_h_one_rec.csv b/asterixdb/asterix-app/data/csv/no_header/no_h_one_rec.csv
new file mode 100644
index 0000000..e80e3a2
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/no_header/no_h_one_rec.csv
@@ -0,0 +1 @@
+1,2,3,"str"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/csv/no_header/no_h_one_rec_with_ln.csv b/asterixdb/asterix-app/data/csv/no_header/no_h_one_rec_with_ln.csv
new file mode 100644
index 0000000..a884ca6
--- /dev/null
+++ b/asterixdb/asterix-app/data/csv/no_header/no_h_one_rec_with_ln.csv
@@ -0,0 +1 @@
+1,2,3,"str"
diff --git a/asterixdb/asterix-app/data/json/malformed-json-no-closing.json b/asterixdb/asterix-app/data/json/malformed-json-no-closing.json
new file mode 100644
index 0000000..83f3087
--- /dev/null
+++ b/asterixdb/asterix-app/data/json/malformed-json-no-closing.json
@@ -0,0 +1,2 @@
+{ "field1": 1, "field2": "text"
+
diff --git a/asterixdb/asterix-app/data/json/multi-lines-with-arrays/5-records.json b/asterixdb/asterix-app/data/json/multi-lines-with-arrays/5-records.json
new file mode 100644
index 0000000..fd8526b
--- /dev/null
+++ b/asterixdb/asterix-app/data/json/multi-lines-with-arrays/5-records.json
@@ -0,0 +1,19 @@
+{"id": 1, "year": null, "quarter": null, "review": "good", "array": [1, 2, 3]}
+
+
+{"id": 2, "year": null, "quarter": null, "review": "good", "array": [1, [1, 2], [1]]}
+{"id": 3, "year": 2018, "quarter": null, "review": "good", "array": [1,
+2, 3]}
+
+{"id": 4,
+ "year": 2018,
+ "quarter": null,
+ "review": "bad",
+ "array": [
+ 1,
+ 2,
+ 3
+ ]
+}
+{"id": 5,
+ "year": 2018, "quarter": 1, "review": "good", "array": [1, 2, 3]}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/json/multi-lines-with-nested-objects/5-records.json b/asterixdb/asterix-app/data/json/multi-lines-with-nested-objects/5-records.json
new file mode 100644
index 0000000..b89e81e
--- /dev/null
+++ b/asterixdb/asterix-app/data/json/multi-lines-with-nested-objects/5-records.json
@@ -0,0 +1,32 @@
+{"id": 1, "year": null, "quarter": null, "review": "good", "array": [1, 2, 3], "nested": { "id" : 1}}
+
+
+{"id": 2, "year": null, "quarter": null, "review": "good", "array": [1, [1, 2], [1]], "nested": { "id" : 1}, "nested2": [ {"id":1 }]}
+{"id":3,"year":2018,"quarter":null,"review":"good","array":[1,2,3,{"nested":{"array":[{"nested":{"array":[1,2]}}]}}]}
+
+{
+ "id": 4,
+ "year": 2018,
+ "quarter": null,
+ "review": "bad",
+ "array": [
+ 1,
+ 2,
+ 3,
+ {
+ "nested1": {
+ "id": 1,
+ "nested2": {
+ "id": 2,
+ "nested3": [
+ {
+ "nested4": null
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
+{"id": 5,
+ "year": 2018, "quarter": 1, "review": "good", "array": [1, 2, 3, {"nested": { "array": [1, 2]}}]}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/json/multi-lines/20-records.json b/asterixdb/asterix-app/data/json/multi-lines/20-records.json
new file mode 100644
index 0000000..0591790
--- /dev/null
+++ b/asterixdb/asterix-app/data/json/multi-lines/20-records.json
@@ -0,0 +1,34 @@
+{"id": 1, "year": null, "quarter": null, "review": "good"}
+
+
+{"id": 2, "year": null, "quarter": null, "review": "good"}
+{"id": 3, "year": 2018, "quarter": null, "review": "good"}
+
+{"id": 4,
+ "year": 2018,
+ "quarter": null,
+ "review": "bad"
+}
+{"id": 5,
+ "year": 2018, "quarter": 1, "review": "good"}
+{"id": 6, "year": 2018, "quarter": 1, "review": "bad"
+}
+{"id": 7, "year": 2018, "quarter": 2, "review": "good"}
+{"id": 8, "year": 2018, "quarter": 2, "review": "bad"}
+{"id": 9, "year": 2019, "quarter": null,
+
+ "review": "good"}
+{"id": 10, "year": 2019,
+
+ "quarter": null,
+ "review": "bad"}
+{"id": 11, "year": 2019, "quarter": 1, "review": "good"}
+{"id": 12, "year": 2019, "quarter": 1, "review": "bad"}
+{"id": 13, "year": 2019, "quarter": 2, "review": "good"}
+{"id": 14, "year": 2019, "quarter": 2, "review": "bad"}
+{"id": 15, "year": 2019, "quarter": null, "review": "good"}
+{"id": 16, "year": 2019, "quarter": null, "review": "bad"}
+{"id": 17, "year": 2019, "quarter": 1, "review": "good"}
+{"id": 18, "year": 2019, "quarter": 1, "review": "bad"}
+{"id": 19, "year": 2019, "quarter": 2, "review": "good"}
+{"id": 20, "year": 2019, "quarter": 2, "review": "bad"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/json/single-line/20-records.json b/asterixdb/asterix-app/data/json/single-line/20-records.json
new file mode 100644
index 0000000..01176da
--- /dev/null
+++ b/asterixdb/asterix-app/data/json/single-line/20-records.json
@@ -0,0 +1,20 @@
+{"id": 1, "year": null, "quarter": null, "review": "good"}
+{"id": 2, "year": null, "quarter": null, "review": "good"}
+{"id": 3, "year": 2018, "quarter": null, "review": "good"}
+{"id": 4, "year": 2018, "quarter": null, "review": "bad"}
+{"id": 5, "year": 2018, "quarter": 1, "review": "good"}
+{"id": 6, "year": 2018, "quarter": 1, "review": "bad"}
+{"id": 7, "year": 2018, "quarter": 2, "review": "good"}
+{"id": 8, "year": 2018, "quarter": 2, "review": "bad"}
+{"id": 9, "year": 2019, "quarter": null, "review": "good"}
+{"id": 10, "year": 2019, "quarter": null, "review": "bad"}
+{"id": 11, "year": 2019, "quarter": 1, "review": "good"}
+{"id": 12, "year": 2019, "quarter": 1, "review": "bad"}
+{"id": 13, "year": 2019, "quarter": 2, "review": "good"}
+{"id": 14, "year": 2019, "quarter": 2, "review": "bad"}
+{"id": 15, "year": 2019, "quarter": null, "review": "good"}
+{"id": 16, "year": 2019, "quarter": null, "review": "bad"}
+{"id": 17, "year": 2019, "quarter": 1, "review": "good"}
+{"id": 18, "year": 2019, "quarter": 1, "review": "bad"}
+{"id": 19, "year": 2019, "quarter": 2, "review": "good"}
+{"id": 20, "year": 2019, "quarter": 2, "review": "bad"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/jsonl/multi-lines-with-arrays/5-records.json b/asterixdb/asterix-app/data/jsonl/multi-lines-with-arrays/5-records.json
new file mode 100644
index 0000000..5bd8cb6
--- /dev/null
+++ b/asterixdb/asterix-app/data/jsonl/multi-lines-with-arrays/5-records.json
@@ -0,0 +1,20 @@
+[]
+{"id": 21, "year": null, "quarter": null, "review": "good", "array": [1, 2, 3]}
+
+
+{"id": 22, "year": null, "quarter": null, "review": "good", "array": [1, [1, 2], [1]]}
+{"id": 23, "year": 2018, "quarter": null, "review": "good", "array": [1,
+2, 3]}
+
+{"id": 24,
+ "year": 2018,
+ "quarter": null,
+ "review": "bad",
+ "array": [
+ 1,
+ 2,
+ 3
+ ]
+}
+{"id": 25,
+ "year": 2018, "quarter": 1, "review": "good", "array": [1, 2, 3]}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/jsonl/multi-lines-with-nested-objects/5-records.json b/asterixdb/asterix-app/data/jsonl/multi-lines-with-nested-objects/5-records.json
new file mode 100644
index 0000000..063e30a
--- /dev/null
+++ b/asterixdb/asterix-app/data/jsonl/multi-lines-with-nested-objects/5-records.json
@@ -0,0 +1,33 @@
+{"id": 26, "year": null, "quarter": null, "review": "good", "array": [1, 2, 3], "nested": { "id" : 1}}
+
+[]
+[ ]
+[{"id": 27, "year": null, "quarter": null, "review": "good", "array": [1, [1, 2], [1]], "nested": { "id" : 1}, "nested2": [ {"id":1 }]},
+{"id":28,"year":2018,"quarter":null,"review":"good","array":[1,2,3,{"nested":{"array":[{"nested":{"array":[1,2]}}]}}]}]
+
+{
+ "id": 29,
+ "year": 2018,
+ "quarter": null,
+ "review": "bad",
+ "array": [
+ 1,
+ 2,
+ 3,
+ {
+ "nested1": {
+ "id": 1,
+ "nested2": {
+ "id": 2,
+ "nested3": [
+ {
+ "nested4": null
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
+{"id": 30,
+ "year": 2018, "quarter": 1, "review": "good", "array": [1, 2, 3, {"nested": { "array": [1, 2]}}]}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/jsonl/multi-lines/20-records.json b/asterixdb/asterix-app/data/jsonl/multi-lines/20-records.json
new file mode 100644
index 0000000..69aa775
--- /dev/null
+++ b/asterixdb/asterix-app/data/jsonl/multi-lines/20-records.json
@@ -0,0 +1,33 @@
+[{"id": 1, "year": null, "quarter": null, "review": "good"},
+
+
+{"id": 2, "year": null, "quarter": null, "review": "good"} ,
+{"id": 3, "year": 2018, "quarter": null, "review": "good"}]
+
+{"id": 4,
+ "year": 2018,
+ "quarter": null,
+ "review": "bad"
+}
+{"id": 5,
+ "year": 2018, "quarter": 1, "review": "good"}
+{"id": 6, "year": 2018, "quarter": 1, "review": "bad"
+}
+{"id": 7, "year": 2018, "quarter": 2, "review": "good"}
+{"id": 8, "year": 2018, "quarter": 2, "review": "bad"}
+[{"id": 9, "year": 2019, "quarter": null,
+
+ "review": "good"},
+{"id": 10, "year": 2019,
+
+ "quarter": null,
+ "review": "bad"} ,
+{"id": 11, "year": 2019, "quarter": 1, "review": "good"}]
+[{"id": 12, "year": 2019, "quarter": 1, "review": "bad"}]
+{"id": 13, "year": 2019, "quarter": 2, "review": "good"}
+{"id": 14, "year": 2019, "quarter": 2, "review": "bad"}
+{"id": 15, "year": 2019, "quarter": null, "review": "good"}
+{"id": 16, "year": 2019, "quarter": null, "review": "bad"}
+{"id": 17, "year": 2019, "quarter": 1, "review": "good"}
+[{"id": 18, "year": 2019, "quarter": 1, "review": "bad"}, {"id": 19, "year": 2019, "quarter": 2, "review": "good"},
+{"id": 20, "year": 2019, "quarter": 2, "review": "bad"}]
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/jsonl/single-line/20-records.json b/asterixdb/asterix-app/data/jsonl/single-line/20-records.json
new file mode 100644
index 0000000..bf86095
--- /dev/null
+++ b/asterixdb/asterix-app/data/jsonl/single-line/20-records.json
@@ -0,0 +1,20 @@
+[{"id": 31, "year": null, "quarter": null, "review": "good"},
+{"id": 32, "year": null, "quarter": null, "review": "good"},
+{"id": 33, "year": 2018, "quarter": null, "review": "good"},
+{"id": 34, "year": 2018, "quarter": null, "review": "bad"},
+{"id": 35, "year": 2018, "quarter": 1, "review": "good"},
+{"id": 36, "year": 2018, "quarter": 1, "review": "bad"},
+{"id": 37, "year": 2018, "quarter": 2, "review": "good"},
+{"id": 38, "year": 2018, "quarter": 2, "review": "bad"},
+{"id": 39, "year": 2019, "quarter": null, "review": "good"},
+{"id": 40, "year": 2019, "quarter": null, "review": "bad"},
+{"id": 41, "year": 2019, "quarter": 1, "review": "good"},
+{"id": 42, "year": 2019, "quarter": 1, "review": "bad"},
+{"id": 43, "year": 2019, "quarter": 2, "review": "good"},
+{"id": 44, "year": 2019, "quarter": 2, "review": "bad"},
+{"id": 45, "year": 2019, "quarter": null, "review": "good"},
+{"id": 46, "year": 2019, "quarter": null, "review": "bad"},
+{"id": 47, "year": 2019, "quarter": 1, "review": "good"},
+{"id": 48, "year": 2019, "quarter": 1, "review": "bad"},
+{"id": 49, "year": 2019, "quarter": 2, "review": "good"},
+{"id": 50, "year": 2019, "quarter": 2, "review": "bad"}]
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/tsv/empty.tsv b/asterixdb/asterix-app/data/tsv/empty.tsv
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/data/tsv/empty.tsv
diff --git a/asterixdb/asterix-app/data/tsv/empty_lines.tsv b/asterixdb/asterix-app/data/tsv/empty_lines.tsv
new file mode 100644
index 0000000..3f2ff2d
--- /dev/null
+++ b/asterixdb/asterix-app/data/tsv/empty_lines.tsv
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/asterixdb/asterix-app/data/tsv/header/h_mul_rec.tsv b/asterixdb/asterix-app/data/tsv/header/h_mul_rec.tsv
new file mode 100644
index 0000000..ba73bb2
--- /dev/null
+++ b/asterixdb/asterix-app/data/tsv/header/h_mul_rec.tsv
@@ -0,0 +1,4 @@
+f1 f2 f3 f4
+1 2 3 "str"
+4 5 6 "rts"
+7 8 9 "srt"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/tsv/header/h_mul_rec_with_ln.tsv b/asterixdb/asterix-app/data/tsv/header/h_mul_rec_with_ln.tsv
new file mode 100644
index 0000000..eaf1fab
--- /dev/null
+++ b/asterixdb/asterix-app/data/tsv/header/h_mul_rec_with_ln.tsv
@@ -0,0 +1,4 @@
+f1 f2 f3 f4
+1 2 3 "str"
+4 5 6 "rts"
+7 8 9 "srt"
diff --git a/asterixdb/asterix-app/data/tsv/header/h_one_rec.tsv b/asterixdb/asterix-app/data/tsv/header/h_one_rec.tsv
new file mode 100644
index 0000000..167b56b
--- /dev/null
+++ b/asterixdb/asterix-app/data/tsv/header/h_one_rec.tsv
@@ -0,0 +1,2 @@
+f1 f2 f3 f4
+1 2 3 "str"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/tsv/header/h_one_rec_with_ln.tsv b/asterixdb/asterix-app/data/tsv/header/h_one_rec_with_ln.tsv
new file mode 100644
index 0000000..95d2d55
--- /dev/null
+++ b/asterixdb/asterix-app/data/tsv/header/h_one_rec_with_ln.tsv
@@ -0,0 +1,2 @@
+f1 f2 f3 f4
+1 2 3 "str"
diff --git a/asterixdb/asterix-app/data/tsv/header/h_only.tsv b/asterixdb/asterix-app/data/tsv/header/h_only.tsv
new file mode 100644
index 0000000..b72029a
--- /dev/null
+++ b/asterixdb/asterix-app/data/tsv/header/h_only.tsv
@@ -0,0 +1 @@
+f1 f2 f3 f4
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/tsv/header/h_only_with_ln.tsv b/asterixdb/asterix-app/data/tsv/header/h_only_with_ln.tsv
new file mode 100644
index 0000000..8180e15
--- /dev/null
+++ b/asterixdb/asterix-app/data/tsv/header/h_only_with_ln.tsv
@@ -0,0 +1 @@
+f1 f2 f3 f4
diff --git a/asterixdb/asterix-app/data/tsv/no_header/no_h_missing_fields.tsv b/asterixdb/asterix-app/data/tsv/no_header/no_h_missing_fields.tsv
new file mode 100644
index 0000000..75002ac
--- /dev/null
+++ b/asterixdb/asterix-app/data/tsv/no_header/no_h_missing_fields.tsv
@@ -0,0 +1,3 @@
+1 2 3 "str"
+4 5 6
+7 8 9 "srt"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/tsv/no_header/no_h_mul_rec.tsv b/asterixdb/asterix-app/data/tsv/no_header/no_h_mul_rec.tsv
new file mode 100644
index 0000000..517974a
--- /dev/null
+++ b/asterixdb/asterix-app/data/tsv/no_header/no_h_mul_rec.tsv
@@ -0,0 +1,3 @@
+1 2 3 "str"
+4 5 6 "rts"
+7 8 9 "srt"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/tsv/no_header/no_h_mul_rec_with_ln.tsv b/asterixdb/asterix-app/data/tsv/no_header/no_h_mul_rec_with_ln.tsv
new file mode 100644
index 0000000..869fefb
--- /dev/null
+++ b/asterixdb/asterix-app/data/tsv/no_header/no_h_mul_rec_with_ln.tsv
@@ -0,0 +1,3 @@
+1 2 3 "str"
+4 5 6 "rts"
+7 8 9 "srt"
diff --git a/asterixdb/asterix-app/data/tsv/no_header/no_h_one_rec.tsv b/asterixdb/asterix-app/data/tsv/no_header/no_h_one_rec.tsv
new file mode 100644
index 0000000..d076cbe
--- /dev/null
+++ b/asterixdb/asterix-app/data/tsv/no_header/no_h_one_rec.tsv
@@ -0,0 +1 @@
+1 2 3 "str"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/data/tsv/no_header/no_h_one_rec_with_ln.tsv b/asterixdb/asterix-app/data/tsv/no_header/no_h_one_rec_with_ln.tsv
new file mode 100644
index 0000000..53d0de6
--- /dev/null
+++ b/asterixdb/asterix-app/data/tsv/no_header/no_h_one_rec_with_ln.tsv
@@ -0,0 +1 @@
+1 2 3 "str"
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
index aff7441..b6ac3f1 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
@@ -27,6 +27,7 @@
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
@@ -204,7 +205,7 @@
}
String type = HttpUtil.mime(StaticResourceServlet.extension(resourcePath));
HttpUtil.setContentType(response, "".equals(type) ? HttpUtil.ContentType.TEXT_PLAIN : type,
- HttpUtil.Encoding.UTF8);
+ StandardCharsets.UTF_8);
writeOutput(response, is, resourcePath);
} catch (IOException e) {
LOGGER.log(Level.WARN, "Failure handling request", e);
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
index 63678f8..319d959 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
@@ -134,8 +134,13 @@
}
@Override
+ protected void get(IServletRequest request, IServletResponse response) throws IOException {
+ handleRequest(request, response, true);
+ }
+
+ @Override
protected void post(IServletRequest request, IServletResponse response) throws IOException {
- handleRequest(request, response);
+ handleRequest(request, response, false);
}
@Override
@@ -237,7 +242,8 @@
return "http://" + host + path + handlePath(delivery);
}
- private void handleRequest(IServletRequest request, IServletResponse response) throws IOException {
+ private void handleRequest(IServletRequest request, IServletResponse response, boolean forceReadOnly)
+ throws IOException {
final IRequestReference requestRef = receptionist.welcome(request);
long elapsedStart = System.nanoTime();
long errorCount = 1;
@@ -258,6 +264,9 @@
optionalParams = optionalParamProvider.apply(request);
}
setRequestParam(request, param, optionalParams);
+ if (forceReadOnly) {
+ param.setReadOnly(true);
+ }
LOGGER.info(() -> "handleRequest: " + LogRedactionUtil.userData(param.toString()));
delivery = param.getMode();
setSessionConfig(sessionOutput, param, delivery);
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RebalanceApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RebalanceApiServlet.java
index 62b96bc..b47960b 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RebalanceApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RebalanceApiServlet.java
@@ -21,6 +21,7 @@
import static org.apache.asterix.api.http.server.ServletConstants.HYRACKS_CONNECTION_ATTR;
import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
@@ -170,7 +171,7 @@
IServletResponse response, CountDownLatch terminated) {
try {
// Sets the content type.
- HttpUtil.setContentType(response, HttpUtil.ContentType.APPLICATION_JSON, HttpUtil.Encoding.UTF8);
+ HttpUtil.setContentType(response, HttpUtil.ContentType.APPLICATION_JSON, StandardCharsets.UTF_8);
if (datasetName == null) {
// Rebalances datasets in a given dataverse or all non-metadata datasets.
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
index ea2ce40..f2302f9 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
@@ -918,6 +918,7 @@
DataverseName dataverseName = getActiveDataverseName(stmtCreateIndex.getDataverseName());
String datasetName = stmtCreateIndex.getDatasetName().getValue();
String indexName = stmtCreateIndex.getIndexName().getValue();
+ IndexType indexType = stmtCreateIndex.getIndexType();
List<Integer> keySourceIndicators = stmtCreateIndex.getFieldSourceIndicators();
MetadataTransactionContext mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
metadataProvider.setMetadataTxnContext(mdTxnCtx);
@@ -930,6 +931,9 @@
dataverseName);
}
+ DatasetType datasetType = ds.getDatasetType();
+ validateIndexType(datasetType, indexType, isSecondaryPrimary, sourceLoc);
+
Index index = MetadataManager.INSTANCE.getIndex(metadataProvider.getMetadataTxnContext(), dataverseName,
datasetName, indexName);
if (index != null) {
@@ -940,14 +944,11 @@
throw new CompilationException(ErrorCode.INDEX_EXISTS, sourceLoc, indexName);
}
}
+
// find keySourceIndicators for secondary primary index since the parser isn't aware of them
- if (isSecondaryPrimary && ds.getDatasetType() == DatasetType.INTERNAL) {
+ if (isSecondaryPrimary && datasetType == DatasetType.INTERNAL) {
keySourceIndicators = ((InternalDatasetDetails) ds.getDatasetDetails()).getKeySourceIndicator();
}
- // disable creating secondary primary index on an external dataset
- if (isSecondaryPrimary && ds.getDatasetType() == DatasetType.EXTERNAL) {
- throw new AsterixException(ErrorCode.CANNOT_CREATE_SEC_PRIMARY_IDX_ON_EXT_DATASET);
- }
// disable creating an index on meta fields (fields with source indicator == 1 are meta fields)
if (keySourceIndicators.stream().anyMatch(fieldSource -> fieldSource == 1) && !isSecondaryPrimary) {
throw new AsterixException(ErrorCode.COMPILATION_ERROR, sourceLoc,
@@ -992,9 +993,8 @@
if (fieldExpr.second == null) {
fieldType = subType.getSubFieldType(fieldExpr.first.subList(i, fieldExpr.first.size()));
} else {
- if (!stmtCreateIndex.isEnforced() && stmtCreateIndex.getIndexType() != IndexType.BTREE) {
- throw new AsterixException(ErrorCode.INDEX_ILLEGAL_NON_ENFORCED_TYPED, sourceLoc,
- stmtCreateIndex.getIndexType());
+ if (!stmtCreateIndex.isEnforced() && indexType != IndexType.BTREE) {
+ throw new AsterixException(ErrorCode.INDEX_ILLEGAL_NON_ENFORCED_TYPED, sourceLoc, indexType);
}
if (stmtCreateIndex.isEnforced() && !fieldExpr.second.isUnknownable()) {
throw new AsterixException(ErrorCode.INDEX_ILLEGAL_ENFORCED_NON_OPTIONAL, sourceLoc,
@@ -1048,10 +1048,10 @@
// Currently, we do not support this. Therefore, as a temporary solution, we
// print an
// error message and stop.
- if (stmtCreateIndex.getIndexType() == IndexType.SINGLE_PARTITION_WORD_INVIX
- || stmtCreateIndex.getIndexType() == IndexType.SINGLE_PARTITION_NGRAM_INVIX
- || stmtCreateIndex.getIndexType() == IndexType.LENGTH_PARTITIONED_WORD_INVIX
- || stmtCreateIndex.getIndexType() == IndexType.LENGTH_PARTITIONED_NGRAM_INVIX) {
+ if (indexType == IndexType.SINGLE_PARTITION_WORD_INVIX
+ || indexType == IndexType.SINGLE_PARTITION_NGRAM_INVIX
+ || indexType == IndexType.LENGTH_PARTITIONED_WORD_INVIX
+ || indexType == IndexType.LENGTH_PARTITIONED_NGRAM_INVIX) {
List<List<String>> partitioningKeys = ds.getPrimaryKeys();
for (List<String> partitioningKey : partitioningKeys) {
IAType keyType = aRecordType.getSubFieldType(partitioningKey);
@@ -1068,9 +1068,9 @@
}
}
- Index newIndex = new Index(dataverseName, datasetName, indexName, stmtCreateIndex.getIndexType(),
- indexFields, keySourceIndicators, indexFieldTypes, stmtCreateIndex.getGramLength(),
- overridesFieldTypes, stmtCreateIndex.isEnforced(), false, MetadataUtil.PENDING_ADD_OP);
+ Index newIndex = new Index(dataverseName, datasetName, indexName, indexType, indexFields,
+ keySourceIndicators, indexFieldTypes, stmtCreateIndex.getGramLength(), overridesFieldTypes,
+ stmtCreateIndex.isEnforced(), false, MetadataUtil.PENDING_ADD_OP);
doCreateIndex(hcc, metadataProvider, ds, newIndex, jobFlags, sourceLoc);
} finally {
metadataProvider.getLocks().unlock();
@@ -1321,6 +1321,14 @@
}
}
+ protected void validateIndexType(DatasetType datasetType, IndexType indexType, boolean isSecondaryPrimaryIndex,
+ SourceLocation sourceLoc) throws AlgebricksException {
+ // disable creating secondary primary index on an external dataset
+ if (datasetType == DatasetType.EXTERNAL && isSecondaryPrimaryIndex) {
+ throw new CompilationException(ErrorCode.CANNOT_CREATE_SEC_PRIMARY_IDX_ON_EXT_DATASET);
+ }
+ }
+
protected void validateIndexKeyFields(CreateIndexStatement stmtCreateIndex, List<Integer> keySourceIndicators,
ARecordType aRecordType, ARecordType metaRecordType, List<List<String>> indexFields,
List<IAType> indexFieldTypes) throws AlgebricksException {
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
index 36a06c0..d4f92fb 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
@@ -23,6 +23,7 @@
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+import java.util.BitSet;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
@@ -129,8 +130,7 @@
}
@Override
- protected void ensureWarnings(int actualWarnCount, int expectedWarnCount, TestCase.CompilationUnit cUnit)
- throws Exception {
+ protected void ensureWarnings(BitSet expectedWarnings, TestCase.CompilationUnit cUnit) throws Exception {
// skip checking warnings as currently cancelled queries with warnings might not run successfully at all
}
}
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/IPollTask.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/IPollTask.java
index ab90244..a1ed12b 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/IPollTask.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/IPollTask.java
@@ -19,6 +19,7 @@
package org.apache.asterix.test.common;
import java.io.File;
+import java.util.BitSet;
import java.util.List;
import java.util.Map;
@@ -43,11 +44,11 @@
* @param expectedResultFileCtxs
* @param testFile
* @param actualPath
- * @param actualWarnCount
+ * @param expectedWarnings
*/
void execute(TestCaseContext testCaseCtx, TestFileContext ctx, Map<String, Object> variableCtx, String statement,
boolean isDmlRecoveryTest, ProcessBuilder pb, CompilationUnit cUnit, MutableInt queryCount,
- List<TestFileContext> expectedResultFileCtxs, File testFile, String actualPath, MutableInt actualWarnCount)
+ List<TestFileContext> expectedResultFileCtxs, File testFile, String actualPath, BitSet expectedWarnings)
throws Exception;
}
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
index eb91675..190b7b0 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
@@ -171,6 +171,10 @@
return extract(resultStream, EnumSet.of(ResultField.PLANS), resultCharset, OutputFormat.ADM, plans).getResult();
}
+ public static InputStream extractStatus(InputStream resultStream, Charset resultCharset) throws Exception {
+ return extract(resultStream, EnumSet.of(ResultField.STATUS), resultCharset).getResult();
+ }
+
public static String extractHandle(InputStream resultStream, Charset responseCharset) throws Exception {
String result = IOUtils.toString(resultStream, responseCharset);
ObjectNode resultJson = OBJECT_READER.readValue(result);
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
index cedcc7f..4275aa6 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
@@ -45,6 +45,7 @@
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -53,6 +54,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.OptionalInt;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ExecutionException;
@@ -169,6 +171,7 @@
Pattern.compile("maxresultreads=(\\d+)(\\D|$)", Pattern.MULTILINE);
private static final Pattern HTTP_REQUEST_TYPE = Pattern.compile("requesttype=(.*)", Pattern.MULTILINE);
private static final Pattern EXTRACT_RESULT_TYPE = Pattern.compile("extractresult=(.*)", Pattern.MULTILINE);
+ private static final Pattern EXTRACT_STATUS_PATTERN = Pattern.compile("extractstatus", Pattern.MULTILINE);
private static final String NC_ENDPOINT_PREFIX = "nc:";
public static final int TRUNCATE_THRESHOLD = 16384;
public static final Set<String> NON_CANCELLABLE =
@@ -177,9 +180,9 @@
private static final ContentType TEXT_PLAIN_UTF8 = ContentType.create(HttpUtil.ContentType.APPLICATION_JSON, UTF_8);
private final IPollTask plainExecutor = (testCaseCtx, ctx, variableCtx, statement, isDmlRecoveryTest, pb, cUnit,
- queryCount, expectedResultFileCtxs, testFile, actualPath, actualWarnCount) -> executeTestFile(testCaseCtx,
+ queryCount, expectedResultFileCtxs, testFile, actualPath, expectedWarnings) -> executeTestFile(testCaseCtx,
ctx, variableCtx, statement, isDmlRecoveryTest, pb, cUnit, queryCount, expectedResultFileCtxs,
- testFile, actualPath, actualWarnCount);
+ testFile, actualPath, expectedWarnings);
public static final String DELIVERY_ASYNC = "async";
public static final String DELIVERY_DEFERRED = "deferred";
@@ -994,7 +997,7 @@
public void executeTestFile(TestCaseContext testCaseCtx, TestFileContext ctx, Map<String, Object> variableCtx,
String statement, boolean isDmlRecoveryTest, ProcessBuilder pb, CompilationUnit cUnit,
MutableInt queryCount, List<TestFileContext> expectedResultFileCtxs, File testFile, String actualPath,
- MutableInt actualWarnCount) throws Exception {
+ BitSet expectedWarnings) throws Exception {
InputStream resultStream;
File qbcFile;
boolean failed = false;
@@ -1022,11 +1025,11 @@
case "pollquery":
poll(testCaseCtx, ctx, variableCtx, statement, isDmlRecoveryTest, pb, cUnit, queryCount,
expectedResultFileCtxs, testFile, actualPath, ctx.getType().substring("poll".length()),
- actualWarnCount, plainExecutor);
+ expectedWarnings, plainExecutor);
break;
case "polldynamic":
polldynamic(testCaseCtx, ctx, variableCtx, statement, isDmlRecoveryTest, pb, cUnit, queryCount,
- expectedResultFileCtxs, testFile, actualPath, actualWarnCount);
+ expectedResultFileCtxs, testFile, actualPath, expectedWarnings);
break;
case "query":
case "async":
@@ -1053,7 +1056,7 @@
if (testCaseCtx.getTestCase().isCheckWarnings()) {
boolean expectedSourceLoc = testCaseCtx.isSourceLocationExpected(cUnit);
- validateWarnings(extractedResult.getWarnings(), cUnit.getExpectedWarn(), actualWarnCount,
+ validateWarnings(extractedResult.getWarnings(), cUnit.getExpectedWarn(), expectedWarnings,
expectedSourceLoc);
}
break;
@@ -1324,6 +1327,7 @@
final Optional<String> body = extractBody(statement);
final Predicate<Integer> statusCodePredicate = extractStatusCodePredicate(statement);
final boolean extracResult = isExtracResult(statement);
+ final boolean extractStatus = isExtractStatus(statement);
final String mimeReqType = extractHttpRequestType(statement);
ContentType contentType = mimeReqType != null ? ContentType.create(mimeReqType, UTF_8) : TEXT_PLAIN_UTF8;
InputStream resultStream;
@@ -1332,12 +1336,14 @@
} else if ("uri".equals(extension)) {
resultStream = executeURI(reqType, URI.create(variablesReplaced), fmt, params, statusCodePredicate, body,
contentType);
- if (extracResult) {
- resultStream = ResultExtractor.extract(resultStream, UTF_8).getResult();
- }
} else {
throw new IllegalArgumentException("Unexpected format for method " + reqType + ": " + extension);
}
+ if (extracResult) {
+ resultStream = ResultExtractor.extract(resultStream, UTF_8).getResult();
+ } else if (extractStatus) {
+ resultStream = ResultExtractor.extractStatus(resultStream, UTF_8);
+ }
if (handleVar != null) {
String handle = ResultExtractor.extractHandle(resultStream, UTF_8);
if (handle != null) {
@@ -1459,17 +1465,17 @@
private void polldynamic(TestCaseContext testCaseCtx, TestFileContext ctx, Map<String, Object> variableCtx,
String statement, boolean isDmlRecoveryTest, ProcessBuilder pb, CompilationUnit cUnit,
MutableInt queryCount, List<TestFileContext> expectedResultFileCtxs, File testFile, String actualPath,
- MutableInt actualWarnCount) throws Exception {
+ BitSet expectedWarnings) throws Exception {
IExpectedResultPoller poller = getExpectedResultPoller(statement);
final String key = getKey(statement);
poll(testCaseCtx, ctx, variableCtx, statement, isDmlRecoveryTest, pb, cUnit, queryCount, expectedResultFileCtxs,
- testFile, actualPath, "validate", actualWarnCount, new IPollTask() {
+ testFile, actualPath, "validate", expectedWarnings, new IPollTask() {
@Override
public void execute(TestCaseContext testCaseCtx, TestFileContext ctx,
Map<String, Object> variableCtx, String statement, boolean isDmlRecoveryTest,
ProcessBuilder pb, CompilationUnit cUnit, MutableInt queryCount,
List<TestFileContext> expectedResultFileCtxs, File testFile, String actualPath,
- MutableInt actualWarnCount) throws Exception {
+ BitSet expectedWarnings) throws Exception {
File actualResultFile = new File(actualPath, testCaseCtx.getTestCase().getFilePath()
+ File.separatorChar + cUnit.getName() + '.' + ctx.getSeqNum() + ".polled.adm");
if (actualResultFile.exists() && !actualResultFile.delete()) {
@@ -1507,7 +1513,7 @@
private void poll(TestCaseContext testCaseCtx, TestFileContext ctx, Map<String, Object> variableCtx,
String statement, boolean isDmlRecoveryTest, ProcessBuilder pb, CompilationUnit cUnit,
MutableInt queryCount, List<TestFileContext> expectedResultFileCtxs, File testFile, String actualPath,
- String newType, MutableInt actualWarnCount, IPollTask pollTask) throws Exception {
+ String newType, BitSet expectedWarnings, IPollTask pollTask) throws Exception {
// polltimeoutsecs=nnn, polldelaysecs=nnn
int timeoutSecs = getTimeoutSecs(statement);
int retryDelaySecs = getRetryDelaySecs(statement);
@@ -1530,7 +1536,7 @@
try {
startSemaphore.release();
pollTask.execute(testCaseCtx, ctx, variableCtx, statement, isDmlRecoveryTest, pb, cUnit,
- queryCount, expectedResultFileCtxs, testFile, actualPath, actualWarnCount);
+ queryCount, expectedResultFileCtxs, testFile, actualPath, expectedWarnings);
} finally {
endSemaphore.release();
}
@@ -1757,6 +1763,11 @@
return m.find() ? Boolean.valueOf(m.group(1)) : false;
}
+ private static boolean isExtractStatus(String statement) {
+ Matcher m = EXTRACT_STATUS_PATTERN.matcher(statement);
+ return m.find();
+ }
+
private static boolean isJsonEncoded(String httpRequestType) throws Exception {
if (httpRequestType == null || httpRequestType.isEmpty()) {
return true;
@@ -1857,7 +1868,8 @@
for (CompilationUnit cUnit : cUnits) {
List<String> expectedErrors = cUnit.getExpectedError();
int expectedWarnCount = cUnit.getExpectedWarn().size();
- MutableInt actualWarnCount = new MutableInt(0);
+ BitSet expectedWarnings = new BitSet(cUnit.getExpectedWarn().size());
+ expectedWarnings.set(0, cUnit.getExpectedWarn().size());
LOGGER.info(
"Starting [TEST]: " + testCaseCtx.getTestCase().getFilePath() + "/" + cUnit.getName() + " ... ");
Map<String, Object> variableCtx = new HashMap<>();
@@ -1877,7 +1889,7 @@
try {
if (!testFile.getName().startsWith(DIAGNOSE)) {
executeTestFile(testCaseCtx, ctx, variableCtx, statement, isDmlRecoveryTest, pb, cUnit,
- queryCount, expectedResultFileCtxs, testFile, actualPath, actualWarnCount);
+ queryCount, expectedResultFileCtxs, testFile, actualPath, expectedWarnings);
}
} catch (TestLoop loop) {
// rewind the iterator until we find our target
@@ -1909,7 +1921,7 @@
throw new Exception(
"Test \"" + cUnit.getName() + "\" FAILED; expected exception was not thrown...");
}
- ensureWarnings(actualWarnCount.getValue(), expectedWarnCount, cUnit);
+ ensureWarnings(expectedWarnings, cUnit);
LOGGER.info(
"[TEST]: " + testCaseCtx.getTestCase().getFilePath() + "/" + cUnit.getName() + " PASSED ");
if (passedGroup != null) {
@@ -2040,7 +2052,7 @@
final File file = ctx.getFile();
final String statement = readTestFile(file);
executeTestFile(testCaseCtx, ctx, variableCtx, statement, false, pb, cUnit, new MutableInt(-1),
- Collections.emptyList(), file, null, new MutableInt(-1));
+ Collections.emptyList(), file, null, new BitSet());
}
}
} catch (Exception diagnosticFailure) {
@@ -2239,9 +2251,17 @@
LOGGER.info("Cluster state now " + desiredState);
}
- protected void ensureWarnings(int actualWarnCount, int expectedWarnCount, CompilationUnit cUnit) throws Exception {
- if (actualWarnCount < expectedWarnCount) {
- LOGGER.error("Test {} failed to raise (an) expected warning(s)", cUnit.getName());
+ protected void ensureWarnings(BitSet expectedWarnings, CompilationUnit cUnit) throws Exception {
+ boolean fail = !expectedWarnings.isEmpty();
+ if (fail) {
+ LOGGER.error("Test {} failed to raise (an) expected warning(s):", cUnit.getName());
+ }
+ List<String> expectedWarn = cUnit.getExpectedWarn();
+ for (int i = expectedWarnings.nextSetBit(0); i >= 0; i = expectedWarnings.nextSetBit(i + 1)) {
+ String warning = expectedWarn.get(i);
+ LOGGER.error(warning);
+ }
+ if (fail) {
throw new Exception("Test \"" + cUnit.getName() + "\" FAILED; expected warning(s) was not returned...");
}
}
@@ -2391,22 +2411,30 @@
return extension.endsWith(AQL) ? getEndpoint(Servlets.QUERY_AQL) : getEndpoint(Servlets.QUERY_SERVICE);
}
- private void validateWarnings(List<String> actualWarnings, List<String> expectedWarn, MutableInt actualWarnCount,
+ private void validateWarnings(List<String> actualWarnings, List<String> expectedWarn, BitSet expectedWarnings,
boolean expectedSourceLoc) throws Exception {
if (actualWarnings != null) {
for (String actualWarn : actualWarnings) {
- if (expectedWarn.stream().noneMatch(actualWarn::contains)) {
- throw new Exception("unexpected warning was encountered (" + actualWarn + ")");
+ OptionalInt first = IntStream.range(0, expectedWarn.size())
+ .filter(i -> actualWarn.contains(expectedWarn.get(i)) && expectedWarnings.get(i)).findFirst();
+ if (!first.isPresent()) {
+ String msg = "unexpected warning was encountered or has already been matched (" + actualWarn + ")";
+ LOGGER.error(msg);
+ if (!expectedWarnings.isEmpty()) {
+ LOGGER.error("was expecting the following warnings: ");
+ }
+ for (int i = expectedWarnings.nextSetBit(0); i >= 0; i = expectedWarnings.nextSetBit(i + 1)) {
+ LOGGER.error(expectedWarn.get(i));
+ }
+ throw new Exception(msg);
}
if (expectedSourceLoc && !containsSourceLocation(actualWarn)) {
throw new Exception(MessageFormat.format(
"Expected to find source location \"{}, {}\" in warning text: +++++{}+++++",
ERR_MSG_SRC_LOC_LINE_REGEX, ERR_MSG_SRC_LOC_COLUMN_REGEX, actualWarn));
}
- actualWarnCount.increment();
- if (actualWarnCount.getValue() > expectedWarn.size()) {
- throw new Exception("returned warnings exceeded expected warnings");
- }
+ int warningIndex = first.getAsInt();
+ expectedWarnings.clear(warningIndex);
}
}
}
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/external_dataset/aws/AwsS3ExternalDatasetOnePartitionTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/external_dataset/aws/AwsS3ExternalDatasetOnePartitionTest.java
new file mode 100644
index 0000000..bd433f1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/external_dataset/aws/AwsS3ExternalDatasetOnePartitionTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+package org.apache.asterix.test.external_dataset.aws;
+
+import java.util.Collection;
+
+import org.apache.asterix.test.runtime.LangExecutionUtil;
+import org.apache.asterix.testframework.context.TestCaseContext;
+import org.junit.FixMethodOrder;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+
+/**
+ * Runs an AWS S3 mock server and test it as an external dataset using one node one partition.
+ */
+@RunWith(Parameterized.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class AwsS3ExternalDatasetOnePartitionTest extends AwsS3ExternalDatasetTest {
+
+ public AwsS3ExternalDatasetOnePartitionTest(TestCaseContext tcCtx) {
+ super(tcCtx);
+ }
+
+ @Parameterized.Parameters(name = "AwsS3ExternalDatasetOnePartitionTest {index}: {0}")
+ public static Collection<Object[]> tests() throws Exception {
+ SUITE_TESTS = "testsuite_external_dataset_one_partition.xml";
+ ONLY_TESTS = "only_external_dataset.xml";
+ TEST_CONFIG_FILE_NAME = "src/test/resources/cc-single.conf";
+ PREPARE_S3_BUCKET = AwsS3ExternalDatasetOnePartitionTest::prepareS3Bucket;
+ PREPARE_FIXED_DATA_BUCKET = AwsS3ExternalDatasetOnePartitionTest::prepareFixedDataBucket;
+ return LangExecutionUtil.tests(ONLY_TESTS, SUITE_TESTS);
+ }
+
+ private static void prepareS3Bucket() {
+ }
+
+ private static void prepareFixedDataBucket() {
+ }
+}
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/external_dataset/aws/AwsS3ExternalDatasetTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/external_dataset/aws/AwsS3ExternalDatasetTest.java
index d2158ba..55c78e3 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/external_dataset/aws/AwsS3ExternalDatasetTest.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/external_dataset/aws/AwsS3ExternalDatasetTest.java
@@ -20,26 +20,42 @@
import static org.apache.hyracks.util.file.FileUtil.joinPath;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.BitSet;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.zip.GZIPOutputStream;
import org.apache.asterix.common.api.INcApplicationContext;
import org.apache.asterix.test.common.TestExecutor;
import org.apache.asterix.test.runtime.ExecutionTestUtil;
import org.apache.asterix.test.runtime.LangExecutionUtil;
import org.apache.asterix.testframework.context.TestCaseContext;
+import org.apache.asterix.testframework.context.TestFileContext;
+import org.apache.asterix.testframework.xml.TestCase;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.hyracks.control.nc.NodeControllerService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.AfterClass;
+import org.junit.Assert;
import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@@ -50,36 +66,62 @@
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3ClientBuilder;
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
+import software.amazon.awssdk.services.s3.model.DeleteBucketRequest;
+import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
/**
* Runs an AWS S3 mock server and test it as an external dataset
*/
@RunWith(Parameterized.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class AwsS3ExternalDatasetTest {
private static final Logger LOGGER = LogManager.getLogger();
- protected static final String TEST_CONFIG_FILE_NAME = "src/main/resources/cc.conf";
+ // subclasses of this class MUST instantiate these variables before using them to avoid unexpected behavior
+ static String SUITE_TESTS;
+ static String ONLY_TESTS;
+ static String TEST_CONFIG_FILE_NAME;
+ static Runnable PREPARE_S3_BUCKET;
+ static Runnable PREPARE_FIXED_DATA_BUCKET;
- // S3 mock server
- private static S3Mock s3MockServer;
-
- // IMPORTANT: The following values must be used in the AWS S3 test case
- private static S3Client client;
- private static final String S3_MOCK_SERVER_BUCKET = "playground";
- private static final String S3_MOCK_SERVER_BUCKET_DEFINITION = "json-data/reviews/"; // data resides here
- private static final String S3_MOCK_SERVER_BUCKET_CSV_DEFINITION = "csv-data/reviews/"; // data resides here
- private static final String S3_MOCK_SERVER_BUCKET_TSV_DEFINITION = "tsv-data/reviews/"; // data resides here
- private static final String S3_MOCK_SERVER_REGION = "us-west-2";
- private static final int S3_MOCK_SERVER_PORT = 8001;
- private static final String S3_MOCK_SERVER_HOSTNAME = "http://localhost:" + S3_MOCK_SERVER_PORT;
+ // Base directory paths for data files
+ private static final String JSON_DATA_PATH = joinPath("data", "json");
private static final String CSV_DATA_PATH = joinPath("data", "csv");
private static final String TSV_DATA_PATH = joinPath("data", "tsv");
+ // Service endpoint
+ private static final int S3_MOCK_SERVER_PORT = 8001;
+ private static final String S3_MOCK_SERVER_HOSTNAME = "http://localhost:" + S3_MOCK_SERVER_PORT;
+
+ // Region, bucket and definitions
+ private static final String S3_MOCK_SERVER_REGION = "us-west-2";
+ private static final String S3_MOCK_SERVER_BUCKET = "playground";
+ private static final String S3_MOCK_SERVER_FIXED_DATA_BUCKET = "fixed-data-bucket"; // Do not use, has fixed data
+ private static final String S3_MOCK_SERVER_BUCKET_JSON_DEFINITION = "json-data/reviews/"; // data resides here
+ private static final String S3_MOCK_SERVER_BUCKET_CSV_DEFINITION = "csv-data/reviews/"; // data resides here
+ private static final String S3_MOCK_SERVER_BUCKET_TSV_DEFINITION = "tsv-data/reviews/"; // data resides here
+
+ private static final Set<String> fileNames = new HashSet<>();
+ private static final CreateBucketRequest.Builder CREATE_BUCKET_BUILDER = CreateBucketRequest.builder();
+ private static final DeleteBucketRequest.Builder DELETE_BUCKET_BUILDER = DeleteBucketRequest.builder();
+ private static final PutObjectRequest.Builder PUT_OBJECT_BUILDER = PutObjectRequest.builder();
+
+ // IMPORTANT: The following values must be used in the AWS S3 test case
+ private static S3Mock s3MockServer;
+ private static S3Client client;
+ private static PutObjectRequest.Builder builder = PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET);
+
+ protected TestCaseContext tcCtx;
+
+ public AwsS3ExternalDatasetTest(TestCaseContext tcCtx) {
+ this.tcCtx = tcCtx;
+ }
+
@BeforeClass
public static void setUp() throws Exception {
- final TestExecutor testExecutor = new TestExecutor();
+ final TestExecutor testExecutor = new AwsTestExecutor();
LangExecutionUtil.setUp(TEST_CONFIG_FILE_NAME, testExecutor);
setNcEndpoints(testExecutor);
startAwsS3MockServer();
@@ -100,15 +142,14 @@
LOGGER.info("S3 mock down and client shut down successfully");
}
- @Parameters(name = "SqlppExecutionTest {index}: {0}")
+ @Parameters(name = "AwsS3ExternalDatasetTest {index}: {0}")
public static Collection<Object[]> tests() throws Exception {
- return LangExecutionUtil.tests("only_external_dataset.xml", "testsuite_external_dataset.xml");
- }
-
- protected TestCaseContext tcCtx;
-
- public AwsS3ExternalDatasetTest(TestCaseContext tcCtx) {
- this.tcCtx = tcCtx;
+ SUITE_TESTS = "testsuite_external_dataset.xml";
+ ONLY_TESTS = "only_external_dataset.xml";
+ TEST_CONFIG_FILE_NAME = "src/main/resources/cc.conf";
+ PREPARE_S3_BUCKET = AwsS3ExternalDatasetTest::prepareS3Bucket;
+ PREPARE_FIXED_DATA_BUCKET = AwsS3ExternalDatasetTest::prepareFixedDataBucket;
+ return LangExecutionUtil.tests(ONLY_TESTS, SUITE_TESTS);
}
@Test
@@ -149,7 +190,8 @@
LOGGER.info("Client created successfully");
// Create the bucket and upload some json files
- prepareS3Bucket();
+ PREPARE_S3_BUCKET.run();
+ PREPARE_FIXED_DATA_BUCKET.run();
}
/**
@@ -161,82 +203,265 @@
LOGGER.info("bucket created successfully");
LOGGER.info("Adding JSON files to the bucket");
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "0.json").build(),
- RequestBody.fromString("{\"id\": 1, \"year\": null, \"quarter\": null, \"review\": \"good\"}"));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "1.json").build(),
- RequestBody.fromString("{\"id\": 2, \"year\": null, \"quarter\": null, \"review\": \"good\"}"));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "2018/1.json").build(),
- RequestBody.fromString("{\"id\": 3, \"year\": 2018, \"quarter\": null, \"review\": \"good\"}"));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "2018/2.json").build(),
- RequestBody.fromString("{\"id\": 4, \"year\": 2018, \"quarter\": null, \"review\": \"bad\"}"));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "2018/q1/1.json").build(),
- RequestBody.fromString("{\"id\": 5, \"year\": 2018, \"quarter\": 1, \"review\": \"good\"}"));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "2018/q1/2.json").build(),
- RequestBody.fromString("{\"id\": 6, \"year\": 2018, \"quarter\": 1, \"review\": \"bad\"}"));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "2018/q2/1.json").build(),
- RequestBody.fromString("{\"id\": 7, \"year\": 2018, \"quarter\": 2, \"review\": \"good\"}"));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "2018/q2/2.json").build(),
- RequestBody.fromString("{\"id\": 8, \"year\": 2018, \"quarter\": 2, \"review\": \"bad\"}"));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "2019/1.json").build(),
- RequestBody.fromString("{\"id\": 9, \"year\": 2019, \"quarter\": null, \"review\": \"good\"}"));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "2019/2.json").build(),
- RequestBody.fromString("{\"id\": 10, \"year\": 2019, \"quarter\": null, \"review\": \"bad\"}"));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "2019/q1/1.json").build(),
- RequestBody.fromString("{\"id\": 11, \"year\": 2019, \"quarter\": 1, \"review\": \"good\"}"));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "2019/q1/2.json").build(),
- RequestBody.fromString("{\"id\": 12, \"year\": 2019, \"quarter\": 1, \"review\": \"bad\"}"));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "2019/q2/1.json").build(),
- RequestBody.fromString("{\"id\": 13, \"year\": 2019, \"quarter\": 2, \"review\": \"good\"}"));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_DEFINITION + "2019/q2/2.json").build(),
- RequestBody.fromString("{\"id\": 14, \"year\": 2019, \"quarter\": 2, \"review\": \"bad\"}"));
+ loadJsonFiles();
+ LOGGER.info("JSON Files added successfully");
LOGGER.info("Adding CSV files to the bucket");
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_CSV_DEFINITION + "01.csv").build(),
- RequestBody.fromFile(Paths.get(CSV_DATA_PATH, "01.csv")));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_CSV_DEFINITION + "2018/01.csv").build(),
- RequestBody.fromFile(Paths.get(CSV_DATA_PATH, "02.csv")));
+ loadCsvFiles();
+ LOGGER.info("CSV Files added successfully");
LOGGER.info("Adding TSV files to the bucket");
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_TSV_DEFINITION + "01.tsv").build(),
- RequestBody.fromFile(Paths.get(TSV_DATA_PATH, "01.tsv")));
- client.putObject(
- PutObjectRequest.builder().bucket(S3_MOCK_SERVER_BUCKET)
- .key(S3_MOCK_SERVER_BUCKET_TSV_DEFINITION + "2018/01.tsv").build(),
- RequestBody.fromFile(Paths.get(TSV_DATA_PATH, "02.tsv")));
- LOGGER.info("Files added successfully");
+ loadTsvFiles();
+ LOGGER.info("TSV Files added successfully");
+ }
+
+ /**
+ * This bucket is being filled by fixed data, a test is counting all records in this bucket. If this bucket is
+ * changed, the test case will fail and its result will need to be updated each time
+ */
+ private static void prepareFixedDataBucket() {
+ LOGGER.info("creating bucket " + S3_MOCK_SERVER_FIXED_DATA_BUCKET);
+ client.createBucket(CreateBucketRequest.builder().bucket(S3_MOCK_SERVER_FIXED_DATA_BUCKET).build());
+ LOGGER.info("bucket " + S3_MOCK_SERVER_FIXED_DATA_BUCKET + " created successfully");
+
+ LOGGER.info("Loading fixed data to " + S3_MOCK_SERVER_FIXED_DATA_BUCKET);
+
+ // Files data
+ RequestBody requestBody = RequestBody.fromFile(Paths.get(JSON_DATA_PATH, "single-line", "20-records.json"));
+ client.putObject(builder.bucket(S3_MOCK_SERVER_FIXED_DATA_BUCKET).key("1.json").build(), requestBody);
+ client.putObject(builder.bucket(S3_MOCK_SERVER_FIXED_DATA_BUCKET).key("2.json").build(), requestBody);
+ client.putObject(builder.bucket(S3_MOCK_SERVER_FIXED_DATA_BUCKET).key("lvl1/3.json").build(), requestBody);
+ client.putObject(builder.bucket(S3_MOCK_SERVER_FIXED_DATA_BUCKET).key("lvl1/4.json").build(), requestBody);
+ client.putObject(builder.bucket(S3_MOCK_SERVER_FIXED_DATA_BUCKET).key("lvl1/lvl2/5.json").build(), requestBody);
+ }
+
+ private static void loadJsonFiles() {
+ String dataBasePath = JSON_DATA_PATH;
+ String definition = S3_MOCK_SERVER_BUCKET_JSON_DEFINITION;
+
+ // Normal format
+ String definitionSegment = "json";
+ loadData(dataBasePath, "single-line", "20-records.json", definition, definitionSegment, false);
+ loadData(dataBasePath, "multi-lines", "20-records.json", definition, definitionSegment, false);
+ loadData(dataBasePath, "multi-lines-with-arrays", "5-records.json", definition, definitionSegment, false);
+ loadData(dataBasePath, "multi-lines-with-nested-objects", "5-records.json", definition, definitionSegment,
+ false);
+
+ // gz compressed format
+ definitionSegment = "gz";
+ loadGzData(dataBasePath, "single-line", "20-records.json", definition, definitionSegment, false);
+ loadGzData(dataBasePath, "multi-lines", "20-records.json", definition, definitionSegment, false);
+ loadGzData(dataBasePath, "multi-lines-with-arrays", "5-records.json", definition, definitionSegment, false);
+ loadGzData(dataBasePath, "multi-lines-with-nested-objects", "5-records.json", definition, definitionSegment,
+ false);
+
+ // Mixed normal and gz compressed format
+ definitionSegment = "mixed";
+ loadData(dataBasePath, "single-line", "20-records.json", definition, definitionSegment, false);
+ loadData(dataBasePath, "multi-lines", "20-records.json", definition, definitionSegment, false);
+ loadData(dataBasePath, "multi-lines-with-arrays", "5-records.json", definition, definitionSegment, false);
+ loadData(dataBasePath, "multi-lines-with-nested-objects", "5-records.json", definition, definitionSegment,
+ false);
+ loadGzData(dataBasePath, "single-line", "20-records.json", definition, definitionSegment, false);
+ loadGzData(dataBasePath, "multi-lines", "20-records.json", definition, definitionSegment, false);
+ loadGzData(dataBasePath, "multi-lines-with-arrays", "5-records.json", definition, definitionSegment, false);
+ loadGzData(dataBasePath, "multi-lines-with-nested-objects", "5-records.json", definition, definitionSegment,
+ false);
+ }
+
+ private static void loadCsvFiles() {
+ String dataBasePath = CSV_DATA_PATH;
+ String definition = S3_MOCK_SERVER_BUCKET_CSV_DEFINITION;
+
+ // Normal format
+ String definitionSegment = "csv";
+ loadData(dataBasePath, "", "01.csv", definition, definitionSegment, false);
+ loadData(dataBasePath, "", "02.csv", definition, definitionSegment, false);
+
+ // gz compressed format
+ definitionSegment = "gz";
+ loadGzData(dataBasePath, "", "01.csv", definition, definitionSegment, false);
+ loadGzData(dataBasePath, "", "02.csv", definition, definitionSegment, false);
+
+ // Mixed normal and gz compressed format
+ definitionSegment = "mixed";
+ loadData(dataBasePath, "", "01.csv", definition, definitionSegment, false);
+ loadData(dataBasePath, "", "02.csv", definition, definitionSegment, false);
+ loadGzData(dataBasePath, "", "01.csv", definition, definitionSegment, false);
+ loadGzData(dataBasePath, "", "02.csv", definition, definitionSegment, false);
+ }
+
+ private static void loadTsvFiles() {
+ String dataBasePath = TSV_DATA_PATH;
+ String definition = S3_MOCK_SERVER_BUCKET_TSV_DEFINITION;
+
+ // Normal format
+ String definitionSegment = "tsv";
+ loadData(dataBasePath, "", "01.tsv", definition, definitionSegment, false);
+ loadData(dataBasePath, "", "02.tsv", definition, definitionSegment, false);
+
+ // gz compressed format
+ definitionSegment = "gz";
+ loadGzData(dataBasePath, "", "01.tsv", definition, definitionSegment, false);
+ loadGzData(dataBasePath, "", "02.tsv", definition, definitionSegment, false);
+
+ // Mixed normal and gz compressed format
+ definitionSegment = "mixed";
+ loadData(dataBasePath, "", "01.tsv", definition, definitionSegment, false);
+ loadData(dataBasePath, "", "02.tsv", definition, definitionSegment, false);
+ loadGzData(dataBasePath, "", "01.tsv", definition, definitionSegment, false);
+ loadGzData(dataBasePath, "", "02.tsv", definition, definitionSegment, false);
+ }
+
+ private static void loadData(String fileBasePath, String filePathSegment, String filename, String definition,
+ String definitionSegment, boolean removeExtension) {
+ // Files data
+ Path filePath = Paths.get(fileBasePath, filePathSegment, filename);
+ RequestBody requestBody = RequestBody.fromFile(filePath);
+
+ // Keep or remove the file extension
+ Assert.assertFalse("Files with no extension are not supported yet for external datasets", removeExtension);
+ String finalFileName;
+ if (removeExtension) {
+ finalFileName = FilenameUtils.removeExtension(filename);
+ } else {
+ finalFileName = filename;
+ }
+
+ // Files base definition
+ filePathSegment = filePathSegment.isEmpty() ? "" : filePathSegment + "/";
+ definitionSegment = definitionSegment.isEmpty() ? "" : definitionSegment + "/";
+ String basePath = definition + filePathSegment + definitionSegment;
+
+ // Load the data
+ client.putObject(builder.key(basePath + finalFileName).build(), requestBody);
+ client.putObject(builder.key(basePath + "level1a/" + finalFileName).build(), requestBody);
+ client.putObject(builder.key(basePath + "level1b/" + finalFileName).build(), requestBody);
+ client.putObject(builder.key(basePath + "level1a/level2a/" + finalFileName).build(), requestBody);
+ client.putObject(builder.key(basePath + "level1a/level2b/" + finalFileName).build(), requestBody);
+ }
+
+ private static void loadGzData(String fileBasePath, String filePathSegment, String filename, String definition,
+ String definitionSegment, boolean removeExtension) {
+ try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream)) {
+
+ // Files data
+ Path filePath = Paths.get(fileBasePath, filePathSegment, filename);
+
+ // Get the compressed data
+ gzipOutputStream.write(Files.readAllBytes(filePath));
+ gzipOutputStream.close(); // Need to close or data will be invalid
+ byte[] gzipBytes = byteArrayOutputStream.toByteArray();
+ RequestBody requestBody = RequestBody.fromBytes(gzipBytes);
+
+ // Keep or remove the file extension
+ Assert.assertFalse("Files with no extension are not supported yet for external datasets", removeExtension);
+ String finalFileName;
+ if (removeExtension) {
+ finalFileName = FilenameUtils.removeExtension(filename);
+ } else {
+ finalFileName = filename;
+ }
+ finalFileName += ".gz";
+
+ // Files base definition
+ filePathSegment = filePathSegment.isEmpty() ? "" : filePathSegment + "/";
+ definitionSegment = definitionSegment.isEmpty() ? "" : definitionSegment + "/";
+ String basePath = definition + filePathSegment + definitionSegment;
+
+ // Load the data
+ client.putObject(builder.key(basePath + finalFileName).build(), requestBody);
+ client.putObject(builder.key(basePath + "level1a/" + finalFileName).build(), requestBody);
+ client.putObject(builder.key(basePath + "level1b/" + finalFileName).build(), requestBody);
+ client.putObject(builder.key(basePath + "level1a/level2a/" + finalFileName).build(), requestBody);
+ client.putObject(builder.key(basePath + "level1a/level2b/" + finalFileName).build(), requestBody);
+ } catch (Exception ex) {
+ LOGGER.error(ex.getMessage());
+ }
+ }
+
+ static class AwsTestExecutor extends TestExecutor {
+
+ public void executeTestFile(TestCaseContext testCaseCtx, TestFileContext ctx, Map<String, Object> variableCtx,
+ String statement, boolean isDmlRecoveryTest, ProcessBuilder pb, TestCase.CompilationUnit cUnit,
+ MutableInt queryCount, List<TestFileContext> expectedResultFileCtxs, File testFile, String actualPath,
+ BitSet expectedWarnings) throws Exception {
+ String[] lines;
+ switch (ctx.getType()) {
+ case "s3bucket":
+ // <bucket> <def> <sub-path:new_fname:src_file1,sub-path:new_fname:src_file2,sub-path:src_file3>
+ lines = TestExecutor.stripAllComments(statement).trim().split("\n");
+ String lastLine = lines[lines.length - 1];
+ String[] command = lastLine.trim().split(" ");
+ int length = command.length;
+ if (length != 3) {
+ throw new Exception("invalid create bucket format");
+ }
+ dropRecreateBucket(command[0], command[1], command[2]);
+ break;
+ default:
+ super.executeTestFile(testCaseCtx, ctx, variableCtx, statement, isDmlRecoveryTest, pb, cUnit,
+ queryCount, expectedResultFileCtxs, testFile, actualPath, expectedWarnings);
+ }
+ }
+ }
+
+ private static void dropRecreateBucket(String bucketName, String definition, String files) {
+ String definitionPath = definition + (definition.endsWith("/") ? "" : "/");
+ String[] fileSplits = files.split(",");
+
+ LOGGER.info("Dropping bucket " + bucketName);
+ try {
+ client.deleteBucket(DELETE_BUCKET_BUILDER.bucket(bucketName).build());
+ } catch (NoSuchBucketException e) {
+ // ignore
+ }
+ LOGGER.info("Creating bucket " + bucketName);
+ client.createBucket(CREATE_BUCKET_BUILDER.bucket(bucketName).build());
+ LOGGER.info("Uploading to bucket " + bucketName + " definition " + definitionPath);
+ fileNames.clear();
+ for (int i = 0; i < fileSplits.length; i++) {
+ String[] s3pathAndSourceFile = fileSplits[i].split(":");
+ int size = s3pathAndSourceFile.length;
+ String path;
+ String sourceFilePath;
+ String uploadedFileName;
+ if (size == 1) {
+ // case: playground json-data/reviews SOURCE_FILE1,SOURCE_FILE2
+ path = definitionPath;
+ sourceFilePath = s3pathAndSourceFile[0];
+ uploadedFileName = FilenameUtils.getName(s3pathAndSourceFile[0]);
+ } else if (size == 2) {
+ // case: playground json-data/reviews level1/sub-level:SOURCE_FILE1,level2/sub-level:SOURCE_FILE2
+ String subPathOrNewFileName = s3pathAndSourceFile[0];
+ if (subPathOrNewFileName.startsWith("$$")) {
+ path = definitionPath;
+ sourceFilePath = s3pathAndSourceFile[1];
+ uploadedFileName = subPathOrNewFileName.substring(2);
+ } else {
+ path = definitionPath + subPathOrNewFileName + (subPathOrNewFileName.endsWith("/") ? "" : "/");
+ sourceFilePath = s3pathAndSourceFile[1];
+ uploadedFileName = FilenameUtils.getName(s3pathAndSourceFile[1]);
+ }
+ } else if (size == 3) {
+ path = definitionPath + s3pathAndSourceFile[0] + (s3pathAndSourceFile[0].endsWith("/") ? "" : "/");
+ uploadedFileName = s3pathAndSourceFile[1];
+ sourceFilePath = s3pathAndSourceFile[2];
+
+ } else {
+ throw new IllegalArgumentException();
+ }
+
+ String keyPath = path + uploadedFileName;
+ int k = 1;
+ while (fileNames.contains(keyPath)) {
+ keyPath = path + (k++) + uploadedFileName;
+ }
+ fileNames.add(keyPath);
+ client.putObject(PUT_OBJECT_BUILDER.bucket(bucketName).key(keyPath).build(),
+ RequestBody.fromFile(Paths.get(sourceFilePath)));
+ }
+ LOGGER.info("Done creating bucket with data");
}
}
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/group-by/gby-case-01.3.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/optimizerts/queries/group-by/gby-case-01.3.sqlpp
index 2dd9cc5..37679f7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/group-by/gby-case-01.3.sqlpp
@@ -17,9 +17,15 @@
* under the License.
*/
+drop dataverse test if exists;
+create dataverse test;
+
use test;
-from test
-select value test
-order by id asc;
+create dataset t1(id integer not null) open type primary key id;
+select x,
+ case when sum(z)=0 then 0 else sum(y*z)/sum(z) end as res
+from t1
+group by x
+order by x;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/group-by/gby-case-01.4.sqlpp
similarity index 73%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/optimizerts/queries/group-by/gby-case-01.4.sqlpp
index 2dd9cc5..f9d5b77 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/group-by/gby-case-01.4.sqlpp
@@ -17,9 +17,20 @@
* under the License.
*/
+drop dataverse test if exists;
+create dataverse test;
+
use test;
-from test
-select value test
-order by id asc;
+create dataset t1(id integer not null) open type primary key id;
+create function f1() {
+ select x,
+ case when sum(z)=0 then 0 else sum(y*z)/sum(z) end as res
+ from t1
+ group by x
+};
+
+select x, res
+from f1() f
+order by x;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/group-by/gby-case-01.3.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/group-by/gby-case-01.3.plan
new file mode 100644
index 0000000..643e12f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/group-by/gby-case-01.3.plan
@@ -0,0 +1,24 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$x(ASC) ] |PARTITIONED|
+ -- SORT_GROUP_BY[$$93] |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- HASH_PARTITION_EXCHANGE [$$93] |PARTITIONED|
+ -- SORT_GROUP_BY[$$81] |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/group-by/gby-case-01.4.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/group-by/gby-case-01.4.plan
new file mode 100644
index 0000000..27432c6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/group-by/gby-case-01.4.plan
@@ -0,0 +1,24 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$x(ASC) ] |PARTITIONED|
+ -- SORT_GROUP_BY[$$120] |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- HASH_PARTITION_EXCHANGE [$$120] |PARTITIONED|
+ -- SORT_GROUP_BY[$$105] |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/metrics.xml b/asterixdb/asterix-app/src/test/resources/runtimets/metrics.xml
index da7ba31..a2c3ae5 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/metrics.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/metrics.xml
@@ -40,5 +40,10 @@
<output-dir compare="Text">secondary-index-index-only</output-dir>
</compilation-unit>
</test-case>
+ <test-case FilePath="metrics">
+ <compilation-unit name="external-dataset">
+ <output-dir compare="Text">external-dataset</output-dir>
+ </compilation-unit>
+ </test-case>
</test-group>
</test-suite>
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-non-query/get-non-query.1.get.http
similarity index 83%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-non-query/get-non-query.1.get.http
index 6e31eb3..e6aff85 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-non-query/get-non-query.1.get.http
@@ -16,7 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+/*
+ * Description: testing passing a non-query statement using GET
+ * Result: failure
+ */
+/query/service
+--body={"statement": "CREATE DATAVERSE dv1;"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-non-query/get-non-query.2.get.http
similarity index 81%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-non-query/get-non-query.2.get.http
index 6e31eb3..5dc6ec7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-non-query/get-non-query.2.get.http
@@ -16,7 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+/*
+ * Description: testing passing a non-query statement using GET
+ * Result: failure
+ */
+/query/service
+--body={"statement": "CREATE TYPE t1 AS {id: int};", "readonly": true}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-non-query/get-non-query.3.get.http
similarity index 81%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-non-query/get-non-query.3.get.http
index 6e31eb3..4f08b95 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-non-query/get-non-query.3.get.http
@@ -16,7 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+/*
+ * Description: testing passing a non-query statement using GET
+ * Result: failure
+ */
+/query/service
+--body={"statement": "CREATE FUNCTION foo(){1};", "readonly": false}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-query/get-query.1.get.http
similarity index 76%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-query/get-query.1.get.http
index 6e31eb3..4743d9f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-query/get-query.1.get.http
@@ -16,7 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+/*
+ * Description: testing passing a query statement using GET
+ * Result: success
+ */
+-- extractresult=true
+/query/service
+--body={"statement": "FROM Metadata.`Dataverse` v WHERE v.DataverseName = 'Metadata' SELECT VALUE v.DataverseName;"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-query/get-query.2.get.http
similarity index 75%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-query/get-query.2.get.http
index 6e31eb3..8995d4f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-query/get-query.2.get.http
@@ -16,7 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+/*
+ * Description: testing passing a query statement using GET
+ * Result: success
+ */
+-- extractresult=true
+/query/service
+--body={"statement": "FROM Metadata.`Dataverse` v WHERE v.DataverseName = 'Metadata' SELECT VALUE v.DataverseName;", "readonly": false}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-query/get-query.3.get.http
similarity index 75%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-query/get-query.3.get.http
index 6e31eb3..f821428 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/get-query/get-query.3.get.http
@@ -16,7 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+/*
+ * Description: testing passing a query statement using GET
+ * Result: success
+ */
+-- extractresult=true
+/query/service
+--body={"statement": "FROM Metadata.`Dataverse` v WHERE v.DataverseName = 'Metadata' SELECT VALUE v.DataverseName;", "readonly": true}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/post-non-query/post-non-query.1.post.http
similarity index 79%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/post-non-query/post-non-query.1.post.http
index 6e31eb3..eec1d95 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/post-non-query/post-non-query.1.post.http
@@ -16,7 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+/*
+ * Description: testing passing a non-query statement using POST with readonly set to true
+ * Result: failure
+ */
+/query/service
+--body={"statement": "CREATE TYPE t1 AS {id: int};", "readonly": true}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/post-non-query/post-non-query.2.post.http
similarity index 77%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/post-non-query/post-non-query.2.post.http
index 6e31eb3..0fa570b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/post-non-query/post-non-query.2.post.http
@@ -16,7 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+/*
+ * Description: testing passing a non-query statement using POST with readonly set to false
+ * Result: success
+ */
+-- extractstatus
+/query/service
+--body={"statement": "CREATE TYPE t1 AS {id: int};", "readonly": false}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/csv-tsv-parser/csv-parser-001/csv-parser-001.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/csv-tsv-parser/csv-parser-001/csv-parser-001.1.ddl.sqlpp
index f7fe18c..65816f6 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/csv-tsv-parser/csv-parser-001/csv-parser-001.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/csv-tsv-parser/csv-parser-001/csv-parser-001.1.ddl.sqlpp
@@ -30,6 +30,6 @@
CREATE EXTERNAL DATASET ds1(t1) USING localfs(("path"="asterix_nc1://data/csv/sample_09.csv"), ("format"="CSV"), ("header"="FALSE"));
CREATE EXTERNAL DATASET ds2(t2) USING localfs(("path"="asterix_nc1://data/csv/sample_10.csv"), ("format"="Csv"), ("header"="False"));
CREATE EXTERNAL DATASET ds3(t1) USING localfs(("path"="asterix_nc1://data/csv/sample_11.csv"), ("format"="csv"), ("header"="FALSE"));
-CREATE EXTERNAL DATASET ds4(t3) USING localfs(("path"="asterix_nc1://data/csv/sample_12.csv"), ("format"="csv"), ("header"="True"));
+CREATE EXTERNAL DATASET ds4(t3) USING localfs(("path"="asterix_nc1://data/csv/sample_12.csv"), ("format"="csv"), ("header"="True"), ("null"=""));
CREATE EXTERNAL DATASET ds5(t4) USING localfs(("path"="asterix_nc1://data/csv/sample_13.csv"), ("format"="csv"), ("header"="True"));
-CREATE EXTERNAL DATASET ds6(t4) USING localfs(("path"="asterix_nc1://data/csv/empty.csv"), ("format"="csv"), ("header"="false"));
\ No newline at end of file
+CREATE EXTERNAL DATASET ds6(t4) USING localfs(("path"="asterix_nc1://data/csv/empty_lines.csv"), ("format"="csv"), ("header"="false"));
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.000.s3bucket.sqlpp
similarity index 91%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.000.s3bucket.sqlpp
index 6e31eb3..dc8b719 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.000.s3bucket.sqlpp
@@ -16,7 +16,5 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+// create S3 bucket with data
+playground data_dir data/csv/empty.csv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.001.ddl.sqlpp
similarity index 75%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.001.ddl.sqlpp
index 6184b19..54022fc 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.001.ddl.sqlpp
@@ -21,17 +21,17 @@
CREATE DATAVERSE test;
USE test;
-DROP TYPE test IF EXISTS;
-CREATE TYPE test AS {id: int, year: int?, review: string, details: string?};
+DROP TYPE t1 IF EXISTS;
+CREATE TYPE t1 AS {f1: int, f2: int, f3: int, f4: string};
-DROP DATASET test IF EXISTS;
-CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+DROP DATASET ds1 IF EXISTS;
+CREATE EXTERNAL DATASET ds1(t1) USING S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="csv-data/reviews"),
-("format"="Csv"),
-("header"="false")
+("definition"="data_dir"),
+("format"="CSV"),
+("header"="true")
);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.002.query.sqlpp
similarity index 88%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.002.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.002.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.003.s3bucket.sqlpp
similarity index 90%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.003.s3bucket.sqlpp
index 6e31eb3..2b31301 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.003.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/csv/empty.csv,data/csv/empty.csv,data/csv/empty.csv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.005.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.005.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.005.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.006.s3bucket.sqlpp
similarity index 83%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.006.s3bucket.sqlpp
index 6e31eb3..5b7650a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.006.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/csv/header/h_one_rec.csv,data/csv/header/h_only.csv,data/csv/header/h_only_with_ln.csv,data/csv/header/h_one_rec_with_ln.csv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.008.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.008.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.008.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.009.s3bucket.sqlpp
similarity index 85%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.009.s3bucket.sqlpp
index 6e31eb3..d7f55e9 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.009.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/csv/header/h_mul_rec.csv,data/csv/empty.csv,data/csv/header/h_only.csv,data/csv/header/h_mul_rec_with_ln.csv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.011.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.011.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.011.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.099.ddl.sqlpp
similarity index 95%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.099.ddl.sqlpp
index 0ff713d..36b2bab 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-header/query-dataset.099.ddl.sqlpp
@@ -17,4 +17,4 @@
* under the License.
*/
-DROP DATASET test IF EXISTS;
\ No newline at end of file
+DROP DATAVERSE test IF EXISTS;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.000.s3bucket.sqlpp
similarity index 91%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.000.s3bucket.sqlpp
index 6e31eb3..dc8b719 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.000.s3bucket.sqlpp
@@ -16,7 +16,5 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+// create S3 bucket with data
+playground data_dir data/csv/empty.csv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.001.ddl.sqlpp
similarity index 76%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.001.ddl.sqlpp
index 6184b19..9adec32 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.001.ddl.sqlpp
@@ -21,17 +21,17 @@
CREATE DATAVERSE test;
USE test;
-DROP TYPE test IF EXISTS;
-CREATE TYPE test AS {id: int, year: int?, review: string, details: string?};
+DROP TYPE t1 IF EXISTS;
+CREATE TYPE t1 AS {f1: int, f2: int, f3: int, f4: string};
-DROP DATASET test IF EXISTS;
-CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+DROP DATASET ds1 IF EXISTS;
+CREATE EXTERNAL DATASET ds1(t1) USING S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="csv-data/reviews"),
-("format"="Csv"),
+("definition"="data_dir"),
+("format"="CSV"),
("header"="false")
);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.002.query.sqlpp
similarity index 88%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.002.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.002.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.003.s3bucket.sqlpp
similarity index 90%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.003.s3bucket.sqlpp
index 6e31eb3..2b31301 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.003.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/csv/empty.csv,data/csv/empty.csv,data/csv/empty.csv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.005.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.005.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.005.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.006.s3bucket.sqlpp
similarity index 84%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.006.s3bucket.sqlpp
index 6e31eb3..d42d322 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.006.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/csv/no_header/no_h_one_rec.csv,data/csv/empty.csv,data/csv/empty_lines.csv,data/csv/no_header/no_h_one_rec_with_ln.csv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.008.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.008.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.008.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.009.s3bucket.sqlpp
similarity index 86%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.009.s3bucket.sqlpp
index 6e31eb3..b9a9796 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.009.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/csv/no_header/no_h_mul_rec.csv,data/csv/empty.csv,data/csv/no_header/no_h_mul_rec_with_ln.csv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.011.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.011.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.011.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.099.ddl.sqlpp
similarity index 95%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.099.ddl.sqlpp
index 0ff713d..36b2bab 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-no-header/query-dataset.099.ddl.sqlpp
@@ -17,4 +17,4 @@
* under the License.
*/
-DROP DATASET test IF EXISTS;
\ No newline at end of file
+DROP DATAVERSE test IF EXISTS;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.001.s3bucket.sqlpp
similarity index 92%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.001.s3bucket.sqlpp
index 6e31eb3..132b862 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.001.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/csv/no_header/no_h_missing_fields.csv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.002.ddl.sqlpp
similarity index 66%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.002.ddl.sqlpp
index 6184b19..6df570c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.002.ddl.sqlpp
@@ -21,17 +21,21 @@
CREATE DATAVERSE test;
USE test;
-DROP TYPE test IF EXISTS;
-CREATE TYPE test AS {id: int, year: int?, review: string, details: string?};
+DROP TYPE t1 IF EXISTS;
+DROP TYPE t2 IF EXISTS;
+DROP TYPE t3 IF EXISTS;
+CREATE TYPE t1 AS {f1: int, f2: int, f3: int, f4: string};
+CREATE TYPE t2 AS {f1: bigint, f2: bigint?, f3: double, f4: double?, f5: string, f6: string?, f7: boolean, f8: boolean?};
+CREATE TYPE t3 AS {f1: bigint, f2: string, f3: string};
-DROP DATASET test IF EXISTS;
-CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+DROP DATASET ds1 IF EXISTS;
+CREATE EXTERNAL DATASET ds1(t1) USING S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="csv-data/reviews"),
-("format"="Csv"),
+("definition"="data_dir"),
+("format"="CSV"),
("header"="false")
);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.003.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.003.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.003.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.004.s3bucket.sqlpp
similarity index 88%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.004.s3bucket.sqlpp
index 6e31eb3..6aa6fc8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.004.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/csv/no_header/no_h_no_closing_q.csv,data/csv/no_header/no_h_one_rec.csv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.006.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.006.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.006.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.007.ddl.sqlpp
similarity index 73%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.007.ddl.sqlpp
index 9c6a994..047a540 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.007.ddl.sqlpp
@@ -17,22 +17,17 @@
* under the License.
*/
-drop dataverse test if exists;
-create dataverse test;
-use test;
+USE test;
-drop type test if exists;
-create type test as open {
-};
-
-drop dataset test if exists;
-create external dataset test(test) using S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+DROP DATASET ds1 IF EXISTS;
+CREATE EXTERNAL DATASET ds1(t1) USING S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="json-data/reviews"),
-("format"="json")
-);
-
+("definition"="data_dir"),
+("format"="CSV"),
+("header"="false"),
+("redact-warnings"="true")
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.008.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.008.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.008.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.009.s3bucket.sqlpp
similarity index 92%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.009.s3bucket.sqlpp
index 6e31eb3..f9da983 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.009.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/csv/header/h_invalid_values.csv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.010.ddl.sqlpp
similarity index 73%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.010.ddl.sqlpp
index 9c6a994..575d46f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.010.ddl.sqlpp
@@ -17,22 +17,18 @@
* under the License.
*/
-drop dataverse test if exists;
-create dataverse test;
-use test;
+USE test;
-drop type test if exists;
-create type test as open {
-};
-
-drop dataset test if exists;
-create external dataset test(test) using S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+DROP DATASET ds2 IF EXISTS;
+CREATE EXTERNAL DATASET ds2(t2) USING S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="json-data/reviews"),
-("format"="json")
-);
-
+("definition"="data_dir"),
+("format"="CSV"),
+("header"="true"),
+("redact-warnings"="true"),
+("null"="\\N")
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.011.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.011.query.sqlpp
index 6e31eb3..e6b24f3 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.011.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds2 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.012.ddl.sqlpp
similarity index 73%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.012.ddl.sqlpp
index 9c6a994..4148939 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.012.ddl.sqlpp
@@ -17,22 +17,17 @@
* under the License.
*/
-drop dataverse test if exists;
-create dataverse test;
-use test;
+USE test;
-drop type test if exists;
-create type test as open {
-};
-
-drop dataset test if exists;
-create external dataset test(test) using S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+DROP DATASET ds2 IF EXISTS;
+CREATE EXTERNAL DATASET ds2(t2) USING S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="json-data/reviews"),
-("format"="json")
-);
-
+("definition"="data_dir"),
+("format"="CSV"),
+("header"="true"),
+("null"="\\N")
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.013.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.013.query.sqlpp
index 6e31eb3..e6b24f3 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.013.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds2 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.014.s3bucket.sqlpp
similarity index 93%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.014.s3bucket.sqlpp
index 0ff713d..5d3989b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.014.s3bucket.sqlpp
@@ -17,4 +17,4 @@
* under the License.
*/
-DROP DATASET test IF EXISTS;
\ No newline at end of file
+playground data_dir data/csv/error1_line_num.csv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.015.ddl.sqlpp
similarity index 73%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.015.ddl.sqlpp
index 9c6a994..75ba5d6 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.015.ddl.sqlpp
@@ -17,22 +17,16 @@
* under the License.
*/
-drop dataverse test if exists;
-create dataverse test;
-use test;
+USE test;
-drop type test if exists;
-create type test as open {
-};
-
-drop dataset test if exists;
-create external dataset test(test) using S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+DROP DATASET ds2 IF EXISTS;
+CREATE EXTERNAL DATASET ds2(t3) USING S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="json-data/reviews"),
-("format"="json")
-);
-
+("definition"="data_dir"),
+("format"="CSV"),
+("header"="false")
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.016.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.016.query.sqlpp
index 6e31eb3..e6b24f3 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.016.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds2 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.017.s3bucket.sqlpp
similarity index 93%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.017.s3bucket.sqlpp
index 0ff713d..c35d646 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.017.s3bucket.sqlpp
@@ -17,4 +17,4 @@
* under the License.
*/
-DROP DATASET test IF EXISTS;
\ No newline at end of file
+playground data_dir data/csv/error2_line_num.csv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.018.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.018.query.sqlpp
index 6e31eb3..e6b24f3 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.018.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds2 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.099.ddl.sqlpp
similarity index 95%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.099.ddl.sqlpp
index 0ff713d..36b2bab 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv-warnings/query-dataset.099.ddl.sqlpp
@@ -17,4 +17,4 @@
* under the License.
*/
-DROP DATASET test IF EXISTS;
\ No newline at end of file
+DROP DATAVERSE test IF EXISTS;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/csv/query-dataset.000.ddl.sqlpp
similarity index 88%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/csv/query-dataset.000.ddl.sqlpp
index 6184b19..54e0dc4 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/csv/query-dataset.000.ddl.sqlpp
@@ -26,12 +26,13 @@
DROP DATASET test IF EXISTS;
CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="csv-data/reviews"),
+("definition"="csv-data/reviews/csv"),
("format"="Csv"),
-("header"="false")
+("header"="false"),
+("null"="")
);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/csv/query-dataset.002.query.sqlpp
similarity index 100%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.002.query.sqlpp
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/csv/query-dataset.002.query.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/csv/query-dataset.003.ddl.sqlpp
similarity index 100%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/csv/query-dataset.003.ddl.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/gz/query-dataset.000.ddl.sqlpp
similarity index 89%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/gz/query-dataset.000.ddl.sqlpp
index 6184b19..413987d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/gz/query-dataset.000.ddl.sqlpp
@@ -26,12 +26,13 @@
DROP DATASET test IF EXISTS;
CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="csv-data/reviews"),
+("definition"="csv-data/reviews/gz"),
("format"="Csv"),
-("header"="false")
+("header"="false"),
+("null"="")
);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/gz/query-dataset.002.query.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/gz/query-dataset.002.query.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/gz/query-dataset.003.ddl.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/gz/query-dataset.003.ddl.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/mixed/query-dataset.000.ddl.sqlpp
similarity index 88%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/mixed/query-dataset.000.ddl.sqlpp
index 6184b19..3ed6a3d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/mixed/query-dataset.000.ddl.sqlpp
@@ -26,12 +26,13 @@
DROP DATASET test IF EXISTS;
CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="csv-data/reviews"),
+("definition"="csv-data/reviews/mixed"),
("format"="Csv"),
-("header"="false")
+("header"="false"),
+("null"="")
);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/mixed/query-dataset.002.query.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/mixed/query-dataset.002.query.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/mixed/query-dataset.003.ddl.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/csv/mixed/query-dataset.003.ddl.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/empty-string-definition/external_dataset.000.ddl.sqlpp
similarity index 89%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/empty-string-definition/external_dataset.000.ddl.sqlpp
index 9c6a994..bb95094 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/empty-string-definition/external_dataset.000.ddl.sqlpp
@@ -27,12 +27,11 @@
drop dataset test if exists;
create external dataset test(test) using S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
-("container"="playground"),
-("definition"="json-data/reviews"),
+("container"="fixed-data-bucket"),
+("definition"=""),
("format"="json")
-);
-
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/empty-string-definition/external_dataset.001.query.sqlpp
similarity index 94%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/empty-string-definition/external_dataset.001.query.sqlpp
index 2dd9cc5..ec40ee0 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/empty-string-definition/external_dataset.001.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select count(*) `count` from test;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.002.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/empty-string-definition/external_dataset.099.ddl.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.002.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/empty-string-definition/external_dataset.099.ddl.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json-warnings/json-warnings.001.s3bucket.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json-warnings/json-warnings.001.s3bucket.sqlpp
index 6e31eb3..2bd413b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json-warnings/json-warnings.001.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir $$1.json:data/json/malformed-json-no-closing.json,$$2.json:data/json/double-150-11.json
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json-warnings/json-warnings.002.ddl.sqlpp
similarity index 75%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json-warnings/json-warnings.002.ddl.sqlpp
index 6184b19..7112bb9 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json-warnings/json-warnings.002.ddl.sqlpp
@@ -21,17 +21,16 @@
CREATE DATAVERSE test;
USE test;
-DROP TYPE test IF EXISTS;
-CREATE TYPE test AS {id: int, year: int?, review: string, details: string?};
+DROP TYPE t1 IF EXISTS;
+CREATE TYPE t1 AS {};
-DROP DATASET test IF EXISTS;
-CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+DROP DATASET ds1 IF EXISTS;
+CREATE EXTERNAL DATASET ds1(t1) USING S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="csv-data/reviews"),
-("format"="Csv"),
-("header"="false")
+("definition"="data_dir"),
+("format"="JSON")
);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json-warnings/json-warnings.003.query.sqlpp
similarity index 89%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json-warnings/json-warnings.003.query.sqlpp
index 6e31eb3..5f2ad26 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json-warnings/json-warnings.003.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json-warnings/json-warnings.099.ddl.sqlpp
similarity index 95%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json-warnings/json-warnings.099.ddl.sqlpp
index 0ff713d..36b2bab 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json-warnings/json-warnings.099.ddl.sqlpp
@@ -17,4 +17,4 @@
* under the License.
*/
-DROP DATASET test IF EXISTS;
\ No newline at end of file
+DROP DATAVERSE test IF EXISTS;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.000.ddl.sqlpp
new file mode 100644
index 0000000..bd6c7ca
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.000.ddl.sqlpp
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+drop type test if exists;
+create type test as open {
+};
+
+drop dataset test1 if exists;
+create external dataset test1(test) using S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
+("region"="us-west-2"),
+("serviceEndpoint"="http://localhost:8001"),
+("container"="playground"),
+("definition"="json-data/reviews/single-line/gz"),
+("format"="json")
+);
+
+drop dataset test2 if exists;
+create external dataset test2(test) using S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
+("region"="us-west-2"),
+("serviceEndpoint"="http://localhost:8001"),
+("container"="playground"),
+("definition"="json-data/reviews/multi-lines/gz"),
+("format"="json")
+);
+
+drop dataset test3 if exists;
+create external dataset test3(test) using S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
+("region"="us-west-2"),
+("serviceEndpoint"="http://localhost:8001"),
+("container"="playground"),
+("definition"="json-data/reviews/multi-lines-with-arrays/gz"),
+("format"="json")
+);
+
+drop dataset test4 if exists;
+create external dataset test4(test) using S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
+("region"="us-west-2"),
+("serviceEndpoint"="http://localhost:8001"),
+("container"="playground"),
+("definition"="json-data/reviews/multi-lines-with-nested-objects/gz"),
+("format"="json")
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.001.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.001.query.sqlpp
index 2dd9cc5..b72e741 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.001.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select count(*) `count` from test1;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.002.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.002.query.sqlpp
index 2dd9cc5..c3e883e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.002.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select count(*) `count` from test2;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.003.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.003.query.sqlpp
index 2dd9cc5..e3d64ff 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.003.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select count(*) `count` from test3;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.004.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.004.query.sqlpp
index 2dd9cc5..1fda76a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.004.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select value test3 from test3 order by id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.005.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.005.query.sqlpp
index 2dd9cc5..2b9b5cb 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.005.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select count(*) `count` from test4;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.006.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.006.query.sqlpp
index 2dd9cc5..2cd184d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.006.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select value test4 from test4 order by id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.002.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.007.ddl.sqlpp
similarity index 100%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.002.ddl.sqlpp
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/gz/external_dataset.007.ddl.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.000.ddl.sqlpp
new file mode 100644
index 0000000..c3e0d20
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.000.ddl.sqlpp
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+drop type test if exists;
+create type test as open {
+};
+
+drop dataset test1 if exists;
+create external dataset test1(test) using S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
+("region"="us-west-2"),
+("serviceEndpoint"="http://localhost:8001"),
+("container"="playground"),
+("definition"="json-data/reviews/single-line/json"),
+("format"="json")
+);
+
+drop dataset test2 if exists;
+create external dataset test2(test) using S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
+("region"="us-west-2"),
+("serviceEndpoint"="http://localhost:8001"),
+("container"="playground"),
+("definition"="json-data/reviews/multi-lines/json"),
+("format"="json")
+);
+
+drop dataset test3 if exists;
+create external dataset test3(test) using S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
+("region"="us-west-2"),
+("serviceEndpoint"="http://localhost:8001"),
+("container"="playground"),
+("definition"="json-data/reviews/multi-lines-with-arrays/json"),
+("format"="json")
+);
+
+drop dataset test4 if exists;
+create external dataset test4(test) using S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
+("region"="us-west-2"),
+("serviceEndpoint"="http://localhost:8001"),
+("container"="playground"),
+("definition"="json-data/reviews/multi-lines-with-nested-objects/json"),
+("format"="json")
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.001.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.001.query.sqlpp
index 2dd9cc5..b72e741 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.001.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select count(*) `count` from test1;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.002.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.002.query.sqlpp
index 2dd9cc5..c3e883e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.002.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select count(*) `count` from test2;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.003.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.003.query.sqlpp
index 2dd9cc5..e3d64ff 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.003.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select count(*) `count` from test3;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.004.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.004.query.sqlpp
index 2dd9cc5..1fda76a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.004.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select value test3 from test3 order by id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.005.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.005.query.sqlpp
index 2dd9cc5..2b9b5cb 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.005.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select count(*) `count` from test4;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.006.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.006.query.sqlpp
index 2dd9cc5..2cd184d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.006.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select value test4 from test4 order by id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.002.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.007.ddl.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.002.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/json/external_dataset.007.ddl.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.000.ddl.sqlpp
new file mode 100644
index 0000000..32d8388
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.000.ddl.sqlpp
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+drop type test if exists;
+create type test as open {
+};
+
+drop dataset test1 if exists;
+create external dataset test1(test) using S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
+("region"="us-west-2"),
+("serviceEndpoint"="http://localhost:8001"),
+("container"="playground"),
+("definition"="json-data/reviews/single-line/mixed"),
+("format"="json")
+);
+
+drop dataset test2 if exists;
+create external dataset test2(test) using S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
+("region"="us-west-2"),
+("serviceEndpoint"="http://localhost:8001"),
+("container"="playground"),
+("definition"="json-data/reviews/multi-lines/mixed"),
+("format"="json")
+);
+
+drop dataset test3 if exists;
+create external dataset test3(test) using S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
+("region"="us-west-2"),
+("serviceEndpoint"="http://localhost:8001"),
+("container"="playground"),
+("definition"="json-data/reviews/multi-lines-with-arrays/mixed"),
+("format"="json")
+);
+
+drop dataset test4 if exists;
+create external dataset test4(test) using S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
+("region"="us-west-2"),
+("serviceEndpoint"="http://localhost:8001"),
+("container"="playground"),
+("definition"="json-data/reviews/multi-lines-with-nested-objects/mixed"),
+("format"="json")
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.001.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.001.query.sqlpp
index 2dd9cc5..b72e741 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.001.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select count(*) `count` from test1;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.002.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.002.query.sqlpp
index 2dd9cc5..c3e883e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.002.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select count(*) `count` from test2;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.003.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.003.query.sqlpp
index 2dd9cc5..e3d64ff 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.003.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select count(*) `count` from test3;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.004.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.004.query.sqlpp
index 2dd9cc5..1fda76a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.004.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select value test3 from test3 order by id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.005.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.005.query.sqlpp
index 2dd9cc5..2b9b5cb 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.005.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select count(*) `count` from test4;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.006.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.006.query.sqlpp
index 2dd9cc5..2cd184d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.006.query.sqlpp
@@ -19,7 +19,5 @@
use test;
-from test
-select value test
-order by id asc;
+select value test4 from test4 order by id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.002.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.007.ddl.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.002.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/json/mixed/external_dataset.007.ddl.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/jsonl/query-dataset.000.s3bucket.sqlpp
similarity index 73%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/jsonl/query-dataset.000.s3bucket.sqlpp
index 6e31eb3..5def284 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/jsonl/query-dataset.000.s3bucket.sqlpp
@@ -16,7 +16,5 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+// create S3 bucket with data
+playground data_dir level1a:data/jsonl/multi-lines/20-records.json,level1a/level2a:data/jsonl/multi-lines-with-arrays/5-records.json,level1b:data/jsonl/multi-lines-with-nested-objects/5-records.json,level1b/level2b:data/jsonl/single-line/20-records.json
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/jsonl/query-dataset.001.ddl.sqlpp
similarity index 75%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/jsonl/query-dataset.001.ddl.sqlpp
index 9c6a994..75535fb 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/jsonl/query-dataset.001.ddl.sqlpp
@@ -17,22 +17,20 @@
* under the License.
*/
-drop dataverse test if exists;
-create dataverse test;
-use test;
+DROP DATAVERSE test IF EXISTS;
+CREATE DATAVERSE test;
+USE test;
-drop type test if exists;
-create type test as open {
-};
+DROP TYPE t1 IF EXISTS;
+CREATE TYPE t1 AS OPEN {};
-drop dataset test if exists;
-create external dataset test(test) using S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+DROP DATASET ds1 IF EXISTS;
+CREATE EXTERNAL DATASET ds1(t1) USING S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="json-data/reviews"),
+("definition"="data_dir"),
("format"="json")
-);
-
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/jsonl/query-dataset.002.query.sqlpp
similarity index 88%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/jsonl/query-dataset.002.query.sqlpp
index 6e31eb3..87490e6 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/jsonl/query-dataset.002.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.id ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/jsonl/query-dataset.099.ddl.sqlpp
similarity index 95%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/jsonl/query-dataset.099.ddl.sqlpp
index 0ff713d..36b2bab 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/jsonl/query-dataset.099.ddl.sqlpp
@@ -17,4 +17,4 @@
* under the License.
*/
-DROP DATASET test IF EXISTS;
\ No newline at end of file
+DROP DATAVERSE test IF EXISTS;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/negative/negative.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/negative/negative.000.ddl.sqlpp
index e0fc056..69768e8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/negative/negative.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/negative/negative.000.ddl.sqlpp
@@ -27,8 +27,8 @@
DROP DATASET test IF EXISTS;
CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.000.s3bucket.sqlpp
similarity index 91%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.000.s3bucket.sqlpp
index 6e31eb3..929442e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.000.s3bucket.sqlpp
@@ -16,7 +16,5 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+// create S3 bucket with data
+playground data_dir data/tsv/empty.tsv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.001.ddl.sqlpp
similarity index 75%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.001.ddl.sqlpp
index 6184b19..265c884 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.001.ddl.sqlpp
@@ -21,17 +21,17 @@
CREATE DATAVERSE test;
USE test;
-DROP TYPE test IF EXISTS;
-CREATE TYPE test AS {id: int, year: int?, review: string, details: string?};
+DROP TYPE t1 IF EXISTS;
+CREATE TYPE t1 AS {f1: int, f2: int, f3: int, f4: string};
-DROP DATASET test IF EXISTS;
-CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+DROP DATASET ds1 IF EXISTS;
+CREATE EXTERNAL DATASET ds1(t1) USING S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="csv-data/reviews"),
-("format"="Csv"),
-("header"="false")
+("definition"="data_dir"),
+("format"="tsv"),
+("header"="true")
);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.002.query.sqlpp
similarity index 88%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.002.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.002.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.003.s3bucket.sqlpp
similarity index 90%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.003.s3bucket.sqlpp
index 6e31eb3..dea81a0 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.003.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/tsv/empty.tsv,data/tsv/empty.tsv,data/tsv/empty.tsv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.005.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.005.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.005.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.006.s3bucket.sqlpp
similarity index 83%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.006.s3bucket.sqlpp
index 6e31eb3..bbdba98 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.006.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/tsv/header/h_one_rec.tsv,data/tsv/header/h_only.tsv,data/tsv/header/h_only_with_ln.tsv,data/tsv/header/h_one_rec_with_ln.tsv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.008.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.008.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.008.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.009.s3bucket.sqlpp
similarity index 85%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.009.s3bucket.sqlpp
index 6e31eb3..a2a20d2 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.009.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/tsv/header/h_mul_rec.tsv,data/tsv/empty.tsv,data/tsv/header/h_only.tsv,data/tsv/header/h_mul_rec_with_ln.tsv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.011.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.011.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.011.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.099.ddl.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-header/query-dataset.099.ddl.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.000.s3bucket.sqlpp
similarity index 91%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.000.s3bucket.sqlpp
index 6e31eb3..929442e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.000.s3bucket.sqlpp
@@ -16,7 +16,5 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+// create S3 bucket with data
+playground data_dir data/tsv/empty.tsv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.001.ddl.sqlpp
similarity index 76%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.001.ddl.sqlpp
index 6184b19..aacf1bd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.001.ddl.sqlpp
@@ -21,17 +21,17 @@
CREATE DATAVERSE test;
USE test;
-DROP TYPE test IF EXISTS;
-CREATE TYPE test AS {id: int, year: int?, review: string, details: string?};
+DROP TYPE t1 IF EXISTS;
+CREATE TYPE t1 AS {f1: int, f2: int, f3: int, f4: string};
-DROP DATASET test IF EXISTS;
-CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+DROP DATASET ds1 IF EXISTS;
+CREATE EXTERNAL DATASET ds1(t1) USING S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="csv-data/reviews"),
-("format"="Csv"),
+("definition"="data_dir"),
+("format"="tsv"),
("header"="false")
);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.002.query.sqlpp
similarity index 88%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.002.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.002.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.003.s3bucket.sqlpp
similarity index 90%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.003.s3bucket.sqlpp
index 6e31eb3..dea81a0 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.003.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/tsv/empty.tsv,data/tsv/empty.tsv,data/tsv/empty.tsv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.005.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.005.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.005.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.006.s3bucket.sqlpp
similarity index 84%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.006.s3bucket.sqlpp
index 6e31eb3..2a7fa79 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.006.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/tsv/no_header/no_h_one_rec.tsv,data/tsv/empty.tsv,data/tsv/empty_lines.tsv,data/tsv/no_header/no_h_one_rec_with_ln.tsv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.008.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.008.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.008.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.009.s3bucket.sqlpp
similarity index 86%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.009.s3bucket.sqlpp
index 6e31eb3..ce3de3c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.009.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/tsv/no_header/no_h_mul_rec.tsv,data/tsv/empty.tsv,data/tsv/no_header/no_h_mul_rec_with_ln.tsv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.011.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.011.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.011.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.099.ddl.sqlpp
similarity index 95%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.099.ddl.sqlpp
index 0ff713d..36b2bab 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-no-header/query-dataset.099.ddl.sqlpp
@@ -17,4 +17,4 @@
* under the License.
*/
-DROP DATASET test IF EXISTS;
\ No newline at end of file
+DROP DATAVERSE test IF EXISTS;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-warnings/query-dataset.001.s3bucket.sqlpp
similarity index 92%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-warnings/query-dataset.001.s3bucket.sqlpp
index 6e31eb3..2bd6d52 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-warnings/query-dataset.001.s3bucket.sqlpp
@@ -17,6 +17,4 @@
* under the License.
*/
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+playground data_dir data/tsv/no_header/no_h_missing_fields.tsv
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-warnings/query-dataset.002.ddl.sqlpp
similarity index 76%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-warnings/query-dataset.002.ddl.sqlpp
index 6184b19..aacf1bd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-warnings/query-dataset.002.ddl.sqlpp
@@ -21,17 +21,17 @@
CREATE DATAVERSE test;
USE test;
-DROP TYPE test IF EXISTS;
-CREATE TYPE test AS {id: int, year: int?, review: string, details: string?};
+DROP TYPE t1 IF EXISTS;
+CREATE TYPE t1 AS {f1: int, f2: int, f3: int, f4: string};
-DROP DATASET test IF EXISTS;
-CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+DROP DATASET ds1 IF EXISTS;
+CREATE EXTERNAL DATASET ds1(t1) USING S3 (
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="csv-data/reviews"),
-("format"="Csv"),
+("definition"="data_dir"),
+("format"="tsv"),
("header"="false")
);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-warnings/query-dataset.003.query.sqlpp
similarity index 87%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-warnings/query-dataset.003.query.sqlpp
index 6e31eb3..26ccfa7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-warnings/query-dataset.003.query.sqlpp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+// requesttype=application/json
+// param max-warnings:json=100
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+FROM ds1 v SELECT VALUE v ORDER BY v.f1 ASC;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-warnings/query-dataset.099.ddl.sqlpp
similarity index 95%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-warnings/query-dataset.099.ddl.sqlpp
index 0ff713d..36b2bab 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.003.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv-warnings/query-dataset.099.ddl.sqlpp
@@ -17,4 +17,4 @@
* under the License.
*/
-DROP DATASET test IF EXISTS;
\ No newline at end of file
+DROP DATAVERSE test IF EXISTS;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/gz/query-dataset.000.ddl.sqlpp
similarity index 89%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.000.ddl.sqlpp
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/gz/query-dataset.000.ddl.sqlpp
index 194adf6..439eb0d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/gz/query-dataset.000.ddl.sqlpp
@@ -26,12 +26,13 @@
DROP DATASET test IF EXISTS;
CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="tsv-data/reviews"),
+("definition"="tsv-data/reviews/gz"),
("format"="TSV"),
-("header"="False")
+("header"="False"),
+("null"="")
);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/gz/query-dataset.002.query.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/gz/query-dataset.002.query.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/gz/query-dataset.003.ddl.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/gz/query-dataset.003.ddl.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/mixed/query-dataset.000.ddl.sqlpp
similarity index 88%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/mixed/query-dataset.000.ddl.sqlpp
index 194adf6..232a6d6 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/mixed/query-dataset.000.ddl.sqlpp
@@ -26,12 +26,13 @@
DROP DATASET test IF EXISTS;
CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="tsv-data/reviews"),
+("definition"="tsv-data/reviews/mixed"),
("format"="TSV"),
-("header"="False")
+("header"="False"),
+("null"="")
);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/mixed/query-dataset.002.query.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/mixed/query-dataset.002.query.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/mixed/query-dataset.003.ddl.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/mixed/query-dataset.003.ddl.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/tsv/query-dataset.000.ddl.sqlpp
similarity index 88%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/tsv/query-dataset.000.ddl.sqlpp
index 194adf6..7a1c0e1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/tsv/query-dataset.000.ddl.sqlpp
@@ -26,12 +26,13 @@
DROP DATASET test IF EXISTS;
CREATE EXTERNAL DATASET test(test) USING S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
+("accessKeyId"="dummyAccessKey"),
+("secretAccessKey"="dummySecretKey"),
("region"="us-west-2"),
("serviceEndpoint"="http://localhost:8001"),
("container"="playground"),
-("definition"="tsv-data/reviews"),
+("definition"="tsv-data/reviews/tsv"),
("format"="TSV"),
-("header"="False")
+("header"="False"),
+("null"="")
);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/tsv/query-dataset.002.query.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/tsv/query-dataset.002.query.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/tsv/query-dataset.003.ddl.sqlpp
similarity index 100%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/001/query-dataset.003.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/tsv/tsv/query-dataset.003.ddl.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-case-01/gby-case-01.1.ddl.sqlpp
similarity index 76%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-case-01/gby-case-01.1.ddl.sqlpp
index 2dd9cc5..4c6addb 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-case-01/gby-case-01.1.ddl.sqlpp
@@ -17,9 +17,16 @@
* under the License.
*/
+drop dataverse test if exists;
+create dataverse test;
+
use test;
-from test
-select value test
-order by id asc;
+create dataset t1(id integer not null) open type primary key id;
+create function f1() {
+ select x,
+ case when sum(z)=0 then 0 else sum(y*z)/sum(z) end as res
+ from t1
+ group by x
+};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-case-01/gby-case-01.2.update.sqlpp
similarity index 68%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-case-01/gby-case-01.2.update.sqlpp
index 2dd9cc5..9c37cf5 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-case-01/gby-case-01.2.update.sqlpp
@@ -19,7 +19,42 @@
use test;
-from test
-select value test
-order by id asc;
-
+insert into t1
+([
+ {
+ "id": 10,
+ "x": 1,
+ "y": 2,
+ "z": 2
+ },
+ {
+ "id": 11,
+ "x": 1,
+ "y": 4,
+ "z": 4
+ },
+ {
+ "id": 12,
+ "x": 1,
+ "y": 8,
+ "z": 8
+ },
+ {
+ "id": 20,
+ "x": 2,
+ "y": 2,
+ "z": 0
+ },
+ {
+ "id": 21,
+ "x": 2,
+ "y": 4,
+ "z": 0
+ },
+ {
+ "id": 22,
+ "x": 2,
+ "y": 8,
+ "z": 0
+ }
+]);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-case-01/gby-case-01.3.query.sqlpp
similarity index 88%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-case-01/gby-case-01.3.query.sqlpp
index 2dd9cc5..90a432c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-case-01/gby-case-01.3.query.sqlpp
@@ -19,7 +19,8 @@
use test;
-from test
-select value test
-order by id asc;
-
+select x,
+ case when sum(z)=0 then 0 else sum(y*z)/sum(z) end as res
+from t1
+group by x
+order by x;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-case-01/gby-case-01.4.query.sqlpp
similarity index 94%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-case-01/gby-case-01.4.query.sqlpp
index 2dd9cc5..6cf2ac9 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-case-01/gby-case-01.4.query.sqlpp
@@ -19,7 +19,6 @@
use test;
-from test
-select value test
-order by id asc;
-
+select x, res
+from f1() f
+order by x;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-nested-01/gby-nested-01.1.ddl.sqlpp
similarity index 80%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-nested-01/gby-nested-01.1.ddl.sqlpp
index 2dd9cc5..859c349 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-nested-01/gby-nested-01.1.ddl.sqlpp
@@ -17,9 +17,10 @@
* under the License.
*/
+drop dataverse test if exists;
+create dataverse test;
+
use test;
-from test
-select value test
-order by id asc;
-
+create dataset prd(p_id integer not null) open type primary key p_id;
+create dataset sls(s_id integer not null) open type primary key s_id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-nested-01/gby-nested-01.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-nested-01/gby-nested-01.2.update.sqlpp
new file mode 100644
index 0000000..1fb010e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-nested-01/gby-nested-01.2.update.sqlpp
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+use test;
+
+insert into prd
+([
+ {
+ "p_id": 1,
+ "p_name": "PRODUCT_1"
+ },
+ {
+ "p_id": 2,
+ "p_name": "PRODUCT_2"
+ }
+]);
+
+insert into sls
+([
+ {
+ "s_id": 10,
+ "s_pid": 1,
+ "s_year": 2019,
+ "s_city": [
+ { "ct_id": "SFO", "ct_sum": 10, "ct_avg": 5.0 },
+ { "ct_id": "SJC", "ct_sum": 12, "ct_avg": 6.0 },
+ { "ct_id": "RNO", "ct_sum": 14, "ct_avg": 7.0 },
+ { "ct_id": "LAS", "ct_sum": 16, "ct_avg": 8.0 }
+ ],
+ "s_state": [
+ { "st_id": "CA", "st_sum": 22, "st_avg": 5.5 },
+ { "st_id": "NV", "st_sum": 30, "st_avg": 7.5 }
+ ]
+ },
+ {
+ "s_id": 11,
+ "s_pid": 1,
+ "s_year": 2020,
+ "s_city": [
+ { "st_id": "SFO", "ct_sum": 20, "ct_avg": 10.0 },
+ { "st_id": "SJC", "ct_sum": 22, "ct_avg": 11.0 },
+ { "st_id": "RNO", "ct_sum": 24, "ct_avg": 12.0 },
+ { "st_id": "LAS", "ct_sum": 26, "ct_avg": 13.0 }
+ ],
+ "s_state": [
+ { "st_id": "CA", "st_sum": 42, "st_avg": 10.5 },
+ { "st_id": "NV", "st_sum": 50, "st_avg": 12.5 }
+ ]
+ }
+]);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-nested-01/gby-nested-01.3.query.sqlpp
similarity index 62%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-nested-01/gby-nested-01.3.query.sqlpp
index 6e31eb3..f417383 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-nested-01/gby-nested-01.3.query.sqlpp
@@ -19,4 +19,27 @@
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+SELECT p.p_id, p.p_name,
+ (
+ SELECT c.ct_id,
+ SUM(c.ct_sum) AS ct_sum,
+ SUM(c.ct_avg) AS ct_avg
+ FROM scs, scs.s_city AS c
+ GROUP BY c.ct_id
+ ORDER BY c.ct_id
+ ) AS ct,
+ (
+ SELECT s.st_id,
+ SUM(s.st_sum) AS st_sum,
+ SUM(s.st_avg) AS st_avg
+ FROM scs, scs.s_state AS s
+ GROUP BY s.st_id
+ ORDER BY s.st_id
+ ) AS st
+FROM prd AS p
+LET scs = (
+ SELECT s.s_city, s.s_state
+ FROM sls s
+ WHERE p.p_id = s.s_pid
+)
+ORDER BY p.p_id
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.01.ddl.sqlpp
similarity index 80%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.01.ddl.sqlpp
index 2dd9cc5..e656d9d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.01.ddl.sqlpp
@@ -17,9 +17,16 @@
* under the License.
*/
+drop dataverse test if exists;
+create dataverse test;
+
use test;
-from test
-select value test
-order by id asc;
+create type test.TestType as
+{
+ id : integer
+};
+create dataset t1(TestType) primary key id;
+
+create dataset t2(TestType) primary key id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.02.update.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.02.update.sqlpp
index 2dd9cc5..950f728 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.02.update.sqlpp
@@ -19,7 +19,16 @@
use test;
-from test
-select value test
-order by id asc;
+insert into t1
+([
+ {"id":1, "x":1, "a": 11 },
+ {"id":2, "x":2, "a": 12 },
+ {"id":3, "x":3, "a": 13 },
+ {"id":4, "x":4, "a": 14 }
+]);
+insert into t2
+([
+ {"id":1, "y":1, "b": 111 },
+ {"id":2, "y":2, "b": 112 }
+]);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.03.query.sqlpp
similarity index 70%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.03.query.sqlpp
index 2dd9cc5..5be33b9 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.03.query.sqlpp
@@ -17,9 +17,16 @@
* under the License.
*/
+/*
+ * Test WHERE .. IS MISSING using right side of an outer join.
+ * 1:1 left outer join.
+ * Expect only 2 tuples in the result (x=3 and x=4 that didn't join)
+ * because t2_right.y evaluates to MISSING in those tuples.
+ */
+
use test;
-from test
-select value test
-order by id asc;
-
+select *
+from t1 t1_left left join t2 t2_right on t1_left.x = t2_right.y
+where t2_right.y is missing
+order by t1_left.a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.04.query.sqlpp
similarity index 67%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.04.query.sqlpp
index 2dd9cc5..20ebff4 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.001.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.04.query.sqlpp
@@ -17,9 +17,17 @@
* under the License.
*/
+/*
+ * Test WHERE .. IS UNKNOWN using right side of an outer join.
+ * 1:1 left outer join.
+ * Expect only 2 tuples in the result (x=3 and x=4 that didn't join)
+ * because t2_right.y evaluates to MISSING in those tuples,
+ * therefore IS UNKNOWN evaluates to TRUE
+ */
+
use test;
-from test
-select value test
-order by id asc;
-
+select *
+from t1 t1_left left join t2 t2_right on t1_left.x = t2_right.y
+where t2_right.y is unknown
+order by t1_left.a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.05.query.sqlpp
similarity index 64%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.05.query.sqlpp
index 9c6a994..0d9515b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.05.query.sqlpp
@@ -17,22 +17,17 @@
* under the License.
*/
-drop dataverse test if exists;
-create dataverse test;
+/*
+ * Test WHERE IF_MISSING(.., "missing") using right side of an outer join.
+ * 1:1 left outer join.
+ * Expect only 2 tuples in the result (x=3 and x=4 that didn't join)
+ * because t2_right.y evaluates to MISSING in those tuples,
+ * therefore IF_MISSING(.., "missing") evaluates to "missing"
+ */
+
use test;
-drop type test if exists;
-create type test as open {
-};
-
-drop dataset test if exists;
-create external dataset test(test) using S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
-("region"="us-west-2"),
-("serviceEndpoint"="http://localhost:8001"),
-("container"="playground"),
-("definition"="json-data/reviews"),
-("format"="json")
-);
-
+select *
+from t1 t1_left left join t2 t2_right on t1_left.x = t2_right.y
+where if_missing(t2_right.y, "missing") = "missing"
+order by t1_left.a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.06.query.sqlpp
similarity index 66%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.06.query.sqlpp
index 9c6a994..9315032 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/000/external_dataset.000.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-02-push-select/loj-02-push-select.06.query.sqlpp
@@ -17,22 +17,17 @@
* under the License.
*/
-drop dataverse test if exists;
-create dataverse test;
+/*
+ * Test WHERE clause using both sides of an outer join.
+ * 1:1 left outer join.
+ * Expect only 2 tuples in the result (x=1 and x=2 that did join)
+ * because t2_right.y and therefore to_string(t2_right.y)
+ * evaluate to MISSING for the other 2 that didn't join.
+ */
+
use test;
-drop type test if exists;
-create type test as open {
-};
-
-drop dataset test if exists;
-create external dataset test(test) using S3 (
-("accessKey"="dummyAccessKey"),
-("secretKey"="dummySecretKey"),
-("region"="us-west-2"),
-("serviceEndpoint"="http://localhost:8001"),
-("container"="playground"),
-("definition"="json-data/reviews"),
-("format"="json")
-);
-
+select *
+from t1 t1_left left join t2 t2_right on t1_left.x = t2_right.y
+where to_string(t1_left.x) = to_string(t2_right.y)
+order by t1_left.a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_01/csv_01.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_01/csv_01.2.update.sqlpp
index 988ebe3..68faf3f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_01/csv_01.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_01/csv_01.2.update.sqlpp
@@ -26,5 +26,5 @@
use temp;
-load dataset testds using localfs ((`path`=`asterix_nc1://data/csv/sample_01.csv`),(`format`=`delimited-text`),(`delimiter`=`,`));
+load dataset testds using localfs ((`path`=`asterix_nc1://data/csv/sample_01.csv`),(`format`=`delimited-text`),(`delimiter`=`,`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_02/csv_02.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_02/csv_02.2.update.sqlpp
index 988ebe3..68faf3f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_02/csv_02.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_02/csv_02.2.update.sqlpp
@@ -26,5 +26,5 @@
use temp;
-load dataset testds using localfs ((`path`=`asterix_nc1://data/csv/sample_01.csv`),(`format`=`delimited-text`),(`delimiter`=`,`));
+load dataset testds using localfs ((`path`=`asterix_nc1://data/csv/sample_01.csv`),(`format`=`delimited-text`),(`delimiter`=`,`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_03/csv_03.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_03/csv_03.2.update.sqlpp
index 7eaaf1d..fdc1d1a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_03/csv_03.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_03/csv_03.2.update.sqlpp
@@ -26,5 +26,5 @@
use temp;
-load dataset testds using localfs ((`path`=`asterix_nc1://data/csv/sample_02.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset testds using localfs ((`path`=`asterix_nc1://data/csv/sample_02.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_08_header_cr/csv_08.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_08_header_cr/csv_08.2.update.sqlpp
index e44dfe9..d05c821 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_08_header_cr/csv_08.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_08_header_cr/csv_08.2.update.sqlpp
@@ -26,5 +26,5 @@
use temp;
-load dataset testds using localfs ((`path`=`asterix_nc1://data/csv/sample_08_header.csv.cr`),(`format`=`delimited-text`),(`header`=`true`));
+load dataset testds using localfs ((`path`=`asterix_nc1://data/csv/sample_08_header.csv.cr`),(`format`=`delimited-text`),(`header`=`true`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_08_header_crlf/csv_08.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_08_header_crlf/csv_08.2.update.sqlpp
index e4da86b..9be6773 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_08_header_crlf/csv_08.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_08_header_crlf/csv_08.2.update.sqlpp
@@ -26,5 +26,5 @@
use temp;
-load dataset testds using localfs ((`path`=`asterix_nc1://data/csv/sample_08_header.csv.crlf`),(`format`=`delimited-text`),(`header`=`true`));
+load dataset testds using localfs ((`path`=`asterix_nc1://data/csv/sample_08_header.csv.crlf`),(`format`=`delimited-text`),(`header`=`true`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_08_header_lf/csv_08.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_08_header_lf/csv_08.2.update.sqlpp
index e024bd3..102b2aa 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_08_header_lf/csv_08.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/load/csv_08_header_lf/csv_08.2.update.sqlpp
@@ -26,5 +26,5 @@
use temp;
-load dataset testds using localfs ((`path`=`asterix_nc1://data/csv/sample_08_header.csv.lf`),(`format`=`delimited-text`),(`header`=`true`));
+load dataset testds using localfs ((`path`=`asterix_nc1://data/csv/sample_08_header.csv.lf`),(`format`=`delimited-text`),(`header`=`true`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/metrics/external-dataset/external-dataset.1.ddl.sqlpp
similarity index 68%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/metrics/external-dataset/external-dataset.1.ddl.sqlpp
index 6e31eb3..a105dfe 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/metrics/external-dataset/external-dataset.1.ddl.sqlpp
@@ -16,7 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
+/*
+ * Description : Processed objects metrics on external dataset
+ * Expected Res : Success
+ */
+
+DROP DATAVERSE test IF EXISTS;
+CREATE DATAVERSE test;
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+CREATE TYPE t1 AS {f1: string, f2: string, f3: string, f4: string, f5: string};
+
+CREATE EXTERNAL DATASET ds1(t1) USING localfs(("path"="asterix_nc1://data/csv/sample_09.csv"), ("format"="CSV"), ("header"="FALSE"));
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/metrics/external-dataset/external-dataset.2.metrics.sqlpp
similarity index 86%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/metrics/external-dataset/external-dataset.2.metrics.sqlpp
index 6e31eb3..e57e938 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/metrics/external-dataset/external-dataset.2.metrics.sqlpp
@@ -16,7 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
+/*
+ * Description : Processed objects metrics on external dataset
+ * Expected Res : Success
+ */
USE test;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+SELECT COUNT(*) from ds1;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/metrics/external-dataset/external-datasett.3.ddl.sqlpp
similarity index 86%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/metrics/external-dataset/external-datasett.3.ddl.sqlpp
index 6e31eb3..0bf95e4 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/metrics/external-dataset/external-datasett.3.ddl.sqlpp
@@ -16,7 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
+/*
+ * Description : Processed objects metrics on external dataset
+ * Expected Res : Success
+ */
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+DROP DATAVERSE test;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/ObjectsQueries.xml b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/ObjectsQueries.xml
index b1ccdcd..d8a13414 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/ObjectsQueries.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/ObjectsQueries.xml
@@ -223,7 +223,7 @@
<expected-warn>Duplicate field name "name" (in line 22, at column 30)</expected-warn>
<expected-warn>Duplicate field name "id" (in line 22, at column 56)</expected-warn>
<expected-warn>Duplicate field name "f1" (in line 22, at column 70)</expected-warn>
- <expected-warn>Duplicate field name "id" (in line 22, at column 36)</expected-warn>
+ <expected-warn>Duplicate field name "id" (in line 22, at column 56)</expected-warn>
<expected-warn>Duplicate field name "f1" (in line 22, at column 83)</expected-warn>
<expected-warn>Duplicate field name "fname1" (in line 25, at column 45)</expected-warn>
</compilation-unit>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q19/q19.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q19/q19.2.update.sqlpp
index b59d644..fc0b44a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q19/q19.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q19/q19.2.update.sqlpp
@@ -20,14 +20,14 @@
use tpcds;
-load dataset customer_address using localfs ((`path`=`asterix_nc1://data/tpcds/customer_address.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer_address using localfs ((`path`=`asterix_nc1://data/tpcds/customer_address.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q25/q25.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q25/q25.2.update.sqlpp
index 3bf9f8d..efd670e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q25/q25.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q25/q25.2.update.sqlpp
@@ -20,14 +20,14 @@
use tpcds;
-load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_returns using localfs ((`path`=`asterix_nc1://data/tpcds/store_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_returns using localfs ((`path`=`asterix_nc1://data/tpcds/store_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset catalog_sales using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset catalog_sales using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q29/q29.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q29/q29.2.update.sqlpp
index 3bf9f8d..efd670e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q29/q29.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q29/q29.2.update.sqlpp
@@ -20,14 +20,14 @@
use tpcds;
-load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_returns using localfs ((`path`=`asterix_nc1://data/tpcds/store_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_returns using localfs ((`path`=`asterix_nc1://data/tpcds/store_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset catalog_sales using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset catalog_sales using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q30/q30.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q30/q30.2.update.sqlpp
index 190a142..8d5b408 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q30/q30.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q30/q30.2.update.sqlpp
@@ -20,10 +20,10 @@
use tpcds;
-load dataset customer_address using localfs ((`path`=`asterix_nc1://data/tpcds/customer_address.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer_address using localfs ((`path`=`asterix_nc1://data/tpcds/customer_address.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset web_returns using localfs ((`path`=`asterix_nc1://data/tpcds/web_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset web_returns using localfs ((`path`=`asterix_nc1://data/tpcds/web_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q34/q34.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q34/q34.2.update.sqlpp
index 97ea2e8..98accdd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q34/q34.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q34/q34.2.update.sqlpp
@@ -20,12 +20,12 @@
use tpcds;
-load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q43/q43.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q43/q43.2.update.sqlpp
index bbf1838..654a1f1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q43/q43.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q43/q43.2.update.sqlpp
@@ -20,8 +20,8 @@
use tpcds;
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q46/q46.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q46/q46.2.update.sqlpp
index 6ab1d16..fc9d724 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q46/q46.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q46/q46.2.update.sqlpp
@@ -20,14 +20,14 @@
use tpcds;
-load dataset customer_address using localfs ((`path`=`asterix_nc1://data/tpcds/customer_address.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer_address using localfs ((`path`=`asterix_nc1://data/tpcds/customer_address.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q50/q50.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q50/q50.2.update.sqlpp
index d50d706..b870b65 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q50/q50.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q50/q50.2.update.sqlpp
@@ -20,10 +20,10 @@
use tpcds;
-load dataset store_returns using localfs ((`path`=`asterix_nc1://data/tpcds/store_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_returns using localfs ((`path`=`asterix_nc1://data/tpcds/store_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q57/q57.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q57/q57.2.update.sqlpp
index 290b1ae..25b4d12 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q57/q57.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q57/q57.2.update.sqlpp
@@ -19,11 +19,11 @@
use tpcds;
-load dataset call_center using localfs ((`path`=`asterix_nc1://data/tpcds/call_center.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset call_center using localfs ((`path`=`asterix_nc1://data/tpcds/call_center.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset catalog_sales using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset catalog_sales using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q59/q59.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q59/q59.2.update.sqlpp
index 4cadf19..80bfe7a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q59/q59.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q59/q59.2.update.sqlpp
@@ -20,8 +20,8 @@
use tpcds;
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q62/q62.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q62/q62.2.update.sqlpp
index 2aab7e4..b1a240c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q62/q62.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q62/q62.2.update.sqlpp
@@ -20,12 +20,12 @@
use tpcds;
-load dataset web_sales using localfs ((`path`=`asterix_nc1://data/tpcds/web_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset web_sales using localfs ((`path`=`asterix_nc1://data/tpcds/web_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset web_site using localfs ((`path`=`asterix_nc1://data/tpcds/web_site.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset web_site using localfs ((`path`=`asterix_nc1://data/tpcds/web_site.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset warehouse using localfs ((`path`=`asterix_nc1://data/tpcds/warehouse.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset warehouse using localfs ((`path`=`asterix_nc1://data/tpcds/warehouse.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset ship_mode using localfs ((`path`=`asterix_nc1://data/tpcds/ship_mode.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset ship_mode using localfs ((`path`=`asterix_nc1://data/tpcds/ship_mode.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q63/q63.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q63/q63.2.update.sqlpp
index c2cef59..a56835d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q63/q63.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q63/q63.2.update.sqlpp
@@ -19,10 +19,10 @@
use tpcds;
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q73/q73.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q73/q73.2.update.sqlpp
index 97ea2e8..98accdd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q73/q73.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q73/q73.2.update.sqlpp
@@ -20,12 +20,12 @@
use tpcds;
-load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q79/q79.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q79/q79.2.update.sqlpp
index 97ea2e8..98accdd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q79/q79.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q79/q79.2.update.sqlpp
@@ -20,12 +20,12 @@
use tpcds;
-load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q81/q81.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q81/q81.2.update.sqlpp
index b7e0e29..9ce02ba 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q81/q81.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q81/q81.2.update.sqlpp
@@ -20,10 +20,10 @@
use tpcds;
-load dataset customer_address using localfs ((`path`=`asterix_nc1://data/tpcds/customer_address.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer_address using localfs ((`path`=`asterix_nc1://data/tpcds/customer_address.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset catalog_returns using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset catalog_returns using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q85/q85.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q85/q85.2.update.sqlpp
index fdb2d4f..821de94 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q85/q85.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q85/q85.2.update.sqlpp
@@ -20,16 +20,16 @@
use tpcds;
-load dataset web_page using localfs ((`path`=`asterix_nc1://data/tpcds/web_page.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset web_page using localfs ((`path`=`asterix_nc1://data/tpcds/web_page.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset customer_address using localfs ((`path`=`asterix_nc1://data/tpcds/customer_address.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer_address using localfs ((`path`=`asterix_nc1://data/tpcds/customer_address.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset reason using localfs ((`path`=`asterix_nc1://data/tpcds/reason.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset reason using localfs ((`path`=`asterix_nc1://data/tpcds/reason.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset customer_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/customer_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/customer_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset web_sales using localfs ((`path`=`asterix_nc1://data/tpcds/web_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset web_sales using localfs ((`path`=`asterix_nc1://data/tpcds/web_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset web_returns using localfs ((`path`=`asterix_nc1://data/tpcds/web_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset web_returns using localfs ((`path`=`asterix_nc1://data/tpcds/web_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q88/q88.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q88/q88.2.update.sqlpp
index a673f5b..87cb458 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q88/q88.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q88/q88.2.update.sqlpp
@@ -20,10 +20,10 @@
use tpcds;
-load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset time_dim using localfs ((`path`=`asterix_nc1://data/tpcds/time_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset time_dim using localfs ((`path`=`asterix_nc1://data/tpcds/time_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q89/q89.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q89/q89.2.update.sqlpp
index c2cef59..a56835d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q89/q89.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q89/q89.2.update.sqlpp
@@ -19,10 +19,10 @@
use tpcds;
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q90/q90.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q90/q90.2.update.sqlpp
index 319491a..512eaf2 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q90/q90.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q90/q90.2.update.sqlpp
@@ -20,10 +20,10 @@
use tpcds;
-load dataset web_page using localfs ((`path`=`asterix_nc1://data/tpcds/web_page.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset web_page using localfs ((`path`=`asterix_nc1://data/tpcds/web_page.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset time_dim using localfs ((`path`=`asterix_nc1://data/tpcds/time_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset time_dim using localfs ((`path`=`asterix_nc1://data/tpcds/time_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset web_sales using localfs ((`path`=`asterix_nc1://data/tpcds/web_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset web_sales using localfs ((`path`=`asterix_nc1://data/tpcds/web_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q91/q91.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q91/q91.2.update.sqlpp
index 4599485..8d50a4a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q91/q91.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q91/q91.2.update.sqlpp
@@ -20,16 +20,16 @@
use tpcds;
-load dataset customer_address using localfs ((`path`=`asterix_nc1://data/tpcds/customer_address.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer_address using localfs ((`path`=`asterix_nc1://data/tpcds/customer_address.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset call_center using localfs ((`path`=`asterix_nc1://data/tpcds/call_center.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset call_center using localfs ((`path`=`asterix_nc1://data/tpcds/call_center.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset customer_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/customer_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/customer_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset catalog_returns using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset catalog_returns using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_returns.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q96/q96.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q96/q96.2.update.sqlpp
index a673f5b..87cb458 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q96/q96.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/q96/q96.2.update.sqlpp
@@ -20,10 +20,10 @@
use tpcds;
-load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset household_demographics using localfs ((`path`=`asterix_nc1://data/tpcds/household_demographics.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset time_dim using localfs ((`path`=`asterix_nc1://data/tpcds/time_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset time_dim using localfs ((`path`=`asterix_nc1://data/tpcds/time_dim.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
-load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`));
+load dataset store using localfs ((`path`=`asterix_nc1://data/tpcds/store.csv`),(`format`=`delimited-text`),(`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/query-ASTERIXDB-1591/query-ASTERIXDB-1591.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/query-ASTERIXDB-1591/query-ASTERIXDB-1591.2.update.sqlpp
index 9401cee..194b60e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/query-ASTERIXDB-1591/query-ASTERIXDB-1591.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/query-ASTERIXDB-1591/query-ASTERIXDB-1591.2.update.sqlpp
@@ -20,22 +20,22 @@
use tpcds;
load dataset customer_address using localfs ((`path`=`asterix_nc1://data/tpcds/customer_address.csv`),
-(`format`=`delimited-text`), (`delimiter`=`|`));
+(`format`=`delimited-text`), (`delimiter`=`|`),(`null`=``));
load dataset customer using localfs ((`path`=`asterix_nc1://data/tpcds/customer.csv`),
-(`format`=`delimited-text`), (`delimiter`=`|`));
+(`format`=`delimited-text`), (`delimiter`=`|`),(`null`=``));
load dataset store_sales using localfs ((`path`=`asterix_nc1://data/tpcds/store_sales.csv`),
-(`format`=`delimited-text`), (`delimiter`=`|`));
+(`format`=`delimited-text`), (`delimiter`=`|`),(`null`=``));
load dataset date_dim using localfs ((`path`=`asterix_nc1://data/tpcds/date_dim.csv`),
-(`format`=`delimited-text`), (`delimiter`=`|`));
+(`format`=`delimited-text`), (`delimiter`=`|`),(`null`=``));
load dataset catalog_sales using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_sales.csv`),
-(`format`=`delimited-text`), (`delimiter`=`|`));
+(`format`=`delimited-text`), (`delimiter`=`|`),(`null`=``));
load dataset catalog_returns using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_returns.csv`),
-(`format`=`delimited-text`), (`delimiter`=`|`));
+(`format`=`delimited-text`), (`delimiter`=`|`),(`null`=``));
load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),
-(`format`=`delimited-text`), (`delimiter`=`|`));
+(`format`=`delimited-text`), (`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/query-ASTERIXDB-1596/query-ASTERIXDB-1596.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/query-ASTERIXDB-1596/query-ASTERIXDB-1596.2.update.sqlpp
index 01cca8d..9c8aa41 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/query-ASTERIXDB-1596/query-ASTERIXDB-1596.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpcds/query-ASTERIXDB-1596/query-ASTERIXDB-1596.2.update.sqlpp
@@ -20,10 +20,10 @@
use tpcds;
load dataset catalog_sales using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_sales.csv`),
-(`format`=`delimited-text`), (`delimiter`=`|`));
+(`format`=`delimited-text`), (`delimiter`=`|`),(`null`=``));
load dataset catalog_returns using localfs ((`path`=`asterix_nc1://data/tpcds/catalog_returns.csv`),
-(`format`=`delimited-text`), (`delimiter`=`|`));
+(`format`=`delimited-text`), (`delimiter`=`|`),(`null`=``));
load dataset item using localfs ((`path`=`asterix_nc1://data/tpcds/item.csv`),
-(`format`=`delimited-text`), (`delimiter`=`|`));
+(`format`=`delimited-text`), (`delimiter`=`|`),(`null`=``));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/get-query/get-query.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/get-query/get-query.1.adm
new file mode 100644
index 0000000..da1b8a2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/get-query/get-query.1.adm
@@ -0,0 +1 @@
+"Metadata"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/get-query/get-query.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/get-query/get-query.2.adm
new file mode 100644
index 0000000..da1b8a2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/get-query/get-query.2.adm
@@ -0,0 +1 @@
+"Metadata"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/get-query/get-query.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/get-query/get-query.3.adm
new file mode 100644
index 0000000..da1b8a2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/get-query/get-query.3.adm
@@ -0,0 +1 @@
+"Metadata"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/post-non-query/post-non-query.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/post-non-query/post-non-query.2.adm
new file mode 100644
index 0000000..4063cf1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/post-non-query/post-non-query.2.adm
@@ -0,0 +1 @@
+"success"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/000/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/000/external_dataset.001.adm
deleted file mode 100644
index a7ce908..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/000/external_dataset.001.adm
+++ /dev/null
@@ -1,14 +0,0 @@
-{ "id": 1, "year": null, "quarter": null, "review": "good" }
-{ "id": 2, "year": null, "quarter": null, "review": "good" }
-{ "id": 3, "year": 2018, "quarter": null, "review": "good" }
-{ "id": 4, "year": 2018, "quarter": null, "review": "bad" }
-{ "id": 5, "year": 2018, "quarter": 1, "review": "good" }
-{ "id": 6, "year": 2018, "quarter": 1, "review": "bad" }
-{ "id": 7, "year": 2018, "quarter": 2, "review": "good" }
-{ "id": 8, "year": 2018, "quarter": 2, "review": "bad" }
-{ "id": 9, "year": 2019, "quarter": null, "review": "good" }
-{ "id": 10, "year": 2019, "quarter": null, "review": "bad" }
-{ "id": 11, "year": 2019, "quarter": 1, "review": "good" }
-{ "id": 12, "year": 2019, "quarter": 1, "review": "bad" }
-{ "id": 13, "year": 2019, "quarter": 2, "review": "good" }
-{ "id": 14, "year": 2019, "quarter": 2, "review": "bad" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/001/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/001/external_dataset.001.adm
deleted file mode 100644
index 93d1b57..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/001/external_dataset.001.adm
+++ /dev/null
@@ -1,6 +0,0 @@
-{ "id": 1, "year": null, "review": "good", "details": "recommend" }
-{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
-{ "id": 3, "year": null, "review": "good", "details": null }
-{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
-{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
-{ "id": 6, "year": 2018, "review": "good", "details": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/002/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/002/external_dataset.001.adm
deleted file mode 100644
index 1954b05..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/002/external_dataset.001.adm
+++ /dev/null
@@ -1,6 +0,0 @@
-{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
-{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
-{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
-{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
-{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
-{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-header/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-header/external_dataset.001.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-header/external_dataset.001.adm
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-header/external_dataset.002.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-header/external_dataset.002.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-header/external_dataset.002.adm
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-header/external_dataset.003.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-header/external_dataset.003.adm
new file mode 100644
index 0000000..dc4d9c9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-header/external_dataset.003.adm
@@ -0,0 +1,2 @@
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "str" }
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "str" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-header/external_dataset.004.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-header/external_dataset.004.adm
new file mode 100644
index 0000000..1aae8c5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-header/external_dataset.004.adm
@@ -0,0 +1,6 @@
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "str" }
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "str" }
+{ "f1": 4, "f2": 5, "f3": 6, "f4": "rts" }
+{ "f1": 4, "f2": 5, "f3": 6, "f4": "rts" }
+{ "f1": 7, "f2": 8, "f3": 9, "f4": "srt" }
+{ "f1": 7, "f2": 8, "f3": 9, "f4": "srt" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-no-header/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-no-header/external_dataset.001.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-no-header/external_dataset.001.adm
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-no-header/external_dataset.002.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-no-header/external_dataset.002.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-no-header/external_dataset.002.adm
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-no-header/external_dataset.003.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-no-header/external_dataset.003.adm
new file mode 100644
index 0000000..dc4d9c9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-no-header/external_dataset.003.adm
@@ -0,0 +1,2 @@
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "str" }
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "str" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-no-header/external_dataset.004.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-no-header/external_dataset.004.adm
new file mode 100644
index 0000000..1aae8c5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-no-header/external_dataset.004.adm
@@ -0,0 +1,6 @@
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "str" }
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "str" }
+{ "f1": 4, "f2": 5, "f3": 6, "f4": "rts" }
+{ "f1": 4, "f2": 5, "f3": 6, "f4": "rts" }
+{ "f1": 7, "f2": 8, "f3": 9, "f4": "srt" }
+{ "f1": 7, "f2": 8, "f3": 9, "f4": "srt" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.001.adm
new file mode 100644
index 0000000..245b406
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.001.adm
@@ -0,0 +1,2 @@
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "str" }
+{ "f1": 7, "f2": 8, "f3": 9, "f4": "srt" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.002.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.002.adm
new file mode 100644
index 0000000..7d3c940
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.002.adm
@@ -0,0 +1 @@
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "str" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.003.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.003.adm
new file mode 100644
index 0000000..7d3c940
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.003.adm
@@ -0,0 +1 @@
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "str" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.004.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.004.adm
new file mode 100644
index 0000000..334381b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.004.adm
@@ -0,0 +1,3 @@
+{ "f1": 1234, "f2": 12, "f3": 15.1, "f4": 16.1, "f5": "fine", "f6": "fine", "f7": true, "f8": false }
+{ "f1": 1234, "f2": 12, "f3": 15.1, "f4": 16.1, "f5": "fine", "f6": "fine", "f7": true, "f8": false }
+{ "f1": 1234, "f2": null, "f3": 15.1, "f4": null, "f5": "\\N", "f6": null, "f7": true, "f8": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.005.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.005.adm
new file mode 100644
index 0000000..334381b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.005.adm
@@ -0,0 +1,3 @@
+{ "f1": 1234, "f2": 12, "f3": 15.1, "f4": 16.1, "f5": "fine", "f6": "fine", "f7": true, "f8": false }
+{ "f1": 1234, "f2": 12, "f3": 15.1, "f4": 16.1, "f5": "fine", "f6": "fine", "f7": true, "f8": false }
+{ "f1": 1234, "f2": null, "f3": 15.1, "f4": null, "f5": "\\N", "f6": null, "f7": true, "f8": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.006.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.006.adm
new file mode 100644
index 0000000..c3ce0a1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.006.adm
@@ -0,0 +1 @@
+{ "f1": 1, "f2": "good", "f3": "recommend" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.007.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.007.adm
new file mode 100644
index 0000000..c56f0c5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv-warnings/external_dataset.007.adm
@@ -0,0 +1,2 @@
+{ "f1": 1, "f2": "good", "f3": "recommend" }
+{ "f1": 3, "f2": "good", "f3": "recommend" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv/csv/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv/csv/external_dataset.001.adm
new file mode 100644
index 0000000..4dbd63a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv/csv/external_dataset.001.adm
@@ -0,0 +1,30 @@
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv/gz/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv/gz/external_dataset.001.adm
new file mode 100644
index 0000000..4dbd63a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv/gz/external_dataset.001.adm
@@ -0,0 +1,30 @@
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv/mixed/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv/mixed/external_dataset.001.adm
new file mode 100644
index 0000000..7aec747
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/csv/mixed/external_dataset.001.adm
@@ -0,0 +1,60 @@
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 1, "year": null, "review": "good", "details": "recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 2, "year": null, "review": "bad", "details": "not recommend" }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 3, "year": null, "review": "good", "details": null }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 4, "year": 2018, "review": "good", "details": "recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 5, "year": 2018, "review": "", "details": "not recommend" }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
+{ "id": 6, "year": 2018, "review": "good", "details": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/empty-string-definition/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/empty-string-definition/external_dataset.001.adm
new file mode 100644
index 0000000..187a8cb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/empty-string-definition/external_dataset.001.adm
@@ -0,0 +1 @@
+{ "count": 100 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json-warnings/json-warnings.003.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json-warnings/json-warnings.003.adm
new file mode 100644
index 0000000..5bae5d1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json-warnings/json-warnings.003.adm
@@ -0,0 +1 @@
+{ "double_value": 150.11 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.001.adm
new file mode 100644
index 0000000..187a8cb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.001.adm
@@ -0,0 +1 @@
+{ "count": 100 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.002.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.002.adm
new file mode 100644
index 0000000..187a8cb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.002.adm
@@ -0,0 +1 @@
+{ "count": 100 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.003.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.003.adm
new file mode 100644
index 0000000..5db606c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.003.adm
@@ -0,0 +1 @@
+{ "count": 25 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.004.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.004.adm
new file mode 100644
index 0000000..7660e7e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.004.adm
@@ -0,0 +1,25 @@
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.005.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.005.adm
new file mode 100644
index 0000000..5db606c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.005.adm
@@ -0,0 +1 @@
+{ "count": 25 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.006.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.006.adm
new file mode 100644
index 0000000..7643986
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/gz/external_dataset.006.adm
@@ -0,0 +1,25 @@
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.001.adm
new file mode 100644
index 0000000..187a8cb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.001.adm
@@ -0,0 +1 @@
+{ "count": 100 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.002.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.002.adm
new file mode 100644
index 0000000..187a8cb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.002.adm
@@ -0,0 +1 @@
+{ "count": 100 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.003.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.003.adm
new file mode 100644
index 0000000..5db606c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.003.adm
@@ -0,0 +1 @@
+{ "count": 25 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.004.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.004.adm
new file mode 100644
index 0000000..7660e7e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.004.adm
@@ -0,0 +1,25 @@
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.005.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.005.adm
new file mode 100644
index 0000000..5db606c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.005.adm
@@ -0,0 +1 @@
+{ "count": 25 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.006.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.006.adm
new file mode 100644
index 0000000..7643986
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/json/external_dataset.006.adm
@@ -0,0 +1,25 @@
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.001.adm
new file mode 100644
index 0000000..8e8fe53
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.001.adm
@@ -0,0 +1 @@
+{ "count": 200 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.002.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.002.adm
new file mode 100644
index 0000000..8e8fe53
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.002.adm
@@ -0,0 +1 @@
+{ "count": 200 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.003.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.003.adm
new file mode 100644
index 0000000..6540472
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.003.adm
@@ -0,0 +1 @@
+{ "count": 50 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.004.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.004.adm
new file mode 100644
index 0000000..9a52dea
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.004.adm
@@ -0,0 +1,50 @@
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.005.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.005.adm
new file mode 100644
index 0000000..6540472
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.005.adm
@@ -0,0 +1 @@
+{ "count": 50 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.006.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.006.adm
new file mode 100644
index 0000000..722dfe1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/json/mixed/external_dataset.006.adm
@@ -0,0 +1,50 @@
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 1, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 2, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/jsonl/external_dataset.002.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/jsonl/external_dataset.002.adm
new file mode 100644
index 0000000..bf2b0e1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/jsonl/external_dataset.002.adm
@@ -0,0 +1,50 @@
+{ "id": 1, "year": null, "quarter": null, "review": "good" }
+{ "id": 2, "year": null, "quarter": null, "review": "good" }
+{ "id": 3, "year": 2018, "quarter": null, "review": "good" }
+{ "id": 4, "year": 2018, "quarter": null, "review": "bad" }
+{ "id": 5, "year": 2018, "quarter": 1, "review": "good" }
+{ "id": 6, "year": 2018, "quarter": 1, "review": "bad" }
+{ "id": 7, "year": 2018, "quarter": 2, "review": "good" }
+{ "id": 8, "year": 2018, "quarter": 2, "review": "bad" }
+{ "id": 9, "year": 2019, "quarter": null, "review": "good" }
+{ "id": 10, "year": 2019, "quarter": null, "review": "bad" }
+{ "id": 11, "year": 2019, "quarter": 1, "review": "good" }
+{ "id": 12, "year": 2019, "quarter": 1, "review": "bad" }
+{ "id": 13, "year": 2019, "quarter": 2, "review": "good" }
+{ "id": 14, "year": 2019, "quarter": 2, "review": "bad" }
+{ "id": 15, "year": 2019, "quarter": null, "review": "good" }
+{ "id": 16, "year": 2019, "quarter": null, "review": "bad" }
+{ "id": 17, "year": 2019, "quarter": 1, "review": "good" }
+{ "id": 18, "year": 2019, "quarter": 1, "review": "bad" }
+{ "id": 19, "year": 2019, "quarter": 2, "review": "good" }
+{ "id": 20, "year": 2019, "quarter": 2, "review": "bad" }
+{ "id": 21, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 22, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ] }
+{ "id": 23, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 24, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3 ] }
+{ "id": 25, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3 ] }
+{ "id": 26, "year": null, "quarter": null, "review": "good", "array": [ 1, 2, 3 ], "nested": { "id": 1 } }
+{ "id": 27, "year": null, "quarter": null, "review": "good", "array": [ 1, [ 1, 2 ], [ 1 ] ], "nested": { "id": 1 }, "nested2": [ { "id": 1 } ] }
+{ "id": 28, "year": 2018, "quarter": null, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ { "nested": { "array": [ 1, 2 ] } } ] } } ] }
+{ "id": 29, "year": 2018, "quarter": null, "review": "bad", "array": [ 1, 2, 3, { "nested1": { "id": 1, "nested2": { "id": 2, "nested3": [ { "nested4": null } ] } } } ] }
+{ "id": 30, "year": 2018, "quarter": 1, "review": "good", "array": [ 1, 2, 3, { "nested": { "array": [ 1, 2 ] } } ] }
+{ "id": 31, "year": null, "quarter": null, "review": "good" }
+{ "id": 32, "year": null, "quarter": null, "review": "good" }
+{ "id": 33, "year": 2018, "quarter": null, "review": "good" }
+{ "id": 34, "year": 2018, "quarter": null, "review": "bad" }
+{ "id": 35, "year": 2018, "quarter": 1, "review": "good" }
+{ "id": 36, "year": 2018, "quarter": 1, "review": "bad" }
+{ "id": 37, "year": 2018, "quarter": 2, "review": "good" }
+{ "id": 38, "year": 2018, "quarter": 2, "review": "bad" }
+{ "id": 39, "year": 2019, "quarter": null, "review": "good" }
+{ "id": 40, "year": 2019, "quarter": null, "review": "bad" }
+{ "id": 41, "year": 2019, "quarter": 1, "review": "good" }
+{ "id": 42, "year": 2019, "quarter": 1, "review": "bad" }
+{ "id": 43, "year": 2019, "quarter": 2, "review": "good" }
+{ "id": 44, "year": 2019, "quarter": 2, "review": "bad" }
+{ "id": 45, "year": 2019, "quarter": null, "review": "good" }
+{ "id": 46, "year": 2019, "quarter": null, "review": "bad" }
+{ "id": 47, "year": 2019, "quarter": 1, "review": "good" }
+{ "id": 48, "year": 2019, "quarter": 1, "review": "bad" }
+{ "id": 49, "year": 2019, "quarter": 2, "review": "good" }
+{ "id": 50, "year": 2019, "quarter": 2, "review": "bad" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-header/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-header/external_dataset.001.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-header/external_dataset.001.adm
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-header/external_dataset.002.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-header/external_dataset.002.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-header/external_dataset.002.adm
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-header/external_dataset.003.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-header/external_dataset.003.adm
new file mode 100644
index 0000000..eb83800
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-header/external_dataset.003.adm
@@ -0,0 +1,2 @@
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "\"str\"" }
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "\"str\"" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-header/external_dataset.004.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-header/external_dataset.004.adm
new file mode 100644
index 0000000..8d60432
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-header/external_dataset.004.adm
@@ -0,0 +1,6 @@
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "\"str\"" }
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "\"str\"" }
+{ "f1": 4, "f2": 5, "f3": 6, "f4": "\"rts\"" }
+{ "f1": 4, "f2": 5, "f3": 6, "f4": "\"rts\"" }
+{ "f1": 7, "f2": 8, "f3": 9, "f4": "\"srt\"" }
+{ "f1": 7, "f2": 8, "f3": 9, "f4": "\"srt\"" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-no-header/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-no-header/external_dataset.001.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-no-header/external_dataset.001.adm
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-no-header/external_dataset.002.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-no-header/external_dataset.002.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-no-header/external_dataset.002.adm
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-no-header/external_dataset.003.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-no-header/external_dataset.003.adm
new file mode 100644
index 0000000..eb83800
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-no-header/external_dataset.003.adm
@@ -0,0 +1,2 @@
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "\"str\"" }
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "\"str\"" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-no-header/external_dataset.004.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-no-header/external_dataset.004.adm
new file mode 100644
index 0000000..8d60432
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-no-header/external_dataset.004.adm
@@ -0,0 +1,6 @@
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "\"str\"" }
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "\"str\"" }
+{ "f1": 4, "f2": 5, "f3": 6, "f4": "\"rts\"" }
+{ "f1": 4, "f2": 5, "f3": 6, "f4": "\"rts\"" }
+{ "f1": 7, "f2": 8, "f3": 9, "f4": "\"srt\"" }
+{ "f1": 7, "f2": 8, "f3": 9, "f4": "\"srt\"" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-warnings/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-warnings/external_dataset.001.adm
new file mode 100644
index 0000000..ac2354d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv-warnings/external_dataset.001.adm
@@ -0,0 +1,2 @@
+{ "f1": 1, "f2": 2, "f3": 3, "f4": "\"str\"" }
+{ "f1": 7, "f2": 8, "f3": 9, "f4": "\"srt\"" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv/gz/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv/gz/external_dataset.001.adm
new file mode 100644
index 0000000..e04a6b5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv/gz/external_dataset.001.adm
@@ -0,0 +1,30 @@
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv/mixed/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv/mixed/external_dataset.001.adm
new file mode 100644
index 0000000..4823286
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv/mixed/external_dataset.001.adm
@@ -0,0 +1,60 @@
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv/tsv/external_dataset.001.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv/tsv/external_dataset.001.adm
new file mode 100644
index 0000000..e04a6b5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-dataset/aws/s3/tsv/tsv/external_dataset.001.adm
@@ -0,0 +1,30 @@
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 1, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 2, "year": null, "review": "\"bad\"", "details": "\"not recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 3, "year": null, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 4, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 5, "year": 2018, "review": "", "details": "\"not recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
+{ "id": 6, "year": 2018, "review": "\"good\"", "details": "\"recommend\"" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-case-01/gby-case-01.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-case-01/gby-case-01.3.adm
new file mode 100644
index 0000000..11331e8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-case-01/gby-case-01.3.adm
@@ -0,0 +1,2 @@
+{ "x": 1, "res": 6.0 }
+{ "x": 2, "res": 0 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-case-01/gby-case-01.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-case-01/gby-case-01.4.adm
new file mode 100644
index 0000000..11331e8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-case-01/gby-case-01.4.adm
@@ -0,0 +1,2 @@
+{ "x": 1, "res": 6.0 }
+{ "x": 2, "res": 0 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-nested-01/gby-nested-01.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-nested-01/gby-nested-01.3.adm
new file mode 100644
index 0000000..caba454
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-nested-01/gby-nested-01.3.adm
@@ -0,0 +1,2 @@
+{ "p_id": 1, "ct": [ { "ct_sum": 92, "ct_avg": 46.0 }, { "ct_id": "LAS", "ct_sum": 16, "ct_avg": 8.0 }, { "ct_id": "RNO", "ct_sum": 14, "ct_avg": 7.0 }, { "ct_id": "SFO", "ct_sum": 10, "ct_avg": 5.0 }, { "ct_id": "SJC", "ct_sum": 12, "ct_avg": 6.0 } ], "st": [ { "st_id": "CA", "st_sum": 64, "st_avg": 16.0 }, { "st_id": "NV", "st_sum": 80, "st_avg": 20.0 } ], "p_name": "PRODUCT_1" }
+{ "p_id": 2, "ct": [ ], "st": [ ], "p_name": "PRODUCT_2" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-02-push-select/loj-02-push-select.03.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-02-push-select/loj-02-push-select.03.adm
new file mode 100644
index 0000000..bd1fb36
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-02-push-select/loj-02-push-select.03.adm
@@ -0,0 +1,2 @@
+{ "t1_left": { "id": 3, "x": 3, "a": 13 } }
+{ "t1_left": { "id": 4, "x": 4, "a": 14 } }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-02-push-select/loj-02-push-select.04.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-02-push-select/loj-02-push-select.04.adm
new file mode 100644
index 0000000..bd1fb36
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-02-push-select/loj-02-push-select.04.adm
@@ -0,0 +1,2 @@
+{ "t1_left": { "id": 3, "x": 3, "a": 13 } }
+{ "t1_left": { "id": 4, "x": 4, "a": 14 } }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-02-push-select/loj-02-push-select.05.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-02-push-select/loj-02-push-select.05.adm
new file mode 100644
index 0000000..bd1fb36
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-02-push-select/loj-02-push-select.05.adm
@@ -0,0 +1,2 @@
+{ "t1_left": { "id": 3, "x": 3, "a": 13 } }
+{ "t1_left": { "id": 4, "x": 4, "a": 14 } }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-02-push-select/loj-02-push-select.06.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-02-push-select/loj-02-push-select.06.adm
new file mode 100644
index 0000000..e9d3c37
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-02-push-select/loj-02-push-select.06.adm
@@ -0,0 +1,2 @@
+{ "t1_left": { "id": 1, "x": 1, "a": 11 }, "t2_right": { "id": 1, "y": 1, "b": 111 } }
+{ "t1_left": { "id": 2, "x": 2, "a": 12 }, "t2_right": { "id": 2, "y": 2, "b": 112 } }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/load/csv_06/csv_06.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/load/csv_06/csv_06.1.adm
index e69de29..1cbcc6c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/load/csv_06/csv_06.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/load/csv_06/csv_06.1.adm
@@ -0,0 +1,3 @@
+{ "id": 2, "float": 0.2, "stringa": "test2a", "stringb": "test2b" }
+{ "id": 3, "float": 0.3, "stringa": "test,3a,3a,3a", "stringb": "\"\"test\"\"" }
+{ "id": 4, "float": 0.4, "stringa": "test\"4a\",4a", "stringb": " test with\nline break " }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/load/csv_07/csv_07.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/load/csv_07/csv_07.1.adm
index e69de29..1cbcc6c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/load/csv_07/csv_07.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/load/csv_07/csv_07.1.adm
@@ -0,0 +1,3 @@
+{ "id": 2, "float": 0.2, "stringa": "test2a", "stringb": "test2b" }
+{ "id": 3, "float": 0.3, "stringa": "test,3a,3a,3a", "stringb": "\"\"test\"\"" }
+{ "id": 4, "float": 0.4, "stringa": "test\"4a\",4a", "stringb": " test with\nline break " }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/metrics/external-dataset/external-dataset.2.regexadm b/asterixdb/asterix-app/src/test/resources/runtimets/results/metrics/external-dataset/external-dataset.2.regexadm
new file mode 100644
index 0000000..ae84a71
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/metrics/external-dataset/external-dataset.2.regexadm
@@ -0,0 +1 @@
+.*"processedObjects":15.*
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
index 3fcce1c..924fd37 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
@@ -1679,19 +1679,16 @@
<test-case FilePath="load">
<compilation-unit name="csv_05"><!-- Someone should check and verify -->
<output-dir compare="Text">csv_05</output-dir>
- <expected-error>At record: 1</expected-error>
</compilation-unit>
</test-case>
<test-case FilePath="load">
<compilation-unit name="csv_06"><!-- Someone should check and verify -->
<output-dir compare="Text">csv_06</output-dir>
- <expected-error>At record: 1</expected-error>
</compilation-unit>
</test-case>
<test-case FilePath="load">
<compilation-unit name="csv_07"><!-- Someone should check and verify -->
<output-dir compare="Text">csv_07</output-dir>
- <expected-error>At record: 1</expected-error>
</compilation-unit>
</test-case>
<test-case FilePath="load">
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_external_dataset.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_external_dataset.xml
index 2456f13..551d777 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_external_dataset.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_external_dataset.xml
@@ -20,24 +20,51 @@
<test-suite xmlns="urn:xml.testframework.asterix.apache.org" ResultOffsetPath="results" QueryOffsetPath="queries_sqlpp" QueryFileExtension=".sqlpp">
<test-group name="external-dataset">
<test-case FilePath="external-dataset">
- <compilation-unit name="aws/s3/000">
- <output-dir compare="Text">aws/s3/000</output-dir>
+ <compilation-unit name="aws/s3/json/json">
+ <output-dir compare="Text">aws/s3/json/json</output-dir>
</compilation-unit>
</test-case>
<test-case FilePath="external-dataset">
- <compilation-unit name="aws/s3/001">
- <output-dir compare="Text">aws/s3/001</output-dir>
+ <compilation-unit name="aws/s3/json/gz">
+ <output-dir compare="Text">aws/s3/json/gz</output-dir>
</compilation-unit>
</test-case>
<test-case FilePath="external-dataset">
- <compilation-unit name="aws/s3/002">
- <output-dir compare="Text">aws/s3/002</output-dir>
+ <compilation-unit name="aws/s3/json/mixed">
+ <output-dir compare="Text">aws/s3/json/mixed</output-dir>
</compilation-unit>
</test-case>
<test-case FilePath="external-dataset">
- <compilation-unit name="aws/s3/negative">
- <output-dir compare="Text">aws/s3/negative</output-dir>
- <expected-error>Parameter(s) format must be specified</expected-error>
+ <compilation-unit name="aws/s3/csv/csv">
+ <output-dir compare="Text">aws/s3/csv/csv</output-dir>
+ </compilation-unit>
+ </test-case><test-case FilePath="external-dataset">
+ <compilation-unit name="aws/s3/csv/gz">
+ <output-dir compare="Text">aws/s3/csv/gz</output-dir>
+ </compilation-unit>
+ </test-case><test-case FilePath="external-dataset">
+ <compilation-unit name="aws/s3/csv/mixed">
+ <output-dir compare="Text">aws/s3/csv/mixed</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="external-dataset">
+ <compilation-unit name="aws/s3/tsv/tsv">
+ <output-dir compare="Text">aws/s3/tsv/tsv</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="external-dataset">
+ <compilation-unit name="aws/s3/tsv/gz">
+ <output-dir compare="Text">aws/s3/tsv/gz</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="external-dataset">
+ <compilation-unit name="aws/s3/tsv/mixed">
+ <output-dir compare="Text">aws/s3/tsv/mixed</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="external-dataset">
+ <compilation-unit name="aws/s3/empty-string-definition">
+ <output-dir compare="Text">aws/s3/empty-string-definition</output-dir>
</compilation-unit>
</test-case>
</test-group>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_external_dataset_one_partition.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_external_dataset_one_partition.xml
new file mode 100644
index 0000000..6704d78
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_external_dataset_one_partition.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ! 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.
+ !-->
+<test-suite xmlns="urn:xml.testframework.asterix.apache.org" ResultOffsetPath="results" QueryOffsetPath="queries_sqlpp" QueryFileExtension=".sqlpp">
+ <test-group name="external-dataset">
+ <test-case FilePath="external-dataset" check-warnings="true">
+ <compilation-unit name="aws/s3/csv-header">
+ <output-dir compare="Text">aws/s3/csv-header</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="external-dataset" check-warnings="true">
+ <compilation-unit name="aws/s3/csv-no-header">
+ <output-dir compare="Text">aws/s3/csv-no-header</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="external-dataset" check-warnings="true">
+ <compilation-unit name="aws/s3/tsv-header">
+ <output-dir compare="Text">aws/s3/tsv-header</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="external-dataset" check-warnings="true">
+ <compilation-unit name="aws/s3/tsv-no-header">
+ <output-dir compare="Text">aws/s3/tsv-no-header</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="external-dataset" check-warnings="true">
+ <compilation-unit name="aws/s3/csv-warnings">
+ <output-dir compare="Text">aws/s3/csv-warnings</output-dir>
+ <expected-warn>Parsing error at data_dir/no_h_missing_fields.csv line 2 field 3: some fields are missing</expected-warn>
+ <expected-warn>Parsing error at data_dir/no_h_no_closing_q.csv line 2 field 0: malformed input record ended abruptly</expected-warn>
+ <expected-warn>Parsing error at line 2 field 0: malformed input record ended abruptly</expected-warn>
+
+ <expected-warn>Parsing error at line 5 field 3: invalid value</expected-warn>
+ <expected-warn>Parsing error at line 2 field 1: invalid value</expected-warn>
+ <expected-warn>Parsing error at line 11 field 1: invalid value</expected-warn>
+ <expected-warn>Parsing error at line 3 field 1: invalid value</expected-warn>
+ <expected-warn>Parsing error at line 4 field 1: invalid value</expected-warn>
+ <expected-warn>Parsing error at line 7 field 7: invalid value</expected-warn>
+ <expected-warn>Parsing error at line 13 field 7: invalid value</expected-warn>
+ <expected-warn>Parsing error at line 12 field 3: invalid value</expected-warn>
+ <expected-warn>Parsing error at line 9 field 6: a quote should be in the beginning</expected-warn>
+
+ <expected-warn>Parsing error at data_dir/h_invalid_values.csv line 5 field 3: invalid value</expected-warn>
+ <expected-warn>Parsing error at data_dir/h_invalid_values.csv line 2 field 1: invalid value</expected-warn>
+ <expected-warn>Parsing error at data_dir/h_invalid_values.csv line 11 field 1: invalid value</expected-warn>
+ <expected-warn>Parsing error at data_dir/h_invalid_values.csv line 3 field 1: invalid value</expected-warn>
+ <expected-warn>Parsing error at data_dir/h_invalid_values.csv line 4 field 1: invalid value</expected-warn>
+ <expected-warn>Parsing error at data_dir/h_invalid_values.csv line 7 field 7: invalid value</expected-warn>
+ <expected-warn>Parsing error at data_dir/h_invalid_values.csv line 13 field 7: invalid value</expected-warn>
+ <expected-warn>Parsing error at data_dir/h_invalid_values.csv line 12 field 3: invalid value</expected-warn>
+ <expected-warn>Parsing error at data_dir/h_invalid_values.csv line 9 field 6: a quote should be in the beginning</expected-warn>
+
+ <expected-warn>Parsing error at data_dir/error1_line_num.csv line 3 field 2: a quote enclosing a field needs to be followed by the delimiter</expected-warn>
+ <expected-warn>Parsing error at data_dir/error2_line_num.csv line 4 field 2: a quote enclosing a field needs to be followed by the delimiter</expected-warn>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="external-dataset" check-warnings="true">
+ <compilation-unit name="aws/s3/tsv-warnings">
+ <output-dir compare="Text">aws/s3/tsv-warnings</output-dir>
+ <expected-warn>Parsing error at data_dir/no_h_missing_fields.tsv line 2 field 3: some fields are missing</expected-warn>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="external-dataset" check-warnings="true">
+ <compilation-unit name="aws/s3/json-warnings">
+ <output-dir compare="Text">aws/s3/json-warnings</output-dir>
+ <expected-warn>Parsing error at data_dir/1.json line 3 field 0: malformed input record ended abruptly</expected-warn>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="external-dataset" check-warnings="true">
+ <compilation-unit name="aws/s3/jsonl">
+ <output-dir compare="Text">aws/s3/jsonl</output-dir>
+ </compilation-unit>
+ </test-case>
+ </test-group>
+</test-suite>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index bcaa397..ca10f51 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -31,15 +31,15 @@
<test-case FilePath="api">
<compilation-unit name="readonly-request">
<output-dir compare="Text">readonly-request</output-dir>
- <expected-error>ASX0044: CREATE_DATAVERSE statement is prohibited by this request</expected-error>
- <expected-error>ASX0044: DATAVERSE_DROP statement is prohibited by this request</expected-error>
- <expected-error>ASX0044: DATASET_DECL statement is prohibited by this request</expected-error>
- <expected-error>ASX0044: DATASET_DROP statement is prohibited by this request</expected-error>
- <expected-error>ASX0044: CREATE_INDEX statement is prohibited by this request</expected-error>
- <expected-error>ASX0044: INDEX_DROP statement is prohibited by this request</expected-error>
- <expected-error>ASX0044: INSERT statement is prohibited by this request</expected-error>
- <expected-error>ASX0044: UPSERT statement is prohibited by this request</expected-error>
- <expected-error>ASX0044: DELETE statement is prohibited by this request</expected-error>
+ <expected-error>ASX0044: CREATE_DATAVERSE statement is not supported in read-only mode</expected-error>
+ <expected-error>ASX0044: DATAVERSE_DROP statement is not supported in read-only mode</expected-error>
+ <expected-error>ASX0044: DATASET_DECL statement is not supported in read-only mode</expected-error>
+ <expected-error>ASX0044: DATASET_DROP statement is not supported in read-only mode</expected-error>
+ <expected-error>ASX0044: CREATE_INDEX statement is not supported in read-only mode</expected-error>
+ <expected-error>ASX0044: INDEX_DROP statement is not supported in read-only mode</expected-error>
+ <expected-error>ASX0044: INSERT statement is not supported in read-only mode</expected-error>
+ <expected-error>ASX0044: UPSERT statement is not supported in read-only mode</expected-error>
+ <expected-error>ASX0044: DELETE statement is not supported in read-only mode</expected-error>
</compilation-unit>
</test-case>
<test-case FilePath="api">
@@ -108,6 +108,25 @@
<output-dir compare="AST">format-param-in-accept-05</output-dir>
</compilation-unit>
</test-case>
+ <test-case FilePath="api">
+ <compilation-unit name="get-non-query">
+ <output-dir compare="Text">get-non-query</output-dir>
+ <expected-error>CREATE_DATAVERSE statement is not supported in read-only mode</expected-error>
+ <expected-error>TYPE_DECL statement is not supported in read-only mode</expected-error>
+ <expected-error>CREATE_FUNCTION statement is not supported in read-only mode</expected-error>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="api">
+ <compilation-unit name="get-query">
+ <output-dir compare="Text">get-query</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="api">
+ <compilation-unit name="post-non-query">
+ <output-dir compare="Text">post-non-query</output-dir>
+ <expected-error>TYPE_DECL statement is not supported in read-only mode</expected-error>
+ </compilation-unit>
+ </test-case>
</test-group>
<test-group name="flwor">
<test-case FilePath="flwor">
@@ -5384,6 +5403,16 @@
</compilation-unit>
</test-case>
<test-case FilePath="group-by">
+ <compilation-unit name="gby-case-01">
+ <output-dir compare="Text">gby-case-01</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="group-by">
+ <compilation-unit name="gby-nested-01">
+ <output-dir compare="Text">gby-nested-01</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="group-by">
<compilation-unit name="gby-record">
<output-dir compare="Text">gby-record</output-dir>
</compilation-unit>
@@ -11962,22 +11991,16 @@
<test-case FilePath="load">
<compilation-unit name="csv_05">
<output-dir compare="Text">csv_05</output-dir>
- <expected-error>At record: 1, field#: 4 - a quote enclosing a field needs to be placed in the beginning of that field</expected-error>
- <source-location>false</source-location>
</compilation-unit>
</test-case>
<test-case FilePath="load">
<compilation-unit name="csv_06">
<output-dir compare="Text">csv_06</output-dir>
- <expected-error>At record: 1, field#: 3 - a quote enclosing a field needs to be placed in the beginning of that field</expected-error>
- <source-location>false</source-location>
</compilation-unit>
</test-case>
<test-case FilePath="load">
<compilation-unit name="csv_07">
<output-dir compare="Text">csv_07</output-dir>
- <expected-error>At record: 1, field#: 3 - A quote enclosing a field needs to be followed by the delimiter</expected-error>
- <source-location>false</source-location>
</compilation-unit>
</test-case>
<test-case FilePath="load">
@@ -12497,6 +12520,11 @@
</compilation-unit>
</test-case>
<test-case FilePath="leftouterjoin">
+ <compilation-unit name="loj-02-push-select">
+ <output-dir compare="Text">loj-02-push-select</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="leftouterjoin">
<compilation-unit name="query_issue658">
<output-dir compare="Text">query_issue658</output-dir>
</compilation-unit>
@@ -13944,7 +13972,7 @@
<expected-warn>Type mismatch: function string-concat expects its 2nd input parameter to be of type string, but the actual input type is bigint (in line 30, at column 1)</expected-warn>
<expected-warn>Type mismatch: function string-concat expects its 2nd input parameter to be of type string, but the actual input type is tinyint (in line 31, at column 7)</expected-warn>
- <expected-warn>Type mismatch: function substring expects its 1st input parameter to be of type string, but the actual input type is bigint (in line 32, at column 1)</expected-warn>
+ <expected-warn>Type mismatch: function substring expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string (in line 32, at column 1)</expected-warn>
<expected-warn>Type mismatch: function codepoint-to-string expects its 1st input parameter to be of type array, but the actual input type is string (in line 33, at column 1)</expected-warn>
<expected-warn>Unsupported type: codepoint-to-string cannot process input type string (in line 34, at column 1)</expected-warn>
<expected-warn>Unsupported type: codepoint-to-string cannot process input type double (in line 35, at column 1)</expected-warn>
@@ -14046,12 +14074,13 @@
<expected-warn>Type mismatch: function round-half-to-even expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
<expected-warn>Type mismatch: function trunc expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
- <expected-warn>Type mismatch: function round expects its 1st input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
- <expected-warn>Type mismatch: function round-half-to-even expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
- <expected-warn>Type mismatch: function trunc expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
- <expected-warn>Type mismatch: function round expects its 1st input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
- <expected-warn>Type mismatch: function round-half-to-even expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
- <expected-warn>Type mismatch: function trunc expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+ <expected-warn>Type mismatch: function round expects its 2nd input parameter to be of type tinyint, smallint, integer or bigint, but the actual input type is string (in line 33, at column 24)</expected-warn>
+ <expected-warn>Type mismatch: function round expects its 2nd input parameter to be of type tinyint, smallint, integer or bigint, but the actual input type is string (in line 33, at column 47)</expected-warn>
+ <expected-warn>Type mismatch: function trunc expects its 1st input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string (in line 34, at column 24)</expected-warn>
+ <expected-warn>Type mismatch: function trunc expects its 1st input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string (in line 34, at column 47)</expected-warn>
+
+ <expected-warn>Type mismatch: function round-half-to-even expects its 1st input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string (in line 36, at column 40)</expected-warn>
+ <expected-warn>Type mismatch: function round-half-to-even expects its 1st input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string (in line 36, at column 79)</expected-warn>
<source-location>false</source-location>
</compilation-unit>
</test-case>
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index 4e10498..e064e8c 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -247,9 +247,9 @@
public static final int LIBRARY_JAVA_FUNCTION_HELPER_OBJ_TYPE_NOT_SUPPORTED = 3046;
public static final int LIBRARY_EXTERNAL_FUNCTION_UNSUPPORTED_NAME = 3047;
public static final int OPERATORS_FEED_META_OPERATOR_DESCRIPTOR_INVALID_RUNTIME = 3048;
- public static final int PARSER_FACTORY_DELIMITED_DATA_PARSER_FACTORY_NOT_VALID_DELIMITER = 3049;
- public static final int PARSER_INVALID_CHAR_LENGTH = 3050;
- public static final int PARSER_FACTORY_DELIMITED_DATA_PARSER_FACTORY_QUOTE_DELIMITER_MISMATCH = 3051;
+ public static final int INVALID_DELIMITER = 3049;
+ public static final int INVALID_CHAR_LENGTH = 3050;
+ public static final int QUOTE_DELIMITER_MISMATCH = 3051;
public static final int INDEXING_EXTERNAL_FILE_INDEX_ACCESSOR_UNABLE_TO_FIND_FILE_INDEX = 3052;
public static final int PARSER_ADM_DATA_PARSER_FIELD_NOT_NULL = 3053;
public static final int PARSER_ADM_DATA_PARSER_TYPE_MISMATCH = 3054;
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IDataSourceAdapter.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IDataSourceAdapter.java
index 18f59f2..8fc70b8 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IDataSourceAdapter.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IDataSourceAdapter.java
@@ -49,4 +49,11 @@
* @throws Exception
*/
public void start(int partition, IFrameWriter writer) throws HyracksDataException, InterruptedException;
+
+ /**
+ * @return The number of processed tuples by this adapter
+ */
+ default long getProcessedTuples() {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
index 48d849f..35509f7 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -78,7 +78,7 @@
41 = Request %1$s has been cancelled
42 = %1$s: \"%2$s\" is not a TPC-DS table name
43 = Value out of range, function %1$s expects its %2$s input parameter value to be between %3$s and %4$s, received %5$s
-44 = %1$s statement is prohibited by this request
+44 = %1$s statement is not supported in read-only mode
45 = Invalid value: function %1$s expects its %2$s input parameter to be an integer value, got %3$s
46 = Invalid pattern \"%1$s\" for LIKE
47 = Invalid value for parameter \"%1$s\": %2$s
diff --git a/asterixdb/asterix-dashboard/pom.xml b/asterixdb/asterix-dashboard/pom.xml
index ff4234f..75fb8d2 100644
--- a/asterixdb/asterix-dashboard/pom.xml
+++ b/asterixdb/asterix-dashboard/pom.xml
@@ -55,120 +55,131 @@
</dependency>
</dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>com.github.eirslett</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.6</version>
- <configuration>
- <nodeVersion>v10.3.0</nodeVersion>
- <npmVersion>6.1.0</npmVersion>
- <workingDirectory>target/dashboard</workingDirectory>
- <installDirectory>target/dashboard</installDirectory>
- </configuration>
- <executions>
- <execution>
- <id>install node and yarn</id>
- <goals>
- <goal>install-node-and-npm</goal>
- </goals>
- <phase>generate-resources</phase>
- </execution>
- <execution>
- <id>npm install</id>
- <phase>process-resources</phase>
- <goals>
- <goal>npm</goal>
- </goals>
+ <profiles>
+ <profile>
+ <id>include-dashboard</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.github.eirslett</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.6</version>
<configuration>
- <arguments>install --cache ${settings.localRepository}/.npm-cache --no-optional</arguments>
+ <nodeVersion>v10.3.0</nodeVersion>
+ <npmVersion>6.1.0</npmVersion>
+ <workingDirectory>target/dashboard</workingDirectory>
+ <installDirectory>target/dashboard</installDirectory>
</configuration>
- </execution>
- <execution>
- <id>npm run-script mavenbuild</id>
- <phase>compile</phase>
- <goals>
- <goal>npm</goal>
- </goals>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-npm</goal>
+ </goals>
+ <phase>generate-resources</phase>
+ </execution>
+ <execution>
+ <id>npm install</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>npm</goal>
+ </goals>
+ <configuration>
+ <arguments>install --cache ${settings.localRepository}/.npm-cache --no-optional</arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>npm run-script mavenbuild</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>npm</goal>
+ </goals>
+ <configuration>
+ <arguments>run-script mavenbuild</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-static</id>
+ <phase>${resource.stage}</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>
+ ${basedir}/target/classes/dashboard/
+ </outputDirectory>
+ <resources>
+ <resource>
+ <directory>${basedir}/target/dashboard/static/
+ </directory>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ <execution>
+ <id>copy-node</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>
+ ${basedir}/target/dashboard
+ </outputDirectory>
+ <resources>
+ <resource>
+ <directory>${basedir}/src/node
+ </directory>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.hyracks</groupId>
+ <artifactId>license-automation-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>${license.stage}</phase>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ </execution>
+ </executions>
<configuration>
- <arguments>run-script mavenbuild</arguments>
+ <templateRootDir>${basedir}</templateRootDir>
+ <outputDir>${project.build.directory}/classes/META-INF</outputDir>
+ <generatedFiles>
+ <generatedFile>
+ <template>src/main/licenses/dashboard-license.ftl</template>
+ <outputFile>LICENSE</outputFile>
+ </generatedFile>
+ </generatedFiles>
+ <location>repo/</location>
+ <timeoutSecs>10</timeoutSecs>
+ <downloadDir>
+ ${project.build.directory}/generated-resources/license
+ </downloadDir>
+ <excludedScopes>
+ <excludedScope>test</excludedScope>
+ </excludedScopes>
+ <licenseDirectory>${basedir}/src/main/licenses/content</licenseDirectory>
</configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <artifactId>maven-resources-plugin</artifactId>
- <executions>
- <execution>
- <id>copy-static</id>
- <phase>${resource.stage}</phase>
- <goals>
- <goal>copy-resources</goal>
- </goals>
- <configuration>
- <outputDirectory>
- ${basedir}/target/classes/dashboard/
- </outputDirectory>
- <resources>
- <resource>
- <directory>${basedir}/target/dashboard/static/
- </directory>
- </resource>
- </resources>
- </configuration>
- </execution>
- <execution>
- <id>copy-node</id>
- <phase>validate</phase>
- <goals>
- <goal>copy-resources</goal>
- </goals>
- <configuration>
- <outputDirectory>
- ${basedir}/target/dashboard
- </outputDirectory>
- <resources>
- <resource>
- <directory>${basedir}/src/node
- </directory>
- </resource>
- </resources>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.hyracks</groupId>
- <artifactId>license-automation-plugin</artifactId>
- <executions>
- <execution>
- <phase>${license.stage}</phase>
- <goals>
- <goal>generate</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <templateRootDir>${basedir}</templateRootDir>
- <outputDir>${project.build.directory}/classes/META-INF</outputDir>
- <generatedFiles>
- <generatedFile>
- <template>src/main/licenses/dashboard-license.ftl</template>
- <outputFile>LICENSE</outputFile>
- </generatedFile>
- </generatedFiles>
- <location>repo/</location>
- <timeoutSecs>10</timeoutSecs>
- <downloadDir>
- ${project.build.directory}/generated-resources/license
- </downloadDir>
- <excludedScopes>
- <excludedScope>test</excludedScope>
- </excludedScopes>
- <licenseDirectory>${basedir}/src/main/licenses/content</licenseDirectory>
- </configuration>
- </plugin>
- </plugins>
- </build>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>skip-dashboard</id>
+ </profile>
+ </profiles>
</project>
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/AsterixInputStream.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/AsterixInputStream.java
index a4c2fae..f959f8d 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/AsterixInputStream.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/AsterixInputStream.java
@@ -47,4 +47,12 @@
public void setNotificationHandler(IStreamNotificationHandler notificationHandler) {
this.notificationHandler = notificationHandler;
}
+
+ public String getStreamName() {
+ return "";
+ }
+
+ public String getPreviousStreamName() {
+ return "";
+ }
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IDataFlowController.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IDataFlowController.java
index f59b82e..ccc420b 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IDataFlowController.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IDataFlowController.java
@@ -43,4 +43,11 @@
public default boolean stop(long timeout) throws HyracksDataException {
throw new RuntimeDataException(ErrorCode.OPERATION_NOT_SUPPORTED);
}
+
+ /**
+ * @return The number of processed tuples by this controller
+ */
+ default long getProcessedTuples() {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IRecordConverter.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IRecordConverter.java
index 9d9ff28..f544ca0 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IRecordConverter.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IRecordConverter.java
@@ -19,9 +19,18 @@
package org.apache.asterix.external.api;
import java.io.IOException;
+import java.util.function.LongSupplier;
@FunctionalInterface
public interface IRecordConverter<I, O> {
public O convert(IRawRecord<? extends I> input) throws IOException;
+
+ /**
+ * Configures the converter with information suppliers from the {@link IRecordReader} data source.
+ *
+ * @param lineNumber line number supplier
+ */
+ default void configure(LongSupplier lineNumber) {
+ }
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IRecordDataParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IRecordDataParser.java
index be17744..c4dfdd0 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IRecordDataParser.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IRecordDataParser.java
@@ -19,15 +19,33 @@
package org.apache.asterix.external.api;
import java.io.DataOutput;
+import java.util.function.LongSupplier;
+import java.util.function.Supplier;
import org.apache.hyracks.api.exceptions.HyracksDataException;
public interface IRecordDataParser<T> extends IDataParser {
/**
- * @param record
- * @param out
- * @throws Exception
+ * Parses the input record and writes the result into the {@code out}. Implementations should only write to the
+ * {@code out} if the record is parsed successfully. If parsing fails, the {@code out} should never be touched. In
+ * other words, no partial writing in case of failure. Additionally, implementations may choose to issue a
+ * warning and/or throw an exception in case of failure.
+ *
+ * @param record input record to parse
+ * @param out output where the parsed record is written into
+ *
+ * @return true if the record was parsed successfully and written to out. False, otherwise.
+ * @throws HyracksDataException HyracksDataException
*/
- public void parse(IRawRecord<? extends T> record, DataOutput out) throws HyracksDataException;
+ public boolean parse(IRawRecord<? extends T> record, DataOutput out) throws HyracksDataException;
+
+ /**
+ * Configures the parser with information suppliers from the {@link IRecordReader} data source.
+ *
+ * @param dataSourceName data source name supplier
+ * @param lineNumber line number supplier
+ */
+ default void configure(Supplier<String> dataSourceName, LongSupplier lineNumber) {
+ }
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IRecordReader.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IRecordReader.java
index 9033814..cb97526 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IRecordReader.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/api/IRecordReader.java
@@ -20,8 +20,11 @@
import java.io.Closeable;
import java.io.IOException;
+import java.util.function.LongSupplier;
+import java.util.function.Supplier;
import org.apache.asterix.external.dataflow.AbstractFeedDataFlowController;
+import org.apache.asterix.external.util.ExternalDataConstants;
import org.apache.asterix.external.util.FeedLogManager;
import org.apache.hyracks.api.exceptions.HyracksDataException;
@@ -84,4 +87,12 @@
default String getStats() {
return null;
}
+
+ default Supplier<String> getDataSourceName() {
+ return ExternalDataConstants.EMPTY_STRING;
+ }
+
+ default LongSupplier getLineNumber() {
+ return ExternalDataConstants.NO_LINES;
+ }
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/AbstractDataFlowController.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/AbstractDataFlowController.java
index a324496..95024e1 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/AbstractDataFlowController.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/AbstractDataFlowController.java
@@ -24,8 +24,14 @@
public abstract class AbstractDataFlowController implements IDataFlowController {
protected final IHyracksTaskContext ctx;
+ protected long processedTuples = 0;
public AbstractDataFlowController(IHyracksTaskContext ctx) {
this.ctx = ctx;
}
+
+ @Override
+ public long getProcessedTuples() {
+ return processedTuples;
+ }
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/FeedRecordDataFlowController.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/FeedRecordDataFlowController.java
index f392139..7a089b8 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/FeedRecordDataFlowController.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/FeedRecordDataFlowController.java
@@ -177,14 +177,19 @@
}
private boolean parseAndForward(IRawRecord<? extends T> record) throws IOException {
+ boolean success;
try {
- dataParser.parse(record, tb.getDataOutput());
+ success = dataParser.parse(record, tb.getDataOutput());
} catch (Exception e) {
LOGGER.log(Level.WARN, ExternalDataConstants.ERROR_PARSE_RECORD, e);
feedLogManager.logRecord(record.toString(), ExternalDataConstants.ERROR_PARSE_RECORD);
// continue the outer loop
return false;
}
+ if (!success) {
+ // continue the outer loop
+ return false;
+ }
tb.addFieldEndOffset();
addMetaPart(tb, record);
addPrimaryKeys(tb, record);
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/RecordDataFlowController.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/RecordDataFlowController.java
index c028965..2c19f9d 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/RecordDataFlowController.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/RecordDataFlowController.java
@@ -44,15 +44,18 @@
@Override
public void start(IFrameWriter writer) throws HyracksDataException {
try {
+ processedTuples = 0;
ArrayTupleBuilder tb = new ArrayTupleBuilder(numOfTupleFields);
TupleForwarder tupleForwarder = new TupleForwarder(ctx, writer);
while (recordReader.hasNext()) {
IRawRecord<? extends T> record = recordReader.next();
tb.reset();
- dataParser.parse(record, tb.getDataOutput());
- tb.addFieldEndOffset();
- appendOtherTupleFields(tb);
- tupleForwarder.addTuple(tb);
+ if (dataParser.parse(record, tb.getDataOutput())) {
+ tb.addFieldEndOffset();
+ appendOtherTupleFields(tb);
+ tupleForwarder.addTuple(tb);
+ processedTuples++;
+ }
}
tupleForwarder.complete();
} catch (Exception e) {
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/StreamDataFlowController.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/StreamDataFlowController.java
index 8275953..9c11c97 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/StreamDataFlowController.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataflow/StreamDataFlowController.java
@@ -35,6 +35,7 @@
@Override
public void start(IFrameWriter writer) throws HyracksDataException {
try {
+ processedTuples = 0;
ArrayTupleBuilder tb = new ArrayTupleBuilder(1);
TupleForwarder tupleForwarder = new TupleForwarder(ctx, writer);
while (true) {
@@ -44,6 +45,7 @@
}
tb.addFieldEndOffset();
tupleForwarder.addTuple(tb);
+ processedTuples++;
}
tupleForwarder.complete();
} catch (Exception e) {
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataset/adapter/FeedAdapter.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataset/adapter/FeedAdapter.java
index 0ab59fe..123a552 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataset/adapter/FeedAdapter.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataset/adapter/FeedAdapter.java
@@ -38,6 +38,11 @@
controller.start(writer);
}
+ @Override
+ public long getProcessedTuples() {
+ return controller.getProcessedTuples();
+ }
+
public boolean stop(long timeout) throws HyracksDataException {
return controller.stop(timeout);
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataset/adapter/GenericAdapter.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataset/adapter/GenericAdapter.java
index 0904384..17a134b 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataset/adapter/GenericAdapter.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataset/adapter/GenericAdapter.java
@@ -35,4 +35,9 @@
public void start(int partition, IFrameWriter writer) throws HyracksDataException, InterruptedException {
controller.start(writer);
}
+
+ @Override
+ public long getProcessedTuples() {
+ return controller.getProcessedTuples();
+ }
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataset/adapter/LookupAdapter.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataset/adapter/LookupAdapter.java
index 82e9bba..5700f9d 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataset/adapter/LookupAdapter.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/dataset/adapter/LookupAdapter.java
@@ -127,9 +127,10 @@
propagateInputFields(tupleIndex);
}
if (record != null) {
- dataParser.parse(record, tb.getDataOutput());
- tb.addFieldEndOffset();
- DataflowUtils.addTupleToFrame(appender, tb, writer);
+ if (dataParser.parse(record, tb.getDataOutput())) {
+ tb.addFieldEndOffset();
+ DataflowUtils.addTupleToFrame(appender, tb, writer);
+ }
} else if (retainNull) {
tb.getDataOutput().write(missingTupleBuild.getByteArray());
tb.addFieldEndOffset();
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/CharArrayRecord.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/CharArrayRecord.java
index aa4abb4..5d7ffb2 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/CharArrayRecord.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/CharArrayRecord.java
@@ -65,7 +65,7 @@
size = length;
}
- private void ensureCapacity(int len) throws IOException {
+ private void ensureCapacity(int len) throws RuntimeDataException {
if (value.length < len) {
if (len > ExternalDataConstants.MAX_RECORD_SIZE) {
throw new RuntimeDataException(ErrorCode.INPUT_RECORD_READER_CHAR_ARRAY_RECORD_TOO_LARGE,
@@ -77,7 +77,7 @@
}
}
- public void append(char[] recordBuffer, int offset, int length) throws IOException {
+ public void append(char[] recordBuffer, int offset, int length) throws RuntimeDataException {
ensureCapacity(size + length);
System.arraycopy(recordBuffer, offset, value, size, length);
size += length;
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/RecordWithMetadataAndPK.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/RecordWithMetadataAndPK.java
index 959e34d..de889a2 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/RecordWithMetadataAndPK.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/RecordWithMetadataAndPK.java
@@ -155,7 +155,9 @@
fieldValueBufferOutputs[index].writeByte(ATypeTag.SERIALIZED_NULL_TYPE_TAG);
} else {
fieldValueBufferOutputs[index].writeByte(fieldTypeTags[index]);
- valueParsers[index].parse(src, offset, length, fieldValueBufferOutputs[index]);
+ if (!valueParsers[index].parse(src, offset, length, fieldValueBufferOutputs[index])) {
+ throw new RuntimeDataException(ErrorCode.FAILED_TO_PARSE_METADATA);
+ }
}
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/CSVToRecordWithMetadataAndPKConverter.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/CSVToRecordWithMetadataAndPKConverter.java
index 5c8f219..8b930aa 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/CSVToRecordWithMetadataAndPKConverter.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/CSVToRecordWithMetadataAndPKConverter.java
@@ -19,13 +19,17 @@
package org.apache.asterix.external.input.record.converter;
import java.io.IOException;
+import java.util.function.LongSupplier;
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.RuntimeDataException;
import org.apache.asterix.external.api.IRawRecord;
import org.apache.asterix.external.input.record.CharArrayRecord;
import org.apache.asterix.external.input.record.RecordWithMetadataAndPK;
import org.apache.asterix.external.util.ExternalDataConstants;
import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
import org.apache.hyracks.dataflow.std.file.FieldCursorForDelimitedDataParser;
public class CSVToRecordWithMetadataAndPKConverter
@@ -35,10 +39,13 @@
private final int valueIndex;
private final RecordWithMetadataAndPK<char[]> recordWithMetadata;
private final CharArrayRecord record;
+ private LongSupplier lineNumber = ExternalDataConstants.NO_LINES;
public CSVToRecordWithMetadataAndPKConverter(final int valueIndex, final char delimiter, final ARecordType metaType,
- final ARecordType recordType, final int[] keyIndicator, final int[] keyIndexes, final IAType[] keyTypes) {
- this.cursor = new FieldCursorForDelimitedDataParser(null, delimiter, ExternalDataConstants.QUOTE);
+ final ARecordType recordType, final int[] keyIndicator, final int[] keyIndexes, final IAType[] keyTypes,
+ IWarningCollector warningCollector) {
+ this.cursor = new FieldCursorForDelimitedDataParser(null, delimiter, ExternalDataConstants.QUOTE,
+ warningCollector, ExternalDataConstants.EMPTY_STRING);
this.record = new CharArrayRecord();
this.valueIndex = valueIndex;
this.recordWithMetadata = new RecordWithMetadataAndPK<>(record, metaType.getFieldTypes(), recordType,
@@ -49,10 +56,11 @@
public RecordWithMetadataAndPK<char[]> convert(final IRawRecord<? extends char[]> input) throws IOException {
record.reset();
recordWithMetadata.reset();
- cursor.nextRecord(input.get(), input.size());
+ cursor.nextRecord(input.get(), input.size(), lineNumber.getAsLong());
int i = 0;
int j = 0;
- while (cursor.nextField()) {
+ FieldCursorForDelimitedDataParser.Result lastResult;
+ while ((lastResult = cursor.nextField()) == FieldCursorForDelimitedDataParser.Result.OK) {
if (cursor.fieldHasDoubleQuote()) {
cursor.eliminateDoubleQuote();
}
@@ -66,6 +74,14 @@
}
i++;
}
+ if (lastResult == FieldCursorForDelimitedDataParser.Result.ERROR) {
+ throw new RuntimeDataException(ErrorCode.FAILED_TO_PARSE_RECORD);
+ }
return recordWithMetadata;
}
+
+ @Override
+ public void configure(LongSupplier lineNumber) {
+ this.lineNumber = lineNumber == null ? ExternalDataConstants.NO_LINES : lineNumber;
+ }
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/CSVWithRecordConverterFactory.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/CSVWithRecordConverterFactory.java
index ee16228..a9e5bc7 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/CSVWithRecordConverterFactory.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/CSVWithRecordConverterFactory.java
@@ -27,6 +27,7 @@
import org.apache.asterix.external.util.ExternalDataConstants;
import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
public class CSVWithRecordConverterFactory implements IRecordConverterFactory<char[], RecordWithMetadataAndPK<char[]>> {
@@ -40,9 +41,9 @@
private IAType[] keyTypes;
@Override
- public IRecordConverter<char[], RecordWithMetadataAndPK<char[]>> createConverter() {
+ public IRecordConverter<char[], RecordWithMetadataAndPK<char[]>> createConverter(IHyracksTaskContext ctx) {
return new CSVToRecordWithMetadataAndPKConverter(recordIndex, delimiter, metaType, recordType, keyIndicators,
- keyIndexes, keyTypes);
+ keyIndexes, keyTypes, ctx.getWarningCollector());
}
@Override
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/DCPConverterFactory.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/DCPConverterFactory.java
index dc93533..b228b94 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/DCPConverterFactory.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/DCPConverterFactory.java
@@ -24,6 +24,7 @@
import org.apache.asterix.external.api.IRecordConverter;
import org.apache.asterix.external.input.record.RecordWithMetadataAndPK;
import org.apache.asterix.om.types.ARecordType;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
import com.couchbase.client.core.message.dcp.DCPRequest;
@@ -50,7 +51,7 @@
}
@Override
- public IRecordConverter<DCPRequest, RecordWithMetadataAndPK<char[]>> createConverter() {
+ public IRecordConverter<DCPRequest, RecordWithMetadataAndPK<char[]>> createConverter(IHyracksTaskContext ctx) {
return new DCPMessageToRecordConverter();
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/IRecordConverterFactory.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/IRecordConverterFactory.java
index 4990527..875a331 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/IRecordConverterFactory.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/converter/IRecordConverterFactory.java
@@ -24,10 +24,11 @@
import org.apache.asterix.common.exceptions.AsterixException;
import org.apache.asterix.external.api.IRecordConverter;
import org.apache.asterix.om.types.ARecordType;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
public interface IRecordConverterFactory<I, O> extends Serializable {
- public IRecordConverter<I, O> createConverter();
+ public IRecordConverter<I, O> createConverter(IHyracksTaskContext ctx);
public void configure(Map<String, String> configuration) throws AsterixException;
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/aws/AwsS3InputStream.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/aws/AwsS3InputStream.java
index cfa1f6a..448d3f5 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/aws/AwsS3InputStream.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/aws/AwsS3InputStream.java
@@ -21,13 +21,13 @@
import static org.apache.asterix.external.util.ExternalDataConstants.AwsS3Constants;
import java.io.IOException;
-import java.io.InputStream;
import java.net.URI;
import java.util.List;
import java.util.Map;
+import java.util.zip.GZIPInputStream;
-import org.apache.asterix.external.api.AsterixInputStream;
-import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.asterix.external.input.stream.AbstractMultipleInputStream;
+import org.apache.asterix.external.util.ExternalDataConstants;
import org.apache.hyracks.api.util.CleanupUtils;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
@@ -37,7 +37,7 @@
import software.amazon.awssdk.services.s3.S3ClientBuilder;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
-public class AwsS3InputStream extends AsterixInputStream {
+public class AwsS3InputStream extends AbstractMultipleInputStream {
// Configuration
private final Map<String, String> configuration;
@@ -48,70 +48,51 @@
private final List<String> filePaths;
private int nextFileIndex = 0;
- // File reading fields
- private InputStream inputStream;
-
public AwsS3InputStream(Map<String, String> configuration, List<String> filePaths) {
this.configuration = configuration;
this.filePaths = filePaths;
-
this.s3Client = buildAwsS3Client(configuration);
}
@Override
- public int read() throws IOException {
- throw new HyracksDataException(
- "read() is not supported with this stream. use read(byte[] b, int off, int len)");
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- if (inputStream == null) {
- if (!advance()) {
- return -1;
- }
- }
-
- int result = inputStream.read(b, off, len);
-
- // If file reading is done, go to the next file, or finish up if no files are left
- if (result < 0) {
- if (advance()) {
- result = inputStream.read(b, off, len);
- } else {
- return -1;
- }
- }
-
- return result;
- }
-
- private boolean advance() throws IOException {
+ protected boolean advance() throws IOException {
// No files to read for this partition
if (filePaths == null || filePaths.isEmpty()) {
return false;
}
// Finished reading all the files
- if (nextFileIndex == filePaths.size()) {
- if (inputStream != null) {
- inputStream.close();
+ if (nextFileIndex >= filePaths.size()) {
+ if (in != null) {
+ CleanupUtils.close(in, null);
}
return false;
}
// Close the current stream before going to the next one
- if (inputStream != null) {
- inputStream.close();
+ if (in != null) {
+ CleanupUtils.close(in, null);
}
String bucket = configuration.get(AwsS3Constants.CONTAINER_NAME_FIELD_NAME);
GetObjectRequest.Builder getObjectBuilder = GetObjectRequest.builder();
GetObjectRequest getObjectRequest = getObjectBuilder.bucket(bucket).key(filePaths.get(nextFileIndex)).build();
- inputStream = s3Client.getObject(getObjectRequest);
+
+ // Have a reference to the S3 stream to ensure that if GZipInputStream causes an IOException because of reading
+ // the header, then the S3 stream gets closed in the close method
+ in = s3Client.getObject(getObjectRequest);
+
+ // Use gzip stream if needed
+ String filename = filePaths.get(nextFileIndex).toLowerCase();
+ if (filename.endsWith(".gz") || filename.endsWith(".gzip")) {
+ in = new GZIPInputStream(s3Client.getObject(getObjectRequest), ExternalDataConstants.DEFAULT_BUFFER_SIZE);
+ }
// Current file ready, point to the next file
nextFileIndex++;
+ if (notificationHandler != null) {
+ notificationHandler.notifyNewSource();
+ }
return true;
}
@@ -127,11 +108,25 @@
@Override
public void close() throws IOException {
- if (inputStream != null) {
- CleanupUtils.close(inputStream, null);
+ if (in != null) {
+ CleanupUtils.close(in, null);
}
}
+ @Override
+ public String getStreamName() {
+ return getStreamNameAt(nextFileIndex - 1);
+ }
+
+ @Override
+ public String getPreviousStreamName() {
+ return getStreamNameAt(nextFileIndex - 2);
+ }
+
+ private String getStreamNameAt(int fileIndex) {
+ return fileIndex < 0 || filePaths == null || filePaths.isEmpty() ? "" : filePaths.get(fileIndex);
+ }
+
/**
* Prepares and builds the Amazon S3 client with the provided configuration
*
@@ -143,9 +138,9 @@
S3ClientBuilder builder = S3Client.builder();
// Credentials
- String accessKey = configuration.get(AwsS3Constants.ACCESS_KEY_FIELD_NAME);
- String secretKey = configuration.get(AwsS3Constants.SECRET_KEY_FIELD_NAME);
- AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKey, secretKey);
+ String accessKeyId = configuration.get(AwsS3Constants.ACCESS_KEY_ID_FIELD_NAME);
+ String secretAccessKey = configuration.get(AwsS3Constants.SECRET_ACCESS_KEY_FIELD_NAME);
+ AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKeyId, secretAccessKey);
builder.credentialsProvider(StaticCredentialsProvider.create(credentials));
// Region
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/aws/AwsS3InputStreamFactory.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/aws/AwsS3InputStreamFactory.java
index 6b8bb59..58a77b1 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/aws/AwsS3InputStreamFactory.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/aws/AwsS3InputStreamFactory.java
@@ -89,7 +89,7 @@
ListObjectsRequest.Builder listObjectsBuilder = ListObjectsRequest.builder().bucket(container);
String path = configuration.get(AwsS3Constants.DEFINITION_FIELD_NAME);
if (path != null) {
- listObjectsBuilder.prefix(path + (path.endsWith("/") ? "" : "/"));
+ listObjectsBuilder.prefix(path + (!path.isEmpty() && !path.endsWith("/") ? "/" : ""));
}
ListObjectsResponse listObjectsResponse = s3Client.listObjects(listObjectsBuilder.build());
List<S3Object> s3Objects = listObjectsResponse.contents();
@@ -123,12 +123,28 @@
throw AsterixException.create(ErrorCode.PROVIDER_STREAM_RECORD_READER_UNKNOWN_FORMAT, fileFormat);
}
- s3Objects.stream().filter(object -> object.key().endsWith(fileExtension)).forEach(filesOnly::add);
+ s3Objects.stream().filter(object -> isValidFile(object.key(), fileFormat)).forEach(filesOnly::add);
return filesOnly;
}
/**
+ * Checks if the file name is of the provided format, or in the provided format in a compressed (.gz or .gzip) state
+ *
+ * @param fileName file name to be checked
+ * @param format expected format
+ * @return {@code true} if the file name is of the expected format, {@code false} otherwise
+ */
+ private boolean isValidFile(String fileName, String format) {
+ String lowCaseName = fileName.toLowerCase();
+ String lowCaseFormat = format.toLowerCase();
+ String gzExt = lowCaseFormat + ".gz";
+ String gzipExt = lowCaseFormat + ".gzip";
+
+ return lowCaseName.endsWith(lowCaseFormat) || lowCaseName.endsWith(gzExt) || lowCaseName.endsWith(gzipExt);
+ }
+
+ /**
* To efficiently utilize the parallelism, work load will be distributed amongst the partitions based on the file
* size.
*
@@ -186,9 +202,9 @@
S3ClientBuilder builder = S3Client.builder();
// Credentials
- String accessKey = configuration.get(AwsS3Constants.ACCESS_KEY_FIELD_NAME);
- String secretKey = configuration.get(AwsS3Constants.SECRET_KEY_FIELD_NAME);
- AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKey, secretKey);
+ String accessKeyId = configuration.get(AwsS3Constants.ACCESS_KEY_ID_FIELD_NAME);
+ String secretAccessKey = configuration.get(AwsS3Constants.SECRET_ACCESS_KEY_FIELD_NAME);
+ AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKeyId, secretAccessKey);
builder.credentialsProvider(StaticCredentialsProvider.create(credentials));
// Region
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/EmptyLineSeparatedRecordReader.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/EmptyLineSeparatedRecordReader.java
index 24a68a7..b697b05 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/EmptyLineSeparatedRecordReader.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/EmptyLineSeparatedRecordReader.java
@@ -137,7 +137,7 @@
@Override
public void configure(IHyracksTaskContext ctx, AsterixInputStream inputStream, Map<String, String> config) {
- super.configure(inputStream);
+ super.configure(inputStream, config);
this.config = config;
}
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/LineRecordReader.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/LineRecordReader.java
index a27397e..4b86142 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/LineRecordReader.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/LineRecordReader.java
@@ -23,6 +23,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.function.LongSupplier;
import org.apache.asterix.external.api.AsterixInputStream;
import org.apache.asterix.external.util.ExternalDataConstants;
@@ -32,11 +33,12 @@
public class LineRecordReader extends StreamRecordReader {
- private boolean hasHeader;
+ protected boolean hasHeader;
protected boolean prevCharCR;
protected int newlineLength;
- protected int recordNumber = 0;
- protected boolean nextIsHeader = false;
+ protected long beginLineNumber = 1;
+ protected long lineNumber = 1;
+ protected boolean newSource = false;
private static final List<String> recordReaderFormats =
Collections.unmodifiableList(Arrays.asList(ExternalDataConstants.FORMAT_DELIMITED_TEXT,
ExternalDataConstants.FORMAT_CSV, ExternalDataConstants.FORMAT_TSV));
@@ -45,19 +47,25 @@
@Override
public void configure(IHyracksTaskContext ctx, AsterixInputStream inputStream, Map<String, String> config)
throws HyracksDataException {
- super.configure(inputStream);
+ super.configure(inputStream, config);
this.hasHeader = ExternalDataUtils.hasHeader(config);
- if (hasHeader) {
- // TODO(ali): revisit this and notifyNewSource
- inputStream.setNotificationHandler(this);
- }
+ this.newSource = true;
+ inputStream.setNotificationHandler(this);
}
@Override
public void notifyNewSource() {
- if (hasHeader) {
- nextIsHeader = true;
- }
+ resetForNewSource();
+ }
+
+ @Override
+ public void resetForNewSource() {
+ super.resetForNewSource();
+ newSource = true;
+ beginLineNumber = 1;
+ lineNumber = 1;
+ prevCharCR = false;
+ newlineLength = 0;
}
@Override
@@ -93,6 +101,7 @@
* consuming it until we have a chance to look at the char that
* follows.
*/
+ beginLineNumber = lineNumber;
newlineLength = 0; //length of terminating newline
prevCharCR = false; //true of prev char was CR
record.reset();
@@ -108,30 +117,24 @@
return false; //EOF
}
record.endRecord();
- if (record.isEmptyRecord()) {
- return false;
- }
- recordNumber++;
- return true;
+ break;
}
}
for (; bufferPosn < bufferLength; ++bufferPosn) { //search for newline
if (inputBuffer[bufferPosn] == ExternalDataConstants.LF) {
newlineLength = (prevCharCR) ? 2 : 1;
++bufferPosn; // at next invocation proceed from following byte
+ ++lineNumber;
break;
}
if (prevCharCR) { //CR + notLF, we are at notLF
+ ++lineNumber;
newlineLength = 1;
break;
}
prevCharCR = (inputBuffer[bufferPosn] == ExternalDataConstants.CR);
}
readLength = bufferPosn - startPosn;
- if (prevCharCR && newlineLength == 0) {
- --readLength; //CR at the end of the buffer
- prevCharCR = false;
- }
if (readLength > 0) {
record.append(inputBuffer, startPosn, readLength);
}
@@ -139,12 +142,20 @@
if (record.isEmptyRecord()) {
continue;
}
- if (nextIsHeader) {
- nextIsHeader = false;
+ if (newSource && hasHeader) {
+ newSource = false;
continue;
}
- recordNumber++;
return true;
}
}
+
+ @Override
+ public LongSupplier getLineNumber() {
+ return this::getBeginLineNumber;
+ }
+
+ private long getBeginLineNumber() {
+ return beginLineNumber;
+ }
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/QuotedLineRecordReader.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/QuotedLineRecordReader.java
index 564df4b..3a502d0 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/QuotedLineRecordReader.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/QuotedLineRecordReader.java
@@ -18,28 +18,30 @@
*/
package org.apache.asterix.external.input.record.reader.stream;
+import static org.apache.asterix.external.util.ExternalDataConstants.REC_ENDED_AT_EOF;
+
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import org.apache.asterix.common.exceptions.ErrorCode;
-import org.apache.asterix.common.exceptions.WarningUtil;
import org.apache.asterix.external.api.AsterixInputStream;
import org.apache.asterix.external.util.ExternalDataConstants;
import org.apache.asterix.external.util.ExternalDataUtils;
+import org.apache.asterix.external.util.ParseUtil;
import org.apache.hyracks.api.context.IHyracksTaskContext;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.exceptions.IWarningCollector;
-import org.apache.hyracks.api.exceptions.SourceLocation;
public class QuotedLineRecordReader extends LineRecordReader {
private char quote;
- private char quoteEscape;
- private IWarningCollector warningCollector;
- private final SourceLocation srcLoc = new SourceLocation(-1, -1);
+ private char escape;
+ private boolean prevCharEscape;
+ private int readLength;
+ private boolean inQuote;
+ private IWarningCollector warnings;
private static final List<String> recordReaderFormats = Collections.unmodifiableList(
Arrays.asList(ExternalDataConstants.FORMAT_DELIMITED_TEXT, ExternalDataConstants.FORMAT_CSV));
private static final String REQUIRED_CONFIGS = ExternalDataConstants.KEY_QUOTE;
@@ -48,11 +50,28 @@
public void configure(IHyracksTaskContext ctx, AsterixInputStream inputStream, Map<String, String> config)
throws HyracksDataException {
super.configure(ctx, inputStream, config);
- this.warningCollector = ctx.getWarningCollector();
+ this.warnings = ctx.getWarningCollector();
String quoteString = config.get(ExternalDataConstants.KEY_QUOTE);
- ExternalDataUtils.validateQuote(quoteString);
+ ExternalDataUtils.validateChar(quoteString, ExternalDataConstants.KEY_QUOTE);
this.quote = quoteString.charAt(0);
- this.quoteEscape = ExternalDataUtils.validateGetQuoteEscape(config);
+ this.escape = ExternalDataUtils.validateGetEscape(config);
+ }
+
+ @Override
+ public void notifyNewSource() {
+ if (!record.isEmptyRecord() && warnings.shouldWarn()) {
+ ParseUtil.warn(warnings, getPreviousStreamName(), lineNumber, 0, REC_ENDED_AT_EOF);
+ }
+ // restart for a new record from a new source
+ resetForNewSource();
+ }
+
+ @Override
+ public void resetForNewSource() {
+ super.resetForNewSource();
+ prevCharEscape = false;
+ readLength = 0;
+ inQuote = false;
}
@Override
@@ -71,12 +90,13 @@
if (done) {
return false;
}
+ beginLineNumber = lineNumber;
newlineLength = 0;
prevCharCR = false;
- boolean prevCharEscape = false;
+ prevCharEscape = false;
record.reset();
- int readLength = 0;
- boolean inQuote = false;
+ readLength = 0;
+ inQuote = false;
do {
int startPosn = bufferPosn;
if (bufferPosn >= bufferLength) {
@@ -86,30 +106,30 @@
// reached end of stream
if (readLength <= 0 || inQuote) {
// haven't read anything previously OR have read and in the middle and hit the end
- if (inQuote && warningCollector.shouldWarn()) {
- warningCollector
- .warn(WarningUtil.forAsterix(srcLoc, ErrorCode.MALFORMED_RECORD, recordNumber));
+ if (inQuote && warnings.shouldWarn()) {
+ ParseUtil.warn(warnings, getDataSourceName().get(), lineNumber, 0, REC_ENDED_AT_EOF);
}
close();
return false;
}
record.endRecord();
- if (record.isEmptyRecord()) {
- return false;
- }
- recordNumber++;
- return true;
+ break;
}
}
boolean maybeInQuote = false;
for (; bufferPosn < bufferLength; ++bufferPosn) {
- if (inputBuffer[bufferPosn] == quote && quoteEscape == quote) {
+ char ch = inputBuffer[bufferPosn];
+ // count lines here since we need to also count the lines inside quotes
+ if (ch == ExternalDataConstants.LF || prevCharCR) {
+ lineNumber++;
+ }
+ if (ch == quote && escape == quote) {
inQuote |= maybeInQuote;
prevCharEscape |= maybeInQuote;
}
maybeInQuote = false;
if (!inQuote) {
- if (inputBuffer[bufferPosn] == ExternalDataConstants.LF) {
+ if (ch == ExternalDataConstants.LF) {
newlineLength = (prevCharCR) ? 2 : 1;
++bufferPosn;
break;
@@ -118,29 +138,22 @@
newlineLength = 1;
break;
}
- prevCharCR = (inputBuffer[bufferPosn] == ExternalDataConstants.CR);
- if (inputBuffer[bufferPosn] == quote && !prevCharEscape) {
- // this is an opening quote
- inQuote = true;
- }
- // the quoteEscape != quote is for making an opening quote not an escape
- prevCharEscape =
- inputBuffer[bufferPosn] == quoteEscape && !prevCharEscape && quoteEscape != quote;
+ // if this is an opening quote, mark it
+ inQuote = ch == quote && !prevCharEscape;
+ // the escape != quote is for making an opening quote not an escape
+ prevCharEscape = ch == escape && !prevCharEscape && escape != quote;
} else {
- // if quote == quoteEscape and current char is quote, then it could be closing or escaping
- if (inputBuffer[bufferPosn] == quote && !prevCharEscape) {
+ // if quote == escape and current char is quote, then it could be closing or escaping
+ if (ch == quote && !prevCharEscape) {
// this is most likely a closing quote. the outcome depends on the next char
inQuote = false;
maybeInQuote = true;
}
- prevCharEscape =
- inputBuffer[bufferPosn] == quoteEscape && !prevCharEscape && quoteEscape != quote;
+ prevCharEscape = ch == escape && !prevCharEscape && escape != quote;
}
+ prevCharCR = (ch == ExternalDataConstants.CR);
}
readLength = bufferPosn - startPosn;
- if (prevCharCR && newlineLength == 0) {
- --readLength;
- }
if (readLength > 0) {
record.append(inputBuffer, startPosn, readLength);
}
@@ -148,11 +161,10 @@
if (record.isEmptyRecord()) {
continue;
}
- if (nextIsHeader) {
- nextIsHeader = false;
+ if (newSource && hasHeader) {
+ newSource = false;
continue;
}
- recordNumber++;
return true;
}
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/SemiStructuredRecordReader.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/SemiStructuredRecordReader.java
index 5ab5730..dfc60bc 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/SemiStructuredRecordReader.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/SemiStructuredRecordReader.java
@@ -18,28 +18,55 @@
*/
package org.apache.asterix.external.input.record.reader.stream;
+import static org.apache.asterix.external.util.ExternalDataConstants.CLOSING_BRACKET;
+import static org.apache.asterix.external.util.ExternalDataConstants.COMMA;
+import static org.apache.asterix.external.util.ExternalDataConstants.CR;
+import static org.apache.asterix.external.util.ExternalDataConstants.KEY_RECORD_END;
+import static org.apache.asterix.external.util.ExternalDataConstants.LF;
+import static org.apache.asterix.external.util.ExternalDataConstants.OPEN_BRACKET;
+import static org.apache.asterix.external.util.ExternalDataConstants.REC_ENDED_AT_EOF;
+import static org.apache.asterix.external.util.ExternalDataConstants.SPACE;
+import static org.apache.asterix.external.util.ExternalDataConstants.TAB;
+
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.function.LongSupplier;
import org.apache.asterix.common.exceptions.ErrorCode;
-import org.apache.asterix.common.exceptions.ExceptionUtils;
import org.apache.asterix.common.exceptions.RuntimeDataException;
import org.apache.asterix.external.api.AsterixInputStream;
import org.apache.asterix.external.util.ExternalDataConstants;
+import org.apache.asterix.external.util.ExternalDataUtils;
+import org.apache.asterix.external.util.ParseUtil;
import org.apache.hyracks.api.context.IHyracksTaskContext;
import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
public class SemiStructuredRecordReader extends StreamRecordReader {
+ private enum State {
+ TOP_LEVEL, // valid chars at this state: '{' or '[' to start a new record or array of records
+ ARRAY, // valid chars at this state: '{' or ']' to start the first nested record or close the array
+ NESTED_OBJECT, // valid chars at this state: ',' or ']' to close the array or expect another nested record
+ AFTER_COMMA // valid chars at this state: '{' to start a new nested record
+ }
+
+ private IWarningCollector warnings;
private int depth;
private boolean prevCharEscape;
private boolean inString;
private char recordStart;
private char recordEnd;
- private int recordNumber = 0;
+ private boolean hasStarted;
+ private boolean hasFinished;
+ private boolean isLastCharCR;
+ private State state = State.TOP_LEVEL;
+ private long beginLineNumber = 1;
+ private long lineNumber = 1;
+
private static final List<String> recordReaderFormats = Collections.unmodifiableList(
Arrays.asList(ExternalDataConstants.FORMAT_ADM, ExternalDataConstants.FORMAT_JSON_LOWER_CASE,
ExternalDataConstants.FORMAT_JSON_UPPER_CASE, ExternalDataConstants.FORMAT_SEMISTRUCTURED));
@@ -48,35 +75,36 @@
@Override
public void configure(IHyracksTaskContext ctx, AsterixInputStream stream, Map<String, String> config)
throws HyracksDataException {
- super.configure(stream);
- String recStartString = config.get(ExternalDataConstants.KEY_RECORD_START);
- String recEndString = config.get(ExternalDataConstants.KEY_RECORD_END);
+ super.configure(stream, config);
+ stream.setNotificationHandler(this);
+ warnings = ctx.getWarningCollector();
// set record opening char
- if (recStartString != null) {
- if (recStartString.length() != 1) {
- throw new HyracksDataException(
- ExceptionUtils.incorrectParameterMessage(ExternalDataConstants.KEY_RECORD_START,
- ExternalDataConstants.PARAMETER_OF_SIZE_ONE, recStartString));
- }
- recordStart = recStartString.charAt(0);
- } else {
- recordStart = ExternalDataConstants.DEFAULT_RECORD_START;
- }
+ recordStart = ExternalDataUtils.validateGetRecordStart(config);
// set record ending char
- if (recEndString != null) {
- if (recEndString.length() != 1) {
- throw new HyracksDataException(
- ExceptionUtils.incorrectParameterMessage(ExternalDataConstants.KEY_RECORD_END,
- ExternalDataConstants.PARAMETER_OF_SIZE_ONE, recEndString));
- }
- recordEnd = recEndString.charAt(0);
- } else {
- recordEnd = ExternalDataConstants.DEFAULT_RECORD_END;
+ recordEnd = ExternalDataUtils.validateGetRecordEnd(config);
+ if (recordStart == recordEnd) {
+ throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, KEY_RECORD_END, recordEnd);
}
}
- public int getRecordNumber() {
- return recordNumber;
+ @Override
+ public void notifyNewSource() {
+ if (hasStarted && warnings.shouldWarn()) {
+ ParseUtil.warn(warnings, getPreviousStreamName(), lineNumber, 0, REC_ENDED_AT_EOF);
+ }
+ beginLineNumber = 1;
+ lineNumber = 1;
+ state = State.TOP_LEVEL;
+ resetForNewRecord();
+ }
+
+ @Override
+ public LongSupplier getLineNumber() {
+ return this::getBeginLineNumber;
+ }
+
+ private long getBeginLineNumber() {
+ return beginLineNumber;
}
@Override
@@ -84,34 +112,51 @@
if (done) {
return false;
}
- record.reset();
- boolean hasStarted = false;
- boolean hasFinished = false;
- prevCharEscape = false;
- inString = false;
- depth = 0;
+ resetForNewRecord();
+ beginLineNumber = lineNumber;
do {
int startPosn = bufferPosn; // starting from where we left off the last time
if (bufferPosn >= bufferLength) {
startPosn = bufferPosn = 0;
bufferLength = reader.read(inputBuffer);
if (bufferLength < 0) {
+ if (hasStarted && warnings.shouldWarn()) {
+ ParseUtil.warn(warnings, getDataSourceName().get(), lineNumber, 0, REC_ENDED_AT_EOF);
+ }
close();
return false; // EOF
}
}
if (!hasStarted) {
for (; bufferPosn < bufferLength; ++bufferPosn) { // search for record begin
- if (inputBuffer[bufferPosn] == recordStart) {
+ char c = inputBuffer[bufferPosn];
+ if (c == LF || isLastCharCR) {
+ lineNumber++;
+ }
+ isLastCharCR = c == CR;
+ if (c == SPACE || c == TAB || c == LF || c == CR) {
+ continue;
+ }
+ if (c == recordStart && state != State.NESTED_OBJECT) {
+ // '{' is allowed at the top level, after '[' and after ','
+ if (state == State.ARRAY || state == State.AFTER_COMMA) {
+ state = State.NESTED_OBJECT;
+ }
startPosn = bufferPosn;
hasStarted = true;
depth = 1;
- ++bufferPosn; // at next invocation proceed from following byte
+ ++bufferPosn;
break;
- } else if (inputBuffer[bufferPosn] != ExternalDataConstants.SPACE
- && inputBuffer[bufferPosn] != ExternalDataConstants.TAB
- && inputBuffer[bufferPosn] != ExternalDataConstants.LF
- && inputBuffer[bufferPosn] != ExternalDataConstants.CR) {
+ } else if (c == OPEN_BRACKET && state == State.TOP_LEVEL) {
+ // '[' is allowed at the top level only
+ state = State.ARRAY;
+ } else if (c == CLOSING_BRACKET && (state == State.ARRAY || state == State.NESTED_OBJECT)) {
+ // ']' is allowed after '[' and after capturing a record in an array
+ state = State.TOP_LEVEL;
+ } else if (c == COMMA && state == State.NESTED_OBJECT) {
+ // ',' is allowed after capturing a record in an array
+ state = State.AFTER_COMMA;
+ } else {
// corrupted file. clear the buffer and stop reading
reader.reset();
bufferPosn = bufferLength = 0;
@@ -120,23 +165,23 @@
}
}
if (hasStarted) {
- for (; bufferPosn < bufferLength; ++bufferPosn) { // search for record begin
+ for (; bufferPosn < bufferLength; ++bufferPosn) {
+ char c = inputBuffer[bufferPosn];
+ if (c == LF || isLastCharCR) {
+ lineNumber++;
+ }
if (inString) {
// we are in a string, we only care about the string end
- if (inputBuffer[bufferPosn] == ExternalDataConstants.QUOTE && !prevCharEscape) {
+ if (c == ExternalDataConstants.QUOTE && !prevCharEscape) {
inString = false;
}
- if (prevCharEscape) {
- prevCharEscape = false;
- } else {
- prevCharEscape = inputBuffer[bufferPosn] == ExternalDataConstants.ESCAPE;
- }
+ prevCharEscape = c == ExternalDataConstants.ESCAPE && !prevCharEscape;
} else {
- if (inputBuffer[bufferPosn] == ExternalDataConstants.QUOTE) {
+ if (c == ExternalDataConstants.QUOTE) {
inString = true;
- } else if (inputBuffer[bufferPosn] == recordStart) {
+ } else if (c == recordStart) {
depth += 1;
- } else if (inputBuffer[bufferPosn] == recordEnd) {
+ } else if (c == recordEnd) {
depth -= 1;
if (depth == 0) {
hasFinished = true;
@@ -145,6 +190,7 @@
}
}
}
+ isLastCharCR = c == CR;
}
}
@@ -152,15 +198,14 @@
if (appendLength > 0) {
try {
record.append(inputBuffer, startPosn, appendLength);
- } catch (IOException e) {
+ } catch (RuntimeDataException e) {
reader.reset();
bufferPosn = bufferLength = 0;
- throw new RuntimeDataException(ErrorCode.RECORD_READER_MALFORMED_INPUT_STREAM);
+ throw e;
}
}
} while (!hasFinished);
record.endRecord();
- recordNumber++;
return true;
}
@@ -174,14 +219,13 @@
return REQUIRED_CONFIGS;
}
- @Override
- public boolean stop() {
- try {
- reader.stop();
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
+ private void resetForNewRecord() {
+ record.reset();
+ hasStarted = false;
+ hasFinished = false;
+ prevCharEscape = false;
+ isLastCharCR = false;
+ inString = false;
+ depth = 0;
}
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/StreamRecordReader.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/StreamRecordReader.java
index 4aed741..cb16de5 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/StreamRecordReader.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/stream/StreamRecordReader.java
@@ -18,9 +18,13 @@
*/
package org.apache.asterix.external.input.record.reader.stream;
+import static org.apache.asterix.external.util.ExternalDataConstants.EMPTY_STRING;
+import static org.apache.asterix.external.util.ExternalDataConstants.KEY_REDACT_WARNINGS;
+
import java.io.IOException;
import java.util.List;
import java.util.Map;
+import java.util.function.Supplier;
import org.apache.asterix.external.api.AsterixInputStream;
import org.apache.asterix.external.api.IRawRecord;
@@ -30,6 +34,7 @@
import org.apache.asterix.external.input.record.CharArrayRecord;
import org.apache.asterix.external.input.stream.AsterixInputStreamReader;
import org.apache.asterix.external.util.ExternalDataConstants;
+import org.apache.asterix.external.util.ExternalDataUtils;
import org.apache.asterix.external.util.FeedLogManager;
import org.apache.hyracks.api.context.IHyracksTaskContext;
import org.apache.hyracks.api.exceptions.HyracksDataException;
@@ -42,11 +47,17 @@
protected int bufferPosn = 0;
protected boolean done = false;
protected FeedLogManager feedLogManager;
+ private Supplier<String> dataSourceName = EMPTY_STRING;
+ private Supplier<String> previousDataSourceName = EMPTY_STRING;
- public void configure(AsterixInputStream inputStream) {
+ public void configure(AsterixInputStream inputStream, Map<String, String> config) {
this.reader = new AsterixInputStreamReader(inputStream);
record = new CharArrayRecord();
inputBuffer = new char[ExternalDataConstants.DEFAULT_BUFFER_SIZE];
+ if (!ExternalDataUtils.isTrue(config, KEY_REDACT_WARNINGS)) {
+ this.dataSourceName = reader::getStreamName;
+ this.previousDataSourceName = reader::getPreviousStreamName;
+ }
}
@Override
@@ -56,10 +67,13 @@
@Override
public void close() throws IOException {
- if (!done) {
- reader.close();
+ try {
+ if (!done) {
+ reader.close();
+ }
+ } finally {
+ done = true;
}
- done = true;
}
@Override
@@ -97,6 +111,19 @@
throw new UnsupportedOperationException();
}
+ protected void resetForNewSource() {
+ record.reset();
+ }
+
+ @Override
+ public final Supplier<String> getDataSourceName() {
+ return dataSourceName;
+ }
+
+ String getPreviousStreamName() {
+ return previousDataSourceName.get();
+ }
+
public abstract List<String> getRecordReaderFormats();
public abstract String getRequiredConfigs();
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/stream/AbstractMultipleInputStream.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/stream/AbstractMultipleInputStream.java
new file mode 100644
index 0000000..8f032d8
--- /dev/null
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/stream/AbstractMultipleInputStream.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+package org.apache.asterix.external.input.stream;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.asterix.external.api.AsterixInputStream;
+import org.apache.asterix.external.api.IStreamNotificationHandler;
+import org.apache.asterix.external.util.ExternalDataConstants;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+/**
+ * Base class for a source stream that is composed of multiple separate input streams. Reading proceeds one stream at
+ * a time.
+ */
+public abstract class AbstractMultipleInputStream extends AsterixInputStream {
+
+ protected InputStream in;
+ private byte lastByte;
+
+ protected AbstractMultipleInputStream() {
+ }
+
+ /**
+ * Closes the current input stream and opens the next one, if any. Implementations should call
+ * {@link IStreamNotificationHandler#notifyNewSource()} using {@link #notificationHandler} if there exists a
+ * notification handler and the handler needs to know when a new input stream has started. Obviously, this method
+ * should populate the {@link #in} upon successfully opening the stream.
+ */
+ protected abstract boolean advance() throws IOException;
+
+ @Override
+ public int read() throws IOException {
+ throw new HyracksDataException(
+ "read() is not supported with this stream. use read(byte[] b, int off, int len)");
+ }
+
+ @Override
+ public final int read(byte[] b, int off, int len) throws IOException {
+ if (in == null) {
+ if (!advance()) {
+ return -1;
+ }
+ }
+ int result = in.read(b, off, len);
+ if (result < 0 && (lastByte != ExternalDataConstants.BYTE_LF) && (lastByte != ExternalDataConstants.BYTE_CR)) {
+ // return a new line at the end of every file <--Might create problems for some cases
+ // depending on the parser implementation-->
+ lastByte = ExternalDataConstants.BYTE_LF;
+ b[off] = ExternalDataConstants.BYTE_LF;
+ return 1;
+ }
+ while ((result < 0) && advance()) {
+ result = in.read(b, off, len);
+ }
+ if (result > 0) {
+ lastByte = b[(off + result) - 1];
+ }
+ return result;
+ }
+}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/stream/AsterixInputStreamReader.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/stream/AsterixInputStreamReader.java
index d35ad26..4e963e4 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/stream/AsterixInputStreamReader.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/stream/AsterixInputStreamReader.java
@@ -127,4 +127,12 @@
public void reset() throws IOException {
byteBuffer.limit(0);
}
+
+ public String getStreamName() {
+ return in.getStreamName();
+ }
+
+ public String getPreviousStreamName() {
+ return in.getPreviousStreamName();
+ }
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/stream/LocalFSInputStream.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/stream/LocalFSInputStream.java
index 2207bd7..9e1b052 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/stream/LocalFSInputStream.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/stream/LocalFSInputStream.java
@@ -24,9 +24,7 @@
import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.exceptions.ExceptionUtils;
-import org.apache.asterix.external.api.AsterixInputStream;
import org.apache.asterix.external.dataflow.AbstractFeedDataFlowController;
-import org.apache.asterix.external.util.ExternalDataConstants;
import org.apache.asterix.external.util.FeedLogManager;
import org.apache.asterix.external.util.FileSystemWatcher;
import org.apache.hyracks.api.exceptions.HyracksDataException;
@@ -34,13 +32,12 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-public class LocalFSInputStream extends AsterixInputStream {
+public class LocalFSInputStream extends AbstractMultipleInputStream {
private static final Logger LOGGER = LogManager.getLogger();
private final FileSystemWatcher watcher;
- private FileInputStream in;
- private byte lastByte;
private File currentFile;
+ private String lastFileName = "";
public LocalFSInputStream(FileSystemWatcher watcher) {
this.watcher = watcher;
@@ -92,10 +89,12 @@
}
}
- /**
- * Closes the current input stream and opens the next one, if any.
- */
- private boolean advance() throws IOException {
+ @Override
+ protected boolean advance() throws IOException {
+ String tmpLastFileName = "";
+ if (currentFile != null) {
+ tmpLastFileName = currentFile.getPath();
+ }
closeFile();
currentFile = watcher.poll();
if (currentFile == null) {
@@ -106,6 +105,7 @@
}
if (currentFile != null) {
in = new FileInputStream(currentFile);
+ lastFileName = tmpLastFileName;
if (notificationHandler != null) {
notificationHandler.notifyNewSource();
}
@@ -115,37 +115,6 @@
}
@Override
- public int read() throws IOException {
- throw new HyracksDataException(
- "read() is not supported with this stream. use read(byte[] b, int off, int len)");
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- if (in == null) {
- if (!advance()) {
- return -1;
- }
- }
- int result = in.read(b, off, len);
- while ((result < 0) && advance()) {
- // return a new line at the end of every file <--Might create problems for some cases
- // depending on the parser implementation-->
- if ((lastByte != ExternalDataConstants.BYTE_LF) && (lastByte != ExternalDataConstants.BYTE_LF)) {
- lastByte = ExternalDataConstants.BYTE_LF;
- b[off] = ExternalDataConstants.BYTE_LF;
- return 1;
- }
- // recursive call
- result = in.read(b, off, len);
- }
- if (result > 0) {
- lastByte = b[(off + result) - 1];
- }
- return result;
- }
-
- @Override
public boolean stop() throws Exception {
closeFile();
watcher.close();
@@ -158,24 +127,44 @@
return false;
}
Throwable root = ExceptionUtils.getRootCause(th);
- if (root instanceof HyracksDataException
- && ((HyracksDataException) root).getErrorCode() == ErrorCode.RECORD_READER_MALFORMED_INPUT_STREAM) {
- if (currentFile != null) {
- try {
- logManager.logRecord(currentFile.getAbsolutePath(), "Corrupted input file");
- } catch (IOException e) {
- LOGGER.log(Level.WARN, "Filed to write to feed log file", e);
+ if (root instanceof HyracksDataException) {
+ HyracksDataException r = (HyracksDataException) root;
+ String component = r.getComponent();
+ if (ErrorCode.ASTERIX.equals(component)) {
+ int errorCode = r.getErrorCode();
+ switch (errorCode) {
+ case ErrorCode.RECORD_READER_MALFORMED_INPUT_STREAM:
+ if (currentFile != null) {
+ try {
+ logManager.logRecord(currentFile.getAbsolutePath(), "Corrupted input file");
+ } catch (IOException e) {
+ LOGGER.log(Level.WARN, "Filed to write to feed log file", e);
+ }
+ LOGGER.log(Level.WARN, "Corrupted input file: " + currentFile.getAbsolutePath());
+ }
+ case ErrorCode.INPUT_RECORD_READER_CHAR_ARRAY_RECORD_TOO_LARGE:
+ try {
+ advance();
+ return true;
+ } catch (Exception e) {
+ LOGGER.log(Level.WARN, "An exception was thrown while trying to skip a file", e);
+ }
+ default:
+ break;
}
- LOGGER.log(Level.WARN, "Corrupted input file: " + currentFile.getAbsolutePath());
- }
- try {
- advance();
- return true;
- } catch (Exception e) {
- LOGGER.log(Level.WARN, "An exception was thrown while trying to skip a file", e);
}
}
LOGGER.log(Level.WARN, "Failed to recover from failure", th);
return false;
}
+
+ @Override
+ public String getStreamName() {
+ return currentFile == null ? "" : currentFile.getPath();
+ }
+
+ @Override
+ public String getPreviousStreamName() {
+ return lastFileName;
+ }
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/operators/ExternalScanOperatorDescriptor.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/operators/ExternalScanOperatorDescriptor.java
index 4fd5151..1d7623d 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/operators/ExternalScanOperatorDescriptor.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/operators/ExternalScanOperatorDescriptor.java
@@ -26,6 +26,7 @@
import org.apache.hyracks.api.dataflow.value.RecordDescriptor;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.job.JobSpecification;
+import org.apache.hyracks.api.job.profiling.IOperatorStats;
import org.apache.hyracks.dataflow.std.base.AbstractSingleActivityOperatorDescriptor;
import org.apache.hyracks.dataflow.std.base.AbstractUnaryOutputSourceOperatorNodePushable;
@@ -53,13 +54,21 @@
return new AbstractUnaryOutputSourceOperatorNodePushable() {
+ private IOperatorStats stats;
+
@Override
public void initialize() throws HyracksDataException {
- IDataSourceAdapter adapter = null;
+ IDataSourceAdapter adapter;
+ if (ctx.getStatsCollector() != null) {
+ stats = ctx.getStatsCollector().getOrAddOperatorStats(getDisplayName());
+ }
try {
writer.open();
adapter = adapterFactory.createAdapter(ctx, partition);
adapter.start(partition, writer);
+ if (stats != null) {
+ stats.getTupleCounter().update(adapter.getProcessedTuples());
+ }
} catch (Exception e) {
writer.fail();
throw HyracksDataException.create(e);
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ADMDataParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ADMDataParser.java
index 42caf12..4a46717 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ADMDataParser.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ADMDataParser.java
@@ -74,8 +74,8 @@
private final TokenImage tmpTokenImage = new TokenImage();
- private final String mismatchErrorMessage = "Mismatch Type, expecting a value of type ";
- private final String mismatchErrorMessage2 = " got a value of type ";
+ private static final String mismatchErrorMessage = "Mismatch Type, expecting a value of type ";
+ private static final String mismatchErrorMessage2 = " got a value of type ";
public ADMDataParser(ARecordType recordType, boolean isStream) {
this(null, recordType, isStream);
@@ -103,11 +103,11 @@
}
@Override
- public void parse(IRawRecord<? extends char[]> record, DataOutput out) throws HyracksDataException {
+ public boolean parse(IRawRecord<? extends char[]> record, DataOutput out) throws HyracksDataException {
try {
resetPools();
admLexer.setBuffer(record.get());
- parseAdmInstance(recordType, out);
+ return parseAdmInstance(recordType, out);
} catch (ParseException e) {
e.setLocation(filename, admLexer.getLine(), admLexer.getColumn());
throw e;
@@ -121,7 +121,7 @@
admLexer = new AdmLexer(new java.io.InputStreamReader(in));
}
- protected boolean parseAdmInstance(IAType objectType, DataOutput out) throws IOException {
+ private boolean parseAdmInstance(IAType objectType, DataOutput out) throws IOException {
int token = admLexer.next();
if (token == AdmLexer.TOKEN_EOF) {
return false;
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/DelimitedDataParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/DelimitedDataParser.java
index 505acbd..60e6e77 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/DelimitedDataParser.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/DelimitedDataParser.java
@@ -18,10 +18,16 @@
*/
package org.apache.asterix.external.parser;
+import static org.apache.asterix.external.util.ExternalDataConstants.EMPTY_FIELD;
+import static org.apache.asterix.external.util.ExternalDataConstants.INVALID_VAL;
+import static org.apache.asterix.external.util.ExternalDataConstants.MISSING_FIELDS;
+
import java.io.DataOutput;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.util.function.LongSupplier;
+import java.util.function.Supplier;
import org.apache.asterix.builders.IARecordBuilder;
import org.apache.asterix.builders.RecordBuilder;
@@ -31,12 +37,17 @@
import org.apache.asterix.external.api.IRawRecord;
import org.apache.asterix.external.api.IRecordDataParser;
import org.apache.asterix.external.api.IStreamDataParser;
+import org.apache.asterix.external.util.ExternalDataConstants;
+import org.apache.asterix.external.util.ParseUtil;
import org.apache.asterix.om.base.AMutableString;
+import org.apache.asterix.om.typecomputer.impl.TypeComputeUtils;
import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.IAType;
import org.apache.asterix.om.utils.NonTaggedFormatUtil;
import org.apache.hyracks.api.context.IHyracksTaskContext;
import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
import org.apache.hyracks.dataflow.common.data.parsers.IValueParser;
import org.apache.hyracks.dataflow.common.data.parsers.IValueParserFactory;
@@ -44,7 +55,7 @@
public class DelimitedDataParser extends AbstractDataParser implements IStreamDataParser, IRecordDataParser<char[]> {
- private final IHyracksTaskContext ctx;
+ private final IWarningCollector warnings;
private final char fieldDelimiter;
private final char quote;
private final boolean hasHeader;
@@ -54,13 +65,19 @@
private final DataOutput fieldValueBufferOutput;
private final IValueParser[] valueParsers;
private FieldCursorForDelimitedDataParser cursor;
+ private Supplier<String> dataSourceName;
+ private LongSupplier lineNumber;
private final byte[] fieldTypeTags;
private final int[] fldIds;
private final ArrayBackedValueStorage[] nameBuffers;
+ private final char[] nullChars;
public DelimitedDataParser(IHyracksTaskContext ctx, IValueParserFactory[] valueParserFactories, char fieldDelimiter,
- char quote, boolean hasHeader, ARecordType recordType, boolean isStreamParser) throws HyracksDataException {
- this.ctx = ctx;
+ char quote, boolean hasHeader, ARecordType recordType, boolean isStreamParser, String nullString)
+ throws HyracksDataException {
+ this.dataSourceName = ExternalDataConstants.EMPTY_STRING;
+ this.lineNumber = ExternalDataConstants.NO_LINES;
+ this.warnings = ctx.getWarningCollector();
this.fieldDelimiter = fieldDelimiter;
this.quote = quote;
this.hasHeader = hasHeader;
@@ -100,17 +117,23 @@
}
}
if (!isStreamParser) {
- cursor = new FieldCursorForDelimitedDataParser(null, this.fieldDelimiter, quote);
+ cursor = new FieldCursorForDelimitedDataParser(null, this.fieldDelimiter, quote, warnings,
+ this::getDataSourceName);
}
+ this.nullChars = nullString != null ? nullString.toCharArray() : null;
}
@Override
public boolean parse(DataOutput out) throws HyracksDataException {
try {
- while (cursor.nextRecord()) {
- parseRecord();
- recBuilder.write(out, true);
- return true;
+ if (cursor.nextRecord()) {
+ if (parseRecord()) {
+ recBuilder.write(out, true);
+ return true;
+ } else {
+ // keeping the behaviour of throwing exception for stream parsers
+ throw new RuntimeDataException(ErrorCode.FAILED_TO_PARSE_RECORD);
+ }
}
return false;
} catch (IOException e) {
@@ -118,39 +141,53 @@
}
}
- private void parseRecord() throws HyracksDataException {
+ private boolean parseRecord() throws HyracksDataException {
recBuilder.reset(recordType);
recBuilder.init();
for (int i = 0; i < valueParsers.length; ++i) {
try {
- if (!cursor.nextField()) {
- break;
+ FieldCursorForDelimitedDataParser.Result result = cursor.nextField();
+ switch (result) {
+ case OK:
+ break;
+ case END:
+ if (warnings.shouldWarn()) {
+ ParseUtil.warn(warnings, dataSourceName.get(), cursor.getLineCount(),
+ cursor.getFieldCount(), MISSING_FIELDS);
+ }
+ return false;
+ case ERROR:
+ return false;
+ default:
+ throw new IllegalStateException();
}
- } catch (IOException e) {
- throw HyracksDataException.create(e);
- }
- fieldValueBuffer.reset();
+ fieldValueBuffer.reset();
- try {
- if (cursor.isFieldEmpty() && recordType.getFieldTypes()[i].getTypeTag() != ATypeTag.STRING
- && recordType.getFieldTypes()[i].getTypeTag() != ATypeTag.NULL) {
- // if the field is empty and the type is optional, insert
- // NULL. Note that string type can also process empty field as an
- // empty string
- if (!NonTaggedFormatUtil.isOptional(recordType.getFieldTypes()[i])) {
- throw new RuntimeDataException(ErrorCode.PARSER_DELIMITED_NONOPTIONAL_NULL,
- cursor.getRecordCount(), cursor.getFieldCount());
- }
+ if (nullChars != null && NonTaggedFormatUtil.isOptional(recordType.getFieldTypes()[i]) && fieldNull()) {
fieldValueBufferOutput.writeByte(ATypeTag.SERIALIZED_NULL_TYPE_TAG);
} else {
+ if (cursor.isFieldEmpty() && !canProcessEmptyField(recordType.getFieldTypes()[i])) {
+ if (warnings.shouldWarn()) {
+ ParseUtil.warn(warnings, dataSourceName.get(), cursor.getLineCount(),
+ cursor.getFieldCount(), EMPTY_FIELD);
+ }
+ return false;
+ }
fieldValueBufferOutput.writeByte(fieldTypeTags[i]);
// Eliminate double quotes in the field that we are going to parse
if (cursor.fieldHasDoubleQuote()) {
cursor.eliminateDoubleQuote();
}
- valueParsers[i].parse(cursor.getBuffer(), cursor.getFieldStart(), cursor.getFieldLength(),
- fieldValueBufferOutput);
+ boolean success = valueParsers[i].parse(cursor.getBuffer(), cursor.getFieldStart(),
+ cursor.getFieldLength(), fieldValueBufferOutput);
+ if (!success) {
+ if (warnings.shouldWarn()) {
+ ParseUtil.warn(warnings, dataSourceName.get(), cursor.getLineCount(),
+ cursor.getFieldCount(), INVALID_VAL);
+ }
+ return false;
+ }
}
if (fldIds[i] < 0) {
recBuilder.addField(nameBuffers[i], fieldValueBuffer);
@@ -161,32 +198,81 @@
throw HyracksDataException.create(e);
}
}
- if (valueParsers.length != cursor.getFieldCount()) {
- throw new HyracksDataException("Record #" + cursor.getRecordCount() + " is missing some fields");
+ try {
+ while (cursor.nextField() == FieldCursorForDelimitedDataParser.Result.OK) {
+ // keep reading and discarding the extra fields
+ }
+ return true;
+ } catch (IOException e) {
+ throw HyracksDataException.create(e);
}
}
@Override
- public void parse(IRawRecord<? extends char[]> record, DataOutput out) throws HyracksDataException {
- cursor.nextRecord(record.get(), record.size());
- parseRecord();
- recBuilder.write(out, true);
+ public boolean parse(IRawRecord<? extends char[]> record, DataOutput out) throws HyracksDataException {
+ cursor.nextRecord(record.get(), record.size(), lineNumber.getAsLong());
+ if (parseRecord()) {
+ recBuilder.write(out, true);
+ return true;
+ }
+ return false;
}
@Override
public void setInputStream(InputStream in) throws IOException {
- cursor = new FieldCursorForDelimitedDataParser(new InputStreamReader(in), fieldDelimiter, quote);
- if (in != null && hasHeader) {
+ // TODO(ali): revisit this in regards to stream
+ cursor = new FieldCursorForDelimitedDataParser(new InputStreamReader(in), fieldDelimiter, quote, warnings,
+ this::getDataSourceName);
+ if (hasHeader) {
cursor.nextRecord();
- while (cursor.nextField()) {
- ;
+ FieldCursorForDelimitedDataParser.Result result;
+ do {
+ result = cursor.nextField();
+ } while (result == FieldCursorForDelimitedDataParser.Result.OK);
+ if (result == FieldCursorForDelimitedDataParser.Result.ERROR) {
+ throw new RuntimeDataException(ErrorCode.FAILED_TO_PARSE_RECORD);
}
}
}
@Override
public boolean reset(InputStream in) throws IOException {
- cursor = new FieldCursorForDelimitedDataParser(new InputStreamReader(in), fieldDelimiter, quote);
+ // TODO(ali): revisit this in regards to stream
+ cursor = new FieldCursorForDelimitedDataParser(new InputStreamReader(in), fieldDelimiter, quote, warnings,
+ this::getDataSourceName);
+ return true;
+ }
+
+ @Override
+ public void configure(Supplier<String> dataSourceName, LongSupplier lineNumber) {
+ this.dataSourceName = dataSourceName == null ? ExternalDataConstants.EMPTY_STRING : dataSourceName;
+ this.lineNumber = lineNumber == null ? ExternalDataConstants.NO_LINES : lineNumber;
+
+ }
+
+ private String getDataSourceName() {
+ return dataSourceName.get();
+ }
+
+ private static boolean canProcessEmptyField(IAType fieldType) {
+ IAType type = TypeComputeUtils.getActualType(fieldType);
+ // TODO(ali): investigate what it means for a field to have type NULL. there is no parser implemented for it
+ return type.getTypeTag() == ATypeTag.STRING || type.getTypeTag() == ATypeTag.NULL;
+ }
+
+ private boolean fieldNull() {
+ int fieldLength = cursor.getFieldLength();
+ int nullStringLength = nullChars.length;
+ if (fieldLength != nullStringLength) {
+ return false;
+ }
+ char[] fieldChars = cursor.getBuffer();
+ int fieldStart = cursor.getFieldStart();
+ for (int i = 0; i < fieldLength; i++) {
+ if (fieldChars[fieldStart + i] != nullChars[i]) {
+ return false;
+ }
+ }
return true;
}
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/HiveRecordParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/HiveRecordParser.java
index 1a88d08..9ab6c7d 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/HiveRecordParser.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/HiveRecordParser.java
@@ -110,7 +110,7 @@
}
@Override
- public void parse(IRawRecord<? extends Writable> record, DataOutput out) throws HyracksDataException {
+ public boolean parse(IRawRecord<? extends Writable> record, DataOutput out) throws HyracksDataException {
try {
Writable hiveRawRecord = record.get();
Object hiveObject = hiveSerde.deserialize(hiveRawRecord);
@@ -129,6 +129,7 @@
recBuilder.addField(i, fieldValueBuffer);
}
recBuilder.write(out, true);
+ return true;
} catch (Exception e) {
throw HyracksDataException.create(e);
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/JSONDataParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/JSONDataParser.java
index 72f86c1..3216aef 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/JSONDataParser.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/JSONDataParser.java
@@ -90,13 +90,14 @@
*/
@Override
- public final void parse(IRawRecord<? extends char[]> record, DataOutput out) throws HyracksDataException {
+ public final boolean parse(IRawRecord<? extends char[]> record, DataOutput out) throws HyracksDataException {
try {
//TODO(wyk): find a way to reset byte[] instead of creating a new parser for each record.
jsonParser = jsonFactory.createParser(record.get(), 0, record.size());
geometryCoParser.reset(jsonParser);
nextToken();
parseObject(rootType, out);
+ return true;
} catch (IOException e) {
throw new RuntimeDataException(ErrorCode.RECORD_READER_MALFORMED_INPUT_STREAM, e);
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/RSSParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/RSSParser.java
index e260083..84a2d90 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/RSSParser.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/RSSParser.java
@@ -48,7 +48,7 @@
}
@Override
- public void parse(IRawRecord<? extends SyndEntry> record, DataOutput out) throws HyracksDataException {
+ public boolean parse(IRawRecord<? extends SyndEntry> record, DataOutput out) throws HyracksDataException {
SyndEntry entry = record.get();
tupleFieldValues[0] = String.valueOf(id);
tupleFieldValues[1] = entry.getTitle();
@@ -62,5 +62,6 @@
recordBuilder.init();
IDataParser.writeRecord(mutableRecord, out, recordBuilder);
id++;
+ return true;
}
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/RecordWithMetadataParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/RecordWithMetadataParser.java
index 6c9298e..820775c 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/RecordWithMetadataParser.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/RecordWithMetadataParser.java
@@ -20,6 +20,8 @@
import java.io.DataOutput;
import java.io.IOException;
+import java.util.function.LongSupplier;
+import java.util.function.Supplier;
import org.apache.asterix.builders.RecordBuilder;
import org.apache.asterix.external.api.IDataParser;
@@ -72,14 +74,15 @@
}
@Override
- public void parse(IRawRecord<? extends T> record, DataOutput out) throws HyracksDataException {
+ public boolean parse(IRawRecord<? extends T> record, DataOutput out) throws HyracksDataException {
try {
rwm = converter.convert(record);
if (rwm.getRecord().size() == 0) {
// null record
out.writeByte(ATypeTag.SERIALIZED_MISSING_TYPE_TAG);
+ return true;
} else {
- recordParser.parse(rwm.getRecord(), out);
+ return recordParser.parse(rwm.getRecord(), out);
}
} catch (IOException e) {
throw HyracksDataException.create(e);
@@ -110,4 +113,10 @@
public void appendLastParsedPrimaryKeyToTuple(ArrayTupleBuilder tb) throws HyracksDataException {
rwm.appendPrimaryKeyToTuple(tb);
}
+
+ @Override
+ public void configure(Supplier<String> dataSourceName, LongSupplier lineNumber) {
+ this.recordParser.configure(dataSourceName, lineNumber);
+ this.converter.configure(lineNumber);
+ }
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/RecordWithPKDataParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/RecordWithPKDataParser.java
index aa0db53..8c00a9f 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/RecordWithPKDataParser.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/RecordWithPKDataParser.java
@@ -37,15 +37,16 @@
}
@Override
- public void parse(IRawRecord<? extends T> record, DataOutput out) throws HyracksDataException {
+ public boolean parse(IRawRecord<? extends T> record, DataOutput out) throws HyracksDataException {
if (record.size() == 0) {
try {
out.writeByte(ATypeTag.SERIALIZED_NULL_TYPE_TAG);
+ return true;
} catch (IOException e) {
throw HyracksDataException.create(e);
}
} else {
- recordParser.parse(record, out);
+ return recordParser.parse(record, out);
}
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java
index 1cbf0be..4726a50 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java
@@ -259,12 +259,13 @@
}
@Override
- public void parse(IRawRecord<? extends char[]> record, DataOutput out) throws HyracksDataException {
+ public boolean parse(IRawRecord<? extends char[]> record, DataOutput out) throws HyracksDataException {
try {
//TODO get rid of this temporary json
resetPools();
ObjectMapper om = new ObjectMapper();
writeRecord(om.readTree(record.getBytes()), out, recordType);
+ return true;
} catch (IOException e) {
throw HyracksDataException.create(e);
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/factory/DelimitedDataParserFactory.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/factory/DelimitedDataParserFactory.java
index 46c5152..09f9697 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/factory/DelimitedDataParserFactory.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/factory/DelimitedDataParserFactory.java
@@ -50,8 +50,9 @@
char delimiter = ExternalDataUtils.validateGetDelimiter(configuration);
char quote = ExternalDataUtils.validateGetQuote(configuration, delimiter);
boolean hasHeader = ExternalDataUtils.hasHeader(configuration);
+ String nullString = configuration.get(ExternalDataConstants.KEY_NULL_STR);
return new DelimitedDataParser(ctx, valueParserFactories, delimiter, quote, hasHeader, recordType,
- ExternalDataUtils.getDataSourceType(configuration).equals(DataSourceType.STREAM));
+ ExternalDataUtils.getDataSourceType(configuration).equals(DataSourceType.STREAM), nullString);
}
@Override
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/factory/RecordWithMetadataParserFactory.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/factory/RecordWithMetadataParserFactory.java
index 704ea29..f940f3d 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/factory/RecordWithMetadataParserFactory.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/factory/RecordWithMetadataParserFactory.java
@@ -99,7 +99,7 @@
@Override
public IRecordDataParser<I> createRecordParser(IHyracksTaskContext ctx) throws HyracksDataException {
IRecordDataParser<O> recordParser = recordParserFactory.createRecordParser(ctx);
- return new RecordWithMetadataParser<I, O>(metaType, recordParser, converterFactory.createConverter());
+ return new RecordWithMetadataParser<I, O>(metaType, recordParser, converterFactory.createConverter(ctx));
}
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/provider/DataflowControllerProvider.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/provider/DataflowControllerProvider.java
index f9b012e..f60ecdc 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/provider/DataflowControllerProvider.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/provider/DataflowControllerProvider.java
@@ -54,6 +54,9 @@
public class DataflowControllerProvider {
+ private DataflowControllerProvider() {
+ }
+
// TODO: Instead, use a factory just like data source and data parser.
@SuppressWarnings({ "rawtypes", "unchecked" })
public static IDataFlowController getDataflowController(ARecordType recordType, IHyracksTaskContext ctx,
@@ -67,6 +70,8 @@
IRecordReader<?> recordReader = recordReaderFactory.createRecordReader(ctx, partition);
IRecordDataParserFactory<?> recordParserFactory = (IRecordDataParserFactory<?>) dataParserFactory;
IRecordDataParser<?> dataParser = recordParserFactory.createRecordParser(ctx);
+ // TODO(ali): revisit to think about passing data source name via setter or via createRecordParser
+ dataParser.configure(recordReader.getDataSourceName(), recordReader.getLineNumber());
if (indexingOp) {
return new IndexingDataFlowController(ctx, dataParser, recordReader,
((IIndexingDatasource) recordReader).getIndexer());
@@ -96,6 +101,7 @@
IInputStreamFactory streamFactory = (IInputStreamFactory) dataSourceFactory;
AsterixInputStream stream = streamFactory.createInputStream(ctx, partition);
IStreamDataParserFactory streamParserFactory = (IStreamDataParserFactory) dataParserFactory;
+ // TODO(ali): revisit to think about passing data source name to parser
IStreamDataParser streamParser = streamParserFactory.createInputStreamParser(ctx, partition);
streamParser.setInputStream(stream);
if (isFeed) {
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataConstants.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataConstants.java
index a05ad77..63f57b6 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataConstants.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataConstants.java
@@ -21,6 +21,8 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
+import java.util.function.LongSupplier;
+import java.util.function.Supplier;
public class ExternalDataConstants {
@@ -70,7 +72,7 @@
public static final String KEY_LOCAL_SOCKET_PATH = "local-socket-path";
public static final String KEY_FORMAT = "format";
public static final String KEY_QUOTE = "quote";
- public static final String KEY_QUOTE_ESCAPE = "quote-escape";
+ public static final String KEY_ESCAPE = "escape";
public static final String KEY_PARSER = "parser";
public static final String KEY_DATASET_RECORD = "dataset-record";
public static final String KEY_HIVE_SERDE = "hive-serde";
@@ -110,6 +112,9 @@
public static final String KEY_HTTP_PROXY_PORT = "http-proxy-port";
public static final String KEY_HTTP_PROXY_USER = "http-proxy-user";
public static final String KEY_HTTP_PROXY_PASSWORD = "http-proxy-password";
+ // a string representing the NULL value
+ public static final String KEY_NULL_STR = "null";
+ public static final String KEY_REDACT_WARNINGS = "redact-warnings";
/**
* Keys for adapter name
@@ -231,6 +236,9 @@
public static final char CR = '\r';
public static final char DEFAULT_RECORD_START = '{';
public static final char DEFAULT_RECORD_END = '}';
+ public static final char OPEN_BRACKET = '[';
+ public static final char CLOSING_BRACKET = ']';
+ public static final char COMMA = ',';
/**
* Constant byte characters
@@ -245,6 +253,9 @@
public static final int DEFAULT_QUEUE_SIZE = 64;
public static final int MAX_RECORD_SIZE = 32000000;
+ public static final Supplier<String> EMPTY_STRING = () -> "";
+ public static final LongSupplier NO_LINES = () -> -1;
+
/**
* Expected parameter values
*/
@@ -260,11 +271,18 @@
public static final String READER_RSS = "rss_feed";
public static final String ERROR_PARSE_RECORD = "Parser failed to parse record";
+ public static final String MISSING_FIELDS = "some fields are missing";
+ public static final String REC_ENDED_AT_EOF = "malformed input record ended abruptly";
+ public static final String EMPTY_FIELD = "empty value";
+ public static final String INVALID_VAL = "invalid value";
public static class AwsS3Constants {
+ private AwsS3Constants() {
+ }
+
public static final String REGION_FIELD_NAME = "region";
- public static final String ACCESS_KEY_FIELD_NAME = "accessKey";
- public static final String SECRET_KEY_FIELD_NAME = "secretKey";
+ public static final String ACCESS_KEY_ID_FIELD_NAME = "accessKeyId";
+ public static final String SECRET_ACCESS_KEY_FIELD_NAME = "secretAccessKey";
public static final String CONTAINER_NAME_FIELD_NAME = "container";
public static final String DEFINITION_FIELD_NAME = "definition";
public static final String SERVICE_END_POINT_FIELD_NAME = "serviceEndpoint";
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataUtils.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataUtils.java
index 652eae5..2bb9077 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataUtils.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataUtils.java
@@ -18,6 +18,13 @@
*/
package org.apache.asterix.external.util;
+import static org.apache.asterix.external.util.ExternalDataConstants.KEY_DELIMITER;
+import static org.apache.asterix.external.util.ExternalDataConstants.KEY_ESCAPE;
+import static org.apache.asterix.external.util.ExternalDataConstants.KEY_QUOTE;
+import static org.apache.asterix.external.util.ExternalDataConstants.KEY_RECORD_END;
+import static org.apache.asterix.external.util.ExternalDataConstants.KEY_RECORD_START;
+import static org.apache.asterix.external.util.ExternalDataConstants.KEY_REDACT_WARNINGS;
+
import java.util.EnumMap;
import java.util.Map;
@@ -63,34 +70,27 @@
// Get a delimiter from the given configuration
public static char validateGetDelimiter(Map<String, String> configuration) throws HyracksDataException {
- String delimiterValue = configuration.get(ExternalDataConstants.KEY_DELIMITER);
- if (delimiterValue == null) {
- return ExternalDataConstants.DEFAULT_DELIMITER.charAt(0);
- }
- validateDelimiter(delimiterValue);
- return delimiterValue.charAt(0);
+ return validateCharOrDefault(configuration, KEY_DELIMITER, ExternalDataConstants.DEFAULT_DELIMITER.charAt(0));
}
// Get a quote from the given configuration when the delimiter is given
// Need to pass delimiter to check whether they share the same character
public static char validateGetQuote(Map<String, String> configuration, char delimiter) throws HyracksDataException {
- String quoteValue = configuration.get(ExternalDataConstants.KEY_QUOTE);
- if (quoteValue == null) {
- return ExternalDataConstants.DEFAULT_QUOTE.charAt(0);
- }
- validateQuote(quoteValue);
- char quote = quoteValue.charAt(0);
+ char quote = validateCharOrDefault(configuration, KEY_QUOTE, ExternalDataConstants.DEFAULT_QUOTE.charAt(0));
validateDelimiterAndQuote(delimiter, quote);
return quote;
}
- public static char validateGetQuoteEscape(Map<String, String> configuration) throws HyracksDataException {
- String quoteEscapeValue = configuration.get(ExternalDataConstants.KEY_QUOTE_ESCAPE);
- if (quoteEscapeValue == null) {
- return ExternalDataConstants.ESCAPE;
- }
- validateQuoteEscape(quoteEscapeValue);
- return quoteEscapeValue.charAt(0);
+ public static char validateGetEscape(Map<String, String> configuration) throws HyracksDataException {
+ return validateCharOrDefault(configuration, KEY_ESCAPE, ExternalDataConstants.ESCAPE);
+ }
+
+ public static char validateGetRecordStart(Map<String, String> configuration) throws HyracksDataException {
+ return validateCharOrDefault(configuration, KEY_RECORD_START, ExternalDataConstants.DEFAULT_RECORD_START);
+ }
+
+ public static char validateGetRecordEnd(Map<String, String> configuration) throws HyracksDataException {
+ return validateCharOrDefault(configuration, KEY_RECORD_END, ExternalDataConstants.DEFAULT_RECORD_END);
}
public static void validateDataParserParameters(Map<String, String> configuration) throws AsterixException {
@@ -193,11 +193,12 @@
}
public static boolean hasHeader(Map<String, String> configuration) {
- String value = configuration.get(ExternalDataConstants.KEY_HEADER);
- if (value != null) {
- return Boolean.valueOf(value);
- }
- return false;
+ return isTrue(configuration, ExternalDataConstants.KEY_HEADER);
+ }
+
+ public static boolean isTrue(Map<String, String> configuration, String key) {
+ String value = configuration.get(key);
+ return value == null ? false : Boolean.valueOf(value);
}
public static IRecordReaderFactory<?> createExternalRecordReaderFactory(ILibraryManager libraryManager,
@@ -339,13 +340,13 @@
if (format != null) {
// default quote, escape character for quote and fields delimiter for csv and tsv format
if (format.equals(ExternalDataConstants.FORMAT_CSV)) {
- configuration.putIfAbsent(ExternalDataConstants.KEY_DELIMITER, ExternalDataConstants.DEFAULT_DELIMITER);
- configuration.putIfAbsent(ExternalDataConstants.KEY_QUOTE, ExternalDataConstants.DEFAULT_QUOTE);
- configuration.putIfAbsent(ExternalDataConstants.KEY_QUOTE_ESCAPE, ExternalDataConstants.DEFAULT_QUOTE);
+ configuration.putIfAbsent(KEY_DELIMITER, ExternalDataConstants.DEFAULT_DELIMITER);
+ configuration.putIfAbsent(KEY_QUOTE, ExternalDataConstants.DEFAULT_QUOTE);
+ configuration.putIfAbsent(KEY_ESCAPE, ExternalDataConstants.DEFAULT_QUOTE);
} else if (format.equals(ExternalDataConstants.FORMAT_TSV)) {
- configuration.putIfAbsent(ExternalDataConstants.KEY_DELIMITER, ExternalDataConstants.TAB_STR);
- configuration.putIfAbsent(ExternalDataConstants.KEY_QUOTE, ExternalDataConstants.NULL_STR);
- configuration.putIfAbsent(ExternalDataConstants.KEY_QUOTE_ESCAPE, ExternalDataConstants.NULL_STR);
+ configuration.putIfAbsent(KEY_DELIMITER, ExternalDataConstants.TAB_STR);
+ configuration.putIfAbsent(KEY_QUOTE, ExternalDataConstants.NULL_STR);
+ configuration.putIfAbsent(KEY_ESCAPE, ExternalDataConstants.NULL_STR);
}
}
}
@@ -406,7 +407,11 @@
}
char delimiter = validateGetDelimiter(configuration);
validateGetQuote(configuration, delimiter);
- validateGetQuoteEscape(configuration);
+ validateGetEscape(configuration);
+ String value = configuration.get(KEY_REDACT_WARNINGS);
+ if (value != null && !isBoolean(value)) {
+ throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, KEY_REDACT_WARNINGS, value);
+ }
}
private static boolean isHeaderRequiredFor(String format) {
@@ -417,31 +422,25 @@
return value.equals(ExternalDataConstants.TRUE) || value.equals(ExternalDataConstants.FALSE);
}
- private static void validateDelimiter(String delimiter) throws RuntimeDataException {
- if (delimiter.length() != 1) {
- throw new RuntimeDataException(ErrorCode.PARSER_FACTORY_DELIMITED_DATA_PARSER_FACTORY_NOT_VALID_DELIMITER,
- delimiter);
- }
- }
-
- public static void validateQuote(String quote) throws RuntimeDataException {
- if (quote.length() != 1) {
- throw new RuntimeDataException(ErrorCode.PARSER_INVALID_CHAR_LENGTH, quote,
- ExternalDataConstants.KEY_QUOTE);
- }
- }
-
- private static void validateQuoteEscape(String quoteEsc) throws RuntimeDataException {
- if (quoteEsc.length() != 1) {
- throw new RuntimeDataException(ErrorCode.PARSER_INVALID_CHAR_LENGTH, quoteEsc,
- ExternalDataConstants.KEY_QUOTE_ESCAPE);
- }
- }
-
private static void validateDelimiterAndQuote(char delimiter, char quote) throws RuntimeDataException {
if (quote == delimiter) {
- throw new RuntimeDataException(
- ErrorCode.PARSER_FACTORY_DELIMITED_DATA_PARSER_FACTORY_QUOTE_DELIMITER_MISMATCH, quote, delimiter);
+ throw new RuntimeDataException(ErrorCode.QUOTE_DELIMITER_MISMATCH, quote, delimiter);
+ }
+ }
+
+ private static char validateCharOrDefault(Map<String, String> configuration, String key, char defaultValue)
+ throws HyracksDataException {
+ String value = configuration.get(key);
+ if (value == null) {
+ return defaultValue;
+ }
+ validateChar(value, key);
+ return value.charAt(0);
+ }
+
+ public static void validateChar(String parameterValue, String parameterName) throws RuntimeDataException {
+ if (parameterValue.length() != 1) {
+ throw new RuntimeDataException(ErrorCode.INVALID_CHAR_LENGTH, parameterValue, parameterName);
}
}
}
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ParseUtil.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ParseUtil.java
new file mode 100644
index 0000000..598d9ff
--- /dev/null
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ParseUtil.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package org.apache.asterix.external.util;
+
+import org.apache.hyracks.api.exceptions.ErrorCode;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.api.exceptions.Warning;
+
+public class ParseUtil {
+
+ private static final SourceLocation SRC_LOC = new SourceLocation(-1, -1);
+
+ private ParseUtil() {
+ }
+
+ public static void warn(IWarningCollector warningCollector, String dataSourceName, long lineNum, int fieldNum,
+ String warnMessage) {
+ warningCollector.warn(
+ Warning.forHyracks(SRC_LOC, ErrorCode.PARSING_ERROR, dataSourceName, lineNum, fieldNum, warnMessage));
+ }
+}
diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/TestRecordWithPKParser.java b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/TestRecordWithPKParser.java
index dad9cfd..925eeee 100644
--- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/TestRecordWithPKParser.java
+++ b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/TestRecordWithPKParser.java
@@ -36,9 +36,9 @@
}
@Override
- public void parse(final IRawRecord<? extends RecordWithPK<T>> record, final DataOutput out)
+ public boolean parse(final IRawRecord<? extends RecordWithPK<T>> record, final DataOutput out)
throws HyracksDataException {
- recordParser.parse(record.get().getRecord(), out);
+ return recordParser.parse(record.get().getRecord(), out);
}
@Override
diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/RecordWithMetaTest.java b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/RecordWithMetaTest.java
index 47c6ffe..888de08 100644
--- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/RecordWithMetaTest.java
+++ b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/RecordWithMetaTest.java
@@ -95,8 +95,9 @@
LineRecordReader lineReader = new LineRecordReader();
lineReader.configure(ctx, inputStream, config);
// create csv with json record reader
- CSVToRecordWithMetadataAndPKConverter recordConverter = new CSVToRecordWithMetadataAndPKConverter(
- valueIndex, delimiter, metaType, recordType, pkIndicators, pkIndexes, keyTypes);
+ CSVToRecordWithMetadataAndPKConverter recordConverter =
+ new CSVToRecordWithMetadataAndPKConverter(valueIndex, delimiter, metaType, recordType, pkIndicators,
+ pkIndexes, keyTypes, ctx.getWarningCollector());
// create the value parser <ADM in this case>
ADMDataParser valueParser = new ADMDataParser(recordType, false);
// create parser.
@@ -124,14 +125,14 @@
while (lineReader.hasNext()) {
IRawRecord<char[]> record = lineReader.next();
tb.reset();
- parser.parse(record, tb.getDataOutput());
- tb.addFieldEndOffset();
- parser.parseMeta(tb.getDataOutput());
- tb.addFieldEndOffset();
- parser.appendLastParsedPrimaryKeyToTuple(tb);
- //print tuple
- printTuple(tb, printers, printStream);
-
+ if (parser.parse(record, tb.getDataOutput())) {
+ tb.addFieldEndOffset();
+ parser.parseMeta(tb.getDataOutput());
+ tb.addFieldEndOffset();
+ parser.appendLastParsedPrimaryKeyToTuple(tb);
+ //print tuple
+ printTuple(tb, printers, printStream);
+ }
}
lineReader.close();
printStream.close();
diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/TweetParserTest.java b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/TweetParserTest.java
index e183a84..b39ca45 100644
--- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/TweetParserTest.java
+++ b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/TweetParserTest.java
@@ -72,7 +72,9 @@
for (int iter1 = 0; iter1 < lines.size(); iter1++) {
record.set(lines.get(iter1));
try {
- parser.parse(record, output);
+ if (!parser.parse(record, output)) {
+ Assert.fail("Unexpected failure in parser.");
+ }
} catch (HyracksDataException e) {
e.printStackTrace();
Assert.fail("Unexpected failure in parser.");
@@ -98,8 +100,9 @@
for (int iter1 = 0; iter1 < lines.size(); iter1++) {
record.set(lines.get(iter1));
try {
- parser.parse(record, output);
- regularCount++;
+ if (parser.parse(record, output)) {
+ regularCount++;
+ }
} catch (HyracksDataException e) {
Assert.assertTrue(e.toString().contains("Non-null") && (iter1 == 0 || iter1 == 1));
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
index 1085e03..e7104dd 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
@@ -67,6 +67,9 @@
// Generate ids for variables (considering scopes) and replace global variable access with the dataset function.
variableCheckAndRewrite();
+ // Extracts SQL-92 aggregate functions from CASE/IF expressions into LET clauses
+ rewriteCaseExpressions();
+
// Rewrites SQL-92 global aggregations.
rewriteGroupByAggregationSugar();
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
index e52d604..1ccea2a 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
@@ -64,6 +64,7 @@
import org.apache.asterix.lang.sqlpp.rewrites.visitor.OperatorExpressionVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.SetOperationVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppBuiltinFunctionRewriteVisitor;
+import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppCaseRewriteVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppGroupByAggregationSugarVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppGroupByVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppGroupingSetsVisitor;
@@ -152,10 +153,13 @@
// Generate ids for variables (considering scopes) and replace global variable access with the dataset function.
variableCheckAndRewrite();
+ // Extracts SQL-92 aggregate functions from CASE/IF expressions into LET clauses
+ rewriteCaseExpressions();
+
// Rewrites SQL-92 aggregate functions
rewriteGroupByAggregationSugar();
- // Rewrite window expression aggregations.
+ // Rewrites window expression aggregations.
rewriteWindowAggregationSugar();
// Rewrites like/not-like expressions.
@@ -263,6 +267,11 @@
rewriteTopExpr(windowVisitor, null);
}
+ protected void rewriteCaseExpressions() throws CompilationException {
+ SqlppCaseRewriteVisitor visitor = new SqlppCaseRewriteVisitor(context);
+ rewriteTopExpr(visitor, null);
+ }
+
protected void inlineDeclaredUdfs(boolean inlineUdfs) throws CompilationException {
List<FunctionSignature> funIds = new ArrayList<FunctionSignature>();
for (FunctionDecl fdecl : declaredFunctions) {
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/AbstractSqlppExpressionExtractionVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/AbstractSqlppExpressionExtractionVisitor.java
index fc2e25b..6b57089 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/AbstractSqlppExpressionExtractionVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/AbstractSqlppExpressionExtractionVisitor.java
@@ -23,22 +23,27 @@
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
+import java.util.function.Predicate;
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.lang.common.base.AbstractClause;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.ILangExpression;
+import org.apache.asterix.lang.common.clause.GroupbyClause;
import org.apache.asterix.lang.common.clause.LetClause;
import org.apache.asterix.lang.common.expression.VariableExpr;
import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
import org.apache.asterix.lang.common.struct.VarIdentifier;
import org.apache.asterix.lang.sqlpp.clause.FromClause;
import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
+import org.apache.asterix.lang.sqlpp.clause.SelectClause;
import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppSimpleExpressionVisitor;
import org.apache.hyracks.algebricks.common.utils.Pair;
/**
* Base class for visitors that extract expressions into LET clauses.
+ * Subclasses should call {@link #extractExpressionsFromList(List, int, Predicate)} or
+ * {@link #extractExpression(Expression)} to perform the extraction.
*/
abstract class AbstractSqlppExpressionExtractionVisitor extends AbstractSqlppSimpleExpressionVisitor {
@@ -56,33 +61,62 @@
stack.push(stackElement);
if (selectBlock.hasFromClause()) {
- FromClause clause = selectBlock.getFromClause();
- clause.accept(this, arg);
- if (!stackElement.extractionList.isEmpty()) {
- handleUnsupportedClause(clause);
- }
+ visitFromClause(selectBlock.getFromClause(), arg, stackElement);
}
List<AbstractClause> letWhereList = selectBlock.getLetWhereList();
if (!letWhereList.isEmpty()) {
- visitLetWhereClauses(letWhereList, stackElement.extractionList, arg);
+ visitLetWhereClauses(letWhereList, arg, stackElement.extractionList);
}
+ GroupbyClause groupbyClause = null;
if (selectBlock.hasGroupbyClause()) {
- selectBlock.getGroupbyClause().accept(this, arg);
- introduceLetClauses(stackElement.extractionList, letWhereList);
+ groupbyClause = selectBlock.getGroupbyClause();
+ visitGroupByClause(groupbyClause, arg, stackElement.extractionList, letWhereList);
}
List<AbstractClause> letHavingListAfterGby = selectBlock.getLetHavingListAfterGroupby();
if (!letHavingListAfterGby.isEmpty()) {
- visitLetWhereClauses(letHavingListAfterGby, stackElement.extractionList, arg);
+ visitLetHavingClausesAfterGby(arg, stackElement.extractionList, letHavingListAfterGby, groupbyClause);
}
- selectBlock.getSelectClause().accept(this, arg);
- introduceLetClauses(stackElement.extractionList,
- selectBlock.hasGroupbyClause() ? letHavingListAfterGby : letWhereList);
+ visitSelectClause(selectBlock.getSelectClause(), arg, stackElement.extractionList,
+ selectBlock.hasGroupbyClause() ? letHavingListAfterGby : letWhereList, groupbyClause);
stack.pop();
return null;
}
- private void visitLetWhereClauses(List<AbstractClause> clauseList,
+ protected void visitFromClause(FromClause clause, ILangExpression arg, StackElement stackElement)
+ throws CompilationException {
+ clause.accept(this, arg);
+ if (!stackElement.extractionList.isEmpty()) {
+ handleUnsupportedClause(clause);
+ }
+ }
+
+ protected void visitLetWhereClauses(List<AbstractClause> letWhereList, ILangExpression arg,
+ List<Pair<Expression, VarIdentifier>> extractionList) throws CompilationException {
+ visitLetWhereClausesImpl(letWhereList, extractionList, arg);
+ }
+
+ protected void visitGroupByClause(GroupbyClause groupbyClause, ILangExpression arg,
+ List<Pair<Expression, VarIdentifier>> extractionList, List<AbstractClause> letWhereList)
+ throws CompilationException {
+ groupbyClause.accept(this, arg);
+ introduceLetClauses(extractionList, letWhereList);
+ }
+
+ protected void visitLetHavingClausesAfterGby(ILangExpression arg,
+ List<Pair<Expression, VarIdentifier>> extractionList, List<AbstractClause> letHavingListAfterGby,
+ GroupbyClause groupbyClause) throws CompilationException {
+ visitLetWhereClausesImpl(letHavingListAfterGby, extractionList, arg);
+ }
+
+ protected void visitSelectClause(SelectClause selectClause, ILangExpression arg,
+ List<Pair<Expression, VarIdentifier>> extractionList, List<AbstractClause> letWhereList,
+ GroupbyClause groupbyClause) throws CompilationException {
+ selectClause.accept(this, arg);
+ introduceLetClauses(extractionList, letWhereList);
+ }
+
+ private void visitLetWhereClausesImpl(List<AbstractClause> clauseList,
List<Pair<Expression, VarIdentifier>> extractionList, ILangExpression arg) throws CompilationException {
List<AbstractClause> newClauseList = new ArrayList<>(clauseList.size());
for (AbstractClause letWhereClause : clauseList) {
@@ -108,13 +142,42 @@
fromBindingList.clear();
}
+ protected List<Expression> extractExpressionsFromList(List<Expression> exprList, int limit,
+ Predicate<Expression> exprTest) {
+ StackElement outElement = stack.peek();
+ if (outElement == null) {
+ return null;
+ }
+ int n = exprList.size();
+ List<Expression> newExprList = new ArrayList<>(n);
+ for (int i = 0; i < n; i++) {
+ Expression expr = exprList.get(i);
+ Expression newExpr = i < limit && exprTest.test(expr) ? extractExpressionImpl(expr, outElement) : expr;
+ newExprList.add(newExpr);
+ }
+ return newExprList;
+ }
+
+ protected Expression extractExpression(Expression expr) {
+ StackElement outLetList = stack.peek();
+ return outLetList != null ? extractExpressionImpl(expr, outLetList) : null;
+ }
+
+ private VariableExpr extractExpressionImpl(Expression expr, StackElement outElement) {
+ VarIdentifier v = context.newVariable();
+ VariableExpr vExpr = new VariableExpr(v);
+ vExpr.setSourceLocation(expr.getSourceLocation());
+ outElement.extractionList.add(new Pair<>(expr, v));
+ return vExpr;
+ }
+
abstract void handleUnsupportedClause(FromClause clause) throws CompilationException;
protected final class StackElement {
private final SelectBlock selectBlock;
- private final List<Pair<Expression, VarIdentifier>> extractionList;
+ protected final List<Pair<Expression, VarIdentifier>> extractionList;
private StackElement(SelectBlock selectBlock) {
this.selectBlock = selectBlock;
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppCaseRewriteVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppCaseRewriteVisitor.java
new file mode 100644
index 0000000..24a9c1f
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppCaseRewriteVisitor.java
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+package org.apache.asterix.lang.sqlpp.rewrites.visitor;
+
+import java.util.List;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.lang.common.base.AbstractClause;
+import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.base.ILangExpression;
+import org.apache.asterix.lang.common.clause.GroupbyClause;
+import org.apache.asterix.lang.common.expression.CallExpr;
+import org.apache.asterix.lang.common.expression.IfExpr;
+import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
+import org.apache.asterix.lang.common.struct.VarIdentifier;
+import org.apache.asterix.lang.sqlpp.clause.FromClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
+import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
+import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
+import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppSimpleExpressionVisitor;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+
+/**
+ * Extracts SQL-92 aggregate functions from CASE/IF expressions into LET clauses,
+ * so they can be pushed into GROUPBY subplans by the optimizer.
+ */
+public final class SqlppCaseRewriteVisitor extends AbstractSqlppExpressionExtractionVisitor {
+
+ public SqlppCaseRewriteVisitor(LangRewritingContext context) {
+ super(context);
+ }
+
+ @Override
+ protected void visitLetWhereClauses(List<AbstractClause> letWhereList, ILangExpression arg,
+ List<Pair<Expression, VarIdentifier>> extractionList) {
+ // do not perform the extraction
+ }
+
+ @Override
+ protected void visitGroupByClause(GroupbyClause groupbyClause, ILangExpression arg,
+ List<Pair<Expression, VarIdentifier>> extractionList, List<AbstractClause> letWhereList) {
+ // do not perform the extraction
+ }
+
+ @Override
+ public Expression visit(CaseExpression caseExpr, ILangExpression arg) throws CompilationException {
+ Expression resultExpr = super.visit(caseExpr, arg);
+ resultExpr.accept(new Sql92AggregateExtractionVisitor(), arg);
+ return resultExpr;
+ }
+
+ @Override
+ public Expression visit(IfExpr ifExpr, ILangExpression arg) throws CompilationException {
+ Expression resultExpr = super.visit(ifExpr, arg);
+ resultExpr.accept(new Sql92AggregateExtractionVisitor(), arg);
+ return resultExpr;
+ }
+
+ @Override
+ void handleUnsupportedClause(FromClause clause) throws CompilationException {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_USE_OF_IDENTIFIER, clause.getSourceLocation(),
+ BuiltinFunctions.SWITCH_CASE.getName());
+ }
+
+ private final class Sql92AggregateExtractionVisitor extends AbstractSqlppSimpleExpressionVisitor {
+
+ @Override
+ public Expression visit(CallExpr callExpr, ILangExpression arg) throws CompilationException {
+ CallExpr resultExpr = (CallExpr) super.visit(callExpr, arg);
+ if (FunctionMapUtil.isSql92AggregateFunction(resultExpr.getFunctionSignature())) {
+ Expression newExpr = extractExpression(resultExpr);
+ if (newExpr != null) {
+ return newExpr;
+ }
+ }
+ return resultExpr;
+ }
+
+ @Override
+ public Expression visit(SelectExpression selectExpression, ILangExpression arg) {
+ // don't visit sub-queries
+ return selectExpression;
+ }
+ }
+}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowRewriteVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowRewriteVisitor.java
index 5c20bec..cbc3ac9 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowRewriteVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowRewriteVisitor.java
@@ -53,6 +53,16 @@
}
@Override
+ protected void visitFromClause(FromClause clause, ILangExpression arg, StackElement stackElement)
+ throws CompilationException {
+ clause.accept(this, arg);
+ if (!stackElement.extractionList.isEmpty()) {
+ throw new CompilationException(ErrorCode.COMPILATION_UNEXPECTED_WINDOW_EXPRESSION,
+ clause.getSourceLocation());
+ }
+ }
+
+ @Override
public Expression visit(WindowExpression winExpr, ILangExpression arg) throws CompilationException {
super.visit(winExpr, arg);
@@ -68,14 +78,16 @@
rewriteSpecificWindowFunctions(winfi, winExpr);
if (BuiltinFunctions.builtinFunctionHasProperty(winfi,
BuiltinFunctions.WindowFunctionProperty.HAS_LIST_ARG)) {
- List<Expression> newExprList = extractExpressions(winExpr.getExprList(), 1);
+ List<Expression> newExprList = extractExpressionsFromList(winExpr.getExprList(), 1,
+ SqlppWindowRewriteVisitor::isExtractableExpression);
if (newExprList == null) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, winExpr.getSourceLocation(), "");
}
winExpr.setExprList(newExprList);
}
} else if (FunctionMapUtil.isSql92AggregateFunction(signature)) {
- List<Expression> newExprList = extractExpressions(winExpr.getExprList(), winExpr.getExprList().size());
+ List<Expression> newExprList = extractExpressionsFromList(winExpr.getExprList(),
+ winExpr.getExprList().size(), SqlppWindowRewriteVisitor::isExtractableExpression);
if (newExprList == null) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, winExpr.getSourceLocation(), "");
}
@@ -111,7 +123,7 @@
return newExprList;
}
- private boolean isExtractableExpression(Expression expr) {
+ protected static boolean isExtractableExpression(Expression expr) {
switch (expr.getKind()) {
case LITERAL_EXPRESSION:
case VARIABLE_EXPRESSION:
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADateParserFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADateParserFactory.java
index ed118f9..35691a1 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADateParserFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADateParserFactory.java
@@ -43,9 +43,10 @@
return new IValueParser() {
@Override
- public void parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
+ public boolean parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
try {
out.writeInt((int) (parseDatePart(buffer, start, length) / GregorianCalendarSystem.CHRONON_OF_DAY));
+ return true;
} catch (IOException ex) {
throw HyracksDataException.create(ex);
}
@@ -56,11 +57,11 @@
/**
* Parse the given char sequence as a date string, and return the milliseconds represented by the date.
*
- * @param charAccessor
+ * @param dateString
* accessor for the char sequence
- * @param isDateOnly
+ * @param start
* indicating whether it is a single date string, or it is the date part of a datetime string
- * @param errorMessage
+ * @param length
* @return
* @throws Exception
*/
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADateTimeParserFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADateTimeParserFactory.java
index 2e32692..f9e53b9 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADateTimeParserFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADateTimeParserFactory.java
@@ -43,7 +43,7 @@
return new IValueParser() {
@Override
- public void parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
+ public boolean parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
long chrononTimeInMs = 0;
short timeOffset = (short) ((buffer[start] == '-') ? 1 : 0);
@@ -64,6 +64,7 @@
try {
out.writeLong(chrononTimeInMs);
+ return true;
} catch (IOException ex) {
throw HyracksDataException.create(ex);
}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADurationParserFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADurationParserFactory.java
index 66fb4c3..ec387e2 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADurationParserFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADurationParserFactory.java
@@ -52,11 +52,12 @@
return new IValueParser() {
@Override
- public void parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
+ public boolean parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
parseDuration(buffer, start, length, aMutableDuration, ADurationParseOption.All);
try {
out.writeInt(aMutableDuration.getMonths());
out.writeLong(aMutableDuration.getMilliseconds());
+ return true;
} catch (IOException ex) {
throw HyracksDataException.create(ex);
}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ATimeParserFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ATimeParserFactory.java
index 40ddc55..039e026 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ATimeParserFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ATimeParserFactory.java
@@ -43,9 +43,10 @@
return new IValueParser() {
@Override
- public void parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
+ public boolean parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
try {
out.writeInt(parseTimePart(buffer, start, length));
+ return true;
} catch (IOException ex) {
throw HyracksDataException.create(ex);
}
@@ -318,7 +319,7 @@
*
* @param timeString
* @param start
- * @param length
+ *
* @return
* @throws HyracksDataException
*/
@@ -473,7 +474,7 @@
*
* @param timeString
* @param start
- * @param length
+ *
* @return
* @throws HyracksDataException
*/
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/ABinaryHexStringConstructorDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/ABinaryHexStringConstructorDescriptor.java
index 3d65b0b..505b650 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/ABinaryHexStringConstructorDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/ABinaryHexStringConstructorDescriptor.java
@@ -111,7 +111,10 @@
utf8Ptr.set(inputArg.getByteArray(), startOffset + 1, len - 1);
char[] buffer = utf8Ptr.toString().toCharArray();
out.write(ATypeTag.BINARY.serialize());
- byteArrayParser.parse(buffer, 0, buffer.length, out);
+ if (!byteArrayParser.parse(buffer, 0, buffer.length, out)) {
+ PointableHelper.setNull(result);
+ return;
+ }
result.set(resultStorage);
} else {
throw new TypeMismatchException(sourceLoc, BuiltinFunctions.BINARY_HEX_CONSTRUCTOR, 0, tt,
diff --git a/asterixdb/asterix-server/pom.xml b/asterixdb/asterix-server/pom.xml
index b794d73..0db37fc 100644
--- a/asterixdb/asterix-server/pom.xml
+++ b/asterixdb/asterix-server/pom.xml
@@ -178,6 +178,30 @@
<url>https://raw.githubusercontent.com/reactive-streams/reactive-streams-jvm/v1.0.2/LICENSE.txt</url>
</override>
<override>
+ <gavs>
+ <gav>software.amazon.awssdk:sdk-core:2.10.83</gav>
+ <gav>software.amazon.awssdk:aws-core:2.10.83</gav>
+ <gav>software.amazon.awssdk:auth:2.10.83</gav>
+ <gav>software.amazon.awssdk:arns:2.10.83</gav>
+ <gav>software.amazon.awssdk:annotations:2.10.83</gav>
+ <gav>software.amazon.awssdk:utils:2.10.83</gav>
+ <gav>software.amazon.awssdk:aws-query-protocol:2.10.83</gav>
+ <gav>software.amazon.awssdk:profiles:2.10.83</gav>
+ <gav>software.amazon.awssdk:protocol-core:2.10.83</gav>
+ <gav>software.amazon.awssdk:s3:2.10.83</gav>
+ <gav>software.amazon.awssdk:netty-nio-client:2.10.83</gav>
+ <gav>software.amazon.awssdk:apache-client:2.10.83</gav>
+ <gav>software.amazon.awssdk:aws-xml-protocol:2.10.83</gav>
+ <gav>software.amazon.awssdk:regions:2.10.83</gav>
+ <gav>software.amazon.awssdk:http-client-spi:2.10.83</gav>
+ </gavs>
+ <noticeUrl>https://raw.githubusercontent.com/aws/aws-sdk-java-v2/2.10.83/NOTICE.txt</noticeUrl>
+ </override>
+ <override>
+ <gav>software.amazon.eventstream:eventstream:1.0.1</gav>
+ <noticeUrl>https://raw.githubusercontent.com/awslabs/aws-eventstream-java/7be2dd80e12f8835674c8ffb0f4a2efb64c7b585/NOTICE</noticeUrl>
+ </override>
+ <override>
<gav>org.mindrot:jbcrypt:0.4</gav>
<url>http://www.mindrot.org/files/jBCrypt/LICENSE</url>
</override>
diff --git a/asterixdb/pom.xml b/asterixdb/pom.xml
index ece4b12..bb3a018 100644
--- a/asterixdb/pom.xml
+++ b/asterixdb/pom.xml
@@ -264,10 +264,49 @@
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-enforcer-plugin</artifactId>
- <version>3.0.0-M1</version>
+ <artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
+ <id>check-pom-packaging</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <exportAntProperties>true</exportAntProperties>
+ <target xmlns:unless="ant:unless">
+ <condition property="skipPomEnforcement">
+ <not><equals arg1="${project.packaging}" arg2="pom"/></not>
+ </condition>
+ <echo message="will enforce non-existence of test source dir due to ${project.packaging} packaging" unless:set="skipPomEnforcement"/>
+ </target>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>ensure-no-tests-for-pom-packaging</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <configuration>
+ <rules>
+ <requireFilesDontExist>
+ <files>
+ <file>${project.build.testSourceDirectory}</file>
+ </files>
+ <message>#### Tests cannot exist in projects with '${project.packaging}' packaging!</message>
+ </requireFilesDontExist>
+ </rules>
+ <skip>${skipPomEnforcement}</skip>
+ </configuration>
+ </execution>
+ <execution>
<id>enforce-versions</id>
<goals>
<goal>enforce</goal>
@@ -615,19 +654,6 @@
</properties>
</profile>
<profile>
- <id>skip-dashboard</id>
- <activation>
- <property>
- <name>skip.npm</name>
- <value>true</value>
- </property>
- </activation>
- <properties>
- <license.stage>none</license.stage>
- <resource.stage>none</resource.stage>
- </properties>
- </profile>
- <profile>
<id>python-udfs</id>
<activation>
<file>
diff --git a/asterixdb/src/main/appended-resources/supplemental-models.xml b/asterixdb/src/main/appended-resources/supplemental-models.xml
index 2d74604..060ce3a 100644
--- a/asterixdb/src/main/appended-resources/supplemental-models.xml
+++ b/asterixdb/src/main/appended-resources/supplemental-models.xml
@@ -271,6 +271,233 @@
</properties>
</project>
</supplement>
+
+ <!-- AWS SDK begin -->
+ <!-- software.amazon.awssdk is ALv2, and does not contain any embedded LICENSE or NOTICE file -->
+ <!-- license override not needed, ALv2 is specified in its pom.xml -->
+ <!-- see https://github.com/aws/aws-sdk-java-v2/blob/master/LICENSE.txt -->
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>sdk-core</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>aws-core</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>s3</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>auth</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>protocol-core</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>regions</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>arns</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>netty-nio-client</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>aws-xml-protocol</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>annotations</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>apache-client</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>utils</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>http-client-spi</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>aws-query-protocol</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <supplement>
+ <project>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>profiles</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.10.83</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.10.83</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>2.10.83</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+
+ <!-- software.amazon.eventstream is ALv2, and does not contain any embedded LICENSE or NOTICE file -->
+ <!-- license override not needed, ALv2 is specified in its pom.xml -->
+ <!-- see https://github.com/awslabs/aws-eventstream-java -->
+ <supplement>
+ <project>
+ <groupId>software.amazon.eventstream</groupId>
+ <artifactId>eventstream</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>1.0.1</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>1.0.1</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreNoticeOverride>1.0.1</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+ <!-- AWS SDK end -->
+
+ <!-- com.typesafe.netty is ALv2, and does not contain any embedded LICENSE or NOTICE file -->
+ <!-- license override not needed, ALv2 is specified in its pom.xml -->
+ <!-- see https://github.com/playframework/netty-reactive-streams -->
+ <supplement>
+ <project>
+ <groupId>com.typesafe.netty</groupId>
+ <artifactId>netty-reactive-streams</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.0.4</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.0.4</license.ignoreMissingEmbeddedNotice>
+ </properties>
+ </project>
+ </supplement>
+
+ <supplement>
+ <project>
+ <groupId>com.typesafe.netty</groupId>
+ <artifactId>netty-reactive-streams-http</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>2.0.4</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>2.0.4</license.ignoreMissingEmbeddedNotice>
+ </properties>
+ </project>
+ </supplement>
+
+ <!-- org.reactivestreams does not contain any embedded LICENSE or NOTICE file -->
+ <!-- see https://github.com/reactive-streams/reactive-streams-jvm -->
+ <supplement>
+ <project>
+ <groupId>org.reactivestreams</groupId>
+ <artifactId>reactive-streams</artifactId>
+ <properties>
+ <license.ignoreMissingEmbeddedLicense>1.0.2</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>1.0.2</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreLicenseOverride>1.0.2</license.ignoreLicenseOverride>
+ <license.ignoreNoticeOverride>1.0.2</license.ignoreNoticeOverride>
+ </properties>
+ </project>
+ </supplement>
+
<supplement>
<project>
<groupId>org.mindrot</groupId>
diff --git a/asterixdb/src/main/licenses/content/raw.githubusercontent.com_aws_aws-sdk-java-v2_2.10.83_NOTICE.txt b/asterixdb/src/main/licenses/content/raw.githubusercontent.com_aws_aws-sdk-java-v2_2.10.83_NOTICE.txt
new file mode 100644
index 0000000..f3c67c6
--- /dev/null
+++ b/asterixdb/src/main/licenses/content/raw.githubusercontent.com_aws_aws-sdk-java-v2_2.10.83_NOTICE.txt
@@ -0,0 +1,16 @@
+AWS SDK for Java 2.0
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+This product includes software developed by
+Amazon Technologies, Inc (http://www.amazon.com/).
+
+**********************
+THIRD PARTY COMPONENTS
+**********************
+This software includes third party software subject to the following copyrights:
+- XML parsing and utility functions from JetS3t - Copyright 2006-2009 James Murty.
+- PKCS#1 PEM encoded private key parsing and utility functions from oauth.googlecode.com - Copyright 1998-2010 AOL Inc.
+- Apache Commons Lang - https://github.com/apache/commons-lang
+- Netty Reactive Streams - https://github.com/playframework/netty-reactive-streams
+
+The licenses for these third party components are included in LICENSE.txt
\ No newline at end of file
diff --git a/asterixdb/src/main/licenses/content/raw.githubusercontent.com_awslabs_aws-eventstream-java_7be2dd80e12f8835674c8ffb0f4a2efb64c7b585_NOTICE.txt b/asterixdb/src/main/licenses/content/raw.githubusercontent.com_awslabs_aws-eventstream-java_7be2dd80e12f8835674c8ffb0f4a2efb64c7b585_NOTICE.txt
new file mode 100644
index 0000000..6822ad6
--- /dev/null
+++ b/asterixdb/src/main/licenses/content/raw.githubusercontent.com_awslabs_aws-eventstream-java_7be2dd80e12f8835674c8ffb0f4a2efb64c7b585_NOTICE.txt
@@ -0,0 +1,2 @@
+AWS EventStream for Java
+Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\ No newline at end of file
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/AbstractIntroduceGroupByCombinerRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/AbstractIntroduceGroupByCombinerRule.java
index d9746b2..6c42929 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/AbstractIntroduceGroupByCombinerRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/AbstractIntroduceGroupByCombinerRule.java
@@ -171,6 +171,9 @@
// Nothing is pushed.
if (bi.modifyGbyMap.isEmpty()) {
+ // Reset the group-by operator with original nested plans.
+ gbyNestedPlans.clear();
+ gbyNestedPlans.addAll(backupNestedPlans);
return null;
}
@@ -188,6 +191,9 @@
LogicalVariable v2 = newOpGbyList.get(i);
if (v != v2) {
// cannot linearize
+ // Reset the group-by operator with original nested plans.
+ gbyNestedPlans.clear();
+ gbyNestedPlans.addAll(backupNestedPlans);
return null;
}
} else {
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PushSelectIntoJoinRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PushSelectIntoJoinRule.java
index d0cd006..5f66c2f 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PushSelectIntoJoinRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PushSelectIntoJoinRule.java
@@ -150,18 +150,24 @@
if (!intersectsBranch[0] && !intersectsBranch[1]) {
return false;
}
+ boolean planChanged;
if (needToPushOps) {
//We should push independent ops into the first branch that the selection depends on
- if (intersectsBranch[0]) {
- pushOps(pushedOnEither, joinBranchLeftRef, context);
- } else {
- pushOps(pushedOnEither, joinBranchRightRef, context);
- }
- pushOps(pushedOnLeft, joinBranchLeftRef, context);
- pushOps(pushedOnRight, joinBranchRightRef, context);
+ planChanged =
+ pushOps(pushedOnEither, intersectsBranch[0] ? joinBranchLeftRef : joinBranchRightRef, context);
+ planChanged |= pushOps(pushedOnLeft, joinBranchLeftRef, context);
+ planChanged |= pushOps(pushedOnRight, joinBranchRightRef, context);
+ } else {
+ planChanged = false;
}
if (intersectsAllBranches) {
- addCondToJoin(select, join, context);
+ // add condition to the join condition only if we have IJ
+ if (isLoj) {
+ notPushedStack.addFirst(select);
+ } else {
+ addCondToJoin(select, join, context);
+ planChanged = true;
+ }
} else { // push down
Iterator<Mutable<ILogicalOperator>> branchIter = join.getInputs().iterator();
ILogicalExpression selectCondition = select.getCondition().getValue();
@@ -172,20 +178,20 @@
if (!inter) {
continue;
}
-
- // if a left outer join, if the select condition is not-missing filtering,
- // we rewrite left outer join
- // to inner join for this case.
- if (j > 0 && isLoj && containsNotMissingFiltering(selectCondition)) {
- lojToInner = true;
- }
- if ((j > 0 && isLoj) && containsMissingFiltering(selectCondition)) {
- // Select "is-not-missing($$var)" cannot be pushed in the right branch of a LOJ;
+ if (j > 0 && isLoj) {
+ // if a LOJ and the select condition is not-missing filtering,
+ // we rewrite LOJ to IJ for this case.
+ if (containsNotMissingFiltering(selectCondition)) {
+ lojToInner = true;
+ }
+ // Do not push conditions into the right branch of a LOJ;
notPushedStack.addFirst(select);
} else {
- // Conditions for the left branch can always be pushed.
- // Other conditions can be pushed to the right branch of a LOJ.
+ // Conditions for the left branch for IJ/LOJ or
+ // for the right branch of IJ can always be pushed into that branch.
+ // We don't push conditions into the right branch of LOJ at this point.
copySelectToBranch(select, branch, context);
+ planChanged = true;
}
}
if (lojToInner) {
@@ -194,23 +200,47 @@
innerJoin.getInputs().addAll(join.getInputs());
join = innerJoin;
context.computeAndSetTypeEnvironmentForOperator(join);
+ planChanged = true;
}
}
- ILogicalOperator top = join;
- for (ILogicalOperator npOp : notPushedStack) {
- List<Mutable<ILogicalOperator>> npInpList = npOp.getInputs();
- npInpList.clear();
- npInpList.add(new MutableObject<ILogicalOperator>(top));
- context.computeAndSetTypeEnvironmentForOperator(npOp);
- top = npOp;
- }
- opRef.setValue(top);
- return true;
+ planChanged |= applyNonPushed(opRef, notPushedStack, join, context);
+ return planChanged;
}
- private void pushOps(List<ILogicalOperator> opList, Mutable<ILogicalOperator> joinBranch,
+ private boolean applyNonPushed(Mutable<ILogicalOperator> opRef, LinkedList<ILogicalOperator> notPushedStack,
+ ILogicalOperator top, IOptimizationContext context) throws AlgebricksException {
+ switch (notPushedStack.size()) {
+ case 0:
+ if (opRef.getValue() == top) {
+ return false;
+ }
+ opRef.setValue(top);
+ return true;
+ case 1:
+ ILogicalOperator notPushedOp = notPushedStack.peek();
+ if (opRef.getValue() == notPushedOp && opRef.getValue().getInputs().get(0).getValue() == top) {
+ return false;
+ }
+ // fall thru to 'default'
+ default:
+ for (ILogicalOperator npOp : notPushedStack) {
+ List<Mutable<ILogicalOperator>> npInpList = npOp.getInputs();
+ npInpList.clear();
+ npInpList.add(new MutableObject<>(top));
+ context.computeAndSetTypeEnvironmentForOperator(npOp);
+ top = npOp;
+ }
+ opRef.setValue(top);
+ return true;
+ }
+ }
+
+ private boolean pushOps(List<ILogicalOperator> opList, Mutable<ILogicalOperator> joinBranch,
IOptimizationContext context) throws AlgebricksException {
+ if (opList.isEmpty()) {
+ return false;
+ }
ILogicalOperator topOp = joinBranch.getValue();
ListIterator<ILogicalOperator> iter = opList.listIterator(opList.size());
while (iter.hasPrevious()) {
@@ -222,6 +252,7 @@
context.computeAndSetTypeEnvironmentForOperator(op);
}
joinBranch.setValue(topOp);
+ return true;
}
private static void addCondToJoin(SelectOperator select, AbstractBinaryJoinOperator join,
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
index 38f49dc..16ba168 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
@@ -157,6 +157,7 @@
public static final int NUMERIC_PROMOTION_ERROR = 121;
public static final int ERROR_PRINTING_PLAN = 122;
public static final int INSUFFICIENT_MEMORY = 123;
+ public static final int PARSING_ERROR = 124;
// Compilation error codes.
public static final int RULECOLLECTION_NOT_INSTANCE_OF_LIST = 10000;
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/CleanupUtils.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/CleanupUtils.java
index 6e6d342..220311e 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/CleanupUtils.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/CleanupUtils.java
@@ -96,7 +96,9 @@
} catch (Throwable loggingFailure) { // NOSONAR: Ignore catching Throwable
// NOSONAR ignore logging failure
}
- root.addSuppressed(th);
+ if (root != null) {
+ root.addSuppressed(th);
+ }
}
}
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/HyracksThrowingConsumer.java
similarity index 77%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/HyracksThrowingConsumer.java
index 6e31eb3..b677132 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/HyracksThrowingConsumer.java
@@ -16,7 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.hyracks.api.util;
-USE test;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+@FunctionalInterface
+public interface HyracksThrowingConsumer<V> {
+ void process(V value) throws HyracksDataException;
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties b/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
index 87b963a..ec536c0 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
@@ -140,6 +140,7 @@
121 = A numeric type promotion error has occurred: %1$s
122 = Encountered an error while printing the plan
123 = Insufficient memory is provided for the join operators, please increase the join memory budget.
+124 = Parsing error at %1$s line %2$s field %3$s: %4$s
10000 = The given rule collection %1$s is not an instance of the List class.
10001 = Cannot compose partition constraint %1$s with %2$s
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/BooleanParserFactory.java b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/BooleanParserFactory.java
index 488be04..141b99f 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/BooleanParserFactory.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/BooleanParserFactory.java
@@ -37,26 +37,43 @@
return BooleanParserFactory::parse;
}
- public static void parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
- try {
- if (length == 4 && (buffer[start] == 't' || buffer[start] == 'T')
- && (buffer[start + 1] == 'r' || buffer[start + 1] == 'R')
- && (buffer[start + 2] == 'u' || buffer[start + 2] == 'U')
- && (buffer[start + 3] == 'e' || buffer[start + 3] == 'E')) {
- out.writeBoolean(true);
- return;
- } else if (length == 5 && (buffer[start] == 'f' || buffer[start] == 'F')
- && (buffer[start + 1] == 'a' || buffer[start + 1] == 'A')
- && (buffer[start + 2] == 'l' || buffer[start + 2] == 'L')
- && (buffer[start + 3] == 's' || buffer[start + 3] == 'S')
- && (buffer[start + 4] == 'e' || buffer[start + 4] == 'E')) {
- out.writeBoolean(false);
- return;
+ public static boolean parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
+ char ch;
+ int i = start;
+ int end = start + length;
+ while (i < end && ((ch = buffer[i]) == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '\f')) {
+ i++;
+ }
+ int remainingLength = end - i;
+ boolean gotBoolean = false;
+ boolean booleanValue = false;
+ if (remainingLength >= 4 && ((ch = buffer[i]) == 't' || ch == 'T') && ((ch = buffer[i + 1]) == 'r' || ch == 'R')
+ && ((ch = buffer[i + 2]) == 'u' || ch == 'U') && ((ch = buffer[i + 3]) == 'e' || ch == 'E')) {
+ gotBoolean = true;
+ booleanValue = true;
+ i = i + 4;
+ } else if (remainingLength >= 5 && ((ch = buffer[i]) == 'f' || ch == 'F')
+ && ((ch = buffer[i + 1]) == 'a' || ch == 'A') && ((ch = buffer[i + 2]) == 'l' || ch == 'L')
+ && ((ch = buffer[i + 3]) == 's' || ch == 'S') && ((ch = buffer[i + 4]) == 'e' || ch == 'E')) {
+ gotBoolean = true;
+ booleanValue = false;
+ i = i + 5;
+ }
+
+ for (; i < end; ++i) {
+ ch = buffer[i];
+ if (ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r' && ch != '\f') {
+ return false;
}
+ }
+ if (!gotBoolean) {
+ return false;
+ }
+ try {
+ out.writeBoolean(booleanValue);
+ return true;
} catch (IOException e) {
throw HyracksDataException.create(e);
}
-
- throw new HyracksDataException("Invalid input data");
}
}
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayBase64ParserFactory.java b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayBase64ParserFactory.java
index 69db7f3..cc5b68c 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayBase64ParserFactory.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayBase64ParserFactory.java
@@ -41,11 +41,12 @@
ByteArraySerializerDeserializer serializer = ByteArraySerializerDeserializer.INSTANCE;
@Override
- public void parse(char[] input, int start, int length, DataOutput out) throws HyracksDataException {
+ public boolean parse(char[] input, int start, int length, DataOutput out) throws HyracksDataException {
parser.generatePureByteArrayFromBase64String(input, start, length);
try {
serializer.serialize(parser.getByteArray(), 0, parser.getLength(), out);
+ return true;
} catch (IOException e) {
throw HyracksDataException.create(e);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayHexParserFactory.java b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayHexParserFactory.java
index c15b2ff..2191c75 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayHexParserFactory.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayHexParserFactory.java
@@ -40,10 +40,11 @@
ByteArraySerializerDeserializer serializer = ByteArraySerializerDeserializer.INSTANCE;
@Override
- public void parse(char[] input, int start, int length, DataOutput out) throws HyracksDataException {
+ public boolean parse(char[] input, int start, int length, DataOutput out) throws HyracksDataException {
try {
parser.generateByteArrayFromHexString(input, start, length);
serializer.serialize(parser.getByteArray(), 0, parser.getLength(), out);
+ return true;
} catch (IOException e) {
throw HyracksDataException.create(e);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/DoubleParserFactory.java b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/DoubleParserFactory.java
index 8998798..2004397 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/DoubleParserFactory.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/DoubleParserFactory.java
@@ -35,12 +35,13 @@
public IValueParser createValueParser() {
return new IValueParser() {
@Override
- public void parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
+ public boolean parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
String s = String.valueOf(buffer, start, length);
try {
out.writeDouble(Double.parseDouble(s));
+ return true;
} catch (NumberFormatException e) {
- throw HyracksDataException.create(e);
+ return false;
} catch (IOException e) {
throw HyracksDataException.create(e);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/FloatParserFactory.java b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/FloatParserFactory.java
index 414946c..2b476f1 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/FloatParserFactory.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/FloatParserFactory.java
@@ -35,12 +35,13 @@
public IValueParser createValueParser() {
return new IValueParser() {
@Override
- public void parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
+ public boolean parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
String s = String.valueOf(buffer, start, length);
try {
out.writeFloat(Float.parseFloat(s));
+ return true;
} catch (NumberFormatException e) {
- throw HyracksDataException.create(e);
+ return false;
} catch (IOException e) {
throw HyracksDataException.create(e);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/IValueParser.java b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/IValueParser.java
index 0fcfa90..7b0090a 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/IValueParser.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/IValueParser.java
@@ -23,5 +23,5 @@
import org.apache.hyracks.api.exceptions.HyracksDataException;
public interface IValueParser {
- void parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException;
+ boolean parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException;
}
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/IntegerParserFactory.java b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/IntegerParserFactory.java
index c6cffb4..450aa70 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/IntegerParserFactory.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/IntegerParserFactory.java
@@ -35,91 +35,61 @@
public IValueParser createValueParser() {
return new IValueParser() {
@Override
- public void parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
- int n = 0;
- int sign = 1;
- int i = 0;
- boolean pre = true;
- for (; pre && i < length; ++i) {
- char ch = buffer[i + start];
- switch (ch) {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- case '\f':
- break;
-
- case '-':
- sign = -1;
- pre = false;
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- pre = false;
- n = n * 10 + (ch - '0');
- break;
-
- default:
- String errorString = new String(buffer, i + start, length - i);
- throw new HyracksDataException(
- "Integer Parser - a digit is expected. But, encountered this character: " + ch
- + " in the incoming input: " + errorString);
+ public boolean parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
+ // accumulating negatively like Integer.parse() to avoid surprises near MAX_VALUE
+ char c;
+ int i = start;
+ int end = start + length;
+ while (i < end && ((c = buffer[i]) == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f')) {
+ i++;
+ }
+ boolean negative = false;
+ int limit = -Integer.MAX_VALUE;
+ if (i < end) {
+ c = buffer[i];
+ if (c == '-') {
+ negative = true;
+ limit = Integer.MIN_VALUE;
+ i++;
+ }
+ if (c == '+') {
+ i++;
}
}
- boolean post = false;
- for (; !post && i < length; ++i) {
- char ch = buffer[i + start];
- switch (ch) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- n = n * 10 + (ch - '0');
- break;
- default:
- String errorString = new String(buffer, i + start, length - i);
- throw new HyracksDataException(
- "Integer Parser - a digit is expected. But, encountered this character: " + ch
- + " in the incoming input: " + errorString);
+ int result = 0;
+ int multiplicationMin = limit / 10;
+ boolean gotNumber = false;
+ for (; i < end; i++) {
+ c = buffer[i];
+ if (c >= '0' && c <= '9') {
+ gotNumber = true;
+ if (result < multiplicationMin) {
+ return false;
+ }
+ result *= 10;
+ int digit = c - '0';
+ if (result < limit + digit) {
+ return false;
+ }
+ result -= digit;
+ } else {
+ break;
}
}
- for (; i < length; ++i) {
- char ch = buffer[i + start];
- switch (ch) {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- case '\f':
- break;
-
- default:
- String errorString = new String(buffer, i + start, length - i);
- throw new HyracksDataException("Integer Parser - a whitespace, tab, new line, or "
- + "form-feed expected. But, encountered this character: " + ch
- + " in the incoming input: " + errorString);
+ for (; i < end; ++i) {
+ c = buffer[i];
+ if (c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != '\f') {
+ return false;
}
}
+ if (!gotNumber) {
+ return false;
+ }
try {
- out.writeInt(n * sign);
+ out.writeInt(negative ? result : -result);
+ return true;
} catch (IOException e) {
throw HyracksDataException.create(e);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/LongParserFactory.java b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/LongParserFactory.java
index fd47475..2cd350c 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/LongParserFactory.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/LongParserFactory.java
@@ -35,92 +35,61 @@
public IValueParser createValueParser() {
return new IValueParser() {
@Override
- public void parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
- long n = 0;
- int sign = 1;
- int i = 0;
- boolean pre = true;
- for (; pre && i < length; ++i) {
- char ch = buffer[i + start];
- switch (ch) {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- case '\f':
- break;
-
- case '-':
- sign = -1;
- pre = false;
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- pre = false;
- n = n * 10 + (ch - '0');
- break;
-
- default:
- String errorString = new String(buffer, i + start, length - i);
- throw new HyracksDataException(
- "Long Parser - a digit is expected. But, encountered this character: " + ch
- + " in the incoming input: " + errorString);
+ public boolean parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
+ // accumulating negatively like Long.parse() to avoid surprises near MAX_VALUE
+ char c;
+ int i = start;
+ int end = start + length;
+ while (i < end && ((c = buffer[i]) == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f')) {
+ i++;
+ }
+ boolean negative = false;
+ long limit = -Long.MAX_VALUE;
+ if (i < end) {
+ c = buffer[i];
+ if (c == '-') {
+ negative = true;
+ limit = Long.MIN_VALUE;
+ i++;
+ }
+ if (c == '+') {
+ i++;
}
}
- boolean post = false;
- for (; !post && i < length; ++i) {
- char ch = buffer[i + start];
- switch (ch) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- n = n * 10 + (ch - '0');
- break;
- default:
- String errorString = new String(buffer, i + start, length - i);
- throw new HyracksDataException(
- "Long Parser - a digit is expected. But, encountered this character: " + ch
- + " in the incoming input: " + errorString);
+ long result = 0;
+ long multiplicationMin = limit / 10;
+ boolean gotNumber = false;
+ for (; i < end; i++) {
+ c = buffer[i];
+ if (c >= '0' && c <= '9') {
+ gotNumber = true;
+ if (result < multiplicationMin) {
+ return false;
+ }
+ result *= 10;
+ int digit = c - '0';
+ if (result < limit + digit) {
+ return false;
+ }
+ result -= digit;
+ } else {
+ break;
}
}
- for (; i < length; ++i) {
- char ch = buffer[i + start];
- switch (ch) {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- case '\f':
- break;
-
- default:
- String errorString = new String(buffer, i + start, length - i);
- throw new HyracksDataException(
- "Long Parser - a whitespace, tab, new line, or form-feed expected. "
- + "But, encountered this character: " + ch + " in the incoming input: "
- + errorString);
+ for (; i < end; ++i) {
+ c = buffer[i];
+ if (c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != '\f') {
+ return false;
}
}
+ if (!gotNumber) {
+ return false;
+ }
try {
- out.writeLong(n * sign);
+ out.writeLong(negative ? result : -result);
+ return true;
} catch (IOException e) {
throw HyracksDataException.create(e);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/UTF8StringParserFactory.java b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/UTF8StringParserFactory.java
index 7848500..22f98a6 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/UTF8StringParserFactory.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/parsers/UTF8StringParserFactory.java
@@ -38,9 +38,10 @@
private UTF8StringWriter writer = new UTF8StringWriter();
@Override
- public void parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
+ public boolean parse(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
try {
writer.writeUTF8(buffer, start, length, out);
+ return true;
} catch (IOException e) {
throw HyracksDataException.create(e);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/test/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayBase64ParserFactoryTest.java b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/test/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayBase64ParserFactoryTest.java
index 29a6d6d..5fcaf65 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/test/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayBase64ParserFactoryTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/test/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayBase64ParserFactoryTest.java
@@ -66,7 +66,8 @@
DataOutputStream outputStream = new DataOutputStream(bos);
ByteArrayPointable bytePtr = new ByteArrayPointable();
- parser.parse(test.toCharArray(), 0, test.length(), outputStream);
+ boolean result = parser.parse(test.toCharArray(), 0, test.length(), outputStream);
+ assertTrue(result);
bytePtr.set(bos.toByteArray(), 0, bos.size());
byte[] answer = DatatypeConverter.parseBase64Binary(test);
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/test/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayHexParserFactoryTest.java b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/test/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayHexParserFactoryTest.java
index c959c8d..a6196e7 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/test/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayHexParserFactoryTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/test/java/org/apache/hyracks/dataflow/common/data/parsers/ByteArrayHexParserFactoryTest.java
@@ -54,7 +54,8 @@
DataOutputStream outputStream = new DataOutputStream(bos);
ByteArrayPointable bytePtr = new ByteArrayPointable();
- parser.parse(test.toCharArray(), 0, test.length(), outputStream);
+ boolean result = parser.parse(test.toCharArray(), 0, test.length(), outputStream);
+ assertTrue(result);
bytePtr.set(bos.toByteArray(), 0, bos.size());
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/test/java/org/apache/hyracks/dataflow/common/data/parsers/ParserFactoryTest.java b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/test/java/org/apache/hyracks/dataflow/common/data/parsers/ParserFactoryTest.java
new file mode 100644
index 0000000..e3e77da
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/test/java/org/apache/hyracks/dataflow/common/data/parsers/ParserFactoryTest.java
@@ -0,0 +1,218 @@
+/*
+ * 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.
+ */
+
+package org.apache.hyracks.dataflow.common.data.parsers;
+
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.primitive.BooleanPointable;
+import org.apache.hyracks.data.std.primitive.IntegerPointable;
+import org.apache.hyracks.data.std.primitive.LongPointable;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+import org.junit.Test;
+
+import junit.framework.TestCase;
+
+public class ParserFactoryTest extends TestCase {
+
+ private final ArrayBackedValueStorage storage = new ArrayBackedValueStorage();
+ private final IValueParser integerParser = IntegerParserFactory.INSTANCE.createValueParser();
+ private final IValueParser longParser = LongParserFactory.INSTANCE.createValueParser();
+ private final IValueParser booleanParser = BooleanParserFactory.INSTANCE.createValueParser();
+ private String chars = "";
+
+ @Test
+ public void testInteger() throws HyracksDataException {
+ String number = "12";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, 12, true);
+ number = "+12";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, 12, true);
+ number = "-12";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, -12, true);
+ number = " 12";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, 12, true);
+ number = " +12";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, 12, true);
+ number = " -12";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, -12, true);
+ number = "12 ";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, 12, true);
+ number = "+12 ";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, 12, true);
+ number = "-12 ";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, -12, true);
+ number = " 12 ";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, 12, true);
+ number = " +12 ";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, 12, true);
+ number = " -12 ";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, -12, true);
+
+ number = Integer.toString(Integer.MAX_VALUE);
+ parse(number, integerParser, storage, IntegerPointable::getInteger, Integer.MAX_VALUE, true);
+ number = Integer.toString(Integer.MIN_VALUE);
+ parse(number, integerParser, storage, IntegerPointable::getInteger, Integer.MIN_VALUE, true);
+
+ // overflow and underflow
+ number = Long.toString(Integer.MAX_VALUE + 1L);
+ parse(number, integerParser, storage, IntegerPointable::getInteger, null, false);
+ number = Long.toString(Integer.MIN_VALUE - 1L);
+ parse(number, integerParser, storage, IntegerPointable::getInteger, null, false);
+
+ // invalid
+ number = "a";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, null, false);
+ number = "12a";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, null, false);
+ number = "12 a";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, null, false);
+ number = " a 12";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, null, false);
+ number = "a12";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, null, false);
+ number = "+ 12";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, null, false);
+ number = "- 12";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, null, false);
+ number = "1 2";
+ parse(number, integerParser, storage, IntegerPointable::getInteger, null, false);
+ }
+
+ @Test
+ public void testLong() throws HyracksDataException {
+ storage.reset();
+ String number = "12";
+ parse(number, longParser, storage, LongPointable::getLong, 12L, true);
+ number = "+12";
+ parse(number, longParser, storage, LongPointable::getLong, 12L, true);
+ number = "-12";
+ parse(number, longParser, storage, LongPointable::getLong, -12L, true);
+ number = " 12";
+ parse(number, longParser, storage, LongPointable::getLong, 12L, true);
+ number = " +12";
+ parse(number, longParser, storage, LongPointable::getLong, 12L, true);
+ number = " -12";
+ parse(number, longParser, storage, LongPointable::getLong, -12L, true);
+ number = "12 ";
+ parse(number, longParser, storage, LongPointable::getLong, 12L, true);
+ number = "+12 ";
+ parse(number, longParser, storage, LongPointable::getLong, 12L, true);
+ number = "-12 ";
+ parse(number, longParser, storage, LongPointable::getLong, -12L, true);
+ number = " 12 ";
+ parse(number, longParser, storage, LongPointable::getLong, 12L, true);
+ number = " +12 ";
+ parse(number, longParser, storage, LongPointable::getLong, 12L, true);
+ number = " -12 ";
+ parse(number, longParser, storage, LongPointable::getLong, -12L, true);
+
+ number = Long.toString(Long.MAX_VALUE);
+ parse(number, longParser, storage, LongPointable::getLong, Long.MAX_VALUE, true);
+ number = Long.toString(Long.MIN_VALUE);
+ parse(number, longParser, storage, LongPointable::getLong, Long.MIN_VALUE, true);
+
+ // overflow and underflow
+ number = Long.toString(Long.MAX_VALUE) + "1";
+ parse(number, longParser, storage, LongPointable::getLong, null, false);
+ number = Long.toString(Long.MIN_VALUE) + "1";
+ parse(number, longParser, storage, LongPointable::getLong, null, false);
+
+ // invalid
+ number = "a";
+ parse(number, longParser, storage, LongPointable::getLong, null, false);
+ number = "12a";
+ parse(number, longParser, storage, LongPointable::getLong, null, false);
+ number = "12 a";
+ parse(number, longParser, storage, LongPointable::getLong, null, false);
+ number = " a 12";
+ parse(number, longParser, storage, LongPointable::getLong, null, false);
+ number = "+ 12";
+ parse(number, longParser, storage, LongPointable::getLong, null, false);
+ number = "- 12";
+ parse(number, longParser, storage, LongPointable::getLong, null, false);
+ number = "1 2";
+ parse(number, longParser, storage, LongPointable::getLong, null, false);
+ }
+
+ @Test
+ public void testBoolean() throws HyracksDataException {
+ storage.reset();
+ String bool = "true";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, Boolean.TRUE, true);
+ bool = "TRUE";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, Boolean.TRUE, true);
+ bool = "True";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, Boolean.TRUE, true);
+ bool = "true ";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, Boolean.TRUE, true);
+ bool = " true";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, Boolean.TRUE, true);
+ bool = " True ";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, Boolean.TRUE, true);
+
+ bool = "false";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, Boolean.FALSE, true);
+ bool = "FALSE";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, Boolean.FALSE, true);
+ bool = "False";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, Boolean.FALSE, true);
+ bool = " false ";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, Boolean.FALSE, true);
+ bool = " false";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, Boolean.FALSE, true);
+ bool = "false ";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, Boolean.FALSE, true);
+
+ // invalid
+ bool = "foo";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, null, false);
+ bool = "truea";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, null, false);
+ bool = "ffalse";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, null, false);
+ bool = "ffalse";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, null, false);
+ bool = "t rue";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, null, false);
+ bool = "true a";
+ parse(bool, booleanParser, storage, BooleanPointable::getBoolean, null, false);
+ }
+
+ private <T> void parse(String test, IValueParser parser, ArrayBackedValueStorage storage, Getter<T> getter,
+ T expectedVal, boolean expectedResult) throws HyracksDataException {
+ int oldSize = storage.getLength();
+ int start = storage.getLength();
+ int stringStart = chars.length();
+ chars = chars + test;
+ int stringLength = chars.length() - stringStart;
+ boolean result = parser.parse(chars.toCharArray(), stringStart, stringLength, storage.getDataOutput());
+ int newSize = storage.getLength();
+ if (!result) {
+ assertEquals(oldSize, newSize);
+ } else {
+ assertEquals(expectedVal, getter.get(storage.getByteArray(), start));
+ }
+ assertEquals(expectedResult, result);
+
+ }
+
+ @FunctionalInterface
+ private interface Getter<T> {
+ T get(byte[] bytes, int start);
+ }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/file/DelimitedDataTupleParserFactory.java b/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/file/DelimitedDataTupleParserFactory.java
index 2eb882a..b8b2ba8 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/file/DelimitedDataTupleParserFactory.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/file/DelimitedDataTupleParserFactory.java
@@ -28,12 +28,16 @@
import org.apache.hyracks.api.comm.VSizeFrame;
import org.apache.hyracks.api.context.IHyracksTaskContext;
import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
import org.apache.hyracks.dataflow.common.comm.io.ArrayTupleBuilder;
import org.apache.hyracks.dataflow.common.comm.io.FrameTupleAppender;
import org.apache.hyracks.dataflow.common.comm.util.FrameUtils;
import org.apache.hyracks.dataflow.common.data.parsers.IValueParser;
import org.apache.hyracks.dataflow.common.data.parsers.IValueParserFactory;
+/**
+ * Currently used by tests only. Reconsider the code when it will be used otherwise.
+ */
public class DelimitedDataTupleParserFactory implements ITupleParserFactory {
private static final long serialVersionUID = 1L;
private IValueParserFactory[] valueParserFactories;
@@ -54,6 +58,8 @@
@Override
public ITupleParser createTupleParser(final IHyracksTaskContext ctx) {
return new ITupleParser() {
+ final IWarningCollector warningCollector = ctx.getWarningCollector();
+
@Override
public void parse(InputStream in, IFrameWriter writer) throws HyracksDataException {
try {
@@ -67,20 +73,29 @@
ArrayTupleBuilder tb = new ArrayTupleBuilder(valueParsers.length);
DataOutput dos = tb.getDataOutput();
- FieldCursorForDelimitedDataParser cursor =
- new FieldCursorForDelimitedDataParser(new InputStreamReader(in), fieldDelimiter, quote);
+ FieldCursorForDelimitedDataParser cursor = new FieldCursorForDelimitedDataParser(
+ new InputStreamReader(in), fieldDelimiter, quote, warningCollector, () -> "");
while (cursor.nextRecord()) {
tb.reset();
for (int i = 0; i < valueParsers.length; ++i) {
- if (!cursor.nextField()) {
- break;
+ FieldCursorForDelimitedDataParser.Result result = cursor.nextField();
+ switch (result) {
+ case OK:
+ break;
+ case END:
+ case ERROR:
+ throw new HyracksDataException("Failed to parse record");
+ default:
+ throw new IllegalStateException();
}
// Eliminate double quotes in the field that we are going to parse
if (cursor.fieldHasDoubleQuote()) {
cursor.eliminateDoubleQuote();
}
- valueParsers[i].parse(cursor.getBuffer(), cursor.getFieldStart(), cursor.getFieldLength(),
- dos);
+ if (!valueParsers[i].parse(cursor.getBuffer(), cursor.getFieldStart(),
+ cursor.getFieldLength(), dos)) {
+ throw new HyracksDataException("Failed to parse field");
+ }
tb.addFieldEndOffset();
}
FrameUtils.appendToWriter(writer, appender, tb.getFieldEndOffsets(), tb.getByteArray(), 0,
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/file/FieldCursorForDelimitedDataParser.java b/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/file/FieldCursorForDelimitedDataParser.java
index fd3e4c3..48cfca6 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/file/FieldCursorForDelimitedDataParser.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/file/FieldCursorForDelimitedDataParser.java
@@ -21,6 +21,12 @@
import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;
+import java.util.function.Supplier;
+
+import org.apache.hyracks.api.exceptions.ErrorCode;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.api.exceptions.Warning;
public class FieldCursorForDelimitedDataParser {
@@ -29,13 +35,26 @@
IN_RECORD, //cursor is inside record
EOR, //cursor is at end of record
CR, //cursor at carriage return
- EOF //end of stream reached
+ EOF, //end of stream reached
+ FAILED // cursor failed to parse a field
}
+ public enum Result {
+ OK,
+ ERROR,
+ END
+ }
+
+ private static final SourceLocation SRC_LOC = new SourceLocation(-1, -1);
+ private static final String CLOSING_Q = "missing a closing quote";
+ private static final String OPENING_Q = "a quote should be in the beginning";
+ private static final String DELIMITER_AFTER_Q = "a quote enclosing a field needs to be followed by the delimiter";
+ private final IWarningCollector warnings;
+ private final Supplier<String> dataSourceName;
private char[] buffer; //buffer to holds the input coming form the underlying input stream
private int fStart; //start position for field
private int fEnd; //end position for field
- private int recordCount; //count of records
+ private long lineCount; //count of lines
private int fieldCount; //count of fields in current record
private int doubleQuoteCount; //count of double quotes
private boolean isDoubleQuoteIncludedInThisField; //does current field include double quotes
@@ -58,7 +77,10 @@
private final char quote; //the quote character
private final char fieldDelimiter; //the delimiter
- public FieldCursorForDelimitedDataParser(Reader in, char fieldDelimiter, char quote) {
+ public FieldCursorForDelimitedDataParser(Reader in, char fieldDelimiter, char quote,
+ IWarningCollector warningCollector, Supplier<String> dataSourceName) {
+ this.warnings = warningCollector;
+ this.dataSourceName = dataSourceName;
this.in = in;
if (in != null) {
buffer = new char[INITIAL_BUFFER_SIZE];
@@ -77,7 +99,7 @@
doubleQuoteCount = 0;
startedQuote = false;
isDoubleQuoteIncludedInThisField = false;
- recordCount = 0;
+ lineCount = 1;
fieldCount = 0;
}
@@ -105,12 +127,12 @@
return fieldCount;
}
- public int getRecordCount() {
- return recordCount;
+ public long getLineCount() {
+ return lineCount;
}
- public void nextRecord(char[] buffer, int recordLength) {
- recordCount++;
+ public void nextRecord(char[] buffer, int recordLength, long lineNumber) {
+ lineCount = lineNumber;
fieldCount = 0;
lastDelimiterPosition = -1;
lastQuotePosition = -1;
@@ -126,7 +148,6 @@
}
public boolean nextRecord() throws IOException {
- recordCount++;
fieldCount = 0;
while (true) {
switch (state) {
@@ -142,6 +163,7 @@
case IN_RECORD:
int p = start;
+ char lastChar = '\0';
while (true) {
if (p >= end) {
int s = start;
@@ -182,6 +204,11 @@
lastDelimiterPosition = p;
break;
}
+ // count lines inside quotes
+ if (ch == '\r' || (ch == '\n' && lastChar != '\r')) {
+ lineCount++;
+ }
+ lastChar = ch;
++p;
}
break;
@@ -195,6 +222,10 @@
}
}
char ch = buffer[start];
+ // if the next char "ch" is not \n, then count the \r
+ if (ch != '\n') {
+ lineCount++;
+ }
if (ch == '\n' && !startedQuote) {
++start;
state = State.EOR;
@@ -204,6 +235,7 @@
}
case EOR:
+ lineCount++;
if (start >= end) {
eof = !readMore();
if (eof) {
@@ -217,17 +249,21 @@
case EOF:
return false;
+ case FAILED:
+ return false;
}
}
}
- public boolean nextField() throws IOException {
+ public Result nextField() throws IOException {
switch (state) {
case INIT:
case EOR:
case EOF:
case CR:
- return false;
+ return Result.END;
+ case FAILED:
+ return Result.ERROR;
case IN_RECORD:
fieldCount++;
@@ -239,6 +275,7 @@
quoteCount = 0;
doubleQuoteCount = 0;
+ char lastChar = '\0';
int p = start;
while (true) {
if (p >= end) {
@@ -260,11 +297,14 @@
fStart = start + 1;
fEnd = p - 1;
} else {
- throw new IOException("At record: " + recordCount + ", field#: " + fieldCount
- + " - missing a closing quote");
+ state = State.FAILED;
+ if (warnings.shouldWarn()) {
+ warn(CLOSING_Q);
+ }
+ return Result.ERROR;
}
}
- return true;
+ return Result.OK;
}
}
char ch = buffer[p];
@@ -275,8 +315,11 @@
startedQuote = true;
} else {
// In this case, we don't have a quote in the beginning of a field.
- throw new IOException("At record: " + recordCount + ", field#: " + fieldCount
- + " - a quote enclosing a field needs to be placed in the beginning of that field");
+ state = State.FAILED;
+ if (warnings.shouldWarn()) {
+ warn(OPENING_Q);
+ }
+ return Result.ERROR;
}
}
// Check double quotes - "". We check [start != p-2]
@@ -300,7 +343,7 @@
fEnd = p;
start = p + 1;
lastDelimiterPosition = p;
- return true;
+ return Result.OK;
}
if (lastQuotePosition == p - 1 && lastDoubleQuotePosition != p - 1
@@ -313,14 +356,17 @@
start = p + 1;
lastDelimiterPosition = p;
startedQuote = false;
- return true;
+ return Result.OK;
} else if (lastQuotePosition < p - 1 && lastQuotePosition != lastDoubleQuotePosition
&& quoteCount == doubleQuoteCount * 2 + 2) {
// There is a quote before the delimiter, however it is not directly placed before the delimiter.
// In this case, we throw an exception.
// quoteCount == doubleQuoteCount * 2 + 2 : only true when we have two quotes except double-quotes.
- throw new IOException("At record: " + recordCount + ", field#: " + fieldCount
- + " - A quote enclosing a field needs to be followed by the delimiter.");
+ state = State.FAILED;
+ if (warnings.shouldWarn()) {
+ warn(DELIMITER_AFTER_Q);
+ }
+ return Result.ERROR;
}
// If the control flow reaches here: we have a delimiter in this field and
// there should be a quote in the beginning and the end of
@@ -332,7 +378,7 @@
start = p + 1;
state = ch == '\n' ? State.EOR : State.CR;
lastDelimiterPosition = p;
- return true;
+ return Result.OK;
} else if (lastQuotePosition == p - 1 && lastDoubleQuotePosition != p - 1
&& quoteCount == doubleQuoteCount * 2 + 2) {
// set the position of fStart to +1, fEnd to -1 to remove quote character
@@ -342,9 +388,14 @@
start = p + 1;
state = ch == '\n' ? State.EOR : State.CR;
startedQuote = false;
- return true;
+ return Result.OK;
}
}
+ // count lines inside quotes
+ if (ch == '\r' || (ch == '\n' && lastChar != '\r')) {
+ lineCount++;
+ }
+ lastChar = ch;
++p;
}
}
@@ -397,4 +448,9 @@
fEnd -= doubleQuoteCount;
isDoubleQuoteIncludedInThisField = false;
}
+
+ private void warn(String message) {
+ warnings.warn(Warning.forHyracks(SRC_LOC, ErrorCode.PARSING_ERROR, dataSourceName.get(), lineCount, fieldCount,
+ message));
+ }
}
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/join/OptimizedHybridHashJoin.java b/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/join/OptimizedHybridHashJoin.java
index 3d3bc7f..5c0b28d 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/join/OptimizedHybridHashJoin.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/join/OptimizedHybridHashJoin.java
@@ -34,6 +34,7 @@
import org.apache.hyracks.api.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.io.FileReference;
+import org.apache.hyracks.api.util.CleanupUtils;
import org.apache.hyracks.dataflow.common.comm.io.FrameTupleAccessor;
import org.apache.hyracks.dataflow.common.comm.io.FrameTupleAppender;
import org.apache.hyracks.dataflow.common.io.RunFileReader;
@@ -219,6 +220,19 @@
}
}
+ public void fail() throws HyracksDataException {
+ for (RunFileWriter writer : buildRFWriters) {
+ if (writer != null) {
+ CleanupUtils.fail(writer, null);
+ }
+ }
+ for (RunFileWriter writer : probeRFWriters) {
+ if (writer != null) {
+ CleanupUtils.fail(writer, null);
+ }
+ }
+ }
+
private void closeAllSpilledPartitions(RunFileWriter[] runFileWriters, String refName) throws HyracksDataException {
try {
for (int pid = spilledStatus.nextSetBit(0); pid >= 0 && pid < numOfPartitions; pid =
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/join/OptimizedHybridHashJoinOperatorDescriptor.java b/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/join/OptimizedHybridHashJoinOperatorDescriptor.java
index 1819b8d..97f9c24 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/join/OptimizedHybridHashJoinOperatorDescriptor.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/main/java/org/apache/hyracks/dataflow/std/join/OptimizedHybridHashJoinOperatorDescriptor.java
@@ -273,7 +273,7 @@
ITuplePartitionComputer buildHpc =
new FieldHashPartitionComputerFamily(buildKeys, buildHashFunctionFactories)
.createPartitioner(0);
- boolean isFailed = false;
+ boolean failed = false;
@Override
public void open() throws HyracksDataException {
@@ -302,21 +302,24 @@
@Override
public void close() throws HyracksDataException {
if (state.hybridHJ != null) {
- state.hybridHJ.closeBuild();
- if (isFailed) {
- state.hybridHJ.clearBuildTempFiles();
- } else {
+ if (!failed) {
+ state.hybridHJ.closeBuild();
ctx.setStateObject(state);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("OptimizedHybridHashJoin closed its build phase");
}
+ } else {
+ state.hybridHJ.clearBuildTempFiles();
}
}
}
@Override
public void fail() throws HyracksDataException {
- isFailed = true;
+ failed = true;
+ if (state.hybridHJ != null) {
+ state.hybridHJ.fail();
+ }
}
@Override
@@ -401,6 +404,9 @@
@Override
public void fail() throws HyracksDataException {
failed = true;
+ if (state.hybridHJ != null) {
+ state.hybridHJ.fail();
+ }
writer.fail();
}
@@ -447,6 +453,9 @@
joinPartitionPair(bReader, pReader, bSize, pSize, 1);
}
} catch (Exception e) {
+ if (state.hybridHJ != null) {
+ state.hybridHJ.fail();
+ }
// Since writer.nextFrame() is called in the above "try" body, we have to call writer.fail()
// to send the failure signal to the downstream, when there is a throwable thrown.
writer.fail();
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/test/java/org/apache/hyracks/dataflow/std/file/CursorTest.java b/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/test/java/org/apache/hyracks/dataflow/std/file/CursorTest.java
index 8edcafc..5561ad1 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/test/java/org/apache/hyracks/dataflow/std/file/CursorTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-std/src/test/java/org/apache/hyracks/dataflow/std/file/CursorTest.java
@@ -30,6 +30,7 @@
public class CursorTest {
// @Test commented out due to ASTERIXDB-1881
+ // fix the code if it is to be enabled
public void test() {
FileInputStream in = null;
BufferedReader reader = null;
@@ -38,24 +39,28 @@
Paths.get(getClass().getResource("/data/beer.txt").toURI()).toAbsolutePath().toString());
reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
// skip header
- final FieldCursorForDelimitedDataParser cursor = new FieldCursorForDelimitedDataParser(reader, ',', '"');
+ final FieldCursorForDelimitedDataParser cursor =
+ new FieldCursorForDelimitedDataParser(reader, ',', '"', null, () -> "");
// get number of fields from header (first record is header)
cursor.nextRecord();
int numOfFields = 0;
int expectedNumberOfRecords = 7307;
- while (cursor.nextField()) {
+ FieldCursorForDelimitedDataParser.Result lastResult = cursor.nextField();
+ while ((lastResult = cursor.nextField()) == FieldCursorForDelimitedDataParser.Result.OK) {
numOfFields++;
}
+ Assert.assertNotEquals(lastResult, FieldCursorForDelimitedDataParser.Result.ERROR);
int recordNumber = 0;
while (cursor.nextRecord()) {
int fieldNumber = 0;
- while (cursor.nextField()) {
+ while ((lastResult = cursor.nextField()) == FieldCursorForDelimitedDataParser.Result.OK) {
if (cursor.fieldHasDoubleQuote()) {
cursor.eliminateDoubleQuote();
}
fieldNumber++;
}
+ Assert.assertNotEquals(lastResult, FieldCursorForDelimitedDataParser.Result.ERROR);
if ((fieldNumber > numOfFields) || (fieldNumber < numOfFields)) {
System.err.println("Test case failed. Expected number of fields in each record is " + numOfFields
+ " and record number " + recordNumber + " was found to have " + fieldNumber);
diff --git a/hyracks-fullstack/hyracks/hyracks-examples/text-example/texthelper/src/main/java/org/apache/hyracks/examples/text/WordTupleParserFactory.java b/hyracks-fullstack/hyracks/hyracks-examples/text-example/texthelper/src/main/java/org/apache/hyracks/examples/text/WordTupleParserFactory.java
index 2219a14..0032c40 100644
--- a/hyracks-fullstack/hyracks/hyracks-examples/text-example/texthelper/src/main/java/org/apache/hyracks/examples/text/WordTupleParserFactory.java
+++ b/hyracks-fullstack/hyracks/hyracks-examples/text-example/texthelper/src/main/java/org/apache/hyracks/examples/text/WordTupleParserFactory.java
@@ -54,7 +54,9 @@
WordCursor cursor = new WordCursor(new InputStreamReader(in));
while (cursor.nextWord()) {
tb.reset();
- utf8StringParser.parse(cursor.buffer, cursor.fStart, cursor.fEnd - cursor.fStart, dos);
+ if (!utf8StringParser.parse(cursor.buffer, cursor.fStart, cursor.fEnd - cursor.fStart, dos)) {
+ throw new HyracksDataException("Failed to parse word");
+ }
tb.addFieldEndOffset();
FrameUtils.appendToWriter(writer, appender, tb.getFieldEndOffsets(), tb.getByteArray(), 0,
tb.getSize());
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
index 21653c8..3977207 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
@@ -22,6 +22,7 @@
import static com.fasterxml.jackson.databind.SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.concurrent.ConcurrentMap;
@@ -113,7 +114,7 @@
protected void sendError(IServletResponse response, HttpResponseStatus status, String message) throws IOException {
response.setStatus(status);
- HttpUtil.setContentType(response, HttpUtil.ContentType.TEXT_PLAIN, HttpUtil.Encoding.UTF8);
+ HttpUtil.setContentType(response, HttpUtil.ContentType.TEXT_PLAIN, StandardCharsets.UTF_8);
if (message != null) {
response.writer().println(message);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
index 46d429a..77e7c5a 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
@@ -19,6 +19,7 @@
package org.apache.hyracks.http.server.utils;
import java.io.IOException;
+import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
@@ -27,14 +28,22 @@
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalDouble;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
+import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.hyracks.http.api.IServletRequest;
import org.apache.hyracks.http.api.IServletResponse;
import org.apache.hyracks.http.server.BaseRequest;
import org.apache.hyracks.http.server.FormUrlEncodedRequest;
+import org.apache.hyracks.util.ThrowingConsumer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -90,12 +99,12 @@
public static Charset setContentType(IServletResponse response, String type, IServletRequest fromRequest)
throws IOException {
Charset preferredCharset = getPreferredCharset(fromRequest);
- response.setHeader(HttpHeaderNames.CONTENT_TYPE, type + "; charset=" + preferredCharset.name());
+ setContentType(response, type, preferredCharset);
return preferredCharset;
}
- public static void setContentType(IServletResponse response, String type, String charset) throws IOException {
- response.setHeader(HttpHeaderNames.CONTENT_TYPE, type + "; charset=" + charset);
+ public static void setContentType(IServletResponse response, String type, Charset charset) throws IOException {
+ response.setHeader(HttpHeaderNames.CONTENT_TYPE, type + "; charset=" + charset.name());
}
public static void setContentType(IServletResponse response, String type) throws IOException {
@@ -184,10 +193,29 @@
return i < 0 ? uri : uri.substring(0, i);
}
- public static class Encoding {
- public static final String UTF8 = "utf-8";
-
- private Encoding() {
+ public static void handleStreamInterruptibly(CloseableHttpResponse response,
+ ThrowingConsumer<InputStreamReader> streamProcessor, ExecutorService executor,
+ Supplier<String> taskDescription) throws IOException, InterruptedException, ExecutionException {
+ // we have to consume the stream in a separate thread, as it not stop on interrupt; we need to
+ // instead close the connection to achieve the interrupt
+ Future<Void> readFuture = executor.submit(() -> {
+ InputStreamReader reader = new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8);
+ streamProcessor.process(reader);
+ return null;
+ });
+ try {
+ readFuture.get();
+ } catch (InterruptedException ex) { // NOSONAR -- interrupt or rethrow
+ response.close();
+ try {
+ readFuture.get(1, TimeUnit.SECONDS);
+ } catch (TimeoutException te) {
+ LOGGER.warn("{} did not exit on stream close due to interrupt after 1s", taskDescription);
+ readFuture.cancel(true);
+ } catch (ExecutionException ee) {
+ LOGGER.debug("ignoring exception awaiting aborted {} shutdown", taskDescription, ee);
+ }
+ throw ex;
}
}
diff --git a/hyracks-fullstack/hyracks/hyracks-maven-plugins/license-automation-plugin/src/main/java/org/apache/hyracks/maven/license/LicenseMojo.java b/hyracks-fullstack/hyracks/hyracks-maven-plugins/license-automation-plugin/src/main/java/org/apache/hyracks/maven/license/LicenseMojo.java
index e72404c..89993fd 100644
--- a/hyracks-fullstack/hyracks/hyracks-maven-plugins/license-automation-plugin/src/main/java/org/apache/hyracks/maven/license/LicenseMojo.java
+++ b/hyracks-fullstack/hyracks/hyracks-maven-plugins/license-automation-plugin/src/main/java/org/apache/hyracks/maven/license/LicenseMojo.java
@@ -360,23 +360,31 @@
gatherProjectDependencies(project, dependencyLicenseMap, dependencyGavMap);
for (Override override : overrides) {
- String gav = override.getGav();
- MavenProject dep = dependencyGavMap.get(gav);
- if (dep == null) {
- getLog().warn("Unused override dependency " + gav + "; ignoring...");
- continue;
+
+ // Collect both <gav></gav> and <gavs><gav></gav><gav></gav>...</gavs>
+ List<String> gavs = override.getGavs();
+ if (override.getGav() != null) {
+ gavs.add(override.getGav());
}
- if (override.getUrl() != null) {
- final List<Pair<String, String>> newLicense =
- Collections.singletonList(new ImmutablePair<>(override.getUrl(), override.getName()));
- List<Pair<String, String>> prevLicense = dependencyLicenseMap.put(dep, newLicense);
- warnUnlessFlag(dep, IGNORE_LICENSE_OVERRIDE, "license list for " + toGav(dep)
- + " changed with <override>; was: " + prevLicense + ", now: " + newLicense);
- }
- if (override.getNoticeUrl() != null) {
- noticeOverrides.put(gav, override.getNoticeUrl());
- warnUnlessFlag(dep, IGNORE_NOTICE_OVERRIDE,
- "notice for " + toGav(dep) + " changed with <override>; now: " + override.getNoticeUrl());
+
+ for (String gav : gavs) {
+ MavenProject dep = dependencyGavMap.get(gav);
+ if (dep == null) {
+ getLog().warn("Unused override dependency " + gav + "; ignoring...");
+ continue;
+ }
+ if (override.getUrl() != null) {
+ final List<Pair<String, String>> newLicense =
+ Collections.singletonList(new ImmutablePair<>(override.getUrl(), override.getName()));
+ List<Pair<String, String>> prevLicense = dependencyLicenseMap.put(dep, newLicense);
+ warnUnlessFlag(dep, IGNORE_LICENSE_OVERRIDE, "license list for " + toGav(dep)
+ + " changed with <override>; was: " + prevLicense + ", now: " + newLicense);
+ }
+ if (override.getNoticeUrl() != null) {
+ noticeOverrides.put(gav, override.getNoticeUrl());
+ warnUnlessFlag(dep, IGNORE_NOTICE_OVERRIDE,
+ "notice for " + toGav(dep) + " changed with <override>; now: " + override.getNoticeUrl());
+ }
}
}
return dependencyLicenseMap;
diff --git a/hyracks-fullstack/hyracks/hyracks-maven-plugins/license-automation-plugin/src/main/java/org/apache/hyracks/maven/license/Override.java b/hyracks-fullstack/hyracks/hyracks-maven-plugins/license-automation-plugin/src/main/java/org/apache/hyracks/maven/license/Override.java
index 0391dfb..f19df51 100644
--- a/hyracks-fullstack/hyracks/hyracks-maven-plugins/license-automation-plugin/src/main/java/org/apache/hyracks/maven/license/Override.java
+++ b/hyracks-fullstack/hyracks/hyracks-maven-plugins/license-automation-plugin/src/main/java/org/apache/hyracks/maven/license/Override.java
@@ -18,6 +18,9 @@
*/
package org.apache.hyracks.maven.license;
+import java.util.ArrayList;
+import java.util.List;
+
public class Override {
@SuppressWarnings("unused") // set by Maven plugin configuration
@@ -27,6 +30,9 @@
private String gav;
@SuppressWarnings("unused") // set by Maven plugin configuration
+ private List<String> gavs = new ArrayList<>();
+
+ @SuppressWarnings("unused") // set by Maven plugin configuration
private String name;
@SuppressWarnings("unused") // set by Maven plugin configuration
@@ -36,6 +42,10 @@
return gav;
}
+ public List<String> getGavs() {
+ return gavs;
+ }
+
public String getUrl() {
return url;
}
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/ThrowingConsumer.java
similarity index 84%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
copy to hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/ThrowingConsumer.java
index 6e31eb3..bfc5fdd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-dataset/aws/s3/002/query-dataset.002.query.sqlpp
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/ThrowingConsumer.java
@@ -16,7 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.hyracks.util;
-USE test;
-
-FROM test SELECT VALUE test ORDER BY id ASC;
\ No newline at end of file
+@FunctionalInterface
+public interface ThrowingConsumer<V> {
+ void process(V value) throws Exception;
+}
diff --git a/hyracks-fullstack/pom.xml b/hyracks-fullstack/pom.xml
index f10f2fa..d07e1dd 100644
--- a/hyracks-fullstack/pom.xml
+++ b/hyracks-fullstack/pom.xml
@@ -271,32 +271,7 @@
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.6.3</version>
- </dependency>
- <dependency>
- <groupId>org.apache.maven</groupId>
- <artifactId>maven-plugin-api</artifactId>
- <version>3.6.3</version>
- </dependency>
- <dependency>
- <groupId>org.apache.maven</groupId>
- <artifactId>maven-model</artifactId>
- <version>3.6.3</version>
- </dependency>
- <dependency>
- <groupId>org.apache.maven</groupId>
- <artifactId>maven-artifact</artifactId>
- <version>3.6.3</version>
- </dependency>
- <dependency>
- <groupId>org.apache.maven</groupId>
- <artifactId>maven-compat</artifactId>
- <version>3.6.3</version>
- </dependency>
- <dependency>
- <groupId>org.apache.maven</groupId>
- <artifactId>maven-core</artifactId>
- <version>3.6.3</version>
- </dependency>
+ </dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
@@ -463,10 +438,49 @@
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-enforcer-plugin</artifactId>
- <version>3.0.0-M1</version>
+ <artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
+ <id>check-pom-packaging</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <exportAntProperties>true</exportAntProperties>
+ <target xmlns:unless="ant:unless">
+ <condition property="skipPomEnforcement">
+ <not><equals arg1="${project.packaging}" arg2="pom"/></not>
+ </condition>
+ <echo message="will enforce non-existence of test source dir due to ${project.packaging} packaging" unless:set="skipPomEnforcement"/>
+ </target>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>ensure-no-tests-for-pom-packaging</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <configuration>
+ <rules>
+ <requireFilesDontExist>
+ <files>
+ <file>${project.build.testSourceDirectory}</file>
+ </files>
+ <message>#### Tests cannot exist in projects with '${project.packaging}' packaging!</message>
+ </requireFilesDontExist>
+ </rules>
+ <skip>${skipPomEnforcement}</skip>
+ </configuration>
+ </execution>
+ <execution>
<id>enforce-versions</id>
<goals>
<goal>enforce</goal>