Merge branch 'eugenia/web_ui_beta_fixes' of https://code.google.com/p/asterixdb into eugenia/web_ui_beta_fixes
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/APIServlet.java b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/APIServlet.java
index f6f0ef9..72d742d 100644
--- a/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/APIServlet.java
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/APIServlet.java
@@ -10,12 +10,14 @@
import java.io.FileInputStream;
import java.util.List;
import java.util.logging.Level;
+import java.awt.image.BufferedImage;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.activation.MimetypesFileTypeMap;
+import javax.imageio.ImageIO;
import edu.uci.ics.asterix.api.common.APIFramework.DisplayFormat;
import edu.uci.ics.asterix.api.common.SessionConfig;
@@ -127,27 +129,18 @@
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
-
- if (resourcePath.endsWith(".png")) {
- // Handle PNG content for webui
- response.setContentType(new MimetypesFileTypeMap().getContentType(resourcePath));
- // Read image file size
- File pngFile = new File(resourcePath);
- response.setContentLength((int)pngFile.length());
-
- // Initialize filestreams, and write to output
- OutputStream pngOut = response.getOutputStream();
-
- byte[] buf = new byte[1024];
- int len;
- while ((len = is.read(buf)) >= 0) {
- pngOut.write(buf, 0, len);
- }
-
- // Close streams
- pngOut.close();
+ // Special handler for font files and .png resources
+ if (resourcePath.endsWith(".png")) {
+
+ BufferedImage img = ImageIO.read(is);
+ OutputStream outputStream = response.getOutputStream();
+ String formatName = "png";
+ response.setContentType("image/png");
+ ImageIO.write(img, formatName, outputStream);
+ outputStream.close();
return;
+
}
response.setCharacterEncoding("utf-8");
diff --git a/asterix-app/src/main/resources/webui/querytemplate.html b/asterix-app/src/main/resources/webui/querytemplate.html
index 3441ce2..3d435e4 100644
--- a/asterix-app/src/main/resources/webui/querytemplate.html
+++ b/asterix-app/src/main/resources/webui/querytemplate.html
@@ -6,9 +6,6 @@
<link href='http://fonts.googleapis.com/css?family=Bitter|PT+Sans+Caption|Open+Sans' rel='stylesheet' type='text/css'>
<script src="/webui/static/js/jquery.min.js"></script>
-<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.no-icons.min.css" rel="stylesheet">
-<link href="//netdna.bootstrapcdn.com/font-awesome/3.1.1/css/font-awesome.css" rel="stylesheet">
-
<link href="/webui/static/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<link href="/webui/static/css/bootstrap-responsive.min.css" rel="stylesheet" type="text/css" />
@@ -20,12 +17,14 @@
$(document).ready(function() {
$('#checkboxes-on').click(function() {
- $('#queryform :input').prop('checked', true);
- return false;
- });
-
- $('#checkboxes-off').click(function() {
- $('form#queryform :input').removeAttr('checked');
+ /* Displays a checkmark to indicate selection/clearing */
+ if ($('#opts').is(":visible")) {
+ $('#opts').hide();
+ $('#queryform :input').prop('checked', false);
+ } else {
+ $('#opts').show();
+ $('#queryform :input').prop('checked', true);
+ }
return false;
});
@@ -34,6 +33,17 @@
return false;
});
+ $('form#queryform :input').click( function () {
+ /* Hides selection check on uncheck, shows when all 5 selected */
+ if ($(this).val()) {
+ if ($(this).is(':checked') && $('input[type=checkbox]').filter(':checked').length == 5) {
+ $('#opts').show();
+ } else {
+ $('#opts').hide();
+ }
+ }
+ });
+
$("form#queryform").submit(function() {
$('#output-message').html("");
$.post("/", $("form#queryform").serialize(), function(data) {
@@ -65,7 +75,7 @@
.attr("data-toggle", "collapse")
.attr("data-target", "#collapse" + resSet)
.css("margin-bottom", "1em")
- .html('Result Plan #' + resNum + '<span id="ibtn' + resSet + '" class="icon icon-chevron-down"></span>')
+ .html('Result Plan #' + resNum + '<i id="ibtn' + resSet + '" class="icon-plus extarget"></i>')
.appendTo('#output-message');
$('<div/>')
@@ -78,11 +88,11 @@
$('#collapse' + resSet).append('<h4>' + components[pos]);
}
+ /* Placeholder for future on show/hide result plan behavior
$('#collapse' + resSet).on('show', function() {
- $("#ibtn" + resSet).removeClass("icon-chevron-down").addClass("icon-chevron-up");
}).on('hide', function() {
- $("#ibtn" + resSet).removeClass("icon-chevron-up").addClass("icon-chevron-down");
});
+ */
$('#output-message').append("<hr/>");
}
@@ -121,14 +131,16 @@
</a>
<!-- Temporary logo placeholder -->
- <!-- <a class="brand" href="#"><img src="/webui/static/img/finalasterixlogo.png"></a> -->
- <a class="brand" href="#"><img src="http://db.tt/J1MTCdKs"></a>
+ <a class="brand" href="#"><img src="/webui/static/img/finalasterixlogo.png"></a>
<div class="nav-collapse collapse">
<ul class="nav">
- <li><a href="http://code.google.com/p/asterixdb/" target="_blank">Open source<i class="icon-external-link"></i></a></li>
- <li><a href="http://code.google.com/p/asterixdb/issues/list" target="_blank">File issues<i class="icon-external-link"></i></a></li>
- <li><a href="https://groups.google.com/forum/?fromgroups#!forum/asterixdb-users" target="_blank">Contact<i class="icon-external-link"></i></a></li>
+ <li><a href="http://code.google.com/p/asterixdb/" target="_blank">
+ Open source<img class="extarget" src="/webui/static/img/targetlink.png"/></a></li>
+ <li><a href="http://code.google.com/p/asterixdb/issues/list" target="_blank">
+ File issues<img class="extarget" src="/webui/static/img/targetlink.png"/></a></li>
+ <li><a href="https://groups.google.com/forum/?fromgroups#!forum/asterixdb-users" target="_blank">
+ Contact<img class="extarget" src="/webui/static/img/targetlink.png"/></a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
@@ -148,19 +160,18 @@
</div>
<div class="btn-group">
+ <button id="checkboxes-on" class="btn"><i id="opts" class="icon-ok" ></i>Select Options</button>
<button id="clear-query-button" class="btn">Clear Query</button>
- <button id="checkboxes-on" class="btn">Select All Options</button>
- <button id="checkboxes-off" class="btn">Clear All Options</button>
+ <!-- <button id="checkboxes-off" class="btn">Clear All Options</button> -->
<button type="submit" id="run-btn" class="btn btn-custom-darken">Run</button>
</div>
<div>
- <label class="checkbox"><input type="checkbox" class="btn" checked="checked" name="print-expr-tree" value="true" /> Print parsed expressions</label>
- <label class="checkbox"><input type="checkbox" checked="checked" name="print-rewritten-expr-tree" value="true" /> Print rewritten expressions</label>
- <label class="checkbox"><input type="checkbox" checked="checked" name="print-logical-plan" value="true" /> Print logical plan</label>
- <label class="checkbox"><input type="checkbox" checked="checked" name="print-optimized-logical-plan" value="true" /> Print optimized logical plan</label>
- <label class="checkbox"><input type="checkbox"
- checked="checked" name="print-job" value="true" /> Print Hyracks job</label>
+ <label class="checkbox optlabel"><input type="checkbox" checked="checked" name="print-expr-tree" value="true" /> Print parsed expressions</label>
+ <label class="checkbox optlabel"><input type="checkbox" checked="checked" name="print-rewritten-expr-tree" value="true" /> Print rewritten expressions</label>
+ <label class="checkbox optlabel"><input type="checkbox" checked="checked" name="print-logical-plan" value="true" /> Print logical plan</label>
+ <label class="checkbox optlabel"><input type="checkbox" checked="checked" name="print-optimized-logical-plan" value="true" /> Print optimized logical plan</label>
+ <label class="checkbox optlabel"><input type="checkbox" checked="checked" name="print-job" value="true" /> Print Hyracks job</label>
</div>
</form>
</div>
diff --git a/asterix-app/src/main/resources/webui/static/css/style.css b/asterix-app/src/main/resources/webui/static/css/style.css
index 6bfd18f..041d9c0 100644
--- a/asterix-app/src/main/resources/webui/static/css/style.css
+++ b/asterix-app/src/main/resources/webui/static/css/style.css
@@ -38,6 +38,13 @@
#run-btn {
}
+#select-toggle-holder {
+ border: 1px black;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+}
+
textarea.query {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
@@ -57,6 +64,10 @@
padding-top: 10px;
}
+#opts {
+ margin-right: 4px;
+}
+
input[type=text] {
height: 20px;
}
@@ -157,8 +168,9 @@
color: #17265a;
}*/
-i {
+.extarget {
margin-left: 4px;
+ padding-bottom: 2px;
}
.btn-custom-darken.active {
diff --git a/asterix-app/src/main/resources/webui/static/img/targetlink.png b/asterix-app/src/main/resources/webui/static/img/targetlink.png
new file mode 100644
index 0000000..68ceb60
--- /dev/null
+++ b/asterix-app/src/main/resources/webui/static/img/targetlink.png
Binary files differ
diff --git a/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443-2/query-issue443-2.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443-2/query-issue443-2.1.ddl.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443-2/query-issue443-2.1.ddl.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443-2/query-issue443-2.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443-2/query-issue443-2.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443-2/query-issue443-2.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443-2/query-issue443-2.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443-2/query-issue443-2.3.query.aql
new file mode 100644
index 0000000..6b09eec
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443-2/query-issue443-2.3.query.aql
@@ -0,0 +1,11 @@
+/*
+ * Description : This test case is to verify the fix for issue443
+ : https://code.google.com/p/asterixdb/issues/detail?id=443
+ * Expected Res : Fail
+ * Date : 22th May 2013
+ */
+
+
+for $a in [ {"f" : 19, "g": 1} , {"f" : 12, "g": 2} , {"f" : 10, "g": 1} , {"f" : 17, "g": 1}, {"f" : 12, "g": 4} ]
+distinct by $a.f
+return $a
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443/query-issue443.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443/query-issue443.1.ddl.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443/query-issue443.1.ddl.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443/query-issue443.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443/query-issue443.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443/query-issue443.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443/query-issue443.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443/query-issue443.3.query.aql
new file mode 100644
index 0000000..602468c
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/distinct/query-issue443/query-issue443.3.query.aql
@@ -0,0 +1,11 @@
+/*
+ * Description : This test case is to verify the fix for issue443
+ : https://code.google.com/p/asterixdb/issues/detail?id=443
+ * Expected Res : Fail
+ * Date : 22th May 2013
+ */
+
+
+for $a in [ {"f" : 19} , {"f" : 12} , {"f" : 10} , {"f" : 17}, {"f" : 12} ]
+distinct by $a.f
+return $a
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/queries/feeds/feeds_02/feeds_02.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/feeds/feeds_02/feeds_02.3.query.aql
index 01ef318..230aa40 100644
--- a/asterix-app/src/test/resources/runtimets/queries/feeds/feeds_02/feeds_02.3.query.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/feeds/feeds_02/feeds_02.3.query.aql
@@ -8,4 +8,5 @@
use dataverse feeds;
for $x in dataset('TweetFeed')
+order by $x.id
return $x
diff --git a/asterix-app/src/test/resources/runtimets/queries/feeds/feeds_04/feeds_04.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/feeds/feeds_04/feeds_04.3.query.aql
index 5146fb5..714dd80 100644
--- a/asterix-app/src/test/resources/runtimets/queries/feeds/feeds_04/feeds_04.3.query.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/feeds/feeds_04/feeds_04.3.query.aql
@@ -8,4 +8,5 @@
use dataverse feeds;
for $x in dataset('TweetFeed')
+order by $x.id
return $x
diff --git a/asterix-app/src/test/resources/runtimets/queries/feeds/issue_230_feeds/issue_230_feeds.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/feeds/issue_230_feeds/issue_230_feeds.3.query.aql
index d94576b..48e18e2 100644
--- a/asterix-app/src/test/resources/runtimets/queries/feeds/issue_230_feeds/issue_230_feeds.3.query.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/feeds/issue_230_feeds/issue_230_feeds.3.query.aql
@@ -7,4 +7,5 @@
use dataverse feeds;
for $x in dataset('TweetFeed')
+order by $x.id
return $x
diff --git a/asterix-app/src/test/resources/runtimets/queries/hints/issue_251_dataset_hint_7/issue_251_dataset_hint_7.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/hints/issue_251_dataset_hint_7/issue_251_dataset_hint_7.3.query.aql
index efa1f9c..f1127f0 100644
--- a/asterix-app/src/test/resources/runtimets/queries/hints/issue_251_dataset_hint_7/issue_251_dataset_hint_7.3.query.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/hints/issue_251_dataset_hint_7/issue_251_dataset_hint_7.3.query.aql
@@ -9,5 +9,6 @@
use dataverse feeds;
for $x in dataset('TweetFeed')
+order by $x.id
return $x
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue423/query-issue423.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue423/query-issue423.1.ddl.aql
new file mode 100644
index 0000000..05eb126
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue423/query-issue423.1.ddl.aql
@@ -0,0 +1,8 @@
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+create type TestType as open { id : int32 ,fname:string, lname:string}
+
+create dataset t2(TestType) primary key fname,lname;
+create dataset t1(TestType) primary key fname,lname;
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue423/query-issue423.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue423/query-issue423.2.update.aql
new file mode 100644
index 0000000..71904f1
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue423/query-issue423.2.update.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+insert into dataset t1({"id":123,"fname":"John","lname":"Doe"});
+insert into dataset t1({"id":122,"fname":"Bruce","lname":"Li"});
+insert into dataset t2({"id":23,"fname":"John","lname":"Doe"});
+insert into dataset t2({"id":24,"fname":"Ravi","lname":"Khanna"});
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue423/query-issue423.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue423/query-issue423.3.query.aql
new file mode 100644
index 0000000..a07b185
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue423/query-issue423.3.query.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+for $l in dataset t1
+for $m in dataset t2
+ where $l.name=$m.name
+return {"l":$l,"m":$m};
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue442/query-issue442.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue442/query-issue442.1.ddl.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue442/query-issue442.1.ddl.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue442/query-issue442.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue442/query-issue442.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue442/query-issue442.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue442/query-issue442.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue442/query-issue442.3.query.aql
new file mode 100644
index 0000000..4da91be
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue442/query-issue442.3.query.aql
@@ -0,0 +1,10 @@
+/*
+ * Description : This test case is to verify the fix for issue442
+ : https://code.google.com/p/asterixdb/issues/detail?id=442
+ * Expected Res : Fail
+ * Date : 22th May 2013
+ */
+
+for $a in [ {"f" : 100} , {"f" : 0}, {"f" : -1}, {"f" : null}, {"f" : 999999}, {"f" : 1} , {"f" : "zzzzz"}]
+order by $a.f desc
+return $a
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/queries/spatial/create-rtree-index/create-rtree-index.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/spatial/create-rtree-index/create-rtree-index.3.query.aql
index 53b1c30..515acc0 100644
--- a/asterix-app/src/test/resources/runtimets/queries/spatial/create-rtree-index/create-rtree-index.3.query.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/spatial/create-rtree-index/create-rtree-index.3.query.aql
@@ -6,4 +6,5 @@
use dataverse test;
for $a in dataset('MyData')
+order by $a.id
return $a.id
diff --git a/asterix-app/src/test/resources/runtimets/results/distinct/query-issue443-2/query-issue443.1.adm b/asterix-app/src/test/resources/runtimets/results/distinct/query-issue443-2/query-issue443.1.adm
new file mode 100644
index 0000000..1a6e796
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/distinct/query-issue443-2/query-issue443.1.adm
@@ -0,0 +1,4 @@
+{ "f": 10, "g": 1 }
+{ "f": 12, "g": 4 }
+{ "f": 17, "g": 1 }
+{ "f": 19, "g": 1 }
diff --git a/asterix-app/src/test/resources/runtimets/results/distinct/query-issue443/query-issue443.1.adm b/asterix-app/src/test/resources/runtimets/results/distinct/query-issue443/query-issue443.1.adm
new file mode 100644
index 0000000..a4a6e48
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/distinct/query-issue443/query-issue443.1.adm
@@ -0,0 +1,4 @@
+{ "f": 10 }
+{ "f": 12 }
+{ "f": 17 }
+{ "f": 19 }
diff --git a/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue423/query-issue423.1.adm b/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue423/query-issue423.1.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue423/query-issue423.1.adm
diff --git a/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue442/query-issue442.1.adm b/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue442/query-issue442.1.adm
new file mode 100644
index 0000000..e34c554
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue442/query-issue442.1.adm
@@ -0,0 +1,7 @@
+{ "f": "zzzzz" }
+{ "f": 999999 }
+{ "f": 100 }
+{ "f": 1 }
+{ "f": 0 }
+{ "f": -1 }
+{ "f": null }
diff --git a/asterix-app/src/test/resources/runtimets/results/spatial/create-rtree-index/create-rtree-index.1.adm b/asterix-app/src/test/resources/runtimets/results/spatial/create-rtree-index/create-rtree-index.1.adm
index b9c6dc7..d4de868 100644
--- a/asterix-app/src/test/resources/runtimets/results/spatial/create-rtree-index/create-rtree-index.1.adm
+++ b/asterix-app/src/test/resources/runtimets/results/spatial/create-rtree-index/create-rtree-index.1.adm
@@ -1,21 +1,21 @@
-2
-4
-6
-8
-10
-12
-14
-16
-18
-20
1
+2
3
+4
5
+6
7
+8
9
+10
11
+12
13
+14
15
+16
17
+18
19
+20
21
diff --git a/asterix-app/src/test/resources/runtimets/testsuite.xml b/asterix-app/src/test/resources/runtimets/testsuite.xml
index 956c76d..9e6c308 100644
--- a/asterix-app/src/test/resources/runtimets/testsuite.xml
+++ b/asterix-app/src/test/resources/runtimets/testsuite.xml
@@ -2805,6 +2805,12 @@
<output-dir compare="Text">query-issue258</output-dir>
</compilation-unit>
</test-case>
+ <test-case FilePath="open-closed">
+ <compilation-unit name="query-issue442">
+ <output-dir compare="Text">query-issue442</output-dir>
+ <expected-error>edu.uci.ics.asterix.common.exceptions.AsterixException</expected-error>
+ </compilation-unit>
+ </test-case>
</test-group>
<test-group name="quantifiers">
<test-case FilePath="quantifiers">
@@ -4349,4 +4355,16 @@
</compilation-unit>
</test-case>
</test-group>
+ <test-group name="distinct">
+ <test-case FilePath="distinct">
+ <compilation-unit name="query-issue443">
+ <output-dir compare="Text">query-issue443</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="distinct">
+ <compilation-unit name="query-issue443-2">
+ <output-dir compare="Text">query-issue443-2</output-dir>
+ </compilation-unit>
+ </test-case>
+ </test-group>
</test-suite>
diff --git a/asterix-doc/src/site/markdown/AsterixQueryLanguageReference.md b/asterix-doc/src/site/markdown/AsterixQueryLanguageReference.md
index c9ed3e2..1ed876e 100644
--- a/asterix-doc/src/site/markdown/AsterixQueryLanguageReference.md
+++ b/asterix-doc/src/site/markdown/AsterixQueryLanguageReference.md
@@ -3,38 +3,79 @@
This document provides an overview of the Asterix Query language.
+
## 2. Expressions
Expression ::= ( OperatorExpr | IfThenElse | FLWOGR | QuantifiedExpression )
+
### Primary Expressions
- PrimaryExpr ::= Literal | VariableRef | ParenthesizedExpression | FunctionCallExpr
- | DatasetAccessExpression | ListConstructor | RecordConstructor
+ PrimaryExpr ::= Literal
+ | VariableRef
+ | ParenthesizedExpression
+ | FunctionCallExpr
+ | DatasetAccessExpression
+ | ListConstructor
+ | RecordConstructor
+
#### Literals
- Literal ::= StringLiteral | <INTEGER_LITERAL> | <FLOAT_LITERAL> | <DOUBLE_LITERAL> | <NULL> | <TRUE> | <FALSE>
+ Literal ::= StringLiteral
+ | <INTEGER_LITERAL>
+ | <FLOAT_LITERAL>
+ | <DOUBLE_LITERAL>
+ | "null"
+ | "true"
+ | "false"
StringLiteral ::= <STRING_LITERAL>
+##### Examples
+
+ "a string"
+ 42
+
+
#### Variable References
VariableRef ::= <VARIABLE>
+
+##### Example
+
+ $id
+
#### Parenthesized Expressions
- ParenthesizedExpression ::= <LEFTPAREN> Expression <RIGHTPAREN>
+ ParenthesizedExpression ::= "(" Expression ")"
+
+##### Example
+
+ ( 1 + 1 )
+
#### Function Calls
- FunctionCallExpr ::= FunctionOrTypeName <LEFTPAREN> ( Expression ( "," Expression )* )? <RIGHTPAREN>
-
+ FunctionCallExpr ::= FunctionOrTypeName "(" ( Expression ( "," Expression )* )? ")"
+
+##### Example
+
+ string-length("a string")
+
+
#### Dataset Access
- DatasetAccessExpression ::= <DATASET> ( ( Identifier ( "." Identifier )? )
- | ( <LEFTPAREN> Expression ( "," Expression )* <RIGHTPAREN> ) )
+ DatasetAccessExpression ::= "dataset" ( ( Identifier ( "." Identifier )? )
+ | ( "(" Expression ")" ) )
Identifier ::= <IDENTIFIER> | StringLiteral
+##### Examples
+
+ dataset customers
+ dataset (string-join("customers", $country))
+
+
#### Constructors
ListConstructor ::= ( OrderedListConstructor | UnorderedListConstructor )
@@ -43,20 +84,51 @@
RecordConstructor ::= "{" ( FieldBinding ( "," FieldBinding )* )? "}"
FieldBinding ::= Expression ":" Expression
+##### Examples
+
+ [ "a", "b", "c" ]
+
+ {{ 42, "forty-two", "AsterixDB!" }}
+
+ {
+ "project name" : "AsterixDB"
+ "project members" : {{ "vinayakb", "dtabass", "chenli" }}
+ }
+
+
### Path Expressions
ValueExpr ::= PrimaryExpr ( Field | Index )*
Field ::= "." Identifier
Index ::= "[" ( Expression | "?" ) "]"
+##### Examples
+
+ { "list" : [ "a", "b", "c"] }.list
+
+ [ "a", "b", "c"][2]
+
+ { "list" : [ "a", "b", "c"] }.list[2]
+
+
### Logical Expressions
OperatorExpr ::= AndExpr ( "or" AndExpr )*
AndExpr ::= RelExpr ( "and" RelExpr )*
+##### Example
+
+ $a > 3 and $a < 5
+
+
### Comparison Expressions
RelExpr ::= AddExpr ( ( "<" | ">" | "<=" | ">=" | "=" | "!=" | "~=" ) AddExpr )?
+
+##### Example
+
+ 5 > 3
+
### Arithmetic Expressions
@@ -64,6 +136,11 @@
MultExpr ::= UnaryExpr ( ( "*" | "/" | "%" | <CARET> | "idiv" ) UnaryExpr )*
UnaryExpr ::= ( ( "+" | "-" ) )? ValueExpr
+##### Example
+
+ 3 ^ 2 + 4 ^ 2
+
+
### FLWOGR Expression
FLWOGR ::= ( ForClause | LetClause ) ( Clause )* "return" Expression
@@ -81,16 +158,99 @@
Variable ::= <VARIABLE>
+##### Example
+
+ for $user in dataset FacebookUsers
+ where $user.id = 8
+ return $user
+
+##### Example
+
+ for $user in dataset FacebookUsers
+ for $message in dataset FacebookMessages
+ where $message.author-id = $user.id
+ return
+ {
+ "uname": $user.name,
+ "message": $message.message
+ };
+
+##### Example
+
+ for $user in dataset FacebookUsers
+ let $messages :=
+ for $message in dataset FacebookMessages
+ where $message.author-id = $user.id
+ return $message.message
+ return
+ {
+ "uname": $user.name,
+ "messages": $messages
+ };
+
+##### Example
+
+ for $user in dataset TwitterUsers
+ order by $user.followers_count desc, $user.lang asc
+ return $user
+
+* null is smaller than any other value
+
+##### Example
+
+ for $x in dataset FacebookMessages
+ let $messages := $x.message
+ group by $loc := $x.sender-location with $messages
+ return
+ {
+ "location" : $loc,
+ "message" : $messages
+ }
+
+* after group by only variables that are either in the group-by-list or in the with-list are in scope
+* the variables in the with-clause contain a collection of items after the group by clause (all the values that the variable was bound to in the tuples that make up the group)
+* null is handled as a single value for grouping
+
+##### Example
+
+ for $user in dataset TwitterUsers
+ order by $user.followers_count desc
+ limit 2
+ return $user
+
+##### Example (currently not working)
+
+ for $x in dataset FacebookMessages
+ distinct by $x.sender-location
+ return
+ {
+ "location" : $x.sender-location,
+ "message" : $x.message
+ }
+
+* every variable that is in-scope before the distinct clause is also in scope after the distinct clause
+* works a lot like group by, but for every variable that contains more than one value after the distinct-by clause, one value is picked non-deterministically
+* if the variable is in the disctict-by list, then value is deterministic
+* null is a single value
+
### Conditional Expression
- IfThenElse ::= "if" <LEFTPAREN> Expression <RIGHTPAREN> "then" Expression "else" Expression
+ IfThenElse ::= "if" "(" Expression ")" "then" Expression "else" Expression
+
+##### Example
+
+ if (2 < 3) then "yes" else "no"
### Quantified Expressions
QuantifiedExpression ::= ( ( "some" ) | ( "every" ) ) Variable "in" Expression
( "," Variable "in" Expression )* "satisfies" Expression
+
+##### Examples
+ every $x in [ 1, 2, 3] satisfies $x < 3
+ some $x in [ 1, 2, 3] satisfies $x < 3
## 3. Statements
@@ -103,7 +263,6 @@
| SetStatement
| InsertStatement
| DeleteStatement
- | FeedStatement
| Query
### Declarations
@@ -111,21 +270,48 @@
DataverseDeclaration ::= "use" "dataverse" Identifier
SetStatement ::= "set" Identifier StringLiteral
FunctionDeclaration ::= "declare" "function" Identifier ParameterList "{" Expression "}"
- ParameterList ::= <LEFTPAREN> ( <VARIABLE> ( "," <VARIABLE> )* )? <RIGHTPAREN>
+ ParameterList ::= "(" ( <VARIABLE> ( "," <VARIABLE> )* )? ")"
+
+##### Example
+
+ use dataverse TinySocial;
+
+##### Example
+
+ set simfunction "jaccard";
+ set simthreshold "0.6f";
+
+##### Example
+
+ set simfunction "jaccard";
+ set simthreshold "0.6f";
+
+##### Example
+
+ declare function add($a, $b) {
+ $a + $b
+ };
### Lifecycle Management Statements
- CreateStatement ::= "create" ( TypeSpecification | DatasetSpecification | IndexSpecification | DataverseSpecification | FunctionSpecification )
+ CreateStatement ::= "create" ( DataverseSpecification
+ | TypeSpecification
+ | DatasetSpecification
+ | IndexSpecification
+ | FunctionSpecification )
- DropStatement ::= "drop" ( <DATASET> QualifiedName IfExists
- | "index" DoubleQualifiedName IfExists
- | "type" FunctionOrTypeName IfExists
- | "dataverse" Identifier IfExists
- | "function" FunctionSignature IfExists )
- IfExists ::= ( "if" "exists" )?
QualifiedName ::= Identifier ( "." Identifier )?
DoubleQualifiedName ::= Identifier "." Identifier ( "." Identifier )?
+#### Dataverses
+
+ DataverseSpecification ::= "dataverse" Identifier IfNotExists ( "with format" StringLiteral )?
+
+
+##### Example
+
+ create dataverse TinySocial;
+
#### Types
TypeSpecification ::= "type" FunctionOrTypeName IfNotExists "as" TypeExpr
@@ -137,55 +323,140 @@
TypeReference ::= Identifier
OrderedListTypeDef ::= "[" ( TypeExpr ) "]"
UnorderedListTypeDef ::= "{{" ( TypeExpr ) "}}"
-
+
+##### Example
+
+ create type FacebookUserType as closed {
+ id: int32,
+ alias: string,
+ name: string,
+ user-since: datetime,
+ friend-ids: {{ int32 }},
+ employment: [EmploymentType]
+ }
+
+
#### Datasets
- DatasetSpecification ::= "external" <DATASET> QualifiedName <LEFTPAREN> Identifier <RIGHTPAREN> IfNotExists
- "using" AdapterName Configuration ( "hints" Properties )?
- | "feed" <DATASET> QualifiedName <LEFTPAREN> Identifier <RIGHTPAREN> IfNotExists
- "using" AdapterName Configuration ( ApplyFunction )? PrimaryKey ( "on" Identifier )? ( "hints" Properties )?
- | "internal"? <DATASET> QualifiedName <LEFTPAREN> Identifier <RIGHTPAREN> IfNotExists
- PrimaryKey ( "on" Identifier )? ( "hints" Properties )?
+ DatasetSpecification ::= "internal"? "dataset" QualifiedName "(" Identifier ")" IfNotExists
+ PrimaryKey ( "on" Identifier )? ( "hints" Properties )?
+ | "external" "dataset" QualifiedName "(" Identifier ")" IfNotExists
+ "using" AdapterName Configuration ( "hints" Properties )?
AdapterName ::= Identifier
- Configuration ::= <LEFTPAREN> ( KeyValuePair ( "," KeyValuePair )* )? <RIGHTPAREN>
- KeyValuePair ::= <LEFTPAREN> StringLiteral "=" StringLiteral <RIGHTPAREN>
- Properties ::= ( <LEFTPAREN> Property ( "," Property )* <RIGHTPAREN> )?
+ Configuration ::= "(" ( KeyValuePair ( "," KeyValuePair )* )? ")"
+ KeyValuePair ::= "(" StringLiteral "=" StringLiteral ")"
+ Properties ::= ( "(" Property ( "," Property )* ")" )?
Property ::= Identifier "=" ( StringLiteral | <INTEGER_LITERAL> )
ApplyFunction ::= "apply" "function" FunctionSignature
FunctionSignature ::= FunctionOrTypeName "@" <INTEGER_LITERAL>
PrimaryKey ::= "primary" "key" Identifier ( "," Identifier )*
+
+##### Example
+ create internal dataset FacebookUsers(FacebookUserType) primary key id;
+
+##### Example
+
+ create external dataset Lineitem(LineitemType) using localfs (
+ ("path"="127.0.0.1://SOURCE_PATH"),
+ ("format"="delimited-text"),
+ ("delimiter"="|"));
+
#### Indices
- IndexSpecification ::= "index" Identifier IfNotExists "on" QualifiedName <LEFTPAREN> ( Identifier ) ( "," Identifier )* <RIGHTPAREN> ( "type" IndexType )?
- IndexType ::= "btree" | "rtree" | "keyword" | "fuzzy keyword" | "ngram" <LEFTPAREN> <INTEGER_LITERAL> <RIGHTPAREN> | "fuzzy ngram" <LEFTPAREN> <INTEGER_LITERAL> <RIGHTPAREN>
+ IndexSpecification ::= "index" Identifier IfNotExists "on" QualifiedName
+ "(" ( Identifier ) ( "," Identifier )* ")" ( "type" IndexType )?
+ IndexType ::= "btree"
+ | "rtree"
+ | "keyword"
+ | "fuzzy keyword"
+ | "ngram" "(" <INTEGER_LITERAL> ")"
+ | "fuzzy ngram" "(" <INTEGER_LITERAL> ")"
-#### Dataverses
+##### Example
- DataverseSpecification ::= "dataverse" Identifier IfNotExists ( "with format" StringLiteral )?
+ create index fbAuthorIdx on FacebookMessages(author-id) type btree;
+
+##### Example
+
+ create index fbSenderLocIndex on FacebookMessages(sender-location) type rtree;
+
+##### Example
+
+ create index fbMessageIdx on FacebookMessages(message) type keyword;
+
#### Functions
- FunctionSpecification ::= "function" FunctionOrTypeName IfNotExists ParameterList "{" Expression "}"
+ FunctionSpecification ::= "function" FunctionOrTypeName IfNotExists ParameterList "{" Expression "}"
+
+##### Example
+
+ create function add($a, $b) {
+ $a + $b
+ };
+
+
+#### Removal
+
+ DropStatement ::= "drop" ( "dataverse" Identifier IfExists
+ | "type" FunctionOrTypeName IfExists
+ | "dataset" QualifiedName IfExists
+ | "index" DoubleQualifiedName IfExists
+ | "function" FunctionSignature IfExists )
+ IfExists ::= ( "if" "exists" )?
+
+##### Example
+
+ drop dataset FacebookUsers if exists;
+
+##### Example
+
+ drop index fbSenderLocIndex;
+
+##### Example
+
+ drop type FacebookUserType;
+
+##### Example
+
+ drop dataverse TinySocial;
+
+##### Example
+
+ drop function add;
+
### Import/Export Statements
- LoadStatement ::= "load" <DATASET> QualifiedName "using" AdapterName Configuration ( "pre-sorted" )?
+ LoadStatement ::= "load" "dataset" QualifiedName "using" AdapterName Configuration ( "pre-sorted" )?
+
+##### Example
+
+ load dataset FacebookUsers using localfs
+ (("path"="localhost:///Users/zuck/AsterixDB/load/fbu.adm"),("format"="adm"));
+
### Modification Statements
- InsertStatement ::= "insert" "into" <DATASET> QualifiedName Query
- DeleteStatement ::= "delete" Variable "from" <DATASET> QualifiedName ( "where" Expression )?
+ InsertStatement ::= "insert" "into" "dataset" QualifiedName Query
+ DeleteStatement ::= "delete" Variable "from" "dataset" QualifiedName ( "where" Expression )?
+
+##### Example
-### Feed Management Statements
+ insert into dataset UsersCopy (for $user in dataset FacebookUsers return $user)
- FeedStatement ::= "begin" "feed" QualifiedName
- | "suspend" "feed" QualifiedName
- | "resume" "feed" QualifiedName
- | "end" "feed" QualifiedName
- | "alter" "feed" QualifiedName "set" Configuration
+##### Example
+
+ delete $user from dataset FacebookUsers where $user.id = 8;
+
### Queries
Query ::= Expression
+##### Example
+
+ for $praise in {{ "great", "brilliant", "awesome" }}
+ return
+ string-concat(["AsterixDB is ", $praise])
diff --git a/asterix-doc/src/site/markdown/index.md b/asterix-doc/src/site/markdown/index.md
new file mode 100644
index 0000000..cba2fdc
--- /dev/null
+++ b/asterix-doc/src/site/markdown/index.md
@@ -0,0 +1 @@
+# AsterixDB
diff --git a/asterix-doc/src/site/site.xml b/asterix-doc/src/site/site.xml
new file mode 100644
index 0000000..6724153
--- /dev/null
+++ b/asterix-doc/src/site/site.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<project name="AsterixDB" xmlns="http://maven.apache.org/DECORATION/1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/DECORATION/1.0.0 http://maven.apache.org/xsd/decoration-1.0.0.xsd">
+ <!--
+ <bannerLeft>
+ <name>Asterix</name>
+ <src>http://asterix.ics.uci.edu/pic/img9.jpg</src>
+ <href>http://asterix.ics.uci.edu/</href>
+ </bannerLeft>
+ -->
+
+ <skin>
+ <groupId>org.apache.maven.skins</groupId>
+ <artifactId>maven-fluido-skin</artifactId>
+ <version>1.2.1</version>
+ </skin>
+ <custom>
+ <fluidoSkin>
+ <sideBarEnabled>true</sideBarEnabled>
+ <!-- <googlePlusOne /> -->
+ </fluidoSkin>
+ </custom>
+
+ <body>
+ <links>
+ <item name="Home" href="index.html"/>
+ </links>
+
+ <menu name="Documentation">
+ <item name="AsterixDB: A Big Data Management System" href="AsterixAlphaRelease.html"/>
+ <item name="Installing Asterix using Managix" href="InstallingAsterixUsingManagix.html"/>
+ <item name="AsterixDB 101: An ADM and AQL Primer" href="AdmAql101.html"/>
+ <item name="Asterix Data Model (ADM)" href="AsterixDBDataModel.html"/>
+ <item name="AsterixDB Functions" href="AsterixDBFunctions.html"/>
+ <item name="The Asterix Query Language" href="AsterixQueryLanguageReference.html"/>
+ <item name="AsterixDB Support of Similarity Queries" href="AsterixSimilarityQueries.html"/>
+ <item name="Accessing External Data in AsterixDB" href="AccessingExternalDataInAsterixDB.html"/>
+ <item name="REST API to AsterixDB" href="AsterixDBRestAPI.html"/>
+ <item name="(old AQL doc)" href="AsterixQueryLanguage.html"/>
+ </menu>
+
+ <menu ref="reports"/>
+ </body>
+</project>
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/comparators/AObjectAscBinaryComparatorFactory.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/comparators/AObjectAscBinaryComparatorFactory.java
index 865ab94..f795b17 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/comparators/AObjectAscBinaryComparatorFactory.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/comparators/AObjectAscBinaryComparatorFactory.java
@@ -62,8 +62,13 @@
return 1;
}
- ATypeTag tag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(b1[s1]);
- switch (tag) {
+ ATypeTag tag1 = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(b1[s1]);
+ ATypeTag tag2 = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(b2[s2]);
+ if (tag1 != tag2) {
+ throw new IllegalStateException("The values of two inconsistent types (" + tag1 + " and " + tag2
+ + ") cannot be compared!");
+ }
+ switch (tag1) {
case BOOLEAN: {
return ascBoolComp.compare(b1, s1 + 1, l1 - 1, b2, s2 + 1, l2 - 1);
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlBinaryHashFunctionFactoryProvider.java b/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlBinaryHashFunctionFactoryProvider.java
index 33698bd..7bfdb050 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlBinaryHashFunctionFactoryProvider.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlBinaryHashFunctionFactoryProvider.java
@@ -106,7 +106,7 @@
@Override
public int hash(byte[] bytes, int offset, int length) {
- return bhf.hash(bytes, offset + 1, length);
+ return bhf.hash(bytes, offset + 1, length - 1);
}
};
}