m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin <marcin.j.chrzanowski@gmail.com>2019-11-23 16:18:49 +0100
committerGitHub <noreply@github.com>2019-11-23 16:18:49 +0100
commit22f6a3082d5e9698e3be4208ca68cd6724239fd0 (patch)
tree6dd78ad1333c18f3b1578b2958d9c7ef687a25c1
parentd683a761b2710a252b0bfb1b3f0879a60247bb50 (diff)
Interpreter conversions (#26)
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/interpreter/Interpreter.java9
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/interpreter/ResultColumn.java16
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/model/ValueDuration.java8
-rw-r--r--src/test/java/pl/edu/mimuw/cloudatlas/interpreter/InterpreterTests.java484
4 files changed, 501 insertions, 16 deletions
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/interpreter/Interpreter.java b/src/main/java/pl/edu/mimuw/cloudatlas/interpreter/Interpreter.java
index 289f99d..6129f48 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/interpreter/Interpreter.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/interpreter/Interpreter.java
@@ -329,8 +329,13 @@ public class Interpreter {
}
public Result visit(CondExprAndC expr, Environment env) {
- // TODO
- throw new UnsupportedOperationException("CondExprAndC Not yet implemented");
+ try {
+ Result left = expr.condexpr_1.accept(new CondExprInterpreter(), env);
+ Result right = expr.condexpr_2.accept(new CondExprInterpreter(), env);
+ return left.and(right);
+ } catch(Exception exception) {
+ throw new InsideQueryException(PrettyPrinter.print(expr), exception);
+ }
}
public Result visit(CondExprNotC expr, Environment env) {
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/interpreter/ResultColumn.java b/src/main/java/pl/edu/mimuw/cloudatlas/interpreter/ResultColumn.java
index b551955..1c0db30 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/interpreter/ResultColumn.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/interpreter/ResultColumn.java
@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import pl.edu.mimuw.cloudatlas.model.Type;
+import pl.edu.mimuw.cloudatlas.model.TypePrimitive;
import pl.edu.mimuw.cloudatlas.model.TypeCollection;
import pl.edu.mimuw.cloudatlas.model.Value;
import pl.edu.mimuw.cloudatlas.model.ValueBoolean;
@@ -100,7 +101,7 @@ class ResultColumn extends Result {
@Override
public Result random(int size) {
- return new ResultColumn(
+ return new ResultSingle(
randomList(
new ValueList(
column,
@@ -124,13 +125,18 @@ class ResultColumn extends Result {
@Override
public ResultSingle isNull() {
- throw new UnsupportedOperationException("Operation isNull not supported yet.");
- // return new ResultSingle(new ValueBoolean(value.isNull()));
+ return new ResultSingle(new ValueBoolean(true));
}
@Override
public Type getType() {
- throw new UnsupportedOperationException("Operation getType not supported yet.");
- // return value.getType();
+ Type type = TypePrimitive.NULL;
+ for (Value value : column) {
+ if (value.getType() != TypePrimitive.NULL) {
+ type = value.getType();
+ }
+ }
+
+ return type;
}
}
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/model/ValueDuration.java b/src/main/java/pl/edu/mimuw/cloudatlas/model/ValueDuration.java
index 7a74776..ad14a30 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/model/ValueDuration.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/model/ValueDuration.java
@@ -264,9 +264,9 @@ public class ValueDuration extends ValueSimple<Long> {
remainingUnits /= 24;
long days = remainingUnits;
- return (positive ? "+" : "-") + Long.toString(days) + " " + Long.toString(hours)
- + ":" + Long.toString(minutes) + ":" + Long.toString(seconds) + "." +
- Long.toString(milliseconds);
+ return (positive ? "+" : "-") + String.format("%d %02d:%02d:%02d.%03d",
+ days, hours, minutes, seconds, milliseconds
+ );
}
@Override
@@ -274,6 +274,8 @@ public class ValueDuration extends ValueSimple<Long> {
switch(type.getPrimaryType()) {
case STRING:
return getValue() == null? ValueString.NULL_STRING : new ValueString(makeString());
+ case INT:
+ return new ValueInt(getValue() == null? null : getValue());
case DURATION:
return this;
default:
diff --git a/src/test/java/pl/edu/mimuw/cloudatlas/interpreter/InterpreterTests.java b/src/test/java/pl/edu/mimuw/cloudatlas/interpreter/InterpreterTests.java
index 3d8584d..aaac9ce 100644
--- a/src/test/java/pl/edu/mimuw/cloudatlas/interpreter/InterpreterTests.java
+++ b/src/test/java/pl/edu/mimuw/cloudatlas/interpreter/InterpreterTests.java
@@ -7,12 +7,14 @@ import java.io.File;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URL;
+import java.util.Calendar;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.Ignore;
import pl.edu.mimuw.cloudatlas.model.AttributesMap;
+import pl.edu.mimuw.cloudatlas.model.ValueBoolean;
import pl.edu.mimuw.cloudatlas.model.ValueTime;
import pl.edu.mimuw.cloudatlas.model.ZMI;
@@ -35,6 +37,467 @@ public class InterpreterTests {
}
@Test
+ public void testAvg() throws Exception {
+ assertInterpreterRun(
+ "SELECT avg(cpu_usage) AS cpu_usage",
+ new String[] {
+ "/uw: cpu_usage: 0.5",
+ "/pjwstk: cpu_usage: 0.25",
+ "/: cpu_usage: 0.375",
+ }
+ );
+ }
+
+ @Test
+ public void testCount() throws Exception {
+ assertInterpreterRun(
+ "SELECT count(cpu_usage) AS cpu_usage",
+ new String[] {
+ "/uw: cpu_usage: 2",
+ "/pjwstk: cpu_usage: 2",
+ "/: cpu_usage: 2",
+ }
+ );
+ }
+
+ @Test
+ public void testSum() throws Exception {
+ assertInterpreterRun(
+ "SELECT sum(cpu_usage) AS cpu_usage",
+ new String[] {
+ "/uw: cpu_usage: 1.0",
+ "/pjwstk: cpu_usage: 0.5",
+ "/: cpu_usage: 1.5",
+ }
+ );
+ }
+
+ @Test
+ public void testFirst() throws Exception {
+ assertInterpreterRun(
+ "SELECT first(1, unfold(php_modules)) AS php_modules",
+ new String[] {
+ "/pjwstk: php_modules: [rewrite]",
+ "/: php_modules: [rewrite]",
+ }
+ );
+ }
+
+ @Test
+ public void testLast() throws Exception {
+ assertInterpreterRun(
+ "SELECT last(1, unfold(php_modules)) AS php_modules",
+ new String[] {
+ "/pjwstk: php_modules: [odbc]",
+ "/: php_modules: [odbc]",
+ }
+ );
+ }
+
+ @Test
+ public void testRandom() throws Exception {
+ String query = "SELECT random(1, unfold(php_modules)) AS php_modules";
+ ByteArrayInputStream in = new ByteArrayInputStream(query.getBytes());
+ String output = runInterpreter(in);
+ String expected1 = join(new String[] {
+ "/pjwstk: php_modules: [odbc]",
+ "/: php_modules: [odbc]",
+ });
+ String expected2 = join(new String[] {
+ "/pjwstk: php_modules: [rewrite]",
+ "/: php_modules: [rewrite]",
+ });
+
+ assertTrue(output.equals(expected1) || output.equals(expected2));
+ }
+
+ @Test
+ public void testMin() throws Exception {
+ assertInterpreterRun(
+ "SELECT min(cpu_usage) AS cpu_usage",
+ new String[] {
+ "/uw: cpu_usage: 0.1",
+ "/pjwstk: cpu_usage: 0.1",
+ "/: cpu_usage: 0.1",
+ }
+ );
+ }
+
+ @Test
+ public void testMax() throws Exception {
+ assertInterpreterRun(
+ "SELECT max(cpu_usage) AS cpu_usage",
+ new String[] {
+ "/uw: cpu_usage: 0.9",
+ "/pjwstk: cpu_usage: 0.4",
+ "/: cpu_usage: 0.9",
+ }
+ );
+ }
+
+ @Test
+ public void testLand() throws Exception {
+ assertInterpreterRun(
+ "SELECT max(cpu_usage) AS cpu_usage; SELECT land(cpu_usage < 0.5) AS low_cpu",
+ new String[] {
+ "/uw: cpu_usage: 0.9",
+ "/uw: low_cpu: false",
+ "/pjwstk: cpu_usage: 0.4",
+ "/pjwstk: low_cpu: true",
+ "/: cpu_usage: 0.9",
+ "/: low_cpu: false",
+ }
+ );
+ }
+
+ @Test
+ public void testLor() throws Exception {
+ assertInterpreterRun(
+ "SELECT max(cpu_usage) AS cpu_usage; SELECT lor(cpu_usage > 0.5) AS high_cpu",
+ new String[] {
+ "/uw: cpu_usage: 0.9",
+ "/uw: high_cpu: true",
+ "/pjwstk: cpu_usage: 0.4",
+ "/pjwstk: high_cpu: false",
+ "/: cpu_usage: 0.9",
+ "/: high_cpu: true",
+ }
+ );
+ }
+
+ @Test
+ public void testNow() throws Exception {
+ ValueTime timeBefore = new ValueTime(Calendar.getInstance().getTimeInMillis());
+ String query = "SELECT now() AS now";
+ ByteArrayInputStream in = new ByteArrayInputStream(query.getBytes());
+ String output = runInterpreter(in);
+ ValueTime timeAfter = new ValueTime(Calendar.getInstance().getTimeInMillis());
+ String[] lines = output.split("\n");
+ assertEquals(3, lines.length);
+ for (String line : lines) {
+ String timestamp = line.split(":", 3)[2];
+ ValueTime resultTime = new ValueTime(timestamp);
+ assertFalse(((ValueBoolean) resultTime.isLowerThan(timeBefore)).getValue());
+ assertFalse(((ValueBoolean) timeAfter.isLowerThan(resultTime)).getValue());
+ }
+ }
+
+ @Test
+ public void testEpoch() throws Exception {
+ assertInterpreterRun(
+ "SELECT epoch() AS epoch",
+ new String[] {
+ "/uw: epoch: 2000/01/01 00:00:00.000",
+ "/pjwstk: epoch: 2000/01/01 00:00:00.000",
+ "/: epoch: 2000/01/01 00:00:00.000",
+ }
+ );
+ }
+
+ @Test
+ public void testSize() throws Exception {
+ assertInterpreterRun(
+ "SELECT max(size(name)) AS max_len_name",
+ new String[] {
+ "/uw: max_len_name: 8",
+ "/pjwstk: max_len_name: 10",
+ "/: max_len_name: 6",
+ }
+ );
+ }
+
+ @Test
+ public void testRound() throws Exception {
+ assertInterpreterRun(
+ "SELECT max(cpu_usage) AS cpu_usage; SELECT round(max(cpu_usage)) AS approximate_cpu",
+ new String[] {
+ "/uw: cpu_usage: 0.9",
+ "/uw: approximate_cpu: 1.0",
+ "/pjwstk: cpu_usage: 0.4",
+ "/pjwstk: approximate_cpu: 0.0",
+ "/: cpu_usage: 0.9",
+ "/: approximate_cpu: 1.0",
+ }
+ );
+ }
+
+ @Test
+ public void testFloor() throws Exception {
+ assertInterpreterRun(
+ "SELECT max(cpu_usage) AS cpu_usage; SELECT floor(0.2 + max(cpu_usage)) AS approximate_cpu",
+ new String[] {
+ "/uw: cpu_usage: 0.9",
+ "/uw: approximate_cpu: 1.0",
+ "/pjwstk: cpu_usage: 0.4",
+ "/pjwstk: approximate_cpu: 0.0",
+ "/: cpu_usage: 0.9",
+ "/: approximate_cpu: 1.0",
+ }
+ );
+ }
+
+ @Test
+ public void testCeil() throws Exception {
+ assertInterpreterRun(
+ "SELECT max(cpu_usage) AS cpu_usage; SELECT ceil(0.2 + max(cpu_usage)) AS approximate_cpu",
+ new String[] {
+ "/uw: cpu_usage: 0.9",
+ "/uw: approximate_cpu: 2.0",
+ "/pjwstk: cpu_usage: 0.4",
+ "/pjwstk: approximate_cpu: 1.0",
+ "/: cpu_usage: 0.9",
+ "/: approximate_cpu: 2.0",
+ }
+ );
+ }
+
+ @Test
+ public void testBoolToString() throws Exception {
+ assertInterpreterRun(
+ "SELECT to_string(true) + \"x\" AS truex",
+ new String[] {
+ "/uw: truex: truex",
+ "/pjwstk: truex: truex",
+ "/: truex: truex",
+ }
+ );
+ }
+
+ @Test
+ public void testStringToBool() throws Exception {
+ assertInterpreterRun(
+ "SELECT to_boolean(\"true\") AND true AS tru",
+ new String[] {
+ "/uw: tru: true",
+ "/pjwstk: tru: true",
+ "/: tru: true",
+ }
+ );
+ }
+
+ @Test
+ public void testIntToString() throws Exception {
+ assertInterpreterRun(
+ "SELECT to_string(1) + \"x\" AS onex",
+ new String[] {
+ "/uw: onex: 1x",
+ "/pjwstk: onex: 1x",
+ "/: onex: 1x",
+ }
+ );
+ }
+
+ @Test
+ public void testStringToInt() throws Exception {
+ assertInterpreterRun(
+ "SELECT to_integer(\"1\") + 1 AS two",
+ new String[] {
+ "/uw: two: 2",
+ "/pjwstk: two: 2",
+ "/: two: 2",
+ }
+ );
+ }
+
+ @Test
+ public void testDoublePlusIntFails() throws Exception {
+ assertInterpreterRun(
+ "SELECT 1 + 1.0 AS two",
+ new String[] {
+ }
+ );
+ }
+
+ @Test
+ public void testDoubleToInt() throws Exception {
+ assertInterpreterRun(
+ "SELECT 1 + to_integer(1.0) AS two",
+ new String[] {
+ "/uw: two: 2",
+ "/pjwstk: two: 2",
+ "/: two: 2",
+ }
+ );
+ }
+
+ @Test
+ public void testIntToDouble() throws Exception {
+ assertInterpreterRun(
+ "SELECT to_double(1) + 1.0 AS two",
+ new String[] {
+ "/uw: two: 2.0",
+ "/pjwstk: two: 2.0",
+ "/: two: 2.0",
+ }
+ );
+ }
+
+ @Test
+ public void testIntToDuration() throws Exception {
+ assertInterpreterRun(
+ "SELECT to_duration(1) AS one_ms",
+ new String[] {
+ "/uw: one_ms: +0 00:00:00.001",
+ "/pjwstk: one_ms: +0 00:00:00.001",
+ "/: one_ms: +0 00:00:00.001",
+ }
+ );
+ }
+
+ @Test
+ public void testDurationToInt() throws Exception {
+ assertInterpreterRun(
+ "SELECT to_integer(to_duration(1)) AS one",
+ new String[] {
+ "/uw: one: 1",
+ "/pjwstk: one: 1",
+ "/: one: 1",
+ }
+ );
+ }
+
+ @Test
+ public void testDoubleToString() throws Exception {
+ assertInterpreterRun(
+ "SELECT to_string(1.0) + \"x\" AS onex",
+ new String[] {
+ "/uw: onex: 1.0x",
+ "/pjwstk: onex: 1.0x",
+ "/: onex: 1.0x",
+ }
+ );
+ }
+
+ @Test
+ public void testStringToDouble() throws Exception {
+ assertInterpreterRun(
+ "SELECT to_double(\"1.0\") + 1.0 AS two",
+ new String[] {
+ "/uw: two: 2.0",
+ "/pjwstk: two: 2.0",
+ "/: two: 2.0",
+ }
+ );
+ }
+
+ @Test
+ public void testSetToList() throws Exception {
+ assertInterpreterRun(
+ "SELECT first(5, unfold(to_list(php_modules) + to_list(php_modules))) AS php_modules",
+ new String[] {
+ "/pjwstk: php_modules: [rewrite, rewrite, odbc, odbc]",
+ "/: php_modules: [rewrite, rewrite, odbc, odbc, rewrite]"
+ }
+ );
+ }
+
+ @Test
+ public void testListToSet() throws Exception {
+ assertInterpreterRun(
+ "SELECT to_set(first(5, unfold(to_list(php_modules) + to_list(php_modules)))) AS php_modules",
+ new String[] {
+ "/pjwstk: php_modules: {odbc, rewrite}",
+ "/: php_modules: {odbc, rewrite}"
+ }
+ );
+ }
+
+ @Test
+ public void testTimeToString() throws Exception {
+ assertInterpreterRun(
+ "SELECT max(to_string(timestamp)) + \"x\" AS timex",
+ new String[] {
+ "/uw: timex: 2012/11/09 21:03:00.000x",
+ "/pjwstk: timex: 2012/11/09 21:13:00.000x",
+ "/: timex: 2012/11/09 20:08:13.123x"
+ }
+ );
+ }
+
+ @Test
+ public void testStringToTime() throws Exception {
+ assertInterpreterRun(
+ "SELECT to_time(\"2012/11/09 21:03:00.000\") + to_duration(1) AS time",
+ new String[] {
+ "/uw: time: 2012/11/09 21:03:00.001",
+ "/pjwstk: time: 2012/11/09 21:03:00.001",
+ "/: time: 2012/11/09 21:03:00.001"
+ }
+ );
+ }
+
+ @Test
+ public void testDurationToString() throws Exception {
+ assertInterpreterRun(
+ "SELECT to_string(epoch() - epoch()) + \"x\" AS zerox",
+ new String[] {
+ "/uw: zerox: +0 00:00:00.000x",
+ "/pjwstk: zerox: +0 00:00:00.000x",
+ "/: zerox: +0 00:00:00.000x"
+ }
+ );
+ }
+
+ @Test
+ public void testStringToDuration() throws Exception {
+ assertInterpreterRun(
+ "SELECT to_duration(\"+0 00:01:12.000\") + to_duration(1) AS dur",
+ new String[] {
+ "/uw: dur: +0 00:01:12.001",
+ "/pjwstk: dur: +0 00:01:12.001",
+ "/: dur: +0 00:01:12.001"
+ }
+ );
+ }
+
+ @Test
+ public void testContactToString() throws Exception {
+ assertInterpreterRun(
+ "SELECT first(1, to_string(unfold(members))) AS member",
+ new String[] {
+ "/uw: member: [(/uw/violet07, /10.1.1.10)]",
+ "/pjwstk: member: [(/uw/whatever01, /82.111.52.56)]",
+ }
+ );
+ }
+
+ @Test
+ public void testListToString() throws Exception {
+ assertInterpreterRun(
+ "SELECT first(1, to_string(to_list(php_modules)) + \"x\") AS listx",
+ new String[] {
+ "/pjwstk: listx: [[rewrite]x]"
+ }
+ );
+ }
+
+ @Test
+ public void testSetToString() throws Exception {
+ assertInterpreterRun(
+ "SELECT first(1, to_string(to_set(php_modules)) + \"x\") AS setx",
+ new String[] {
+ "/pjwstk: setx: [{rewrite}x]"
+ }
+ );
+ }
+
+ private void assertInterpreterRun(String query, String[] expectedOutput) throws Exception {
+ ByteArrayInputStream in = new ByteArrayInputStream(query.getBytes());
+
+ String expected = join(expectedOutput);
+
+ runTest(in, expected);
+ }
+
+ private String join(String[] strings) {
+ if (strings.length == 0) {
+ return "";
+ }
+
+ return String.join("\n", strings) + "\n";
+ }
+
+ @Test
public void fileTest01() throws Exception {
runFileTest(1);
}
@@ -135,19 +598,28 @@ public class InterpreterTests {
URL testOut = InterpreterTests.class.getResource(i + ".out");
FileInputStream in = new FileInputStream(test.getFile());
+
+ File expectedFile = new File(testOut.getFile());
+ FileInputStream expectedIn = new FileInputStream(expectedFile);
+ byte[] buffer = new byte[(int)expectedFile.length()];
+ expectedIn.read(buffer);
+ String expected = new String(buffer, "UTF-8");
+
+ runTest(in, expected);
+ }
+
+ private String runInterpreter(InputStream in) throws Exception {
ByteArrayOutputStream outByteArray = new ByteArrayOutputStream();
PrintStream outPrint = new PrintStream(outByteArray);
ZMI root = Main.createTestHierarchy();
Main.runTest(in, outPrint, root);
- String actual = outByteArray.toString();
+ return outByteArray.toString();
+ }
- File expectedFile = new File(testOut.getFile());
- FileInputStream expectedIn = new FileInputStream(expectedFile);
- byte[] buffer = new byte[(int)expectedFile.length()];
- expectedIn.read(buffer);
- String expected = new String(buffer, "UTF-8");
+ private void runTest(InputStream in, String expected) throws Exception {
+ String actual = runInterpreter(in);
assertEquals(expected, actual);
}