From b1f9a3dbee5b6af03aafd42336dc8a2646a822e2 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Mon, 7 Jun 2021 19:18:02 +0200
Subject: [PATCH 001/142] test with error
---
.../strings/LowerCaseFunctionIterator.java | 21 +++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/LowerCaseFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/LowerCaseFunctionIterator.java
index 74befc29bd..19131e1c15 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/LowerCaseFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/LowerCaseFunctionIterator.java
@@ -21,16 +21,18 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
+import java.util.Locale;
-public class LowerCaseFunctionIterator extends LocalFunctionCallIterator {
+public class LowerCaseFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -42,6 +44,20 @@ public LowerCaseFunctionIterator(
super(arguments, executionMode, iteratorMetadata);
}
+ @Override
+ public Item materializeFirstItemOrNull(DynamicContext dynamicContext) {
+ Item stringItem = this.children.get(0).materializeFirstItemOrNull(dynamicContext);
+ if (stringItem == null) {
+ return ItemFactory.getInstance().createStringItem("test");
+ //return ItemFactory.getInstance().createStringItem("");
+ } else {
+ String input = stringItem.getStringValue();
+ return ItemFactory.getInstance().createStringItem(input.toUpperCase());
+ }
+
+ }
+
+ /*
@Override
public Item next() {
if (this.hasNext) {
@@ -62,4 +78,5 @@ public Item next() {
getMetadata()
);
}
+ */
}
From e6942f202a28a542a17d07684e3f0072bc182f89 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Mon, 7 Jun 2021 19:49:34 +0200
Subject: [PATCH 002/142] AtMostOneItem LowerCaseFunction
---
.../strings/LowerCaseFunctionIterator.java | 28 ++-----------------
1 file changed, 3 insertions(+), 25 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/LowerCaseFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/LowerCaseFunctionIterator.java
index 19131e1c15..260d145123 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/LowerCaseFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/LowerCaseFunctionIterator.java
@@ -47,36 +47,14 @@ public LowerCaseFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext dynamicContext) {
Item stringItem = this.children.get(0).materializeFirstItemOrNull(dynamicContext);
+
if (stringItem == null) {
- return ItemFactory.getInstance().createStringItem("test");
- //return ItemFactory.getInstance().createStringItem("");
+ return ItemFactory.getInstance().createStringItem("");
} else {
String input = stringItem.getStringValue();
- return ItemFactory.getInstance().createStringItem(input.toUpperCase());
+ return ItemFactory.getInstance().createStringItem(input.toLowerCase());
}
}
- /*
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item stringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
-
- if (stringItem == null) {
- return ItemFactory.getInstance().createStringItem("");
- } else {
- String input = stringItem.getStringValue();
- return ItemFactory.getInstance().createStringItem(input.toLowerCase());
- }
-
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " replace function",
- getMetadata()
- );
- }
- */
}
From a17a2072642621dd77f1402bfb940f51084d81cb Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Mon, 7 Jun 2021 20:01:40 +0200
Subject: [PATCH 003/142] LowerCase pass spotless test
---
.../runtime/functions/strings/LowerCaseFunctionIterator.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/LowerCaseFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/LowerCaseFunctionIterator.java
index 260d145123..450afbad4b 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/LowerCaseFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/LowerCaseFunctionIterator.java
@@ -23,14 +23,12 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import java.util.List;
-import java.util.Locale;
public class LowerCaseFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
From 95e89d32c50af5897fcd15dd37b86ff9e1a7ebec Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Mon, 7 Jun 2021 20:09:20 +0200
Subject: [PATCH 004/142] AtMostOneItem UpperCaseFunction
---
.../strings/UpperCaseFunctionIterator.java | 33 +++++++------------
1 file changed, 12 insertions(+), 21 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/UpperCaseFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/UpperCaseFunctionIterator.java
index dabc1da3f3..9c613187b4 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/UpperCaseFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/UpperCaseFunctionIterator.java
@@ -21,16 +21,16 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class UpperCaseFunctionIterator extends LocalFunctionCallIterator {
+public class UpperCaseFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -43,23 +43,14 @@ public UpperCaseFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item stringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
-
- if (stringItem == null) {
- return ItemFactory.getInstance().createStringItem("");
- } else {
- String input = stringItem.getStringValue();
- return ItemFactory.getInstance().createStringItem(input.toUpperCase());
- }
-
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " replace function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext dynamicContext) {
+ Item stringItem = this.children.get(0).materializeFirstItemOrNull(dynamicContext);
+
+ if (stringItem == null) {
+ return ItemFactory.getInstance().createStringItem("");
+ } else {
+ String input = stringItem.getStringValue();
+ return ItemFactory.getInstance().createStringItem(input.toUpperCase());
+ }
}
}
From d03b29b59526f4be618d1cf359c33f53d058ea0d Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Tue, 8 Jun 2021 11:26:54 +0200
Subject: [PATCH 005/142] AtMostOne: Trigo (acos, asin, atan) and sumFunction
AtMostOne: Trigo (acos, asin, atan) and sumFunction
---
.../trigonometric/ACosFunctionIterator.java | 37 ++++++-------------
.../trigonometric/ASinFunctionIterator.java | 35 ++++++------------
.../trigonometric/ATanFunctionIterator.java | 35 ++++++------------
.../aggregate/SumFunctionIterator.java | 23 ++----------
4 files changed, 37 insertions(+), 93 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ACosFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ACosFunctionIterator.java
index 841d114efa..925ae189c2 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ACosFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ACosFunctionIterator.java
@@ -23,20 +23,17 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class ACosFunctionIterator extends LocalFunctionCallIterator {
+public class ACosFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
- private RuntimeIterator iterator;
-
public ACosFunctionIterator(
List arguments,
ExecutionMode executionMode,
@@ -46,28 +43,16 @@ public ACosFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.iterator = this.children.get(0);
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
- .createDoubleItem(
- Math.acos(
- this.iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution)
- .castToDoubleValue()
- )
- );
+ public Item materializeFirstItemOrNull(DynamicContext dynamicContext) {
+ Item value = this.children.get(0).materializeFirstItemOrNull(dynamicContext);
+ if (value == null) {
+ return null;
+ }
+ double dvalue = value.getDoubleValue();
+ if (Double.isNaN(dvalue) || Double.isInfinite(dvalue)) {
+ return ItemFactory.getInstance().createDoubleItem(Double.NaN);
}
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " acos function", getMetadata());
+ return ItemFactory.getInstance().createDoubleItem(Math.acos(dvalue));
}
-
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ASinFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ASinFunctionIterator.java
index 46e38a01d3..1f236216b8 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ASinFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ASinFunctionIterator.java
@@ -23,19 +23,17 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class ASinFunctionIterator extends LocalFunctionCallIterator {
+public class ASinFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
- private RuntimeIterator iterator;
public ASinFunctionIterator(
List arguments,
@@ -46,27 +44,16 @@ public ASinFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.iterator = this.children.get(0);
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
- .createDoubleItem(
- Math.asin(
- this.iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution)
- .castToDoubleValue()
- )
- );
+ public Item materializeFirstItemOrNull(DynamicContext dynamicContext) {
+ Item value = this.children.get(0).materializeFirstItemOrNull(dynamicContext);
+ if (value == null) {
+ return null;
+ }
+ double dvalue = value.getDoubleValue();
+ if (Double.isNaN(dvalue) || Double.isInfinite(dvalue)) {
+ return ItemFactory.getInstance().createDoubleItem(Double.NaN);
}
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " asin function", getMetadata());
+ return ItemFactory.getInstance().createDoubleItem(Math.asin(dvalue));
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ATanFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ATanFunctionIterator.java
index caeab58ee4..9596054447 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ATanFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ATanFunctionIterator.java
@@ -23,19 +23,17 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class ATanFunctionIterator extends LocalFunctionCallIterator {
+public class ATanFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
- private RuntimeIterator iterator;
public ATanFunctionIterator(
List arguments,
@@ -46,27 +44,16 @@ public ATanFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.iterator = this.children.get(0);
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
- .createDoubleItem(
- Math.atan(
- this.iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution)
- .castToDoubleValue()
- )
- );
+ public Item materializeFirstItemOrNull(DynamicContext dynamicContext) {
+ Item value = this.children.get(0).materializeFirstItemOrNull(dynamicContext);
+ if (value == null) {
+ return null;
+ }
+ double dvalue = value.getDoubleValue();
+ if (Double.isNaN(dvalue) || Double.isInfinite(dvalue)) {
+ return ItemFactory.getInstance().createDoubleItem(Double.NaN);
}
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " atan function", getMetadata());
+ return ItemFactory.getInstance().createDoubleItem(Math.atan(dvalue));
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java
index 48423d1723..03ca5e3032 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java
@@ -26,13 +26,12 @@
import org.rumbledb.context.Name;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.InvalidArgumentTypeException;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.items.structured.JSoundDataFrame;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.arithmetics.AdditiveOperationIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import org.rumbledb.runtime.primary.VariableReferenceIterator;
import sparksoniq.spark.SparkSessionManager;
@@ -42,7 +41,7 @@
import java.util.Map;
import java.util.TreeMap;
-public class SumFunctionIterator extends LocalFunctionCallIterator {
+public class SumFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -57,28 +56,14 @@ public SumFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
+ public Item materializeFirstItemOrNull(DynamicContext context) {
this.item = computeSum(
zeroElement(),
this.children.get(0),
this.currentDynamicContextForLocalExecution,
getMetadata()
);
- this.hasNext = this.item != null;
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return this.item;
- } else {
- throw new IteratorFlowException(
- FLOW_EXCEPTION_MESSAGE + "SUM function",
- getMetadata()
- );
- }
+ return this.item;
}
private Item zeroElement() {
From 3ea5cff0990636c7074f1b68e4bd8a6cd0ac6b24 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Tue, 8 Jun 2021 23:00:08 +0200
Subject: [PATCH 006/142] Trigo Arc (cos, sin, tan)
Trigo Arc (cos, sin, tan)
---
.../trigonometric/ACosFunctionIterator.java | 37 ++++++-------------
.../trigonometric/ASinFunctionIterator.java | 35 ++++++------------
.../trigonometric/ATanFunctionIterator.java | 35 ++++++------------
3 files changed, 33 insertions(+), 74 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ACosFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ACosFunctionIterator.java
index 841d114efa..925ae189c2 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ACosFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ACosFunctionIterator.java
@@ -23,20 +23,17 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class ACosFunctionIterator extends LocalFunctionCallIterator {
+public class ACosFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
- private RuntimeIterator iterator;
-
public ACosFunctionIterator(
List arguments,
ExecutionMode executionMode,
@@ -46,28 +43,16 @@ public ACosFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.iterator = this.children.get(0);
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
- .createDoubleItem(
- Math.acos(
- this.iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution)
- .castToDoubleValue()
- )
- );
+ public Item materializeFirstItemOrNull(DynamicContext dynamicContext) {
+ Item value = this.children.get(0).materializeFirstItemOrNull(dynamicContext);
+ if (value == null) {
+ return null;
+ }
+ double dvalue = value.getDoubleValue();
+ if (Double.isNaN(dvalue) || Double.isInfinite(dvalue)) {
+ return ItemFactory.getInstance().createDoubleItem(Double.NaN);
}
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " acos function", getMetadata());
+ return ItemFactory.getInstance().createDoubleItem(Math.acos(dvalue));
}
-
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ASinFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ASinFunctionIterator.java
index 46e38a01d3..1f236216b8 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ASinFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ASinFunctionIterator.java
@@ -23,19 +23,17 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class ASinFunctionIterator extends LocalFunctionCallIterator {
+public class ASinFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
- private RuntimeIterator iterator;
public ASinFunctionIterator(
List arguments,
@@ -46,27 +44,16 @@ public ASinFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.iterator = this.children.get(0);
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
- .createDoubleItem(
- Math.asin(
- this.iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution)
- .castToDoubleValue()
- )
- );
+ public Item materializeFirstItemOrNull(DynamicContext dynamicContext) {
+ Item value = this.children.get(0).materializeFirstItemOrNull(dynamicContext);
+ if (value == null) {
+ return null;
+ }
+ double dvalue = value.getDoubleValue();
+ if (Double.isNaN(dvalue) || Double.isInfinite(dvalue)) {
+ return ItemFactory.getInstance().createDoubleItem(Double.NaN);
}
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " asin function", getMetadata());
+ return ItemFactory.getInstance().createDoubleItem(Math.asin(dvalue));
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ATanFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ATanFunctionIterator.java
index caeab58ee4..9596054447 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ATanFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/ATanFunctionIterator.java
@@ -23,19 +23,17 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class ATanFunctionIterator extends LocalFunctionCallIterator {
+public class ATanFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
- private RuntimeIterator iterator;
public ATanFunctionIterator(
List arguments,
@@ -46,27 +44,16 @@ public ATanFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.iterator = this.children.get(0);
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
- .createDoubleItem(
- Math.atan(
- this.iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution)
- .castToDoubleValue()
- )
- );
+ public Item materializeFirstItemOrNull(DynamicContext dynamicContext) {
+ Item value = this.children.get(0).materializeFirstItemOrNull(dynamicContext);
+ if (value == null) {
+ return null;
+ }
+ double dvalue = value.getDoubleValue();
+ if (Double.isNaN(dvalue) || Double.isInfinite(dvalue)) {
+ return ItemFactory.getInstance().createDoubleItem(Double.NaN);
}
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " atan function", getMetadata());
+ return ItemFactory.getInstance().createDoubleItem(Math.atan(dvalue));
}
From 7b8f54e57668ca3752080e8764c1b90e838cf202 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Wed, 9 Jun 2021 11:06:00 +0200
Subject: [PATCH 007/142] back to localCall SumFunction
---
.../aggregate/SumFunctionIterator.java | 77 +++++++++++--------
1 file changed, 46 insertions(+), 31 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java
index 03ca5e3032..82aa256479 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java
@@ -26,12 +26,13 @@
import org.rumbledb.context.Name;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.InvalidArgumentTypeException;
+import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.items.structured.JSoundDataFrame;
-import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.arithmetics.AdditiveOperationIterator;
+import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import org.rumbledb.runtime.primary.VariableReferenceIterator;
import sparksoniq.spark.SparkSessionManager;
@@ -41,7 +42,7 @@
import java.util.Map;
import java.util.TreeMap;
-public class SumFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
+public class SumFunctionIterator extends LocalFunctionCallIterator {
private static final long serialVersionUID = 1L;
@@ -56,14 +57,28 @@ public SumFunctionIterator(
}
@Override
- public Item materializeFirstItemOrNull(DynamicContext context) {
+ public void open(DynamicContext context) {
+ super.open(context);
this.item = computeSum(
- zeroElement(),
- this.children.get(0),
- this.currentDynamicContextForLocalExecution,
- getMetadata()
+ zeroElement(),
+ this.children.get(0),
+ this.currentDynamicContextForLocalExecution,
+ getMetadata()
);
- return this.item;
+ this.hasNext = this.item != null;
+ }
+
+ @Override
+ public Item next() {
+ if (this.hasNext) {
+ this.hasNext = false;
+ return this.item;
+ } else {
+ throw new IteratorFlowException(
+ FLOW_EXCEPTION_MESSAGE + "SUM function",
+ getMetadata()
+ );
+ }
}
private Item zeroElement() {
@@ -82,24 +97,24 @@ public static Item computeSum(
) {
if (iterator.isDataFrame()) {
return computeDataFrame(
- zeroElement,
- iterator,
- context,
- metadata
+ zeroElement,
+ iterator,
+ context,
+ metadata
);
} else if (iterator.isRDDOrDataFrame()) {
return computeRDD(
- zeroElement,
- iterator,
- context,
- metadata
+ zeroElement,
+ iterator,
+ context,
+ metadata
);
} else {
return computeLocally(
- zeroElement,
- iterator,
- context,
- metadata
+ zeroElement,
+ iterator,
+ context,
+ metadata
);
}
}
@@ -121,10 +136,10 @@ private static Item computeLocally(
if (sum == null) {
throw new InvalidArgumentTypeException(
" \"+\": operation not possible with parameters of type \""
- + result.getDynamicType().toString()
- + "\" and \""
- + results.get(i).getDynamicType().toString()
- + "\"",
+ + result.getDynamicType().toString()
+ + "\" and \""
+ + results.get(i).getDynamicType().toString()
+ + "\"",
metadata
);
}
@@ -156,12 +171,12 @@ private static Item computeDataFrame(
}
df.createOrReplaceTempView("input");
JSoundDataFrame summedDF = df.evaluateSQL(
- String.format(
- "SELECT SUM(`%s`) as `%s` FROM input",
- SparkSessionManager.atomicJSONiqItemColumnName,
- SparkSessionManager.atomicJSONiqItemColumnName
- ),
- df.getItemType()
+ String.format(
+ "SELECT SUM(`%s`) as `%s` FROM input",
+ SparkSessionManager.atomicJSONiqItemColumnName,
+ SparkSessionManager.atomicJSONiqItemColumnName
+ ),
+ df.getItemType()
);
return summedDF.getExactlyOneItem();
}
@@ -170,7 +185,7 @@ public Map getVariableDependencies() {
if (this.children.get(0) instanceof VariableReferenceIterator) {
VariableReferenceIterator expr = (VariableReferenceIterator) this.children.get(0);
Map result =
- new TreeMap();
+ new TreeMap();
result.put(expr.getVariableName(), DynamicContext.VariableDependency.SUM);
return result;
} else {
From 2764b693c7570b37d28a108b39519c4bd65518c7 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Wed, 9 Jun 2021 11:18:28 +0200
Subject: [PATCH 008/142] spotless
---
.../aggregate/SumFunctionIterator.java | 54 +++++++++----------
1 file changed, 27 insertions(+), 27 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java
index 82aa256479..48423d1723 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java
@@ -60,10 +60,10 @@ public SumFunctionIterator(
public void open(DynamicContext context) {
super.open(context);
this.item = computeSum(
- zeroElement(),
- this.children.get(0),
- this.currentDynamicContextForLocalExecution,
- getMetadata()
+ zeroElement(),
+ this.children.get(0),
+ this.currentDynamicContextForLocalExecution,
+ getMetadata()
);
this.hasNext = this.item != null;
}
@@ -97,24 +97,24 @@ public static Item computeSum(
) {
if (iterator.isDataFrame()) {
return computeDataFrame(
- zeroElement,
- iterator,
- context,
- metadata
+ zeroElement,
+ iterator,
+ context,
+ metadata
);
} else if (iterator.isRDDOrDataFrame()) {
return computeRDD(
- zeroElement,
- iterator,
- context,
- metadata
+ zeroElement,
+ iterator,
+ context,
+ metadata
);
} else {
return computeLocally(
- zeroElement,
- iterator,
- context,
- metadata
+ zeroElement,
+ iterator,
+ context,
+ metadata
);
}
}
@@ -136,10 +136,10 @@ private static Item computeLocally(
if (sum == null) {
throw new InvalidArgumentTypeException(
" \"+\": operation not possible with parameters of type \""
- + result.getDynamicType().toString()
- + "\" and \""
- + results.get(i).getDynamicType().toString()
- + "\"",
+ + result.getDynamicType().toString()
+ + "\" and \""
+ + results.get(i).getDynamicType().toString()
+ + "\"",
metadata
);
}
@@ -171,12 +171,12 @@ private static Item computeDataFrame(
}
df.createOrReplaceTempView("input");
JSoundDataFrame summedDF = df.evaluateSQL(
- String.format(
- "SELECT SUM(`%s`) as `%s` FROM input",
- SparkSessionManager.atomicJSONiqItemColumnName,
- SparkSessionManager.atomicJSONiqItemColumnName
- ),
- df.getItemType()
+ String.format(
+ "SELECT SUM(`%s`) as `%s` FROM input",
+ SparkSessionManager.atomicJSONiqItemColumnName,
+ SparkSessionManager.atomicJSONiqItemColumnName
+ ),
+ df.getItemType()
);
return summedDF.getExactlyOneItem();
}
@@ -185,7 +185,7 @@ public Map getVariableDependencies() {
if (this.children.get(0) instanceof VariableReferenceIterator) {
VariableReferenceIterator expr = (VariableReferenceIterator) this.children.get(0);
Map result =
- new TreeMap();
+ new TreeMap();
result.put(expr.getVariableName(), DynamicContext.VariableDependency.SUM);
return result;
} else {
From 1cd496e9713908318c3e0afd9dd09c20c7d03908 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Wed, 9 Jun 2021 13:21:21 +0200
Subject: [PATCH 009/142] AtMost MinFunction
---
.../aggregate/MinFunctionIterator.java | 74 ++++++++-----------
1 file changed, 29 insertions(+), 45 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MinFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MinFunctionIterator.java
index 884f805506..9607f158b3 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MinFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MinFunctionIterator.java
@@ -26,12 +26,11 @@
import org.rumbledb.context.Name;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.InvalidArgumentTypeException;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.exceptions.RumbleException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemComparator;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import org.rumbledb.runtime.primary.VariableReferenceIterator;
import java.util.Collections;
@@ -39,7 +38,7 @@
import java.util.Map;
import java.util.TreeMap;
-public class MinFunctionIterator extends LocalFunctionCallIterator {
+public class MinFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -56,58 +55,43 @@ public MinFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- if (!this.iterator.isRDDOrDataFrame()) {
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- return;
- }
- JavaRDD- rdd = this.iterator.getRDD(this.currentDynamicContextForLocalExecution);
- if (rdd.isEmpty()) {
- this.hasNext = false;
- return;
- }
+ public Item materializeFirstItemOrNull(DynamicContext context) {
ItemComparator comparator = new ItemComparator(
new InvalidArgumentTypeException(
"Min expression input error. Input has to be non-null atomics of matching types",
getMetadata()
)
);
- this.result = rdd.min(comparator);
- }
- @Override
- public Item next() {
- if (!this.hasNext) {
- throw new IteratorFlowException(
- FLOW_EXCEPTION_MESSAGE + "Min function",
- getMetadata()
- );
- }
- this.hasNext = false;
- ItemComparator comparator = new ItemComparator(
- new InvalidArgumentTypeException(
- "Max expression input error. Input has to be non-null atomics of matching types",
+ if (!this.iterator.isRDDOrDataFrame()) {
+
+ List
- results = this.iterator.materialize(context);
+ if (results.size() == 0) {
+ return null;
+ }
+
+ try {
+ return Collections.min(results, comparator);
+ } catch (RumbleException e) {
+ RumbleException ex = new InvalidArgumentTypeException(
+ "Max expression input error. Input has to be non-null atomics of matching types.",
getMetadata()
- )
- );
- if (this.iterator.isRDDOrDataFrame()) {
- return this.result;
+ );
+ ex.initCause(e);
+ throw ex;
+ }
}
- List
- results = this.iterator.materialize(this.currentDynamicContextForLocalExecution);
-
- try {
- return Collections.min(results, comparator);
- } catch (RumbleException e) {
- RumbleException ex = new InvalidArgumentTypeException(
- "Max expression input error. Input has to be non-null atomics of matching types.",
- getMetadata()
- );
- ex.initCause(e);
- throw ex;
+
+ JavaRDD
- rdd = this.iterator.getRDD(context);
+ this.iterator.close();
+ if (rdd.isEmpty()) {
+ return null;
}
+
+ this.result = rdd.min(comparator);
+ return this.result;
+
+
}
public Map getVariableDependencies() {
From e3df9038f1d5566dcba34ccdb37d41aa84aa02e3 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Wed, 9 Jun 2021 14:27:51 +0200
Subject: [PATCH 010/142] AtMostOne FloorFunction
---
.../numerics/FloorFunctionIterator.java | 38 +++++++------------
1 file changed, 14 insertions(+), 24 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java
index c616d4d3ac..5a30edea65 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java
@@ -23,21 +23,19 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.flwor.NativeClauseContext;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import org.rumbledb.types.BuiltinTypesCatalogue;
import java.util.List;
-public class FloorFunctionIterator extends LocalFunctionCallIterator {
+public class FloorFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
- private RuntimeIterator iterator;
public FloorFunctionIterator(
List arguments,
@@ -48,27 +46,19 @@ public FloorFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.iterator = this.children.get(0);
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
- .createDoubleItem(
- Math.floor(
- this.iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution)
- .castToDoubleValue()
- )
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item value = this.children.get(0).materializeFirstItemOrNull(context);
+ if (value == null) {
+ return null;
}
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " floor function", getMetadata());
+ return ItemFactory.getInstance()
+ .createDoubleItem(
+ Math.floor(
+ this.children.get(0)
+ .materializeFirstItemOrNull(context)
+ .castToDoubleValue()
+ )
+ );
}
@Override
From 36f6fe1d938b6a7681fef9aa9037b477cebfe38b Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Wed, 9 Jun 2021 14:32:26 +0200
Subject: [PATCH 011/142] AtMostOne Ceiling
Correct Floor to re-use value
---
.../numerics/CeilingFunctionIterator.java | 34 +++++++------------
.../numerics/FloorFunctionIterator.java | 4 +--
2 files changed, 14 insertions(+), 24 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/CeilingFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/CeilingFunctionIterator.java
index fb5ace24b2..c9566a0fe4 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/CeilingFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/CeilingFunctionIterator.java
@@ -26,12 +26,13 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class CeilingFunctionIterator extends LocalFunctionCallIterator {
+public class CeilingFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -46,27 +47,18 @@ public CeilingFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.iterator = this.children.get(0);
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
- .createDoubleItem(
- Math.ceil(
- this.iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution)
- .castToDoubleValue()
- )
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item value = this.children.get(0).materializeFirstItemOrNull(context);
+ if (value == null) {
+ return null;
}
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " ceiling function", getMetadata());
+ return ItemFactory.getInstance()
+ .createDoubleItem(
+ Math.ceil(
+ value.castToDoubleValue()
+ )
+ );
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java
index 5a30edea65..b5a6351847 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java
@@ -54,9 +54,7 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
return ItemFactory.getInstance()
.createDoubleItem(
Math.floor(
- this.children.get(0)
- .materializeFirstItemOrNull(context)
- .castToDoubleValue()
+ value.castToDoubleValue()
)
);
}
From 5beb18d541a3a9259c3638a5e468b21183fd472e Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Wed, 9 Jun 2021 16:21:24 +0200
Subject: [PATCH 012/142] Ceiling, Floor, Pow, Number, RoundHalf, Max, fix Min
---
.../numerics/CeilingFunctionIterator.java | 2 -
.../numerics/FloorFunctionIterator.java | 2 +-
.../numerics/NumberFunctionIterator.java | 33 ++++-----
.../RoundHalfToEvenFunctionIterator.java | 58 +++++++--------
.../exponential/PowFunctionIterator.java | 36 ++++------
.../aggregate/MaxFunctionIterator.java | 70 +++++++------------
.../aggregate/MinFunctionIterator.java | 3 +-
7 files changed, 78 insertions(+), 126 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/CeilingFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/CeilingFunctionIterator.java
index c9566a0fe4..7811c5ea12 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/CeilingFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/CeilingFunctionIterator.java
@@ -23,12 +23,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java
index b5a6351847..4ea1f013ab 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java
@@ -54,7 +54,7 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
return ItemFactory.getInstance()
.createDoubleItem(
Math.floor(
- value.castToDoubleValue()
+ value.castToDoubleValue()
)
);
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/NumberFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/NumberFunctionIterator.java
index b3e64d2550..d51b0637ec 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/NumberFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/NumberFunctionIterator.java
@@ -21,17 +21,17 @@
package org.rumbledb.runtime.functions.numerics;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import org.rumbledb.runtime.typing.CastIterator;
import org.rumbledb.types.BuiltinTypesCatalogue;
import java.util.List;
-public class NumberFunctionIterator extends LocalFunctionCallIterator {
+public class NumberFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -44,23 +44,18 @@ public NumberFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item anyItem = this.children.get(0).materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (anyItem == null) {
- return ItemFactory.getInstance().createDoubleItem(Double.NaN);
- }
+ public Item materializeFirstItemOrNull(DynamicContext context) {
- Item result = CastIterator.castItemToType(anyItem, BuiltinTypesCatalogue.doubleItem, getMetadata());
- if (result != null) {
- return result;
- }
+ Item anyItem = this.children.get(0).materializeFirstItemOrNull(context);
+ if (anyItem == null) {
return ItemFactory.getInstance().createDoubleItem(Double.NaN);
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " number function",
- getMetadata()
- );
+ }
+
+ Item result = CastIterator.castItemToType(anyItem, BuiltinTypesCatalogue.doubleItem, getMetadata());
+ if (result != null) {
+ return result;
+ }
+ return ItemFactory.getInstance().createDoubleItem(Double.NaN);
+
}
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
index 0082820e9b..3d6bd94dbe 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
@@ -26,14 +26,14 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
-public class RoundHalfToEvenFunctionIterator extends LocalFunctionCallIterator {
+public class RoundHalfToEvenFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -48,41 +48,31 @@ public RoundHalfToEvenFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.iterator = this.children.get(0);
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- }
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item value = this.children.get(0).materializeFirstItemOrNull(context);
+ if (value == null) {
+ return null;
+ }
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item value = this.iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- Item precision;
- if (this.children.size() > 1) {
- precision = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- }
- // if second param is not given precision is set as 0 (rounds to a whole number)
- else {
- precision = ItemFactory.getInstance().createIntItem(0);
- }
- try {
- BigDecimal bd = new BigDecimal(value.castToDoubleValue());
- bd = bd.setScale(precision.getIntValue(), RoundingMode.HALF_EVEN);
- return ItemFactory.getInstance().createDoubleItem(bd.doubleValue());
+ int precision;
+ if (this.children.size() > 1) {
+ precision = this.children.get(1)
+ .materializeFirstItemOrNull(context)
+ .getIntValue();
+ }
+ // if second param is not given precision is set as 0 (rounds to a whole number)
+ else {
+ precision = 0;
+ }
+ try {
+ BigDecimal bd = new BigDecimal(value.castToDoubleValue());
+ bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
+ return ItemFactory.getInstance().createDoubleItem(bd.doubleValue());
- } catch (IteratorFlowException e) {
- throw new IteratorFlowException(e.getJSONiqErrorMessage(), getMetadata());
- }
+ } catch (IteratorFlowException e) {
+ throw new IteratorFlowException(e.getJSONiqErrorMessage(), getMetadata());
}
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " round-half-to-even function",
- getMetadata()
- );
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/PowFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/PowFunctionIterator.java
index 71b63325f7..950f777cf0 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/PowFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/PowFunctionIterator.java
@@ -26,12 +26,12 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class PowFunctionIterator extends LocalFunctionCallIterator {
+public class PowFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -46,29 +46,17 @@ public PowFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.iterator = this.children.get(0);
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- Item base = this.iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- Item exponent = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- try {
- this.hasNext = false;
- return ItemFactory.getInstance()
- .createDoubleItem(Math.pow(base.castToDoubleValue(), exponent.castToDoubleValue()));
- } catch (IteratorFlowException e) {
- throw new IteratorFlowException(e.getJSONiqErrorMessage(), getMetadata());
- }
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item base = this.children.get(0).materializeFirstItemOrNull(context);
+ Item exponent = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ try {
+ return ItemFactory.getInstance()
+ .createDoubleItem(Math.pow(base.castToDoubleValue(), exponent.castToDoubleValue()));
+ } catch (IteratorFlowException e) {
+ throw new IteratorFlowException(e.getJSONiqErrorMessage(), getMetadata());
}
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " pow function", getMetadata());
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MaxFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MaxFunctionIterator.java
index 23e1e383f0..aab3046b02 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MaxFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MaxFunctionIterator.java
@@ -26,12 +26,11 @@
import org.rumbledb.context.Name;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.InvalidArgumentTypeException;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.exceptions.RumbleException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemComparator;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import org.rumbledb.runtime.primary.VariableReferenceIterator;
import java.util.Collections;
@@ -39,7 +38,7 @@
import java.util.Map;
import java.util.TreeMap;
-public class MaxFunctionIterator extends LocalFunctionCallIterator {
+public class MaxFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -56,58 +55,41 @@ public MaxFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- if (!this.iterator.isRDDOrDataFrame()) {
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- return;
- }
- JavaRDD
- rdd = this.iterator.getRDD(this.currentDynamicContextForLocalExecution);
- if (rdd.isEmpty()) {
- this.hasNext = false;
- return;
- }
+ public Item materializeFirstItemOrNull(DynamicContext context) {
ItemComparator comparator = new ItemComparator(
new InvalidArgumentTypeException(
"Max expression input error. Input has to be non-null atomics of matching types",
getMetadata()
)
);
- this.result = rdd.max(comparator);
- }
- @Override
- public Item next() {
- if (!this.hasNext) {
- throw new IteratorFlowException(
- FLOW_EXCEPTION_MESSAGE + "MAX function",
- getMetadata()
- );
- }
- this.hasNext = false;
- ItemComparator comparator = new ItemComparator(
- new InvalidArgumentTypeException(
- "Max expression input error. Input has to be non-null atomics of matching types",
+ if (!this.iterator.isRDDOrDataFrame()) {
+
+ List
- results = this.iterator.materialize(context);
+ if (results.size() == 0) {
+ return null;
+ }
+
+ try {
+ return Collections.max(results, comparator);
+ } catch (RumbleException e) {
+ RumbleException ex = new InvalidArgumentTypeException(
+ "Max expression input error. Input has to be non-null atomics of matching types.",
getMetadata()
- )
- );
- if (this.iterator.isRDDOrDataFrame()) {
- return this.result;
+ );
+ ex.initCause(e);
+ throw ex;
+ }
}
- List
- results = this.iterator.materialize(this.currentDynamicContextForLocalExecution);
- try {
- return Collections.max(results, comparator);
- } catch (RumbleException e) {
- RumbleException ex = new InvalidArgumentTypeException(
- "Max expression input error. Input has to be non-null atomics of matching types.",
- getMetadata()
- );
- ex.initCause(e);
- throw ex;
+ JavaRDD
- rdd = this.iterator.getRDD(context);
+ if (rdd.isEmpty()) {
+ return null;
}
+
+ this.result = rdd.max(comparator);
+ return this.result;
+
}
public Map getVariableDependencies() {
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MinFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MinFunctionIterator.java
index 9607f158b3..ea637426df 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MinFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MinFunctionIterator.java
@@ -74,7 +74,7 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
return Collections.min(results, comparator);
} catch (RumbleException e) {
RumbleException ex = new InvalidArgumentTypeException(
- "Max expression input error. Input has to be non-null atomics of matching types.",
+ "Min expression input error. Input has to be non-null atomics of matching types.",
getMetadata()
);
ex.initCause(e);
@@ -83,7 +83,6 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
}
JavaRDD
- rdd = this.iterator.getRDD(context);
- this.iterator.close();
if (rdd.isEmpty()) {
return null;
}
From 0b4f4fa7f06bd3ceeb4a0790796b445da635f86e Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Wed, 9 Jun 2021 20:08:36 +0200
Subject: [PATCH 013/142] fix Pow nullException
---
.../functions/numerics/exponential/PowFunctionIterator.java | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/PowFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/PowFunctionIterator.java
index 950f777cf0..6ffcc590a6 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/PowFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/PowFunctionIterator.java
@@ -48,8 +48,14 @@ public PowFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
Item base = this.children.get(0).materializeFirstItemOrNull(context);
+ if (base == null) {
+ return null;
+ }
Item exponent = this.children.get(1)
.materializeFirstItemOrNull(context);
+ if (exponent == null) {
+ return null;
+ }
try {
return ItemFactory.getInstance()
.createDoubleItem(Math.pow(base.castToDoubleValue(), exponent.castToDoubleValue()));
From c1dbace330758b22d8bf765879c08066894a3440 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Wed, 9 Jun 2021 23:04:43 +0200
Subject: [PATCH 014/142] Exp10, Log10, Pi, Tan, YFromDateTime
---
.../YearFromDateTimeFunctionIterator.java | 25 +++++---------
.../numerics/PiFunctionIterator.java | 14 +++-----
.../exponential/Exp10FunctionIterator.java | 34 ++++++-------------
.../exponential/Log10FunctionIterator.java | 33 +++++++-----------
.../trigonometric/TanFunctionIterator.java | 34 +++++++------------
5 files changed, 49 insertions(+), 91 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateTimeFunctionIterator.java
index ad0b3c33e7..3a34a7ddc6 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateTimeFunctionIterator.java
@@ -6,12 +6,13 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class YearFromDateTimeFunctionIterator extends LocalFunctionCallIterator {
+public class YearFromDateTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateTimeItem = null;
@@ -25,23 +26,13 @@ public YearFromDateTimeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.dateTimeItem.getDateTimeValue().getYear());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " year-from-dateTime function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateTimeItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.dateTimeItem == null) {
+ return null;
}
+ return ItemFactory.getInstance().createIntItem(this.dateTimeItem.getDateTimeValue().getYear());
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.dateTimeItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/PiFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/PiFunctionIterator.java
index b059cd564a..331f7c3dcf 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/PiFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/PiFunctionIterator.java
@@ -21,16 +21,18 @@
package org.rumbledb.runtime.functions.numerics;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class PiFunctionIterator extends LocalFunctionCallIterator {
+public class PiFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -43,14 +45,8 @@ public PiFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createDoubleItem(Math.PI);
- } else {
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " pi function", getMetadata());
- }
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ return ItemFactory.getInstance().createDoubleItem(Math.PI);
}
-
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Exp10FunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Exp10FunctionIterator.java
index 983c9a9fc3..bebec8164b 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Exp10FunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Exp10FunctionIterator.java
@@ -23,15 +23,14 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class Exp10FunctionIterator extends LocalFunctionCallIterator {
+public class Exp10FunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -46,27 +45,16 @@ public Exp10FunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.iterator = this.children.get(0);
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item exponent = this.iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- try {
- return ItemFactory.getInstance().createDoubleItem(Math.pow(10.0, exponent.castToDoubleValue()));
- } catch (IteratorFlowException e) {
- throw new IteratorFlowException(e.getJSONiqErrorMessage(), getMetadata());
- }
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item exponent = this.iterator.materializeFirstItemOrNull(context);
+ if (exponent == null) {
+ return null;
}
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " exp10 function", getMetadata());
+ double dexponent = exponent.getDoubleValue();
+ if (Double.isNaN(dexponent) || Double.isInfinite(dexponent)) {
+ return ItemFactory.getInstance().createDoubleItem(Double.NaN);
+ }
+ return ItemFactory.getInstance().createDoubleItem(Math.pow(10.0, dexponent));
}
-
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Log10FunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Log10FunctionIterator.java
index 1e7198ed42..72b265d90a 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Log10FunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Log10FunctionIterator.java
@@ -26,12 +26,13 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class Log10FunctionIterator extends LocalFunctionCallIterator {
+public class Log10FunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -46,26 +47,16 @@ public Log10FunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.iterator = this.children.get(0);
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item value = this.iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- try {
- return ItemFactory.getInstance().createDoubleItem(Math.log10(value.castToDoubleValue()));
-
- } catch (IteratorFlowException e) {
- throw new IteratorFlowException(e.getJSONiqErrorMessage(), getMetadata());
- }
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item value = this.iterator.materializeFirstItemOrNull(context);
+ if (value == null) {
+ return null;
+ }
+ double dvalue = value.getDoubleValue();
+ if (Double.isNaN(dvalue) || Double.isInfinite(dvalue)) {
+ return ItemFactory.getInstance().createDoubleItem(Double.NaN);
}
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " log10 function", getMetadata());
+ return ItemFactory.getInstance().createDoubleItem(Math.log10(dvalue));
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/TanFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/TanFunctionIterator.java
index 5d88473c2b..e03124905e 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/TanFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/TanFunctionIterator.java
@@ -26,12 +26,13 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class TanFunctionIterator extends LocalFunctionCallIterator {
+public class TanFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -46,26 +47,17 @@ public TanFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.iterator = this.children.get(0);
- this.iterator.open(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.iterator.hasNext();
- this.iterator.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
- .createDoubleItem(
- Math.tan(
- this.iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution)
- .castToDoubleValue()
- )
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item value = this.children.get(0).materializeFirstItemOrNull(context);
+ if (value == null) {
+ return null;
}
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " tan function", getMetadata());
+ double dvalue = value.getDoubleValue();
+ if (Double.isNaN(dvalue) || Double.isInfinite(dvalue)) {
+ return ItemFactory.getInstance().createDoubleItem(Double.NaN);
+ }
+ return ItemFactory.getInstance().createDoubleItem(Math.tan(dvalue));
+
}
+
}
From 7b53eb69a01c6ebd5a2934c22dfe10aeccfffb14 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Wed, 9 Jun 2021 23:07:01 +0200
Subject: [PATCH 015/142] Spotless
---
.../datetime/components/YearFromDateTimeFunctionIterator.java | 4 +---
.../runtime/functions/numerics/PiFunctionIterator.java | 2 --
.../functions/numerics/exponential/Log10FunctionIterator.java | 2 --
.../functions/numerics/trigonometric/TanFunctionIterator.java | 2 --
4 files changed, 1 insertion(+), 9 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateTimeFunctionIterator.java
index 3a34a7ddc6..67415c9690 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateTimeFunctionIterator.java
@@ -3,12 +3,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
@@ -28,7 +26,7 @@ public YearFromDateTimeFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
this.dateTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
if (this.dateTimeItem == null) {
return null;
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/PiFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/PiFunctionIterator.java
index 331f7c3dcf..a7faf61a51 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/PiFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/PiFunctionIterator.java
@@ -23,12 +23,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Log10FunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Log10FunctionIterator.java
index 72b265d90a..3a64da2907 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Log10FunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Log10FunctionIterator.java
@@ -23,12 +23,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/TanFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/TanFunctionIterator.java
index e03124905e..52a61824e9 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/TanFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/TanFunctionIterator.java
@@ -23,12 +23,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
From 8ccfc95b31293f894a665c866131ebdacc72341b Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Wed, 9 Jun 2021 23:07:01 +0200
Subject: [PATCH 016/142] Spotless
---
.../components/YearFromDateTimeFunctionIterator.java | 4 +---
.../runtime/functions/numerics/PiFunctionIterator.java | 2 --
.../numerics/exponential/Exp10FunctionIterator.java | 3 +--
.../numerics/exponential/Log10FunctionIterator.java | 5 +----
.../numerics/trigonometric/TanFunctionIterator.java | 2 --
5 files changed, 3 insertions(+), 13 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateTimeFunctionIterator.java
index 3a34a7ddc6..67415c9690 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateTimeFunctionIterator.java
@@ -3,12 +3,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
@@ -28,7 +26,7 @@ public YearFromDateTimeFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
this.dateTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
if (this.dateTimeItem == null) {
return null;
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/PiFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/PiFunctionIterator.java
index 331f7c3dcf..a7faf61a51 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/PiFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/PiFunctionIterator.java
@@ -23,12 +23,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Exp10FunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Exp10FunctionIterator.java
index bebec8164b..1a8c78cd3c 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Exp10FunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Exp10FunctionIterator.java
@@ -34,7 +34,6 @@ public class Exp10FunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
- private RuntimeIterator iterator;
public Exp10FunctionIterator(
List arguments,
@@ -46,7 +45,7 @@ public Exp10FunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
- Item exponent = this.iterator.materializeFirstItemOrNull(context);
+ Item exponent = this.children.get(0).materializeFirstItemOrNull(context);
if (exponent == null) {
return null;
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Log10FunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Log10FunctionIterator.java
index 72b265d90a..3591e711bd 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Log10FunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/exponential/Log10FunctionIterator.java
@@ -23,12 +23,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
@@ -36,7 +34,6 @@ public class Log10FunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
- private RuntimeIterator iterator;
public Log10FunctionIterator(
List arguments,
@@ -48,7 +45,7 @@ public Log10FunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
- Item value = this.iterator.materializeFirstItemOrNull(context);
+ Item value = this.children.get(0).materializeFirstItemOrNull(context);
if (value == null) {
return null;
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/TanFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/TanFunctionIterator.java
index e03124905e..52a61824e9 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/TanFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/trigonometric/TanFunctionIterator.java
@@ -23,12 +23,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
From fc5665e2a2d7a4ee7100bf650ce6f70ff19697fa Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Fri, 11 Jun 2021 11:45:34 +0200
Subject: [PATCH 017/142] AtMostOne - Avg, Count, Sum
---
.../aggregate/AvgFunctionIterator.java | 33 ++++----------
.../aggregate/CountFunctionIterator.java | 45 ++++++++-----------
.../aggregate/SumFunctionIterator.java | 32 +++++--------
3 files changed, 37 insertions(+), 73 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/AvgFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/AvgFunctionIterator.java
index 71c664a316..08885034f2 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/AvgFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/AvgFunctionIterator.java
@@ -24,13 +24,12 @@
import org.rumbledb.context.DynamicContext;
import org.rumbledb.context.Name;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.expressions.arithmetic.MultiplicativeExpression;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.arithmetics.MultiplicativeOperationIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import org.rumbledb.runtime.primary.VariableReferenceIterator;
import java.math.BigInteger;
@@ -38,7 +37,7 @@
import java.util.Map;
import java.util.TreeMap;
-public class AvgFunctionIterator extends LocalFunctionCallIterator {
+public class AvgFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -53,25 +52,22 @@ public AvgFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
+ public Item materializeFirstItemOrNull(DynamicContext context) {
Item count = CountFunctionIterator.computeCount(
this.children.get(0),
- this.currentDynamicContextForLocalExecution,
+ context,
getMetadata()
);
if (count.isInt() && count.getIntValue() == 0) {
- this.hasNext = false;
- return;
+ return null;
}
if (count.isInteger() && count.getIntegerValue().equals(BigInteger.ZERO)) {
- this.hasNext = false;
- return;
+ return null;
}
Item sum = SumFunctionIterator.computeSum(
ItemFactory.getInstance().createIntegerItem(BigInteger.ZERO),
this.children.get(0),
- this.currentDynamicContextForLocalExecution,
+ context,
getMetadata()
);
this.item = MultiplicativeOperationIterator.processItem(
@@ -80,20 +76,7 @@ public void open(DynamicContext context) {
MultiplicativeExpression.MultiplicativeOperator.DIV,
getMetadata()
);
- this.hasNext = true;
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return this.item;
- } else {
- throw new IteratorFlowException(
- FLOW_EXCEPTION_MESSAGE + "SUM function",
- getMetadata()
- );
- }
+ return this.item;
}
public Map getVariableDependencies() {
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/CountFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/CountFunctionIterator.java
index 66bf52522c..c4a7b79764 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/CountFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/CountFunctionIterator.java
@@ -24,19 +24,18 @@
import org.rumbledb.context.DynamicContext;
import org.rumbledb.context.Name;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.exceptions.OurBadException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import org.rumbledb.runtime.primary.VariableReferenceIterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
-public class CountFunctionIterator extends LocalFunctionCallIterator {
+public class CountFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
/**
*
*/
@@ -50,32 +49,26 @@ public CountFunctionIterator(
super(arguments, executionMode, iteratorMetadata);
}
+
@Override
- public Item next() {
- if (this.hasNext) {
- RuntimeIterator iterator = this.children.get(0);
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ RuntimeIterator iterator = this.children.get(0);
- // the count($x) case is treated separately because we can short-circuit the
- // count, e.g., if it comes from the group-by aggregation of a non-grouping
- // key.
- if (iterator instanceof VariableReferenceIterator) {
- VariableReferenceIterator expr = (VariableReferenceIterator) iterator;
- this.hasNext = false;
- return this.currentDynamicContextForLocalExecution.getVariableValues()
- .getVariableCount(expr.getVariableName());
- }
- this.hasNext = false;
- return computeCount(
- this.children.get(0),
- this.currentDynamicContextForLocalExecution,
- getMetadata()
- );
- } else {
- throw new IteratorFlowException(
- FLOW_EXCEPTION_MESSAGE + " count function",
- getMetadata()
- );
+ // the count($x) case is treated separately because we can short-circuit the
+ // count, e.g., if it comes from the group-by aggregation of a non-grouping
+ // key.
+ if (iterator instanceof VariableReferenceIterator) {
+ VariableReferenceIterator expr = (VariableReferenceIterator) iterator;
+ // this.hasNext = false;
+ return context.getVariableValues()
+ .getVariableCount(expr.getVariableName());
}
+ return computeCount(
+ iterator,
+ context,
+ getMetadata()
+ );
+
}
public static Item computeCount(
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java
index 48423d1723..5ed560f999 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/SumFunctionIterator.java
@@ -26,13 +26,12 @@
import org.rumbledb.context.Name;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.InvalidArgumentTypeException;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.items.structured.JSoundDataFrame;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.arithmetics.AdditiveOperationIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import org.rumbledb.runtime.primary.VariableReferenceIterator;
import sparksoniq.spark.SparkSessionManager;
@@ -42,7 +41,7 @@
import java.util.Map;
import java.util.TreeMap;
-public class SumFunctionIterator extends LocalFunctionCallIterator {
+public class SumFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -57,33 +56,22 @@ public SumFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
+ public Item materializeFirstItemOrNull(DynamicContext context) {
this.item = computeSum(
- zeroElement(),
+ zeroElement(context),
this.children.get(0),
- this.currentDynamicContextForLocalExecution,
+ context,
getMetadata()
);
- this.hasNext = this.item != null;
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return this.item;
- } else {
- throw new IteratorFlowException(
- FLOW_EXCEPTION_MESSAGE + "SUM function",
- getMetadata()
- );
+ if (this.item == null) {
+ return null;
}
+ return this.item;
}
- private Item zeroElement() {
+ private Item zeroElement(DynamicContext context) {
if (this.children.size() > 1) {
- return this.children.get(1).materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
+ return this.children.get(1).materializeFirstItemOrNull(context);
} else {
return ItemFactory.getInstance().createIntegerItem(BigInteger.ZERO);
}
From 7b9ff713a4303a0b524bd92c14d7956fbf9b0a81 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Fri, 11 Jun 2021 16:17:19 +0200
Subject: [PATCH 018/142] AtMostOne: ZeroOrOne (Cardinality) and Replace
---
.../CardinalityFunctionIterator.java | 4 +-
.../cardinality/ZeroOrOneIterator.java | 49 +++-------
.../strings/ReplaceFunctionIterator.java | 93 +++++++++----------
3 files changed, 62 insertions(+), 84 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/cardinality/CardinalityFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/cardinality/CardinalityFunctionIterator.java
index 0c7f8f0835..e775cbb6f5 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/cardinality/CardinalityFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/cardinality/CardinalityFunctionIterator.java
@@ -22,12 +22,12 @@
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.expressions.ExecutionMode;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public abstract class CardinalityFunctionIterator extends LocalFunctionCallIterator {
+public abstract class CardinalityFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/cardinality/ZeroOrOneIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/cardinality/ZeroOrOneIterator.java
index d9461867d5..2a9012932e 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/cardinality/ZeroOrOneIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/cardinality/ZeroOrOneIterator.java
@@ -24,7 +24,6 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.exceptions.SequenceExceptionZeroOrOne;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.runtime.RuntimeIterator;
@@ -46,47 +45,27 @@ public ZeroOrOneIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return this.nextResult;
- }
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " ZERO-OR-ONE function",
- getMetadata()
- );
- }
-
- @Override
- public void open(DynamicContext context) {
- super.open(context);
-
+ public Item materializeFirstItemOrNull(DynamicContext context) {
RuntimeIterator sequenceIterator = this.children.get(0);
-
if (!sequenceIterator.isRDDOrDataFrame()) {
- sequenceIterator.open(context);
- if (!sequenceIterator.hasNext()) {
- this.hasNext = false;
+ List
- results = sequenceIterator.materialize(context);
+ if (results.size() == 0) {
+ return null;
+ } else if (results.size() == 1) {
+ return results.get(0);
} else {
- this.nextResult = sequenceIterator.next();
- if (sequenceIterator.hasNext()) {
- throw new SequenceExceptionZeroOrOne(
- "fn:zero-or-one() called with a sequence containing more than one item",
- getMetadata()
- );
- } else {
- this.hasNext = true;
- }
+ throw new SequenceExceptionZeroOrOne(
+ "fn:zero-or-one() called with a sequence containing more than one item",
+ getMetadata()
+ );
}
- sequenceIterator.close();
} else {
- JavaRDD
- rdd = sequenceIterator.getRDD(this.currentDynamicContextForLocalExecution);
+ JavaRDD
- rdd = sequenceIterator.getRDD(context);
List
- results = rdd.take(2);
if (results.size() == 0) {
- this.hasNext = false;
+ return null;
} else if (results.size() == 1) {
- this.hasNext = true;
- this.nextResult = results.get(0);
+ return results.get(0);
} else if (results.size() > 1) {
throw new SequenceExceptionZeroOrOne(
"fn:zero-or-one() called with a sequence containing more than one item",
@@ -94,5 +73,7 @@ public void open(DynamicContext context) {
);
}
}
+ return null;
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/ReplaceFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/ReplaceFunctionIterator.java
index 7c5cd988e8..4e1b23afd8 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/ReplaceFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/ReplaceFunctionIterator.java
@@ -21,22 +21,22 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.InvalidRegexPatternException;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.exceptions.MatchesEmptyStringException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.exceptions.InvalidReplacementStringException;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.regex.PatternSyntaxException;
-public class ReplaceFunctionIterator extends LocalFunctionCallIterator {
+public class ReplaceFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -49,56 +49,53 @@ public ReplaceFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item stringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item stringItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ Item patternStringItem = this.children.get(1)
+ .materializeFirstItemOrNull(context);
- Item patternStringItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- String pattern = patternStringItem.getStringValue();
-
- Pattern p;
- try {
- p = Pattern.compile(pattern);
- } catch (PatternSyntaxException e) {
- throw new InvalidRegexPatternException(
- e.getDescription(),
- getMetadata()
- );
- }
- if ("".matches(pattern)) {
- throw new MatchesEmptyStringException(
- "'" + pattern + "' matches empty string",
- getMetadata()
- );
- }
-
- Item replacementStringItem = this.children.get(2)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- String replacement = replacementStringItem.getStringValue();
- if (!(checkReplacementStringForValidity(replacement))) {
- throw new InvalidReplacementStringException(
- "'" + replacement + "' contains a disallowed sequence of characters",
- getMetadata()
- );
- }
+ if (patternStringItem == null) {
+ return null;
+ }
+ String pattern = patternStringItem.getStringValue();
+ Pattern p;
- String input;
- if (stringItem == null) {
- input = "";
- } else {
- input = stringItem.getStringValue();
- }
+ try {
+ p = Pattern.compile(pattern);
+ } catch (PatternSyntaxException e) {
+ throw new InvalidRegexPatternException(
+ e.getDescription(),
+ getMetadata()
+ );
+ }
+ if ("".matches(pattern)) {
+ throw new MatchesEmptyStringException(
+ "'" + pattern + "' matches empty string",
+ getMetadata()
+ );
+ }
- Matcher m = p.matcher(input);
- return ItemFactory.getInstance().createStringItem(m.replaceAll(replacement));
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " replace function",
+ Item replacementStringItem = this.children.get(2)
+ .materializeFirstItemOrNull(context);
+ String replacement = replacementStringItem.getStringValue();
+ if (!(checkReplacementStringForValidity(replacement))) {
+ throw new InvalidReplacementStringException(
+ "'" + replacement + "' contains a disallowed sequence of characters",
getMetadata()
);
+ }
+
+ String input;
+ if (stringItem == null) {
+ input = "";
+ } else {
+ input = stringItem.getStringValue();
+ }
+
+ Matcher m = p.matcher(input);
+ return ItemFactory.getInstance().createStringItem(m.replaceAll(replacement));
+
}
private static boolean checkReplacementStringForValidity(String repl) {
From 7614f864ff8a2640671c27415c70f5ea70fdc8c2 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Fri, 11 Jun 2021 16:54:09 +0200
Subject: [PATCH 019/142] AtMostOne String functions
Contains, Matches, Substring, Substring After/Before, Translate
---
.../strings/ContainsFunctionIterator.java | 45 +++++------
.../strings/MatchesFunctionIterator.java | 36 ++++-----
.../SubstringAfterFunctionIterator.java | 58 ++++++--------
.../SubstringBeforeFunctionIterator.java | 64 +++++++--------
.../strings/SubstringFunctionIterator.java | 74 ++++++++---------
.../strings/TranslateFunctionIterator.java | 79 +++++++++----------
6 files changed, 155 insertions(+), 201 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/ContainsFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/ContainsFunctionIterator.java
index 96ae94b26b..2c46ee4802 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/ContainsFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/ContainsFunctionIterator.java
@@ -21,16 +21,16 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class ContainsFunctionIterator extends LocalFunctionCallIterator {
+public class ContainsFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -43,29 +43,22 @@ public ContainsFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item substringItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (substringItem == null || substringItem.getStringValue().isEmpty()) {
- return ItemFactory.getInstance().createBooleanItem(true);
- }
- Item stringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (stringItem == null || stringItem.getStringValue().isEmpty()) {
- return ItemFactory.getInstance().createBooleanItem(false);
- }
- boolean result = stringItem.getStringValue()
- .contains(
- substringItem.getStringValue()
- );
- return ItemFactory.getInstance().createBooleanItem(result);
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " contains function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item substringItem = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ if (substringItem == null || substringItem.getStringValue().isEmpty()) {
+ return ItemFactory.getInstance().createBooleanItem(true);
+ }
+ Item stringItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (stringItem == null || stringItem.getStringValue().isEmpty()) {
+ return ItemFactory.getInstance().createBooleanItem(false);
}
+ boolean result = stringItem.getStringValue()
+ .contains(
+ substringItem.getStringValue()
+ );
+ return ItemFactory.getInstance().createBooleanItem(result);
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/MatchesFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/MatchesFunctionIterator.java
index 1938269fd7..a616a4ba68 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/MatchesFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/MatchesFunctionIterator.java
@@ -21,18 +21,18 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-public class MatchesFunctionIterator extends LocalFunctionCallIterator {
+public class MatchesFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -45,26 +45,18 @@ public MatchesFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item regexpItem = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ Item stringItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (stringItem == null) {
+ stringItem = ItemFactory.getInstance().createStringItem("");
+ }
- Item regexpItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- Item stringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (stringItem == null) {
- stringItem = ItemFactory.getInstance().createStringItem("");
- }
+ Matcher matcher = Pattern.compile(regexpItem.getStringValue()).matcher(stringItem.getStringValue());
+ boolean result = matcher.find();
+ return ItemFactory.getInstance().createBooleanItem(result);
- Matcher matcher = Pattern.compile(regexpItem.getStringValue()).matcher(stringItem.getStringValue());
- boolean result = matcher.find();
- return ItemFactory.getInstance().createBooleanItem(result);
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " matches function",
- getMetadata()
- );
- }
}
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/SubstringAfterFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/SubstringAfterFunctionIterator.java
index 25902f4beb..bbc91f2275 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/SubstringAfterFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/SubstringAfterFunctionIterator.java
@@ -1,16 +1,16 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class SubstringAfterFunctionIterator extends LocalFunctionCallIterator {
+public class SubstringAfterFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -23,37 +23,29 @@ public SubstringAfterFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item stringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- Item substringItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
-
- if (stringItem == null || stringItem.getStringValue().isEmpty()) {
- return ItemFactory.getInstance().createStringItem("");
- }
- if (substringItem == null || substringItem.getStringValue().isEmpty()) {
- return ItemFactory.getInstance().createStringItem(stringItem.getStringValue());
- }
-
- int indexOfOccurrence = stringItem.getStringValue().indexOf(substringItem.getStringValue());
- return indexOfOccurrence == -1
- ? ItemFactory.getInstance().createStringItem("")
- : ItemFactory.getInstance()
- .createStringItem(
- stringItem.getStringValue()
- .substring(
- indexOfOccurrence + substringItem.getStringValue().length()
- )
- );
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " substring-after function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item stringItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ Item substringItem = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+
+ if (stringItem == null || stringItem.getStringValue().isEmpty()) {
+ return ItemFactory.getInstance().createStringItem("");
+ }
+ if (substringItem == null || substringItem.getStringValue().isEmpty()) {
+ return ItemFactory.getInstance().createStringItem(stringItem.getStringValue());
}
+ int indexOfOccurrence = stringItem.getStringValue().indexOf(substringItem.getStringValue());
+ return indexOfOccurrence == -1
+ ? ItemFactory.getInstance().createStringItem("")
+ : ItemFactory.getInstance()
+ .createStringItem(
+ stringItem.getStringValue()
+ .substring(
+ indexOfOccurrence + substringItem.getStringValue().length()
+ )
+ );
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/SubstringBeforeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/SubstringBeforeFunctionIterator.java
index f389b42f69..eafc21e68b 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/SubstringBeforeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/SubstringBeforeFunctionIterator.java
@@ -1,16 +1,16 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class SubstringBeforeFunctionIterator extends LocalFunctionCallIterator {
+public class SubstringBeforeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -23,39 +23,31 @@ public SubstringBeforeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item stringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- Item substringItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (
- substringItem == null
- || substringItem.getStringValue().isEmpty()
- ||
- stringItem == null
- || stringItem.getStringValue().isEmpty()
- ) {
- return ItemFactory.getInstance().createStringItem("");
- }
- int indexOfOccurrence = stringItem.getStringValue().indexOf(substringItem.getStringValue());
- return indexOfOccurrence == -1
- ? ItemFactory.getInstance().createStringItem("")
- : ItemFactory.getInstance()
- .createStringItem(
- stringItem.getStringValue()
- .substring(
- 0,
- indexOfOccurrence
- )
- );
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " substring-before function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item stringItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ Item substringItem = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ if (
+ substringItem == null
+ || substringItem.getStringValue().isEmpty()
+ ||
+ stringItem == null
+ || stringItem.getStringValue().isEmpty()
+ ) {
+ return ItemFactory.getInstance().createStringItem("");
}
-
+ int indexOfOccurrence = stringItem.getStringValue().indexOf(substringItem.getStringValue());
+ return indexOfOccurrence == -1
+ ? ItemFactory.getInstance().createStringItem("")
+ : ItemFactory.getInstance()
+ .createStringItem(
+ stringItem.getStringValue()
+ .substring(
+ 0,
+ indexOfOccurrence
+ )
+ );
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/SubstringFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/SubstringFunctionIterator.java
index 0621871418..19da188cef 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/SubstringFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/SubstringFunctionIterator.java
@@ -21,17 +21,17 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.exceptions.UnexpectedTypeException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class SubstringFunctionIterator extends LocalFunctionCallIterator {
+public class SubstringFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -44,52 +44,44 @@ public SubstringFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- String result;
- Item stringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (stringItem == null) {
- return ItemFactory.getInstance().createStringItem("");
- }
- Item indexItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (indexItem == null) {
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ String result;
+ Item stringItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (stringItem == null) {
+ return ItemFactory.getInstance().createStringItem("");
+ }
+ Item indexItem = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ if (indexItem == null) {
+ throw new UnexpectedTypeException(
+ "Type error; Start index parameter can't be empty sequence ",
+ getMetadata()
+ );
+ }
+ int index = (int) Math.round(indexItem.getDoubleValue() - 1);
+ if (index >= stringItem.getStringValue().length()) {
+ return ItemFactory.getInstance().createStringItem("");
+ }
+ if (this.children.size() > 2) {
+ Item endIndexItem = this.children.get(2)
+ .materializeFirstItemOrNull(context);
+ if (endIndexItem == null) {
throw new UnexpectedTypeException(
- "Type error; Start index parameter can't be empty sequence ",
+ "Type error; End index parameter can't be empty sequence ",
getMetadata()
);
}
- int index = (int) Math.round(indexItem.getDoubleValue() - 1);
- if (index >= stringItem.getStringValue().length()) {
+ double endIndex = sanitizeEndIndex(stringItem, endIndexItem, index);
+ if (endIndex < index) {
return ItemFactory.getInstance().createStringItem("");
}
- if (this.children.size() > 2) {
- Item endIndexItem = this.children.get(2)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (endIndexItem == null) {
- throw new UnexpectedTypeException(
- "Type error; End index parameter can't be empty sequence ",
- getMetadata()
- );
- }
- double endIndex = sanitizeEndIndex(stringItem, endIndexItem, index);
- if (endIndex < index) {
- return ItemFactory.getInstance().createStringItem("");
- }
- result = stringItem.getStringValue().substring(Math.max(index, 0), (int) Math.round(endIndex));
- } else {
- result = stringItem.getStringValue().substring(index);
- }
-
- return ItemFactory.getInstance().createStringItem(result);
+ result = stringItem.getStringValue().substring(Math.max(index, 0), (int) Math.round(endIndex));
} else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " substring function",
- getMetadata()
- );
+ result = stringItem.getStringValue().substring(index);
}
+
+ return ItemFactory.getInstance().createStringItem(result);
}
private double sanitizeEndIndex(Item stringItem, Item endIndexItem, int startIndex) {
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/TranslateFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/TranslateFunctionIterator.java
index bd0a87497f..f0302909af 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/TranslateFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/TranslateFunctionIterator.java
@@ -21,18 +21,18 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
import java.util.HashMap;
import java.util.stream.Collectors;
-public class TranslateFunctionIterator extends LocalFunctionCallIterator {
+public class TranslateFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -45,51 +45,44 @@ public TranslateFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item inputItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- Item mapStringItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- Item transStringItem = this.children.get(2)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item inputItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ Item mapStringItem = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ Item transStringItem = this.children.get(2)
+ .materializeFirstItemOrNull(context);
- if (inputItem == null) {
- return ItemFactory.getInstance().createStringItem("");
- }
+ if (inputItem == null) {
+ return ItemFactory.getInstance().createStringItem("");
+ }
- String input = inputItem.getStringValue();
- String mapString = mapStringItem.getStringValue();
- String transString = transStringItem.getStringValue();
+ String input = inputItem.getStringValue();
+ String mapString = mapStringItem.getStringValue();
+ String transString = transStringItem.getStringValue();
- HashMap mp = new HashMap<>();
- for (int i = 0; i < mapString.length(); i++) {
- char c = mapString.charAt(i);
- if (!(mp.containsKey(c))) {
- mp.put(c, i < transString.length() ? transString.charAt(i) : '\0');
- }
+ HashMap mp = new HashMap<>();
+ for (int i = 0; i < mapString.length(); i++) {
+ char c = mapString.charAt(i);
+ if (!(mp.containsKey(c))) {
+ mp.put(c, i < transString.length() ? transString.charAt(i) : '\0');
}
+ }
- String output = input
- .codePoints()
- .mapToObj(c -> (char) c)
- .filter(s -> !(mp.containsKey(s) && mp.get(s) == '\0'))
- .map(s -> {
- if (mp.containsKey(s)) {
- return mp.get(s);
- }
- return s;
- })
- .map(String::valueOf)
- .collect(Collectors.joining());
-
- return ItemFactory.getInstance().createStringItem(output);
+ String output = input
+ .codePoints()
+ .mapToObj(c -> (char) c)
+ .filter(s -> !(mp.containsKey(s) && mp.get(s) == '\0'))
+ .map(s -> {
+ if (mp.containsKey(s)) {
+ return mp.get(s);
+ }
+ return s;
+ })
+ .map(String::valueOf)
+ .collect(Collectors.joining());
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " translate function",
- getMetadata()
- );
+ return ItemFactory.getInstance().createStringItem(output);
}
+
}
From 4024df36ccb18a2cf1212006c195c79ff226e3b7 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Fri, 11 Jun 2021 17:14:20 +0200
Subject: [PATCH 020/142] Normalize Space and Unicode, Codepoints2String.
---
.../CodepointsToStringFunctionIterator.java | 48 +++++-----
.../NormalizeSpaceFunctionIterator.java | 30 +++----
.../NormalizeUnicodeFunctionIterator.java | 87 +++++++++----------
3 files changed, 72 insertions(+), 93 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/CodepointsToStringFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/CodepointsToStringFunctionIterator.java
index ad59b87c53..35a9dca6d5 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/CodepointsToStringFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/CodepointsToStringFunctionIterator.java
@@ -21,18 +21,18 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.exceptions.UnexpectedTypeException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.exceptions.CodepointNotValidException;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class CodepointsToStringFunctionIterator extends LocalFunctionCallIterator {
+public class CodepointsToStringFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -45,34 +45,28 @@ public CodepointsToStringFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- List
- codepoints = this.children.get(0).materialize(this.currentDynamicContextForLocalExecution);
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ List
- codepoints = this.children.get(0).materialize(context);
- StringBuilder stringBuilder = new StringBuilder();
- for (Item item : codepoints) {
- if (!(item.isInt())) {
- throw new UnexpectedTypeException(
- "Int item expected",
- this.children.get(0).getMetadata()
- );
- } else if (!(isValidCodePoint(item.getIntValue()))) {
- throw new CodepointNotValidException(
- "Non-XML-conformant codepoint: " + item.getIntValue(),
- this.children.get(0).getMetadata()
- );
- }
- stringBuilder.appendCodePoint(item.getIntValue());
+ StringBuilder stringBuilder = new StringBuilder();
+ for (Item item : codepoints) {
+ if (!(item.isInt())) {
+ throw new UnexpectedTypeException(
+ "Int item expected",
+ this.children.get(0).getMetadata()
+ );
+ } else if (!(isValidCodePoint(item.getIntValue()))) {
+ throw new CodepointNotValidException(
+ "Non-XML-conformant codepoint: " + item.getIntValue(),
+ this.children.get(0).getMetadata()
+ );
}
- this.hasNext = false;
- return ItemFactory.getInstance().createStringItem(stringBuilder.toString());
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " codepoints-to-string function",
- getMetadata()
- );
+ stringBuilder.appendCodePoint(item.getIntValue());
+ }
+ return ItemFactory.getInstance().createStringItem(stringBuilder.toString());
}
+
private static boolean isValidCodePoint(int codepoint) {
/* Checks if the codepoints are within the ranges allowed for in the XML 1.1 specification. */
return 1 <= codepoint && codepoint <= 55295
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/NormalizeSpaceFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/NormalizeSpaceFunctionIterator.java
index 604aab5ad6..69819b1ecf 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/NormalizeSpaceFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/NormalizeSpaceFunctionIterator.java
@@ -22,16 +22,16 @@
import org.apache.commons.lang.StringUtils;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class NormalizeSpaceFunctionIterator extends LocalFunctionCallIterator {
+public class NormalizeSpaceFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -44,23 +44,15 @@ public NormalizeSpaceFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item stringItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
- Item stringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
-
- if (stringItem == null) {
- return ItemFactory.getInstance().createStringItem("");
- }
-
- return ItemFactory.getInstance().createStringItem(StringUtils.normalizeSpace(stringItem.getStringValue()));
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " normalize-space function",
- getMetadata()
- );
+ if (stringItem == null) {
+ return ItemFactory.getInstance().createStringItem("");
}
+
+ return ItemFactory.getInstance().createStringItem(StringUtils.normalizeSpace(stringItem.getStringValue()));
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/NormalizeUnicodeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/NormalizeUnicodeFunctionIterator.java
index 37082d2905..606871c5fe 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/NormalizeUnicodeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/NormalizeUnicodeFunctionIterator.java
@@ -21,20 +21,20 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.InvalidNormalizationException;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.text.Normalizer;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
-public class NormalizeUnicodeFunctionIterator extends LocalFunctionCallIterator {
+public class NormalizeUnicodeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private static final HashSet exclusionCharacters = new HashSet(
@@ -133,56 +133,49 @@ public NormalizeUnicodeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- boolean fullyNormalized = false;
- Normalizer.Form normalizationForm = Normalizer.Form.NFC;
- Item inputItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ boolean fullyNormalized = false;
+ Normalizer.Form normalizationForm = Normalizer.Form.NFC;
+ Item inputItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
- if (inputItem == null) {
- return ItemFactory.getInstance().createStringItem("");
- }
-
- if (this.children.size() > 1) {
- Item normalizationFormItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
+ if (inputItem == null) {
+ return ItemFactory.getInstance().createStringItem("");
+ }
- String normalizationFormRaw = normalizationFormItem.getStringValue();
- if (normalizationFormRaw.length() == 0) {
- return inputItem;
- }
+ if (this.children.size() > 1) {
+ Item normalizationFormItem = this.children.get(1)
+ .materializeFirstItemOrNull(context);
- if (
- normalizationFormRaw.equals("NFC")
- || normalizationFormRaw.equals("NFD")
- || normalizationFormRaw.equals("NFKC")
- || normalizationFormRaw.equals("NFKD")
- ) {
- normalizationForm = Normalizer.Form.valueOf(normalizationFormItem.getStringValue());
- } else if (normalizationFormRaw.equals("FULLY-NORMALIZED")) {
- fullyNormalized = true;
- normalizationForm = Normalizer.Form.NFC;
- } else {
- throw new InvalidNormalizationException(
- normalizationFormRaw + " is not a valid normalization form",
- getMetadata()
- );
- }
+ String normalizationFormRaw = normalizationFormItem.getStringValue();
+ if (normalizationFormRaw.length() == 0) {
+ return inputItem;
}
- String input = inputItem.getStringValue();
- if (fullyNormalized && exclusionCharacters.contains(input.codePointAt(0))) {
- input = " " + input;
+ if (
+ normalizationFormRaw.equals("NFC")
+ || normalizationFormRaw.equals("NFD")
+ || normalizationFormRaw.equals("NFKC")
+ || normalizationFormRaw.equals("NFKD")
+ ) {
+ normalizationForm = Normalizer.Form.valueOf(normalizationFormItem.getStringValue());
+ } else if (normalizationFormRaw.equals("FULLY-NORMALIZED")) {
+ fullyNormalized = true;
+ normalizationForm = Normalizer.Form.NFC;
+ } else {
+ throw new InvalidNormalizationException(
+ normalizationFormRaw + " is not a valid normalization form",
+ getMetadata()
+ );
}
- String normalizedString = Normalizer.normalize(input, normalizationForm);
- return ItemFactory.getInstance().createStringItem(normalizedString);
+ }
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " translate function",
- getMetadata()
- );
+ String input = inputItem.getStringValue();
+ if (fullyNormalized && exclusionCharacters.contains(input.codePointAt(0))) {
+ input = " " + input;
+ }
+ String normalizedString = Normalizer.normalize(input, normalizationForm);
+ return ItemFactory.getInstance().createStringItem(normalizedString);
}
+
}
From 254b637ee23649a40872d610fadd3000c2106231 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Sun, 13 Jun 2021 15:26:43 +0200
Subject: [PATCH 021/142] AtMostOne - Time functions
---
.../datetime/CurrentDateFunctionIterator.java | 16 +-
.../CurrentDateTimeFunctionIterator.java | 16 +-
.../datetime/CurrentTimeFunctionIterator.java | 16 +-
.../datetime/FormatDateFunctionIterator.java | 224 ++++++++---------
.../FormatDateTimeFunctionIterator.java | 232 +++++++++---------
.../datetime/FormatTimeFunctionIterator.java | 232 +++++++++---------
.../components/AdjustDateTimeToTimezone.java | 103 ++++----
.../components/AdjustDateToTimezone.java | 103 ++++----
.../components/AdjustTimeToTimezone.java | 103 ++++----
.../DayFromDateFunctionIterator.java | 23 +-
.../DayFromDateTimeFunctionIterator.java | 25 +-
.../TimezoneFromDateFunctionIterator.java | 28 +--
.../TimezoneFromDateTimeFunctionIterator.java | 28 +--
.../TimezoneFromTimeFunctionIterator.java | 27 +-
.../DayTimeDurationFunctionIterator.java | 39 ++-
.../DaysFromDurationFunctionIterator.java | 25 +-
16 files changed, 553 insertions(+), 687 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateFunctionIterator.java
index 443f4b0d5a..3a97d2019b 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateFunctionIterator.java
@@ -2,16 +2,18 @@
import org.joda.time.DateTime;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class CurrentDateFunctionIterator extends LocalFunctionCallIterator {
+public class CurrentDateFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -24,14 +26,8 @@ public CurrentDateFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createDateItem(new DateTime(), true);
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " current-date function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ return ItemFactory.getInstance().createDateItem(new DateTime(), true);
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateTimeFunctionIterator.java
index 0cbbabf901..902d2cd933 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateTimeFunctionIterator.java
@@ -2,16 +2,18 @@
import org.joda.time.DateTime;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class CurrentDateTimeFunctionIterator extends LocalFunctionCallIterator {
+public class CurrentDateTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -24,14 +26,8 @@ public CurrentDateTimeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createDateTimeItem(new DateTime(), true);
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " current-dateTime function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ return ItemFactory.getInstance().createDateTimeItem(new DateTime(), true);
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentTimeFunctionIterator.java
index cc6984b144..b45a605eff 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentTimeFunctionIterator.java
@@ -2,16 +2,18 @@
import org.joda.time.DateTime;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class CurrentTimeFunctionIterator extends LocalFunctionCallIterator {
+public class CurrentTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -24,14 +26,8 @@ public CurrentTimeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createTimeItem(new DateTime(), true);
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " current-time function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ return ItemFactory.getInstance().createTimeItem(new DateTime(), true);
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateFunctionIterator.java
index bfaebd15c7..2839571d30 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateFunctionIterator.java
@@ -11,6 +11,7 @@
import org.rumbledb.exceptions.UnsupportedFeatureException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
@@ -19,7 +20,7 @@
import java.util.Calendar;
import java.util.List;
-public class FormatDateFunctionIterator extends LocalFunctionCallIterator {
+public class FormatDateFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item valueDateItem = null;
@@ -33,6 +34,112 @@ public FormatDateFunctionIterator(
super(arguments, executionMode, iteratorMetadata);
}
+ @Override
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.valueDateItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ this.pictureStringItem = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ if (this.valueDateItem == null || this.pictureStringItem == null) {
+ return null;
+ }
+ try {
+ if (this.valueDateItem.isNull()) {
+ return this.valueDateItem;
+ }
+
+ DateTime dateValue = this.valueDateItem.getDateTimeValue();
+ String pictureString = this.pictureStringItem.getStringValue();
+
+ int startOfSequence = 0;
+ boolean variableMarkerSequence = false;
+
+ StringBuilder result = new StringBuilder();
+
+ // Iterate over picture
+ for (int i = 0; i < pictureString.length(); i++) {
+ char c = pictureString.charAt(i);
+ if (variableMarkerSequence) {
+ if (c == ']') {
+ String variableMarker = pictureString.substring(startOfSequence, i);
+ String pattern = parseVariableMarker(variableMarker, result);
+
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern.toString());
+ Calendar formatCalendar = Calendar.getInstance();
+ formatCalendar.set(
+ dateValue.getYear(),
+ dateValue.getMonthOfYear() - 1,
+ dateValue.getDayOfMonth()
+ );
+ result.append(simpleDateFormat.format(formatCalendar.getTime()));
+
+ variableMarkerSequence = false;
+ startOfSequence = i + 1;
+ }
+ } else {
+ if (c == ']') {
+ if (i == pictureString.length() - 1 || pictureString.charAt(i + 1) != ']') {
+ String message = String.format(
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
+ );
+ throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
+ } else {
+ String literalSubstring = pictureString.substring(startOfSequence, i + 1);
+ result.append(literalSubstring);
+ startOfSequence = i + 2;
+ i++;
+ }
+ } else if (c == '[') {
+ if (i == pictureString.length() - 1) {
+ String message = String.format(
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
+ );
+ throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
+ }
+
+ if (pictureString.charAt(i + 1) == '[') {
+ String literalSubstring = pictureString.substring(startOfSequence, i + 1);
+ result.append(literalSubstring);
+ startOfSequence = i + 2;
+ i++;
+ } else {
+ String literalSubstring = pictureString.substring(startOfSequence, i);
+ result.append(literalSubstring);
+ variableMarkerSequence = true;
+ startOfSequence = i + 1;
+ }
+ }
+ }
+ }
+
+ if (startOfSequence != pictureString.length()) {
+ if (variableMarkerSequence) {
+ String message = String.format(
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
+ );
+ throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
+ } else {
+ String literalSubstring = pictureString.substring(
+ startOfSequence,
+ pictureString.length()
+ );
+ result.append(literalSubstring);
+ }
+ }
+ return ItemFactory.getInstance().createStringItem(result.toString());
+ } catch (UnsupportedOperationException | IllegalArgumentException e) {
+ String message = String.format(
+ "\"%s\": not castable to type %s",
+ this.valueDateItem.serialize(),
+ "date"
+ );
+ throw new CastException(message, getMetadata());
+ }
+ }
+
private String parsePresentationModifiers(String presentationModifiers) {
String presentationModifier1 = "";
@@ -235,119 +342,4 @@ private String parseVariableMarker(String variableMarker, StringBuilder result)
return pattern.toString();
}
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- try {
- if (this.valueDateItem.isNull()) {
- return this.valueDateItem;
- }
-
- DateTime dateValue = this.valueDateItem.getDateTimeValue();
- String pictureString = this.pictureStringItem.getStringValue();
-
- int startOfSequence = 0;
- boolean variableMarkerSequence = false;
-
- StringBuilder result = new StringBuilder();
-
- // Iterate over picture
- for (int i = 0; i < pictureString.length(); i++) {
- char c = pictureString.charAt(i);
- if (variableMarkerSequence) {
- if (c == ']') {
- String variableMarker = pictureString.substring(startOfSequence, i);
- String pattern = parseVariableMarker(variableMarker, result);
-
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern.toString());
- Calendar formatCalendar = Calendar.getInstance();
- formatCalendar.set(
- dateValue.getYear(),
- dateValue.getMonthOfYear() - 1,
- dateValue.getDayOfMonth()
- );
- result.append(simpleDateFormat.format(formatCalendar.getTime()));
-
- variableMarkerSequence = false;
- startOfSequence = i + 1;
- }
- } else {
- if (c == ']') {
- if (i == pictureString.length() - 1 || pictureString.charAt(i + 1) != ']') {
- String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
- );
- throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
- } else {
- String literalSubstring = pictureString.substring(startOfSequence, i + 1);
- result.append(literalSubstring);
- startOfSequence = i + 2;
- i++;
- }
- } else if (c == '[') {
- if (i == pictureString.length() - 1) {
- String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
- );
- throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
- }
-
- if (pictureString.charAt(i + 1) == '[') {
- String literalSubstring = pictureString.substring(startOfSequence, i + 1);
- result.append(literalSubstring);
- startOfSequence = i + 2;
- i++;
- } else {
- String literalSubstring = pictureString.substring(startOfSequence, i);
- result.append(literalSubstring);
- variableMarkerSequence = true;
- startOfSequence = i + 1;
- }
- }
- }
- }
-
- if (startOfSequence != pictureString.length()) {
- if (variableMarkerSequence) {
- String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
- );
- throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
- } else {
- String literalSubstring = pictureString.substring(
- startOfSequence,
- pictureString.length()
- );
- result.append(literalSubstring);
- }
- }
- return ItemFactory.getInstance().createStringItem(result.toString());
- } catch (UnsupportedOperationException | IllegalArgumentException e) {
- String message = String.format(
- "\"%s\": not castable to type %s",
- this.valueDateItem.serialize(),
- "date"
- );
- throw new CastException(message, getMetadata());
- }
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " format-date function",
- getMetadata()
- );
- }
-
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.valueDateItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.pictureStringItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.valueDateItem != null && this.pictureStringItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateTimeFunctionIterator.java
index 2ea82ec9df..93912bb288 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateTimeFunctionIterator.java
@@ -11,6 +11,7 @@
import org.rumbledb.exceptions.UnsupportedFeatureException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
@@ -19,7 +20,7 @@
import java.util.Calendar;
import java.util.List;
-public class FormatDateTimeFunctionIterator extends LocalFunctionCallIterator {
+public class FormatDateTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item valueDateTimeItem = null;
@@ -33,6 +34,116 @@ public FormatDateTimeFunctionIterator(
super(arguments, executionMode, iteratorMetadata);
}
+ @Override
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.valueDateTimeItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ this.pictureStringItem = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ if (this.valueDateTimeItem == null || this.pictureStringItem == null) {
+ return null;
+ }
+ try {
+ if (this.valueDateTimeItem.isNull()) {
+ return this.valueDateTimeItem;
+ }
+
+ DateTime dateTimeValue = this.valueDateTimeItem.getDateTimeValue();
+ String pictureString = this.pictureStringItem.getStringValue();
+
+ // Start sequence
+ int startOfSequence = 0;
+ boolean variableMarkerSequence = false;
+
+ StringBuilder result = new StringBuilder();
+
+ // Iterate over picture
+ for (int i = 0; i < pictureString.length(); i++) {
+ char c = pictureString.charAt(i);
+ if (variableMarkerSequence) {
+ if (c == ']') {
+ String variableMarker = pictureString.substring(startOfSequence, i);
+ String pattern = parseVariableMarker(variableMarker, result);
+
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern.toString());
+ Calendar formatCalendar = Calendar.getInstance();
+ formatCalendar.set(
+ dateTimeValue.getYear(),
+ dateTimeValue.getMonthOfYear() - 1,
+ dateTimeValue.getDayOfMonth(),
+ dateTimeValue.getHourOfDay(),
+ dateTimeValue.getMinuteOfHour(),
+ dateTimeValue.getSecondOfMinute()
+ );
+ result.append(simpleDateFormat.format(formatCalendar.getTime()));
+
+ variableMarkerSequence = false;
+ startOfSequence = i + 1;
+ }
+ } else {
+ if (c == ']') {
+ if (i == pictureString.length() - 1 || pictureString.charAt(i + 1) != ']') {
+ String message = String.format(
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
+ );
+ throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
+ } else {
+ String literalSubstring = pictureString.substring(startOfSequence, i + 1);
+ result.append(literalSubstring);
+ startOfSequence = i + 2;
+ i++;
+ }
+ } else if (c == '[') {
+ if (i == pictureString.length() - 1) {
+ String message = String.format(
+ "\"%s\": incorrect syntax lala",
+ this.pictureStringItem.serialize()
+ );
+ throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
+ }
+
+ if (pictureString.charAt(i + 1) == '[') {
+ String literalSubstring = pictureString.substring(startOfSequence, i + 1);
+ result.append(literalSubstring);
+ startOfSequence = i + 2;
+ i++;
+ } else {
+ String literalSubstring = pictureString.substring(startOfSequence, i);
+ result.append(literalSubstring);
+ variableMarkerSequence = true;
+ startOfSequence = i + 1;
+ }
+ }
+ }
+ }
+
+ if (startOfSequence != pictureString.length()) {
+ if (variableMarkerSequence) {
+ String message = String.format(
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
+ );
+ throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
+ } else {
+ String literalSubstring = pictureString.substring(
+ startOfSequence,
+ pictureString.length()
+ );
+ result.append(literalSubstring);
+ }
+ }
+ return ItemFactory.getInstance().createStringItem(result.toString());
+ } catch (UnsupportedOperationException | IllegalArgumentException e) {
+ String message = String.format(
+ "\"%s\": not castable to type %s",
+ this.valueDateTimeItem.serialize(),
+ "dateTime"
+ );
+ throw new CastException(message, getMetadata());
+ }
+ }
+
private String parsePresentationModifiers(String presentationModifiers) {
String presentationModifier1 = "";
@@ -249,123 +360,4 @@ private String parseVariableMarker(String variableMarker, StringBuilder result)
return pattern.toString();
}
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- try {
- if (this.valueDateTimeItem.isNull()) {
- return this.valueDateTimeItem;
- }
-
- DateTime dateTimeValue = this.valueDateTimeItem.getDateTimeValue();
- String pictureString = this.pictureStringItem.getStringValue();
-
- // Start sequence
- int startOfSequence = 0;
- boolean variableMarkerSequence = false;
-
- StringBuilder result = new StringBuilder();
-
- // Iterate over picture
- for (int i = 0; i < pictureString.length(); i++) {
- char c = pictureString.charAt(i);
- if (variableMarkerSequence) {
- if (c == ']') {
- String variableMarker = pictureString.substring(startOfSequence, i);
- String pattern = parseVariableMarker(variableMarker, result);
-
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern.toString());
- Calendar formatCalendar = Calendar.getInstance();
- formatCalendar.set(
- dateTimeValue.getYear(),
- dateTimeValue.getMonthOfYear() - 1,
- dateTimeValue.getDayOfMonth(),
- dateTimeValue.getHourOfDay(),
- dateTimeValue.getMinuteOfHour(),
- dateTimeValue.getSecondOfMinute()
- );
- result.append(simpleDateFormat.format(formatCalendar.getTime()));
-
- variableMarkerSequence = false;
- startOfSequence = i + 1;
- }
- } else {
- if (c == ']') {
- if (i == pictureString.length() - 1 || pictureString.charAt(i + 1) != ']') {
- String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
- );
- throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
- } else {
- String literalSubstring = pictureString.substring(startOfSequence, i + 1);
- result.append(literalSubstring);
- startOfSequence = i + 2;
- i++;
- }
- } else if (c == '[') {
- if (i == pictureString.length() - 1) {
- String message = String.format(
- "\"%s\": incorrect syntax lala",
- this.pictureStringItem.serialize()
- );
- throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
- }
-
- if (pictureString.charAt(i + 1) == '[') {
- String literalSubstring = pictureString.substring(startOfSequence, i + 1);
- result.append(literalSubstring);
- startOfSequence = i + 2;
- i++;
- } else {
- String literalSubstring = pictureString.substring(startOfSequence, i);
- result.append(literalSubstring);
- variableMarkerSequence = true;
- startOfSequence = i + 1;
- }
- }
- }
- }
-
- if (startOfSequence != pictureString.length()) {
- if (variableMarkerSequence) {
- String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
- );
- throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
- } else {
- String literalSubstring = pictureString.substring(
- startOfSequence,
- pictureString.length()
- );
- result.append(literalSubstring);
- }
- }
- return ItemFactory.getInstance().createStringItem(result.toString());
- } catch (UnsupportedOperationException | IllegalArgumentException e) {
- String message = String.format(
- "\"%s\": not castable to type %s",
- this.valueDateTimeItem.serialize(),
- "dateTime"
- );
- throw new CastException(message, getMetadata());
- }
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " format-dateTime function",
- getMetadata()
- );
- }
-
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.valueDateTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.pictureStringItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.valueDateTimeItem != null && this.pictureStringItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/FormatTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/FormatTimeFunctionIterator.java
index cdea9f166c..5091e92f32 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/FormatTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/FormatTimeFunctionIterator.java
@@ -11,6 +11,7 @@
import org.rumbledb.exceptions.UnsupportedFeatureException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
@@ -19,7 +20,7 @@
import java.util.Calendar;
import java.util.List;
-public class FormatTimeFunctionIterator extends LocalFunctionCallIterator {
+public class FormatTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item valueTimeItem = null;
@@ -33,6 +34,116 @@ public FormatTimeFunctionIterator(
super(arguments, executionMode, iteratorMetadata);
}
+ @Override
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.valueTimeItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ this.pictureStringItem = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ if (this.valueTimeItem == null || this.pictureStringItem == null) {
+ return null;
+ }
+ try {
+ if (this.valueTimeItem.isNull()) {
+ return this.valueTimeItem;
+ }
+
+ DateTime timeValue = this.valueTimeItem.getDateTimeValue();
+ String pictureString = this.pictureStringItem.getStringValue();
+
+ // Start sequence
+ int startOfSequence = 0;
+ boolean variableMarkerSequence = false;
+
+ StringBuilder result = new StringBuilder();
+
+ // Iterate over picture
+ for (int i = 0; i < pictureString.length(); i++) {
+ char c = pictureString.charAt(i);
+ if (variableMarkerSequence) {
+ if (c == ']') {
+ String variableMarker = pictureString.substring(startOfSequence, i);
+ String pattern = parseVariableMarker(variableMarker, result);
+
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern.toString());
+ Calendar formatCalendar = Calendar.getInstance();
+ formatCalendar.set(
+ timeValue.getYear(),
+ timeValue.getMonthOfYear() - 1,
+ timeValue.getDayOfMonth(),
+ timeValue.getHourOfDay(),
+ timeValue.getMinuteOfHour(),
+ timeValue.getSecondOfMinute()
+ );
+ result.append(simpleDateFormat.format(formatCalendar.getTime()));
+
+ variableMarkerSequence = false;
+ startOfSequence = i + 1;
+ }
+ } else {
+ if (c == ']') {
+ if (i == pictureString.length() - 1 || pictureString.charAt(i + 1) != ']') {
+ String message = String.format(
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
+ );
+ throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
+ } else {
+ String literalSubstring = pictureString.substring(startOfSequence, i + 1);
+ result.append(literalSubstring);
+ startOfSequence = i + 2;
+ i++;
+ }
+ } else if (c == '[') {
+ if (i == pictureString.length() - 1) {
+ String message = String.format(
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
+ );
+ throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
+ }
+
+ if (pictureString.charAt(i + 1) == '[') {
+ String literalSubstring = pictureString.substring(startOfSequence, i + 1);
+ result.append(literalSubstring);
+ startOfSequence = i + 2;
+ i++;
+ } else {
+ String literalSubstring = pictureString.substring(startOfSequence, i);
+ result.append(literalSubstring);
+ variableMarkerSequence = true;
+ startOfSequence = i + 1;
+ }
+ }
+ }
+ }
+
+ if (startOfSequence != pictureString.length()) {
+ if (variableMarkerSequence) {
+ String message = String.format(
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
+ );
+ throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
+ } else {
+ String literalSubstring = pictureString.substring(
+ startOfSequence,
+ pictureString.length()
+ );
+ result.append(literalSubstring);
+ }
+ }
+ return ItemFactory.getInstance().createStringItem(result.toString());
+ } catch (UnsupportedOperationException | IllegalArgumentException e) {
+ String message = String.format(
+ "\"%s\": not castable to type %s",
+ this.valueTimeItem.serialize(),
+ "time"
+ );
+ throw new CastException(message, getMetadata());
+ }
+ }
+
private String parsePresentationModifiers(String presentationModifiers) {
String presentationModifier1 = "";
@@ -234,123 +345,4 @@ private String parseVariableMarker(String variableMarker, StringBuilder result)
return pattern.toString();
}
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- try {
- if (this.valueTimeItem.isNull()) {
- return this.valueTimeItem;
- }
-
- DateTime timeValue = this.valueTimeItem.getDateTimeValue();
- String pictureString = this.pictureStringItem.getStringValue();
-
- // Start sequence
- int startOfSequence = 0;
- boolean variableMarkerSequence = false;
-
- StringBuilder result = new StringBuilder();
-
- // Iterate over picture
- for (int i = 0; i < pictureString.length(); i++) {
- char c = pictureString.charAt(i);
- if (variableMarkerSequence) {
- if (c == ']') {
- String variableMarker = pictureString.substring(startOfSequence, i);
- String pattern = parseVariableMarker(variableMarker, result);
-
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern.toString());
- Calendar formatCalendar = Calendar.getInstance();
- formatCalendar.set(
- timeValue.getYear(),
- timeValue.getMonthOfYear() - 1,
- timeValue.getDayOfMonth(),
- timeValue.getHourOfDay(),
- timeValue.getMinuteOfHour(),
- timeValue.getSecondOfMinute()
- );
- result.append(simpleDateFormat.format(formatCalendar.getTime()));
-
- variableMarkerSequence = false;
- startOfSequence = i + 1;
- }
- } else {
- if (c == ']') {
- if (i == pictureString.length() - 1 || pictureString.charAt(i + 1) != ']') {
- String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
- );
- throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
- } else {
- String literalSubstring = pictureString.substring(startOfSequence, i + 1);
- result.append(literalSubstring);
- startOfSequence = i + 2;
- i++;
- }
- } else if (c == '[') {
- if (i == pictureString.length() - 1) {
- String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
- );
- throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
- }
-
- if (pictureString.charAt(i + 1) == '[') {
- String literalSubstring = pictureString.substring(startOfSequence, i + 1);
- result.append(literalSubstring);
- startOfSequence = i + 2;
- i++;
- } else {
- String literalSubstring = pictureString.substring(startOfSequence, i);
- result.append(literalSubstring);
- variableMarkerSequence = true;
- startOfSequence = i + 1;
- }
- }
- }
- }
-
- if (startOfSequence != pictureString.length()) {
- if (variableMarkerSequence) {
- String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
- );
- throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
- } else {
- String literalSubstring = pictureString.substring(
- startOfSequence,
- pictureString.length()
- );
- result.append(literalSubstring);
- }
- }
- return ItemFactory.getInstance().createStringItem(result.toString());
- } catch (UnsupportedOperationException | IllegalArgumentException e) {
- String message = String.format(
- "\"%s\": not castable to type %s",
- this.valueTimeItem.serialize(),
- "time"
- );
- throw new CastException(message, getMetadata());
- }
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " format-time function",
- getMetadata()
- );
- }
-
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.valueTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.pictureStringItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.valueTimeItem != null && this.pictureStringItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateTimeToTimezone.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateTimeToTimezone.java
index c2c990a9d3..4a58055d7a 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateTimeToTimezone.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateTimeToTimezone.java
@@ -9,12 +9,13 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class AdjustDateTimeToTimezone extends LocalFunctionCallIterator {
+public class AdjustDateTimeToTimezone extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item timeItem = null;
@@ -29,71 +30,59 @@ public AdjustDateTimeToTimezone(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- if (this.timezone == null && this.children.size() == 1) {
- return ItemFactory.getInstance()
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.timeItem = this.children.get(0).materializeFirstItemOrNull(context);
+ if (this.children.size() == 2) {
+ this.timezone = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ }
+ if (this.timeItem == null) {
+ return null;
+ }
+ if (this.timezone == null && this.children.size() == 1) {
+ return ItemFactory.getInstance()
.createDateTimeItem(this.timeItem.getDateTimeValue().withZone(DateTimeZone.UTC), true);
- }
- if (this.timezone == null) {
- if (this.timeItem.hasTimeZone()) {
- return ItemFactory.getInstance()
+ }
+ if (this.timezone == null) {
+ if (this.timeItem.hasTimeZone()) {
+ return ItemFactory.getInstance()
.createDateTimeItem(
- this.timeItem.getDateTimeValue()
- .withZoneRetainFields(this.timeItem.getDateTimeValue().getZone()),
- false
+ this.timeItem.getDateTimeValue()
+ .withZoneRetainFields(this.timeItem.getDateTimeValue().getZone()),
+ false
);
- }
- return ItemFactory.getInstance()
+ }
+ return ItemFactory.getInstance()
.createDateTimeItem(this.timeItem.getDateTimeValue(), this.timeItem.hasTimeZone());
- } else {
- if (this.checkTimeZoneArgument()) {
- throw new InvalidTimezoneException("Invalid timezone", getMetadata());
- }
- if (this.timeItem.hasTimeZone()) {
- return ItemFactory.getInstance()
+ } else {
+ if (this.checkTimeZoneArgument()) {
+ throw new InvalidTimezoneException("Invalid timezone", getMetadata());
+ }
+ if (this.timeItem.hasTimeZone()) {
+ return ItemFactory.getInstance()
.createDateTimeItem(
- this.timeItem.getDateTimeValue()
- .withZone(
- DateTimeZone.forOffsetHoursMinutes(
- this.timezone.getDurationValue().getHours(),
- this.timezone.getDurationValue().getMinutes()
- )
- ),
- true
+ this.timeItem.getDateTimeValue()
+ .withZone(
+ DateTimeZone.forOffsetHoursMinutes(
+ this.timezone.getDurationValue().getHours(),
+ this.timezone.getDurationValue().getMinutes()
+ )
+ ),
+ true
);
- }
- return ItemFactory.getInstance()
+ }
+ return ItemFactory.getInstance()
.createDateTimeItem(
- this.timeItem.getDateTimeValue()
- .withZoneRetainFields(
- DateTimeZone.forOffsetHoursMinutes(
- this.timezone.getDurationValue().getHours(),
- this.timezone.getDurationValue().getMinutes()
- )
- ),
- true
+ this.timeItem.getDateTimeValue()
+ .withZoneRetainFields(
+ DateTimeZone.forOffsetHoursMinutes(
+ this.timezone.getDurationValue().getHours(),
+ this.timezone.getDurationValue().getMinutes()
+ )
+ ),
+ true
);
- }
-
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " adjust-dateTime-to-timezone function",
- getMetadata()
- );
- }
- }
-
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.timeItem = this.children.get(0).materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (this.children.size() == 2) {
- this.timezone = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
}
- this.hasNext = this.timeItem != null;
}
private boolean checkTimeZoneArgument() {
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateToTimezone.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateToTimezone.java
index ab6005dcfe..4b82561fb9 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateToTimezone.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateToTimezone.java
@@ -9,12 +9,13 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class AdjustDateToTimezone extends LocalFunctionCallIterator {
+public class AdjustDateToTimezone extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateItem = null;
@@ -29,71 +30,59 @@ public AdjustDateToTimezone(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- if (this.timezone == null && this.children.size() == 1) {
- return ItemFactory.getInstance()
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateItem = this.children.get(0).materializeFirstItemOrNull(context);
+ if (this.children.size() == 2) {
+ this.timezone = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ }
+ if (this.dateItem == null) {
+ return null;
+ }
+ if (this.timezone == null && this.children.size() == 1) {
+ return ItemFactory.getInstance()
.createDateItem(this.dateItem.getDateTimeValue().withZone(DateTimeZone.UTC), true);
- }
- if (this.timezone == null) {
- if (this.dateItem.hasTimeZone()) {
- return ItemFactory.getInstance()
+ }
+ if (this.timezone == null) {
+ if (this.dateItem.hasTimeZone()) {
+ return ItemFactory.getInstance()
.createDateItem(
- this.dateItem.getDateTimeValue()
- .withZoneRetainFields(this.dateItem.getDateTimeValue().getZone()),
- false
+ this.dateItem.getDateTimeValue()
+ .withZoneRetainFields(this.dateItem.getDateTimeValue().getZone()),
+ false
);
- }
- return ItemFactory.getInstance()
+ }
+ return ItemFactory.getInstance()
.createDateItem(this.dateItem.getDateTimeValue(), this.dateItem.hasTimeZone());
- } else {
- if (this.checkTimeZoneArgument()) {
- throw new InvalidTimezoneException("Invalid timezone", getMetadata());
- }
- if (this.dateItem.hasTimeZone()) {
- return ItemFactory.getInstance()
+ } else {
+ if (this.checkTimeZoneArgument()) {
+ throw new InvalidTimezoneException("Invalid timezone", getMetadata());
+ }
+ if (this.dateItem.hasTimeZone()) {
+ return ItemFactory.getInstance()
.createDateItem(
- this.dateItem.getDateTimeValue()
- .withZone(
- DateTimeZone.forOffsetHoursMinutes(
- this.timezone.getDurationValue().getHours(),
- this.timezone.getDurationValue().getMinutes()
- )
- ),
- true
+ this.dateItem.getDateTimeValue()
+ .withZone(
+ DateTimeZone.forOffsetHoursMinutes(
+ this.timezone.getDurationValue().getHours(),
+ this.timezone.getDurationValue().getMinutes()
+ )
+ ),
+ true
);
- }
- return ItemFactory.getInstance()
+ }
+ return ItemFactory.getInstance()
.createDateItem(
- this.dateItem.getDateTimeValue()
- .withZoneRetainFields(
- DateTimeZone.forOffsetHoursMinutes(
- this.timezone.getDurationValue().getHours(),
- this.timezone.getDurationValue().getMinutes()
- )
- ),
- true
+ this.dateItem.getDateTimeValue()
+ .withZoneRetainFields(
+ DateTimeZone.forOffsetHoursMinutes(
+ this.timezone.getDurationValue().getHours(),
+ this.timezone.getDurationValue().getMinutes()
+ )
+ ),
+ true
);
- }
-
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " adjust-date-to-timezone function",
- getMetadata()
- );
- }
- }
-
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateItem = this.children.get(0).materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (this.children.size() == 2) {
- this.timezone = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
}
- this.hasNext = this.dateItem != null;
}
private boolean checkTimeZoneArgument() {
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustTimeToTimezone.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustTimeToTimezone.java
index 37b00ef28a..fb4a0b20a7 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustTimeToTimezone.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustTimeToTimezone.java
@@ -9,12 +9,13 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class AdjustTimeToTimezone extends LocalFunctionCallIterator {
+public class AdjustTimeToTimezone extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item timeItem = null;
@@ -29,71 +30,59 @@ public AdjustTimeToTimezone(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- if (this.timezone == null && this.children.size() == 1) {
- return ItemFactory.getInstance()
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.timeItem = this.children.get(0).materializeFirstItemOrNull(context);
+ if (this.children.size() == 2) {
+ this.timezone = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ }
+ if (this.timeItem == null) {
+ return null;
+ }
+ if (this.timezone == null && this.children.size() == 1) {
+ return ItemFactory.getInstance()
.createTimeItem(this.timeItem.getDateTimeValue().withZone(DateTimeZone.UTC), true);
- }
- if (this.timezone == null) {
- if (this.timeItem.hasTimeZone()) {
- return ItemFactory.getInstance()
+ }
+ if (this.timezone == null) {
+ if (this.timeItem.hasTimeZone()) {
+ return ItemFactory.getInstance()
.createTimeItem(
- this.timeItem.getDateTimeValue()
- .withZoneRetainFields(this.timeItem.getDateTimeValue().getZone()),
- false
+ this.timeItem.getDateTimeValue()
+ .withZoneRetainFields(this.timeItem.getDateTimeValue().getZone()),
+ false
);
- }
- return ItemFactory.getInstance()
+ }
+ return ItemFactory.getInstance()
.createTimeItem(this.timeItem.getDateTimeValue(), this.timeItem.hasTimeZone());
- } else {
- if (this.checkTimeZoneArgument()) {
- throw new InvalidTimezoneException("Invalid timezone", getMetadata());
- }
- if (this.timeItem.hasTimeZone()) {
- return ItemFactory.getInstance()
+ } else {
+ if (this.checkTimeZoneArgument()) {
+ throw new InvalidTimezoneException("Invalid timezone", getMetadata());
+ }
+ if (this.timeItem.hasTimeZone()) {
+ return ItemFactory.getInstance()
.createTimeItem(
- this.timeItem.getDateTimeValue()
- .withZone(
- DateTimeZone.forOffsetHoursMinutes(
- this.timezone.getDurationValue().getHours(),
- this.timezone.getDurationValue().getMinutes()
- )
- ),
- true
+ this.timeItem.getDateTimeValue()
+ .withZone(
+ DateTimeZone.forOffsetHoursMinutes(
+ this.timezone.getDurationValue().getHours(),
+ this.timezone.getDurationValue().getMinutes()
+ )
+ ),
+ true
);
- }
- return ItemFactory.getInstance()
+ }
+ return ItemFactory.getInstance()
.createTimeItem(
- this.timeItem.getDateTimeValue()
- .withZoneRetainFields(
- DateTimeZone.forOffsetHoursMinutes(
- this.timezone.getDurationValue().getHours(),
- this.timezone.getDurationValue().getMinutes()
- )
- ),
- true
+ this.timeItem.getDateTimeValue()
+ .withZoneRetainFields(
+ DateTimeZone.forOffsetHoursMinutes(
+ this.timezone.getDurationValue().getHours(),
+ this.timezone.getDurationValue().getMinutes()
+ )
+ ),
+ true
);
- }
-
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " adjust-time-to-timezone function",
- getMetadata()
- );
- }
- }
-
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.timeItem = this.children.get(0).materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (this.children.size() == 2) {
- this.timezone = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
}
- this.hasNext = this.timeItem != null;
}
private boolean checkTimeZoneArgument() {
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateFunctionIterator.java
index 823f351447..41ce4303c1 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateFunctionIterator.java
@@ -6,12 +6,13 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class DayFromDateFunctionIterator extends LocalFunctionCallIterator {
+public class DayFromDateFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateItem = null;
@@ -25,22 +26,12 @@ public DayFromDateFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.dateItem.getDateTimeValue().getDayOfMonth());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " day-from-date function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateItem = this.children.get(0).materializeFirstItemOrNull(context);
+ if (this.dateItem == null) {
+ return null;
}
+ return ItemFactory.getInstance().createIntItem(this.dateItem.getDateTimeValue().getDayOfMonth());
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateItem = this.children.get(0).materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.dateItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateTimeFunctionIterator.java
index b4c51d135e..02f12a024c 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateTimeFunctionIterator.java
@@ -6,12 +6,13 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class DayFromDateTimeFunctionIterator extends LocalFunctionCallIterator {
+public class DayFromDateTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateTimeItem = null;
@@ -25,23 +26,13 @@ public DayFromDateTimeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.dateTimeItem.getDateTimeValue().getDayOfMonth());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " day-from-dateTime function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateTimeItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.dateTimeItem == null) {
+ return null;
}
+ return ItemFactory.getInstance().createIntItem(this.dateTimeItem.getDateTimeValue().getDayOfMonth());
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.dateTimeItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateFunctionIterator.java
index 956c0be941..257533de38 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateFunctionIterator.java
@@ -7,12 +7,13 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class TimezoneFromDateFunctionIterator extends LocalFunctionCallIterator {
+public class TimezoneFromDateFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateItem = null;
@@ -26,25 +27,14 @@ public TimezoneFromDateFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateItem = this.children.get(0).materializeFirstItemOrNull(context);
+ if (this.dateItem == null || !this.dateItem.hasTimeZone()) {
+ return null;
+ }
+ return ItemFactory.getInstance()
.createDayTimeDurationItem(
- new Period(this.dateItem.getDateTimeValue().getZone().toTimeZone().getRawOffset())
+ new Period(this.dateItem.getDateTimeValue().getZone().toTimeZone().getRawOffset())
);
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " timezone-from-date function",
- getMetadata()
- );
- }
- }
-
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateItem = this.children.get(0).materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.dateItem != null && this.dateItem.hasTimeZone();
}
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateTimeFunctionIterator.java
index 55d00eb8a3..ce6147c9ac 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateTimeFunctionIterator.java
@@ -7,12 +7,13 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class TimezoneFromDateTimeFunctionIterator extends LocalFunctionCallIterator {
+public class TimezoneFromDateTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateTimeItem = null;
@@ -26,26 +27,15 @@ public TimezoneFromDateTimeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateTimeItem = this.children.get(0).materializeFirstItemOrNull(context);
+ if (this.dateTimeItem == null || !this.dateTimeItem.hasTimeZone()) {
+ return null;
+ }
+ return ItemFactory.getInstance()
.createDayTimeDurationItem(
- new Period(this.dateTimeItem.getDateTimeValue().getZone().toTimeZone().getRawOffset())
+ new Period(this.dateTimeItem.getDateTimeValue().getZone().toTimeZone().getRawOffset())
);
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " timezone-from-dateTime function",
- getMetadata()
- );
- }
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.dateTimeItem != null && this.dateTimeItem.hasTimeZone();
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromTimeFunctionIterator.java
index 40a5f3d611..3f14eec9b3 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromTimeFunctionIterator.java
@@ -7,12 +7,13 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class TimezoneFromTimeFunctionIterator extends LocalFunctionCallIterator {
+public class TimezoneFromTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item timeItem = null;
@@ -26,25 +27,15 @@ public TimezoneFromTimeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.timeItem = this.children.get(0).materializeFirstItemOrNull(context);
+ if(this.timeItem == null || !this.timeItem.hasTimeZone()) {
+ return null;
+ }
+ return ItemFactory.getInstance()
.createDayTimeDurationItem(
- new Period(this.timeItem.getDateTimeValue().getZone().toTimeZone().getRawOffset())
+ new Period(this.timeItem.getDateTimeValue().getZone().toTimeZone().getRawOffset())
);
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " timezone-from-time function",
- getMetadata()
- );
- }
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.timeItem = this.children.get(0).materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.timeItem != null && this.timeItem.hasTimeZone();
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/DayTimeDurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/DayTimeDurationFunctionIterator.java
index 0c0c9160f2..f6b7099faa 100644
--- a/src/main/java/org/rumbledb/runtime/functions/durations/DayTimeDurationFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/durations/DayTimeDurationFunctionIterator.java
@@ -9,12 +9,13 @@
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.DurationItem;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import org.rumbledb.types.BuiltinTypesCatalogue;
import java.util.List;
-public class DayTimeDurationFunctionIterator extends LocalFunctionCallIterator {
+public class DayTimeDurationFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item durationStringItem = null;
@@ -28,37 +29,27 @@ public DayTimeDurationFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- try {
- Period period = DurationItem.getDurationFromString(
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.durationStringItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.durationStringItem == null) {
+ return null;
+ }
+ try {
+ Period period = DurationItem.getDurationFromString(
this.durationStringItem.getStringValue(),
BuiltinTypesCatalogue.dayTimeDurationItem
- );
- return ItemFactory.getInstance().createDayTimeDurationItem(period);
- } catch (UnsupportedOperationException | IllegalArgumentException e) {
- String message = String.format(
+ );
+ return ItemFactory.getInstance().createDayTimeDurationItem(period);
+ } catch (UnsupportedOperationException | IllegalArgumentException e) {
+ String message = String.format(
"\"%s\": value of type %s is not castable to type %s",
this.durationStringItem.serialize(),
"string",
"dayTimeDuration"
- );
- throw new CastException(message, getMetadata());
- }
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " dayTimeDuration function",
- getMetadata()
);
+ throw new CastException(message, getMetadata());
}
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.durationStringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.durationStringItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/components/DaysFromDurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/components/DaysFromDurationFunctionIterator.java
index 58924c0237..67199b0220 100644
--- a/src/main/java/org/rumbledb/runtime/functions/durations/components/DaysFromDurationFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/durations/components/DaysFromDurationFunctionIterator.java
@@ -6,12 +6,13 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class DaysFromDurationFunctionIterator extends LocalFunctionCallIterator {
+public class DaysFromDurationFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item durationItem = null;
@@ -25,23 +26,13 @@ public DaysFromDurationFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.durationItem.getDurationValue().getDays());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " days-from-duration function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.durationItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.durationItem == null) {
+ return null;
}
+ return ItemFactory.getInstance().createIntItem(this.durationItem.getDurationValue().getDays());
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.durationItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.durationItem != null;
- }
}
From 8a37b40b0e29e82a0aae48ef6f5a0c855ad4307c Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Mon, 14 Jun 2021 10:34:10 +0200
Subject: [PATCH 022/142] Spotless. AtMostOne. Time Functions, Parse, Null,
Codepoint, Length
---
.../functions/NullFunctionIterator.java | 8 ++-
.../arrays/ArraySizeFunctionIterator.java | 32 +++-------
.../datetime/CurrentDateFunctionIterator.java | 2 -
.../CurrentDateTimeFunctionIterator.java | 2 -
.../datetime/CurrentTimeFunctionIterator.java | 2 -
.../datetime/FormatDateFunctionIterator.java | 34 +++++------
.../FormatDateTimeFunctionIterator.java | 40 ++++++-------
.../datetime/FormatTimeFunctionIterator.java | 40 ++++++-------
.../components/AdjustDateTimeToTimezone.java | 58 +++++++++----------
.../components/AdjustDateToTimezone.java | 58 +++++++++----------
.../components/AdjustTimeToTimezone.java | 58 +++++++++----------
.../DayFromDateFunctionIterator.java | 2 -
.../DayFromDateTimeFunctionIterator.java | 4 +-
.../HoursFromDateTimeFunctionIterator.java | 27 +++------
.../HoursFromTimeFunctionIterator.java | 26 +++------
.../MinutesFromDateTimeFunctionIterator.java | 27 +++------
.../MinutesFromTimeFunctionIterator.java | 27 +++------
.../MonthFromDateFunctionIterator.java | 25 +++-----
.../MonthFromDateTimeFunctionIterator.java | 27 +++------
.../SecondsFromDateTimeFunctionIterator.java | 39 +++++--------
.../SecondsFromTimeFunctionIterator.java | 37 +++++-------
.../TimezoneFromDateFunctionIterator.java | 8 +--
.../TimezoneFromDateTimeFunctionIterator.java | 8 +--
.../TimezoneFromTimeFunctionIterator.java | 10 ++--
.../YearFromDateFunctionIterator.java | 25 +++-----
.../DayTimeDurationFunctionIterator.java | 16 +++--
.../YearMonthDurationFunctionIterator.java | 53 +++++++----------
.../DaysFromDurationFunctionIterator.java | 4 +-
.../HoursFromDurationFunctionIterator.java | 28 +++------
.../MinutesFromDurationFunctionIterator.java | 27 +++------
.../MonthsFromDurationFunctionIterator.java | 27 +++------
.../SecondsFromDurationFunctionIterator.java | 39 +++++--------
.../YearsFromDurationFunctionIterator.java | 27 +++------
.../io/ParseJsonFunctionIterator.java | 43 ++++++--------
.../CodepointEqualFunctionIterator.java | 31 +++-------
.../strings/EndsWithFunctionIterator.java | 45 ++++++--------
.../strings/StartsWithFunctionIterator.java | 45 ++++++--------
.../strings/StringLengthFunctionIterator.java | 30 ++++------
38 files changed, 393 insertions(+), 648 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/NullFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/NullFunctionIterator.java
index 519930ab19..064ce7beeb 100644
--- a/src/main/java/org/rumbledb/runtime/functions/NullFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/NullFunctionIterator.java
@@ -21,15 +21,16 @@
package org.rumbledb.runtime.functions;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class NullFunctionIterator extends LocalFunctionCallIterator {
+public class NullFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -43,7 +44,8 @@ protected NullFunctionIterator(
}
@Override
- public Item next() {
+ public Item materializeFirstItemOrNull(DynamicContext context) {
return ItemFactory.getInstance().createNullItem();
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/arrays/ArraySizeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/arrays/ArraySizeFunctionIterator.java
index 39f0643a24..25790c8c41 100644
--- a/src/main/java/org/rumbledb/runtime/functions/arrays/ArraySizeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/arrays/ArraySizeFunctionIterator.java
@@ -23,19 +23,17 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class ArraySizeFunctionIterator extends LocalFunctionCallIterator {
+public class ArraySizeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
- private RuntimeIterator arrayIterator;
public ArraySizeFunctionIterator(
List arguments,
@@ -46,26 +44,12 @@ public ArraySizeFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
-
- this.arrayIterator = this.children.get(0);
- this.arrayIterator.open(context);
- this.hasNext = this.arrayIterator.hasNext();
- this.arrayIterator.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
-
- Item array = this.arrayIterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- return ItemFactory.getInstance().createIntItem(array.getSize());
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item array = this.children.get(0).materializeFirstItemOrNull(context);
+ if (array == null) {
+ return null;
}
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + "SIZE function",
- getMetadata()
- );
+ return ItemFactory.getInstance().createIntItem(array.getSize());
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateFunctionIterator.java
index 3a97d2019b..41448e2769 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateFunctionIterator.java
@@ -4,12 +4,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateTimeFunctionIterator.java
index 902d2cd933..ae1f153389 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentDateTimeFunctionIterator.java
@@ -4,12 +4,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentTimeFunctionIterator.java
index b45a605eff..2ad9294f19 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/CurrentTimeFunctionIterator.java
@@ -4,12 +4,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateFunctionIterator.java
index 2839571d30..37e8b83107 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateFunctionIterator.java
@@ -7,13 +7,11 @@
import org.rumbledb.exceptions.ComponentSpecifierNotAvailableException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.IncorrectSyntaxFormatDateTimeException;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.exceptions.UnsupportedFeatureException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.text.SimpleDateFormat;
import java.util.Arrays;
@@ -37,9 +35,9 @@ public FormatDateFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
this.valueDateItem = this.children.get(0)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
this.pictureStringItem = this.children.get(1)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
if (this.valueDateItem == null || this.pictureStringItem == null) {
return null;
}
@@ -67,9 +65,9 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern.toString());
Calendar formatCalendar = Calendar.getInstance();
formatCalendar.set(
- dateValue.getYear(),
- dateValue.getMonthOfYear() - 1,
- dateValue.getDayOfMonth()
+ dateValue.getYear(),
+ dateValue.getMonthOfYear() - 1,
+ dateValue.getDayOfMonth()
);
result.append(simpleDateFormat.format(formatCalendar.getTime()));
@@ -80,8 +78,8 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
if (c == ']') {
if (i == pictureString.length() - 1 || pictureString.charAt(i + 1) != ']') {
String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
);
throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
} else {
@@ -93,8 +91,8 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
} else if (c == '[') {
if (i == pictureString.length() - 1) {
String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
);
throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
}
@@ -117,14 +115,14 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
if (startOfSequence != pictureString.length()) {
if (variableMarkerSequence) {
String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
);
throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
} else {
String literalSubstring = pictureString.substring(
- startOfSequence,
- pictureString.length()
+ startOfSequence,
+ pictureString.length()
);
result.append(literalSubstring);
}
@@ -132,9 +130,9 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
return ItemFactory.getInstance().createStringItem(result.toString());
} catch (UnsupportedOperationException | IllegalArgumentException e) {
String message = String.format(
- "\"%s\": not castable to type %s",
- this.valueDateItem.serialize(),
- "date"
+ "\"%s\": not castable to type %s",
+ this.valueDateItem.serialize(),
+ "date"
);
throw new CastException(message, getMetadata());
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateTimeFunctionIterator.java
index 93912bb288..d66bd9d8c8 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/FormatDateTimeFunctionIterator.java
@@ -7,13 +7,11 @@
import org.rumbledb.exceptions.ComponentSpecifierNotAvailableException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.IncorrectSyntaxFormatDateTimeException;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.exceptions.UnsupportedFeatureException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.text.SimpleDateFormat;
import java.util.Arrays;
@@ -37,9 +35,9 @@ public FormatDateTimeFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
this.valueDateTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
this.pictureStringItem = this.children.get(1)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
if (this.valueDateTimeItem == null || this.pictureStringItem == null) {
return null;
}
@@ -68,12 +66,12 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern.toString());
Calendar formatCalendar = Calendar.getInstance();
formatCalendar.set(
- dateTimeValue.getYear(),
- dateTimeValue.getMonthOfYear() - 1,
- dateTimeValue.getDayOfMonth(),
- dateTimeValue.getHourOfDay(),
- dateTimeValue.getMinuteOfHour(),
- dateTimeValue.getSecondOfMinute()
+ dateTimeValue.getYear(),
+ dateTimeValue.getMonthOfYear() - 1,
+ dateTimeValue.getDayOfMonth(),
+ dateTimeValue.getHourOfDay(),
+ dateTimeValue.getMinuteOfHour(),
+ dateTimeValue.getSecondOfMinute()
);
result.append(simpleDateFormat.format(formatCalendar.getTime()));
@@ -84,8 +82,8 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
if (c == ']') {
if (i == pictureString.length() - 1 || pictureString.charAt(i + 1) != ']') {
String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
);
throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
} else {
@@ -97,8 +95,8 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
} else if (c == '[') {
if (i == pictureString.length() - 1) {
String message = String.format(
- "\"%s\": incorrect syntax lala",
- this.pictureStringItem.serialize()
+ "\"%s\": incorrect syntax lala",
+ this.pictureStringItem.serialize()
);
throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
}
@@ -121,14 +119,14 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
if (startOfSequence != pictureString.length()) {
if (variableMarkerSequence) {
String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
);
throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
} else {
String literalSubstring = pictureString.substring(
- startOfSequence,
- pictureString.length()
+ startOfSequence,
+ pictureString.length()
);
result.append(literalSubstring);
}
@@ -136,9 +134,9 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
return ItemFactory.getInstance().createStringItem(result.toString());
} catch (UnsupportedOperationException | IllegalArgumentException e) {
String message = String.format(
- "\"%s\": not castable to type %s",
- this.valueDateTimeItem.serialize(),
- "dateTime"
+ "\"%s\": not castable to type %s",
+ this.valueDateTimeItem.serialize(),
+ "dateTime"
);
throw new CastException(message, getMetadata());
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/FormatTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/FormatTimeFunctionIterator.java
index 5091e92f32..9b68e53af7 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/FormatTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/FormatTimeFunctionIterator.java
@@ -7,13 +7,11 @@
import org.rumbledb.exceptions.ComponentSpecifierNotAvailableException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.IncorrectSyntaxFormatDateTimeException;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.exceptions.UnsupportedFeatureException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.text.SimpleDateFormat;
import java.util.Arrays;
@@ -37,9 +35,9 @@ public FormatTimeFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
this.valueTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
this.pictureStringItem = this.children.get(1)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
if (this.valueTimeItem == null || this.pictureStringItem == null) {
return null;
}
@@ -68,12 +66,12 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern.toString());
Calendar formatCalendar = Calendar.getInstance();
formatCalendar.set(
- timeValue.getYear(),
- timeValue.getMonthOfYear() - 1,
- timeValue.getDayOfMonth(),
- timeValue.getHourOfDay(),
- timeValue.getMinuteOfHour(),
- timeValue.getSecondOfMinute()
+ timeValue.getYear(),
+ timeValue.getMonthOfYear() - 1,
+ timeValue.getDayOfMonth(),
+ timeValue.getHourOfDay(),
+ timeValue.getMinuteOfHour(),
+ timeValue.getSecondOfMinute()
);
result.append(simpleDateFormat.format(formatCalendar.getTime()));
@@ -84,8 +82,8 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
if (c == ']') {
if (i == pictureString.length() - 1 || pictureString.charAt(i + 1) != ']') {
String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
);
throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
} else {
@@ -97,8 +95,8 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
} else if (c == '[') {
if (i == pictureString.length() - 1) {
String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
);
throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
}
@@ -121,14 +119,14 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
if (startOfSequence != pictureString.length()) {
if (variableMarkerSequence) {
String message = String.format(
- "\"%s\": incorrect syntax",
- this.pictureStringItem.serialize()
+ "\"%s\": incorrect syntax",
+ this.pictureStringItem.serialize()
);
throw new IncorrectSyntaxFormatDateTimeException(message, getMetadata());
} else {
String literalSubstring = pictureString.substring(
- startOfSequence,
- pictureString.length()
+ startOfSequence,
+ pictureString.length()
);
result.append(literalSubstring);
}
@@ -136,9 +134,9 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
return ItemFactory.getInstance().createStringItem(result.toString());
} catch (UnsupportedOperationException | IllegalArgumentException e) {
String message = String.format(
- "\"%s\": not castable to type %s",
- this.valueTimeItem.serialize(),
- "time"
+ "\"%s\": not castable to type %s",
+ this.valueTimeItem.serialize(),
+ "time"
);
throw new CastException(message, getMetadata());
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateTimeToTimezone.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateTimeToTimezone.java
index 4a58055d7a..e5abe9197a 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateTimeToTimezone.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateTimeToTimezone.java
@@ -6,12 +6,10 @@
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.InvalidTimezoneException;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
@@ -34,54 +32,54 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
this.timeItem = this.children.get(0).materializeFirstItemOrNull(context);
if (this.children.size() == 2) {
this.timezone = this.children.get(1)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
}
if (this.timeItem == null) {
return null;
}
if (this.timezone == null && this.children.size() == 1) {
return ItemFactory.getInstance()
- .createDateTimeItem(this.timeItem.getDateTimeValue().withZone(DateTimeZone.UTC), true);
+ .createDateTimeItem(this.timeItem.getDateTimeValue().withZone(DateTimeZone.UTC), true);
}
if (this.timezone == null) {
if (this.timeItem.hasTimeZone()) {
return ItemFactory.getInstance()
- .createDateTimeItem(
- this.timeItem.getDateTimeValue()
- .withZoneRetainFields(this.timeItem.getDateTimeValue().getZone()),
- false
- );
+ .createDateTimeItem(
+ this.timeItem.getDateTimeValue()
+ .withZoneRetainFields(this.timeItem.getDateTimeValue().getZone()),
+ false
+ );
}
return ItemFactory.getInstance()
- .createDateTimeItem(this.timeItem.getDateTimeValue(), this.timeItem.hasTimeZone());
+ .createDateTimeItem(this.timeItem.getDateTimeValue(), this.timeItem.hasTimeZone());
} else {
if (this.checkTimeZoneArgument()) {
throw new InvalidTimezoneException("Invalid timezone", getMetadata());
}
if (this.timeItem.hasTimeZone()) {
return ItemFactory.getInstance()
- .createDateTimeItem(
- this.timeItem.getDateTimeValue()
- .withZone(
- DateTimeZone.forOffsetHoursMinutes(
- this.timezone.getDurationValue().getHours(),
- this.timezone.getDurationValue().getMinutes()
- )
- ),
- true
- );
- }
- return ItemFactory.getInstance()
.createDateTimeItem(
- this.timeItem.getDateTimeValue()
- .withZoneRetainFields(
- DateTimeZone.forOffsetHoursMinutes(
- this.timezone.getDurationValue().getHours(),
- this.timezone.getDurationValue().getMinutes()
- )
- ),
- true
+ this.timeItem.getDateTimeValue()
+ .withZone(
+ DateTimeZone.forOffsetHoursMinutes(
+ this.timezone.getDurationValue().getHours(),
+ this.timezone.getDurationValue().getMinutes()
+ )
+ ),
+ true
);
+ }
+ return ItemFactory.getInstance()
+ .createDateTimeItem(
+ this.timeItem.getDateTimeValue()
+ .withZoneRetainFields(
+ DateTimeZone.forOffsetHoursMinutes(
+ this.timezone.getDurationValue().getHours(),
+ this.timezone.getDurationValue().getMinutes()
+ )
+ ),
+ true
+ );
}
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateToTimezone.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateToTimezone.java
index 4b82561fb9..8f87fabec3 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateToTimezone.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustDateToTimezone.java
@@ -6,12 +6,10 @@
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.InvalidTimezoneException;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
@@ -34,54 +32,54 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
this.dateItem = this.children.get(0).materializeFirstItemOrNull(context);
if (this.children.size() == 2) {
this.timezone = this.children.get(1)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
}
if (this.dateItem == null) {
return null;
}
if (this.timezone == null && this.children.size() == 1) {
return ItemFactory.getInstance()
- .createDateItem(this.dateItem.getDateTimeValue().withZone(DateTimeZone.UTC), true);
+ .createDateItem(this.dateItem.getDateTimeValue().withZone(DateTimeZone.UTC), true);
}
if (this.timezone == null) {
if (this.dateItem.hasTimeZone()) {
return ItemFactory.getInstance()
- .createDateItem(
- this.dateItem.getDateTimeValue()
- .withZoneRetainFields(this.dateItem.getDateTimeValue().getZone()),
- false
- );
+ .createDateItem(
+ this.dateItem.getDateTimeValue()
+ .withZoneRetainFields(this.dateItem.getDateTimeValue().getZone()),
+ false
+ );
}
return ItemFactory.getInstance()
- .createDateItem(this.dateItem.getDateTimeValue(), this.dateItem.hasTimeZone());
+ .createDateItem(this.dateItem.getDateTimeValue(), this.dateItem.hasTimeZone());
} else {
if (this.checkTimeZoneArgument()) {
throw new InvalidTimezoneException("Invalid timezone", getMetadata());
}
if (this.dateItem.hasTimeZone()) {
return ItemFactory.getInstance()
- .createDateItem(
- this.dateItem.getDateTimeValue()
- .withZone(
- DateTimeZone.forOffsetHoursMinutes(
- this.timezone.getDurationValue().getHours(),
- this.timezone.getDurationValue().getMinutes()
- )
- ),
- true
- );
- }
- return ItemFactory.getInstance()
.createDateItem(
- this.dateItem.getDateTimeValue()
- .withZoneRetainFields(
- DateTimeZone.forOffsetHoursMinutes(
- this.timezone.getDurationValue().getHours(),
- this.timezone.getDurationValue().getMinutes()
- )
- ),
- true
+ this.dateItem.getDateTimeValue()
+ .withZone(
+ DateTimeZone.forOffsetHoursMinutes(
+ this.timezone.getDurationValue().getHours(),
+ this.timezone.getDurationValue().getMinutes()
+ )
+ ),
+ true
);
+ }
+ return ItemFactory.getInstance()
+ .createDateItem(
+ this.dateItem.getDateTimeValue()
+ .withZoneRetainFields(
+ DateTimeZone.forOffsetHoursMinutes(
+ this.timezone.getDurationValue().getHours(),
+ this.timezone.getDurationValue().getMinutes()
+ )
+ ),
+ true
+ );
}
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustTimeToTimezone.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustTimeToTimezone.java
index fb4a0b20a7..c9af1b24ea 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustTimeToTimezone.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/AdjustTimeToTimezone.java
@@ -6,12 +6,10 @@
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.InvalidTimezoneException;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
@@ -34,54 +32,54 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
this.timeItem = this.children.get(0).materializeFirstItemOrNull(context);
if (this.children.size() == 2) {
this.timezone = this.children.get(1)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
}
if (this.timeItem == null) {
return null;
}
if (this.timezone == null && this.children.size() == 1) {
return ItemFactory.getInstance()
- .createTimeItem(this.timeItem.getDateTimeValue().withZone(DateTimeZone.UTC), true);
+ .createTimeItem(this.timeItem.getDateTimeValue().withZone(DateTimeZone.UTC), true);
}
if (this.timezone == null) {
if (this.timeItem.hasTimeZone()) {
return ItemFactory.getInstance()
- .createTimeItem(
- this.timeItem.getDateTimeValue()
- .withZoneRetainFields(this.timeItem.getDateTimeValue().getZone()),
- false
- );
+ .createTimeItem(
+ this.timeItem.getDateTimeValue()
+ .withZoneRetainFields(this.timeItem.getDateTimeValue().getZone()),
+ false
+ );
}
return ItemFactory.getInstance()
- .createTimeItem(this.timeItem.getDateTimeValue(), this.timeItem.hasTimeZone());
+ .createTimeItem(this.timeItem.getDateTimeValue(), this.timeItem.hasTimeZone());
} else {
if (this.checkTimeZoneArgument()) {
throw new InvalidTimezoneException("Invalid timezone", getMetadata());
}
if (this.timeItem.hasTimeZone()) {
return ItemFactory.getInstance()
- .createTimeItem(
- this.timeItem.getDateTimeValue()
- .withZone(
- DateTimeZone.forOffsetHoursMinutes(
- this.timezone.getDurationValue().getHours(),
- this.timezone.getDurationValue().getMinutes()
- )
- ),
- true
- );
- }
- return ItemFactory.getInstance()
.createTimeItem(
- this.timeItem.getDateTimeValue()
- .withZoneRetainFields(
- DateTimeZone.forOffsetHoursMinutes(
- this.timezone.getDurationValue().getHours(),
- this.timezone.getDurationValue().getMinutes()
- )
- ),
- true
+ this.timeItem.getDateTimeValue()
+ .withZone(
+ DateTimeZone.forOffsetHoursMinutes(
+ this.timezone.getDurationValue().getHours(),
+ this.timezone.getDurationValue().getMinutes()
+ )
+ ),
+ true
);
+ }
+ return ItemFactory.getInstance()
+ .createTimeItem(
+ this.timeItem.getDateTimeValue()
+ .withZoneRetainFields(
+ DateTimeZone.forOffsetHoursMinutes(
+ this.timezone.getDurationValue().getHours(),
+ this.timezone.getDurationValue().getMinutes()
+ )
+ ),
+ true
+ );
}
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateFunctionIterator.java
index 41ce4303c1..7b00705fcc 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateFunctionIterator.java
@@ -3,12 +3,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateTimeFunctionIterator.java
index 02f12a024c..e1c7dca542 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/DayFromDateTimeFunctionIterator.java
@@ -3,12 +3,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
@@ -28,7 +26,7 @@ public DayFromDateTimeFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
this.dateTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
if (this.dateTimeItem == null) {
return null;
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/HoursFromDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/HoursFromDateTimeFunctionIterator.java
index 322ea41433..dcef0581ce 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/HoursFromDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/HoursFromDateTimeFunctionIterator.java
@@ -3,15 +3,14 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class HoursFromDateTimeFunctionIterator extends LocalFunctionCallIterator {
+public class HoursFromDateTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateTimeItem = null;
@@ -25,23 +24,13 @@ public HoursFromDateTimeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.dateTimeItem.getDateTimeValue().getHourOfDay());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " hours-from-dateTime function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateTimeItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.dateTimeItem == null) {
+ return null;
}
+ return ItemFactory.getInstance().createIntItem(this.dateTimeItem.getDateTimeValue().getHourOfDay());
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.dateTimeItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/HoursFromTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/HoursFromTimeFunctionIterator.java
index 281ddf57d3..6c2ab11686 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/HoursFromTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/HoursFromTimeFunctionIterator.java
@@ -3,15 +3,14 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class HoursFromTimeFunctionIterator extends LocalFunctionCallIterator {
+public class HoursFromTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateItem = null;
@@ -25,22 +24,11 @@ public HoursFromTimeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.dateItem.getDateTimeValue().getHourOfDay());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " hours-from-time function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateItem = this.children.get(0).materializeFirstItemOrNull(context);
+ if (this.dateItem == null) {
+ return null;
}
- }
-
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateItem = this.children.get(0).materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.dateItem != null;
+ return ItemFactory.getInstance().createIntItem(this.dateItem.getDateTimeValue().getHourOfDay());
}
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/MinutesFromDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/MinutesFromDateTimeFunctionIterator.java
index 1e4a23bef2..fe23568a4a 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/MinutesFromDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/MinutesFromDateTimeFunctionIterator.java
@@ -3,15 +3,14 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class MinutesFromDateTimeFunctionIterator extends LocalFunctionCallIterator {
+public class MinutesFromDateTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateTimeItem = null;
@@ -25,23 +24,13 @@ public MinutesFromDateTimeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.dateTimeItem.getDateTimeValue().getMinuteOfHour());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " minutes-from-dateTime function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateTimeItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.dateTimeItem == null) {
+ return null;
}
+ return ItemFactory.getInstance().createIntItem(this.dateTimeItem.getDateTimeValue().getMinuteOfHour());
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.dateTimeItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/MinutesFromTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/MinutesFromTimeFunctionIterator.java
index 682be068a2..ff3e3016a2 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/MinutesFromTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/MinutesFromTimeFunctionIterator.java
@@ -3,15 +3,14 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class MinutesFromTimeFunctionIterator extends LocalFunctionCallIterator {
+public class MinutesFromTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateTimeItem = null;
@@ -25,23 +24,13 @@ public MinutesFromTimeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.dateTimeItem.getDateTimeValue().getMinuteOfHour());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " minutes-from-time function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateTimeItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.dateTimeItem == null) {
+ return null;
}
+ return ItemFactory.getInstance().createIntItem(this.dateTimeItem.getDateTimeValue().getMinuteOfHour());
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.dateTimeItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/MonthFromDateFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/MonthFromDateFunctionIterator.java
index 53636007a0..91c573575b 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/MonthFromDateFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/MonthFromDateFunctionIterator.java
@@ -3,15 +3,14 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class MonthFromDateFunctionIterator extends LocalFunctionCallIterator {
+public class MonthFromDateFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateItem = null;
@@ -25,22 +24,12 @@ public MonthFromDateFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.dateItem.getDateTimeValue().getMonthOfYear());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " month-from-date function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateItem = this.children.get(0).materializeFirstItemOrNull(context);
+ if (this.dateItem == null) {
+ return null;
}
+ return ItemFactory.getInstance().createIntItem(this.dateItem.getDateTimeValue().getMonthOfYear());
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateItem = this.children.get(0).materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.dateItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/MonthFromDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/MonthFromDateTimeFunctionIterator.java
index 0549046988..6766fa3f1a 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/MonthFromDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/MonthFromDateTimeFunctionIterator.java
@@ -3,15 +3,14 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class MonthFromDateTimeFunctionIterator extends LocalFunctionCallIterator {
+public class MonthFromDateTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateTimeItem = null;
@@ -25,23 +24,13 @@ public MonthFromDateTimeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.dateTimeItem.getDateTimeValue().getMonthOfYear());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " month-from-dateTime function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateTimeItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.dateTimeItem == null) {
+ return null;
}
+ return ItemFactory.getInstance().createIntItem(this.dateTimeItem.getDateTimeValue().getMonthOfYear());
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.dateTimeItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/SecondsFromDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/SecondsFromDateTimeFunctionIterator.java
index 9e559fa953..40c7baea00 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/SecondsFromDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/SecondsFromDateTimeFunctionIterator.java
@@ -3,16 +3,15 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.math.BigDecimal;
import java.util.List;
-public class SecondsFromDateTimeFunctionIterator extends LocalFunctionCallIterator {
+public class SecondsFromDateTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateTimeItem = null;
@@ -26,29 +25,19 @@ public SecondsFromDateTimeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
- .createDecimalItem(
- BigDecimal.valueOf(
- this.dateTimeItem.getDateTimeValue().getSecondOfMinute()
- + this.dateTimeItem.getDateTimeValue().getMillisOfSecond() * 1.0 / 1000
- )
- );
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " seconds-from-dateTime function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateTimeItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.dateTimeItem == null) {
+ return null;
}
+ return ItemFactory.getInstance()
+ .createDecimalItem(
+ BigDecimal.valueOf(
+ this.dateTimeItem.getDateTimeValue().getSecondOfMinute()
+ + this.dateTimeItem.getDateTimeValue().getMillisOfSecond() * 1.0 / 1000
+ )
+ );
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateTimeItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.dateTimeItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/SecondsFromTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/SecondsFromTimeFunctionIterator.java
index 455d0d5878..33e6e95e03 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/SecondsFromTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/SecondsFromTimeFunctionIterator.java
@@ -3,16 +3,15 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.math.BigDecimal;
import java.util.List;
-public class SecondsFromTimeFunctionIterator extends LocalFunctionCallIterator {
+public class SecondsFromTimeFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item timeItem = null;
@@ -26,28 +25,18 @@ public SecondsFromTimeFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
- .createDecimalItem(
- BigDecimal.valueOf(
- this.timeItem.getDateTimeValue().getSecondOfMinute()
- + this.timeItem.getDateTimeValue().getMillisOfSecond() * 1.0 / 1000
- )
- );
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " seconds-from-time function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.timeItem = this.children.get(0).materializeFirstItemOrNull(context);
+ if (this.timeItem == null) {
+ return null;
}
+ return ItemFactory.getInstance()
+ .createDecimalItem(
+ BigDecimal.valueOf(
+ this.timeItem.getDateTimeValue().getSecondOfMinute()
+ + this.timeItem.getDateTimeValue().getMillisOfSecond() * 1.0 / 1000
+ )
+ );
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.timeItem = this.children.get(0).materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.timeItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateFunctionIterator.java
index 257533de38..7499bd6d54 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateFunctionIterator.java
@@ -4,12 +4,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
@@ -33,8 +31,8 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
return null;
}
return ItemFactory.getInstance()
- .createDayTimeDurationItem(
- new Period(this.dateItem.getDateTimeValue().getZone().toTimeZone().getRawOffset())
- );
+ .createDayTimeDurationItem(
+ new Period(this.dateItem.getDateTimeValue().getZone().toTimeZone().getRawOffset())
+ );
}
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateTimeFunctionIterator.java
index ce6147c9ac..d157dddb3b 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromDateTimeFunctionIterator.java
@@ -4,12 +4,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
@@ -33,9 +31,9 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
return null;
}
return ItemFactory.getInstance()
- .createDayTimeDurationItem(
- new Period(this.dateTimeItem.getDateTimeValue().getZone().toTimeZone().getRawOffset())
- );
+ .createDayTimeDurationItem(
+ new Period(this.dateTimeItem.getDateTimeValue().getZone().toTimeZone().getRawOffset())
+ );
}
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromTimeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromTimeFunctionIterator.java
index 3f14eec9b3..9b08f5e1dc 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromTimeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/TimezoneFromTimeFunctionIterator.java
@@ -4,12 +4,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
@@ -29,13 +27,13 @@ public TimezoneFromTimeFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
this.timeItem = this.children.get(0).materializeFirstItemOrNull(context);
- if(this.timeItem == null || !this.timeItem.hasTimeZone()) {
+ if (this.timeItem == null || !this.timeItem.hasTimeZone()) {
return null;
}
return ItemFactory.getInstance()
- .createDayTimeDurationItem(
- new Period(this.timeItem.getDateTimeValue().getZone().toTimeZone().getRawOffset())
- );
+ .createDayTimeDurationItem(
+ new Period(this.timeItem.getDateTimeValue().getZone().toTimeZone().getRawOffset())
+ );
}
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateFunctionIterator.java
index 4f3437814b..4b52489032 100644
--- a/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/datetime/components/YearFromDateFunctionIterator.java
@@ -3,15 +3,14 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class YearFromDateFunctionIterator extends LocalFunctionCallIterator {
+public class YearFromDateFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item dateItem = null;
@@ -25,22 +24,12 @@ public YearFromDateFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.dateItem.getDateTimeValue().getYear());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " year-from-date function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.dateItem = this.children.get(0).materializeFirstItemOrNull(context);
+ if (this.dateItem == null) {
+ return null;
}
+ return ItemFactory.getInstance().createIntItem(this.dateItem.getDateTimeValue().getYear());
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.dateItem = this.children.get(0).materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.dateItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/DayTimeDurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/DayTimeDurationFunctionIterator.java
index f6b7099faa..739f004278 100644
--- a/src/main/java/org/rumbledb/runtime/functions/durations/DayTimeDurationFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/durations/DayTimeDurationFunctionIterator.java
@@ -5,13 +5,11 @@
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.CastException;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.DurationItem;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import org.rumbledb.types.BuiltinTypesCatalogue;
import java.util.List;
@@ -31,22 +29,22 @@ public DayTimeDurationFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
this.durationStringItem = this.children.get(0)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
if (this.durationStringItem == null) {
return null;
}
try {
Period period = DurationItem.getDurationFromString(
- this.durationStringItem.getStringValue(),
- BuiltinTypesCatalogue.dayTimeDurationItem
+ this.durationStringItem.getStringValue(),
+ BuiltinTypesCatalogue.dayTimeDurationItem
);
return ItemFactory.getInstance().createDayTimeDurationItem(period);
} catch (UnsupportedOperationException | IllegalArgumentException e) {
String message = String.format(
- "\"%s\": value of type %s is not castable to type %s",
- this.durationStringItem.serialize(),
- "string",
- "dayTimeDuration"
+ "\"%s\": value of type %s is not castable to type %s",
+ this.durationStringItem.serialize(),
+ "string",
+ "dayTimeDuration"
);
throw new CastException(message, getMetadata());
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/YearMonthDurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/YearMonthDurationFunctionIterator.java
index c2d4e6038f..c2d72e7cf9 100644
--- a/src/main/java/org/rumbledb/runtime/functions/durations/YearMonthDurationFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/durations/YearMonthDurationFunctionIterator.java
@@ -5,16 +5,15 @@
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.CastException;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.DurationItem;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import org.rumbledb.types.BuiltinTypesCatalogue;
import java.util.List;
-public class YearMonthDurationFunctionIterator extends LocalFunctionCallIterator {
+public class YearMonthDurationFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item durationStringItem = null;
@@ -28,37 +27,27 @@ public YearMonthDurationFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- try {
- Period period = DurationItem.getDurationFromString(
- this.durationStringItem.getStringValue(),
- BuiltinTypesCatalogue.yearMonthDurationItem
- );
- return ItemFactory.getInstance().createYearMonthDurationItem(period);
- } catch (UnsupportedOperationException | IllegalArgumentException e) {
- String message = String.format(
- "\"%s\": value of type %s is not castable to type %s",
- this.durationStringItem.serialize(),
- "string",
- "yearMonthDuration"
- );
- throw new CastException(message, getMetadata());
- }
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " yearMonthDuration function",
- getMetadata()
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.durationStringItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.durationStringItem == null) {
+ return null;
+ }
+ try {
+ Period period = DurationItem.getDurationFromString(
+ this.durationStringItem.getStringValue(),
+ BuiltinTypesCatalogue.yearMonthDurationItem
+ );
+ return ItemFactory.getInstance().createYearMonthDurationItem(period);
+ } catch (UnsupportedOperationException | IllegalArgumentException e) {
+ String message = String.format(
+ "\"%s\": value of type %s is not castable to type %s",
+ this.durationStringItem.serialize(),
+ "string",
+ "yearMonthDuration"
);
+ throw new CastException(message, getMetadata());
}
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.durationStringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.durationStringItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/components/DaysFromDurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/components/DaysFromDurationFunctionIterator.java
index 67199b0220..2554d8fbb1 100644
--- a/src/main/java/org/rumbledb/runtime/functions/durations/components/DaysFromDurationFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/durations/components/DaysFromDurationFunctionIterator.java
@@ -3,12 +3,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
@@ -28,7 +26,7 @@ public DaysFromDurationFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
this.durationItem = this.children.get(0)
- .materializeFirstItemOrNull(context);
+ .materializeFirstItemOrNull(context);
if (this.durationItem == null) {
return null;
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/components/HoursFromDurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/components/HoursFromDurationFunctionIterator.java
index 1b26437975..a406efeccc 100644
--- a/src/main/java/org/rumbledb/runtime/functions/durations/components/HoursFromDurationFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/durations/components/HoursFromDurationFunctionIterator.java
@@ -3,15 +3,14 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class HoursFromDurationFunctionIterator extends LocalFunctionCallIterator {
+public class HoursFromDurationFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item durationItem = null;
@@ -25,23 +24,14 @@ public HoursFromDurationFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.durationItem.getDurationValue().getHours());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " hours-from-duration function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.durationItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.durationItem == null) {
+ return null;
}
- }
+ return ItemFactory.getInstance().createIntItem(this.durationItem.getDurationValue().getHours());
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.durationItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.durationItem != null;
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/components/MinutesFromDurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/components/MinutesFromDurationFunctionIterator.java
index dc554ad29a..b0f092a4ba 100644
--- a/src/main/java/org/rumbledb/runtime/functions/durations/components/MinutesFromDurationFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/durations/components/MinutesFromDurationFunctionIterator.java
@@ -3,15 +3,14 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class MinutesFromDurationFunctionIterator extends LocalFunctionCallIterator {
+public class MinutesFromDurationFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item durationItem = null;
@@ -25,23 +24,13 @@ public MinutesFromDurationFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.durationItem.getDurationValue().getMinutes());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " minutes-from-duration function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.durationItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.durationItem == null) {
+ return null;
}
+ return ItemFactory.getInstance().createIntItem(this.durationItem.getDurationValue().getMinutes());
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.durationItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.durationItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/components/MonthsFromDurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/components/MonthsFromDurationFunctionIterator.java
index ba41e43a8b..a9cb393610 100644
--- a/src/main/java/org/rumbledb/runtime/functions/durations/components/MonthsFromDurationFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/durations/components/MonthsFromDurationFunctionIterator.java
@@ -3,15 +3,14 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class MonthsFromDurationFunctionIterator extends LocalFunctionCallIterator {
+public class MonthsFromDurationFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item durationItem = null;
@@ -25,23 +24,13 @@ public MonthsFromDurationFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.durationItem.getDurationValue().getMonths());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " months-from-duration function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.durationItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.durationItem == null) {
+ return null;
}
+ return ItemFactory.getInstance().createIntItem(this.durationItem.getDurationValue().getMonths());
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.durationItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.durationItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/components/SecondsFromDurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/components/SecondsFromDurationFunctionIterator.java
index 6a797e09db..9fe0e39000 100644
--- a/src/main/java/org/rumbledb/runtime/functions/durations/components/SecondsFromDurationFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/durations/components/SecondsFromDurationFunctionIterator.java
@@ -3,16 +3,15 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.math.BigDecimal;
import java.util.List;
-public class SecondsFromDurationFunctionIterator extends LocalFunctionCallIterator {
+public class SecondsFromDurationFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item durationItem = null;
@@ -26,29 +25,19 @@ public SecondsFromDurationFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance()
- .createDecimalItem(
- BigDecimal.valueOf(
- this.durationItem.getDurationValue().getSeconds()
- + this.durationItem.getDurationValue().getMillis() * 1.0 / 1000
- )
- );
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " seconds-from-duration function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.durationItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.durationItem == null) {
+ return null;
}
+ return ItemFactory.getInstance()
+ .createDecimalItem(
+ BigDecimal.valueOf(
+ this.durationItem.getDurationValue().getSeconds()
+ + this.durationItem.getDurationValue().getMillis() * 1.0 / 1000
+ )
+ );
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.durationItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.durationItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/components/YearsFromDurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/components/YearsFromDurationFunctionIterator.java
index 518f856527..5c1d6d7723 100644
--- a/src/main/java/org/rumbledb/runtime/functions/durations/components/YearsFromDurationFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/durations/components/YearsFromDurationFunctionIterator.java
@@ -3,15 +3,14 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class YearsFromDurationFunctionIterator extends LocalFunctionCallIterator {
+public class YearsFromDurationFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item durationItem = null;
@@ -25,23 +24,13 @@ public YearsFromDurationFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- return ItemFactory.getInstance().createIntItem(this.durationItem.getDurationValue().getYears());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " years-from-duration function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.durationItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.durationItem == null) {
+ return null;
}
+ return ItemFactory.getInstance().createIntItem(this.durationItem.getDurationValue().getYears());
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.durationItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.durationItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/io/ParseJsonFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/io/ParseJsonFunctionIterator.java
index 493fd71dc2..69206fb9bc 100644
--- a/src/main/java/org/rumbledb/runtime/functions/io/ParseJsonFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/io/ParseJsonFunctionIterator.java
@@ -29,13 +29,13 @@
import org.rumbledb.exceptions.RumbleException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.parsing.ItemParser;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.io.StringReader;
import java.util.List;
-public class ParseJsonFunctionIterator extends LocalFunctionCallIterator {
+public class ParseJsonFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -50,39 +50,30 @@ public ParseJsonFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
+ public Item materializeFirstItemOrNull(DynamicContext context) {
this.string = this.children.get(0).materializeFirstItemOrNull(context);
- this.hasNext = this.string != null;
+ if (this.string == null) {
+ return null;
+ }
+ try {
+ JsonReader object = new JsonReader(new StringReader(this.string.getStringValue()));
+ return ItemParser.getItemFromObject(object, getMetadata());
+ } catch (IteratorFlowException e) {
+ RumbleException ex = new IteratorFlowException(e.getJSONiqErrorMessage(), getMetadata());
+ ex.initCause(e);
+ throw ex;
+ }
}
@Override
public void reset(DynamicContext context) {
super.reset(context);
this.string = this.children.get(0).materializeFirstItemOrNull(context);
- this.hasNext = this.string != null;
- }
-
- @Override
- public void close() {
- super.close();
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- try {
- JsonReader object = new JsonReader(new StringReader(this.string.getStringValue()));
- return ItemParser.getItemFromObject(object, getMetadata());
- } catch (IteratorFlowException e) {
- RumbleException ex = new IteratorFlowException(e.getJSONiqErrorMessage(), getMetadata());
- ex.initCause(e);
- throw ex;
- }
+ if (this.string == null) {
+ return;
}
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " json-parse function", getMetadata());
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/CodepointEqualFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/CodepointEqualFunctionIterator.java
index 8ca0d37748..2dd47fc648 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/CodepointEqualFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/CodepointEqualFunctionIterator.java
@@ -23,15 +23,14 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class CodepointEqualFunctionIterator extends LocalFunctionCallIterator {
+public class CodepointEqualFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private String input1;
@@ -47,32 +46,20 @@ public CodepointEqualFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
+ public Item materializeFirstItemOrNull(DynamicContext context) {
this.input1 = null;
this.input2 = null;
- setNextResult();
+ setNextResult(context);
+ Item result = this.nextResult;
+ return result;
}
- @Override
- public Item next() {
- if (this.hasNext) {
- Item result = this.nextResult;
- setNextResult();
- return result;
- } else
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " codepoint-equal function",
- getMetadata()
- );
- }
-
- public void setNextResult() {
+ public void setNextResult(DynamicContext context) {
if (this.input1 == null || this.input2 == null) {
Item operandOneItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
+ .materializeFirstItemOrNull(context);
Item operandTwoItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
+ .materializeFirstItemOrNull(context);
if (operandOneItem == null || operandTwoItem == null) {
this.hasNext = false;
return;
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/EndsWithFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/EndsWithFunctionIterator.java
index be6a7c8ac1..049e50f314 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/EndsWithFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/EndsWithFunctionIterator.java
@@ -21,16 +21,16 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class EndsWithFunctionIterator extends LocalFunctionCallIterator {
+public class EndsWithFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -43,29 +43,22 @@ public EndsWithFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item substringItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (substringItem == null || substringItem.getStringValue().isEmpty()) {
- return ItemFactory.getInstance().createBooleanItem(true);
- }
- Item stringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (stringItem == null || stringItem.getStringValue().isEmpty()) {
- return ItemFactory.getInstance().createBooleanItem(false);
- }
- boolean result = stringItem.getStringValue()
- .endsWith(
- substringItem.getStringValue()
- );
- return ItemFactory.getInstance().createBooleanItem(result);
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " ends-with function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item substringItem = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ if (substringItem == null || substringItem.getStringValue().isEmpty()) {
+ return ItemFactory.getInstance().createBooleanItem(true);
+ }
+ Item stringItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (stringItem == null || stringItem.getStringValue().isEmpty()) {
+ return ItemFactory.getInstance().createBooleanItem(false);
}
+ boolean result = stringItem.getStringValue()
+ .endsWith(
+ substringItem.getStringValue()
+ );
+ return ItemFactory.getInstance().createBooleanItem(result);
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/StartsWithFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/StartsWithFunctionIterator.java
index 5154d80dff..c79eb47192 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/StartsWithFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/StartsWithFunctionIterator.java
@@ -21,16 +21,16 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class StartsWithFunctionIterator extends LocalFunctionCallIterator {
+public class StartsWithFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -43,29 +43,22 @@ public StartsWithFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item substringItem = this.children.get(1)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (substringItem == null || substringItem.getStringValue().isEmpty()) {
- return ItemFactory.getInstance().createBooleanItem(true);
- }
- Item stringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- if (stringItem == null || stringItem.getStringValue().isEmpty()) {
- return ItemFactory.getInstance().createBooleanItem(false);
- }
- boolean result = stringItem.getStringValue()
- .startsWith(
- substringItem.getStringValue()
- );
- return ItemFactory.getInstance().createBooleanItem(result);
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " starts-with function",
- getMetadata()
- );
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item substringItem = this.children.get(1)
+ .materializeFirstItemOrNull(context);
+ if (substringItem == null || substringItem.getStringValue().isEmpty()) {
+ return ItemFactory.getInstance().createBooleanItem(true);
+ }
+ Item stringItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (stringItem == null || stringItem.getStringValue().isEmpty()) {
+ return ItemFactory.getInstance().createBooleanItem(false);
}
+ boolean result = stringItem.getStringValue()
+ .startsWith(
+ substringItem.getStringValue()
+ );
+ return ItemFactory.getInstance().createBooleanItem(result);
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/StringLengthFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/StringLengthFunctionIterator.java
index 5a697cf40a..36023d8448 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/StringLengthFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/StringLengthFunctionIterator.java
@@ -21,16 +21,16 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class StringLengthFunctionIterator extends LocalFunctionCallIterator {
+public class StringLengthFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -43,23 +43,15 @@ public StringLengthFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item stringItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
- Item stringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
-
- if (stringItem == null) {
- return ItemFactory.getInstance().createIntItem(0);
- }
-
- return ItemFactory.getInstance().createIntItem(stringItem.getStringValue().length());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " string-length function",
- getMetadata()
- );
+ if (stringItem == null) {
+ return ItemFactory.getInstance().createIntItem(0);
}
+
+ return ItemFactory.getInstance().createIntItem(stringItem.getStringValue().length());
}
+
}
From af25858bcba83f32786d99b4af69ce0d5a3f4949 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Mon, 14 Jun 2021 10:43:48 +0200
Subject: [PATCH 023/142] AtMostOne. Boolean, Concat
---
.../booleans/BooleanFunctionIterator.java | 23 ++++++------
.../strings/ConcatFunctionIterator.java | 35 ++++++++-----------
2 files changed, 24 insertions(+), 34 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/booleans/BooleanFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/booleans/BooleanFunctionIterator.java
index 3296a0c167..f9f68a285b 100644
--- a/src/main/java/org/rumbledb/runtime/functions/booleans/BooleanFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/booleans/BooleanFunctionIterator.java
@@ -21,16 +21,16 @@
package org.rumbledb.runtime.functions.booleans;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class BooleanFunctionIterator extends LocalFunctionCallIterator {
+public class BooleanFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -43,15 +43,12 @@ public BooleanFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- RuntimeIterator iterator = this.children.get(0);
- boolean effectiveBooleanValue = iterator.getEffectiveBooleanValue(
- this.currentDynamicContextForLocalExecution
- );
- return ItemFactory.getInstance().createBooleanItem(effectiveBooleanValue);
- }
- throw new IteratorFlowException(RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " boolean function", getMetadata());
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ RuntimeIterator iterator = this.children.get(0);
+ boolean effectiveBooleanValue = iterator.getEffectiveBooleanValue(
+ context
+ );
+ return ItemFactory.getInstance().createBooleanItem(effectiveBooleanValue);
}
+
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/ConcatFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/ConcatFunctionIterator.java
index f0e7436dea..eee61095e0 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/ConcatFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/ConcatFunctionIterator.java
@@ -21,16 +21,16 @@
package org.rumbledb.runtime.functions.strings;
import org.rumbledb.api.Item;
+import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
-public class ConcatFunctionIterator extends LocalFunctionCallIterator {
+public class ConcatFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -43,26 +43,19 @@ public ConcatFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- StringBuilder builder = new StringBuilder();
- for (RuntimeIterator iterator : this.children) {
- Item item = iterator.materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- // if not empty sequence
- if (item != null) {
- String stringValue = item.serialize();
- if (!stringValue.equals("")) {
- builder.append(stringValue);
- }
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ StringBuilder builder = new StringBuilder();
+ for (RuntimeIterator iterator : this.children) {
+ Item item = iterator.materializeFirstItemOrNull(context);
+ // if not empty sequence
+ if (item != null) {
+ String stringValue = item.serialize();
+ if (!stringValue.equals("")) {
+ builder.append(stringValue);
}
}
- this.hasNext = false;
- return ItemFactory.getInstance().createStringItem(builder.toString());
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " substring function",
- getMetadata()
- );
}
+ return ItemFactory.getInstance().createStringItem(builder.toString());
}
+
}
From 242cbc5f324c047d911fd545a46e1aad60742513 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Tue, 15 Jun 2021 10:38:27 +0200
Subject: [PATCH 024/142] AtMostOne. Extra functions not in excel
---
.../context/LastFunctionIterator.java | 24 ++-----
.../context/PositionFunctionIterator.java | 24 ++-----
.../durations/DurationFunctionIterator.java | 53 ++++++--------
.../value/DeepEqualFunctionIterator.java | 71 ++++++++-----------
4 files changed, 64 insertions(+), 108 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/context/LastFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/context/LastFunctionIterator.java
index f732f32544..7094815ef0 100644
--- a/src/main/java/org/rumbledb/runtime/functions/context/LastFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/context/LastFunctionIterator.java
@@ -26,14 +26,14 @@
import org.rumbledb.exceptions.AbsentPartOfDynamicContextException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.expressions.ExecutionMode;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
-public class LastFunctionIterator extends LocalFunctionCallIterator {
+public class LastFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -47,22 +47,12 @@ public LastFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.hasNext = true;
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item result = this.currentDynamicContextForLocalExecution.getVariableValues().getLast();
- if (result == null) {
- throw new AbsentPartOfDynamicContextException("Context undefined (last) ", getMetadata());
- }
- return result;
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item result = context.getVariableValues().getLast();
+ if (result == null) {
+ throw new AbsentPartOfDynamicContextException("Context undefined (last) ", getMetadata());
}
- return null;
+ return result;
}
public Map getVariableDependencies() {
diff --git a/src/main/java/org/rumbledb/runtime/functions/context/PositionFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/context/PositionFunctionIterator.java
index 9a34f09a04..db9dba61ba 100644
--- a/src/main/java/org/rumbledb/runtime/functions/context/PositionFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/context/PositionFunctionIterator.java
@@ -26,14 +26,14 @@
import org.rumbledb.exceptions.AbsentPartOfDynamicContextException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.expressions.ExecutionMode;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
-public class PositionFunctionIterator extends LocalFunctionCallIterator {
+public class PositionFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -47,22 +47,12 @@ public PositionFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- this.hasNext = true;
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- Item result = this.currentDynamicContextForLocalExecution.getVariableValues().getPosition();
- if (result == null) {
- throw new AbsentPartOfDynamicContextException("Context undefined (position) ", getMetadata());
- }
- return result;
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ Item result = context.getVariableValues().getPosition();
+ if (result == null) {
+ throw new AbsentPartOfDynamicContextException("Context undefined (position) ", getMetadata());
}
- return null;
+ return result;
}
public Map getVariableDependencies() {
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/DurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/DurationFunctionIterator.java
index 4bc7440c72..a652a2d424 100644
--- a/src/main/java/org/rumbledb/runtime/functions/durations/DurationFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/durations/DurationFunctionIterator.java
@@ -5,16 +5,15 @@
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.CastException;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.DurationItem;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import org.rumbledb.types.BuiltinTypesCatalogue;
import java.util.List;
-public class DurationFunctionIterator extends LocalFunctionCallIterator {
+public class DurationFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
private Item durationStringItem = null;
@@ -28,37 +27,27 @@ public DurationFunctionIterator(
}
@Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
- try {
- Period period = DurationItem.getDurationFromString(
- this.durationStringItem.getStringValue(),
- BuiltinTypesCatalogue.durationItem
- );
- return ItemFactory.getInstance().createDurationItem(period);
- } catch (UnsupportedOperationException | IllegalArgumentException e) {
- String message = String.format(
- "\"%s\": value of type %s is not castable to type %s",
- this.durationStringItem.serialize(),
- "string",
- "duration"
- );
- throw new CastException(message, getMetadata());
- }
- } else {
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " duration function",
- getMetadata()
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ this.durationStringItem = this.children.get(0)
+ .materializeFirstItemOrNull(context);
+ if (this.durationStringItem == null) {
+ return null;
+ }
+ try {
+ Period period = DurationItem.getDurationFromString(
+ this.durationStringItem.getStringValue(),
+ BuiltinTypesCatalogue.durationItem
+ );
+ return ItemFactory.getInstance().createDurationItem(period);
+ } catch (UnsupportedOperationException | IllegalArgumentException e) {
+ String message = String.format(
+ "\"%s\": value of type %s is not castable to type %s",
+ this.durationStringItem.serialize(),
+ "string",
+ "duration"
);
+ throw new CastException(message, getMetadata());
}
}
- @Override
- public void open(DynamicContext context) {
- super.open(context);
- this.durationStringItem = this.children.get(0)
- .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution);
- this.hasNext = this.durationStringItem != null;
- }
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java
index 301c011db0..2e444a3614 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java
@@ -27,17 +27,16 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
import scala.Tuple2;
import java.util.Iterator;
import java.util.List;
-public class DeepEqualFunctionIterator extends LocalFunctionCallIterator {
+public class DeepEqualFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
@@ -52,48 +51,36 @@ public DeepEqualFunctionIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- }
-
- @Override
- public Item next() {
- if (this.hasNext) {
- this.hasNext = false;
-
- RuntimeIterator sequenceIterator1 = this.children.get(0);
- RuntimeIterator sequenceIterator2 = this.children.get(1);
-
- if (sequenceIterator1.isRDDOrDataFrame() && sequenceIterator2.isRDDOrDataFrame()) {
- JavaRDD
- rdd1 = sequenceIterator1.getRDD(this.currentDynamicContextForLocalExecution);
- JavaRDD
- rdd2 = sequenceIterator2.getRDD(this.currentDynamicContextForLocalExecution);
- if (rdd1.partitions().size() == rdd2.partitions().size()) {
- FlatMapFunction2, Iterator
- , Boolean> filter =
- new SameElementsAndLengthClosure();
- JavaRDD differences = rdd1.zipPartitions(rdd2, filter);
- return ItemFactory.getInstance().createBooleanItem(differences.isEmpty());
- } else {
- JavaPairRDD rdd1Zipped = rdd1.zipWithIndex().mapToPair(Tuple2::swap);
- JavaPairRDD rdd2Zipped = rdd2.zipWithIndex().mapToPair(Tuple2::swap);
- JavaPairRDD, Optional
- >> rddJoined = rdd1Zipped.fullOuterJoin(
- rdd2Zipped
- );
- JavaPairRDD, Optional
- >> rddFiltered = rddJoined.filter(
- tuple -> !tuple._2()._1().equals(tuple._2()._2())
- );
- return ItemFactory.getInstance().createBooleanItem(rddFiltered.isEmpty());
- }
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ RuntimeIterator sequenceIterator1 = this.children.get(0);
+ RuntimeIterator sequenceIterator2 = this.children.get(1);
+
+ if (sequenceIterator1.isRDDOrDataFrame() && sequenceIterator2.isRDDOrDataFrame()) {
+ JavaRDD
- rdd1 = sequenceIterator1.getRDD(context);
+ JavaRDD
- rdd2 = sequenceIterator2.getRDD(context);
+ if (rdd1.partitions().size() == rdd2.partitions().size()) {
+ FlatMapFunction2, Iterator
- , Boolean> filter =
+ new SameElementsAndLengthClosure();
+ JavaRDD differences = rdd1.zipPartitions(rdd2, filter);
+ return ItemFactory.getInstance().createBooleanItem(differences.isEmpty());
+ } else {
+ JavaPairRDD rdd1Zipped = rdd1.zipWithIndex().mapToPair(Tuple2::swap);
+ JavaPairRDD rdd2Zipped = rdd2.zipWithIndex().mapToPair(Tuple2::swap);
+ JavaPairRDD, Optional
- >> rddJoined = rdd1Zipped.fullOuterJoin(
+ rdd2Zipped
+ );
+ JavaPairRDD, Optional
- >> rddFiltered = rddJoined.filter(
+ tuple -> !tuple._2()._1().equals(tuple._2()._2())
+ );
+ return ItemFactory.getInstance().createBooleanItem(rddFiltered.isEmpty());
}
- List
- items1 = sequenceIterator1.materialize(this.currentDynamicContextForLocalExecution);
- List
- items2 = sequenceIterator2.materialize(this.currentDynamicContextForLocalExecution);
-
- boolean res = checkDeepEqual(items1, items2);
- return ItemFactory.getInstance().createBooleanItem(res);
- } else {
- throw new IteratorFlowException(FLOW_EXCEPTION_MESSAGE + "deep-equal function", getMetadata());
}
- }
+ List
- items1 = sequenceIterator1.materialize(context);
+ List
- items2 = sequenceIterator2.materialize(context);
+ boolean res = checkDeepEqual(items1, items2);
+ return ItemFactory.getInstance().createBooleanItem(res);
+ }
public boolean checkDeepEqual(List
- items1, List
- items2) {
if (items1.size() != items2.size()) {
From 01005f1fa08689edea247e8139b834f027e3f5c7 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Fri, 18 Jun 2021 17:36:47 +0200
Subject: [PATCH 025/142] Intersection from Hybrid to AtMostOne
---
.../context/BuiltinFunctionCatalogue.java | 4 +-
.../ObjectIntersectFunctionIterator.java | 99 +++++++------------
2 files changed, 38 insertions(+), 65 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index ebfa8dfb33..70ea352915 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -2135,9 +2135,9 @@ private static BuiltinFunction createBuiltinFunction(
"intersect"
),
"item*",
- "object+",
+ "object",
ObjectIntersectFunctionIterator.class,
- BuiltinFunction.BuiltinFunctionExecutionMode.INHERIT_FROM_FIRST_ARGUMENT
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
/**
* function that projects objects by filtering their pairs and leaves non-objects intact
diff --git a/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
index 7897cc061c..207383de37 100644
--- a/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
@@ -27,10 +27,9 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
-import org.rumbledb.runtime.HybridRuntimeIterator;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import sparksoniq.spark.SparkSessionManager;
@@ -41,91 +40,65 @@
import java.util.LinkedHashMap;
import java.util.List;
-public class ObjectIntersectFunctionIterator extends HybridRuntimeIterator {
+public class ObjectIntersectFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
/**
*
*/
private static final long serialVersionUID = 1L;
- private RuntimeIterator iterator;
public ObjectIntersectFunctionIterator(
- List arguments,
+ List children,
ExecutionMode executionMode,
ExceptionMetadata iteratorMetadata
) {
- super(arguments, executionMode, iteratorMetadata);
- this.iterator = arguments.get(0);
+ super(children, executionMode, iteratorMetadata);
}
@Override
- public Item nextLocal() {
- if (this.hasNext) {
- List
- items = this.iterator.materialize(this.currentDynamicContextForLocalExecution);
- LinkedHashMap> keyValuePairs = new LinkedHashMap<>();
- boolean firstItem = true;
- for (Item item : items) {
- // ignore non-object items
- if (item.isObject()) {
- if (firstItem) {
- // add all key-value pairs of the first item
- for (String key : item.getKeys()) {
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ List
- items = this.children.get(0).materialize(context);
+ LinkedHashMap> keyValuePairs = new LinkedHashMap<>();
+ boolean firstItem = true;
+ for (Item item : items) {
+ // ignore non-object items
+ if (item.isObject()) {
+ if (firstItem) {
+ // add all key-value pairs of the first item
+ for (String key : item.getKeys()) {
+ Item value = item.getItemByKey(key);
+ ArrayList
- valueList = new ArrayList<>();
+ valueList.add(value);
+ keyValuePairs.put(key, valueList);
+ }
+ firstItem = false;
+ } else {
+ // iterate over existing keys in the map of results
+ Iterator keyIterator = keyValuePairs.keySet().iterator();
+ while (keyIterator.hasNext()) {
+ String key = keyIterator.next();
+ // if the new item doesn't contain the same keys
+ if (!item.getKeys().contains(key)) {
+ // remove the key from the map
+ keyIterator.remove();
+ } else {
+ // add the matching key's value to the list
Item value = item.getItemByKey(key);
- ArrayList
- valueList = new ArrayList<>();
- valueList.add(value);
- keyValuePairs.put(key, valueList);
- }
- firstItem = false;
- } else {
- // iterate over existing keys in the map of results
- Iterator keyIterator = keyValuePairs.keySet().iterator();
- while (keyIterator.hasNext()) {
- String key = keyIterator.next();
- // if the new item doesn't contain the same keys
- if (!item.getKeys().contains(key)) {
- // remove the key from the map
- keyIterator.remove();
- } else {
- // add the matching key's value to the list
- Item value = item.getItemByKey(key);
- keyValuePairs.get(key).add(value);
- }
+ keyValuePairs.get(key).add(value);
}
}
}
}
-
- Item result = ItemFactory.getInstance().createObjectItem(keyValuePairs);
-
- this.hasNext = false;
- return result;
}
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " INTERSECT function",
- getMetadata()
- );
- }
- @Override
- protected void openLocal() {
- }
+ Item result = ItemFactory.getInstance().createObjectItem(keyValuePairs);
- @Override
- protected void closeLocal() {
+ return result;
}
- @Override
- protected void resetLocal() {
- }
-
- @Override
- protected boolean hasNextLocal() {
- return this.hasNext;
- }
-
- @Override
+ // @Override
protected JavaRDD
- getRDDAux(DynamicContext context) {
// Enclose object values into arrays.
- JavaRDD
- childRDD = this.iterator.getRDD(context);
+ JavaRDD
- childRDD = this.children.get(0).getRDD(context);
Function
- mapTransformation = new ObjectIntersectMapClosure();
JavaRDD
- mapResult = childRDD.map(mapTransformation);
From 00014981b2069ae8d7da243b77e5543819d7e1aa Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Fri, 18 Jun 2021 17:36:47 +0200
Subject: [PATCH 026/142] Revert "Intersection from Hybrid to AtMostOne"
This reverts commit 01005f1fa08689edea247e8139b834f027e3f5c7.
---
.../context/BuiltinFunctionCatalogue.java | 4 +-
.../ObjectIntersectFunctionIterator.java | 99 ++++++++++++-------
2 files changed, 65 insertions(+), 38 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index 70ea352915..ebfa8dfb33 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -2135,9 +2135,9 @@ private static BuiltinFunction createBuiltinFunction(
"intersect"
),
"item*",
- "object",
+ "object+",
ObjectIntersectFunctionIterator.class,
- BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ BuiltinFunction.BuiltinFunctionExecutionMode.INHERIT_FROM_FIRST_ARGUMENT
);
/**
* function that projects objects by filtering their pairs and leaves non-objects intact
diff --git a/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
index 207383de37..7897cc061c 100644
--- a/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
@@ -27,9 +27,10 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
+import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
-import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
+import org.rumbledb.runtime.HybridRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import sparksoniq.spark.SparkSessionManager;
@@ -40,65 +41,91 @@
import java.util.LinkedHashMap;
import java.util.List;
-public class ObjectIntersectFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
+public class ObjectIntersectFunctionIterator extends HybridRuntimeIterator {
/**
*
*/
private static final long serialVersionUID = 1L;
+ private RuntimeIterator iterator;
public ObjectIntersectFunctionIterator(
- List children,
+ List arguments,
ExecutionMode executionMode,
ExceptionMetadata iteratorMetadata
) {
- super(children, executionMode, iteratorMetadata);
+ super(arguments, executionMode, iteratorMetadata);
+ this.iterator = arguments.get(0);
}
@Override
- public Item materializeFirstItemOrNull(DynamicContext context) {
- List
- items = this.children.get(0).materialize(context);
- LinkedHashMap> keyValuePairs = new LinkedHashMap<>();
- boolean firstItem = true;
- for (Item item : items) {
- // ignore non-object items
- if (item.isObject()) {
- if (firstItem) {
- // add all key-value pairs of the first item
- for (String key : item.getKeys()) {
- Item value = item.getItemByKey(key);
- ArrayList
- valueList = new ArrayList<>();
- valueList.add(value);
- keyValuePairs.put(key, valueList);
- }
- firstItem = false;
- } else {
- // iterate over existing keys in the map of results
- Iterator keyIterator = keyValuePairs.keySet().iterator();
- while (keyIterator.hasNext()) {
- String key = keyIterator.next();
- // if the new item doesn't contain the same keys
- if (!item.getKeys().contains(key)) {
- // remove the key from the map
- keyIterator.remove();
- } else {
- // add the matching key's value to the list
+ public Item nextLocal() {
+ if (this.hasNext) {
+ List
- items = this.iterator.materialize(this.currentDynamicContextForLocalExecution);
+ LinkedHashMap> keyValuePairs = new LinkedHashMap<>();
+ boolean firstItem = true;
+ for (Item item : items) {
+ // ignore non-object items
+ if (item.isObject()) {
+ if (firstItem) {
+ // add all key-value pairs of the first item
+ for (String key : item.getKeys()) {
Item value = item.getItemByKey(key);
- keyValuePairs.get(key).add(value);
+ ArrayList
- valueList = new ArrayList<>();
+ valueList.add(value);
+ keyValuePairs.put(key, valueList);
+ }
+ firstItem = false;
+ } else {
+ // iterate over existing keys in the map of results
+ Iterator keyIterator = keyValuePairs.keySet().iterator();
+ while (keyIterator.hasNext()) {
+ String key = keyIterator.next();
+ // if the new item doesn't contain the same keys
+ if (!item.getKeys().contains(key)) {
+ // remove the key from the map
+ keyIterator.remove();
+ } else {
+ // add the matching key's value to the list
+ Item value = item.getItemByKey(key);
+ keyValuePairs.get(key).add(value);
+ }
}
}
}
}
+
+ Item result = ItemFactory.getInstance().createObjectItem(keyValuePairs);
+
+ this.hasNext = false;
+ return result;
}
+ throw new IteratorFlowException(
+ RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " INTERSECT function",
+ getMetadata()
+ );
+ }
- Item result = ItemFactory.getInstance().createObjectItem(keyValuePairs);
+ @Override
+ protected void openLocal() {
+ }
- return result;
+ @Override
+ protected void closeLocal() {
}
- // @Override
+ @Override
+ protected void resetLocal() {
+ }
+
+ @Override
+ protected boolean hasNextLocal() {
+ return this.hasNext;
+ }
+
+ @Override
protected JavaRDD
- getRDDAux(DynamicContext context) {
// Enclose object values into arrays.
- JavaRDD
- childRDD = this.children.get(0).getRDD(context);
+ JavaRDD
- childRDD = this.iterator.getRDD(context);
Function
- mapTransformation = new ObjectIntersectMapClosure();
JavaRDD
- mapResult = childRDD.map(mapTransformation);
From af86868f3eff884bce63146440aa0576c691e381 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Fri, 18 Jun 2021 18:47:04 +0200
Subject: [PATCH 027/142] Auto stash before revert of "Intersection from Hybrid
to AtMostOne"
---
.../object/ObjectIntersectFunctionIterator.java | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
index 7897cc061c..8b00afbaa2 100644
--- a/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
@@ -47,14 +47,13 @@ public class ObjectIntersectFunctionIterator extends HybridRuntimeIterator {
*/
private static final long serialVersionUID = 1L;
private RuntimeIterator iterator;
-
public ObjectIntersectFunctionIterator(
- List arguments,
+ List children,
ExecutionMode executionMode,
ExceptionMetadata iteratorMetadata
) {
- super(arguments, executionMode, iteratorMetadata);
- this.iterator = arguments.get(0);
+ super(children, executionMode, iteratorMetadata);
+ this.iterator = this.children.get(0);
}
@Override
@@ -137,5 +136,7 @@ protected JavaRDD
- getRDDAux(DynamicContext context) {
JavaSparkContext sparkContext = SparkSessionManager.getInstance().getJavaSparkContext();
List
- listResult = Arrays.asList(reduceResult);
return sparkContext.parallelize(listResult);
+
}
+
}
From ec5f04b183b62e1a774482dcef414ab25fb9ea57 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Fri, 18 Jun 2021 19:03:43 +0200
Subject: [PATCH 028/142] spotless
---
.../java/org/rumbledb/context/BuiltinFunctionCatalogue.java | 4 ++--
.../functions/object/ObjectIntersectFunctionIterator.java | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index ebfa8dfb33..70ea352915 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -2135,9 +2135,9 @@ private static BuiltinFunction createBuiltinFunction(
"intersect"
),
"item*",
- "object+",
+ "object",
ObjectIntersectFunctionIterator.class,
- BuiltinFunction.BuiltinFunctionExecutionMode.INHERIT_FROM_FIRST_ARGUMENT
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
/**
* function that projects objects by filtering their pairs and leaves non-objects intact
diff --git a/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
index 8b00afbaa2..ef8e9188e4 100644
--- a/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
@@ -47,6 +47,7 @@ public class ObjectIntersectFunctionIterator extends HybridRuntimeIterator {
*/
private static final long serialVersionUID = 1L;
private RuntimeIterator iterator;
+
public ObjectIntersectFunctionIterator(
List children,
ExecutionMode executionMode,
From c2321df60693a3465899887c95138fe5a640f669 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Fri, 18 Jun 2021 19:14:33 +0200
Subject: [PATCH 029/142] intersect catalogue back to initial
---
.../java/org/rumbledb/context/BuiltinFunctionCatalogue.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index 70ea352915..ebfa8dfb33 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -2135,9 +2135,9 @@ private static BuiltinFunction createBuiltinFunction(
"intersect"
),
"item*",
- "object",
+ "object+",
ObjectIntersectFunctionIterator.class,
- BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ BuiltinFunction.BuiltinFunctionExecutionMode.INHERIT_FROM_FIRST_ARGUMENT
);
/**
* function that projects objects by filtering their pairs and leaves non-objects intact
From a87f780110ccc3b566c87d0c4fc8931bca1ced46 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Sat, 19 Jun 2021 21:08:58 +0200
Subject: [PATCH 030/142] deepEqual. add if collation
---
.../sequences/value/DeepEqualFunctionIterator.java | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java
index 2e444a3614..4e69718140 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java
@@ -26,7 +26,9 @@
import org.apache.spark.api.java.function.FlatMapFunction2;
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
+import org.rumbledb.exceptions.DefaultCollationException;
import org.rumbledb.exceptions.ExceptionMetadata;
+import org.rumbledb.exceptions.RumbleException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
@@ -55,6 +57,13 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
RuntimeIterator sequenceIterator1 = this.children.get(0);
RuntimeIterator sequenceIterator2 = this.children.get(1);
+ if (this.children.size() == 3) {
+ Item strColl = this.children.get(2).materializeFirstItemOrNull(context);
+ if (!strColl.equals("http://www.w3.org/2005/xpath-functions/collation/codepoint")) {
+ throw new DefaultCollationException("XQST0038", getMetadata());
+ }
+ }
+
if (sequenceIterator1.isRDDOrDataFrame() && sequenceIterator2.isRDDOrDataFrame()) {
JavaRDD
- rdd1 = sequenceIterator1.getRDD(context);
JavaRDD
- rdd2 = sequenceIterator2.getRDD(context);
From 8a6399b8460396e1594c13fe7aa8e724edf7585d Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Sun, 20 Jun 2021 13:03:06 +0200
Subject: [PATCH 031/142] RoundHalfToEven to numeric?
---
.../context/BuiltinFunctionCatalogue.java | 6 +++---
.../RoundHalfToEvenFunctionIterator.java | 20 +++++++++++++++----
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index ebfa8dfb33..9d53884779 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -884,7 +884,7 @@ private static BuiltinFunction createBuiltinFunction(
"math",
"round-half-to-even"
),
- "double?",
+ "numeric?",
"double?",
RoundHalfToEvenFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
@@ -895,9 +895,9 @@ private static BuiltinFunction createBuiltinFunction(
"math",
"round-half-to-even"
),
- "double?",
+ "numeric?",
"integer",
- "double?",
+ "numeric?",
RoundHalfToEvenFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
index 3d6bd94dbe..67e3f3c23a 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
@@ -24,6 +24,7 @@
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.IteratorFlowException;
+import org.rumbledb.exceptions.UnexpectedTypeException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
@@ -37,7 +38,6 @@ public class RoundHalfToEvenFunctionIterator extends AtMostOneItemLocalRuntimeIt
private static final long serialVersionUID = 1L;
- private RuntimeIterator iterator;
public RoundHalfToEvenFunctionIterator(
List arguments,
@@ -65,9 +65,21 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
precision = 0;
}
try {
- BigDecimal bd = new BigDecimal(value.castToDoubleValue());
- bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
- return ItemFactory.getInstance().createDoubleItem(bd.doubleValue());
+ if (value.isDouble()) {
+ BigDecimal bd = new BigDecimal(value.getDoubleValue());
+ bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
+ return ItemFactory.getInstance().createDoubleItem(bd.doubleValue());
+ }
+ if (value.isDecimal()) {
+ BigDecimal bd = value.getDecimalValue().setScale(precision, RoundingMode.HALF_EVEN);
+ return ItemFactory.getInstance().createDecimalItem(bd);
+ }
+ if (value.isFloat()) {
+ BigDecimal bd = new BigDecimal(value.getFloatValue());
+ bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
+ return ItemFactory.getInstance().createFloatItem(bd.floatValue());
+ }
+ throw new UnexpectedTypeException("Unexpected value in round-half-to-even(): " + value.getDynamicType(), getMetadata());
} catch (IteratorFlowException e) {
throw new IteratorFlowException(e.getJSONiqErrorMessage(), getMetadata());
From 1b47cbedc84bec48b310ef75d0e8b557b730828f Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Sun, 20 Jun 2021 13:03:06 +0200
Subject: [PATCH 032/142] RoundHalfToEven to numeric?
---
.../context/BuiltinFunctionCatalogue.java | 8 ++++----
.../RoundHalfToEvenFunctionIterator.java | 20 +++++++++++++++----
2 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index ebfa8dfb33..e8e425e2b6 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -884,8 +884,8 @@ private static BuiltinFunction createBuiltinFunction(
"math",
"round-half-to-even"
),
- "double?",
- "double?",
+ "numeric?",
+ "numeric?",
RoundHalfToEvenFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
@@ -895,9 +895,9 @@ private static BuiltinFunction createBuiltinFunction(
"math",
"round-half-to-even"
),
- "double?",
+ "numeric?",
"integer",
- "double?",
+ "numeric?",
RoundHalfToEvenFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
index 3d6bd94dbe..67e3f3c23a 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
@@ -24,6 +24,7 @@
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.IteratorFlowException;
+import org.rumbledb.exceptions.UnexpectedTypeException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
@@ -37,7 +38,6 @@ public class RoundHalfToEvenFunctionIterator extends AtMostOneItemLocalRuntimeIt
private static final long serialVersionUID = 1L;
- private RuntimeIterator iterator;
public RoundHalfToEvenFunctionIterator(
List arguments,
@@ -65,9 +65,21 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
precision = 0;
}
try {
- BigDecimal bd = new BigDecimal(value.castToDoubleValue());
- bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
- return ItemFactory.getInstance().createDoubleItem(bd.doubleValue());
+ if (value.isDouble()) {
+ BigDecimal bd = new BigDecimal(value.getDoubleValue());
+ bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
+ return ItemFactory.getInstance().createDoubleItem(bd.doubleValue());
+ }
+ if (value.isDecimal()) {
+ BigDecimal bd = value.getDecimalValue().setScale(precision, RoundingMode.HALF_EVEN);
+ return ItemFactory.getInstance().createDecimalItem(bd);
+ }
+ if (value.isFloat()) {
+ BigDecimal bd = new BigDecimal(value.getFloatValue());
+ bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
+ return ItemFactory.getInstance().createFloatItem(bd.floatValue());
+ }
+ throw new UnexpectedTypeException("Unexpected value in round-half-to-even(): " + value.getDynamicType(), getMetadata());
} catch (IteratorFlowException e) {
throw new IteratorFlowException(e.getJSONiqErrorMessage(), getMetadata());
From fe51050ea769b427ed4fae167340aa0e53c958f4 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Sun, 20 Jun 2021 13:13:28 +0200
Subject: [PATCH 033/142] spotless.
---
.../functions/numerics/RoundHalfToEvenFunctionIterator.java | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
index 67e3f3c23a..8151e9194f 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
@@ -79,7 +79,10 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
return ItemFactory.getInstance().createFloatItem(bd.floatValue());
}
- throw new UnexpectedTypeException("Unexpected value in round-half-to-even(): " + value.getDynamicType(), getMetadata());
+ throw new UnexpectedTypeException(
+ "Unexpected value in round-half-to-even(): " + value.getDynamicType(),
+ getMetadata()
+ );
} catch (IteratorFlowException e) {
throw new IteratorFlowException(e.getJSONiqErrorMessage(), getMetadata());
From fbf8e11eabc553cd4b223b3a18fcde0bd6f2feb5 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Sun, 20 Jun 2021 16:34:53 +0200
Subject: [PATCH 034/142] roundHalfToEven. support Int & Integer
in order to pass the 2 last failed tests
---
.../numerics/RoundHalfToEvenFunctionIterator.java | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
index 8151e9194f..4b89bd0691 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
@@ -79,6 +79,16 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
return ItemFactory.getInstance().createFloatItem(bd.floatValue());
}
+ if (value.isInt()) {
+ BigDecimal bd = new BigDecimal(value.getIntValue());
+ bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
+ return ItemFactory.getInstance().createIntItem(bd.intValue());
+ }
+ if (value.isInteger()) {
+ BigDecimal bd = new BigDecimal(value.getIntegerValue());
+ bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
+ return ItemFactory.getInstance().createIntegerItem(bd.toBigInteger());
+ }
throw new UnexpectedTypeException(
"Unexpected value in round-half-to-even(): " + value.getDynamicType(),
getMetadata()
From 8cf9dee8144dc437567643d51afab8d8ffd8daf0 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Sun, 20 Jun 2021 16:34:53 +0200
Subject: [PATCH 035/142] roundHalfToEven. support Int & Integer
in order to pass the 2 last failed tests
---
.../numerics/RoundHalfToEvenFunctionIterator.java | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
index 8151e9194f..cc0d40e0e2 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
@@ -65,6 +65,16 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
precision = 0;
}
try {
+ if (value.isInt()) {
+ BigDecimal bd = new BigDecimal(value.getIntValue());
+ bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
+ return ItemFactory.getInstance().createIntItem(bd.intValue());
+ }
+ if (value.isInteger()) {
+ BigDecimal bd = new BigDecimal(value.getIntegerValue());
+ bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
+ return ItemFactory.getInstance().createIntegerItem(bd.toBigInteger());
+ }
if (value.isDouble()) {
BigDecimal bd = new BigDecimal(value.getDoubleValue());
bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
@@ -79,6 +89,7 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
return ItemFactory.getInstance().createFloatItem(bd.floatValue());
}
+
throw new UnexpectedTypeException(
"Unexpected value in round-half-to-even(): " + value.getDynamicType(),
getMetadata()
From 97267db75b0144f0d3aa418bb15e7f8b2cba0851 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Mon, 21 Jun 2021 11:46:33 +0200
Subject: [PATCH 036/142] comment collation part
---
.../functions/sequences/value/DeepEqualFunctionIterator.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java
index 4e69718140..00f7e27065 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java
@@ -57,12 +57,14 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
RuntimeIterator sequenceIterator1 = this.children.get(0);
RuntimeIterator sequenceIterator2 = this.children.get(1);
+ /*
if (this.children.size() == 3) {
Item strColl = this.children.get(2).materializeFirstItemOrNull(context);
if (!strColl.equals("http://www.w3.org/2005/xpath-functions/collation/codepoint")) {
throw new DefaultCollationException("XQST0038", getMetadata());
}
}
+ */
if (sequenceIterator1.isRDDOrDataFrame() && sequenceIterator2.isRDDOrDataFrame()) {
JavaRDD
- rdd1 = sequenceIterator1.getRDD(context);
From 3f0ecc8ec22f41a697efeb89fc5760d494a4e8d3 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Mon, 21 Jun 2021 13:08:20 +0200
Subject: [PATCH 037/142] SupportCollation. DeepEqual, Contains, StartsWith
adapt catalogue as well, remaining crashes are from different collation strings
---
.../context/BuiltinFunctionCatalogue.java | 55 ++++++++++++++++---
.../value/DeepEqualFunctionIterator.java | 10 +---
.../strings/ContainsFunctionIterator.java | 8 +++
.../strings/StartsWithFunctionIterator.java | 8 +++
4 files changed, 67 insertions(+), 14 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index ebfa8dfb33..4114a58d82 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -793,7 +793,7 @@ private static BuiltinFunction createBuiltinFunction(
/**
* function that returns whether two sequences are deep-equal to each other
*/
- static final BuiltinFunction deep_equal = createBuiltinFunction(
+ static final BuiltinFunction deep_equal1 = createBuiltinFunction(
new Name(
Name.FN_NS,
"fn",
@@ -805,6 +805,19 @@ private static BuiltinFunction createBuiltinFunction(
DeepEqualFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
+ static final BuiltinFunction deep_equal2 = createBuiltinFunction(
+ new Name(
+ Name.FN_NS,
+ "fn",
+ "deep-equal"
+ ),
+ "item*",
+ "item*",
+ "string",
+ "boolean",
+ DeepEqualFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ );
/**
* function that returns the absolute value of the arg
*/
@@ -1404,7 +1417,7 @@ private static BuiltinFunction createBuiltinFunction(
/**
* function that checks whether a string starts with a substring
*/
- static final BuiltinFunction starts_with = createBuiltinFunction(
+ static final BuiltinFunction starts_with1 = createBuiltinFunction(
new Name(
Name.FN_NS,
"fn",
@@ -1416,10 +1429,35 @@ private static BuiltinFunction createBuiltinFunction(
StartsWithFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
+ static final BuiltinFunction starts_with2 = createBuiltinFunction(
+ new Name(
+ Name.FN_NS,
+ "fn",
+ "starts-with"
+ ),
+ "string?",
+ "string?",
+ "string",
+ "boolean",
+ StartsWithFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ );
/**
* function that checks whether a string contains a substring
*/
- static final BuiltinFunction contains = createBuiltinFunction(
+ static final BuiltinFunction contains1 = createBuiltinFunction(
+ new Name(
+ Name.FN_NS,
+ "fn",
+ "contains"
+ ),
+ "string?",
+ "string?",
+ "boolean",
+ ContainsFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ );
+ static final BuiltinFunction contains2 = createBuiltinFunction(
new Name(
Name.FN_NS,
"fn",
@@ -1427,6 +1465,7 @@ private static BuiltinFunction createBuiltinFunction(
),
"string?",
"string?",
+ "string",
"boolean",
ContainsFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
@@ -2295,8 +2334,8 @@ private static BuiltinFunction createBuiltinFunction(
builtinFunctions.put(distinct_values.getIdentifier(), distinct_values);
builtinFunctions.put(index_of.getIdentifier(), index_of);
- builtinFunctions.put(deep_equal.getIdentifier(), deep_equal);
-
+ builtinFunctions.put(deep_equal1.getIdentifier(), deep_equal1);
+ builtinFunctions.put(deep_equal2.getIdentifier(), deep_equal2);
builtinFunctions.put(abs.getIdentifier(), abs);
builtinFunctions.put(ceiling.getIdentifier(), ceiling);
builtinFunctions.put(floor.getIdentifier(), floor);
@@ -2343,9 +2382,11 @@ private static BuiltinFunction createBuiltinFunction(
builtinFunctions.put(upper_case.getIdentifier(), upper_case);
builtinFunctions.put(translate.getIdentifier(), translate);
builtinFunctions.put(codepoint_equal.getIdentifier(), codepoint_equal);
- builtinFunctions.put(starts_with.getIdentifier(), starts_with);
+ builtinFunctions.put(starts_with1.getIdentifier(), starts_with1);
+ builtinFunctions.put(starts_with2.getIdentifier(), starts_with2);
builtinFunctions.put(matches.getIdentifier(), matches);
- builtinFunctions.put(contains.getIdentifier(), contains);
+ builtinFunctions.put(contains1.getIdentifier(), contains1);
+ builtinFunctions.put(contains2.getIdentifier(), contains2);
builtinFunctions.put(normalize_space.getIdentifier(), normalize_space);
builtinFunctions.put(normalize_unicode1.getIdentifier(), normalize_unicode1);
builtinFunctions.put(normalize_unicode2.getIdentifier(), normalize_unicode2);
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java
index 00f7e27065..7c7b18b729 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/value/DeepEqualFunctionIterator.java
@@ -28,7 +28,6 @@
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.DefaultCollationException;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.RumbleException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
@@ -56,15 +55,12 @@ public DeepEqualFunctionIterator(
public Item materializeFirstItemOrNull(DynamicContext context) {
RuntimeIterator sequenceIterator1 = this.children.get(0);
RuntimeIterator sequenceIterator2 = this.children.get(1);
-
- /*
if (this.children.size() == 3) {
- Item strColl = this.children.get(2).materializeFirstItemOrNull(context);
- if (!strColl.equals("http://www.w3.org/2005/xpath-functions/collation/codepoint")) {
- throw new DefaultCollationException("XQST0038", getMetadata());
+ String collation = this.children.get(2).materializeFirstItemOrNull(context).getStringValue();
+ if (!collation.equals("http://www.w3.org/2005/xpath-functions/collation/codepoint")) {
+ throw new DefaultCollationException("Wrong collation parameter", getMetadata());
}
}
- */
if (sequenceIterator1.isRDDOrDataFrame() && sequenceIterator2.isRDDOrDataFrame()) {
JavaRDD
- rdd1 = sequenceIterator1.getRDD(context);
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/ContainsFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/ContainsFunctionIterator.java
index 2c46ee4802..08d3f04eef 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/ContainsFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/ContainsFunctionIterator.java
@@ -22,6 +22,7 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
+import org.rumbledb.exceptions.DefaultCollationException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
@@ -44,6 +45,13 @@ public ContainsFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
+ if (this.children.size() == 3) {
+ String collation = this.children.get(2).materializeFirstItemOrNull(context).getStringValue();
+ if (!collation.equals("http://www.w3.org/2005/xpath-functions/collation/codepoint")) {
+ throw new DefaultCollationException("Wrong collation parameter", getMetadata());
+ }
+ }
+
Item substringItem = this.children.get(1)
.materializeFirstItemOrNull(context);
if (substringItem == null || substringItem.getStringValue().isEmpty()) {
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/StartsWithFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/StartsWithFunctionIterator.java
index c79eb47192..8920c40d60 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/StartsWithFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/StartsWithFunctionIterator.java
@@ -22,6 +22,7 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
+import org.rumbledb.exceptions.DefaultCollationException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
@@ -44,6 +45,13 @@ public StartsWithFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
+ if (this.children.size() == 3) {
+ String collation = this.children.get(2).materializeFirstItemOrNull(context).getStringValue();
+ if (!collation.equals("http://www.w3.org/2005/xpath-functions/collation/codepoint")) {
+ throw new DefaultCollationException("Wrong collation parameter", getMetadata());
+ }
+ }
+
Item substringItem = this.children.get(1)
.materializeFirstItemOrNull(context);
if (substringItem == null || substringItem.getStringValue().isEmpty()) {
From a3afd87d3acadbbad55530c2c551fc528117d861 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Mon, 21 Jun 2021 14:04:18 +0200
Subject: [PATCH 038/142] Revert "Merge remote-tracking branch
'origin/correct-types-pierre-motard' into support-collation-pierre-motard"
This reverts commit a1595b711e174f68fc0b534582f65649017d28b6.
---
.../context/BuiltinFunctionCatalogue.java | 8 ++---
.../RoundHalfToEvenFunctionIterator.java | 34 +++----------------
2 files changed, 8 insertions(+), 34 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index 2ab0b17ced..4114a58d82 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -897,8 +897,8 @@ private static BuiltinFunction createBuiltinFunction(
"math",
"round-half-to-even"
),
- "numeric?",
- "numeric?",
+ "double?",
+ "double?",
RoundHalfToEvenFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
@@ -908,9 +908,9 @@ private static BuiltinFunction createBuiltinFunction(
"math",
"round-half-to-even"
),
- "numeric?",
+ "double?",
"integer",
- "numeric?",
+ "double?",
RoundHalfToEvenFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
index cc0d40e0e2..3d6bd94dbe 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundHalfToEvenFunctionIterator.java
@@ -24,7 +24,6 @@
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.IteratorFlowException;
-import org.rumbledb.exceptions.UnexpectedTypeException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
@@ -38,6 +37,7 @@ public class RoundHalfToEvenFunctionIterator extends AtMostOneItemLocalRuntimeIt
private static final long serialVersionUID = 1L;
+ private RuntimeIterator iterator;
public RoundHalfToEvenFunctionIterator(
List arguments,
@@ -65,35 +65,9 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
precision = 0;
}
try {
- if (value.isInt()) {
- BigDecimal bd = new BigDecimal(value.getIntValue());
- bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
- return ItemFactory.getInstance().createIntItem(bd.intValue());
- }
- if (value.isInteger()) {
- BigDecimal bd = new BigDecimal(value.getIntegerValue());
- bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
- return ItemFactory.getInstance().createIntegerItem(bd.toBigInteger());
- }
- if (value.isDouble()) {
- BigDecimal bd = new BigDecimal(value.getDoubleValue());
- bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
- return ItemFactory.getInstance().createDoubleItem(bd.doubleValue());
- }
- if (value.isDecimal()) {
- BigDecimal bd = value.getDecimalValue().setScale(precision, RoundingMode.HALF_EVEN);
- return ItemFactory.getInstance().createDecimalItem(bd);
- }
- if (value.isFloat()) {
- BigDecimal bd = new BigDecimal(value.getFloatValue());
- bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
- return ItemFactory.getInstance().createFloatItem(bd.floatValue());
- }
-
- throw new UnexpectedTypeException(
- "Unexpected value in round-half-to-even(): " + value.getDynamicType(),
- getMetadata()
- );
+ BigDecimal bd = new BigDecimal(value.castToDoubleValue());
+ bd = bd.setScale(precision, RoundingMode.HALF_EVEN);
+ return ItemFactory.getInstance().createDoubleItem(bd.doubleValue());
} catch (IteratorFlowException e) {
throw new IteratorFlowException(e.getJSONiqErrorMessage(), getMetadata());
From 3f381b473f7b55623eb7757962d9c7c8ffc5f2d4 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Mon, 21 Jun 2021 15:30:26 +0200
Subject: [PATCH 039/142] Collation support. EndsWith, Substring before/after
---
.../context/BuiltinFunctionCatalogue.java | 64 ++++++++++++++++---
.../strings/EndsWithFunctionIterator.java | 7 ++
.../SubstringAfterFunctionIterator.java | 8 ++-
.../SubstringBeforeFunctionIterator.java | 7 ++
4 files changed, 75 insertions(+), 11 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index 4114a58d82..2fbc806407 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -1146,7 +1146,7 @@ private static BuiltinFunction createBuiltinFunction(
* function that returns the part of the first variable that precedes the first occurrence of the second
* variable.
*/
- static final BuiltinFunction substring_before = createBuiltinFunction(
+ static final BuiltinFunction substring_before1 = createBuiltinFunction(
new Name(
Name.FN_NS,
"fn",
@@ -1158,11 +1158,36 @@ private static BuiltinFunction createBuiltinFunction(
SubstringBeforeFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
+ static final BuiltinFunction substring_before2 = createBuiltinFunction(
+ new Name(
+ Name.FN_NS,
+ "fn",
+ "substring-before"
+ ),
+ "string?",
+ "string?",
+ "string",
+ "string",
+ SubstringBeforeFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ );
/**
* function that returns the part of the first variable that follows the first occurrence of the second
* vairable.
*/
- static final BuiltinFunction substring_after = createBuiltinFunction(
+ static final BuiltinFunction substring_after1 = createBuiltinFunction(
+ new Name(
+ Name.FN_NS,
+ "fn",
+ "substring-after"
+ ),
+ "string?",
+ "string?",
+ "string",
+ SubstringAfterFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ );
+ static final BuiltinFunction substring_after2 = createBuiltinFunction(
new Name(
Name.FN_NS,
"fn",
@@ -1171,6 +1196,7 @@ private static BuiltinFunction createBuiltinFunction(
"string?",
"string?",
"string",
+ "string",
SubstringAfterFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
@@ -1262,7 +1288,7 @@ private static BuiltinFunction createBuiltinFunction(
/**
* function that replaces parts of a string according to a regex expression
*/
- static final BuiltinFunction replace = createBuiltinFunction(
+ static final BuiltinFunction replace1 = createBuiltinFunction(
new Name(
Name.FN_NS,
"fn",
@@ -1275,6 +1301,7 @@ private static BuiltinFunction createBuiltinFunction(
ReplaceFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
+
/**
* function that returns the string length
*/
@@ -1402,7 +1429,7 @@ private static BuiltinFunction createBuiltinFunction(
/**
* function that checks whether a string ends with a substring
*/
- static final BuiltinFunction ends_with = createBuiltinFunction(
+ static final BuiltinFunction ends_with1 = createBuiltinFunction(
new Name(
Name.FN_NS,
"fn",
@@ -1414,6 +1441,19 @@ private static BuiltinFunction createBuiltinFunction(
EndsWithFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
+ static final BuiltinFunction ends_with2 = createBuiltinFunction(
+ new Name(
+ Name.FN_NS,
+ "fn",
+ "ends-with"
+ ),
+ "string?",
+ "string?",
+ "string",
+ "boolean",
+ EndsWithFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ );
/**
* function that checks whether a string starts with a substring
*/
@@ -1473,7 +1513,7 @@ private static BuiltinFunction createBuiltinFunction(
/**
* function that checks whether a string matches a regular expression
*/
- static final BuiltinFunction matches = createBuiltinFunction(
+ static final BuiltinFunction matches1 = createBuiltinFunction(
new Name(
Name.FN_NS,
"fn",
@@ -1485,6 +1525,7 @@ private static BuiltinFunction createBuiltinFunction(
MatchesFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
+
/**
* function that normalizes spaces in a string
*/
@@ -2361,18 +2402,21 @@ private static BuiltinFunction createBuiltinFunction(
builtinFunctions.put(codepoints_to_string.getIdentifier(), codepoints_to_string);
builtinFunctions.put(string_to_codepoints.getIdentifier(), string_to_codepoints);
- builtinFunctions.put(replace.getIdentifier(), replace);
+ builtinFunctions.put(replace1.getIdentifier(), replace1);
builtinFunctions.put(substring2.getIdentifier(), substring2);
builtinFunctions.put(substring3.getIdentifier(), substring3);
- builtinFunctions.put(substring_before.getIdentifier(), substring_before);
- builtinFunctions.put(substring_after.getIdentifier(), substring_after);
+ builtinFunctions.put(substring_before1.getIdentifier(), substring_before1);
+ builtinFunctions.put(substring_before2.getIdentifier(), substring_before2);
+ builtinFunctions.put(substring_after1.getIdentifier(), substring_after1);
+ builtinFunctions.put(substring_after2.getIdentifier(), substring_after2);
for (int i = 0; i < 100; i++) {
builtinFunctions.put(
new FunctionIdentifier(Name.createVariableInDefaultFunctionNamespace("concat"), i),
concat
);
}
- builtinFunctions.put(ends_with.getIdentifier(), ends_with);
+ builtinFunctions.put(ends_with1.getIdentifier(), ends_with1);
+ builtinFunctions.put(ends_with2.getIdentifier(), ends_with2);
builtinFunctions.put(string_join1.getIdentifier(), string_join1);
builtinFunctions.put(string_join2.getIdentifier(), string_join2);
builtinFunctions.put(string_length.getIdentifier(), string_length);
@@ -2384,7 +2428,7 @@ private static BuiltinFunction createBuiltinFunction(
builtinFunctions.put(codepoint_equal.getIdentifier(), codepoint_equal);
builtinFunctions.put(starts_with1.getIdentifier(), starts_with1);
builtinFunctions.put(starts_with2.getIdentifier(), starts_with2);
- builtinFunctions.put(matches.getIdentifier(), matches);
+ builtinFunctions.put(matches1.getIdentifier(), matches1);
builtinFunctions.put(contains1.getIdentifier(), contains1);
builtinFunctions.put(contains2.getIdentifier(), contains2);
builtinFunctions.put(normalize_space.getIdentifier(), normalize_space);
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/EndsWithFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/EndsWithFunctionIterator.java
index 049e50f314..6cf37d6cfe 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/EndsWithFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/EndsWithFunctionIterator.java
@@ -22,6 +22,7 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
+import org.rumbledb.exceptions.DefaultCollationException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
@@ -44,6 +45,12 @@ public EndsWithFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
+ if (this.children.size() == 3) {
+ String collation = this.children.get(2).materializeFirstItemOrNull(context).getStringValue();
+ if (!collation.equals("http://www.w3.org/2005/xpath-functions/collation/codepoint")) {
+ throw new DefaultCollationException("Wrong collation parameter", getMetadata());
+ }
+ }
Item substringItem = this.children.get(1)
.materializeFirstItemOrNull(context);
if (substringItem == null || substringItem.getStringValue().isEmpty()) {
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/SubstringAfterFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/SubstringAfterFunctionIterator.java
index bbc91f2275..cc524fa5f2 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/SubstringAfterFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/SubstringAfterFunctionIterator.java
@@ -2,6 +2,7 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
+import org.rumbledb.exceptions.DefaultCollationException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
@@ -28,7 +29,12 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
.materializeFirstItemOrNull(context);
Item substringItem = this.children.get(1)
.materializeFirstItemOrNull(context);
-
+ if (this.children.size() == 3) {
+ String collation = this.children.get(2).materializeFirstItemOrNull(context).getStringValue();
+ if (!collation.equals("http://www.w3.org/2005/xpath-functions/collation/codepoint")) {
+ throw new DefaultCollationException("Wrong collation parameter", getMetadata());
+ }
+ }
if (stringItem == null || stringItem.getStringValue().isEmpty()) {
return ItemFactory.getInstance().createStringItem("");
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/SubstringBeforeFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/SubstringBeforeFunctionIterator.java
index eafc21e68b..1924f86b09 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/SubstringBeforeFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/SubstringBeforeFunctionIterator.java
@@ -2,6 +2,7 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
+import org.rumbledb.exceptions.DefaultCollationException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
@@ -28,6 +29,12 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
.materializeFirstItemOrNull(context);
Item substringItem = this.children.get(1)
.materializeFirstItemOrNull(context);
+ if (this.children.size() == 3) {
+ String collation = this.children.get(2).materializeFirstItemOrNull(context).getStringValue();
+ if (!collation.equals("http://www.w3.org/2005/xpath-functions/collation/codepoint")) {
+ throw new DefaultCollationException("Wrong collation parameter", getMetadata());
+ }
+ }
if (
substringItem == null
|| substringItem.getStringValue().isEmpty()
From 1cea585951b53576a26f07c620b5d7b9a63ba404 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Mon, 21 Jun 2021 15:42:08 +0200
Subject: [PATCH 040/142] Support collation. Distinct values, index of
---
.../context/BuiltinFunctionCatalogue.java | 35 ++++++++++++++++---
.../value/DistinctValuesFunctionIterator.java | 9 +++++
.../value/IndexOfFunctionIterator.java | 11 ++++++
3 files changed, 51 insertions(+), 4 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index 2fbc806407..f1671d2cf9 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -764,7 +764,7 @@ private static BuiltinFunction createBuiltinFunction(
/**
* function that returns the values that appear in a sequence, with duplicates eliminated
*/
- static final BuiltinFunction distinct_values = createBuiltinFunction(
+ static final BuiltinFunction distinct_values1 = createBuiltinFunction(
new Name(
Name.FN_NS,
"fn",
@@ -775,10 +775,22 @@ private static BuiltinFunction createBuiltinFunction(
DistinctValuesFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.INHERIT_FROM_FIRST_ARGUMENT
);
+ static final BuiltinFunction distinct_values2 = createBuiltinFunction(
+ new Name(
+ Name.FN_NS,
+ "fn",
+ "distinct-values"
+ ),
+ "atomic*",
+ "string",
+ "atomic*",
+ DistinctValuesFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.INHERIT_FROM_FIRST_ARGUMENT
+ );
/**
* function that returns indices of items that are equal to the search parameter
*/
- static final BuiltinFunction index_of = createBuiltinFunction(
+ static final BuiltinFunction index_of1 = createBuiltinFunction(
new Name(
Name.FN_NS,
"fn",
@@ -790,6 +802,19 @@ private static BuiltinFunction createBuiltinFunction(
IndexOfFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.INHERIT_FROM_FIRST_ARGUMENT
);
+ static final BuiltinFunction index_of2 = createBuiltinFunction(
+ new Name(
+ Name.FN_NS,
+ "fn",
+ "index-of"
+ ),
+ "atomic*",
+ "atomic",
+ "string",
+ "integer*",
+ IndexOfFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.INHERIT_FROM_FIRST_ARGUMENT
+ );
/**
* function that returns whether two sequences are deep-equal to each other
*/
@@ -2373,8 +2398,10 @@ private static BuiltinFunction createBuiltinFunction(
builtinFunctions.put(one_or_more.getIdentifier(), one_or_more);
builtinFunctions.put(exactly_one.getIdentifier(), exactly_one);
- builtinFunctions.put(distinct_values.getIdentifier(), distinct_values);
- builtinFunctions.put(index_of.getIdentifier(), index_of);
+ builtinFunctions.put(distinct_values1.getIdentifier(), distinct_values1);
+ builtinFunctions.put(distinct_values2.getIdentifier(), distinct_values2);
+ builtinFunctions.put(index_of1.getIdentifier(), index_of1);
+ builtinFunctions.put(index_of2.getIdentifier(), index_of2);
builtinFunctions.put(deep_equal1.getIdentifier(), deep_equal1);
builtinFunctions.put(deep_equal2.getIdentifier(), deep_equal2);
builtinFunctions.put(abs.getIdentifier(), abs);
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/value/DistinctValuesFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/value/DistinctValuesFunctionIterator.java
index dc8011905f..12a094b58e 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/value/DistinctValuesFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/value/DistinctValuesFunctionIterator.java
@@ -23,6 +23,7 @@
import org.apache.spark.api.java.JavaRDD;
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
+import org.rumbledb.exceptions.DefaultCollationException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
@@ -48,6 +49,14 @@ public DistinctValuesFunctionIterator(
) {
super(arguments, executionMode, iteratorMetadata);
this.sequenceIterator = arguments.get(0);
+ if (arguments.size() == 2) {
+ String collation = arguments.get(1)
+ .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution)
+ .getStringValue();
+ if (!collation.equals("http://www.w3.org/2005/xpath-functions/collation/codepoint")) {
+ throw new DefaultCollationException("Wrong collation parameter", getMetadata());
+ }
+ }
}
public Item nextLocal() {
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/value/IndexOfFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/value/IndexOfFunctionIterator.java
index 3b26d79534..9cf3bcabda 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/value/IndexOfFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/value/IndexOfFunctionIterator.java
@@ -24,6 +24,7 @@
import org.apache.spark.api.java.JavaRDD;
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
+import org.rumbledb.exceptions.DefaultCollationException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.exceptions.NonAtomicKeyException;
@@ -54,6 +55,16 @@ public IndexOfFunctionIterator(
super(arguments, executionMode, iteratorMetadata);
this.sequenceIterator = this.children.get(0);
this.searchIterator = this.children.get(1);
+
+ if (this.children.size() == 3) {
+ String collation = this.children.get(2)
+ .materializeFirstItemOrNull(this.currentDynamicContextForLocalExecution)
+ .getStringValue();
+ if (!collation.equals("http://www.w3.org/2005/xpath-functions/collation/codepoint")) {
+ throw new DefaultCollationException("Wrong collation parameter", getMetadata());
+ }
+ }
+
}
@Override
From 67c94ba7b2a261d9838c3abe673d2fa621c83fa5 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Mon, 21 Jun 2021 16:48:46 +0200
Subject: [PATCH 041/142] AtMostOne from Hybrid. ObjectIntersect
---
.../ObjectIntersectFunctionIterator.java | 42 ++++---------------
1 file changed, 8 insertions(+), 34 deletions(-)
diff --git a/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
index ef8e9188e4..ced3eacea0 100644
--- a/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
@@ -30,6 +30,7 @@
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.HybridRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
@@ -41,7 +42,7 @@
import java.util.LinkedHashMap;
import java.util.List;
-public class ObjectIntersectFunctionIterator extends HybridRuntimeIterator {
+public class ObjectIntersectFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
/**
*
*/
@@ -58,9 +59,9 @@ public ObjectIntersectFunctionIterator(
}
@Override
- public Item nextLocal() {
- if (this.hasNext) {
- List
- items = this.iterator.materialize(this.currentDynamicContextForLocalExecution);
+ public Item materializeFirstItemOrNull(DynamicContext context) {
+ if (!this.iterator.isRDDOrDataFrame()) {
+ List
- items = this.iterator.materialize(context);
LinkedHashMap> keyValuePairs = new LinkedHashMap<>();
boolean firstItem = true;
for (Item item : items) {
@@ -96,34 +97,9 @@ public Item nextLocal() {
Item result = ItemFactory.getInstance().createObjectItem(keyValuePairs);
- this.hasNext = false;
return result;
}
- throw new IteratorFlowException(
- RuntimeIterator.FLOW_EXCEPTION_MESSAGE + " INTERSECT function",
- getMetadata()
- );
- }
-
- @Override
- protected void openLocal() {
- }
- @Override
- protected void closeLocal() {
- }
-
- @Override
- protected void resetLocal() {
- }
-
- @Override
- protected boolean hasNextLocal() {
- return this.hasNext;
- }
-
- @Override
- protected JavaRDD
- getRDDAux(DynamicContext context) {
// Enclose object values into arrays.
JavaRDD
- childRDD = this.iterator.getRDD(context);
Function
- mapTransformation = new ObjectIntersectMapClosure();
@@ -131,13 +107,11 @@ protected JavaRDD
- getRDDAux(DynamicContext context) {
// Reduce input objects.
Function2
- transformation = new ObjectIntersectReduceClosure();
- Item reduceResult = mapResult.reduce(transformation);
+ Item result = mapResult.reduce(transformation);
- // transform Item to JavaRDD
-
- JavaSparkContext sparkContext = SparkSessionManager.getInstance().getJavaSparkContext();
- List
- listResult = Arrays.asList(reduceResult);
- return sparkContext.parallelize(listResult);
+ return result;
}
+
}
From 1689eb3896f03b83d2a32ad783a463f8223f4c60 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Tue, 22 Jun 2021 12:06:02 +0200
Subject: [PATCH 042/142] Collation min#2 max#2
---
.../context/BuiltinFunctionCatalogue.java | 26 ++++++++++++++++---
.../aggregate/MaxFunctionIterator.java | 7 +++++
.../aggregate/MinFunctionIterator.java | 7 +++++
3 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index f1671d2cf9..9b016e93a2 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -549,23 +549,39 @@ private static BuiltinFunction createBuiltinFunction(
/**
* function that returns the minimum of a sequence
*/
- static final BuiltinFunction min = createBuiltinFunction(
+ static final BuiltinFunction min1 = createBuiltinFunction(
new Name(Name.FN_NS, "fn", "min"),
"item*",
"atomic?",
MinFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
+ static final BuiltinFunction min2 = createBuiltinFunction(
+ new Name(Name.FN_NS, "fn", "min"),
+ "item*",
+ "string",
+ "atomic?",
+ MinFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ );
/**
* function that returns the maximum of a sequence
*/
- static final BuiltinFunction max = createBuiltinFunction(
+ static final BuiltinFunction max1 = createBuiltinFunction(
new Name(Name.FN_NS, "fn", "max"),
"item*",
"atomic?",
MaxFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
+ static final BuiltinFunction max2 = createBuiltinFunction(
+ new Name(Name.FN_NS, "fn", "max"),
+ "item*",
+ "string",
+ "atomic?",
+ MaxFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ );
/**
* function that returns the average of a sequence
*/
@@ -2378,8 +2394,10 @@ private static BuiltinFunction createBuiltinFunction(
builtinFunctions.put(count.getIdentifier(), count);
builtinFunctions.put(boolean_function.getIdentifier(), boolean_function);
- builtinFunctions.put(min.getIdentifier(), min);
- builtinFunctions.put(max.getIdentifier(), max);
+ builtinFunctions.put(min1.getIdentifier(), min1);
+ builtinFunctions.put(min2.getIdentifier(), min2);
+ builtinFunctions.put(max1.getIdentifier(), max1);
+ builtinFunctions.put(max2.getIdentifier(), max2);
builtinFunctions.put(sum1.getIdentifier(), sum1);
builtinFunctions.put(sum2.getIdentifier(), sum2);
builtinFunctions.put(avg.getIdentifier(), avg);
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MaxFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MaxFunctionIterator.java
index aab3046b02..0b64e88d07 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MaxFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MaxFunctionIterator.java
@@ -24,6 +24,7 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.context.Name;
+import org.rumbledb.exceptions.DefaultCollationException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.InvalidArgumentTypeException;
import org.rumbledb.exceptions.RumbleException;
@@ -62,6 +63,12 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
getMetadata()
)
);
+ if (this.children.size() == 2) {
+ String collation = this.children.get(1).materializeFirstItemOrNull(context).getStringValue();
+ if (!collation.equals("http://www.w3.org/2005/xpath-functions/collation/codepoint")) {
+ throw new DefaultCollationException("Wrong collation parameter", getMetadata());
+ }
+ }
if (!this.iterator.isRDDOrDataFrame()) {
diff --git a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MinFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MinFunctionIterator.java
index ea637426df..aa5b17f66e 100644
--- a/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MinFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/sequences/aggregate/MinFunctionIterator.java
@@ -24,6 +24,7 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.context.Name;
+import org.rumbledb.exceptions.DefaultCollationException;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.InvalidArgumentTypeException;
import org.rumbledb.exceptions.RumbleException;
@@ -62,6 +63,12 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
getMetadata()
)
);
+ if (this.children.size() == 2) {
+ String collation = this.children.get(1).materializeFirstItemOrNull(context).getStringValue();
+ if (!collation.equals("http://www.w3.org/2005/xpath-functions/collation/codepoint")) {
+ throw new DefaultCollationException("Wrong collation parameter", getMetadata());
+ }
+ }
if (!this.iterator.isRDDOrDataFrame()) {
From 902a9041c7d2d3731406f13a6ac66a7e1437ebfa Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Tue, 22 Jun 2021 15:25:38 +0200
Subject: [PATCH 043/142] fix intersect
---
.../java/org/rumbledb/context/BuiltinFunctionCatalogue.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index ebfa8dfb33..70ea352915 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -2135,9 +2135,9 @@ private static BuiltinFunction createBuiltinFunction(
"intersect"
),
"item*",
- "object+",
+ "object",
ObjectIntersectFunctionIterator.class,
- BuiltinFunction.BuiltinFunctionExecutionMode.INHERIT_FROM_FIRST_ARGUMENT
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
/**
* function that projects objects by filtering their pairs and leaves non-objects intact
From 2e63c10dd9633c1a1d2765adac08b9b728ffb543 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Tue, 22 Jun 2021 15:25:38 +0200
Subject: [PATCH 044/142] fix intersect
---
.../java/org/rumbledb/context/BuiltinFunctionCatalogue.java | 4 ++--
.../functions/object/ObjectIntersectFunctionIterator.java | 5 -----
2 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index ebfa8dfb33..70ea352915 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -2135,9 +2135,9 @@ private static BuiltinFunction createBuiltinFunction(
"intersect"
),
"item*",
- "object+",
+ "object",
ObjectIntersectFunctionIterator.class,
- BuiltinFunction.BuiltinFunctionExecutionMode.INHERIT_FROM_FIRST_ARGUMENT
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
/**
* function that projects objects by filtering their pairs and leaves non-objects intact
diff --git a/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
index ced3eacea0..4f475ab0db 100644
--- a/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/object/ObjectIntersectFunctionIterator.java
@@ -21,23 +21,18 @@
package org.rumbledb.runtime.functions.object;
import org.apache.spark.api.java.JavaRDD;
-import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.Function;
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
-import org.rumbledb.runtime.HybridRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import sparksoniq.spark.SparkSessionManager;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
From 33dd84474fc323d7beae636b8e3d91731117103a Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Wed, 23 Jun 2021 07:30:47 +0000
Subject: [PATCH 045/142] Revert "Remove DurationFunction"
This reverts commit ec61adb3843511c03a29497c5f242a38da887237.
---
.../context/BuiltinFunctionCatalogue.java | 50 -----------------
.../DayTimeDurationFunctionIterator.java | 53 -------------------
.../durations/DurationFunctionIterator.java | 53 -------------------
.../YearMonthDurationFunctionIterator.java | 53 -------------------
4 files changed, 209 deletions(-)
delete mode 100644 src/main/java/org/rumbledb/runtime/functions/durations/DayTimeDurationFunctionIterator.java
delete mode 100644 src/main/java/org/rumbledb/runtime/functions/durations/DurationFunctionIterator.java
delete mode 100644 src/main/java/org/rumbledb/runtime/functions/durations/YearMonthDurationFunctionIterator.java
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index e2f916ae8b..1ed0c73cc0 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -38,9 +38,6 @@
import org.rumbledb.runtime.functions.datetime.components.TimezoneFromTimeFunctionIterator;
import org.rumbledb.runtime.functions.datetime.components.YearFromDateFunctionIterator;
import org.rumbledb.runtime.functions.datetime.components.YearFromDateTimeFunctionIterator;
-import org.rumbledb.runtime.functions.durations.DayTimeDurationFunctionIterator;
-import org.rumbledb.runtime.functions.durations.DurationFunctionIterator;
-import org.rumbledb.runtime.functions.durations.YearMonthDurationFunctionIterator;
import org.rumbledb.runtime.functions.durations.components.DaysFromDurationFunctionIterator;
import org.rumbledb.runtime.functions.durations.components.HoursFromDurationFunctionIterator;
import org.rumbledb.runtime.functions.durations.components.MinutesFromDurationFunctionIterator;
@@ -1611,50 +1608,6 @@ private static BuiltinFunction createBuiltinFunction(
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
- /**
- * function that returns the duration item from the supplied string
- */
- static final BuiltinFunction duration = createBuiltinFunction(
- new Name(
- Name.FN_NS,
- "fn",
- "duration"
- ),
- "string?",
- "duration?",
- DurationFunctionIterator.class,
- BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
- );
- /**
- * function that returns the yearMonthDuration item from the supplied string
- */
- static final BuiltinFunction yearMonthDuration = createBuiltinFunction(
- new Name(
- Name.FN_NS,
- "fn",
- "yearMonthDuration"
- ),
- "string?",
- "yearMonthDuration?",
- YearMonthDurationFunctionIterator.class,
- BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
- );
- /**
- * function that returns the dayTimeDuration item from the supplied string
- */
- static final BuiltinFunction dayTimeDuration = createBuiltinFunction(
- new Name(
- Name.FN_NS,
- "fn",
- "dayTimeDuration"
- ),
- "string?",
- "dayTimeDuration?",
- DayTimeDurationFunctionIterator.class,
- BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
- );
-
-
/**
* function that returns the years from a duration
*/
@@ -2483,9 +2436,6 @@ private static BuiltinFunction createBuiltinFunction(
builtinFunctions.put(number.getIdentifier(), number);
builtinFunctions.put(encode_for_uri.getIdentifier(), encode_for_uri);
- builtinFunctions.put(duration.getIdentifier(), duration);
- builtinFunctions.put(dayTimeDuration.getIdentifier(), dayTimeDuration);
- builtinFunctions.put(yearMonthDuration.getIdentifier(), yearMonthDuration);
builtinFunctions.put(years_from_duration.getIdentifier(), years_from_duration);
builtinFunctions.put(months_from_duration.getIdentifier(), months_from_duration);
builtinFunctions.put(days_from_duration.getIdentifier(), days_from_duration);
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/DayTimeDurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/DayTimeDurationFunctionIterator.java
deleted file mode 100644
index 739f004278..0000000000
--- a/src/main/java/org/rumbledb/runtime/functions/durations/DayTimeDurationFunctionIterator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.rumbledb.runtime.functions.durations;
-
-import org.joda.time.Period;
-import org.rumbledb.api.Item;
-import org.rumbledb.context.DynamicContext;
-import org.rumbledb.exceptions.CastException;
-import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.expressions.ExecutionMode;
-import org.rumbledb.items.DurationItem;
-import org.rumbledb.items.ItemFactory;
-import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
-import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.types.BuiltinTypesCatalogue;
-import java.util.List;
-
-public class DayTimeDurationFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
-
- private static final long serialVersionUID = 1L;
- private Item durationStringItem = null;
-
- public DayTimeDurationFunctionIterator(
- List parameters,
- ExecutionMode executionMode,
- ExceptionMetadata iteratorMetadata
- ) {
- super(parameters, executionMode, iteratorMetadata);
- }
-
- @Override
- public Item materializeFirstItemOrNull(DynamicContext context) {
- this.durationStringItem = this.children.get(0)
- .materializeFirstItemOrNull(context);
- if (this.durationStringItem == null) {
- return null;
- }
- try {
- Period period = DurationItem.getDurationFromString(
- this.durationStringItem.getStringValue(),
- BuiltinTypesCatalogue.dayTimeDurationItem
- );
- return ItemFactory.getInstance().createDayTimeDurationItem(period);
- } catch (UnsupportedOperationException | IllegalArgumentException e) {
- String message = String.format(
- "\"%s\": value of type %s is not castable to type %s",
- this.durationStringItem.serialize(),
- "string",
- "dayTimeDuration"
- );
- throw new CastException(message, getMetadata());
- }
- }
-
-}
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/DurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/DurationFunctionIterator.java
deleted file mode 100644
index a652a2d424..0000000000
--- a/src/main/java/org/rumbledb/runtime/functions/durations/DurationFunctionIterator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.rumbledb.runtime.functions.durations;
-
-import org.joda.time.Period;
-import org.rumbledb.api.Item;
-import org.rumbledb.context.DynamicContext;
-import org.rumbledb.exceptions.CastException;
-import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.expressions.ExecutionMode;
-import org.rumbledb.items.DurationItem;
-import org.rumbledb.items.ItemFactory;
-import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
-import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.types.BuiltinTypesCatalogue;
-import java.util.List;
-
-public class DurationFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
-
- private static final long serialVersionUID = 1L;
- private Item durationStringItem = null;
-
- public DurationFunctionIterator(
- List arguments,
- ExecutionMode executionMode,
- ExceptionMetadata iteratorMetadata
- ) {
- super(arguments, executionMode, iteratorMetadata);
- }
-
- @Override
- public Item materializeFirstItemOrNull(DynamicContext context) {
- this.durationStringItem = this.children.get(0)
- .materializeFirstItemOrNull(context);
- if (this.durationStringItem == null) {
- return null;
- }
- try {
- Period period = DurationItem.getDurationFromString(
- this.durationStringItem.getStringValue(),
- BuiltinTypesCatalogue.durationItem
- );
- return ItemFactory.getInstance().createDurationItem(period);
- } catch (UnsupportedOperationException | IllegalArgumentException e) {
- String message = String.format(
- "\"%s\": value of type %s is not castable to type %s",
- this.durationStringItem.serialize(),
- "string",
- "duration"
- );
- throw new CastException(message, getMetadata());
- }
- }
-
-}
diff --git a/src/main/java/org/rumbledb/runtime/functions/durations/YearMonthDurationFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/durations/YearMonthDurationFunctionIterator.java
deleted file mode 100644
index c2d72e7cf9..0000000000
--- a/src/main/java/org/rumbledb/runtime/functions/durations/YearMonthDurationFunctionIterator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.rumbledb.runtime.functions.durations;
-
-import org.joda.time.Period;
-import org.rumbledb.api.Item;
-import org.rumbledb.context.DynamicContext;
-import org.rumbledb.exceptions.CastException;
-import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.expressions.ExecutionMode;
-import org.rumbledb.items.DurationItem;
-import org.rumbledb.items.ItemFactory;
-import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
-import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.types.BuiltinTypesCatalogue;
-import java.util.List;
-
-public class YearMonthDurationFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
-
- private static final long serialVersionUID = 1L;
- private Item durationStringItem = null;
-
- public YearMonthDurationFunctionIterator(
- List parameters,
- ExecutionMode executionMode,
- ExceptionMetadata iteratorMetadata
- ) {
- super(parameters, executionMode, iteratorMetadata);
- }
-
- @Override
- public Item materializeFirstItemOrNull(DynamicContext context) {
- this.durationStringItem = this.children.get(0)
- .materializeFirstItemOrNull(context);
- if (this.durationStringItem == null) {
- return null;
- }
- try {
- Period period = DurationItem.getDurationFromString(
- this.durationStringItem.getStringValue(),
- BuiltinTypesCatalogue.yearMonthDurationItem
- );
- return ItemFactory.getInstance().createYearMonthDurationItem(period);
- } catch (UnsupportedOperationException | IllegalArgumentException e) {
- String message = String.format(
- "\"%s\": value of type %s is not castable to type %s",
- this.durationStringItem.serialize(),
- "string",
- "yearMonthDuration"
- );
- throw new CastException(message, getMetadata());
- }
- }
-
-}
From 265918ca171422a46c22a45f7e1735f4d76c04f7 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Wed, 23 Jun 2021 10:07:27 +0000
Subject: [PATCH 046/142] Ceiling supports numeric
only single quote test and fn-ceiling-double-5 not passing
---
.../context/BuiltinFunctionCatalogue.java | 14 +++----
.../numerics/CeilingFunctionIterator.java | 37 +++++++++++++++----
.../numerics/FloorFunctionIterator.java | 36 +++++++++++++++---
.../numerics/RoundFunctionIterator.java | 14 +++++--
4 files changed, 77 insertions(+), 24 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index 1ed0c73cc0..785333da90 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -317,7 +317,7 @@ private static BuiltinFunction createBuiltinFunction(
*/
static final BuiltinFunction position = createBuiltinFunction(
new Name(Name.FN_NS, "fn", "position"),
- "integer?",
+ "integer",
PositionFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
@@ -326,7 +326,7 @@ private static BuiltinFunction createBuiltinFunction(
*/
static final BuiltinFunction last = createBuiltinFunction(
new Name(Name.FN_NS, "fn", "last"),
- "integer?",
+ "integer",
LastFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
@@ -879,8 +879,8 @@ private static BuiltinFunction createBuiltinFunction(
"math",
"ceiling"
),
- "double?",
- "double?",
+ "numeric?",
+ "numeric?",
CeilingFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
@@ -893,8 +893,8 @@ private static BuiltinFunction createBuiltinFunction(
"math",
"floor"
),
- "double?",
- "double?",
+ "numeric?",
+ "numeric?",
FloorFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
@@ -962,7 +962,7 @@ private static BuiltinFunction createBuiltinFunction(
"math",
"pi"
),
- "double?",
+ "double",
PiFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/CeilingFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/CeilingFunctionIterator.java
index 7811c5ea12..58ec68618f 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/CeilingFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/CeilingFunctionIterator.java
@@ -23,18 +23,20 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
+import org.rumbledb.exceptions.UnexpectedTypeException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.util.List;
public class CeilingFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
- private RuntimeIterator iterator;
public CeilingFunctionIterator(
List arguments,
@@ -50,12 +52,33 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
if (value == null) {
return null;
}
- return ItemFactory.getInstance()
- .createDoubleItem(
- Math.ceil(
- value.castToDoubleValue()
- )
- );
+ if (value.isInt()) {
+ return ItemFactory.getInstance().createIntItem(value.getIntValue());
+ }
+ if (value.isInteger()) {
+ return ItemFactory.getInstance().createIntegerItem(value.getIntegerValue());
+ }
+ if (value.isDecimal()) {
+ BigDecimal bd = value.getDecimalValue().setScale(0, RoundingMode.CEILING);
+ return ItemFactory.getInstance().createDecimalItem(bd);
+ }
+ if (value.isFloat()) {
+ BigDecimal bd = new BigDecimal(value.getFloatValue());
+ bd = bd.setScale(0, RoundingMode.CEILING);
+ return ItemFactory.getInstance().createFloatItem(bd.floatValue());
+ }
+ if (value.isDouble()) {
+ return ItemFactory.getInstance()
+ .createDoubleItem(
+ Math.ceil(
+ value.castToDoubleValue()
+ )
+ );
+ }
+ throw new UnexpectedTypeException(
+ "Unexpected value in ceiling(): " + value.getDynamicType(),
+ getMetadata()
+ );
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java
index 4ea1f013ab..44fcddacbb 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/FloorFunctionIterator.java
@@ -23,6 +23,7 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.exceptions.ExceptionMetadata;
+import org.rumbledb.exceptions.UnexpectedTypeException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
@@ -30,6 +31,8 @@
import org.rumbledb.runtime.flwor.NativeClauseContext;
import org.rumbledb.types.BuiltinTypesCatalogue;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.util.List;
public class FloorFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
@@ -51,12 +54,33 @@ public Item materializeFirstItemOrNull(DynamicContext context) {
if (value == null) {
return null;
}
- return ItemFactory.getInstance()
- .createDoubleItem(
- Math.floor(
- value.castToDoubleValue()
- )
- );
+ if (value.isInt()) {
+ return ItemFactory.getInstance().createIntItem(value.getIntValue());
+ }
+ if (value.isInteger()) {
+ return ItemFactory.getInstance().createIntegerItem(value.getIntegerValue());
+ }
+ if (value.isDecimal()) {
+ BigDecimal bd = value.getDecimalValue().setScale(0, RoundingMode.FLOOR);
+ return ItemFactory.getInstance().createDecimalItem(bd);
+ }
+ if (value.isFloat()) {
+ BigDecimal bd = new BigDecimal(value.getFloatValue());
+ bd = bd.setScale(0, RoundingMode.FLOOR);
+ return ItemFactory.getInstance().createFloatItem(bd.floatValue());
+ }
+ if (value.isDouble()) {
+ return ItemFactory.getInstance()
+ .createDoubleItem(
+ Math.floor(
+ value.castToDoubleValue()
+ )
+ );
+ }
+ throw new UnexpectedTypeException(
+ "Unexpected value in floor(): " + value.getDynamicType(),
+ getMetadata()
+ );
}
@Override
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundFunctionIterator.java
index 861aaec7dd..78c60deb98 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/RoundFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/RoundFunctionIterator.java
@@ -74,18 +74,24 @@ public Item materializeFirstItemOrNull(DynamicContext dynamicContext) {
precision = 0;
}
try {
+ if (value.isInt()) {
+ BigDecimal bd = new BigDecimal(value.getIntValue()).setScale(precision, RoundingMode.HALF_UP);
+ return ItemFactory.getInstance().createIntItem(bd.intValue());
+ }
+ if (value.isInteger()) {
+ BigDecimal bd = new BigDecimal(value.getIntegerValue()).setScale(precision, RoundingMode.HALF_UP);
+ return ItemFactory.getInstance().createIntegerItem(bd.toBigInteger());
+ }
if (value.isDecimal()) {
BigDecimal bd = value.getDecimalValue().setScale(precision, RoundingMode.HALF_UP);
return ItemFactory.getInstance().createDecimalItem(bd);
}
if (value.isDouble()) {
- BigDecimal bd = new BigDecimal(value.getDoubleValue());
- bd = bd.setScale(precision, RoundingMode.HALF_UP);
+ BigDecimal bd = new BigDecimal(value.getDoubleValue()).setScale(precision, RoundingMode.HALF_UP);
return ItemFactory.getInstance().createDoubleItem(bd.doubleValue());
}
if (value.isFloat()) {
- BigDecimal bd = new BigDecimal(value.getFloatValue());
- bd = bd.setScale(precision, RoundingMode.HALF_UP);
+ BigDecimal bd = new BigDecimal(value.getFloatValue()).setScale(precision, RoundingMode.HALF_UP);
return ItemFactory.getInstance().createFloatItem(bd.floatValue());
}
throw new UnexpectedTypeException("Unexpected value in round(): " + value.getDynamicType(), getMetadata());
From 94063db76baeb456b6dbb805f506f1383f7354a9 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Thu, 24 Jun 2021 11:46:45 +0000
Subject: [PATCH 047/142] Add support for 0 parameter, in context
---
.../context/BuiltinFunctionCatalogue.java | 45 ++++++++++++++++---
.../numerics/NumberFunctionIterator.java | 5 +++
.../NormalizeSpaceFunctionIterator.java | 6 +++
.../strings/StringLengthFunctionIterator.java | 5 +++
4 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index 785333da90..9f08b349b4 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -1343,7 +1343,17 @@ private static BuiltinFunction createBuiltinFunction(
/**
* function that returns the string length
*/
- static final BuiltinFunction string_length = createBuiltinFunction(
+ static final BuiltinFunction string_length0 = createBuiltinFunction(
+ new Name(
+ Name.FN_NS,
+ "fn",
+ "string-length"
+ ),
+ "integer",
+ StringLengthFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ );
+ static final BuiltinFunction string_length1 = createBuiltinFunction(
new Name(
Name.FN_NS,
"fn",
@@ -1567,7 +1577,17 @@ private static BuiltinFunction createBuiltinFunction(
/**
* function that normalizes spaces in a string
*/
- static final BuiltinFunction normalize_space = createBuiltinFunction(
+ static final BuiltinFunction normalize_space0 = createBuiltinFunction(
+ new Name(
+ Name.FN_NS,
+ "fn",
+ "normalize-space"
+ ),
+ "string",
+ NormalizeSpaceFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ );
+ static final BuiltinFunction normalize_space1 = createBuiltinFunction(
new Name(
Name.FN_NS,
"fn",
@@ -1596,7 +1616,17 @@ private static BuiltinFunction createBuiltinFunction(
/**
* function that that returns the double representation of the input string or number
*/
- static final BuiltinFunction number = createBuiltinFunction(
+ static final BuiltinFunction number0 = createBuiltinFunction(
+ new Name(
+ Name.FN_NS,
+ "fn",
+ "number"
+ ),
+ "double",
+ NumberFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ );
+ static final BuiltinFunction number1 = createBuiltinFunction(
new Name(
Name.FN_NS,
"fn",
@@ -2417,7 +2447,8 @@ private static BuiltinFunction createBuiltinFunction(
builtinFunctions.put(ends_with2.getIdentifier(), ends_with2);
builtinFunctions.put(string_join1.getIdentifier(), string_join1);
builtinFunctions.put(string_join2.getIdentifier(), string_join2);
- builtinFunctions.put(string_length.getIdentifier(), string_length);
+ builtinFunctions.put(string_length0.getIdentifier(), string_length0);
+ builtinFunctions.put(string_length1.getIdentifier(), string_length1);
builtinFunctions.put(tokenize1.getIdentifier(), tokenize1);
builtinFunctions.put(tokenize2.getIdentifier(), tokenize2);
builtinFunctions.put(lower_case.getIdentifier(), lower_case);
@@ -2429,11 +2460,13 @@ private static BuiltinFunction createBuiltinFunction(
builtinFunctions.put(matches1.getIdentifier(), matches1);
builtinFunctions.put(contains1.getIdentifier(), contains1);
builtinFunctions.put(contains2.getIdentifier(), contains2);
- builtinFunctions.put(normalize_space.getIdentifier(), normalize_space);
+ builtinFunctions.put(normalize_space0.getIdentifier(), normalize_space0);
+ builtinFunctions.put(normalize_space1.getIdentifier(), normalize_space1);
builtinFunctions.put(normalize_unicode1.getIdentifier(), normalize_unicode1);
builtinFunctions.put(normalize_unicode2.getIdentifier(), normalize_unicode2);
builtinFunctions.put(serialize.getIdentifier(), serialize);
- builtinFunctions.put(number.getIdentifier(), number);
+ builtinFunctions.put(number0.getIdentifier(), number0);
+ builtinFunctions.put(number1.getIdentifier(), number1);
builtinFunctions.put(encode_for_uri.getIdentifier(), encode_for_uri);
builtinFunctions.put(years_from_duration.getIdentifier(), years_from_duration);
diff --git a/src/main/java/org/rumbledb/runtime/functions/numerics/NumberFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/numerics/NumberFunctionIterator.java
index d51b0637ec..3a17f005b2 100644
--- a/src/main/java/org/rumbledb/runtime/functions/numerics/NumberFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/numerics/NumberFunctionIterator.java
@@ -22,6 +22,7 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
+import org.rumbledb.context.Name;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
@@ -45,6 +46,10 @@ public NumberFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
+ if (this.children.size() == 0) {
+ List
- items = context.getVariableValues().getLocalVariableValue(Name.CONTEXT_ITEM, getMetadata());
+ return CastIterator.castItemToType(items.get(0), BuiltinTypesCatalogue.doubleItem, getMetadata());
+ }
Item anyItem = this.children.get(0).materializeFirstItemOrNull(context);
if (anyItem == null) {
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/NormalizeSpaceFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/NormalizeSpaceFunctionIterator.java
index 69819b1ecf..4426dff4c6 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/NormalizeSpaceFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/NormalizeSpaceFunctionIterator.java
@@ -23,6 +23,7 @@
import org.apache.commons.lang.StringUtils;
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
+import org.rumbledb.context.Name;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
@@ -45,6 +46,11 @@ public NormalizeSpaceFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
+ if (this.children.size() == 0) {
+ List
- items = context.getVariableValues().getLocalVariableValue(Name.CONTEXT_ITEM, getMetadata());
+ return ItemFactory.getInstance()
+ .createStringItem(StringUtils.normalizeSpace(items.get(0).getStringValue()));
+ }
Item stringItem = this.children.get(0)
.materializeFirstItemOrNull(context);
diff --git a/src/main/java/org/rumbledb/runtime/functions/strings/StringLengthFunctionIterator.java b/src/main/java/org/rumbledb/runtime/functions/strings/StringLengthFunctionIterator.java
index 36023d8448..21f2a158a5 100644
--- a/src/main/java/org/rumbledb/runtime/functions/strings/StringLengthFunctionIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/strings/StringLengthFunctionIterator.java
@@ -22,6 +22,7 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
+import org.rumbledb.context.Name;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.ItemFactory;
@@ -44,6 +45,10 @@ public StringLengthFunctionIterator(
@Override
public Item materializeFirstItemOrNull(DynamicContext context) {
+ if (this.children.size() == 0) {
+ List
- items = context.getVariableValues().getLocalVariableValue(Name.CONTEXT_ITEM, getMetadata());
+ return ItemFactory.getInstance().createIntItem(items.get(0).getStringValue().length());
+ }
Item stringItem = this.children.get(0)
.materializeFirstItemOrNull(context);
From 2e24d6c911bca1e6df2cb0e8dbaf9d97049a1c59 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Fri, 25 Jun 2021 09:15:45 +0000
Subject: [PATCH 048/142] Correct prefix from math: to fn:
---
.../context/BuiltinFunctionCatalogue.java | 28 +++++++++----------
.../runtime/FunctionNumerics/FunctionAbs.jq | 2 +-
.../FunctionNumerics/FunctionCeiling.jq | 2 +-
.../runtime/FunctionNumerics/FunctionFloor.jq | 2 +-
.../FunctionNumerics/FunctionRound1.jq | 2 +-
.../FunctionRoundHalfToEven1.jq | 2 +-
6 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index 9f08b349b4..d2b825030f 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -861,8 +861,8 @@ private static BuiltinFunction createBuiltinFunction(
*/
static final BuiltinFunction abs = createBuiltinFunction(
new Name(
- Name.MATH_NS,
- "math",
+ Name.FN_NS,
+ "fn",
"abs"
),
"numeric?",
@@ -875,8 +875,8 @@ private static BuiltinFunction createBuiltinFunction(
*/
static final BuiltinFunction ceiling = createBuiltinFunction(
new Name(
- Name.MATH_NS,
- "math",
+ Name.FN_NS,
+ "fn",
"ceiling"
),
"numeric?",
@@ -889,8 +889,8 @@ private static BuiltinFunction createBuiltinFunction(
*/
static final BuiltinFunction floor = createBuiltinFunction(
new Name(
- Name.MATH_NS,
- "math",
+ Name.FN_NS,
+ "fn",
"floor"
),
"numeric?",
@@ -904,8 +904,8 @@ private static BuiltinFunction createBuiltinFunction(
*/
static final BuiltinFunction round1 = createBuiltinFunction(
new Name(
- Name.MATH_NS,
- "math",
+ Name.FN_NS,
+ "fn",
"round"
),
"numeric?",
@@ -915,8 +915,8 @@ private static BuiltinFunction createBuiltinFunction(
);
static final BuiltinFunction round2 = createBuiltinFunction(
new Name(
- Name.MATH_NS,
- "math",
+ Name.FN_NS,
+ "fn",
"round"
),
"numeric?",
@@ -931,8 +931,8 @@ private static BuiltinFunction createBuiltinFunction(
*/
static final BuiltinFunction round_half_to_even1 = createBuiltinFunction(
new Name(
- Name.MATH_NS,
- "math",
+ Name.FN_NS,
+ "fn",
"round-half-to-even"
),
"double?",
@@ -942,8 +942,8 @@ private static BuiltinFunction createBuiltinFunction(
);
static final BuiltinFunction round_half_to_even2 = createBuiltinFunction(
new Name(
- Name.MATH_NS,
- "math",
+ Name.FN_NS,
+ "fn",
"round-half-to-even"
),
"double?",
diff --git a/src/test/resources/test_files/runtime/FunctionNumerics/FunctionAbs.jq b/src/test/resources/test_files/runtime/FunctionNumerics/FunctionAbs.jq
index 4a11f28d5e..3b63a58930 100644
--- a/src/test/resources/test_files/runtime/FunctionNumerics/FunctionAbs.jq
+++ b/src/test/resources/test_files/runtime/FunctionNumerics/FunctionAbs.jq
@@ -1,4 +1,4 @@
(:JIQS: ShouldRun; Output="(10.5, 10.5)" :)
-math:abs(10.5),
+fn:abs(10.5),
abs(-10.5),
abs(())
diff --git a/src/test/resources/test_files/runtime/FunctionNumerics/FunctionCeiling.jq b/src/test/resources/test_files/runtime/FunctionNumerics/FunctionCeiling.jq
index b2d144888c..ed6a857e33 100644
--- a/src/test/resources/test_files/runtime/FunctionNumerics/FunctionCeiling.jq
+++ b/src/test/resources/test_files/runtime/FunctionNumerics/FunctionCeiling.jq
@@ -1,4 +1,4 @@
(:JIQS: ShouldRun; Output="(11, -10)" :)
-ceiling(10.5),
+fn:ceiling(10.5),
ceiling(-10.5),
ceiling(())
diff --git a/src/test/resources/test_files/runtime/FunctionNumerics/FunctionFloor.jq b/src/test/resources/test_files/runtime/FunctionNumerics/FunctionFloor.jq
index 7148bb3827..03917dfc36 100644
--- a/src/test/resources/test_files/runtime/FunctionNumerics/FunctionFloor.jq
+++ b/src/test/resources/test_files/runtime/FunctionNumerics/FunctionFloor.jq
@@ -1,4 +1,4 @@
(:JIQS: ShouldRun; Output="(10, -11)" :)
-floor(10.5),
+fn:floor(10.5),
floor(-10.5),
floor(())
diff --git a/src/test/resources/test_files/runtime/FunctionNumerics/FunctionRound1.jq b/src/test/resources/test_files/runtime/FunctionNumerics/FunctionRound1.jq
index 48d736cae4..c9ee9082b7 100644
--- a/src/test/resources/test_files/runtime/FunctionNumerics/FunctionRound1.jq
+++ b/src/test/resources/test_files/runtime/FunctionNumerics/FunctionRound1.jq
@@ -1,5 +1,5 @@
(:JIQS: ShouldRun; Output="(3, 2, -3, 1.13, 8500, 3.14, NaN, INF, -INF, 0, -0)" :)
-round(2.5),
+fn:round(2.5),
round(2.4999),
round(-2.5),
round(1.125, 2),
diff --git a/src/test/resources/test_files/runtime/FunctionNumerics/FunctionRoundHalfToEven1.jq b/src/test/resources/test_files/runtime/FunctionNumerics/FunctionRoundHalfToEven1.jq
index 9419507dd1..b76ed4d0d0 100644
--- a/src/test/resources/test_files/runtime/FunctionNumerics/FunctionRoundHalfToEven1.jq
+++ b/src/test/resources/test_files/runtime/FunctionNumerics/FunctionRoundHalfToEven1.jq
@@ -1,5 +1,5 @@
(:JIQS: ShouldRun; Output="(0, 2, 2, 3567.81, 0, 35600)" :)
-round-half-to-even(0.5),
+fn:round-half-to-even(0.5),
round-half-to-even(1.5),
round-half-to-even(2.5),
round-half-to-even(3.567812e+3, 2),
From a7c1b341c6c69d0cbb69fab07230e79f1417b777 Mon Sep 17 00:00:00 2001
From: Pierre Motard
Date: Mon, 28 Jun 2021 13:02:17 +0000
Subject: [PATCH 049/142] Master into master pierre motard
---
docs/RumbleML.md | 38 +-
src/main/java/org/rumbledb/api/Item.java | 18 +
.../compiler/ExecutionModeVisitor.java | 411 +++++++
.../rumbledb/compiler/InferTypeVisitor.java | 1061 +++++++++--------
.../compiler/StaticContextVisitor.java | 230 ++--
.../rumbledb/compiler/TranslationVisitor.java | 18 +-
.../org/rumbledb/compiler/VisitorHelpers.java | 30 +-
.../compiler/XQueryTranslationVisitor.java | 38 +-
.../config/RumbleRuntimeConfiguration.java | 85 +-
.../context/BuiltinFunctionCatalogue.java | 45 +-
.../org/rumbledb/context/InScopeVariable.java | 4 +
src/main/java/org/rumbledb/context/Name.java | 24 +
.../org/rumbledb/context/NamedFunctions.java | 9 +-
.../org/rumbledb/context/StaticContext.java | 59 +-
.../exceptions/ExceptionMetadata.java | 5 +-
.../InvalidRumbleMLParamException.java | 7 +
.../rumbledb/exceptions/RumbleException.java | 4 +
.../UnknownFunctionCallException.java | 14 +
.../org/rumbledb/expressions/Expression.java | 35 +-
.../java/org/rumbledb/expressions/Node.java | 16 +
.../arithmetic/AdditiveExpression.java | 2 +-
.../arithmetic/MultiplicativeExpression.java | 2 +-
.../arithmetic/UnaryExpression.java | 2 +-
.../comparison/ComparisonExpression.java | 2 +-
.../expressions/flowr/FlworExpression.java | 6 -
.../rumbledb/expressions/flowr/ForClause.java | 1 +
.../flowr/GroupByVariableDeclaration.java | 2 +-
.../rumbledb/expressions/flowr/LetClause.java | 11 +-
.../expressions/flowr/ReturnClause.java | 19 -
.../flowr/SimpleMapExpression.java | 2 +-
.../module/VariableDeclaration.java | 8 +-
.../DynamicFunctionCallExpression.java | 31 +-
.../primary/BooleanLiteralExpression.java | 2 +-
.../primary/DecimalLiteralExpression.java | 2 +-
.../primary/DoubleLiteralExpression.java | 2 +-
.../primary/FunctionCallExpression.java | 17 +-
.../primary/InlineFunctionExpression.java | 20 +-
.../primary/IntegerLiteralExpression.java | 2 +-
.../NamedFunctionReferenceExpression.java | 2 +-
.../primary/StringLiteralExpression.java | 2 +-
.../primary/VariableReferenceExpression.java | 17 +-
.../expressions/typing/CastExpression.java | 15 +-
.../typing/CastableExpression.java | 9 +-
.../typing/InstanceOfExpression.java | 9 +-
.../typing/IsStaticallyExpression.java | 8 +-
.../expressions/typing/TreatExpression.java | 9 +-
.../typing/ValidateTypeExpression.java | 15 +-
.../java/org/rumbledb/items/FunctionItem.java | 33 +
.../flwor/clauses/LetClauseSparkIterator.java | 2 +-
.../DynamicFunctionCallIterator.java | 87 +-
.../functions/FunctionItemCallIterator.java | 4 +-
.../org/rumbledb/types/ArrayItemType.java | 19 +-
.../org/rumbledb/types/AtomicItemType.java | 9 +-
.../rumbledb/types/BuiltinTypesCatalogue.java | 301 ++++-
.../rumbledb/types/DerivedAtomicItemType.java | 4 +-
.../org/rumbledb/types/FunctionItemType.java | 15 +-
.../java/org/rumbledb/types/ItemItemType.java | 13 +-
.../java/org/rumbledb/types/ItemType.java | 30 +-
.../org/rumbledb/types/ItemTypeFactory.java | 13 +-
.../org/rumbledb/types/ItemTypeReference.java | 24 +
.../java/org/rumbledb/types/JsonItemType.java | 17 +-
.../org/rumbledb/types/ObjectItemType.java | 17 +-
.../java/org/rumbledb/types/SequenceType.java | 130 +-
.../org/rumbledb/types/UnionItemType.java | 12 +-
.../java/sparksoniq/spark/DataFrameUtils.java | 94 +-
.../sparksoniq/spark/SparkSessionManager.java | 12 +-
.../spark/ml/AnnotateFunctionIterator.java | 14 +-
.../ml/ApplyEstimatorRuntimeIterator.java | 115 +-
.../ml/ApplyTransformerRuntimeIterator.java | 90 +-
.../ml/GetEstimatorFunctionIterator.java | 150 ++-
.../ml/GetTransformerFunctionIterator.java | 160 +--
.../sparksoniq/spark/ml/RumbleMLCatalog.java | 7 +-
.../sparksoniq/spark/ml/RumbleMLUtils.java | 17 +-
.../java/iq/base/AnnotationsTestsBase.java | 3 +-
.../runtime-native-flwor/udt/type4.jq | 7 +
.../runtime-native-flwor/udt/typeError11.jq | 2 +-
.../runtime-native-flwor/udt/typeError12.jq | 2 +-
.../MLAnnotateDF-SchemaError1.jq | 2 +-
.../MLAnnotateDF-SchemaError3.jq | 2 +-
.../MLAnnotateDF-SchemaError4.jq | 2 +-
.../AnnotateFunction/MLAnnotateDF2.jq | 2 +-
.../MLAnnotateForChaining1.jq | 4 +-
.../MLAnnotateForChaining2.jq | 4 +-
.../MLAnnotateForChaining4.jq | 10 +-
.../MLAnnotateForEstimator1.jq | 8 +-
.../MLAnnotateLocal-SchemaError3.jq | 2 +-
.../MLAnnotateRDD-SchemaError3.jq | 2 +-
.../MLEstimator-AFTSurvivalRegression.jq | 6 +-
.../MLEstimator-BisectingKMeans.jq | 6 +-
...MLEstimator-BucketedRandomProjectionLSH.jq | 6 +-
.../MLEstimator-ChiSqSelector.jq | 6 +-
.../MLEstimator-DecisionTreeClassifier.jq | 6 +-
.../MLEstimator-DecisionTreeRegressor.jq | 6 +-
.../MLEstimator-GBTClassifier.jq | 6 +-
.../MLEstimator-GBTRegressor.jq | 6 +-
.../MLEstimator-GaussianMixture.jq | 6 +-
...MLEstimator-GeneralizedLinearRegression.jq | 6 +-
.../EstimatorTests/MLEstimator-IDF.jq | 6 +-
.../MLEstimator-IsotonicRegression.jq | 6 +-
.../EstimatorTests/MLEstimator-KMeans1.jq | 6 +-
.../EstimatorTests/MLEstimator-LDA.jq | 6 +-
.../MLEstimator-LinearRegression.jq | 6 +-
.../EstimatorTests/MLEstimator-LinearSVC.jq | 6 +-
.../MLEstimator-LogisticRegression1.jq | 6 +-
.../MLEstimator-MaxAbsScaler.jq | 6 +-
.../EstimatorTests/MLEstimator-MinHashLSH.jq | 6 +-
.../MLEstimator-MinMaxScaler.jq | 6 +-
...timator-MultilayerPerceptronClassifier2.jq | 6 +-
.../EstimatorTests/MLEstimator-NaiveBayes.jq | 6 +-
.../EstimatorTests/MLEstimator-PCA.jq | 6 +-
.../MLEstimator-RandomForestClassifier.jq | 6 +-
.../MLEstimator-RandomForestRegressor.jq | 6 +-
.../MLEstimator-StandardScaler.jq | 6 +-
.../MLEstimator-VectorIndexer.jq | 6 +-
.../MLFeatureVectorization-Error1.jq | 6 +-
.../MLFeatureVectorization1.jq | 4 +-
.../runtime-spark/RumbleML/MLPipeline1.jq | 29 +
.../runtime-spark/RumbleML/MLPipeline2.jq | 29 +
.../runtime-spark/RumbleML/MLPipeline3.jq | 36 +
.../runtime-spark/RumbleML/MLPipeline4.jq | 29 +
.../runtime-spark/RumbleML/MLPipeline5.jq | 23 +
.../runtime-spark/RumbleML/MLPipeline6.jq | 24 +
...ansformer-DiscreteCosineTransform(DCT)1.jq | 4 +-
.../MLTransformer-Normalizer1.jq | 4 +-
.../MLTransformer-PolynomialExpansion1.jq | 4 +-
.../MLTransformer-Tokenizer2.jq | 20 +
.../MLTransformer-VectorSizeHint1.jq | 4 +-
.../MLTransformer-VectorSlicer1.jq | 4 +-
.../static-typing/postfix/dynamicfunc1.jq | 2 +-
.../static-typing/postfix/dynamicfunc3.jq | 2 +-
130 files changed, 3029 insertions(+), 1168 deletions(-)
create mode 100644 src/main/java/org/rumbledb/compiler/ExecutionModeVisitor.java
create mode 100644 src/test/resources/test_files/runtime-native-flwor/udt/type4.jq
create mode 100644 src/test/resources/test_files/runtime-spark/RumbleML/MLPipeline1.jq
create mode 100644 src/test/resources/test_files/runtime-spark/RumbleML/MLPipeline2.jq
create mode 100644 src/test/resources/test_files/runtime-spark/RumbleML/MLPipeline3.jq
create mode 100644 src/test/resources/test_files/runtime-spark/RumbleML/MLPipeline4.jq
create mode 100644 src/test/resources/test_files/runtime-spark/RumbleML/MLPipeline5.jq
create mode 100644 src/test/resources/test_files/runtime-spark/RumbleML/MLPipeline6.jq
create mode 100644 src/test/resources/test_files/runtime-spark/RumbleML/TransformerTests/MLTransformer-Tokenizer2.jq
diff --git a/docs/RumbleML.md b/docs/RumbleML.md
index 7a44291ebb..f6abb9b09e 100644
--- a/docs/RumbleML.md
+++ b/docs/RumbleML.md
@@ -3,7 +3,7 @@ RumbleML is a Machine Learning library built on top of the Rumble engine that ma
The machine learning capabilities are exposed through JSONiq function items. The concepts of "estimator" and "transformer", which are core to Machine Learning, are naturally function items and fit seamlessly in the JSONiq data model.
-Training sets, test sets, and validation sets, which containing features and labels, are exposed through JSONiq sequences of object items: the keys of these objects are the features and labels.
+Training sets, test sets, and validation sets, which contain features and labels, are exposed through JSONiq sequences of object items: the keys of these objects are the features and labels.
The names of the estimators and of the transformers, as well as the functionality they encapsulate, are directly inherited from the [SparkML](https://spark.apache.org/docs/latest/ml-guide.html) library which RumbleML is based on: we chose not to reinvent the wheel.
@@ -19,7 +19,7 @@ It is an abstraction that either performs a feature transformation or generates
## Estimators
-An **estimator** is a function item that maps a sequence of objects to a transformer (yes, you got it right: that's a function item. This is why they are also called higher-order functions!).
+An **estimator** is a function item that maps a sequence of objects to a transformer (yes, you got it right: that's a function item returned by a function item. This is why they are also called higher-order functions!).
Estimators abstract the concept of a Machine Learning algorithm or any algorithm that fits or trains on data. For example, a learning algorithm such as _KMeans_ is implemented as an Estimator. Calling this estimator on data essentially trains a KMeansModel, which is a Model and hence a Transformer.
@@ -29,19 +29,30 @@ Transformers and estimators are function items in the Rumble Data Model. Their f
## Type Annotations
-RumbleML works on highly structured data, because it requires full type information for all the fields in the training set or test set. While it is on our development plan to automate the detection of these types when the sequence of objects gets created in the fly, Rumble does not support a full object type system yet. Thus, the annotate() function has been introduced as a temporary remedy which facilitates the manual annotation of data against a schema for structured data. This annotation operation is required to be applied on any dataset that must be used as input to RumbleML, but it is superfluous if the data was directly read from a structured input format such as Parquet, CSV, Avro, SVM or ROOT.
+RumbleML works on highly structured data, because it requires full type information for all the fields in the training set or test set. It is on our development plan to automate the detection of these types when the sequence of objects gets created in the fly.
+
+Rumble supports a user-defined type system with which you can validate and annotate datasets against a JSound schema.
+
+This annotation is required to be applied on any dataset that must be used as input to RumbleML, but it is superfluous if the data was directly read from a structured input format such as Parquet, CSV, Avro, SVM or ROOT.
## Examples
- Tokenizer Example:
```
+
+declare type local:id-and-sentence as {
+ "id": "integer",
+ "sentence": "string"
+};
+
+
let $local-data := (
{"id": 1, "sentence": "Hi I heard about Spark"},
{"id": 2, "sentence": "I wish Java could use case classes"},
{"id": 3, "sentence": "Logistic regression models are neat"}
)
-let $df-data := annotate($local-data, {"id": "integer", "sentence": "string"})
+let $df-data := validate type local:id-and-sentence* { $local-data }
let $transformer := get-transformer("Tokenizer")
for $i in $transformer(
@@ -58,6 +69,18 @@ return $i
- KMeans Example:
```
+declare type local:col-1-2-3 as {
+ "id": "integer",
+ "col1": "decimal",
+ "col2": "decimal",
+ "col3": "decimal"
+};
+
+let $vector-assembler := get-transformer("VectorAssembler")(
+ ?,
+ { "inputCols" : [ "col1", "col2", "col3" ], "outputCol" : "features" }
+)
+
let $local-data := (
{"id": 0, "col1": 0.0, "col2": 0.0, "col3": 0.0},
{"id": 1, "col1": 0.1, "col2": 0.1, "col3": 0.1},
@@ -66,17 +89,18 @@ let $local-data := (
{"id": 4, "col1": 9.1, "col2": 9.1, "col3": 9.1},
{"id": 5, "col1": 9.2, "col2": 9.2, "col3": 9.2}
)
-let $df-data := annotate($local-data, {"id": "integer", "col1": "decimal", "col2": "decimal", "col3": "decimal"})
+let $df-data := validate type local:col-1-2-3* {$local-data }
+let $df-data := $vector-assembler($df-data)
let $est := get-estimator("KMeans")
let $tra := $est(
$df-data,
- {"featuresCol": ["col1", "col2", "col3"]}
+ {"featuresCol": "features"}
)
for $i in $tra(
$df-data,
- {"featuresCol": ["col1", "col2", "col3"]}
+ {"featuresCol": "features"}
)
return $i
diff --git a/src/main/java/org/rumbledb/api/Item.java b/src/main/java/org/rumbledb/api/Item.java
index 01d5f3f270..2169d3b562 100644
--- a/src/main/java/org/rumbledb/api/Item.java
+++ b/src/main/java/org/rumbledb/api/Item.java
@@ -7,6 +7,8 @@
import java.util.Map;
import org.apache.spark.api.java.JavaRDD;
+import org.apache.spark.ml.Estimator;
+import org.apache.spark.ml.Transformer;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.rumbledb.context.DynamicContext;
@@ -599,4 +601,20 @@ default int castToIntValue() {
default NativeClauseContext generateNativeQuery(NativeClauseContext context) {
return NativeClauseContext.NoNativeQuery;
}
+
+ default boolean isEstimator() {
+ return false;
+ }
+
+ default Estimator> getEstimator() {
+ throw new UnsupportedOperationException("Operation not defined for type " + this.getDynamicType());
+ }
+
+ default boolean isTransformer() {
+ return false;
+ }
+
+ default Transformer getTransformer() {
+ throw new UnsupportedOperationException("Operation not defined for type " + this.getDynamicType());
+ }
}
diff --git a/src/main/java/org/rumbledb/compiler/ExecutionModeVisitor.java b/src/main/java/org/rumbledb/compiler/ExecutionModeVisitor.java
new file mode 100644
index 0000000000..e85c34979c
--- /dev/null
+++ b/src/main/java/org/rumbledb/compiler/ExecutionModeVisitor.java
@@ -0,0 +1,411 @@
+/*
+ * 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.
+ *
+ * Authors: Stefan Irimescu, Can Berker Cikis
+ *
+ */
+
+package org.rumbledb.compiler;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+
+import org.rumbledb.context.BuiltinFunctionCatalogue;
+import org.rumbledb.context.FunctionIdentifier;
+import org.rumbledb.context.InScopeVariable;
+import org.rumbledb.context.Name;
+import org.rumbledb.context.StaticContext;
+import org.rumbledb.expressions.AbstractNodeVisitor;
+import org.rumbledb.expressions.ExecutionMode;
+import org.rumbledb.expressions.Expression;
+import org.rumbledb.expressions.Node;
+import org.rumbledb.expressions.control.TypeSwitchExpression;
+import org.rumbledb.expressions.control.TypeswitchCase;
+import org.rumbledb.expressions.flowr.Clause;
+import org.rumbledb.expressions.flowr.CountClause;
+import org.rumbledb.expressions.flowr.FlworExpression;
+import org.rumbledb.expressions.flowr.GroupByVariableDeclaration;
+import org.rumbledb.expressions.flowr.ForClause;
+import org.rumbledb.expressions.flowr.GroupByClause;
+import org.rumbledb.expressions.flowr.LetClause;
+import org.rumbledb.expressions.flowr.ReturnClause;
+import org.rumbledb.expressions.module.FunctionDeclaration;
+import org.rumbledb.expressions.module.LibraryModule;
+import org.rumbledb.expressions.module.MainModule;
+import org.rumbledb.expressions.module.Prolog;
+import org.rumbledb.expressions.module.VariableDeclaration;
+import org.rumbledb.expressions.primary.FunctionCallExpression;
+import org.rumbledb.expressions.primary.InlineFunctionExpression;
+import org.rumbledb.expressions.primary.VariableReferenceExpression;
+import org.rumbledb.types.SequenceType;
+import org.rumbledb.types.SequenceType.Arity;
+
+/**
+ * Static context visitor implements a multi-pass algorithm that enables function hoisting
+ */
+public class ExecutionModeVisitor extends AbstractNodeVisitor {
+
+ private VisitorConfig visitorConfig;
+
+ ExecutionModeVisitor() {
+ this.visitorConfig = VisitorConfig.staticContextVisitorInitialPassConfig;
+ }
+
+ void setVisitorConfig(VisitorConfig visitorConfig) {
+ this.visitorConfig = visitorConfig;
+ }
+
+ @Override
+ protected StaticContext defaultAction(Node node, StaticContext argument) {
+ visitDescendants(node, argument);
+ node.initHighestExecutionMode(this.visitorConfig);
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitMainModule(MainModule mainModule, StaticContext argument) {
+ visitDescendants(mainModule, mainModule.getStaticContext());
+ mainModule.initHighestExecutionMode(this.visitorConfig);
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitLibraryModule(LibraryModule libraryModule, StaticContext argument) {
+ if (libraryModule.getProlog() != null) {
+ libraryModule.getProlog().initHighestExecutionMode(this.visitorConfig);
+ this.visit(libraryModule.getProlog(), libraryModule.getStaticContext());
+ }
+ libraryModule.initHighestExecutionMode(this.visitorConfig);
+ return argument;
+ }
+
+ // region primary
+ @Override
+ public StaticContext visitVariableReference(VariableReferenceExpression expression, StaticContext argument) {
+ if (expression.alwaysReturnsAtMostOneItem()) {
+ expression.setHighestExecutionMode(ExecutionMode.LOCAL);
+ return argument;
+ }
+ Name variableName = expression.getVariableName();
+ ExecutionMode mode = expression.getStaticContext().getVariableStorageMode(variableName);
+ if (this.visitorConfig.setUnsetToLocal() && mode.equals(ExecutionMode.UNSET)) {
+ if (
+ expression.getStaticSequenceType().getArity().equals(Arity.OneOrMore)
+ ||
+ expression.getStaticSequenceType().getArity().equals(Arity.ZeroOrMore)
+ ) {
+ if (expression.getStaticSequenceType().getItemType().isObjectItemType()) {
+ System.err.println(
+ "[WARNING] Forcing execution mode of variable "
+ + expression.getVariableName()
+ + " to DataFrame based on static object* type."
+ );
+ expression.setHighestExecutionMode(ExecutionMode.DATAFRAME);
+ return argument;
+ }
+ }
+ System.err.println(
+ "[WARNING] Forcing execution mode of variable " + expression.getVariableName() + " to local."
+ );
+ expression.setHighestExecutionMode(ExecutionMode.LOCAL);
+ return argument;
+ }
+ expression.setHighestExecutionMode(mode);
+ return argument;
+ }
+
+ private void populateFunctionDeclarationStaticContext(
+ StaticContext functionDeclarationContext,
+ List modes,
+ InlineFunctionExpression expression
+ ) {
+ int i = 0;
+ for (Name name : expression.getParams().keySet()) {
+ ExecutionMode mode = modes.get(i);
+ SequenceType type = expression.getParams().get(name);
+ if (type.isEmptySequence()) {
+ mode = ExecutionMode.LOCAL;
+ } else if (type.getArity().equals(Arity.OneOrZero) || type.getArity().equals(Arity.One)) {
+ mode = ExecutionMode.LOCAL;
+ }
+ functionDeclarationContext.setVariableStorageMode(
+ name,
+ mode
+ );
+ ++i;
+ }
+ }
+
+ @Override
+ public StaticContext visitFunctionDeclaration(FunctionDeclaration declaration, StaticContext argument) {
+ InlineFunctionExpression expression = (InlineFunctionExpression) declaration.getExpression();
+ // define a static context for the function body, add params to the context and visit the body expression
+ List modes = expression.getStaticContext()
+ .getUserDefinedFunctionsExecutionModes()
+ .getParameterExecutionMode(
+ expression.getFunctionIdentifier(),
+ expression.getMetadata()
+ );
+ populateFunctionDeclarationStaticContext(expression.getStaticContext(), modes, expression);
+ // visit the body first to make its execution mode available while adding the function to the catalog
+ this.visit(expression.getBody(), expression.getStaticContext());
+ expression.initHighestExecutionMode(this.visitorConfig);
+ declaration.initHighestExecutionMode(this.visitorConfig);
+ expression.registerUserDefinedFunctionExecutionMode(
+ this.visitorConfig
+ );
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitInlineFunctionExpr(InlineFunctionExpression expression, StaticContext argument) {
+ // define a static context for the function body, add params to the context and visit the body expression
+ expression.getParams()
+ .forEach(
+ (paramName, sequenceType) -> expression.getBody()
+ .getStaticContext()
+ .setVariableStorageMode(
+ paramName,
+ ExecutionMode.LOCAL
+ )
+ );
+ // visit the body first to make its execution mode available while adding the function to the catalog
+ this.visit(expression.getBody(), expression.getBody().getStaticContext());
+ expression.initHighestExecutionMode(this.visitorConfig);
+ expression.registerUserDefinedFunctionExecutionMode(
+ this.visitorConfig
+ );
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitFunctionCall(FunctionCallExpression expression, StaticContext argument) {
+ visitDescendants(expression, expression.getStaticContext());
+ FunctionIdentifier identifier = expression.getFunctionIdentifier();
+ if (!BuiltinFunctionCatalogue.exists(identifier)) {
+ List modes = new ArrayList<>();
+ for (Expression parameter : expression.getArguments()) {
+ if (parameter == null) {
+ // This is for a partial application, for ? arguments.
+ // We do not modify the current mode for this parameter.
+ modes.add(ExecutionMode.UNSET);
+ } else {
+ modes.add(parameter.getHighestExecutionMode(this.visitorConfig));
+ }
+ }
+ expression.getStaticContext()
+ .getUserDefinedFunctionsExecutionModes()
+ .setParameterExecutionMode(
+ identifier,
+ modes,
+ expression.getMetadata()
+ );
+ }
+ expression.initFunctionCallHighestExecutionMode(this.visitorConfig);
+ return argument;
+ }
+ // endregion
+
+ @Override
+ public StaticContext visitReturnClause(ReturnClause expression, StaticContext argument) {
+ System.err.println(expression.getStaticContext());
+ visitDescendants(expression, expression.getStaticContext());
+ if (expression.getPreviousClause().getHighestExecutionMode(this.visitorConfig).isDataFrame()) {
+ expression.setHighestExecutionMode(ExecutionMode.RDD);
+ return argument;
+ }
+ if (expression.getReturnExpr().getHighestExecutionMode(this.visitorConfig).isRDD()) {
+ expression.setHighestExecutionMode(ExecutionMode.RDD);
+ return argument;
+ }
+ if (expression.getReturnExpr().getHighestExecutionMode(this.visitorConfig).isDataFrame()) {
+ expression.setHighestExecutionMode(ExecutionMode.DATAFRAME);
+ return argument;
+ }
+ if (expression.getReturnExpr().getHighestExecutionMode(this.visitorConfig).isUnset()) {
+ expression.setHighestExecutionMode(ExecutionMode.UNSET);
+ return argument;
+ }
+ if (expression.getPreviousClause().getHighestExecutionMode(this.visitorConfig).isUnset()) {
+ expression.setHighestExecutionMode(ExecutionMode.UNSET);
+ return argument;
+ }
+ expression.setHighestExecutionMode(ExecutionMode.LOCAL);
+ return argument;
+ }
+
+ // region FLWOR
+ @Override
+ public StaticContext visitFlowrExpression(FlworExpression expression, StaticContext argument) {
+ Clause clause = expression.getReturnClause().getFirstClause();
+ while (clause != null) {
+ if (clause.getNextClause() != null) {
+ this.visit(clause, clause.getNextClause().getStaticContext());
+ } else {
+ this.visit(clause, null);
+ }
+ clause = clause.getNextClause();
+ }
+ if (expression.alwaysReturnsAtMostOneItem()) {
+ expression.setHighestExecutionMode(ExecutionMode.LOCAL);
+ } else {
+ expression.setHighestExecutionMode(
+ expression.getReturnClause().getHighestExecutionMode(this.visitorConfig)
+ );
+ }
+ return argument;
+ }
+
+ // region FLWOR vars
+ @Override
+ public StaticContext visitForClause(ForClause clause, StaticContext argument) {
+ this.visit(clause.getExpression(), clause.getExpression().getStaticContext());
+ clause.initHighestExecutionMode(this.visitorConfig);
+
+ argument.setVariableStorageMode(
+ clause.getVariableName(),
+ clause.getVariableHighestStorageMode(this.visitorConfig)
+ );
+
+ if (clause.getPositionalVariableName() != null) {
+ argument.setVariableStorageMode(
+ clause.getPositionalVariableName(),
+ ExecutionMode.LOCAL
+ );
+ }
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitLetClause(LetClause clause, StaticContext argument) {
+ this.visit(clause.getExpression(), clause.getExpression().getStaticContext());
+ clause.initHighestExecutionMode(this.visitorConfig);
+
+ argument.setVariableStorageMode(
+ clause.getVariableName(),
+ clause.getVariableHighestStorageMode(this.visitorConfig)
+ );
+
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitGroupByClause(GroupByClause clause, StaticContext argument) {
+ for (GroupByVariableDeclaration variable : clause.getGroupVariables()) {
+ if (variable.getExpression() != null) {
+ // if a variable declaration takes place
+ this.visit(variable.getExpression(), null);
+ argument.setVariableStorageMode(
+ variable.getVariableName(),
+ ExecutionMode.LOCAL
+ );
+ }
+ }
+ clause.initHighestExecutionMode(this.visitorConfig);
+ StaticContext clauseContext = clause.getStaticContext();
+ for (Entry entry : argument.getInScopeVariables().entrySet()) {
+ boolean isKeyVariable = false;
+ for (GroupByVariableDeclaration variable : clause.getGroupVariables()) {
+ if (variable.getExpression() != null) {
+ if (entry.getKey().equals(variable.getVariableName())) {
+ isKeyVariable = true;
+ }
+ }
+ }
+ if (isKeyVariable) {
+ continue;
+ }
+ argument.setVariableStorageMode(
+ entry.getKey(),
+ clauseContext.getVariableStorageMode(entry.getKey())
+ );
+ }
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitCountClause(CountClause expression, StaticContext argument) {
+ expression.initHighestExecutionMode(this.visitorConfig);
+ argument.setVariableStorageMode(
+ expression.getCountVariable().getVariableName(),
+ ExecutionMode.LOCAL
+ );
+ this.visit(expression.getCountVariable(), expression.getCountVariable().getStaticContext());
+ return argument;
+ }
+
+ // endregion
+
+ // region control
+ @Override
+ public StaticContext visitTypeSwitchExpression(TypeSwitchExpression expression, StaticContext argument) {
+ this.visit(expression.getTestCondition(), null);
+ for (TypeswitchCase c : expression.getCases()) {
+ Name variableName = c.getVariableName();
+ if (variableName != null) {
+ c.getReturnExpression()
+ .getStaticContext()
+ .setVariableStorageMode(
+ variableName,
+ ExecutionMode.LOCAL
+ );
+ }
+ this.visit(c.getReturnExpression(), c.getReturnExpression().getStaticContext());
+ }
+
+ Name defaultCaseVariableName = expression.getDefaultCase().getVariableName();
+ if (defaultCaseVariableName == null) {
+ this.visit(expression.getDefaultCase().getReturnExpression(), null);
+ } else {
+ // add variable to child context to visit default return expression
+ expression.getDefaultCase()
+ .getReturnExpression()
+ .getStaticContext()
+ .setVariableStorageMode(
+ defaultCaseVariableName,
+ ExecutionMode.LOCAL
+ );
+ this.visit(expression.getDefaultCase().getReturnExpression(), null);
+ }
+ expression.initHighestExecutionMode(this.visitorConfig);
+ // return the given context unchanged as defined variables go out of scope
+ return argument;
+ }
+ // endregion
+
+ @Override
+ public StaticContext visitVariableDeclaration(VariableDeclaration variableDeclaration, StaticContext argument) {
+ if (variableDeclaration.getExpression() != null) {
+ this.visit(variableDeclaration.getExpression(), null);
+ }
+ variableDeclaration.initHighestExecutionMode(this.visitorConfig);
+ // first pass.
+ argument.setVariableStorageMode(
+ variableDeclaration.getVariableName(),
+ variableDeclaration.getVariableHighestStorageMode(this.visitorConfig)
+ );
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitProlog(Prolog prolog, StaticContext argument) {
+ visitDescendants(prolog, argument);
+ prolog.initHighestExecutionMode(this.visitorConfig);
+ return argument;
+ }
+
+}
diff --git a/src/main/java/org/rumbledb/compiler/InferTypeVisitor.java b/src/main/java/org/rumbledb/compiler/InferTypeVisitor.java
index 08c165e191..9fb3b23218 100644
--- a/src/main/java/org/rumbledb/compiler/InferTypeVisitor.java
+++ b/src/main/java/org/rumbledb/compiler/InferTypeVisitor.java
@@ -7,7 +7,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.stream.Collectors;
import org.apache.spark.sql.AnalysisException;
import org.apache.spark.sql.types.StructType;
@@ -23,6 +22,7 @@
import org.rumbledb.exceptions.IsStaticallyUnexpectedTypeException;
import org.rumbledb.exceptions.OurBadException;
import org.rumbledb.exceptions.UnexpectedStaticTypeException;
+import org.rumbledb.exceptions.UnknownFunctionCallException;
import org.rumbledb.expressions.AbstractNodeVisitor;
import org.rumbledb.expressions.CommaExpression;
import org.rumbledb.expressions.Expression;
@@ -54,6 +54,9 @@
import org.rumbledb.expressions.miscellaneous.RangeExpression;
import org.rumbledb.expressions.miscellaneous.StringConcatExpression;
import org.rumbledb.expressions.module.FunctionDeclaration;
+import org.rumbledb.expressions.module.LibraryModule;
+import org.rumbledb.expressions.module.MainModule;
+import org.rumbledb.expressions.module.Prolog;
import org.rumbledb.expressions.module.VariableDeclaration;
import org.rumbledb.expressions.postfix.ArrayLookupExpression;
import org.rumbledb.expressions.postfix.ArrayUnboxingExpression;
@@ -78,6 +81,7 @@
import org.rumbledb.expressions.typing.InstanceOfExpression;
import org.rumbledb.expressions.typing.IsStaticallyExpression;
import org.rumbledb.expressions.typing.TreatExpression;
+import org.rumbledb.expressions.typing.ValidateTypeExpression;
import org.rumbledb.runtime.functions.input.FileSystemUtil;
import org.rumbledb.types.BuiltinTypesCatalogue;
import org.rumbledb.types.FieldDescriptor;
@@ -105,6 +109,34 @@ public class InferTypeVisitor extends AbstractNodeVisitor {
this.rumbleRuntimeConfiguration = rumbleRuntimeConfiguration;
}
+ private void throwStaticTypeException(String message, ErrorCode code) {
+ if (this.rumbleRuntimeConfiguration.doStaticAnalysis()) {
+ throw new UnexpectedStaticTypeException(
+ message,
+ code
+ );
+ }
+ }
+
+ private void throwStaticTypeException(String message, ExceptionMetadata metadata) {
+ if (this.rumbleRuntimeConfiguration.doStaticAnalysis()) {
+ throw new UnexpectedStaticTypeException(
+ message,
+ metadata
+ );
+ }
+ }
+
+ private void throwStaticTypeException(String message, ErrorCode code, ExceptionMetadata metadata) {
+ if (this.rumbleRuntimeConfiguration.doStaticAnalysis()) {
+ throw new UnexpectedStaticTypeException(
+ message,
+ code,
+ metadata
+ );
+ }
+ }
+
/**
* Perform basic checks on a list of SequenceType, available checks are for null (OurBad exception) and inferred the
* empty sequence (XPST0005)
@@ -131,11 +163,11 @@ private void basicChecks(
if (inferredEmptyCheck) {
for (SequenceType type : types) {
if (type.isEmptySequence()) {
- throw new UnexpectedStaticTypeException(
- "Inferred type for "
- + nodeName
- + " is empty sequence (with active static typing feature, only allowed for CommaExpression)",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression
+ throwStaticTypeException(
+ "Inferred type for "
+ + nodeName
+ + " is empty sequence (with active static typing feature, only allowed for CommaExpression)",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression
);
}
}
@@ -164,12 +196,12 @@ private void basicChecks(
}
}
if (inferredEmptyCheck) {
- if (type.isEmptySequence()) {
- throw new UnexpectedStaticTypeException(
- "Inferred type for "
- + nodeName
- + " is empty sequence (with active static typing feature, only allowed for CommaExpression)",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression
+ if (type != null && type.isEmptySequence()) {
+ throwStaticTypeException(
+ "Inferred type for "
+ + nodeName
+ + " is empty sequence (with active static typing feature, only allowed for CommaExpression)",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression
);
}
}
@@ -182,13 +214,13 @@ public StaticContext visitCommaExpression(CommaExpression expression, StaticCont
SequenceType inferredType = SequenceType.EMPTY_SEQUENCE;
for (Expression childExpression : expression.getExpressions()) {
- SequenceType childExpressionInferredType = childExpression.getInferredSequenceType();
+ SequenceType childExpressionInferredType = childExpression.getStaticSequenceType();
// if a child expression has no inferred type throw an error
if (childExpressionInferredType == null) {
- throw new UnexpectedStaticTypeException(
- "A child expression of a CommaExpression has no inferred type",
- expression.getMetadata()
+ throwStaticTypeException(
+ "A child expression of a CommaExpression has no inferred type",
+ expression.getMetadata()
);
}
@@ -212,8 +244,7 @@ public StaticContext visitCommaExpression(CommaExpression expression, StaticCont
}
}
- System.out.println("visited comma expression with inferred type: " + inferredType);
- expression.setInferredSequenceType(inferredType);
+ expression.setStaticSequenceType(inferredType);
return argument;
}
@@ -221,43 +252,37 @@ public StaticContext visitCommaExpression(CommaExpression expression, StaticCont
@Override
public StaticContext visitString(StringLiteralExpression expression, StaticContext argument) {
- System.out.println("visiting String literal");
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.stringItem));
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.stringItem));
return argument;
}
@Override
public StaticContext visitInteger(IntegerLiteralExpression expression, StaticContext argument) {
- System.out.println("visiting Int literal");
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.integerItem));
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.integerItem));
return argument;
}
@Override
public StaticContext visitDouble(DoubleLiteralExpression expression, StaticContext argument) {
- System.out.println("visiting Double literal");
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.doubleItem));
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.doubleItem));
return argument;
}
@Override
public StaticContext visitDecimal(DecimalLiteralExpression expression, StaticContext argument) {
- System.out.println("visiting Decimal literal");
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.decimalItem));
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.decimalItem));
return argument;
}
@Override
public StaticContext visitNull(NullLiteralExpression expression, StaticContext argument) {
- System.out.println("visiting Null literal");
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.nullItem));
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.nullItem));
return argument;
}
@Override
public StaticContext visitBoolean(BooleanLiteralExpression expression, StaticContext argument) {
- System.out.println("visiting Boolean literal");
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.booleanItem));
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.booleanItem));
return argument;
}
@@ -266,66 +291,68 @@ public StaticContext visitVariableReference(VariableReferenceExpression expressi
SequenceType variableType = expression.getActualType();
if (variableType == null) {
// if is null, no 'as [SequenceType]' part was present in the declaration, therefore we infer it
- System.out.println("variable reference type was null so we infer it");
variableType = expression.getStaticContext().getVariableSequenceType(expression.getVariableName());
// we also set variableReference type
- expression.setType(variableType);
+ if (variableType == null) {
+ System.err.println(
+ "pWARNING] Variable reference type was null so we infer it. Please let us know as we would like to look into it."
+ );
+ variableType = SequenceType.ITEM_STAR;
+ }
+ expression.setActualType(variableType);
}
basicChecks(variableType, expression.getClass().getSimpleName(), false, true, expression.getMetadata());
- System.out.println("visiting variable reference with type: " + variableType);
- expression.setInferredSequenceType(variableType);
+ expression.setStaticSequenceType(variableType);
return argument;
}
@Override
public StaticContext visitArrayConstructor(ArrayConstructorExpression expression, StaticContext argument) {
- System.out.println("visiting Array constructor literal");
visitDescendants(expression, argument);
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.arrayItem));
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.arrayItem));
return argument;
}
@Override
public StaticContext visitObjectConstructor(ObjectConstructorExpression expression, StaticContext argument) {
- System.out.println("visiting Object constructor literal");
visitDescendants(expression, argument);
if (expression.isMergedConstructor()) {
// if it is a merged constructor the child must be a subtype of object* inferred type
- SequenceType childSequenceType = ((Expression) expression.getChildren().get(0)).getInferredSequenceType();
+ SequenceType childSequenceType = ((Expression) expression.getChildren().get(0)).getStaticSequenceType();
if (childSequenceType == null) {
- throw new UnexpectedStaticTypeException(
- "The child expression has no inferred type",
- expression.getMetadata()
+ throwStaticTypeException(
+ "The child expression has no inferred type",
+ expression.getMetadata()
);
}
if (!childSequenceType.isSubtypeOf(SequenceType.createSequenceType("object*"))) {
- throw new UnexpectedStaticTypeException(
- "The child expression must have object* sequence type, instead found: " + childSequenceType,
- expression.getMetadata()
+ throwStaticTypeException(
+ "The child expression must have object* sequence type, instead found: " + childSequenceType,
+ expression.getMetadata()
);
}
} else {
for (Expression keyExpression : expression.getKeys()) {
- SequenceType keySequenceType = keyExpression.getInferredSequenceType();
+ SequenceType keySequenceType = keyExpression.getStaticSequenceType();
if (keySequenceType == null) {
- throw new UnexpectedStaticTypeException(
- "One of the key in the object constructor has no inferred type",
- expression.getMetadata()
+ throwStaticTypeException(
+ "One of the key in the object constructor has no inferred type",
+ expression.getMetadata()
);
}
if (
!keySequenceType.isSubtypeOf(SequenceType.createSequenceType("string"))
&& !keySequenceType.isSubtypeOf(SequenceType.createSequenceType("anyURI"))
) {
- throw new UnexpectedStaticTypeException(
- "The inferred static sequence types for the keys of an Object must be a subtype of string or anyURI, instead found a: "
- + keySequenceType,
- expression.getMetadata()
+ throwStaticTypeException(
+ "The inferred static sequence types for the keys of an Object must be a subtype of string or anyURI, instead found a: "
+ + keySequenceType,
+ expression.getMetadata()
);
}
}
}
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.objectItem));
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.objectItem));
return argument;
}
@@ -335,8 +362,7 @@ public StaticContext visitContextExpr(ContextItemExpression expression, StaticCo
if (contextType == null) {
contextType = new SequenceType(BuiltinTypesCatalogue.item);
}
- expression.setInferredSequenceType(contextType);
- System.out.println("Visited context expression, set type: " + contextType);
+ expression.setStaticSequenceType(contextType);
return argument;
}
@@ -345,28 +371,23 @@ public StaticContext visitInlineFunctionExpr(InlineFunctionExpression expression
visitDescendants(expression, argument);
SequenceType returnType = expression.getActualReturnType();
if (returnType == null) {
- returnType = expression.getBody().getInferredSequenceType();
+ returnType = expression.getBody().getStaticSequenceType();
}
List params = new ArrayList<>(expression.getParams().values());
FunctionSignature signature = new FunctionSignature(params, returnType);
- expression.setInferredSequenceType(new SequenceType(ItemTypeFactory.createFunctionItemType(signature)));
- System.out.println("Visited inline function expression");
+ expression.setStaticSequenceType(new SequenceType(ItemTypeFactory.createFunctionItemType(signature)));
return argument;
}
private FunctionSignature getSignature(FunctionIdentifier identifier, StaticContext staticContext) {
BuiltinFunction function = null;
FunctionSignature signature = null;
- try {
- function = BuiltinFunctionCatalogue.getBuiltinFunction(identifier);
- } catch (OurBadException exception) {
- signature = staticContext.getFunctionSignature(identifier);
- }
-
+ function = BuiltinFunctionCatalogue.getBuiltinFunction(identifier);
if (function != null) {
signature = function.getSignature();
+ } else {
+ signature = staticContext.getFunctionSignature(identifier);
}
-
return signature;
}
@@ -374,10 +395,16 @@ private FunctionSignature getSignature(FunctionIdentifier identifier, StaticCont
public StaticContext visitNamedFunctionRef(NamedFunctionReferenceExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
- FunctionSignature signature = getSignature(expression.getIdentifier(), expression.getStaticContext());
-
- expression.setInferredSequenceType(new SequenceType(ItemTypeFactory.createFunctionItemType(signature)));
- System.out.println("Visited named function expression");
+ try {
+ FunctionSignature signature = getSignature(expression.getIdentifier(), expression.getStaticContext());
+ expression.setStaticSequenceType(new SequenceType(ItemTypeFactory.createFunctionItemType(signature)));
+ } catch (UnknownFunctionCallException e) {
+ throw new UnknownFunctionCallException(
+ expression.getIdentifier().getName(),
+ expression.getIdentifier().getArity(),
+ expression.getMetadata()
+ );
+ }
return argument;
}
@@ -409,9 +436,8 @@ private boolean tryAnnotateSpecificFunctions(FunctionCallExpression expression,
.parquet(uri.toString())
.schema();
ItemType schemaItemType = ItemTypeFactory.createItemType(s);
- System.out.println(schemaItemType.toString());
// TODO : check if arity is correct
- expression.setInferredSequenceType(new SequenceType(schemaItemType, SequenceType.Arity.ZeroOrMore));
+ expression.setStaticSequenceType(new SequenceType(schemaItemType, SequenceType.Arity.ZeroOrMore));
return true;
} catch (Exception e) {
if (e instanceof AnalysisException) {
@@ -424,7 +450,7 @@ private boolean tryAnnotateSpecificFunctions(FunctionCallExpression expression,
// handle 'round' function
if (functionName.equals(Name.createVariableInDefaultFunctionNamespace("round"))) {
// set output type to the same of the first argument (special handling of numeric)
- expression.setInferredSequenceType(args.get(0).getInferredSequenceType());
+ expression.setStaticSequenceType(args.get(0).getStaticSequenceType());
return true;
}
@@ -434,9 +460,12 @@ private boolean tryAnnotateSpecificFunctions(FunctionCallExpression expression,
@Override
public StaticContext visitFunctionCall(FunctionCallExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
-
- FunctionSignature signature = getSignature(expression.getFunctionIdentifier(), expression.getStaticContext());
-
+ FunctionSignature signature = null;
+ try {
+ signature = getSignature(expression.getFunctionIdentifier(), expression.getStaticContext());
+ } catch (UnknownFunctionCallException e) {
+ throw new UnknownFunctionCallException(expression.getFunctionIdentifier(), expression.getMetadata());
+ }
List parameterExpressions = expression.getArguments();
List parameterTypes = signature.getParameterTypes();
List partialParams = new ArrayList<>();
@@ -445,13 +474,16 @@ public StaticContext visitFunctionCall(FunctionCallExpression expression, Static
// check arguments are of correct type
for (int i = 0; i < paramsLength; ++i) {
if (parameterExpressions.get(i) != null) {
- SequenceType actualType = parameterExpressions.get(i).getInferredSequenceType();
+ SequenceType actualType = parameterExpressions.get(i).getStaticSequenceType();
+ if (actualType == null) {
+ throw new OurBadException("No static type inferred for expression " + parameterExpressions.get(i));
+ }
SequenceType expectedType = parameterTypes.get(i);
// check actual parameters is either a subtype of or can be promoted to expected type
if (!actualType.isSubtypeOfOrCanBePromotedTo(expectedType)) {
- throw new UnexpectedStaticTypeException(
- "Argument " + i + " requires " + expectedType + " but " + actualType + " was found",
- expression.getMetadata()
+ throwStaticTypeException(
+ "Argument " + i + " requires " + expectedType + " but " + actualType + " was found",
+ expression.getMetadata()
);
}
} else {
@@ -461,7 +493,7 @@ public StaticContext visitFunctionCall(FunctionCallExpression expression, Static
if (expression.isPartialApplication()) {
FunctionSignature partialSignature = new FunctionSignature(partialParams, signature.getReturnType());
- expression.setInferredSequenceType(
+ expression.setStaticSequenceType(
new SequenceType(ItemTypeFactory.createFunctionItemType(partialSignature))
);
} else {
@@ -470,13 +502,12 @@ public StaticContext visitFunctionCall(FunctionCallExpression expression, Static
// we did not annotate a specific function, therefore we use default return type
SequenceType returnType = signature.getReturnType();
if (returnType == null) {
- returnType = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ returnType = SequenceType.ITEM_STAR;
}
- expression.setInferredSequenceType(returnType);
+ expression.setStaticSequenceType(returnType);
}
}
- System.out.println("Visited static function call, set type to " + expression.getInferredSequenceType());
return argument;
}
@@ -486,110 +517,110 @@ public StaticContext visitFunctionCall(FunctionCallExpression expression, Static
@Override
public StaticContext visitCastableExpression(CastableExpression expression, StaticContext argument) {
- System.out.println("visiting Castable expression");
visitDescendants(expression, argument);
ItemType itemType = expression.getSequenceType().getItemType();
if (itemType.equals(BuiltinTypesCatalogue.atomicItem)) {
- throw new UnexpectedStaticTypeException(
- "atomic item type is not allowed in castable expression",
- ErrorCode.CastableErrorCode,
- expression.getMetadata()
+ throwStaticTypeException(
+ "atomic item type is not allowed in castable expression",
+ ErrorCode.CastableErrorCode,
+ expression.getMetadata()
);
}
- SequenceType expressionType = expression.getMainExpression().getInferredSequenceType();
+ SequenceType expressionType = expression.getMainExpression().getStaticSequenceType();
basicChecks(expressionType, expression.getClass().getSimpleName(), true, false, expression.getMetadata());
if (
!expressionType.isEmptySequence()
&& !expressionType.getItemType().isSubtypeOf(BuiltinTypesCatalogue.atomicItem)
) {
- throw new UnexpectedStaticTypeException(
- "non-atomic item types are not allowed in castable expression, found "
- + expressionType.getItemType(),
- expressionType.getItemType().isSubtypeOf(BuiltinTypesCatalogue.JSONItem)
- ? ErrorCode.NonAtomicElementErrorCode
- : ErrorCode.AtomizationError,
- expression.getMetadata()
+ throwStaticTypeException(
+ "non-atomic item types are not allowed in castable expression, found "
+ + expressionType.getItemType(),
+ expressionType.getItemType().isSubtypeOf(BuiltinTypesCatalogue.JSONItem)
+ ? ErrorCode.NonAtomicElementErrorCode
+ : ErrorCode.AtomizationError,
+ expression.getMetadata()
);
}
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.booleanItem));
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.booleanItem));
return argument;
}
@Override
public StaticContext visitCastExpression(CastExpression expression, StaticContext argument) {
- System.out.println("visiting Cast expression");
visitDescendants(expression, argument);
// check at static time for casting errors (note cast only allows for normal or ? arity)
- SequenceType expressionSequenceType = expression.getMainExpression().getInferredSequenceType();
+ SequenceType expressionSequenceType = expression.getMainExpression().getStaticSequenceType();
SequenceType castedSequenceType = expression.getSequenceType();
if (castedSequenceType.getItemType().equals(BuiltinTypesCatalogue.atomicItem)) {
- throw new UnexpectedStaticTypeException(
- "atomic item type is not allowed in cast expression",
- ErrorCode.CastableErrorCode,
- expression.getMetadata()
+ throwStaticTypeException(
+ "atomic item type is not allowed in cast expression",
+ ErrorCode.CastableErrorCode,
+ expression.getMetadata()
);
}
// Empty sequence case
if (expressionSequenceType.isEmptySequence()) {
if (castedSequenceType.getArity() != SequenceType.Arity.OneOrZero) {
- throw new UnexpectedStaticTypeException(
- "Empty sequence cannot be cast to type with quantifier different from '?'",
- expression.getMetadata()
+ throwStaticTypeException(
+ "Empty sequence cannot be cast to type with quantifier different from '?'",
+ expression.getMetadata()
);
} else {
// no additional check is needed
- expression.setInferredSequenceType(castedSequenceType);
+ expression.setStaticSequenceType(castedSequenceType);
return argument;
}
}
if (!expressionSequenceType.isAritySubtypeOf(castedSequenceType.getArity())) {
- throw new UnexpectedStaticTypeException(
- "with static type feature it is not possible to cast a "
- +
- expressionSequenceType
- + " as "
- + castedSequenceType,
- expression.getMetadata()
+ throwStaticTypeException(
+ "with static type feature it is not possible to cast a "
+ +
+ expressionSequenceType
+ + " as "
+ + castedSequenceType,
+ expression.getMetadata()
);
}
// ItemType static castability check
if (!expressionSequenceType.getItemType().isSubtypeOf(BuiltinTypesCatalogue.atomicItem)) {
- throw new UnexpectedStaticTypeException(
- "It is never possible to cast a non-atomic sequence type: "
- +
- expressionSequenceType,
- expressionSequenceType.getItemType().isSubtypeOf(BuiltinTypesCatalogue.JSONItem)
- ? ErrorCode.NonAtomicElementErrorCode
- : ErrorCode.AtomizationError,
- expression.getMetadata()
+ throwStaticTypeException(
+ "It is never possible to cast a non-atomic sequence type: "
+ +
+ expressionSequenceType,
+ expressionSequenceType.getItemType().isSubtypeOf(BuiltinTypesCatalogue.JSONItem)
+ ? ErrorCode.NonAtomicElementErrorCode
+ : ErrorCode.AtomizationError,
+ expression.getMetadata()
);
}
- if (!expressionSequenceType.getItemType().isStaticallyCastableAs(castedSequenceType.getItemType())) {
- throw new UnexpectedStaticTypeException(
- "It is never possible to cast a "
- +
- expressionSequenceType
- + " as "
- + castedSequenceType,
- expression.getMetadata()
+ if (
+ !expressionSequenceType.getItemType().isAtomicItemType()
+ || !expressionSequenceType.getItemType().isStaticallyCastableAs(castedSequenceType.getItemType())
+ ) {
+ throwStaticTypeException(
+ "It is never possible to cast a "
+ +
+ expressionSequenceType
+ + " as "
+ + castedSequenceType,
+ expression.getMetadata()
);
}
- expression.setInferredSequenceType(castedSequenceType);
+ expression.setStaticSequenceType(castedSequenceType);
return argument;
}
@Override
public StaticContext visitIsStaticallyExpr(IsStaticallyExpression expression, StaticContext argument) {
- System.out.println("visiting StaticallyIs expression");
visitDescendants(expression, argument);
- SequenceType inferred = expression.getMainExpression().getInferredSequenceType();
+ SequenceType inferred = expression.getMainExpression().getStaticSequenceType();
SequenceType expected = expression.getSequenceType();
if (!inferred.equals(expected)) {
throw new IsStaticallyUnexpectedTypeException(
@@ -598,35 +629,33 @@ public StaticContext visitIsStaticallyExpr(IsStaticallyExpression expression, St
);
}
- expression.setInferredSequenceType(expected);
+ expression.setStaticSequenceType(expected);
return argument;
}
@Override
public StaticContext visitInstanceOfExpression(InstanceOfExpression expression, StaticContext argument) {
- System.out.println("visiting InstanceOf expression");
visitDescendants(expression, argument);
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.booleanItem));
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.booleanItem));
return argument;
}
@Override
public StaticContext visitTreatExpression(TreatExpression expression, StaticContext argument) {
- System.out.println("visiting Treat expression");
visitDescendants(expression, argument);
// check at static time for treat errors
- SequenceType expressionSequenceType = expression.getMainExpression().getInferredSequenceType();
+ SequenceType expressionSequenceType = expression.getMainExpression().getStaticSequenceType();
SequenceType treatedSequenceType = expression.getSequenceType();
if (expressionSequenceType == null || treatedSequenceType == null) {
- throw new UnexpectedStaticTypeException(
- "The child expression of a Treat expression has no inferred type or it is being treated as null sequence type",
- expression.getMetadata()
+ throwStaticTypeException(
+ "The child expression of a Treat expression has no inferred type or it is being treated as null sequence type",
+ expression.getMetadata()
);
}
- expression.setInferredSequenceType(treatedSequenceType);
+ expression.setStaticSequenceType(treatedSequenceType);
return argument;
}
@@ -638,8 +667,8 @@ public StaticContext visitTreatExpression(TreatExpression expression, StaticCont
public StaticContext visitAdditiveExpr(AdditiveExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
- SequenceType leftInferredType = expression.getLeftExpression().getInferredSequenceType();
- SequenceType rightInferredType = expression.getRightExpression().getInferredSequenceType();
+ SequenceType leftInferredType = expression.getLeftExpression().getStaticSequenceType();
+ SequenceType rightInferredType = expression.getRightExpression().getStaticSequenceType();
basicChecks(
Arrays.asList(leftInferredType, rightInferredType),
@@ -654,10 +683,11 @@ public StaticContext visitAdditiveExpr(AdditiveExpression expression, StaticCont
// arity check
if (inferredArity == null) {
- throw new UnexpectedStaticTypeException(
- "'+' and '*' arities are not allowed for additive expressions",
- expression.getMetadata()
+ throwStaticTypeException(
+ "'+' and '*' arities are not allowed for additive expressions",
+ expression.getMetadata()
);
+ inferredArity = SequenceType.Arity.OneOrZero;
}
ItemType leftItemType = leftInferredType.getItemType();
@@ -712,24 +742,24 @@ public StaticContext visitAdditiveExpr(AdditiveExpression expression, StaticCont
if (inferredType == null) {
if (inferredArity == SequenceType.Arity.OneOrZero) {
// Only possible resulting type is empty sequence so throw error XPST0005
- throw new UnexpectedStaticTypeException(
- "Inferred type is empty sequence and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type is empty sequence and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
} else {
- throw new UnexpectedStaticTypeException(
- "The following types operation is not possible: "
- + leftInferredType
- + (expression.isMinus() ? " - " : " + ")
- + rightInferredType,
- expression.getMetadata()
+ throwStaticTypeException(
+ "The following types operation is not possible: "
+ + leftInferredType
+ + (expression.isMinus() ? " - " : " + ")
+ + rightInferredType,
+ expression.getMetadata()
);
}
+ inferredType = BuiltinTypesCatalogue.atomicItem;
}
- expression.setInferredSequenceType(new SequenceType(inferredType, inferredArity));
- System.out.println("visiting Additive expression, set type: " + expression.getInferredSequenceType());
+ expression.setStaticSequenceType(new SequenceType(inferredType, inferredArity));
return argument;
}
@@ -769,8 +799,8 @@ private SequenceType.Arity resolveArities(SequenceType.Arity left, SequenceType.
public StaticContext visitMultiplicativeExpr(MultiplicativeExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
- SequenceType leftInferredType = expression.getLeftExpression().getInferredSequenceType();
- SequenceType rightInferredType = expression.getRightExpression().getInferredSequenceType();
+ SequenceType leftInferredType = expression.getLeftExpression().getStaticSequenceType();
+ SequenceType rightInferredType = expression.getRightExpression().getStaticSequenceType();
basicChecks(
Arrays.asList(leftInferredType, rightInferredType),
@@ -784,10 +814,11 @@ public StaticContext visitMultiplicativeExpr(MultiplicativeExpression expression
SequenceType.Arity inferredArity = resolveArities(leftInferredType.getArity(), rightInferredType.getArity());
if (inferredArity == null) {
- throw new UnexpectedStaticTypeException(
- "'+' and '*' arities are not allowed for multiplicative expressions",
- expression.getMetadata()
+ throwStaticTypeException(
+ "'+' and '*' arities are not allowed for multiplicative expressions",
+ expression.getMetadata()
);
+ inferredArity = SequenceType.Arity.OneOrZero;
}
ItemType leftItemType = leftInferredType.getItemType();
@@ -835,48 +866,48 @@ public StaticContext visitMultiplicativeExpr(MultiplicativeExpression expression
if (inferredType == null) {
if (inferredArity == SequenceType.Arity.OneOrZero) {
// Only possible resulting type is empty sequence so throw error XPST0005
- throw new UnexpectedStaticTypeException(
- "Inferred type is empty sequence and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type is empty sequence and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
} else {
- throw new UnexpectedStaticTypeException(
- "The following types expression is not valid: "
- + leftItemType
- + " "
- + expression.getMultiplicativeOperator()
- + " "
- + rightItemType,
- expression.getMetadata()
+ throwStaticTypeException(
+ "The following types expression is not valid: "
+ + leftItemType
+ + " "
+ + expression.getMultiplicativeOperator()
+ + " "
+ + rightItemType,
+ expression.getMetadata()
);
}
+ inferredType = BuiltinTypesCatalogue.atomicItem;
}
- expression.setInferredSequenceType(new SequenceType(inferredType, inferredArity));
- System.out.println("visiting Multiplicative expression, set type: " + expression.getInferredSequenceType());
+ expression.setStaticSequenceType(new SequenceType(inferredType, inferredArity));
return argument;
}
@Override
public StaticContext visitUnaryExpr(UnaryExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
- SequenceType childInferredType = expression.getMainExpression().getInferredSequenceType();
+ SequenceType childInferredType = expression.getMainExpression().getStaticSequenceType();
// if the child expression has null inferred type throw error
if (childInferredType == null) {
- throw new UnexpectedStaticTypeException(
- "The child expression of a UnaryExpression has no inferred type",
- expression.getMetadata()
+ throwStaticTypeException(
+ "The child expression of a UnaryExpression has no inferred type",
+ expression.getMetadata()
);
}
// if the child is the empty sequence just infer the empty sequence
if (childInferredType.isEmptySequence()) {
- throw new UnexpectedStaticTypeException(
- "Inferred type is empty sequence and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type is empty sequence and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
}
@@ -884,9 +915,9 @@ public StaticContext visitUnaryExpr(UnaryExpression expression, StaticContext ar
childInferredType.getArity() == SequenceType.Arity.OneOrMore
|| childInferredType.getArity() == SequenceType.Arity.ZeroOrMore
) {
- throw new UnexpectedStaticTypeException(
- "'+' and '*' arities are not allowed for unary expressions",
- expression.getMetadata()
+ throwStaticTypeException(
+ "'+' and '*' arities are not allowed for unary expressions",
+ expression.getMetadata()
);
}
@@ -895,21 +926,20 @@ public StaticContext visitUnaryExpr(UnaryExpression expression, StaticContext ar
ItemType childItemType = childInferredType.getItemType();
if (!childItemType.isNumeric()) {
if (childInferredType.getArity() == SequenceType.Arity.OneOrZero) {
- throw new UnexpectedStaticTypeException(
- "Inferred type is empty sequence and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type is empty sequence and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
} else {
- throw new UnexpectedStaticTypeException(
- "It is not possible to have an Unary expression with the following type: " + childInferredType,
- expression.getMetadata()
+ throwStaticTypeException(
+ "It is not possible to have an Unary expression with the following type: " + childInferredType,
+ expression.getMetadata()
);
}
}
- expression.setInferredSequenceType(new SequenceType(childItemType, childInferredType.getArity()));
- System.out.println("visiting Unary expression, set type: " + expression.getInferredSequenceType());
+ expression.setStaticSequenceType(new SequenceType(childItemType, childInferredType.getArity()));
return argument;
}
@@ -921,39 +951,39 @@ private StaticContext visitAndOrExpr(Expression expression, StaticContext argume
visitDescendants(expression, argument);
List childrenExpressions = expression.getChildren();
- SequenceType leftInferredType = ((Expression) childrenExpressions.get(0)).getInferredSequenceType();
- SequenceType rightInferredType = ((Expression) childrenExpressions.get(1)).getInferredSequenceType();
+ SequenceType leftInferredType = ((Expression) childrenExpressions.get(0)).getStaticSequenceType();
+ SequenceType rightInferredType = ((Expression) childrenExpressions.get(1)).getStaticSequenceType();
if (leftInferredType == null || rightInferredType == null) {
- throw new UnexpectedStaticTypeException(
- "A child expression of a " + expressionName + "Expression has no inferred type",
- expression.getMetadata()
+ throwStaticTypeException(
+ "A child expression of a " + expressionName + "Expression has no inferred type",
+ expression.getMetadata()
);
}
if (!leftInferredType.hasEffectiveBooleanValue()) {
- throw new UnexpectedStaticTypeException(
- "left expression of a "
- + expressionName
- + "Expression has "
- + leftInferredType
- + " inferred type, which has no effective boolean value",
- expression.getMetadata()
+ throwStaticTypeException(
+ "left expression of a "
+ + expressionName
+ + "Expression has "
+ + leftInferredType
+ + " inferred type, which has no effective boolean value",
+ expression.getMetadata()
);
}
if (!rightInferredType.hasEffectiveBooleanValue()) {
- throw new UnexpectedStaticTypeException(
- "right expression of a "
- + expressionName
- + "Expression has "
- + rightInferredType
- + " inferred type, which has no effective boolean value",
- expression.getMetadata()
+ throwStaticTypeException(
+ "right expression of a "
+ + expressionName
+ + "Expression has "
+ + rightInferredType
+ + " inferred type, which has no effective boolean value",
+ expression.getMetadata()
);
}
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.booleanItem));
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.booleanItem));
return argument;
}
@@ -971,23 +1001,23 @@ public StaticContext visitOrExpr(OrExpression expression, StaticContext argument
public StaticContext visitNotExpr(NotExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
- SequenceType childInferredType = expression.getMainExpression().getInferredSequenceType();
+ SequenceType childInferredType = expression.getMainExpression().getStaticSequenceType();
if (childInferredType == null) {
- throw new UnexpectedStaticTypeException(
- "The child expression of NotExpression has no inferred type",
- expression.getMetadata()
+ throwStaticTypeException(
+ "The child expression of NotExpression has no inferred type",
+ expression.getMetadata()
);
}
if (!childInferredType.hasEffectiveBooleanValue()) {
- throw new UnexpectedStaticTypeException(
- "The child expression of NotExpression has "
- + childInferredType
- + " inferred type, which has no effective boolean value",
- expression.getMetadata()
+ throwStaticTypeException(
+ "The child expression of NotExpression has "
+ + childInferredType
+ + " inferred type, which has no effective boolean value",
+ expression.getMetadata()
);
}
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.booleanItem));
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.booleanItem));
return argument;
}
@@ -1000,14 +1030,14 @@ public StaticContext visitComparisonExpr(ComparisonExpression expression, Static
visitDescendants(expression, argument);
List childrenExpressions = expression.getChildren();
- SequenceType leftInferredType = ((Expression) childrenExpressions.get(0)).getInferredSequenceType();
- SequenceType rightInferredType = ((Expression) childrenExpressions.get(1)).getInferredSequenceType();
+ SequenceType leftInferredType = ((Expression) childrenExpressions.get(0)).getStaticSequenceType();
+ SequenceType rightInferredType = ((Expression) childrenExpressions.get(1)).getStaticSequenceType();
SequenceType.Arity returnArity = SequenceType.Arity.One;
if (leftInferredType == null || rightInferredType == null) {
- throw new UnexpectedStaticTypeException(
- "A child expression of a ComparisonExpression has no inferred type",
- expression.getMetadata()
+ throwStaticTypeException(
+ "A child expression of a ComparisonExpression has no inferred type",
+ expression.getMetadata()
);
}
@@ -1017,18 +1047,19 @@ public StaticContext visitComparisonExpr(ComparisonExpression expression, Static
// XPST0005 error
if (operator.isValueComparison()) {
if (leftInferredType.isEmptySequence() || rightInferredType.isEmptySequence()) {
- throw new UnexpectedStaticTypeException(
- "Inferred type is empty sequence and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type is empty sequence and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
}
returnArity = resolveArities(leftInferredType.getArity(), rightInferredType.getArity());
if (returnArity == null) {
- throw new UnexpectedStaticTypeException(
- "'+' and '*' arities are not allowed for this comparison operator: " + operator,
- expression.getMetadata()
+ throwStaticTypeException(
+ "'+' and '*' arities are not allowed for this comparison operator: " + operator,
+ expression.getMetadata()
);
+ returnArity = SequenceType.Arity.OneOrZero;
}
}
@@ -1046,10 +1077,10 @@ public StaticContext visitComparisonExpr(ComparisonExpression expression, Static
leftItemType.isSubtypeOf(BuiltinTypesCatalogue.JSONItem)
|| rightItemType.isSubtypeOf(BuiltinTypesCatalogue.JSONItem)
) {
- throw new UnexpectedStaticTypeException(
- "It is not possible to compare with non-atomic types",
- ErrorCode.NonAtomicElementErrorCode,
- expression.getMetadata()
+ throwStaticTypeException(
+ "It is not possible to compare with non-atomic types",
+ ErrorCode.NonAtomicElementErrorCode,
+ expression.getMetadata()
);
}
if (
@@ -1058,9 +1089,9 @@ public StaticContext visitComparisonExpr(ComparisonExpression expression, Static
|| leftItemType.equals(BuiltinTypesCatalogue.atomicItem)
|| rightItemType.equals(BuiltinTypesCatalogue.atomicItem)
) {
- throw new UnexpectedStaticTypeException(
- "It is not possible to compare with non-atomic types",
- expression.getMetadata()
+ throwStaticTypeException(
+ "It is not possible to compare with non-atomic types",
+ expression.getMetadata()
);
}
@@ -1080,9 +1111,9 @@ public StaticContext visitComparisonExpr(ComparisonExpression expression, Static
!(leftItemType.equals(BuiltinTypesCatalogue.nullItem)
|| rightItemType.equals(BuiltinTypesCatalogue.nullItem))
) {
- throw new UnexpectedStaticTypeException(
- "It is not possible to compare these types: " + leftItemType + " and " + rightItemType,
- expression.getMetadata()
+ throwStaticTypeException(
+ "It is not possible to compare these types: " + leftItemType + " and " + rightItemType,
+ expression.getMetadata()
);
}
@@ -1105,19 +1136,19 @@ public StaticContext visitComparisonExpr(ComparisonExpression expression, Static
|| leftItemType.equals(BuiltinTypesCatalogue.yearMonthDurationItem))
&& !rightItemType.equals(leftItemType)))
) {
- throw new UnexpectedStaticTypeException(
- "It is not possible to compare these types: "
- + leftItemType
- + " "
- + operator
- + " "
- + rightItemType,
- expression.getMetadata()
+ throwStaticTypeException(
+ "It is not possible to compare these types: "
+ + leftItemType
+ + " "
+ + operator
+ + " "
+ + rightItemType,
+ expression.getMetadata()
);
}
}
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.booleanItem, returnArity));
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.booleanItem, returnArity));
return argument;
}
@@ -1129,9 +1160,9 @@ public StaticContext visitComparisonExpr(ComparisonExpression expression, Static
public StaticContext visitConditionalExpression(ConditionalExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
- SequenceType ifType = expression.getCondition().getInferredSequenceType();
- SequenceType thenType = expression.getBranch().getInferredSequenceType();
- SequenceType elseType = expression.getElseBranch().getInferredSequenceType();
+ SequenceType ifType = expression.getCondition().getStaticSequenceType();
+ SequenceType thenType = expression.getBranch().getStaticSequenceType();
+ SequenceType elseType = expression.getElseBranch().getStaticSequenceType();
if (ifType == null || thenType == null || elseType == null) {
throw new OurBadException(
@@ -1141,11 +1172,11 @@ public StaticContext visitConditionalExpression(ConditionalExpression expression
}
if (!ifType.hasEffectiveBooleanValue()) {
- throw new UnexpectedStaticTypeException(
- "The condition in the 'if' must have effective boolean value, found inferred type: "
- + ifType
- + " (which has not effective boolean value)",
- expression.getMetadata()
+ throwStaticTypeException(
+ "The condition in the 'if' must have effective boolean value, found inferred type: "
+ + ifType
+ + " (which has not effective boolean value)",
+ expression.getMetadata()
);
}
@@ -1155,15 +1186,14 @@ public StaticContext visitConditionalExpression(ConditionalExpression expression
: thenType.leastCommonSupertypeWith(elseType);
if (resultingType.isEmptySequence()) {
- throw new UnexpectedStaticTypeException(
- "Inferred type is empty sequence and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type is empty sequence and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
}
- expression.setInferredSequenceType(resultingType);
- System.out.println("visiting Conditional expression, type set to: " + expression.getInferredSequenceType());
+ expression.setStaticSequenceType(resultingType);
return argument;
}
@@ -1176,32 +1206,32 @@ public void checkSwitchType(SequenceType type, ExceptionMetadata metadata) {
return; // no further check is required
}
if (type.getArity() == SequenceType.Arity.OneOrMore || type.getArity() == SequenceType.Arity.ZeroOrMore) {
- throw new UnexpectedStaticTypeException(
- "+ and * arities are not allowed for the expressions of switch test condition and cases",
- metadata
+ throwStaticTypeException(
+ "+ and * arities are not allowed for the expressions of switch test condition and cases",
+ metadata
);
}
ItemType itemType = type.getItemType();
if (itemType.isFunctionItemType()) {
- throw new UnexpectedStaticTypeException(
- "function item not allowed for the expressions of switch test condition and cases",
- ErrorCode.UnexpectedFunctionItem,
- metadata
+ throwStaticTypeException(
+ "function item not allowed for the expressions of switch test condition and cases",
+ ErrorCode.UnexpectedFunctionItem,
+ metadata
);
}
if (itemType.isSubtypeOf(BuiltinTypesCatalogue.JSONItem)) {
- throw new UnexpectedStaticTypeException(
- "switch test condition and cases expressions' item type must match atomic, instead inferred: "
- + itemType,
- ErrorCode.NonAtomicElementErrorCode,
- metadata
+ throwStaticTypeException(
+ "switch test condition and cases expressions' item type must match atomic, instead inferred: "
+ + itemType,
+ ErrorCode.NonAtomicElementErrorCode,
+ metadata
);
}
if (!itemType.isSubtypeOf(BuiltinTypesCatalogue.atomicItem)) {
- throw new UnexpectedStaticTypeException(
- "switch test condition and cases expressions' item type must match atomic, instead inferred: "
- + itemType,
- metadata
+ throwStaticTypeException(
+ "switch test condition and cases expressions' item type must match atomic, instead inferred: "
+ + itemType,
+ metadata
);
}
}
@@ -1209,10 +1239,10 @@ public void checkSwitchType(SequenceType type, ExceptionMetadata metadata) {
@Override
public StaticContext visitSwitchExpression(SwitchExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
- SequenceType testType = expression.getTestCondition().getInferredSequenceType();
+ SequenceType testType = expression.getTestCondition().getStaticSequenceType();
checkSwitchType(testType, expression.getMetadata());
- SequenceType returnType = expression.getDefaultExpression().getInferredSequenceType();
+ SequenceType returnType = expression.getDefaultExpression().getStaticSequenceType();
if (returnType == null) {
throw new OurBadException(
"A child expression of a SwitchExpression has no inferred type",
@@ -1224,13 +1254,13 @@ public StaticContext visitSwitchExpression(SwitchExpression expression, StaticCo
boolean addToReturnType = false;
for (Expression caseExpression : switchCase.getConditionExpressions()) {
// test the case expression
- checkSwitchType(caseExpression.getInferredSequenceType(), expression.getMetadata());
+ checkSwitchType(caseExpression.getStaticSequenceType(), expression.getMetadata());
// if has overlap with the test condition will add the return type to the possible ones
- if (caseExpression.getInferredSequenceType().hasOverlapWith(testType)) {
+ if (caseExpression.getStaticSequenceType().hasOverlapWith(testType)) {
addToReturnType = true;
}
}
- SequenceType caseReturnType = switchCase.getReturnExpression().getInferredSequenceType();
+ SequenceType caseReturnType = switchCase.getReturnExpression().getStaticSequenceType();
if (caseReturnType == null) {
throw new OurBadException(
"A child expression of a SwitchExpression has no inferred type",
@@ -1242,8 +1272,7 @@ public StaticContext visitSwitchExpression(SwitchExpression expression, StaticCo
}
}
- expression.setInferredSequenceType(returnType);
- System.out.println("visiting Switch expression, type set to: " + expression.getInferredSequenceType());
+ expression.setStaticSequenceType(returnType);
return argument;
}
@@ -1253,7 +1282,7 @@ public StaticContext visitTryCatchExpression(TryCatchExpression expression, Stat
SequenceType inferredType = null;
for (Node childNode : expression.getChildren()) {
- SequenceType childType = ((Expression) childNode).getInferredSequenceType();
+ SequenceType childType = ((Expression) childNode).getStaticSequenceType();
if (childType == null) {
throw new OurBadException(
"A child expression of a TryCatchExpression has no inferred type",
@@ -1269,14 +1298,13 @@ public StaticContext visitTryCatchExpression(TryCatchExpression expression, Stat
}
if (inferredType.isEmptySequence()) {
- throw new UnexpectedStaticTypeException(
- "Inferred type is empty sequence and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type is empty sequence and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
}
- expression.setInferredSequenceType(inferredType);
- System.out.println("visiting TryCatch expression, type set to: " + expression.getInferredSequenceType());
+ expression.setStaticSequenceType(inferredType);
return argument;
}
@@ -1285,7 +1313,7 @@ public StaticContext visitTypeSwitchExpression(TypeSwitchExpression expression,
visit(expression.getTestCondition(), argument);
SequenceType inferredType = null;
- SequenceType conditionType = expression.getTestCondition().getInferredSequenceType();
+ SequenceType conditionType = expression.getTestCondition().getStaticSequenceType();
basicChecks(conditionType, expression.getClass().getSimpleName(), true, false, expression.getMetadata());
for (TypeswitchCase typeswitchCase : expression.getCases()) {
@@ -1301,7 +1329,7 @@ public StaticContext visitTypeSwitchExpression(TypeSwitchExpression expression,
}
visit(returnExpression, argument);
- SequenceType caseType = returnExpression.getInferredSequenceType();
+ SequenceType caseType = returnExpression.getStaticSequenceType();
basicChecks(caseType, expression.getClass().getSimpleName(), true, false, expression.getMetadata());
inferredType = inferredType == null ? caseType : inferredType.leastCommonSupertypeWith(caseType);
}
@@ -1313,13 +1341,12 @@ public StaticContext visitTypeSwitchExpression(TypeSwitchExpression expression,
returnExpression.getStaticContext().replaceVariableSequenceType(variableName, conditionType);
}
visit(returnExpression, argument);
- SequenceType defaultType = returnExpression.getInferredSequenceType();
+ SequenceType defaultType = returnExpression.getStaticSequenceType();
basicChecks(defaultType, expression.getClass().getSimpleName(), true, false, expression.getMetadata());
inferredType = inferredType.leastCommonSupertypeWith(defaultType);
basicChecks(inferredType, expression.getClass().getSimpleName(), false, true, expression.getMetadata());
- expression.setInferredSequenceType(inferredType);
- System.out.println("visiting TypeSwitch expression, type set to: " + expression.getInferredSequenceType());
+ expression.setStaticSequenceType(inferredType);
return argument;
}
@@ -1332,39 +1359,45 @@ public StaticContext visitRangeExpr(RangeExpression expression, StaticContext ar
visitDescendants(expression, argument);
List children = expression.getChildren();
- SequenceType leftType = ((Expression) children.get(0)).getInferredSequenceType();
- SequenceType rightType = ((Expression) children.get(1)).getInferredSequenceType();
+ SequenceType leftType = ((Expression) children.get(0)).getStaticSequenceType();
+ SequenceType rightType = ((Expression) children.get(1)).getStaticSequenceType();
- if (leftType == null || rightType == null) {
+ if (leftType == null) {
throw new OurBadException(
"A child expression of a RangeExpression has no inferred type",
- expression.getMetadata()
+ ((Expression) children.get(0)).getMetadata()
+ );
+ }
+
+ if (rightType == null) {
+ throw new OurBadException(
+ "A child expression of a RangeExpression has no inferred type",
+ ((Expression) children.get(1)).getMetadata()
);
}
if (leftType.isEmptySequence() || rightType.isEmptySequence()) {
- throw new UnexpectedStaticTypeException(
- "Inferred type is empty sequence and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type is empty sequence and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
}
SequenceType intOpt = new SequenceType(BuiltinTypesCatalogue.integerItem, SequenceType.Arity.OneOrZero);
if (!leftType.isSubtypeOf(intOpt) || !rightType.isSubtypeOf(intOpt)) {
- throw new UnexpectedStaticTypeException(
- "operands of the range expression must match type integer? instead found: "
- + leftType
- + " and "
- + rightType,
- expression.getMetadata()
+ throwStaticTypeException(
+ "operands of the range expression must match type integer? instead found: "
+ + leftType
+ + " and "
+ + rightType,
+ expression.getMetadata()
);
}
- expression.setInferredSequenceType(
+ expression.setStaticSequenceType(
new SequenceType(BuiltinTypesCatalogue.integerItem, SequenceType.Arity.ZeroOrMore)
);
- System.out.println("visiting Range expression, type set to: " + expression.getInferredSequenceType());
return argument;
}
@@ -1373,8 +1406,8 @@ public StaticContext visitStringConcatExpr(StringConcatExpression expression, St
visitDescendants(expression, argument);
List children = expression.getChildren();
- SequenceType leftType = ((Expression) children.get(0)).getInferredSequenceType();
- SequenceType rightType = ((Expression) children.get(1)).getInferredSequenceType();
+ SequenceType leftType = ((Expression) children.get(0)).getStaticSequenceType();
+ SequenceType rightType = ((Expression) children.get(1)).getStaticSequenceType();
if (leftType == null || rightType == null) {
throw new OurBadException(
@@ -1385,17 +1418,16 @@ public StaticContext visitStringConcatExpr(StringConcatExpression expression, St
SequenceType intOpt = new SequenceType(BuiltinTypesCatalogue.atomicItem, SequenceType.Arity.OneOrZero);
if (!leftType.isSubtypeOf(intOpt) || !rightType.isSubtypeOf(intOpt)) {
- throw new UnexpectedStaticTypeException(
- "operands of the concat expression must match type atomic? instead found: "
- + leftType
- + " and "
- + rightType,
- expression.getMetadata()
+ throwStaticTypeException(
+ "operands of the concat expression must match type atomic? instead found: "
+ + leftType
+ + " and "
+ + rightType,
+ expression.getMetadata()
);
}
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.stringItem));
- System.out.println("visiting Concat expression, type set to: " + expression.getInferredSequenceType());
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.stringItem));
return argument;
}
@@ -1407,8 +1439,8 @@ public StaticContext visitStringConcatExpr(StringConcatExpression expression, St
public StaticContext visitArrayLookupExpression(ArrayLookupExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
- SequenceType mainType = expression.getMainExpression().getInferredSequenceType();
- SequenceType lookupType = expression.getLookupExpression().getInferredSequenceType();
+ SequenceType mainType = expression.getMainExpression().getStaticSequenceType();
+ SequenceType lookupType = expression.getLookupExpression().getStaticSequenceType();
if (mainType == null || lookupType == null) {
throw new OurBadException(
@@ -1418,25 +1450,24 @@ public StaticContext visitArrayLookupExpression(ArrayLookupExpression expression
}
if (!lookupType.isSubtypeOf(SequenceType.createSequenceType("integer"))) {
- throw new UnexpectedStaticTypeException(
- "the lookup expression type must match integer, instead " + lookupType + " was inferred",
- expression.getMetadata()
+ throwStaticTypeException(
+ "the lookup expression type must match integer, instead " + lookupType + " was inferred",
+ expression.getMetadata()
);
}
if (!mainType.hasOverlapWith(SequenceType.createSequenceType("array*")) || mainType.isEmptySequence()) {
- throw new UnexpectedStaticTypeException(
- "Inferred type is empty sequence and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type is empty sequence and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
}
SequenceType.Arity inferredArity = mainType.isAritySubtypeOf(SequenceType.Arity.OneOrZero)
? SequenceType.Arity.OneOrZero
: SequenceType.Arity.ZeroOrMore;
- expression.setInferredSequenceType(new SequenceType(BuiltinTypesCatalogue.item, inferredArity));
- System.out.println("visiting ArrayLookup expression, type set to: " + expression.getInferredSequenceType());
+ expression.setStaticSequenceType(new SequenceType(BuiltinTypesCatalogue.item, inferredArity));
return argument;
}
@@ -1444,8 +1475,8 @@ public StaticContext visitArrayLookupExpression(ArrayLookupExpression expression
public StaticContext visitObjectLookupExpression(ObjectLookupExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
- SequenceType mainType = expression.getMainExpression().getInferredSequenceType();
- SequenceType lookupType = expression.getLookupExpression().getInferredSequenceType();
+ SequenceType mainType = expression.getMainExpression().getStaticSequenceType();
+ SequenceType lookupType = expression.getLookupExpression().getStaticSequenceType();
if (mainType == null || lookupType == null) {
throw new OurBadException(
@@ -1456,19 +1487,19 @@ public StaticContext visitObjectLookupExpression(ObjectLookupExpression expressi
// must be castable to string
if (!lookupType.isSubtypeOf(SequenceType.createSequenceType("atomic"))) {
- throw new UnexpectedStaticTypeException(
- "the lookup expression type must be castable to string (i.e. must match atomic), instead "
- + lookupType
- + " was inferred",
- expression.getMetadata()
+ throwStaticTypeException(
+ "the lookup expression type must be castable to string (i.e. must match atomic), instead "
+ + lookupType
+ + " was inferred",
+ expression.getMetadata()
);
}
if (!mainType.hasOverlapWith(SequenceType.createSequenceType("object*")) || mainType.isEmptySequence()) {
- throw new UnexpectedStaticTypeException(
- "Inferred type is empty sequence and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type is empty sequence and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
}
@@ -1495,16 +1526,15 @@ public StaticContext visitObjectLookupExpression(ObjectLookupExpression expressi
}
} else if (isObjectClosed) {
// if object is closed and key is not found then for sure we will return the empty sequence
- throw new UnexpectedStaticTypeException(
- "Inferred type is empty sequence and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type is empty sequence and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
}
}
- expression.setInferredSequenceType(new SequenceType(inferredType, inferredArity));
- System.out.println("visiting ObjectLookup expression, type set to: " + expression.getInferredSequenceType());
+ expression.setStaticSequenceType(new SequenceType(inferredType, inferredArity));
return argument;
}
@@ -1512,7 +1542,7 @@ public StaticContext visitObjectLookupExpression(ObjectLookupExpression expressi
public StaticContext visitArrayUnboxingExpression(ArrayUnboxingExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
- SequenceType mainType = expression.getMainExpression().getInferredSequenceType();
+ SequenceType mainType = expression.getMainExpression().getStaticSequenceType();
if (mainType == null) {
throw new OurBadException(
@@ -1522,47 +1552,44 @@ public StaticContext visitArrayUnboxingExpression(ArrayUnboxingExpression expres
}
if (!mainType.hasOverlapWith(SequenceType.createSequenceType("array*")) || mainType.isEmptySequence()) {
- throw new UnexpectedStaticTypeException(
- "Inferred type is empty sequence and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type is empty sequence and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
}
- expression.setInferredSequenceType(SequenceType.createSequenceType("item*"));
- System.out.println(
- "visiting ArrayUnboxingExpression expression, type set to: " + expression.getInferredSequenceType()
- );
+ expression.setStaticSequenceType(SequenceType.createSequenceType("item*"));
return argument;
}
@Override
public StaticContext visitFilterExpression(FilterExpression expression, StaticContext argument) {
visit(expression.getMainExpression(), argument);
- SequenceType mainType = expression.getMainExpression().getInferredSequenceType();
+ SequenceType mainType = expression.getMainExpression().getStaticSequenceType();
basicChecks(mainType, expression.getClass().getSimpleName(), true, true, expression.getMetadata());
Expression predicateExpression = expression.getPredicateExpression();
// set context item static type
predicateExpression.getStaticContext().setContextItemStaticType(new SequenceType(mainType.getItemType()));
visit(predicateExpression, argument);
- SequenceType predicateType = predicateExpression.getInferredSequenceType();
+ SequenceType predicateType = predicateExpression.getStaticSequenceType();
// unset context item static type
predicateExpression.getStaticContext().setContextItemStaticType(null);
basicChecks(predicateType, expression.getClass().getSimpleName(), true, true, expression.getMetadata());
// always false so the return type is for sure ()
if (predicateType.isSubtypeOf(SequenceType.createSequenceType("null?"))) {
- throw new UnexpectedStaticTypeException(
- "Inferred type for FilterExpression is empty sequence (with active static typing feature, only allowed for CommaExpression)",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type for FilterExpression is empty sequence (with active static typing feature, only allowed for CommaExpression)",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
}
if (!predicateType.hasEffectiveBooleanValue()) {
- throw new UnexpectedStaticTypeException(
- "Inferred type " + predicateType + " in FilterExpression has no effective boolean value",
- expression.getMetadata()
+ throwStaticTypeException(
+ "Inferred type " + predicateType + " in FilterExpression has no effective boolean value",
+ expression.getMetadata()
);
}
@@ -1572,8 +1599,7 @@ public StaticContext visitFilterExpression(FilterExpression expression, StaticCo
|| predicateType.getItemType().equals(BuiltinTypesCatalogue.integerItem))
? SequenceType.Arity.OneOrZero
: SequenceType.Arity.ZeroOrMore;
- expression.setInferredSequenceType(new SequenceType(mainType.getItemType(), inferredArity));
- System.out.println("visiting Filter expression, type set to: " + expression.getInferredSequenceType());
+ expression.setStaticSequenceType(new SequenceType(mainType.getItemType(), inferredArity));
return argument;
}
@@ -1596,42 +1622,69 @@ public StaticContext visitDynamicFunctionCallExpression(
DynamicFunctionCallExpression expression,
StaticContext argument
) {
- // since we do not specify function's signature in the itemType we can only check that it is a function
visitDescendants(expression, argument);
- SequenceType mainType = expression.getMainExpression().getInferredSequenceType();
+ SequenceType mainType = expression.getMainExpression().getStaticSequenceType();
basicChecks(mainType, expression.getClass().getSimpleName(), true, false, expression.getMetadata());
+ if (mainType.isEmptySequence()) {
+ expression.setStaticSequenceType(SequenceType.EMPTY_SEQUENCE);
+ return argument;
+ }
- FunctionSignature signature = null;
- boolean isAnyFunction = false;
- if (!mainType.isEmptySequence()) {
- ItemType type = mainType.getItemType();
- if (type.isFunctionItemType()) {
- if (type.equals(BuiltinTypesCatalogue.anyFunctionItem)) {
- isAnyFunction = true;
+ ItemType type = mainType.getItemType();
+ if (!type.isFunctionItemType()) {
+ expression.setStaticSequenceType(SequenceType.ITEM_STAR);
+
+ throwStaticTypeException(
+ "the type of a dynamic function call main expression must be function, instead inferred " + mainType,
+ expression.getMetadata()
+ );
+ return argument;
+ }
+
+ if (type.equals(BuiltinTypesCatalogue.anyFunctionItem)) {
+ expression.setStaticSequenceType(SequenceType.ITEM_STAR);
+ return argument;
+ }
+
+ FunctionSignature signature = type.getSignature();
+ List actualParameterTypes = new ArrayList<>();
+ List formalParameterTypes = signature.getParameterTypes();
+ List partialFormalParameterTypes = new ArrayList<>();
+ boolean isPartialApplication = false;
+ int i = 0;
+ for (Expression e : expression.getArguments()) {
+ if (e == null) {
+ isPartialApplication = true;
+ if (signature != null) {
+ partialFormalParameterTypes.add(formalParameterTypes.get(i));
} else {
- signature = type.getSignature();
+ partialFormalParameterTypes.add(SequenceType.ITEM_STAR);
}
}
+ if (e != null) {
+ actualParameterTypes.add(e.getStaticSequenceType());
+ }
+ ++i;
}
-
- List argsType = expression.getArguments()
- .stream()
- .map(Expression::getInferredSequenceType)
- .collect(Collectors.toList());
- if (isAnyFunction || (signature != null && checkArguments(signature.getParameterTypes(), argsType))) {
- // TODO: need to add support for partial application
- expression.setInferredSequenceType(signature.getReturnType());
- System.out.println(
- "visiting DynamicFunctionCall expression, type set to: " + expression.getInferredSequenceType()
+ if (isPartialApplication) {
+ FunctionSignature newSignature = new FunctionSignature(
+ partialFormalParameterTypes,
+ signature.getReturnType()
);
+ expression.setStaticSequenceType(new SequenceType(ItemTypeFactory.createFunctionItemType(newSignature)));
return argument;
}
-
- throw new UnexpectedStaticTypeException(
- "the type of a dynamic function call main expression must be function, instead inferred " + mainType,
+ if (!checkArguments(formalParameterTypes, actualParameterTypes)) {
+ throwStaticTypeException(
+ "the type of a dynamic function call main expression must be function, instead inferred "
+ + mainType,
expression.getMetadata()
- );
+ );
+ }
+
+ expression.setStaticSequenceType(signature.getReturnType());
+ return argument;
}
@Override
@@ -1641,7 +1694,7 @@ public StaticContext visitSimpleMapExpr(SimpleMapExpression expression, StaticCo
Expression rightExpression = (Expression) nodes.get(1);
visit(leftExpression, argument);
- SequenceType leftType = leftExpression.getInferredSequenceType();
+ SequenceType leftType = leftExpression.getStaticSequenceType();
basicChecks(leftType, expression.getClass().getSimpleName(), true, true, expression.getMetadata());
// set context item static type
@@ -1649,12 +1702,11 @@ public StaticContext visitSimpleMapExpr(SimpleMapExpression expression, StaticCo
visit(rightExpression, argument);
rightExpression.getStaticContext().setContextItemStaticType(null);
- SequenceType rightType = rightExpression.getInferredSequenceType();
+ SequenceType rightType = rightExpression.getStaticSequenceType();
basicChecks(rightType, expression.getClass().getSimpleName(), true, true, expression.getMetadata());
SequenceType.Arity resultingArity = leftType.getArity().multiplyWith(rightType.getArity());
- expression.setInferredSequenceType(new SequenceType(rightType.getItemType(), resultingArity));
- System.out.println("visiting SimpleMap expression, type set to: " + expression.getInferredSequenceType());
+ expression.setStaticSequenceType(new SequenceType(rightType.getItemType(), resultingArity));
return argument;
}
@@ -1669,10 +1721,10 @@ public StaticContext visitFlowrExpression(FlworExpression expression, StaticCont
SequenceType forType;
while (clause != null) {
- this.visit(clause, argument);
+ this.visit(clause, clause.getStaticContext());
// if there are for clauses we need to consider their arities for the returning expression
if (clause.getClauseType() == FLWOR_CLAUSES.FOR) {
- forType = ((ForClause) clause).getExpression().getInferredSequenceType();
+ forType = ((ForClause) clause).getExpression().getStaticSequenceType();
// if forType is the empty sequence that means that allowing empty is set otherwise we would have thrown
// an error
// therefore this for loop will generate one tuple binding the empty sequence, so as for the arities
@@ -1691,30 +1743,32 @@ public StaticContext visitFlowrExpression(FlworExpression expression, StaticCont
clause = clause.getNextClause();
}
- SequenceType returnType = expression.getReturnClause().getReturnExpr().getInferredSequenceType();
+ SequenceType returnType = expression.getReturnClause().getReturnExpr().getStaticSequenceType();
basicChecks(returnType, expression.getClass().getSimpleName(), true, true, expression.getMetadata());
returnType = new SequenceType(returnType.getItemType(), returnType.getArity().multiplyWith(forArities));
- expression.setInferredSequenceType(returnType);
- System.out.println("visiting Flowr expression, type set to: " + expression.getInferredSequenceType());
+ expression.setStaticSequenceType(returnType);
return argument;
}
@Override
public StaticContext visitForClause(ForClause expression, StaticContext argument) {
- visit(expression.getExpression(), argument);
-
+ visitDescendants(expression, argument);
SequenceType declaredType = expression.getActualSequenceType();
- SequenceType inferredType = (declaredType == null
- ? expression.getExpression()
- : ((TreatExpression) expression.getExpression()).getMainExpression()).getInferredSequenceType();
+ SequenceType inferredType = SequenceType.ITEM_STAR;
+ if (declaredType == null) {
+ inferredType = expression.getExpression().getStaticSequenceType();
+ } else {
+ inferredType = declaredType;
+ }
+
basicChecks(inferredType, expression.getClass().getSimpleName(), true, false, expression.getMetadata());
if (inferredType.isEmptySequence()) {
if (!expression.isAllowEmpty()) {
// for sure we will not have any tuple to process and return the empty sequence
- throw new UnexpectedStaticTypeException(
- "In for clause Inferred type is empty sequence, empty is not allowed, so the result returned is for sure () and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "In for clause Inferred type is empty sequence, empty is not allowed, so the result returned is for sure () and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
}
} else {
@@ -1731,7 +1785,7 @@ public StaticContext visitForClause(ForClause expression, StaticContext argument
}
}
- checkVariableType(
+ checkAndUpdateVariableStaticType(
declaredType,
inferredType,
expression.getNextClause().getStaticContext(),
@@ -1740,7 +1794,6 @@ public StaticContext visitForClause(ForClause expression, StaticContext argument
expression.getMetadata()
);
- System.out.println("visiting For clause, inferred var " + expression.getVariableName() + " : " + inferredType);
return argument;
}
@@ -1750,8 +1803,8 @@ public StaticContext visitLetClause(LetClause expression, StaticContext argument
SequenceType declaredType = expression.getActualSequenceType();
SequenceType inferredType = (declaredType == null
? expression.getExpression()
- : ((TreatExpression) expression.getExpression()).getMainExpression()).getInferredSequenceType();
- checkVariableType(
+ : ((TreatExpression) expression.getExpression()).getMainExpression()).getStaticSequenceType();
+ checkAndUpdateVariableStaticType(
declaredType,
inferredType,
expression.getNextClause().getStaticContext(),
@@ -1760,26 +1813,25 @@ public StaticContext visitLetClause(LetClause expression, StaticContext argument
expression.getMetadata()
);
- System.out.println("visiting Let clause, var " + expression.getVariableName() + " : " + inferredType);
return argument;
}
@Override
public StaticContext visitWhereClause(WhereClause expression, StaticContext argument) {
visit(expression.getWhereExpression(), argument);
- SequenceType whereType = expression.getWhereExpression().getInferredSequenceType();
+ SequenceType whereType = expression.getWhereExpression().getStaticSequenceType();
basicChecks(whereType, expression.getClass().getSimpleName(), true, false, expression.getMetadata());
if (!whereType.hasEffectiveBooleanValue()) {
- throw new UnexpectedStaticTypeException(
- "where clause inferred type (" + whereType + ") has no effective boolean value",
- expression.getMetadata()
+ throwStaticTypeException(
+ "where clause inferred type (" + whereType + ") has no effective boolean value",
+ expression.getMetadata()
);
}
if (whereType.isEmptySequence() || whereType.isSubtypeOf(SequenceType.createSequenceType("null?"))) {
- throw new UnexpectedStaticTypeException(
- "where clause always return false, so return expression inferred type is empty sequence and this is not a CommaExpression",
- ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
- expression.getMetadata()
+ throwStaticTypeException(
+ "where clause always return false, so return expression inferred type is empty sequence and this is not a CommaExpression",
+ ErrorCode.StaticallyInferredEmptySequenceNotFromCommaExpression,
+ expression.getMetadata()
);
}
return argument;
@@ -1795,17 +1847,17 @@ public StaticContext visitGroupByClause(GroupByClause expression, StaticContext
Expression groupByVarExpr = groupByVar.getExpression();
SequenceType expectedType;
if (groupByVarExpr != null) {
- visit(groupByVarExpr, argument);
+ visit(groupByVarExpr, groupByVarExpr.getStaticContext());
SequenceType declaredType = groupByVar.getActualSequenceType();
SequenceType inferredType;
if (declaredType == null) {
- inferredType = groupByVarExpr.getInferredSequenceType();
+ inferredType = groupByVarExpr.getStaticSequenceType();
expectedType = inferredType;
} else {
- inferredType = ((TreatExpression) groupByVarExpr).getMainExpression().getInferredSequenceType();
+ inferredType = ((TreatExpression) groupByVarExpr).getMainExpression().getStaticSequenceType();
expectedType = declaredType;
}
- checkVariableType(
+ checkAndUpdateVariableStaticType(
declaredType,
inferredType,
nextClause.getStaticContext(),
@@ -1818,22 +1870,22 @@ public StaticContext visitGroupByClause(GroupByClause expression, StaticContext
}
// check that expectedType is a subtype of atomic?
if (expectedType.isSubtypeOf(SequenceType.createSequenceType("json-item*"))) {
- throw new UnexpectedStaticTypeException(
- "group by variable "
- + groupByVar.getVariableName()
- + " must match atomic? instead found "
- + expectedType,
- ErrorCode.NonAtomicElementErrorCode,
- expression.getMetadata()
+ throwStaticTypeException(
+ "group by variable "
+ + groupByVar.getVariableName()
+ + " must match atomic? instead found "
+ + expectedType,
+ ErrorCode.NonAtomicElementErrorCode,
+ expression.getMetadata()
);
}
if (!expectedType.isSubtypeOf(SequenceType.createSequenceType("atomic?"))) {
- throw new UnexpectedStaticTypeException(
- "group by variable "
- + groupByVar.getVariableName()
- + " must match atomic? instead found "
- + expectedType,
- expression.getMetadata()
+ throwStaticTypeException(
+ "group by variable "
+ + groupByVar.getVariableName()
+ + " must match atomic? instead found "
+ + expectedType,
+ expression.getMetadata()
);
}
groupingVars.add(groupByVar.getVariableName());
@@ -1851,14 +1903,14 @@ public StaticContext visitGroupByClause(GroupByClause expression, StaticContext
public StaticContext visitOrderByClause(OrderByClause expression, StaticContext argument) {
visitDescendants(expression, argument);
for (OrderByClauseSortingKey orderClause : expression.getSortingKeys()) {
- SequenceType orderType = orderClause.getExpression().getInferredSequenceType();
+ SequenceType orderType = orderClause.getExpression().getStaticSequenceType();
basicChecks(orderType, expression.getClass().getSimpleName(), true, false, expression.getMetadata());
if (orderType.isSubtypeOf(SequenceType.createSequenceType("json-item*"))) {
- throw new UnexpectedStaticTypeException(
- "order by sorting expression's type must match atomic? and be comparable using 'gt' operator (so duration, hexBinary, base64Binary and atomic item type are not allowed), instead inferred: "
- + orderType,
- ErrorCode.NonAtomicElementErrorCode,
- expression.getMetadata()
+ throwStaticTypeException(
+ "order by sorting expression's type must match atomic? and be comparable using 'gt' operator (so duration, hexBinary, base64Binary and atomic item type are not allowed), instead inferred: "
+ + orderType,
+ ErrorCode.NonAtomicElementErrorCode,
+ expression.getMetadata()
);
}
if (
@@ -1872,10 +1924,10 @@ public StaticContext visitOrderByClause(OrderByClause expression, StaticContext
||
orderType.getItemType().equals(BuiltinTypesCatalogue.base64BinaryItem)
) {
- throw new UnexpectedStaticTypeException(
- "order by sorting expression's type must match atomic? and be comparable using 'gt' operator (so duration, hexBinary, base64Binary and atomic item type are not allowed), instead inferred: "
- + orderType,
- expression.getMetadata()
+ throwStaticTypeException(
+ "order by sorting expression's type must match atomic? and be comparable using 'gt' operator (so duration, hexBinary, base64Binary and atomic item type are not allowed), instead inferred: "
+ + orderType,
+ expression.getMetadata()
);
}
}
@@ -1890,7 +1942,7 @@ public StaticContext visitOrderByClause(OrderByClause expression, StaticContext
// if [declaredType] is not null, check if the inferred type matches or can be promoted to the declared type
// (otherwise throw type error)
// if [declaredType] is null, replace the type of [variableName] in the [context] with the inferred type
- public void checkVariableType(
+ public void checkAndUpdateVariableStaticType(
SequenceType declaredType,
SequenceType inferredType,
StaticContext context,
@@ -1906,16 +1958,16 @@ public void checkVariableType(
context.replaceVariableSequenceType(variableName, inferredType);
} else {
if (!inferredType.isSubtypeOf(declaredType)) {
- throw new UnexpectedStaticTypeException(
- "In a "
- + nodeName
- + ", the variable $"
- + variableName
- + " inferred type "
- + inferredType
- + " does not match or can be promoted to the declared type "
- + declaredType,
- metadata
+ throwStaticTypeException(
+ "In a "
+ + nodeName
+ + ", the variable $"
+ + variableName
+ + " inferred type "
+ + inferredType
+ + " does not match or can be promoted to the declared type "
+ + declaredType,
+ metadata
);
}
}
@@ -1925,10 +1977,15 @@ public void checkVariableType(
public StaticContext visitVariableDeclaration(VariableDeclaration expression, StaticContext argument) {
visitDescendants(expression, argument);
SequenceType declaredType = expression.getActualSequenceType();
- SequenceType inferredType = (declaredType == null
- ? expression.getExpression()
- : ((TreatExpression) expression.getExpression()).getMainExpression()).getInferredSequenceType();
- checkVariableType(
+ SequenceType inferredType = SequenceType.ITEM_STAR;
+ if (declaredType == null) {
+ if (expression.getExpression() != null) {
+ inferredType = expression.getExpression().getStaticSequenceType();
+ }
+ } else {
+ inferredType = declaredType;
+ }
+ checkAndUpdateVariableStaticType(
declaredType,
inferredType,
argument,
@@ -1943,29 +2000,49 @@ public StaticContext visitVariableDeclaration(VariableDeclaration expression, St
@Override
public StaticContext visitFunctionDeclaration(FunctionDeclaration expression, StaticContext argument) {
visitDescendants(expression, argument);
-
InlineFunctionExpression inlineExpression = (InlineFunctionExpression) expression.getExpression();
- SequenceType inferredType = inlineExpression.getBody().getInferredSequenceType();
+ SequenceType inferredType = inlineExpression.getBody().getStaticSequenceType();
SequenceType expectedType = inlineExpression.getActualReturnType();
if (expectedType == null) {
expectedType = inferredType;
} else if (!inferredType.isSubtypeOfOrCanBePromotedTo(expectedType)) {
- throw new UnexpectedStaticTypeException(
- "The declared function return inferred type "
- + inferredType
- + " does not match or can be promoted to the expected return type "
- + expectedType,
- expression.getMetadata()
+ throwStaticTypeException(
+ "The declared function return inferred type "
+ + inferredType
+ + " does not match or can be promoted to the expected return type "
+ + expectedType,
+ expression.getMetadata()
);
}
- // add function signature to the statically known one
- argument.addFunctionSignature(
- inlineExpression.getFunctionIdentifier(),
- new FunctionSignature(new ArrayList(inlineExpression.getParams().values()), expectedType)
- );
+ return argument;
+ }
+ @Override
+ public StaticContext visitMainModule(MainModule mainModule, StaticContext argument) {
+ StaticContext generatedContext = visitDescendants(mainModule, mainModule.getStaticContext());
+ return generatedContext;
+ }
+
+ @Override
+ public StaticContext visitLibraryModule(LibraryModule libraryModule, StaticContext argument) {
+ visitDescendants(libraryModule, libraryModule.getStaticContext());
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitProlog(Prolog prolog, StaticContext argument) {
+ for (Node child : prolog.getChildren()) {
+ visit(child, argument);
+ }
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitValidateTypeExpression(ValidateTypeExpression expression, StaticContext argument) {
+ visitDescendants(expression, expression.getStaticContext());
+ expression.setStaticSequenceType(expression.getSequenceType());
return argument;
}
diff --git a/src/main/java/org/rumbledb/compiler/StaticContextVisitor.java b/src/main/java/org/rumbledb/compiler/StaticContextVisitor.java
index 3d95657546..be20f6851a 100644
--- a/src/main/java/org/rumbledb/compiler/StaticContextVisitor.java
+++ b/src/main/java/org/rumbledb/compiler/StaticContextVisitor.java
@@ -22,18 +22,14 @@
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
-import org.rumbledb.context.BuiltinFunctionCatalogue;
-import org.rumbledb.context.FunctionIdentifier;
import org.rumbledb.context.Name;
import org.rumbledb.context.StaticContext;
import org.rumbledb.exceptions.OurBadException;
import org.rumbledb.exceptions.UndeclaredVariableException;
-import org.rumbledb.exceptions.VariableAlreadyExistsException;
import org.rumbledb.expressions.AbstractNodeVisitor;
-import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.expressions.Expression;
import org.rumbledb.expressions.Node;
import org.rumbledb.expressions.control.TypeSwitchExpression;
@@ -48,36 +44,36 @@
import org.rumbledb.expressions.module.FunctionDeclaration;
import org.rumbledb.expressions.module.LibraryModule;
import org.rumbledb.expressions.module.MainModule;
+import org.rumbledb.expressions.module.Prolog;
+import org.rumbledb.expressions.module.TypeDeclaration;
import org.rumbledb.expressions.module.VariableDeclaration;
-import org.rumbledb.expressions.primary.FunctionCallExpression;
import org.rumbledb.expressions.primary.InlineFunctionExpression;
import org.rumbledb.expressions.primary.VariableReferenceExpression;
+import org.rumbledb.expressions.typing.CastExpression;
+import org.rumbledb.expressions.typing.CastableExpression;
+import org.rumbledb.expressions.typing.InstanceOfExpression;
+import org.rumbledb.expressions.typing.TreatExpression;
+import org.rumbledb.expressions.typing.ValidateTypeExpression;
import org.rumbledb.types.BuiltinTypesCatalogue;
+import org.rumbledb.types.FunctionSignature;
+import org.rumbledb.types.ItemType;
import org.rumbledb.types.SequenceType;
-import org.rumbledb.types.SequenceType.Arity;
/**
* Static context visitor implements a multi-pass algorithm that enables function hoisting
*/
public class StaticContextVisitor extends AbstractNodeVisitor {
- private VisitorConfig visitorConfig;
private Map importedModuleContexts;
StaticContextVisitor() {
- this.visitorConfig = VisitorConfig.staticContextVisitorInitialPassConfig;
this.importedModuleContexts = new HashMap<>();
}
- void setVisitorConfig(VisitorConfig visitorConfig) {
- this.visitorConfig = visitorConfig;
- }
-
@Override
protected StaticContext defaultAction(Node node, StaticContext argument) {
StaticContext generatedContext = visitDescendants(node, argument);
// initialize execution mode by visiting children and expressions first, then calling initialize methods
- node.initHighestExecutionMode(this.visitorConfig);
return generatedContext;
}
@@ -99,7 +95,6 @@ public StaticContext visit(Node node, StaticContext argument) {
public StaticContext visitMainModule(MainModule mainModule, StaticContext argument) {
this.importedModuleContexts.clear();
StaticContext generatedContext = visitDescendants(mainModule, argument);
- mainModule.initHighestExecutionMode(this.visitorConfig);
return generatedContext;
}
@@ -109,14 +104,16 @@ public StaticContext visitLibraryModule(LibraryModule libraryModule, StaticConte
StaticContext moduleContext = libraryModule.getStaticContext();
this.visit(libraryModule.getProlog(), moduleContext);
this.importedModuleContexts.put(libraryModule.getNamespace(), moduleContext);
- } else {
- libraryModule.getProlog().initHighestExecutionMode(this.visitorConfig);
}
- libraryModule.initHighestExecutionMode(this.visitorConfig);
argument.importModuleContext(
this.importedModuleContexts.get(libraryModule.getNamespace()),
libraryModule.getNamespace()
);
+ argument.getInScopeSchemaTypes()
+ .importModuleTypes(
+ this.importedModuleContexts.get(libraryModule.getNamespace()).getInScopeSchemaTypes(),
+ libraryModule.getNamespace()
+ );
return argument;
}
@@ -131,59 +128,45 @@ public StaticContext visitVariableReference(VariableReferenceExpression expressi
);
} else {
// note: sequence type can be null
- expression.setType(argument.getVariableSequenceType(variableName));
- ExecutionMode mode = argument.getVariableStorageMode(variableName);
- if (this.visitorConfig.setUnsetToLocal() && mode.equals(ExecutionMode.UNSET)) {
- mode = ExecutionMode.LOCAL;
- }
- expression.setHighestExecutionMode(mode);
- // TODO: check staticContext available
+ expression.setActualType(argument.getVariableSequenceType(variableName));
return argument;
}
}
private void populateFunctionDeclarationStaticContext(
StaticContext functionDeclarationContext,
- List modes,
InlineFunctionExpression expression
) {
- int i = 0;
for (Name name : expression.getParams().keySet()) {
- ExecutionMode mode = modes.get(i);
- SequenceType type = expression.getParams().get(name);
- if (type.isEmptySequence()) {
- mode = ExecutionMode.LOCAL;
- } else if (type.getArity().equals(Arity.OneOrZero) || type.getArity().equals(Arity.One)) {
- mode = ExecutionMode.LOCAL;
- }
functionDeclarationContext.addVariable(
name,
expression.getParams().get(name),
- expression.getMetadata(),
- mode
+ expression.getMetadata()
);
- ++i;
}
}
@Override
public StaticContext visitFunctionDeclaration(FunctionDeclaration declaration, StaticContext argument) {
InlineFunctionExpression expression = (InlineFunctionExpression) declaration.getExpression();
+ if (expression.getActualReturnType() != null) {
+ expression.getActualReturnType().resolve(argument, declaration.getMetadata());
+ }
+ for (Entry itemType : expression.getParams().entrySet()) {
+ itemType.getValue().resolve(argument, declaration.getMetadata());
+ }
// define a static context for the function body, add params to the context and visit the body expression
- List modes = argument.getUserDefinedFunctionsExecutionModes()
- .getParameterExecutionMode(
- expression.getFunctionIdentifier(),
- expression.getMetadata()
- );
StaticContext functionDeclarationContext = new StaticContext(argument);
- expression.setStaticContext(argument);
- populateFunctionDeclarationStaticContext(functionDeclarationContext, modes, expression);
+ expression.setStaticContext(functionDeclarationContext);
+ populateFunctionDeclarationStaticContext(functionDeclarationContext, expression);
// visit the body first to make its execution mode available while adding the function to the catalog
this.visit(expression.getBody(), functionDeclarationContext);
- expression.initHighestExecutionMode(this.visitorConfig);
- declaration.initHighestExecutionMode(this.visitorConfig);
- expression.registerUserDefinedFunctionExecutionMode(
- this.visitorConfig
+ argument.addFunctionSignature(
+ expression.getFunctionIdentifier(),
+ new FunctionSignature(
+ new ArrayList<>(expression.getParams().values()),
+ expression.getReturnType()
+ )
);
return argument;
}
@@ -192,62 +175,29 @@ public StaticContext visitFunctionDeclaration(FunctionDeclaration declaration, S
public StaticContext visitInlineFunctionExpr(InlineFunctionExpression expression, StaticContext argument) {
// define a static context for the function body, add params to the context and visit the body expression
StaticContext functionDeclarationContext = new StaticContext(argument);
- expression.getParams()
- .forEach(
- (paramName, sequenceType) -> functionDeclarationContext.addVariable(
- paramName,
- sequenceType,
- expression.getMetadata(),
- ExecutionMode.LOCAL
- )
+ for (Entry entry : expression.getParams().entrySet()) {
+ functionDeclarationContext.addVariable(
+ entry.getKey(),
+ entry.getValue(),
+ expression.getMetadata()
);
+ }
// visit the body first to make its execution mode available while adding the function to the catalog
this.visit(expression.getBody(), functionDeclarationContext);
- expression.initHighestExecutionMode(this.visitorConfig);
- expression.registerUserDefinedFunctionExecutionMode(
- this.visitorConfig
- );
return functionDeclarationContext;
}
- @Override
- public StaticContext visitFunctionCall(FunctionCallExpression expression, StaticContext argument) {
- visitDescendants(expression, argument);
- FunctionIdentifier identifier = expression.getFunctionIdentifier();
- if (!BuiltinFunctionCatalogue.exists(identifier)) {
- List modes = new ArrayList<>();
- if (expression.isPartialApplication()) {
- for (@SuppressWarnings("unused")
- Expression parameter : expression.getArguments()) {
- modes.add(ExecutionMode.LOCAL);
- }
- } else {
- for (Expression parameter : expression.getArguments()) {
- modes.add(parameter.getHighestExecutionMode(this.visitorConfig));
- }
- }
- argument.getUserDefinedFunctionsExecutionModes()
- .setParameterExecutionMode(
- identifier,
- modes,
- expression.getMetadata()
- );
- }
- expression.initFunctionCallHighestExecutionMode(this.visitorConfig);
- return argument;
- }
// endregion
// region FLWOR
@Override
public StaticContext visitFlowrExpression(FlworExpression expression, StaticContext argument) {
Clause clause = expression.getReturnClause().getFirstClause();
- StaticContext result = this.visit(clause, argument);
+ StaticContext result = argument;
while (clause != null) {
result = this.visit(clause, result);
clause = clause.getNextClause();
}
- expression.initHighestExecutionMode(this.visitorConfig);
return argument;
}
@@ -256,22 +206,20 @@ public StaticContext visitFlowrExpression(FlworExpression expression, StaticCont
public StaticContext visitForClause(ForClause clause, StaticContext argument) {
// TODO visit at...
this.visit(clause.getExpression(), argument);
- clause.initHighestExecutionMode(this.visitorConfig);
StaticContext result = new StaticContext(argument);
result.addVariable(
clause.getVariableName(),
clause.getActualSequenceType(),
- clause.getMetadata(),
- clause.getVariableHighestStorageMode(this.visitorConfig)
+ clause.getMetadata()
);
+ clause.getSequenceType().resolve(result, clause.getMetadata());
if (clause.getPositionalVariableName() != null) {
result.addVariable(
clause.getPositionalVariableName(),
new SequenceType(BuiltinTypesCatalogue.integerItem),
- clause.getMetadata(),
- ExecutionMode.LOCAL
+ clause.getMetadata()
);
}
return result;
@@ -280,15 +228,14 @@ public StaticContext visitForClause(ForClause clause, StaticContext argument) {
@Override
public StaticContext visitLetClause(LetClause clause, StaticContext argument) {
this.visit(clause.getExpression(), argument);
- clause.initHighestExecutionMode(this.visitorConfig);
StaticContext result = new StaticContext(argument);
result.addVariable(
clause.getVariableName(),
clause.getActualSequenceType(),
- clause.getMetadata(),
- clause.getVariableHighestStorageMode(this.visitorConfig)
+ clause.getMetadata()
);
+ clause.getSequenceType().resolve(result, clause.getMetadata());
return result;
}
@@ -303,8 +250,7 @@ public StaticContext visitGroupByClause(GroupByClause clause, StaticContext argu
groupByClauseContext.addVariable(
variable.getVariableName(),
variable.getActualSequenceType(),
- clause.getMetadata(),
- ExecutionMode.LOCAL
+ clause.getMetadata()
);
} else if (!argument.isInScope(variable.getVariableName())) {
throw new UndeclaredVariableException(
@@ -313,19 +259,16 @@ public StaticContext visitGroupByClause(GroupByClause clause, StaticContext argu
);
}
}
- clause.initHighestExecutionMode(this.visitorConfig);
return groupByClauseContext;
}
@Override
public StaticContext visitCountClause(CountClause expression, StaticContext argument) {
- expression.initHighestExecutionMode(this.visitorConfig);
StaticContext result = new StaticContext(argument);
result.addVariable(
expression.getCountVariable().getVariableName(),
new SequenceType(BuiltinTypesCatalogue.integerItem, SequenceType.Arity.One),
- expression.getMetadata(),
- ExecutionMode.LOCAL
+ expression.getMetadata()
);
this.visit(expression.getCountVariable(), result);
return result;
@@ -344,11 +287,13 @@ public StaticContext visitTypeSwitchExpression(TypeSwitchExpression expression,
caseContext.addVariable(
variableName,
null,
- expression.getMetadata(),
- ExecutionMode.LOCAL
+ expression.getMetadata()
);
}
this.visit(c.getReturnExpression(), caseContext);
+ for (SequenceType sequenceType : c.getUnion()) {
+ sequenceType.resolve(argument, expression.getMetadata());
+ }
}
Name defaultCaseVariableName = expression.getDefaultCase().getVariableName();
@@ -360,12 +305,10 @@ public StaticContext visitTypeSwitchExpression(TypeSwitchExpression expression,
defaultCaseStaticContext.addVariable(
defaultCaseVariableName,
null,
- expression.getMetadata(),
- ExecutionMode.LOCAL
+ expression.getMetadata()
);
this.visit(expression.getDefaultCase().getReturnExpression(), defaultCaseStaticContext);
}
- expression.initHighestExecutionMode(this.visitorConfig);
// return the given context unchanged as defined variables go out of scope
return argument;
}
@@ -376,23 +319,64 @@ public StaticContext visitVariableDeclaration(VariableDeclaration variableDeclar
if (variableDeclaration.getExpression() != null) {
this.visit(variableDeclaration.getExpression(), argument);
}
- variableDeclaration.initHighestExecutionMode(this.visitorConfig);
- if (argument.hasVariable(variableDeclaration.getVariableName())) {
- if (!this.visitorConfig.suppressErrorsForFunctionSignatureCollision()) {
- throw new VariableAlreadyExistsException(
- variableDeclaration.getVariableName(),
- variableDeclaration.getMetadata()
- );
- }
- } else {
- // first pass.
- argument.addVariable(
- variableDeclaration.getVariableName(),
- variableDeclaration.getActualSequenceType(),
- variableDeclaration.getMetadata(),
- variableDeclaration.getVariableHighestStorageMode(this.visitorConfig)
- );
+ // first pass.
+ argument.addVariable(
+ variableDeclaration.getVariableName(),
+ variableDeclaration.getActualSequenceType(),
+ variableDeclaration.getMetadata()
+ );
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitTypeDeclaration(TypeDeclaration declaration, StaticContext argument) {
+ ItemType type = declaration.getDefinition();
+ // only first pass
+ argument.getInScopeSchemaTypes().addInScopeSchemaType(type, declaration.getMetadata());
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitProlog(Prolog prolog, StaticContext argument) {
+ StaticContext generatedContext = visitDescendants(prolog, argument);
+ for (ItemType itemType : generatedContext.getInScopeSchemaTypes().getInScopeSchemaTypes()) {
+ itemType.resolve(generatedContext, prolog.getMetadata());
}
+ return generatedContext;
+ }
+
+ @Override
+ public StaticContext visitValidateTypeExpression(ValidateTypeExpression expression, StaticContext argument) {
+ visitDescendants(expression, argument);
+ expression.getSequenceType().resolve(argument, expression.getMetadata());
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitCastExpression(CastExpression expression, StaticContext argument) {
+ visitDescendants(expression, argument);
+ expression.getSequenceType().resolve(argument, expression.getMetadata());
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitCastableExpression(CastableExpression expression, StaticContext argument) {
+ visitDescendants(expression, argument);
+ expression.getSequenceType().resolve(argument, expression.getMetadata());
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitTreatExpression(TreatExpression expression, StaticContext argument) {
+ visitDescendants(expression, argument);
+ expression.getSequenceType().resolve(argument, expression.getMetadata());
+ return argument;
+ }
+
+ @Override
+ public StaticContext visitInstanceOfExpression(InstanceOfExpression expression, StaticContext argument) {
+ visitDescendants(expression, argument);
+ expression.getSequenceType().resolve(argument, expression.getMetadata());
return argument;
}
diff --git a/src/main/java/org/rumbledb/compiler/TranslationVisitor.java b/src/main/java/org/rumbledb/compiler/TranslationVisitor.java
index fdcfb10336..47d874e6f5 100644
--- a/src/main/java/org/rumbledb/compiler/TranslationVisitor.java
+++ b/src/main/java/org/rumbledb/compiler/TranslationVisitor.java
@@ -20,7 +20,7 @@
package org.rumbledb.compiler;
-import static org.rumbledb.types.SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+import static org.rumbledb.types.SequenceType.ITEM_STAR;
import java.io.IOException;
import java.math.BigDecimal;
@@ -399,14 +399,14 @@ public Name parseName(JsoniqParser.QnameContext ctx, boolean isFunction, boolean
@Override
public Node visitFunctionDecl(JsoniqParser.FunctionDeclContext ctx) {
Name name = parseName(ctx.qname(), true, false);
- Map fnParams = new LinkedHashMap<>();
+ LinkedHashMap fnParams = new LinkedHashMap<>();
SequenceType fnReturnType = null;
Name paramName;
SequenceType paramType;
if (ctx.paramList() != null) {
for (JsoniqParser.ParamContext param : ctx.paramList().param()) {
paramName = parseName(param.qname(), false, false);
- paramType = MOST_GENERAL_SEQUENCE_TYPE;
+ paramType = ITEM_STAR;
if (fnParams.containsKey(paramName)) {
throw new DuplicateParamNameException(
name,
@@ -417,7 +417,7 @@ public Node visitFunctionDecl(JsoniqParser.FunctionDeclContext ctx) {
if (param.sequenceType() != null) {
paramType = this.processSequenceType(param.sequenceType());
} else {
- paramType = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ paramType = SequenceType.ITEM_STAR;
}
fnParams.put(paramName, paramType);
}
@@ -470,7 +470,7 @@ public Node visitTypeDecl(JsoniqParser.TypeDeclContext ctx) {
throw pe;
}
Name name = parseName(ctx.qname(), false, true);
- ItemType type = ItemTypeFactory.createItemTypeFromJSoundCompactItem(name, definitionItem);
+ ItemType type = ItemTypeFactory.createItemTypeFromJSoundCompactItem(name, definitionItem, this.moduleContext);
return new TypeDeclaration(
type,
createMetadataFromContext(ctx)
@@ -1374,14 +1374,14 @@ public Node visitNamedFunctionRef(JsoniqParser.NamedFunctionRefContext ctx) {
@Override
public Node visitInlineFunctionExpr(JsoniqParser.InlineFunctionExprContext ctx) {
- Map fnParams = new LinkedHashMap<>();
- SequenceType fnReturnType = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ LinkedHashMap fnParams = new LinkedHashMap<>();
+ SequenceType fnReturnType = SequenceType.ITEM_STAR;
Name paramName;
SequenceType paramType;
if (ctx.paramList() != null) {
for (JsoniqParser.ParamContext param : ctx.paramList().param()) {
paramName = parseName(param.qname(), false, false);
- paramType = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ paramType = SequenceType.ITEM_STAR;
if (fnParams.containsKey(paramName)) {
throw new DuplicateParamNameException(
Name.createVariableInDefaultFunctionNamespace("inline-function`"),
@@ -1392,7 +1392,7 @@ public Node visitInlineFunctionExpr(JsoniqParser.InlineFunctionExprContext ctx)
if (param.sequenceType() != null) {
paramType = this.processSequenceType(param.sequenceType());
} else {
- paramType = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ paramType = SequenceType.ITEM_STAR;
}
fnParams.put(paramName, paramType);
}
diff --git a/src/main/java/org/rumbledb/compiler/VisitorHelpers.java b/src/main/java/org/rumbledb/compiler/VisitorHelpers.java
index 51f3134f70..21554015bd 100644
--- a/src/main/java/org/rumbledb/compiler/VisitorHelpers.java
+++ b/src/main/java/org/rumbledb/compiler/VisitorHelpers.java
@@ -55,10 +55,8 @@ private static void pruneModules(Node node, RumbleRuntimeConfiguration conf) {
}
private static void inferTypes(Module module, RumbleRuntimeConfiguration conf) {
- System.out.println("* Starting type inference *");
new InferTypeVisitor(conf).visit(module, module.getStaticContext());
- System.out.println("* Completed type inference *");
- if (conf.printInferredTypes()) {
+ if (conf.printInferredTypes() || conf.isPrintIteratorTree()) {
printTree(module, conf);
}
}
@@ -141,9 +139,8 @@ public static MainModule parseJSONiqMainModule(
pruneModules(mainModule, configuration);
resolveDependencies(mainModule, configuration);
populateStaticContext(mainModule, configuration);
- if (configuration.doStaticAnalysis()) {
- inferTypes(mainModule, configuration);
- }
+ inferTypes(mainModule, configuration);
+ populateExecutionModes(mainModule, configuration);
return mainModule;
} catch (ParseCancellationException ex) {
ParsingException e = new ParsingException(
@@ -182,9 +179,8 @@ public static MainModule parseXQueryMainModule(
pruneModules(mainModule, configuration);
resolveDependencies(mainModule, configuration);
populateStaticContext(mainModule, configuration);
- if (configuration.doStaticAnalysis()) {
- inferTypes(mainModule, configuration);
- }
+ inferTypes(mainModule, configuration);
+ populateExecutionModes(mainModule, configuration);
return mainModule;
} catch (ParseCancellationException ex) {
ParsingException e = new ParsingException(
@@ -298,11 +294,11 @@ public static LibraryModule parseXQueryLibraryModule(
}
}
- private static void populateStaticContext(Module module, RumbleRuntimeConfiguration conf) {
+ private static void populateExecutionModes(Module module, RumbleRuntimeConfiguration conf) {
if (conf.isPrintIteratorTree()) {
printTree(module, conf);
}
- StaticContextVisitor visitor = new StaticContextVisitor();
+ ExecutionModeVisitor visitor = new ExecutionModeVisitor();
visitor.visit(module, module.getStaticContext());
@@ -351,6 +347,18 @@ private static void populateStaticContext(Module module, RumbleRuntimeConfigurat
}
+ private static void populateStaticContext(Module module, RumbleRuntimeConfiguration conf) {
+ if (conf.isPrintIteratorTree()) {
+ printTree(module, conf);
+ }
+ StaticContextVisitor visitor = new StaticContextVisitor();
+ visitor.visit(module, module.getStaticContext());
+
+ if (conf.isPrintIteratorTree()) {
+ printTree(module, conf);
+ }
+ }
+
public static DynamicContext createDynamicContext(Node node, RumbleRuntimeConfiguration configuration) {
DynamicContextVisitor visitor = new DynamicContextVisitor(configuration);
return visitor.visit(node, null);
diff --git a/src/main/java/org/rumbledb/compiler/XQueryTranslationVisitor.java b/src/main/java/org/rumbledb/compiler/XQueryTranslationVisitor.java
index c5bf1b20b3..78143f439b 100644
--- a/src/main/java/org/rumbledb/compiler/XQueryTranslationVisitor.java
+++ b/src/main/java/org/rumbledb/compiler/XQueryTranslationVisitor.java
@@ -42,7 +42,7 @@
import java.net.URI;
import java.util.*;
-import static org.rumbledb.types.SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+import static org.rumbledb.types.SequenceType.ITEM_STAR;
public class XQueryTranslationVisitor extends org.rumbledb.parser.XQueryParserBaseVisitor {
private StaticContext moduleContext;
@@ -319,7 +319,7 @@ public Node visitVarDecl(XQueryParser.VarDeclContext ctx) {
if (ctx.typeDeclaration() != null) {
seq = this.processSequenceType(ctx.typeDeclaration().sequenceType());
} else {
- seq = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ seq = SequenceType.ITEM_STAR;
}
XQueryParser.ExprSingleContext exprSingle = null;
@@ -335,7 +335,7 @@ public Node visitVarDecl(XQueryParser.VarDeclContext ctx) {
}
if (exprSingle != null) {
expr = (Expression) this.visitExprSingle(exprSingle);
- if (!seq.equals(SequenceType.MOST_GENERAL_SEQUENCE_TYPE)) {
+ if (!seq.equals(SequenceType.ITEM_STAR)) {
expr = new TreatExpression(expr, seq, ErrorCode.UnexpectedTypeErrorCode, expr.getMetadata());
}
}
@@ -375,8 +375,8 @@ private void processAnnotations(XQueryParser.AnnotationsContext annotations) {
@Override
public Node visitFunctionDecl(XQueryParser.FunctionDeclContext ctx) {
Name name = parseName(ctx.eqName(), true, false);
- Map fnParams = new LinkedHashMap<>();
- SequenceType fnReturnType = MOST_GENERAL_SEQUENCE_TYPE;
+ LinkedHashMap fnParams = new LinkedHashMap<>();
+ SequenceType fnReturnType = ITEM_STAR;
Name paramName;
SequenceType paramType;
@@ -387,7 +387,7 @@ public Node visitFunctionDecl(XQueryParser.FunctionDeclContext ctx) {
if (ctx.functionParams() != null) {
for (XQueryParser.FunctionParamContext param : ctx.functionParams().functionParam()) {
paramName = parseName(param.qName(), false, false);
- paramType = MOST_GENERAL_SEQUENCE_TYPE;
+ paramType = ITEM_STAR;
if (fnParams.containsKey(paramName)) {
throw new DuplicateParamNameException(
name,
@@ -398,7 +398,7 @@ public Node visitFunctionDecl(XQueryParser.FunctionDeclContext ctx) {
if (param.typeDeclaration() != null) {
paramType = this.processSequenceType(param.typeDeclaration().sequenceType());
} else {
- paramType = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ paramType = SequenceType.ITEM_STAR;
}
fnParams.put(paramName, paramType);
}
@@ -407,7 +407,7 @@ public Node visitFunctionDecl(XQueryParser.FunctionDeclContext ctx) {
if (ctx.functionReturn() != null) {
fnReturnType = this.processSequenceType(ctx.functionReturn().sequenceType());
} else {
- fnReturnType = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ fnReturnType = SequenceType.ITEM_STAR;
}
Expression bodyExpression = null;
@@ -1283,15 +1283,15 @@ public Node visitNamedFunctionRef(XQueryParser.NamedFunctionRefContext ctx) {
@Override
public Node visitInlineFunctionRef(XQueryParser.InlineFunctionRefContext ctx) {
- Map fnParams = new LinkedHashMap<>();
- SequenceType fnReturnType = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ LinkedHashMap fnParams = new LinkedHashMap<>();
+ SequenceType fnReturnType = SequenceType.ITEM_STAR;
Name paramName;
SequenceType paramType;
if (ctx.functionParams() != null) {
for (XQueryParser.FunctionParamContext param : ctx.functionParams().functionParam()) {
// TODO here we have qname instead eqName
paramName = parseName(param.name, false, false);
- paramType = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ paramType = SequenceType.ITEM_STAR;
if (fnParams.containsKey(paramName)) {
throw new DuplicateParamNameException(
Name.createVariableInDefaultFunctionNamespace("inline-function`"),
@@ -1302,7 +1302,7 @@ public Node visitInlineFunctionRef(XQueryParser.InlineFunctionRefContext ctx) {
if (param.type.sequenceType() != null) {
paramType = this.processSequenceType(param.type.sequenceType());
} else {
- paramType = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ paramType = SequenceType.ITEM_STAR;
}
fnParams.put(paramName, paramType);
}
@@ -1411,7 +1411,7 @@ public Node visitForBinding(XQueryParser.ForBindingContext ctx) {
if (ctx.seq != null) {
seq = this.processSequenceType(ctx.seq.sequenceType());
} else {
- seq = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ seq = SequenceType.ITEM_STAR;
}
emptyFlag = (ctx.flag != null);
Name atVar = null;
@@ -1432,7 +1432,7 @@ public Node visitForBinding(XQueryParser.ForBindingContext ctx) {
seq.getItemType(),
SequenceType.Arity.ZeroOrMore
);
- if (!expressionType.equals(SequenceType.MOST_GENERAL_SEQUENCE_TYPE)) {
+ if (!expressionType.equals(SequenceType.ITEM_STAR)) {
expr = new TreatExpression(expr, expressionType, ErrorCode.UnexpectedTypeErrorCode, expr.getMetadata());
}
@@ -1461,11 +1461,11 @@ public Node visitLetBinding(XQueryParser.LetBindingContext ctx) {
if (ctx.typeDeclaration() != null) {
seq = this.processSequenceType(ctx.typeDeclaration().sequenceType());
} else {
- seq = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ seq = SequenceType.ITEM_STAR;
}
Expression expr = (Expression) this.visitExprSingle(ctx.exprSingle());
- if (!seq.equals(SequenceType.MOST_GENERAL_SEQUENCE_TYPE)) {
+ if (!seq.equals(SequenceType.ITEM_STAR)) {
expr = new TreatExpression(expr, seq, ErrorCode.UnexpectedTypeErrorCode, expr.getMetadata());
}
@@ -1507,12 +1507,12 @@ public GroupByVariableDeclaration processGroupByVar(XQueryParser.GroupingSpecCon
if (ctx.typeDeclaration() != null) {
seq = this.processSequenceType(ctx.typeDeclaration().sequenceType());
} else {
- seq = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ seq = SequenceType.ITEM_STAR;
}
if (ctx.exprSingle() != null) {
expr = (Expression) this.visitExprSingle(ctx.exprSingle());
- if (!seq.equals(SequenceType.MOST_GENERAL_SEQUENCE_TYPE)) {
+ if (!seq.equals(SequenceType.ITEM_STAR)) {
expr = new TreatExpression(expr, seq, ErrorCode.UnexpectedTypeErrorCode, expr.getMetadata());
}
@@ -1620,7 +1620,7 @@ public Node visitQuantifiedExpr(XQueryParser.QuantifiedExprContext ctx) {
if (currentVariable.typeDeclaration() != null) {
sequenceType = this.processSequenceType(currentVariable.typeDeclaration().sequenceType());
} else {
- sequenceType = SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+ sequenceType = SequenceType.ITEM_STAR;
}
varExpression = (Expression) this.visitExprSingle(currentVariable.exprSingle());
diff --git a/src/main/java/org/rumbledb/config/RumbleRuntimeConfiguration.java b/src/main/java/org/rumbledb/config/RumbleRuntimeConfiguration.java
index 8a20b1b317..a700c724d7 100644
--- a/src/main/java/org/rumbledb/config/RumbleRuntimeConfiguration.java
+++ b/src/main/java/org/rumbledb/config/RumbleRuntimeConfiguration.java
@@ -322,27 +322,78 @@ public boolean isLocal() {
@Override
public String toString() {
- String result = "";
- result += "Master: "
- + SparkSessionManager.getInstance().getJavaSparkContext().getConf().get("spark.master")
- + "\n"
- +
+ StringBuffer sb = new StringBuffer();
+ sb.append(
+ "App name: "
+ + SparkSessionManager.getInstance().getJavaSparkContext().getConf().get("spark.app.name", "(not set)")
+ + "\n"
+ );
+ sb.append(
+ "Master: "
+ + SparkSessionManager.getInstance().getJavaSparkContext().getConf().get("spark.master", "(not set)")
+ + "\n"
+ );
+ sb.append(
+ "Driver's memory: "
+ + SparkSessionManager.getInstance()
+ .getJavaSparkContext()
+ .getConf()
+ .get("spark.driver.memory", "(not set)")
+ + "\n"
+ );
+ sb.append(
+ "Number of executors (only applies if running on a cluster): "
+ + SparkSessionManager.getInstance()
+ .getJavaSparkContext()
+ .getConf()
+ .get("spark.executor.instances", "(not set)")
+ + "\n"
+ );
+ sb.append(
+ "Cores per executor (only applies if running on a cluster): "
+ + SparkSessionManager.getInstance()
+ .getJavaSparkContext()
+ .getConf()
+ .get("spark.executor.cores", "(not set)")
+ + "\n"
+ );
+ sb.append(
+ "Memory per executor (only applies if running on a cluster): "
+ + SparkSessionManager.getInstance()
+ .getJavaSparkContext()
+ .getConf()
+ .get("spark.executor.memory", "(not set)")
+ + "\n"
+ );
+ sb.append(
+ "Dynamic allocation: "
+ + SparkSessionManager.getInstance()
+ .getJavaSparkContext()
+ .getConf()
+ .get("spark.dynamicAllocation.enabled", "(not set)")
+ + "\n"
+ );
+ sb.append(
"Item Display Limit: "
- + getResultSizeCap()
- + "\n"
- +
+ + getResultSizeCap()
+ + "\n"
+ );
+ sb.append(
"Output Path: "
- + (this.arguments.getOrDefault("output-path", "-"))
- + "\n"
- +
+ + (this.arguments.getOrDefault("output-path", "-"))
+ + "\n"
+ );
+ sb.append(
"Log Path: "
- + (this.arguments.getOrDefault("log-path", "-"))
- + "\n"
- +
+ + (this.arguments.getOrDefault("log-path", "-"))
+ + "\n"
+ );
+ sb.append(
"Query Path : "
- + (this.arguments.getOrDefault("query-path", "-"))
- + "\n";
- return result;
+ + (this.arguments.getOrDefault("query-path", "-"))
+ + "\n"
+ );
+ return sb.toString();
}
@Override
diff --git a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
index d2b825030f..e340dafbb0 100644
--- a/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
+++ b/src/main/java/org/rumbledb/context/BuiltinFunctionCatalogue.java
@@ -4,7 +4,6 @@
import java.util.Collections;
import java.util.HashMap;
-import org.rumbledb.exceptions.OurBadException;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.runtime.functions.NullFunctionIterator;
import org.rumbledb.runtime.functions.arrays.ArrayDescendantFunctionIterator;
@@ -179,7 +178,7 @@ public static BuiltinFunction getBuiltinFunction(FunctionIdentifier identifier)
return builtinFunctions.get(array);
}
}
- throw new OurBadException("Unknown builtin function: " + identifier);
+ return null;
}
public static boolean exists(FunctionIdentifier identifier) {
@@ -2298,7 +2297,23 @@ private static BuiltinFunction createBuiltinFunction(
"get-transformer"
),
"string",
- "item",
+ "function(object*, object) as object*",
+ GetTransformerFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ );
+
+ /**
+ * function fetches the transformer class from SparkML API
+ */
+ static final BuiltinFunction get_transformer2 = createBuiltinFunction(
+ new Name(
+ Name.JN_NS,
+ "jn",
+ "get-transformer"
+ ),
+ "string",
+ "object",
+ "function(object*, object) as object*",
GetTransformerFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
@@ -2313,7 +2328,23 @@ private static BuiltinFunction createBuiltinFunction(
"get-estimator"
),
"string",
- "item",
+ "function(object*, object) as function(object*, object) as object*",
+ GetEstimatorFunctionIterator.class,
+ BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
+ );
+
+ /**
+ * function fetches the estimator class from SparkML API
+ */
+ static final BuiltinFunction get_estimator2 = createBuiltinFunction(
+ new Name(
+ Name.JN_NS,
+ "jn",
+ "get-estimator"
+ ),
+ "string",
+ "object",
+ "function(object*, object) as function(object*, object) as object*",
GetEstimatorFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.LOCAL
);
@@ -2327,9 +2358,9 @@ private static BuiltinFunction createBuiltinFunction(
"jn",
"annotate"
),
- "item*", // TODO: revert back to ObjectItem when TypePromotionIter. has DF implementation
+ "object*", // TODO: revert back to ObjectItem when TypePromotionIter. has DF implementation
"object",
- "item*", // TODO: revert back to ObjectItem when TypePromotionIter. has DF implementation
+ "object*", // TODO: revert back to ObjectItem when TypePromotionIter. has DF implementation
AnnotateFunctionIterator.class,
BuiltinFunction.BuiltinFunctionExecutionMode.DATAFRAME
);
@@ -2521,7 +2552,9 @@ private static BuiltinFunction createBuiltinFunction(
builtinFunctions.put(values.getIdentifier(), values);
builtinFunctions.put(get_transformer.getIdentifier(), get_transformer);
+ builtinFunctions.put(get_transformer2.getIdentifier(), get_transformer2);
builtinFunctions.put(get_estimator.getIdentifier(), get_estimator);
+ builtinFunctions.put(get_estimator2.getIdentifier(), get_estimator2);
builtinFunctions.put(annotate.getIdentifier(), annotate);
builtinFunctions.put(trace.getIdentifier(), trace);
diff --git a/src/main/java/org/rumbledb/context/InScopeVariable.java b/src/main/java/org/rumbledb/context/InScopeVariable.java
index 54d223131b..86f0e098a3 100644
--- a/src/main/java/org/rumbledb/context/InScopeVariable.java
+++ b/src/main/java/org/rumbledb/context/InScopeVariable.java
@@ -47,6 +47,10 @@ public ExecutionMode getStorageMode() {
return this.storageMode;
}
+ public void setStorageMode(ExecutionMode mode) {
+ this.storageMode = mode;
+ }
+
@Override
public void write(Kryo kryo, Output output) {
kryo.writeObject(output, this.name);
diff --git a/src/main/java/org/rumbledb/context/Name.java b/src/main/java/org/rumbledb/context/Name.java
index 0c25facff4..abfb635463 100644
--- a/src/main/java/org/rumbledb/context/Name.java
+++ b/src/main/java/org/rumbledb/context/Name.java
@@ -143,6 +143,30 @@ public static Name createVariableResolvingPrefix(String prefix, String localName
}
}
+ /**
+ * Creates an expanded name resolving the prefix from namespace bindings.
+ *
+ * @param prefixedName the QName literal.
+ * @param moduleContext the module context containing the bindings.
+ * @return the expanded name.
+ */
+ public static Name createTypeNameFromLiteral(String prefixedName, StaticContext moduleContext) {
+ int pos = prefixedName.indexOf(":");
+ String prefix = null;
+ String localName = prefixedName;
+ if (pos == -1) {
+ return new Name(JSONIQ_DEFAULT_TYPE_NS, prefix, localName);
+ }
+ prefix = prefixedName.substring(0, pos);
+ localName = prefixedName.substring(pos + 1);
+ String namespace = moduleContext.resolveNamespace(prefix);
+ if (namespace != null) {
+ return new Name(namespace, prefix, localName);
+ } else {
+ throw new OurBadException("Prefix " + prefix + " could not be resolved against a namespace in scope.");
+ }
+ }
+
/**
* Converts the expanded name to an expanded name whose local name has a #n suffix, where n is the arity of the
* function,
diff --git a/src/main/java/org/rumbledb/context/NamedFunctions.java b/src/main/java/org/rumbledb/context/NamedFunctions.java
index 5ac764d70a..6dd8bf242d 100644
--- a/src/main/java/org/rumbledb/context/NamedFunctions.java
+++ b/src/main/java/org/rumbledb/context/NamedFunctions.java
@@ -95,7 +95,7 @@ public static RuntimeIterator buildUserDefinedFunctionCallIterator(
metadata
);
SequenceType sequenceType = functionItem.getSignature().getReturnType();
- if (sequenceType.equals(SequenceType.MOST_GENERAL_SEQUENCE_TYPE)) {
+ if (sequenceType.equals(SequenceType.ITEM_STAR)) {
return functionCallIterator;
}
if (
@@ -162,12 +162,15 @@ public static RuntimeIterator getBuiltInFunctionIterator(
ExceptionMetadata metadata
) {
BuiltinFunction builtinFunction = BuiltinFunctionCatalogue.getBuiltinFunction(identifier);
+ if (builtinFunction == null) {
+ throw new UnknownFunctionCallException(identifier.getName(), identifier.getArity(), metadata);
+ }
for (int i = 0; i < arguments.size(); i++) {
if (
!builtinFunction.getSignature()
.getParameterTypes()
.get(i)
- .equals(SequenceType.MOST_GENERAL_SEQUENCE_TYPE)
+ .equals(SequenceType.ITEM_STAR)
) {
SequenceType sequenceType = builtinFunction.getSignature().getParameterTypes().get(i);
if (
@@ -215,7 +218,7 @@ public static RuntimeIterator getBuiltInFunctionIterator(
);
}
- if (!builtinFunction.getSignature().getReturnType().equals(SequenceType.MOST_GENERAL_SEQUENCE_TYPE)) {
+ if (!builtinFunction.getSignature().getReturnType().equals(SequenceType.ITEM_STAR)) {
if (!checkReturnTypesOfBuiltinFunctions) {
return functionCallIterator;
}
diff --git a/src/main/java/org/rumbledb/context/StaticContext.java b/src/main/java/org/rumbledb/context/StaticContext.java
index 7069738b79..c02c9a1196 100644
--- a/src/main/java/org/rumbledb/context/StaticContext.java
+++ b/src/main/java/org/rumbledb/context/StaticContext.java
@@ -24,8 +24,10 @@
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.OurBadException;
import org.rumbledb.exceptions.SemanticException;
+import org.rumbledb.exceptions.UnknownFunctionCallException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.types.FunctionSignature;
+import org.rumbledb.types.ItemType;
import org.rumbledb.types.SequenceType;
import com.esotericsoftware.kryo.Kryo;
@@ -37,6 +39,7 @@
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
public class StaticContext implements Serializable, KryoSerializable {
@@ -153,7 +156,7 @@ private InScopeVariable getInScopeVariable(Name varName) {
}
ancestor = ancestor.parent;
}
- throw new SemanticException("Variable " + varName + " not in scope", null);
+ throw new SemanticException("Variable " + varName + " not in scope", ExceptionMetadata.EMPTY_METADATA);
}
}
@@ -168,7 +171,11 @@ public FunctionSignature getFunctionSignature(FunctionIdentifier identifier) {
}
ancestor = ancestor.parent;
}
- throw new SemanticException("function " + identifier + " not in scope", null);
+ throw new UnknownFunctionCallException(
+ identifier.getName(),
+ identifier.getArity(),
+ ExceptionMetadata.EMPTY_METADATA
+ );
}
}
@@ -193,29 +200,53 @@ public ExecutionMode getVariableStorageMode(Name varName) {
return getInScopeVariable(varName).getStorageMode();
}
+ public void setVariableStorageMode(Name varName, ExecutionMode mode) {
+ getInScopeVariable(varName).setStorageMode(mode);
+ }
+
public void addVariable(
Name varName,
SequenceType type,
- ExceptionMetadata metadata,
- ExecutionMode storageMode
+ ExceptionMetadata metadata
) {
- this.inScopeVariables.put(varName, new InScopeVariable(varName, type, metadata, storageMode));
+ this.inScopeVariables.put(varName, new InScopeVariable(varName, type, metadata, ExecutionMode.UNSET));
}
public void addFunctionSignature(FunctionIdentifier identifier, FunctionSignature signature) {
this.staticallyKnownFunctionSignatures.put(identifier, signature);
}
- protected Map getInScopeVariables() {
+ public Map getInScopeVariables() {
return this.inScopeVariables;
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append("Static context with variables: ");
- this.inScopeVariables.keySet().forEach(a -> stringBuilder.append(a));
- stringBuilder.append("\n");
+ stringBuilder.append("Static context with variables:\n");
+ for (Entry entry : this.inScopeVariables.entrySet()) {
+ stringBuilder.append(entry.getKey());
+ stringBuilder.append(" as " + entry.getValue().getSequenceType());
+ stringBuilder.append(" (namespace " + entry.getKey().getNamespace() + ")");
+ stringBuilder.append(" | " + entry.getValue().getStorageMode());
+ stringBuilder.append("\n");
+ }
+ stringBuilder.append("Static context with user-defined functions:\n");
+ for (Entry entry : this.staticallyKnownFunctionSignatures.entrySet()) {
+ stringBuilder.append(entry.getKey());
+ stringBuilder.append(" as " + entry.getValue());
+ stringBuilder.append(" (namespace " + entry.getKey().getName().getNamespace() + ")");
+ stringBuilder.append("\n");
+ }
+ if (this.inScopeSchemaTypes != null) {
+ stringBuilder.append("Static context with user-defined types:\n");
+ for (ItemType itemType : this.inScopeSchemaTypes.getInScopeSchemaTypes()) {
+ stringBuilder.append(itemType.getName());
+ stringBuilder.append(itemType.isResolved() ? " (resolved)" : " (unresolved)");
+ stringBuilder.append("\n");
+ }
+ stringBuilder.append("\n");
+ }
if (this.userDefinedFunctionExecutionModes != null) {
stringBuilder.append(this.userDefinedFunctionExecutionModes.toString());
}
@@ -288,6 +319,12 @@ public void importModuleContext(StaticContext moduleContext, String targetNamesp
this.inScopeVariables.put(name, variable);
}
}
+ for (FunctionIdentifier fi : moduleContext.staticallyKnownFunctionSignatures.keySet()) {
+ if (fi.getName().getNamespace().contentEquals(targetNamespace)) {
+ FunctionSignature signature = moduleContext.staticallyKnownFunctionSignatures.get(fi);
+ this.staticallyKnownFunctionSignatures.put(fi, signature);
+ }
+ }
}
public void setUserDefinedFunctionsExecutionModes(
@@ -354,13 +391,13 @@ public void incrementArities(StaticContext stopContext, Set varToExclude)
);
StaticContext current = this.parent;
while (current != null && current != stopContext) {
+ System.err.println("Next loop: " + current);
for (Map.Entry entry : current.inScopeVariables.entrySet()) {
if (!this.inScopeVariables.containsKey(entry.getKey())) {
this.addVariable(
entry.getKey(),
entry.getValue().getSequenceType().incrementArity(),
- entry.getValue().getMetadata(),
- entry.getValue().getStorageMode()
+ entry.getValue().getMetadata()
);
}
}
diff --git a/src/main/java/org/rumbledb/exceptions/ExceptionMetadata.java b/src/main/java/org/rumbledb/exceptions/ExceptionMetadata.java
index e5a6332997..d4401e2b3d 100644
--- a/src/main/java/org/rumbledb/exceptions/ExceptionMetadata.java
+++ b/src/main/java/org/rumbledb/exceptions/ExceptionMetadata.java
@@ -42,6 +42,7 @@ public class ExceptionMetadata implements Serializable {
* @param location the URI of the JSONiq module at which the exception occurred.
* @param line the line number at which the error occurred.
* @param column the column number at which the error occurred.
+ * @param code the query code around the error.
*/
public ExceptionMetadata(String location, int line, int column, String code) {
this.location = location;
@@ -78,9 +79,9 @@ public String getLocation() {
}
/**
- * Returns the column number.
+ * Returns the the query code around the error.
*
- * @return the column number.
+ * @return the the query code around the error.
*/
public String getCode() {
return this.code;
diff --git a/src/main/java/org/rumbledb/exceptions/InvalidRumbleMLParamException.java b/src/main/java/org/rumbledb/exceptions/InvalidRumbleMLParamException.java
index 5b42aede50..b8e16355f4 100644
--- a/src/main/java/org/rumbledb/exceptions/InvalidRumbleMLParamException.java
+++ b/src/main/java/org/rumbledb/exceptions/InvalidRumbleMLParamException.java
@@ -26,11 +26,18 @@ public class InvalidRumbleMLParamException extends RumbleException {
private static final long serialVersionUID = 1L;
+ String message;
+
public InvalidRumbleMLParamException(String message, ExceptionMetadata metadata) {
super(
"Invalid Param; " + message,
ErrorCode.InvalidRumbleMLParamErrorCode,
metadata
);
+ this.message = message;
+ }
+
+ public String getMLMessage() {
+ return this.message;
}
}
diff --git a/src/main/java/org/rumbledb/exceptions/RumbleException.java b/src/main/java/org/rumbledb/exceptions/RumbleException.java
index 3f5b4d66fd..fe2772adb0 100644
--- a/src/main/java/org/rumbledb/exceptions/RumbleException.java
+++ b/src/main/java/org/rumbledb/exceptions/RumbleException.java
@@ -123,6 +123,10 @@ public ExceptionMetadata getMetadata() {
return this.metadata;
}
+ public void setMetadata(ExceptionMetadata metadata) {
+ this.metadata = metadata;
+ }
+
public String getJSONiqErrorMessage() {
return this.errorMessage;
}
diff --git a/src/main/java/org/rumbledb/exceptions/UnknownFunctionCallException.java b/src/main/java/org/rumbledb/exceptions/UnknownFunctionCallException.java
index 0c0e150641..aa8e889c05 100644
--- a/src/main/java/org/rumbledb/exceptions/UnknownFunctionCallException.java
+++ b/src/main/java/org/rumbledb/exceptions/UnknownFunctionCallException.java
@@ -20,6 +20,7 @@
package org.rumbledb.exceptions;
+import org.rumbledb.context.FunctionIdentifier;
import org.rumbledb.context.Name;
import org.rumbledb.errorcodes.ErrorCode;
@@ -39,4 +40,17 @@ public UnknownFunctionCallException(Name fnName, int arity, ExceptionMetadata me
metadata
);
}
+
+ public UnknownFunctionCallException(FunctionIdentifier identifier, ExceptionMetadata metadata) {
+ super(
+ "Undefined function call; Entered function name and arity doesn't match a defined function signature: \""
+ +
+ identifier.getName()
+ + "\" called with "
+ + identifier.getArity()
+ + " parameters.",
+ ErrorCode.InvalidFunctionCallErrorCode,
+ metadata
+ );
+ }
}
diff --git a/src/main/java/org/rumbledb/expressions/Expression.java b/src/main/java/org/rumbledb/expressions/Expression.java
index 9cc6c5529d..6ba0e8a19c 100644
--- a/src/main/java/org/rumbledb/expressions/Expression.java
+++ b/src/main/java/org/rumbledb/expressions/Expression.java
@@ -23,6 +23,7 @@
import org.rumbledb.context.StaticContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.types.SequenceType;
+import org.rumbledb.types.SequenceType.Arity;
/**
* An expression is the first-class citizen in JSONiq syntax. Any expression
@@ -38,7 +39,7 @@ public abstract class Expression extends Node {
protected StaticContext staticContext;
- protected SequenceType inferredSequenceType;
+ protected SequenceType staticSequenceType;
protected Expression(ExceptionMetadata metadata) {
super(metadata);
@@ -68,18 +69,32 @@ public void setStaticContext(StaticContext staticContext) {
*
* @return the statically inferred sequence type.
*/
- public SequenceType getInferredSequenceType() {
- return this.inferredSequenceType;
+ public SequenceType getStaticSequenceType() {
+ return this.staticSequenceType;
+ }
+
+ /**
+ * Tells whether this expression is guaranteed to return
+ * zero or one item but not more.
+ *
+ * @return true if yes, false otherwise.
+ */
+ public boolean alwaysReturnsAtMostOneItem() {
+ return this.staticSequenceType.getArity().equals(Arity.One)
+ ||
+ this.staticSequenceType.getArity().equals(Arity.OneOrZero)
+ ||
+ this.staticSequenceType.getArity().equals(Arity.Zero);
}
/**
* Sets the inferred static type, for used by the static
* analysis visitor.
*
- * @param inferredSequenceType the statically inferred sequence type to set.
+ * @param staticSequenceType the statically inferred sequence type to set.
*/
- public void setInferredSequenceType(SequenceType inferredSequenceType) {
- this.inferredSequenceType = inferredSequenceType;
+ public void setStaticSequenceType(SequenceType staticSequenceType) {
+ this.staticSequenceType = staticSequenceType;
}
@Override
@@ -89,7 +104,13 @@ public void print(StringBuffer buffer, int indent) {
}
buffer.append(getClass().getSimpleName());
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(
+ " | "
+ + (this.staticSequenceType == null
+ ? "not set"
+ : this.staticSequenceType
+ + (this.staticSequenceType.isResolved() ? " (resolved)" : " (unresolved)"))
+ );
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/Node.java b/src/main/java/org/rumbledb/expressions/Node.java
index 4105b8b561..6b562ad668 100644
--- a/src/main/java/org/rumbledb/expressions/Node.java
+++ b/src/main/java/org/rumbledb/expressions/Node.java
@@ -53,12 +53,28 @@ protected Node(ExceptionMetadata metadata) {
* overridden by subclasses that support higher execution modes. By
* default, the highest execution mode is assumed to be local.
*
+ * This method is deprecated as the logic of execution mode
+ * initialization is being moved to the ExecutionModeVisitor
+ * which invokes setHighestExecutionMode.
+ *
* @param visitorConfig the configuration of the visitor.
*/
public void initHighestExecutionMode(VisitorConfig visitorConfig) {
this.highestExecutionMode = ExecutionMode.LOCAL;
}
+ /**
+ * Initializes the highest execution mode of this node, which determines
+ * whether evaluation will be done locally, with RDDs or with DataFrames.
+ *
+ * This method is used during the static analysis. It is meant to be
+ * overridden by subclasses that support higher execution modes. By
+ * default, the highest execution mode is assumed to be local.
+ */
+ public final void setHighestExecutionMode(ExecutionMode newMode) {
+ this.highestExecutionMode = newMode;
+ }
+
/**
* Gets the highest execution mode of this node, which determines
* whether evaluation will be done locally, with RDDs or with DataFrames.
diff --git a/src/main/java/org/rumbledb/expressions/arithmetic/AdditiveExpression.java b/src/main/java/org/rumbledb/expressions/arithmetic/AdditiveExpression.java
index c99b7c2f85..b8176dbb2b 100644
--- a/src/main/java/org/rumbledb/expressions/arithmetic/AdditiveExpression.java
+++ b/src/main/java/org/rumbledb/expressions/arithmetic/AdditiveExpression.java
@@ -75,7 +75,7 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(getClass().getSimpleName());
buffer.append(" (" + (this.isMinus ? "-" : "+") + ") ");
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/arithmetic/MultiplicativeExpression.java b/src/main/java/org/rumbledb/expressions/arithmetic/MultiplicativeExpression.java
index 16423c5a59..5ea6859317 100644
--- a/src/main/java/org/rumbledb/expressions/arithmetic/MultiplicativeExpression.java
+++ b/src/main/java/org/rumbledb/expressions/arithmetic/MultiplicativeExpression.java
@@ -111,7 +111,7 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(getClass().getSimpleName());
buffer.append(" (" + (this.multiplicativeOperator) + ") ");
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/arithmetic/UnaryExpression.java b/src/main/java/org/rumbledb/expressions/arithmetic/UnaryExpression.java
index caaed0664d..cf5974b810 100644
--- a/src/main/java/org/rumbledb/expressions/arithmetic/UnaryExpression.java
+++ b/src/main/java/org/rumbledb/expressions/arithmetic/UnaryExpression.java
@@ -70,7 +70,7 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(getClass().getSimpleName());
buffer.append(" (" + (this.negated ? "-" : "+") + ") ");
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/comparison/ComparisonExpression.java b/src/main/java/org/rumbledb/expressions/comparison/ComparisonExpression.java
index 4525c5d4a0..301953df28 100644
--- a/src/main/java/org/rumbledb/expressions/comparison/ComparisonExpression.java
+++ b/src/main/java/org/rumbledb/expressions/comparison/ComparisonExpression.java
@@ -151,7 +151,7 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(getClass().getSimpleName());
buffer.append(" (" + (this.comparisonOperator) + ") ");
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/flowr/FlworExpression.java b/src/main/java/org/rumbledb/expressions/flowr/FlworExpression.java
index f728b0a023..ce0797434a 100644
--- a/src/main/java/org/rumbledb/expressions/flowr/FlworExpression.java
+++ b/src/main/java/org/rumbledb/expressions/flowr/FlworExpression.java
@@ -20,7 +20,6 @@
package org.rumbledb.expressions.flowr;
-import org.rumbledb.compiler.VisitorConfig;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.SemanticException;
import org.rumbledb.expressions.AbstractNodeVisitor;
@@ -55,11 +54,6 @@ public ReturnClause getReturnClause() {
return this.returnClause;
}
- @Override
- public void initHighestExecutionMode(VisitorConfig visitorConfig) {
- this.highestExecutionMode = this.returnClause.getHighestExecutionMode(visitorConfig);
- }
-
public List getChildren() {
return Collections.singletonList(this.returnClause);
}
diff --git a/src/main/java/org/rumbledb/expressions/flowr/ForClause.java b/src/main/java/org/rumbledb/expressions/flowr/ForClause.java
index 31a3373a17..435c0dadf1 100644
--- a/src/main/java/org/rumbledb/expressions/flowr/ForClause.java
+++ b/src/main/java/org/rumbledb/expressions/flowr/ForClause.java
@@ -132,6 +132,7 @@ public void print(StringBuffer buffer, int indent) {
+ (this.variableName)
+ ", "
+ this.getSequenceType().toString()
+ + (this.getSequenceType().isResolved() ? " (resolved)" : " (unresolved)")
+ ", "
+ (this.allowingEmpty ? "allowing empty, " : "")
+ this.positionalVariableName
diff --git a/src/main/java/org/rumbledb/expressions/flowr/GroupByVariableDeclaration.java b/src/main/java/org/rumbledb/expressions/flowr/GroupByVariableDeclaration.java
index a9dd4e8c48..817cb406b3 100644
--- a/src/main/java/org/rumbledb/expressions/flowr/GroupByVariableDeclaration.java
+++ b/src/main/java/org/rumbledb/expressions/flowr/GroupByVariableDeclaration.java
@@ -52,7 +52,7 @@ public Expression getExpression() {
}
public SequenceType getSequenceType() {
- return this.sequenceType == null ? SequenceType.MOST_GENERAL_SEQUENCE_TYPE : this.sequenceType;
+ return this.sequenceType == null ? SequenceType.ITEM_STAR : this.sequenceType;
}
public SequenceType getActualSequenceType() {
diff --git a/src/main/java/org/rumbledb/expressions/flowr/LetClause.java b/src/main/java/org/rumbledb/expressions/flowr/LetClause.java
index 8be7d8545d..b548b22efb 100644
--- a/src/main/java/org/rumbledb/expressions/flowr/LetClause.java
+++ b/src/main/java/org/rumbledb/expressions/flowr/LetClause.java
@@ -63,7 +63,7 @@ public Name getVariableName() {
}
public SequenceType getSequenceType() {
- return this.sequenceType == null ? SequenceType.MOST_GENERAL_SEQUENCE_TYPE : this.sequenceType;
+ return this.sequenceType == null ? SequenceType.ITEM_STAR : this.sequenceType;
}
public SequenceType getActualSequenceType() {
@@ -114,7 +114,14 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(" ");
}
buffer.append(getClass().getSimpleName());
- buffer.append(" (" + (this.variableName) + ", " + this.getSequenceType().toString() + ") ");
+ buffer.append(
+ " ("
+ + (this.variableName)
+ + ", "
+ + this.getSequenceType().toString()
+ + (this.getSequenceType().isResolved() ? " (resolved)" : " (unresolved)")
+ + ") "
+ );
buffer.append(")");
buffer.append(" | " + this.highestExecutionMode);
buffer.append("\n");
diff --git a/src/main/java/org/rumbledb/expressions/flowr/ReturnClause.java b/src/main/java/org/rumbledb/expressions/flowr/ReturnClause.java
index 5753a05840..265eaa9ec3 100644
--- a/src/main/java/org/rumbledb/expressions/flowr/ReturnClause.java
+++ b/src/main/java/org/rumbledb/expressions/flowr/ReturnClause.java
@@ -20,10 +20,8 @@
package org.rumbledb.expressions.flowr;
-import org.rumbledb.compiler.VisitorConfig;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.expressions.AbstractNodeVisitor;
-import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.expressions.Expression;
import org.rumbledb.expressions.Node;
@@ -44,23 +42,6 @@ public Expression getReturnExpr() {
return this.returnExpr;
}
- @Override
- public void initHighestExecutionMode(VisitorConfig visitorConfig) {
- if (this.previousClause.getHighestExecutionMode(visitorConfig).isDataFrame()) {
- this.highestExecutionMode = ExecutionMode.RDD;
- return;
- }
- if (this.returnExpr.getHighestExecutionMode(visitorConfig).isRDD()) {
- this.highestExecutionMode = ExecutionMode.RDD;
- return;
- }
- if (this.returnExpr.getHighestExecutionMode(visitorConfig).isDataFrame()) {
- this.highestExecutionMode = ExecutionMode.DATAFRAME;
- return;
- }
- this.highestExecutionMode = ExecutionMode.LOCAL;
- }
-
@Override
public List getChildren() {
List result = new ArrayList<>();
diff --git a/src/main/java/org/rumbledb/expressions/flowr/SimpleMapExpression.java b/src/main/java/org/rumbledb/expressions/flowr/SimpleMapExpression.java
index 91ef9bc425..a9c8dd5c96 100644
--- a/src/main/java/org/rumbledb/expressions/flowr/SimpleMapExpression.java
+++ b/src/main/java/org/rumbledb/expressions/flowr/SimpleMapExpression.java
@@ -66,7 +66,7 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(getClass().getSimpleName());
buffer.append(" (!)");
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/module/VariableDeclaration.java b/src/main/java/org/rumbledb/expressions/module/VariableDeclaration.java
index 9a2d858cff..0b8f67be57 100644
--- a/src/main/java/org/rumbledb/expressions/module/VariableDeclaration.java
+++ b/src/main/java/org/rumbledb/expressions/module/VariableDeclaration.java
@@ -70,7 +70,13 @@ public boolean external() {
// return item* if sequenceType is [null]
public SequenceType getSequenceType() {
- return this.sequenceType == null ? SequenceType.MOST_GENERAL_SEQUENCE_TYPE : this.sequenceType;
+ if (this.sequenceType != null) {
+ return this.sequenceType;
+ }
+ if (this.expression != null && this.expression.getStaticSequenceType() != null) {
+ return this.expression.getStaticSequenceType();
+ }
+ return SequenceType.ITEM_STAR;
}
// as above but does NOT default to item*
diff --git a/src/main/java/org/rumbledb/expressions/postfix/DynamicFunctionCallExpression.java b/src/main/java/org/rumbledb/expressions/postfix/DynamicFunctionCallExpression.java
index d2aa9cf11e..b77e5bd990 100644
--- a/src/main/java/org/rumbledb/expressions/postfix/DynamicFunctionCallExpression.java
+++ b/src/main/java/org/rumbledb/expressions/postfix/DynamicFunctionCallExpression.java
@@ -20,11 +20,15 @@
package org.rumbledb.expressions.postfix;
+import org.rumbledb.compiler.VisitorConfig;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.OurBadException;
import org.rumbledb.expressions.AbstractNodeVisitor;
+import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.expressions.Expression;
import org.rumbledb.expressions.Node;
+import org.rumbledb.types.SequenceType.Arity;
+
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -82,11 +86,18 @@ public void print(StringBuffer buffer, int indent) {
}
buffer.append(getClass().getSimpleName());
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(
+ " | "
+ + (this.staticSequenceType == null
+ ? "not set"
+ : this.staticSequenceType
+ + (this.staticSequenceType.isResolved() ? " (resolved)" : " (unresolved)"))
+ );
buffer.append("\n");
+ this.mainExpression.print(buffer, indent + 1);
for (Expression arg : this.arguments) {
if (arg == null) {
- for (int i = 0; i < indent; ++i) {
+ for (int i = 0; i < indent + 1; ++i) {
buffer.append(" ");
}
buffer.append("?\n");
@@ -115,4 +126,20 @@ public void serializeToJSONiq(StringBuffer sb, int indent) {
}
sb.append(")\n");
}
+
+ @Override
+ public void initHighestExecutionMode(VisitorConfig visitorConfig) {
+ if (this.arguments.size() == 0) {
+ this.highestExecutionMode = ExecutionMode.LOCAL;
+ return;
+ }
+ if (this.getStaticSequenceType().getArity().equals(Arity.One)) {
+ this.highestExecutionMode = ExecutionMode.LOCAL;
+ return;
+ }
+ this.highestExecutionMode = this.arguments.get(0).getHighestExecutionMode(visitorConfig);
+ if (this.highestExecutionMode.equals(ExecutionMode.RDD)) {
+ this.highestExecutionMode = ExecutionMode.LOCAL;
+ }
+ }
}
diff --git a/src/main/java/org/rumbledb/expressions/primary/BooleanLiteralExpression.java b/src/main/java/org/rumbledb/expressions/primary/BooleanLiteralExpression.java
index b276978f98..62ac22aea8 100644
--- a/src/main/java/org/rumbledb/expressions/primary/BooleanLiteralExpression.java
+++ b/src/main/java/org/rumbledb/expressions/primary/BooleanLiteralExpression.java
@@ -59,7 +59,7 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(getClass().getSimpleName());
buffer.append(" (" + (this.value) + ") ");
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/primary/DecimalLiteralExpression.java b/src/main/java/org/rumbledb/expressions/primary/DecimalLiteralExpression.java
index b1c7e35589..5d4eb39bad 100644
--- a/src/main/java/org/rumbledb/expressions/primary/DecimalLiteralExpression.java
+++ b/src/main/java/org/rumbledb/expressions/primary/DecimalLiteralExpression.java
@@ -60,7 +60,7 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(getClass().getSimpleName());
buffer.append(" (" + (this.value) + ") ");
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/primary/DoubleLiteralExpression.java b/src/main/java/org/rumbledb/expressions/primary/DoubleLiteralExpression.java
index 3db15cc36a..0313eb5db7 100644
--- a/src/main/java/org/rumbledb/expressions/primary/DoubleLiteralExpression.java
+++ b/src/main/java/org/rumbledb/expressions/primary/DoubleLiteralExpression.java
@@ -59,7 +59,7 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(getClass().getSimpleName());
buffer.append(" (" + (this.value) + ") ");
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/primary/FunctionCallExpression.java b/src/main/java/org/rumbledb/expressions/primary/FunctionCallExpression.java
index ceb14792fc..1a497038fc 100644
--- a/src/main/java/org/rumbledb/expressions/primary/FunctionCallExpression.java
+++ b/src/main/java/org/rumbledb/expressions/primary/FunctionCallExpression.java
@@ -95,6 +95,13 @@ public void initFunctionCallHighestExecutionMode(VisitorConfig visitorConfig) {
);
}
BuiltinFunction builtinFunction = BuiltinFunctionCatalogue.getBuiltinFunction(this.identifier);
+ if (builtinFunction == null) {
+ throw new UnknownFunctionCallException(
+ this.identifier.getName(),
+ this.identifier.getArity(),
+ this.getMetadata()
+ );
+ }
this.highestExecutionMode = this.getBuiltInFunctionExecutionMode(builtinFunction, visitorConfig);
return;
}
@@ -173,11 +180,17 @@ public void print(StringBuffer buffer, int indent) {
}
buffer.append(getClass().getSimpleName());
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(
+ " | "
+ + (this.staticSequenceType == null
+ ? "not set"
+ : this.staticSequenceType
+ + (this.staticSequenceType.isResolved() ? " (resolved)" : " (unresolved)"))
+ );
buffer.append("\n");
for (Expression arg : this.arguments) {
if (arg == null) {
- for (int i = 0; i < indent; ++i) {
+ for (int i = 0; i < indent + 1; ++i) {
buffer.append(" ");
}
buffer.append("?\n");
diff --git a/src/main/java/org/rumbledb/expressions/primary/InlineFunctionExpression.java b/src/main/java/org/rumbledb/expressions/primary/InlineFunctionExpression.java
index e37f19c9dc..31964210ca 100644
--- a/src/main/java/org/rumbledb/expressions/primary/InlineFunctionExpression.java
+++ b/src/main/java/org/rumbledb/expressions/primary/InlineFunctionExpression.java
@@ -70,7 +70,7 @@ public Map getParams() {
}
public SequenceType getReturnType() {
- return this.returnType == null ? SequenceType.MOST_GENERAL_SEQUENCE_TYPE : this.returnType;
+ return this.returnType == null ? SequenceType.ITEM_STAR : this.returnType;
}
public SequenceType getActualReturnType() {
@@ -116,13 +116,25 @@ public void print(StringBuffer buffer, int indent) {
for (Map.Entry entry : this.params.entrySet()) {
buffer.append(entry.getKey());
buffer.append(", ");
- buffer.append(entry.getValue().toString());
+ buffer.append(
+ entry.getValue().toString() + (entry.getValue().isResolved() ? " (resolved)" : " (unresolved)")
+ );
buffer.append(", ");
}
- buffer.append(this.returnType == null ? "not set" : this.returnType.toString());
+ buffer.append(
+ this.returnType == null
+ ? "not set"
+ : this.returnType.toString() + (this.returnType.isResolved() ? " (resolved)" : " (unresolved)")
+ );
buffer.append(")");
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(
+ " | "
+ + (this.staticSequenceType == null
+ ? "not set"
+ : this.staticSequenceType
+ + (this.staticSequenceType.isResolved() ? " (resolved)" : " (unresolved)"))
+ );
buffer.append("\n");
for (int i = 0; i < indent + 2; ++i) {
buffer.append(" ");
diff --git a/src/main/java/org/rumbledb/expressions/primary/IntegerLiteralExpression.java b/src/main/java/org/rumbledb/expressions/primary/IntegerLiteralExpression.java
index fcbf9a639f..bd906a343e 100644
--- a/src/main/java/org/rumbledb/expressions/primary/IntegerLiteralExpression.java
+++ b/src/main/java/org/rumbledb/expressions/primary/IntegerLiteralExpression.java
@@ -59,7 +59,7 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(getClass().getSimpleName());
buffer.append(" (" + (this.lexicalValue) + ") ");
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/primary/NamedFunctionReferenceExpression.java b/src/main/java/org/rumbledb/expressions/primary/NamedFunctionReferenceExpression.java
index b3342992c3..c9d7c89c11 100644
--- a/src/main/java/org/rumbledb/expressions/primary/NamedFunctionReferenceExpression.java
+++ b/src/main/java/org/rumbledb/expressions/primary/NamedFunctionReferenceExpression.java
@@ -60,7 +60,7 @@ public void print(StringBuffer buffer, int indent) {
}
buffer.append(getClass().getSimpleName());
buffer.append(" (" + this.identifier.getName() + "#" + this.identifier.getArity() + ") ");
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
}
diff --git a/src/main/java/org/rumbledb/expressions/primary/StringLiteralExpression.java b/src/main/java/org/rumbledb/expressions/primary/StringLiteralExpression.java
index da81e29a81..86d7971592 100644
--- a/src/main/java/org/rumbledb/expressions/primary/StringLiteralExpression.java
+++ b/src/main/java/org/rumbledb/expressions/primary/StringLiteralExpression.java
@@ -60,7 +60,7 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(getClass().getSimpleName());
buffer.append(" (" + (this.value) + ") ");
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/primary/VariableReferenceExpression.java b/src/main/java/org/rumbledb/expressions/primary/VariableReferenceExpression.java
index 5fd2ea8004..363a204896 100644
--- a/src/main/java/org/rumbledb/expressions/primary/VariableReferenceExpression.java
+++ b/src/main/java/org/rumbledb/expressions/primary/VariableReferenceExpression.java
@@ -26,7 +26,6 @@
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.OurBadException;
import org.rumbledb.expressions.AbstractNodeVisitor;
-import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.expressions.Expression;
import org.rumbledb.expressions.Node;
import org.rumbledb.types.SequenceType;
@@ -47,24 +46,20 @@ public VariableReferenceExpression(Name name, ExceptionMetadata metadata) {
this.name = name;
}
- public void setHighestExecutionMode(ExecutionMode highestExecutionMode) {
- this.highestExecutionMode = highestExecutionMode;
- }
-
public Name getVariableName() {
return this.name;
}
// default to item* if type is null
public SequenceType getType() {
- return this.type == null ? SequenceType.MOST_GENERAL_SEQUENCE_TYPE : this.type;
+ return this.type == null ? SequenceType.ITEM_STAR : this.type;
}
public SequenceType getActualType() {
return this.type;
}
- public void setType(SequenceType type) {
+ public void setActualType(SequenceType type) {
this.type = type;
}
@@ -92,7 +87,13 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(getClass().getSimpleName());
buffer.append(" ($" + this.name + ") ");
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(
+ " | "
+ + (this.staticSequenceType == null
+ ? "not set"
+ : this.staticSequenceType
+ + (this.staticSequenceType.isResolved() ? " (resolved)" : " (unresolved)"))
+ );
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/typing/CastExpression.java b/src/main/java/org/rumbledb/expressions/typing/CastExpression.java
index 6dd9e10bbe..b17d62cfb3 100644
--- a/src/main/java/org/rumbledb/expressions/typing/CastExpression.java
+++ b/src/main/java/org/rumbledb/expressions/typing/CastExpression.java
@@ -53,9 +53,20 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(" ");
}
buffer.append(getClass().getSimpleName());
- buffer.append(" (" + (this.sequenceType.toString()) + ") ");
+ buffer.append(
+ " ("
+ + (this.sequenceType.toString())
+ + (this.getSequenceType().isResolved() ? " (resolved)" : " (unresolved)")
+ + ") "
+ );
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(
+ " | "
+ + (this.staticSequenceType == null
+ ? "not set"
+ : this.staticSequenceType
+ + (this.staticSequenceType.isResolved() ? " (resolved)" : " (unresolved)"))
+ );
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/typing/CastableExpression.java b/src/main/java/org/rumbledb/expressions/typing/CastableExpression.java
index d790fa91cf..d2e05dfbed 100644
--- a/src/main/java/org/rumbledb/expressions/typing/CastableExpression.java
+++ b/src/main/java/org/rumbledb/expressions/typing/CastableExpression.java
@@ -53,9 +53,14 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(" ");
}
buffer.append(getClass().getSimpleName());
- buffer.append(" (" + (this.sequenceType.toString()) + ") ");
+ buffer.append(
+ " ("
+ + (this.sequenceType.toString())
+ + (this.getSequenceType().isResolved() ? " (resolved)" : " (unresolved)")
+ + ") "
+ );
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/typing/InstanceOfExpression.java b/src/main/java/org/rumbledb/expressions/typing/InstanceOfExpression.java
index ef730359a8..0805f3dfe8 100644
--- a/src/main/java/org/rumbledb/expressions/typing/InstanceOfExpression.java
+++ b/src/main/java/org/rumbledb/expressions/typing/InstanceOfExpression.java
@@ -72,9 +72,14 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(" ");
}
buffer.append(getClass().getSimpleName());
- buffer.append(" (" + (this.sequenceType.toString()) + ") ");
+ buffer.append(
+ " ("
+ + (this.sequenceType.toString())
+ + (this.getSequenceType().isResolved() ? " (resolved)" : " (unresolved)")
+ + ") "
+ );
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/typing/IsStaticallyExpression.java b/src/main/java/org/rumbledb/expressions/typing/IsStaticallyExpression.java
index cad37ad1d1..99b992642a 100644
--- a/src/main/java/org/rumbledb/expressions/typing/IsStaticallyExpression.java
+++ b/src/main/java/org/rumbledb/expressions/typing/IsStaticallyExpression.java
@@ -52,7 +52,13 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(getClass().getSimpleName());
buffer.append(" (" + (this.sequenceType.toString()) + ") ");
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(
+ " | "
+ + (this.staticSequenceType == null
+ ? "not set"
+ : this.staticSequenceType
+ + (this.staticSequenceType.isResolved() ? " (resolved)" : " (unresolved)"))
+ );
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/typing/TreatExpression.java b/src/main/java/org/rumbledb/expressions/typing/TreatExpression.java
index 8d740040be..c7d7c4fd3e 100644
--- a/src/main/java/org/rumbledb/expressions/typing/TreatExpression.java
+++ b/src/main/java/org/rumbledb/expressions/typing/TreatExpression.java
@@ -90,9 +90,14 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(" ");
}
buffer.append(getClass().getSimpleName());
- buffer.append(" (" + (this.sequenceType.toString()) + ") ");
+ buffer.append(
+ " ("
+ + (this.sequenceType.toString())
+ + (this.getSequenceType().isResolved() ? " (resolved)" : " (unresolved)")
+ + ") "
+ );
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(" | " + (this.staticSequenceType == null ? "not set" : this.staticSequenceType));
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/expressions/typing/ValidateTypeExpression.java b/src/main/java/org/rumbledb/expressions/typing/ValidateTypeExpression.java
index 85543b4965..6e69da76ed 100644
--- a/src/main/java/org/rumbledb/expressions/typing/ValidateTypeExpression.java
+++ b/src/main/java/org/rumbledb/expressions/typing/ValidateTypeExpression.java
@@ -54,9 +54,20 @@ public void print(StringBuffer buffer, int indent) {
buffer.append(" ");
}
buffer.append(getClass().getSimpleName());
- buffer.append(" (" + (this.sequenceType.toString()) + ") ");
+ buffer.append(
+ " ("
+ + (this.sequenceType.toString())
+ + (this.getSequenceType().isResolved() ? " (resolved)" : " (unresolved)")
+ + ") "
+ );
buffer.append(" | " + this.highestExecutionMode);
- buffer.append(" | " + (this.inferredSequenceType == null ? "not set" : this.inferredSequenceType));
+ buffer.append(
+ " | "
+ + (this.staticSequenceType == null
+ ? "not set"
+ : this.staticSequenceType
+ + (this.staticSequenceType.isResolved() ? " (resolved)" : " (unresolved)"))
+ );
buffer.append("\n");
for (Node iterator : getChildren()) {
iterator.print(buffer, indent + 1);
diff --git a/src/main/java/org/rumbledb/items/FunctionItem.java b/src/main/java/org/rumbledb/items/FunctionItem.java
index 5a219b04c6..83824fe9d7 100644
--- a/src/main/java/org/rumbledb/items/FunctionItem.java
+++ b/src/main/java/org/rumbledb/items/FunctionItem.java
@@ -31,6 +31,8 @@
import java.util.Map;
import org.apache.spark.api.java.JavaRDD;
+import org.apache.spark.ml.Estimator;
+import org.apache.spark.ml.Transformer;
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.context.FunctionIdentifier;
@@ -50,6 +52,9 @@
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
+import sparksoniq.spark.ml.ApplyEstimatorRuntimeIterator;
+import sparksoniq.spark.ml.ApplyTransformerRuntimeIterator;
+
public class FunctionItem implements Item {
private static final long serialVersionUID = 1L;
@@ -326,4 +331,32 @@ public void populateClosureFromDynamicContext(DynamicContext dynamicContext, Exc
);
}
}
+
+ @Override
+ public boolean isEstimator() {
+ return this.bodyIterator instanceof ApplyEstimatorRuntimeIterator;
+ }
+
+ @Override
+ public Estimator> getEstimator() {
+ if (!isEstimator()) {
+ throw new OurBadException("This is not an estimator.", ExceptionMetadata.EMPTY_METADATA);
+ }
+ return ((ApplyEstimatorRuntimeIterator) this.bodyIterator).getEstimator();
+ }
+
+ @Override
+ public boolean isTransformer() {
+ return this.bodyIterator instanceof ApplyTransformerRuntimeIterator;
+ }
+
+ @Override
+ public Transformer getTransformer() {
+ if (!isTransformer()) {
+ throw new OurBadException("This is not a transformer.", ExceptionMetadata.EMPTY_METADATA);
+ }
+ return ((ApplyTransformerRuntimeIterator) this.bodyIterator).getTransformer();
+ }
+
+
}
diff --git a/src/main/java/org/rumbledb/runtime/flwor/clauses/LetClauseSparkIterator.java b/src/main/java/org/rumbledb/runtime/flwor/clauses/LetClauseSparkIterator.java
index 8d70dc2279..1ec498d348 100644
--- a/src/main/java/org/rumbledb/runtime/flwor/clauses/LetClauseSparkIterator.java
+++ b/src/main/java/org/rumbledb/runtime/flwor/clauses/LetClauseSparkIterator.java
@@ -413,7 +413,7 @@ public Dataset
getDataFrameAsJoin(
RuntimeIterator filteringPredicateIterator = new PredicateIterator(
new VariableReferenceIterator(
this.variableName,
- SequenceType.MOST_GENERAL_SEQUENCE_TYPE,
+ SequenceType.ITEM_STAR,
ExecutionMode.LOCAL,
getMetadata()
),
diff --git a/src/main/java/org/rumbledb/runtime/functions/DynamicFunctionCallIterator.java b/src/main/java/org/rumbledb/runtime/functions/DynamicFunctionCallIterator.java
index ec07f74a5e..1fa5b6bae2 100644
--- a/src/main/java/org/rumbledb/runtime/functions/DynamicFunctionCallIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/DynamicFunctionCallIterator.java
@@ -20,20 +20,24 @@
package org.rumbledb.runtime.functions;
+import org.apache.spark.api.java.JavaRDD;
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.context.NamedFunctions;
import org.rumbledb.exceptions.ExceptionMetadata;
+import org.rumbledb.exceptions.InvalidRumbleMLParamException;
import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.exceptions.MoreThanOneItemException;
+import org.rumbledb.exceptions.OurBadException;
import org.rumbledb.exceptions.UnexpectedTypeException;
import org.rumbledb.expressions.ExecutionMode;
-import org.rumbledb.runtime.LocalRuntimeIterator;
+import org.rumbledb.items.structured.JSoundDataFrame;
+import org.rumbledb.runtime.HybridRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import java.util.List;
-public class DynamicFunctionCallIterator extends LocalRuntimeIterator {
+public class DynamicFunctionCallIterator extends HybridRuntimeIterator {
// dynamic: functionIdentifier is not known at compile time
// it is known only after evaluating postfix expression at runtime
@@ -45,6 +49,7 @@ public class DynamicFunctionCallIterator extends LocalRuntimeIterator {
// calculated fields
private Item functionItem;
private RuntimeIterator functionCallIterator;
+ private boolean isPartialApplication;
private Item nextResult;
public DynamicFunctionCallIterator(
@@ -54,9 +59,12 @@ public DynamicFunctionCallIterator(
ExceptionMetadata iteratorMetadata
) {
super(null, executionMode, iteratorMetadata);
+ this.isPartialApplication = false;
for (RuntimeIterator arg : functionArguments) {
if (arg != null) {
this.children.add(arg);
+ } else {
+ this.isPartialApplication = true;
}
}
if (!this.children.contains(functionItemIterator)) {
@@ -67,15 +75,24 @@ public DynamicFunctionCallIterator(
}
@Override
- public void open(DynamicContext context) {
- super.open(context);
- setFunctionItemAndIteratorWithCurrentContext();
- this.functionCallIterator.open(this.currentDynamicContextForLocalExecution);
+ public void openLocal() {
+ setFunctionItemAndIteratorWithCurrentContext(this.currentDynamicContextForLocalExecution);
+ try {
+ this.functionCallIterator.open(this.currentDynamicContextForLocalExecution);
+ } catch (InvalidRumbleMLParamException e) {
+ String m = e.getMLMessage();
+ throw new InvalidRumbleMLParamException(m, getMetadata());
+ }
setNextResult();
}
@Override
- public Item next() {
+ protected boolean hasNextLocal() {
+ return this.hasNext;
+ }
+
+ @Override
+ public Item nextLocal() {
if (this.hasNext) {
Item result = this.nextResult;
setNextResult();
@@ -93,7 +110,12 @@ public Item next() {
public void setNextResult() {
this.nextResult = null;
if (this.functionCallIterator.hasNext()) {
- this.nextResult = this.functionCallIterator.next();
+ try {
+ this.nextResult = this.functionCallIterator.next();
+ } catch (InvalidRumbleMLParamException e) {
+ String m = e.getMLMessage();
+ throw new InvalidRumbleMLParamException(m, getMetadata());
+ }
}
if (this.nextResult == null) {
@@ -103,45 +125,74 @@ public void setNextResult() {
}
}
- private void setFunctionItemAndIteratorWithCurrentContext() {
+ private void setFunctionItemAndIteratorWithCurrentContext(DynamicContext context) {
try {
- this.functionItem = this.functionItemIterator.materializeAtMostOneItemOrNull(
- this.currentDynamicContextForLocalExecution
- );
+ this.functionItem = this.functionItemIterator.materializeAtMostOneItemOrNull(context);
} catch (MoreThanOneItemException e) {
throw new UnexpectedTypeException(
"A dynamic function call can not be performed on a sequence of more than one item.",
getMetadata()
);
}
- if (this.functionItem == null && !this.functionItem.isFunction()) {
+ if (this.functionItem == null || !this.functionItem.isFunction()) {
throw new UnexpectedTypeException(
"Dynamic function calls can only be performed on functions.",
getMetadata()
);
}
+ if (
+ this.functionItem.getBodyIterator().getHighestExecutionMode().equals(ExecutionMode.LOCAL)
+ && this.getHighestExecutionMode().equals(ExecutionMode.DATAFRAME)
+ ) {
+ throw new OurBadException(
+ "Execution mode mismatch in dynamic function call. At this point, Rumble only supports higher-order functions "
+ + "that are either machine learning models or estimators (which process validated and structured sequences of objects at any scale), or that take and return just one item at a time.",
+ getMetadata()
+ );
+ }
this.functionCallIterator = NamedFunctions.buildUserDefinedFunctionCallIterator(
this.functionItem,
- this.functionItem.getBodyIterator().getHighestExecutionMode(),
+ this.isPartialApplication
+ ? ExecutionMode.LOCAL
+ : this.functionItem.getBodyIterator().getHighestExecutionMode(),
getMetadata(),
this.functionArguments
);
}
@Override
- public void reset(DynamicContext context) {
- super.reset(context);
+ public void resetLocal() {
this.functionCallIterator.reset(this.currentDynamicContextForLocalExecution);
setNextResult();
}
@Override
- public void close() {
+ public void closeLocal() {
// ensure that recursive function calls terminate gracefully
// the function call in the body of the deepest recursion call is never visited, never opened and never closed
if (this.isOpen) {
this.functionCallIterator.close();
}
- super.close();
+ }
+
+ protected boolean implementsDataFrames() {
+ return true;
+ }
+
+ @Override
+ public JavaRDD- getRDDAux(DynamicContext dynamicContext) {
+ setFunctionItemAndIteratorWithCurrentContext(dynamicContext);
+ return this.functionCallIterator.getRDD(dynamicContext);
+ }
+
+ @Override
+ public JSoundDataFrame getDataFrame(DynamicContext dynamicContext) {
+ setFunctionItemAndIteratorWithCurrentContext(dynamicContext);
+ try {
+ return this.functionCallIterator.getDataFrame(dynamicContext);
+ } catch (InvalidRumbleMLParamException e) {
+ String m = e.getMLMessage();
+ throw new InvalidRumbleMLParamException(m, getMetadata());
+ }
}
}
diff --git a/src/main/java/org/rumbledb/runtime/functions/FunctionItemCallIterator.java b/src/main/java/org/rumbledb/runtime/functions/FunctionItemCallIterator.java
index 88241894dd..3816b736eb 100644
--- a/src/main/java/org/rumbledb/runtime/functions/FunctionItemCallIterator.java
+++ b/src/main/java/org/rumbledb/runtime/functions/FunctionItemCallIterator.java
@@ -41,7 +41,7 @@
import org.rumbledb.types.SequenceType;
import org.rumbledb.types.SequenceType.Arity;
-import static org.rumbledb.types.SequenceType.MOST_GENERAL_SEQUENCE_TYPE;
+import static org.rumbledb.types.SequenceType.ITEM_STAR;
import java.util.ArrayList;
import java.util.LinkedHashMap;
@@ -124,7 +124,7 @@ private void wrapArgumentIteratorsWithTypeCheckingIterators() {
&& !this.functionItem.getSignature()
.getParameterTypes()
.get(i)
- .equals(MOST_GENERAL_SEQUENCE_TYPE)
+ .equals(ITEM_STAR)
) {
SequenceType sequenceType = this.functionItem.getSignature().getParameterTypes().get(i);
ExecutionMode executionMode = this.functionArguments.get(i).getHighestExecutionMode();
diff --git a/src/main/java/org/rumbledb/types/ArrayItemType.java b/src/main/java/org/rumbledb/types/ArrayItemType.java
index ae2a05e5f4..511b7267db 100644
--- a/src/main/java/org/rumbledb/types/ArrayItemType.java
+++ b/src/main/java/org/rumbledb/types/ArrayItemType.java
@@ -3,7 +3,9 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.context.Name;
+import org.rumbledb.context.StaticContext;
import org.rumbledb.exceptions.ExceptionMetadata;
+import org.rumbledb.exceptions.OurBadException;
import java.util.*;
@@ -45,6 +47,9 @@ public class ArrayItemType implements ItemType {
List
- enumeration
) {
this.name = name;
+ if (baseType == null) {
+ throw new OurBadException("Unexpected error: baseType is null.");
+ }
this.baseType = baseType;
this.typeTreeDepth = baseType.getTypeTreeDepth() + 1;
if (content == null) {
@@ -62,7 +67,7 @@ public boolean equals(Object other) {
if (!(other instanceof ItemType)) {
return false;
}
- return this.getIdentifierString().equals(((ItemType) other).getIdentifierString());
+ return isEqualTo((ItemType) other);
}
@Override
@@ -160,7 +165,10 @@ public String getIdentifierString() {
@Override
public String toString() {
// consider add content and various stuff
- return this.name.toString();
+ return ((this.name == null) ? "" : this.name.toString())
+ + "(array of "
+ + this.getArrayContentFacet().getType()
+ + ")";
}
@Override
@@ -175,6 +183,13 @@ public void resolve(DynamicContext context, ExceptionMetadata metadata) {
}
}
+ @Override
+ public void resolve(StaticContext context, ExceptionMetadata metadata) {
+ if (!this.content.getType().isResolved()) {
+ this.content.getType().resolve(context, metadata);
+ }
+ }
+
@Override
public boolean isResolved() {
return this.content.getType().isResolved();
diff --git a/src/main/java/org/rumbledb/types/AtomicItemType.java b/src/main/java/org/rumbledb/types/AtomicItemType.java
index 99e865fb07..7f947a4676 100644
--- a/src/main/java/org/rumbledb/types/AtomicItemType.java
+++ b/src/main/java/org/rumbledb/types/AtomicItemType.java
@@ -231,7 +231,7 @@ public class AtomicItemType implements ItemType {
public AtomicItemType() {
}
- private AtomicItemType(Name name, Set allowedFacets, DataType dataFrameType) {
+ AtomicItemType(Name name, Set allowedFacets, DataType dataFrameType) {
this.name = name;
this.allowedFacets = allowedFacets;
this.dataFrameType = dataFrameType;
@@ -242,7 +242,7 @@ public boolean equals(Object other) {
if (!(other instanceof ItemType)) {
return false;
}
- return this.getIdentifierString().equals(((ItemType) other).getIdentifierString());
+ return isEqualTo((ItemType) other);
}
@Override
@@ -511,4 +511,9 @@ public DataType toDataFrameType() {
public boolean isDataFrameType() {
return true;
}
+
+ @Override
+ public boolean isResolved() {
+ return true;
+ }
}
diff --git a/src/main/java/org/rumbledb/types/BuiltinTypesCatalogue.java b/src/main/java/org/rumbledb/types/BuiltinTypesCatalogue.java
index 42418660c7..954ccef642 100644
--- a/src/main/java/org/rumbledb/types/BuiltinTypesCatalogue.java
+++ b/src/main/java/org/rumbledb/types/BuiltinTypesCatalogue.java
@@ -1,38 +1,287 @@
package org.rumbledb.types;
+import org.apache.spark.sql.types.DataTypes;
import org.rumbledb.context.Name;
import org.rumbledb.exceptions.OurBadException;
+import org.rumbledb.items.IntItem;
+import org.rumbledb.items.IntegerItem;
+import java.math.BigInteger;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
public class BuiltinTypesCatalogue {
- public static final ItemType item = ItemItemType.item;
- public static final ItemType atomicItem = AtomicItemType.atomicItem;
- public static final ItemType stringItem = AtomicItemType.stringItem;
- public static final ItemType integerItem = DerivedAtomicItemType.integerItem;
- public static final ItemType decimalItem = AtomicItemType.decimalItem;
- public static final ItemType doubleItem = AtomicItemType.doubleItem;
- public static final ItemType floatItem = AtomicItemType.floatItem;
- public static final ItemType numericItem = AtomicItemType.numericItem;
- public static final ItemType booleanItem = AtomicItemType.booleanItem;
- public static final ItemType nullItem = AtomicItemType.nullItem;
- public static final ItemType durationItem = AtomicItemType.durationItem;
- public static final ItemType yearMonthDurationItem = AtomicItemType.yearMonthDurationItem;
- public static final ItemType dayTimeDurationItem = AtomicItemType.dayTimeDurationItem;
- public static final ItemType dateTimeItem = AtomicItemType.dateTimeItem;
- public static final ItemType dateItem = AtomicItemType.dateItem;
- public static final ItemType timeItem = AtomicItemType.timeItem;
- public static final ItemType hexBinaryItem = AtomicItemType.hexBinaryItem;
- public static final ItemType anyURIItem = AtomicItemType.anyURIItem;
- public static final ItemType base64BinaryItem = AtomicItemType.base64BinaryItem;
- public static final ItemType JSONItem = JsonItemType.jsonItem;
- public static final ItemType objectItem = ObjectItemType.anyObjectItem;
- public static final ItemType arrayItem = ArrayItemType.anyArrayItem;
- public static final ItemType longItem = DerivedAtomicItemType.longItem;
- public static final ItemType intItem = DerivedAtomicItemType.intItem;
- public static final ItemType shortItem = DerivedAtomicItemType.shortItem;
- public static final ItemType anyFunctionItem = FunctionItemType.anyFunctionItem;
+ public static final ItemType item = new ItemItemType(Name.createVariableInDefaultTypeNamespace("item"));
+
+ public static final ItemType atomicItem = new AtomicItemType(
+ new Name(Name.JS_NS, "js", "atomic"),
+ Collections.emptySet(),
+ DataTypes.BinaryType
+ );
+ public static final ItemType stringItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "string"),
+ new HashSet<>(
+ Arrays.asList(
+ FacetTypes.ENUMERATION,
+ FacetTypes.CONSTRAINTS,
+ FacetTypes.LENGTH,
+ FacetTypes.MINLENGTH,
+ FacetTypes.MAXLENGTH
+ )
+ ),
+ DataTypes.StringType
+ );
+
+ // numeric is an internal type for avoiding function overloading, it is not available in JSONiq
+ // it is the base type for xs:decimal, xs:double, and xs:float (those are now treated specially in type functions)
+ public static final ItemType numericItem = new AtomicItemType(
+ new Name(Name.JS_NS, "js", "numeric"),
+ Collections.emptySet(),
+ DataTypes.BinaryType // TODO: consider if specific type is needed
+ );
+
+ public static final ItemType decimalItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "decimal"),
+ new HashSet<>(
+ Arrays.asList(
+ FacetTypes.ENUMERATION,
+ FacetTypes.CONSTRAINTS,
+ FacetTypes.MININCLUSIVE,
+ FacetTypes.MAXINCLUSIVE,
+ FacetTypes.MINEXCLUSIVE,
+ FacetTypes.MAXINCLUSIVE,
+ FacetTypes.TOTALDIGITS,
+ FacetTypes.FRACTIONDIGITS
+ )
+ ),
+ DataTypes.createDecimalType()
+ );
+ public static final ItemType doubleItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "double"),
+ new HashSet<>(
+ Arrays.asList(
+ FacetTypes.ENUMERATION,
+ FacetTypes.CONSTRAINTS,
+ FacetTypes.MININCLUSIVE,
+ FacetTypes.MAXINCLUSIVE,
+ FacetTypes.MINEXCLUSIVE,
+ FacetTypes.MAXINCLUSIVE
+ )
+ ),
+ DataTypes.DoubleType
+ );
+ public static final ItemType floatItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "float"),
+ new HashSet<>(
+ Arrays.asList(
+ FacetTypes.ENUMERATION,
+ FacetTypes.CONSTRAINTS,
+ FacetTypes.MININCLUSIVE,
+ FacetTypes.MAXINCLUSIVE,
+ FacetTypes.MINEXCLUSIVE,
+ FacetTypes.MAXINCLUSIVE
+ )
+ ),
+ DataTypes.FloatType
+ );
+
+ public static final ItemType booleanItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "boolean"),
+ new HashSet<>(Arrays.asList(FacetTypes.ENUMERATION, FacetTypes.CONSTRAINTS)),
+ DataTypes.BooleanType
+ );
+ public static final ItemType nullItem = new AtomicItemType(
+ new Name(Name.JS_NS, "js", "null"),
+ Collections.emptySet(),
+ DataTypes.NullType // TODO : see appropriate type
+ );
+ public static final ItemType durationItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "duration"),
+ new HashSet<>(
+ Arrays.asList(
+ FacetTypes.ENUMERATION,
+ FacetTypes.CONSTRAINTS,
+ FacetTypes.MININCLUSIVE,
+ FacetTypes.MAXINCLUSIVE,
+ FacetTypes.MINEXCLUSIVE,
+ FacetTypes.MAXINCLUSIVE
+ )
+ ),
+ DataTypes.BinaryType // TODO : appropriate datatype
+ );
+ public static final ItemType yearMonthDurationItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "yearMonthDuration"),
+ new HashSet<>(
+ Arrays.asList(
+ FacetTypes.ENUMERATION,
+ FacetTypes.CONSTRAINTS,
+ FacetTypes.MININCLUSIVE,
+ FacetTypes.MAXINCLUSIVE,
+ FacetTypes.MINEXCLUSIVE,
+ FacetTypes.MAXINCLUSIVE
+ )
+ ),
+ DataTypes.BinaryType // TODO : appropriate datatype
+ );
+ public static final ItemType dayTimeDurationItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "dayTimeDuration"),
+ new HashSet<>(
+ Arrays.asList(
+ FacetTypes.ENUMERATION,
+ FacetTypes.CONSTRAINTS,
+ FacetTypes.MININCLUSIVE,
+ FacetTypes.MAXINCLUSIVE,
+ FacetTypes.MINEXCLUSIVE,
+ FacetTypes.MAXINCLUSIVE
+ )
+ ),
+ DataTypes.BinaryType // TODO : appropriate datatype
+ );
+ public static final ItemType dateTimeItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "dateTime"),
+ new HashSet<>(
+ Arrays.asList(
+ FacetTypes.ENUMERATION,
+ FacetTypes.CONSTRAINTS,
+ FacetTypes.MININCLUSIVE,
+ FacetTypes.MAXINCLUSIVE,
+ FacetTypes.MINEXCLUSIVE,
+ FacetTypes.MAXINCLUSIVE,
+ FacetTypes.EXPLICITTIMEZONE
+ )
+ ),
+ DataTypes.DateType
+ );
+ public static final ItemType dateItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "date"),
+ new HashSet<>(
+ Arrays.asList(
+ FacetTypes.ENUMERATION,
+ FacetTypes.CONSTRAINTS,
+ FacetTypes.MININCLUSIVE,
+ FacetTypes.MAXINCLUSIVE,
+ FacetTypes.MINEXCLUSIVE,
+ FacetTypes.MAXINCLUSIVE,
+ FacetTypes.EXPLICITTIMEZONE
+ )
+ ),
+ DataTypes.TimestampType
+ );
+ public static final ItemType timeItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "time"),
+ new HashSet<>(
+ Arrays.asList(
+ FacetTypes.ENUMERATION,
+ FacetTypes.CONSTRAINTS,
+ FacetTypes.MININCLUSIVE,
+ FacetTypes.MAXINCLUSIVE,
+ FacetTypes.MINEXCLUSIVE,
+ FacetTypes.MAXINCLUSIVE,
+ FacetTypes.EXPLICITTIMEZONE
+ )
+ ),
+ DataTypes.TimestampType
+ );
+ public static final ItemType hexBinaryItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "hexBinary"),
+ new HashSet<>(
+ Arrays.asList(
+ FacetTypes.ENUMERATION,
+ FacetTypes.CONSTRAINTS,
+ FacetTypes.LENGTH,
+ FacetTypes.MINLENGTH,
+ FacetTypes.MAXLENGTH
+ )
+ ),
+ DataTypes.BinaryType
+ );
+ public static final ItemType anyURIItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "anyURI"),
+ new HashSet<>(
+ Arrays.asList(
+ FacetTypes.ENUMERATION,
+ FacetTypes.CONSTRAINTS,
+ FacetTypes.LENGTH,
+ FacetTypes.MINLENGTH,
+ FacetTypes.MAXLENGTH
+ )
+ ),
+ DataTypes.StringType
+ );
+ public static final ItemType base64BinaryItem = new AtomicItemType(
+ new Name(Name.XS_NS, "xs", "base64Binary"),
+ new HashSet<>(
+ Arrays.asList(
+ FacetTypes.ENUMERATION,
+ FacetTypes.CONSTRAINTS,
+ FacetTypes.LENGTH,
+ FacetTypes.MINLENGTH,
+ FacetTypes.MAXLENGTH
+ )
+ ),
+ DataTypes.BinaryType
+ );
+
+ public static final ItemType integerItem = new DerivedAtomicItemType(
+ new Name(Name.XS_NS, "xs", "integer"),
+ AtomicItemType.decimalItem,
+ AtomicItemType.decimalItem,
+ Facets.getIntegerFacets(),
+ false,
+ DataTypes.createDecimalType() // TODO : how to support arbitrary-sized integer
+ );
+
+ public static final ItemType longItem = new DerivedAtomicItemType(
+ new Name(Name.XS_NS, "xs", "long"),
+ integerItem,
+ AtomicItemType.decimalItem,
+ Facets.createMinMaxFacets(
+ new IntegerItem(new BigInteger("-9223372036854775808")),
+ new IntegerItem(new BigInteger("9223372036854775807")),
+ true
+ ),
+ false,
+ DataTypes.LongType // TODO : how to support arbitrary-sized integer
+ );
+
+ public static final ItemType intItem = new DerivedAtomicItemType(
+ Name.createVariableInDefaultTypeNamespace("int"),
+ longItem,
+ AtomicItemType.decimalItem,
+ Facets.createMinMaxFacets(new IntItem(-2147483648), new IntItem(2147483647), true),
+ false,
+ DataTypes.IntegerType // TODO : how to support arbitrary-sized integer
+ );
+
+ public static final ItemType shortItem = new DerivedAtomicItemType(
+ new Name(Name.XS_NS, "xs", "short"),
+ intItem,
+ AtomicItemType.decimalItem,
+ Facets.createMinMaxFacets(new IntItem(-32768), new IntItem(32767), true),
+ false,
+ DataTypes.ShortType // TODO : how to support arbitrary-sized integer
+ );
+
+ public static final ItemType JSONItem = new JsonItemType();
+ public static final ItemType objectItem = new ObjectItemType(
+ new Name(Name.JS_NS, "js", "object"),
+ BuiltinTypesCatalogue.JSONItem,
+ false,
+ Collections.emptyMap(),
+ Collections.emptyList(),
+ null
+ );
+ public static final ItemType arrayItem = new ArrayItemType(
+ new Name(Name.JS_NS, "js", "array"),
+ BuiltinTypesCatalogue.JSONItem,
+ null,
+ null,
+ null,
+ null
+ );
+ public static final ItemType anyFunctionItem = new FunctionItemType(true);
public static boolean typeExists(Name name) {
for (ItemType builtInItemType : builtInItemTypes) {
diff --git a/src/main/java/org/rumbledb/types/DerivedAtomicItemType.java b/src/main/java/org/rumbledb/types/DerivedAtomicItemType.java
index 36d4ab633d..ac40cfd644 100644
--- a/src/main/java/org/rumbledb/types/DerivedAtomicItemType.java
+++ b/src/main/java/org/rumbledb/types/DerivedAtomicItemType.java
@@ -72,7 +72,7 @@ public class DerivedAtomicItemType implements ItemType {
}
// TODO : turn builtin derived atomic types into this class
- private DerivedAtomicItemType(
+ DerivedAtomicItemType(
Name name,
ItemType baseType,
ItemType primitiveType,
@@ -112,7 +112,7 @@ public boolean equals(Object other) {
if (!(other instanceof ItemType)) {
return false;
}
- return this.getIdentifierString().equals(((ItemType) other).getIdentifierString());
+ return isEqualTo((ItemType) other);
}
@Override
diff --git a/src/main/java/org/rumbledb/types/FunctionItemType.java b/src/main/java/org/rumbledb/types/FunctionItemType.java
index d14a4c7a76..3cd7f7abdd 100644
--- a/src/main/java/org/rumbledb/types/FunctionItemType.java
+++ b/src/main/java/org/rumbledb/types/FunctionItemType.java
@@ -1,5 +1,6 @@
package org.rumbledb.types;
+import org.rumbledb.context.Name;
import org.rumbledb.exceptions.OurBadException;
import java.util.Set;
@@ -22,17 +23,22 @@ public class FunctionItemType implements ItemType {
}
// we have a parameter because the empty one is public and inherited
- private FunctionItemType(boolean isGeneric) {
+ FunctionItemType(boolean isGeneric) {
this.isGeneric = true;
this.signature = null;
}
+ @Override
+ public Name getName() {
+ return null;
+ }
+
@Override
public boolean equals(Object other) {
- if (!(other instanceof FunctionItemType)) {
+ if (!(other instanceof ItemType)) {
return false;
}
- return this.toString().equals(other.toString());
+ return isEqualTo((ItemType) other);
}
@Override
@@ -52,6 +58,9 @@ public boolean isSubtypeOf(ItemType superType) {
) {
return true;
}
+ if (this.signature == null) {
+ return false;
+ }
if (superType.isFunctionItemType() && this.signature.isSubtypeOf(superType.getSignature())) {
return true;
}
diff --git a/src/main/java/org/rumbledb/types/ItemItemType.java b/src/main/java/org/rumbledb/types/ItemItemType.java
index cedb5aeb07..84b9a241fa 100644
--- a/src/main/java/org/rumbledb/types/ItemItemType.java
+++ b/src/main/java/org/rumbledb/types/ItemItemType.java
@@ -19,16 +19,16 @@ public class ItemItemType implements ItemType {
public ItemItemType() {
}
- private ItemItemType(Name name) {
+ ItemItemType(Name name) {
this.name = name;
}
@Override
- public boolean equals(Object o) {
- if (!(o instanceof ItemType)) {
+ public boolean equals(Object other) {
+ if (!(other instanceof ItemType)) {
return false;
}
- return this.getIdentifierString().equals(((ItemType) o).getIdentifierString());
+ return isEqualTo((ItemType) other);
}
@Override
@@ -80,4 +80,9 @@ public DataType toDataFrameType() {
public boolean isDataFrameType() {
return false;
}
+
+ @Override
+ public boolean isResolved() {
+ return true;
+ }
}
diff --git a/src/main/java/org/rumbledb/types/ItemType.java b/src/main/java/org/rumbledb/types/ItemType.java
index 3af43dd021..f9333fb05d 100644
--- a/src/main/java/org/rumbledb/types/ItemType.java
+++ b/src/main/java/org/rumbledb/types/ItemType.java
@@ -25,6 +25,7 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.context.Name;
+import org.rumbledb.context.StaticContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import java.io.Serializable;
@@ -39,11 +40,30 @@ public interface ItemType extends Serializable {
/**
* Tests for itemType equality.
*
- * @param other another item type.
+ * @param other another object.
* @return true it is equal to other, false otherwise.
*/
boolean equals(Object other);
+
+ /**
+ * Tests for itemType equality.
+ *
+ * @param otherType another item type.
+ * @return true it is equal to other, false otherwise.
+ */
+ default boolean isEqualTo(ItemType otherType) {
+ if (this instanceof FunctionItemType || otherType instanceof FunctionItemType) {
+ if (!(this instanceof FunctionItemType) || !(otherType instanceof FunctionItemType)) {
+ return false;
+ }
+ return this.toString().equals(otherType.toString());
+ }
+ if (this.getName() == null || otherType.getName() == null) {
+ return this == otherType;
+ }
+ return this.getName().equals(otherType.getName());
+ }
// region kind
/**
@@ -393,7 +413,9 @@ default boolean getClosedFacet() {
* @return content facet value for array item types
*/
default ArrayContentDescriptor getArrayContentFacet() {
- throw new UnsupportedOperationException("array content facet is allowed only for array item types");
+ throw new UnsupportedOperationException(
+ "array content facet is allowed only for array item types " + this.getClass().getCanonicalName()
+ );
}
/**
@@ -432,4 +454,8 @@ default boolean isResolved() {
default void resolve(DynamicContext context, ExceptionMetadata metadata) {
return;
}
+
+ default void resolve(StaticContext context, ExceptionMetadata metadata) {
+ return;
+ }
}
diff --git a/src/main/java/org/rumbledb/types/ItemTypeFactory.java b/src/main/java/org/rumbledb/types/ItemTypeFactory.java
index f02314b455..d420c310b2 100644
--- a/src/main/java/org/rumbledb/types/ItemTypeFactory.java
+++ b/src/main/java/org/rumbledb/types/ItemTypeFactory.java
@@ -11,6 +11,7 @@
import org.apache.spark.sql.types.VarcharType;
import org.rumbledb.api.Item;
import org.rumbledb.context.Name;
+import org.rumbledb.context.StaticContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.InvalidSchemaException;
import org.rumbledb.exceptions.OurBadException;
@@ -22,21 +23,20 @@
public class ItemTypeFactory {
- public static ItemType createItemTypeFromJSoundCompactItem(Name name, Item item) {
+ public static ItemType createItemTypeFromJSoundCompactItem(Name name, Item item, StaticContext staticContext) {
if (item.isString()) {
String typeString = item.getStringValue();
if (typeString.contains("=")) {
throw new InvalidSchemaException("= not supported yet", ExceptionMetadata.EMPTY_METADATA);
}
- Name typeName = Name.createVariableInDefaultTypeNamespace(typeString);
- return new ItemTypeReference(typeName);
+ return new ItemTypeReference(Name.createTypeNameFromLiteral(typeString, staticContext));
}
if (item.isArray()) {
List
- members = item.getItems();
if (members.size() != 1) {
throw new InvalidSchemaException("Invalid JSound: " + item, ExceptionMetadata.EMPTY_METADATA);
}
- ItemType memberType = createItemTypeFromJSoundCompactItem(null, members.get(0));
+ ItemType memberType = createItemTypeFromJSoundCompactItem(null, members.get(0), staticContext);
return new ArrayItemType(
null,
BuiltinTypesCatalogue.arrayItem,
@@ -64,7 +64,7 @@ public static ItemType createItemTypeFromJSoundCompactItem(Name name, Item item)
FieldDescriptor fieldDescriptor = new FieldDescriptor();
fieldDescriptor.setName(key);
fieldDescriptor.setRequired(required);
- fieldDescriptor.setType(createItemTypeFromJSoundCompactItem(null, value));
+ fieldDescriptor.setType(createItemTypeFromJSoundCompactItem(null, value, staticContext));
fieldDescriptor.setUnique(false);
fieldDescriptor.setDefaultValue(null);
fields.put(key, fieldDescriptor);
@@ -105,9 +105,6 @@ private static ItemType createItemTypeFromSparkStructType(StructType structType)
ItemType mappedItemType;
if (filedType instanceof StructType) {
mappedItemType = createItemTypeFromSparkStructType((StructType) filedType);
- } else if (filedType instanceof ArrayType) {
- // TODO : add proper function
- mappedItemType = BuiltinTypesCatalogue.arrayItem;
} else {
mappedItemType = createItemType(filedType);
}
diff --git a/src/main/java/org/rumbledb/types/ItemTypeReference.java b/src/main/java/org/rumbledb/types/ItemTypeReference.java
index 1ef76128fa..8c0012bf09 100644
--- a/src/main/java/org/rumbledb/types/ItemTypeReference.java
+++ b/src/main/java/org/rumbledb/types/ItemTypeReference.java
@@ -4,6 +4,7 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.context.Name;
+import org.rumbledb.context.StaticContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.OurBadException;
import org.rumbledb.exceptions.UndefinedTypeException;
@@ -18,6 +19,9 @@ public class ItemTypeReference implements ItemType {
private Name name;
public ItemTypeReference(Name name) {
+ if (name == null) {
+ throw new OurBadException("A type name cannot be null!");
+ }
this.name = name;
}
@@ -35,6 +39,16 @@ public void resolve(DynamicContext context, ExceptionMetadata metadata) {
}
}
+ public void resolve(StaticContext context, ExceptionMetadata metadata) {
+ if (!context.getInScopeSchemaTypes().checkInScopeSchemaTypeExists(this.name)) {
+ throw new UndefinedTypeException("Type undefined: " + this.name, metadata);
+ }
+ this.resolvedItemType = context.getInScopeSchemaTypes().getInScopeSchemaType(this.name);
+ if (!this.resolvedItemType.isResolved()) {
+ this.resolvedItemType.resolve(context, metadata);
+ }
+ }
+
@Override
public int getTypeTreeDepth() {
if (this.resolvedItemType == null) {
@@ -121,6 +135,9 @@ public boolean hasName() {
public Name getName() {
+ if (this.resolvedItemType != null) {
+ return this.resolvedItemType.getName();
+ }
return this.name;
}
@@ -299,6 +316,13 @@ public String getIdentifierString() {
return this.name.toString();
}
+ public String toString() {
+ if (!this.hasName()) {
+ return "";
+ }
+ return this.name.toString();
+ }
+
public DataType toDataFrameType() {
if (this.resolvedItemType == null) {
throw new OurBadException("Unresolved type: " + this.name);
diff --git a/src/main/java/org/rumbledb/types/JsonItemType.java b/src/main/java/org/rumbledb/types/JsonItemType.java
index f71ed7b559..17017aeb17 100644
--- a/src/main/java/org/rumbledb/types/JsonItemType.java
+++ b/src/main/java/org/rumbledb/types/JsonItemType.java
@@ -13,19 +13,19 @@ public class JsonItemType implements ItemType {
private static final long serialVersionUID = 1L;
- static final ItemType jsonItem = new JsonItemType(new Name(Name.JS_NS, "js", "json-item"));
+ static final ItemType jsonItem = new JsonItemType();
private final Name name;
- private JsonItemType(Name name) {
- this.name = name;
+ JsonItemType() {
+ this.name = new Name(Name.JS_NS, "js", "json-item");
}
@Override
- public boolean equals(Object o) {
- if (!(o instanceof ItemType)) {
+ public boolean equals(Object other) {
+ if (!(other instanceof ItemType)) {
return false;
}
- return this.getIdentifierString().equals(((ItemType) o).getIdentifierString());
+ return isEqualTo((ItemType) other);
}
@Override
@@ -80,4 +80,9 @@ public DataType toDataFrameType() {
public boolean isDataFrameType() {
return false;
}
+
+ @Override
+ public boolean isResolved() {
+ return true;
+ }
}
diff --git a/src/main/java/org/rumbledb/types/ObjectItemType.java b/src/main/java/org/rumbledb/types/ObjectItemType.java
index 39f39ae923..c6f22cd9ca 100644
--- a/src/main/java/org/rumbledb/types/ObjectItemType.java
+++ b/src/main/java/org/rumbledb/types/ObjectItemType.java
@@ -4,6 +4,7 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.context.Name;
+import org.rumbledb.context.StaticContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import java.util.*;
@@ -60,7 +61,7 @@ public boolean equals(Object other) {
if (!(other instanceof ItemType)) {
return false;
}
- return this.getIdentifierString().equals(((ItemType) other).getIdentifierString());
+ return isEqualTo((ItemType) other);
}
@Override
@@ -204,7 +205,7 @@ public String toString() {
sb.append(" (object item)\n");
sb.append("base type : ");
- sb.append(this.baseType.getIdentifierString());
+ sb.append(this.baseType.toString());
sb.append("\n");
List fields = new ArrayList<>(this.getObjectContentFacet().values());
@@ -218,7 +219,7 @@ public String toString() {
sb.append(" (required)");
}
sb.append(" : ");
- sb.append(field.getType().getIdentifierString());
+ sb.append(field.getType().toString());
sb.append("\n");
}
}
@@ -243,6 +244,7 @@ public boolean isDataFrameType() {
public boolean isResolved() {
for (Map.Entry entry : this.content.entrySet()) {
if (!entry.getValue().getType().isResolved()) {
+ System.err.println("Unresolved: " + entry.getValue().getType().getClass().getCanonicalName());
return false;
}
}
@@ -257,4 +259,13 @@ public void resolve(DynamicContext context, ExceptionMetadata metadata) {
}
}
}
+
+ @Override
+ public void resolve(StaticContext context, ExceptionMetadata metadata) {
+ for (Map.Entry entry : this.content.entrySet()) {
+ if (!entry.getValue().getType().isResolved()) {
+ entry.getValue().getType().resolve(context, metadata);
+ }
+ }
+ }
}
diff --git a/src/main/java/org/rumbledb/types/SequenceType.java b/src/main/java/org/rumbledb/types/SequenceType.java
index f60a40243c..28492073f9 100644
--- a/src/main/java/org/rumbledb/types/SequenceType.java
+++ b/src/main/java/org/rumbledb/types/SequenceType.java
@@ -21,21 +21,22 @@
package org.rumbledb.types;
import org.rumbledb.context.DynamicContext;
+import org.rumbledb.context.StaticContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.OurBadException;
import java.io.Serializable;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class SequenceType implements Serializable {
private static final long serialVersionUID = 1L;
- private Arity arity;
private ItemType itemType;
- private boolean isEmptySequence = false;
+ private Arity arity;
- public final static SequenceType MOST_GENERAL_SEQUENCE_TYPE = new SequenceType(
+ public final static SequenceType ITEM_STAR = new SequenceType(
BuiltinTypesCatalogue.item,
Arity.ZeroOrMore
);
@@ -44,55 +45,79 @@ public class SequenceType implements Serializable {
public SequenceType(ItemType itemType, Arity arity) {
+ if (arity == Arity.Zero) {
+ this.itemType = BuiltinTypesCatalogue.item;
+ this.arity = Arity.Zero;
+ return;
+ }
this.itemType = itemType;
this.arity = arity;
+ if (this.itemType == null) {
+ System.err.println(
+ "[WARNING] Missing item type in incomplete sequence type "
+ + this.arity
+ + ", defaulting to item. Please let us know as we would like to look into this!"
+ );
+ this.itemType = BuiltinTypesCatalogue.item;
+ }
+ if (this.arity == null) {
+ System.err.println(
+ "[WARNING] Missing arity in incomplete sequence type "
+ + this.itemType
+ + ", defaulting to *. Please let us know as we would like to look into this!"
+ );
+ this.arity = Arity.ZeroOrMore;
+ }
}
public SequenceType(ItemType itemType) {
this.itemType = itemType;
this.arity = Arity.One;
+ if (this.itemType == null) {
+ throw new OurBadException("Missing item type in incomplete sequence type " + this.arity);
+ }
}
private SequenceType() {
- this.itemType = null;
- this.arity = null;
- this.isEmptySequence = true;
+ this.itemType = BuiltinTypesCatalogue.item;
+ this.arity = Arity.Zero;
}
public boolean isResolved() {
- if (this.isEmptySequence) {
+ if (isEmptySequence()) {
return true;
}
return this.itemType.isResolved();
}
public void resolve(DynamicContext context, ExceptionMetadata metadata) {
- if (this.isEmptySequence) {
+ if (isEmptySequence()) {
+ return;
+ }
+ this.itemType.resolve(context, metadata);
+ }
+
+ public void resolve(StaticContext context, ExceptionMetadata metadata) {
+ if (isEmptySequence()) {
return;
}
this.itemType.resolve(context, metadata);
}
public boolean isEmptySequence() {
- return this.isEmptySequence;
+ return this.arity == Arity.Zero;
}
public ItemType getItemType() {
- if (this.isEmptySequence) {
- throw new OurBadException("Empty sequence type has no item");
- }
return this.itemType;
}
public Arity getArity() {
- if (this.isEmptySequence) {
- throw new OurBadException("Empty sequence type has no arity");
- }
return this.arity;
}
public boolean isSubtypeOf(SequenceType superType) {
- if (this.isEmptySequence) {
+ if (isEmptySequence()) {
return superType.arity == Arity.OneOrZero || superType.arity == Arity.ZeroOrMore;
}
return this.itemType.isSubtypeOf(superType.getItemType())
@@ -102,7 +127,7 @@ public boolean isSubtypeOf(SequenceType superType) {
// keep in consideration also automatic promotion of integer > decimal > double and anyURI > string
public boolean isSubtypeOfOrCanBePromotedTo(SequenceType superType) {
- if (this.isEmptySequence) {
+ if (isEmptySequence()) {
return superType.arity == Arity.OneOrZero || superType.arity == Arity.ZeroOrMore;
}
return this.isAritySubtypeOf(superType.arity)
@@ -118,7 +143,7 @@ public boolean isAritySubtypeOf(Arity superArity) {
}
public boolean hasEffectiveBooleanValue() {
- if (this.isEmptySequence) {
+ if (isEmptySequence()) {
return true;
} else if (this.itemType.isSubtypeOf(BuiltinTypesCatalogue.JSONItem)) {
return true;
@@ -142,7 +167,7 @@ public boolean hasEffectiveBooleanValue() {
public boolean hasOverlapWith(SequenceType other) {
// types overlap if both itemType and Arity overlap, we also need to take care of empty sequence
- if (this.isEmptySequence()) {
+ if (isEmptySequence()) {
return other.isEmptySequence()
|| other.getArity() == Arity.OneOrZero
|| other.getArity() == Arity.ZeroOrMore;
@@ -156,7 +181,7 @@ public boolean hasOverlapWith(SequenceType other) {
}
public SequenceType leastCommonSupertypeWith(SequenceType other) {
- if (this.isEmptySequence) {
+ if (isEmptySequence()) {
if (other.isEmptySequence()) {
return this;
} else {
@@ -192,7 +217,7 @@ public SequenceType leastCommonSupertypeWith(SequenceType other) {
// increment arity of a sequence type from ? to * and from 1 to +, leave others arity or sequence types untouched
public SequenceType incrementArity() {
- if (!this.isEmptySequence()) {
+ if (!isEmptySequence()) {
if (this.arity == Arity.One) {
return new SequenceType(this.getItemType(), Arity.OneOrMore);
} else if (this.arity == Arity.OneOrZero) {
@@ -208,7 +233,7 @@ public boolean equals(Object other) {
return false;
}
SequenceType sequenceType = (SequenceType) other;
- if (this.isEmptySequence) {
+ if (isEmptySequence()) {
return sequenceType.isEmptySequence();
}
if (sequenceType.isEmptySequence()) {
@@ -241,11 +266,23 @@ public String getSymbol() {
public String getSymbol() {
return "";
}
+ },
+ Zero {
+ @Override
+ public String getSymbol() {
+ return "";
+ }
};
public abstract String getSymbol();
public boolean isSubtypeOf(Arity superArity) {
+ if (superArity == Zero) {
+ return this == Arity.Zero;
+ }
+ if (this == Zero) {
+ return this == Arity.ZeroOrMore || this == Arity.OneOrZero;
+ }
if (superArity == Arity.ZeroOrMore || superArity == this)
return true;
else
@@ -253,6 +290,9 @@ public boolean isSubtypeOf(Arity superArity) {
}
public Arity multiplyWith(Arity other) {
+ if (this == Zero || other == Zero) {
+ return Zero;
+ }
if (this == One && other == One) {
return One;
} else if (this.isSubtypeOf(OneOrZero) && other.isSubtypeOf(OneOrZero)) {
@@ -268,7 +308,7 @@ public Arity multiplyWith(Arity other) {
@Override
public String toString() {
- if (this.isEmptySequence) {
+ if (isEmptySequence()) {
return "()";
}
StringBuilder result = new StringBuilder();
@@ -388,6 +428,50 @@ public String toString() {
);
sequenceTypes.put("null?", new SequenceType(BuiltinTypesCatalogue.nullItem, SequenceType.Arity.OneOrZero));
+ sequenceTypes.put(
+ "function(object*, object) as object*",
+ new SequenceType(
+ ItemTypeFactory.createFunctionItemType(
+ new FunctionSignature(
+ Arrays.asList(
+ new SequenceType(BuiltinTypesCatalogue.objectItem, SequenceType.Arity.ZeroOrMore),
+ new SequenceType(BuiltinTypesCatalogue.objectItem)
+ ),
+ new SequenceType(BuiltinTypesCatalogue.objectItem, SequenceType.Arity.ZeroOrMore)
+ )
+ )
+ )
+ );
+ sequenceTypes.put(
+ "function(object*, object) as function(object*, object) as object*",
+ new SequenceType(
+ ItemTypeFactory.createFunctionItemType(
+ new FunctionSignature(
+ Arrays.asList(
+ new SequenceType(BuiltinTypesCatalogue.objectItem, SequenceType.Arity.ZeroOrMore),
+ new SequenceType(BuiltinTypesCatalogue.objectItem)
+ ),
+ new SequenceType(
+ ItemTypeFactory.createFunctionItemType(
+ new FunctionSignature(
+ Arrays.asList(
+ new SequenceType(
+ BuiltinTypesCatalogue.objectItem,
+ SequenceType.Arity.ZeroOrMore
+ ),
+ new SequenceType(BuiltinTypesCatalogue.objectItem)
+ ),
+ new SequenceType(
+ BuiltinTypesCatalogue.objectItem,
+ SequenceType.Arity.ZeroOrMore
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ );
}
public static SequenceType createSequenceType(String userFriendlyName) {
diff --git a/src/main/java/org/rumbledb/types/UnionItemType.java b/src/main/java/org/rumbledb/types/UnionItemType.java
index 013c90ac6f..1f66bf3925 100644
--- a/src/main/java/org/rumbledb/types/UnionItemType.java
+++ b/src/main/java/org/rumbledb/types/UnionItemType.java
@@ -4,6 +4,7 @@
import org.apache.spark.sql.types.DataTypes;
import org.rumbledb.context.DynamicContext;
import org.rumbledb.context.Name;
+import org.rumbledb.context.StaticContext;
import org.rumbledb.exceptions.ExceptionMetadata;
import java.util.Arrays;
@@ -40,7 +41,7 @@ public boolean equals(Object other) {
if (!(other instanceof ItemType)) {
return false;
}
- return this.getIdentifierString().equals(((ItemType) other).getIdentifierString());
+ return isEqualTo((ItemType) other);
}
@Override
@@ -148,4 +149,13 @@ public void resolve(DynamicContext context, ExceptionMetadata metadata) {
}
}
}
+
+ @Override
+ public void resolve(StaticContext context, ExceptionMetadata metadata) {
+ for (ItemType itemType : this.content.getTypes()) {
+ if (!itemType.isResolved()) {
+ itemType.resolve(context, metadata);
+ }
+ }
+ }
}
diff --git a/src/main/java/sparksoniq/spark/DataFrameUtils.java b/src/main/java/sparksoniq/spark/DataFrameUtils.java
index 5ceb22bd44..7ca241a805 100644
--- a/src/main/java/sparksoniq/spark/DataFrameUtils.java
+++ b/src/main/java/sparksoniq/spark/DataFrameUtils.java
@@ -11,15 +11,17 @@
import org.rumbledb.api.Item;
import org.rumbledb.context.Name;
import org.rumbledb.exceptions.InvalidInstanceException;
+import org.rumbledb.exceptions.RumbleException;
import org.rumbledb.items.ObjectItem;
import org.rumbledb.items.parsing.ItemParser;
import org.rumbledb.runtime.typing.ValidateTypeIterator;
import org.rumbledb.types.BuiltinTypesCatalogue;
+import org.rumbledb.types.FieldDescriptor;
import org.rumbledb.types.ItemType;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
+import java.util.Map.Entry;
public class DataFrameUtils {
public static Dataset
convertItemRDDToDataFrame(
@@ -158,55 +160,87 @@ private static void validateArrayItemInSchema(Item item) {
}
public static void validateSchemaItemAgainstDataFrame(
- Item schemaItem,
- StructType dataFrameSchema
+ ItemType expectedType,
+ ItemType actualType
) {
- StructType generatedSchema = generateDataFrameSchemaFromSchemaItem(schemaItem);
- for (StructField column : dataFrameSchema.fields()) {
- final String columnName = column.name();
- final DataType columnDataType = column.dataType();
-
- boolean columnMatched = Arrays.stream(generatedSchema.fields()).anyMatch(structField -> {
- String generatedColumnName = structField.name();
- if (!generatedColumnName.equals(columnName)) {
- return false;
+ if (expectedType.isAtomicItemType()) {
+ if (actualType.isSubtypeOf(expectedType)) {
+ return;
+ }
+ throw new InvalidInstanceException(
+ "Type mismatch: " + expectedType + " vs. " + actualType
+ );
+ }
+ if (expectedType.isArrayItemType()) {
+ if (actualType.isArrayItemType()) {
+ if (
+ actualType.getArrayContentFacet()
+ .getType()
+ .isSubtypeOf(expectedType.getArrayContentFacet().getType())
+ ) {
+ return;
}
+ }
+ throw new InvalidInstanceException(
+ "Type mismatch: expected "
+ + expectedType.getArrayContentFacet().getType()
+ + " but actually "
+ + actualType.getArrayContentFacet().getType()
+ );
+ }
+ for (Entry actualTypeDescriptor : actualType.getObjectContentFacet().entrySet()) {
+ final String actualColumnName = actualTypeDescriptor.getKey();
+ final ItemType columnDataType = actualTypeDescriptor.getValue().getType();
- DataType generatedDataType = structField.dataType();
- if (isUserTypeApplicable(generatedDataType, columnDataType)) {
- return true;
+ boolean columnMatched = false;
+ for (
+ Entry expectedTypeDescriptor : expectedType.getObjectContentFacet().entrySet()
+ ) {
+ String expectedColumnName = expectedTypeDescriptor.getKey();
+ if (!expectedColumnName.equals(actualColumnName)) {
+ continue;
}
- throw new InvalidInstanceException(
- "Fields defined in schema must fully match the fields of input data: "
- + "expected '"
- + ItemParser.getItemTypeNameFromDataFrameDataType(columnDataType)
- + "' type for field '"
- + columnName
- + "', but found '"
- + ItemParser.getItemTypeNameFromDataFrameDataType(generatedDataType)
- + "'"
- );
- });
+ ItemType expectedColumnType = expectedTypeDescriptor.getValue().getType();
+ try {
+ validateSchemaItemAgainstDataFrame(expectedColumnType, columnDataType);
+ } catch (Exception e) {
+ RumbleException ex = new InvalidInstanceException(
+ "Fields defined in schema must fully match the fields of input data: "
+ + "expected '"
+ + expectedColumnType
+ + "' type for field '"
+ + actualColumnName
+ + "', but found '"
+ + columnDataType
+ + "'"
+ );
+ ex.initCause(e);
+ throw ex;
+ }
+
+ columnMatched = true;
+ break;
+ }
if (!columnMatched) {
throw new InvalidInstanceException(
"Fields defined in schema must fully match the fields of input data: "
+ "missing type information for '"
- + columnName
+ + actualColumnName
+ "' field."
);
}
}
- for (String generatedSchemaColumnName : generatedSchema.fieldNames()) {
- boolean userColumnMatched = Arrays.asList(dataFrameSchema.fieldNames()).contains(generatedSchemaColumnName);
+ for (String expectedColumnName : expectedType.getObjectContentFacet().keySet()) {
+ boolean userColumnMatched = actualType.getObjectContentFacet().keySet().contains(expectedColumnName);
if (!userColumnMatched) {
throw new InvalidInstanceException(
"Fields defined in schema must fully match the fields of input data: "
+ "redundant type information for non-existent field '"
- + generatedSchemaColumnName
+ + expectedColumnName
+ "'."
);
}
diff --git a/src/main/java/sparksoniq/spark/SparkSessionManager.java b/src/main/java/sparksoniq/spark/SparkSessionManager.java
index e4cc9deb4c..5e77f7b410 100644
--- a/src/main/java/sparksoniq/spark/SparkSessionManager.java
+++ b/src/main/java/sparksoniq/spark/SparkSessionManager.java
@@ -51,7 +51,7 @@
public class SparkSessionManager {
- private static final String APP_NAME = "jsoniq-on-spark";
+ private static final String APP_NAME = "Rumble application";
public static int COLLECT_ITEM_LIMIT = 0;
private static SparkSessionManager instance;
private static Level LOG_LEVEL = Level.FATAL;
@@ -91,9 +91,12 @@ public SparkSession getOrCreateSession() {
private void setDefaultConfiguration() {
try {
- this.configuration = new SparkConf()
- .setAppName(APP_NAME)
- .set("spark.sql.crossJoin.enabled", "true"); // enables cartesian product
+ this.configuration = new SparkConf();
+ if (this.configuration.get("spark.app.name", "").equals(" long collectRDDwithLimitWarningOnly(JavaRDD rdd, List ou
return count;
}
}
+
}
diff --git a/src/main/java/sparksoniq/spark/ml/AnnotateFunctionIterator.java b/src/main/java/sparksoniq/spark/ml/AnnotateFunctionIterator.java
index 57bc782b9b..c8b22fdc6e 100644
--- a/src/main/java/sparksoniq/spark/ml/AnnotateFunctionIterator.java
+++ b/src/main/java/sparksoniq/spark/ml/AnnotateFunctionIterator.java
@@ -10,6 +10,8 @@
import org.rumbledb.runtime.DataFrameRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
import org.rumbledb.types.BuiltinTypesCatalogue;
+import org.rumbledb.types.ItemType;
+import org.rumbledb.types.ItemTypeFactory;
import sparksoniq.spark.DataFrameUtils;
@@ -32,15 +34,21 @@ public JSoundDataFrame getDataFrame(DynamicContext context) {
RuntimeIterator inputDataIterator = this.children.get(0);
RuntimeIterator schemaIterator = this.children.get(1);
Item schemaItem = schemaIterator.materializeFirstItemOrNull(context);
-
+ ItemType schemaType = ItemTypeFactory.createItemTypeFromJSoundCompactItem(null, schemaItem, null);
+ schemaType.resolve(context, getMetadata());
try {
if (inputDataIterator.isDataFrame()) {
JSoundDataFrame inputDataAsDataFrame = inputDataIterator.getDataFrame(context);
- DataFrameUtils.validateSchemaItemAgainstDataFrame(
- schemaItem,
+ inputDataAsDataFrame.getDataFrame().printSchema();
+ inputDataAsDataFrame.getDataFrame().show();
+ ItemType actualSchemaType = ItemTypeFactory.createItemType(
inputDataAsDataFrame.getDataFrame().schema()
);
+ DataFrameUtils.validateSchemaItemAgainstDataFrame(
+ schemaType,
+ actualSchemaType
+ );
return inputDataAsDataFrame;
}
diff --git a/src/main/java/sparksoniq/spark/ml/ApplyEstimatorRuntimeIterator.java b/src/main/java/sparksoniq/spark/ml/ApplyEstimatorRuntimeIterator.java
index 7df04db024..a84f8192bf 100644
--- a/src/main/java/sparksoniq/spark/ml/ApplyEstimatorRuntimeIterator.java
+++ b/src/main/java/sparksoniq/spark/ml/ApplyEstimatorRuntimeIterator.java
@@ -15,6 +15,7 @@
import org.rumbledb.exceptions.InvalidRumbleMLParamException;
import org.rumbledb.exceptions.MLNotADataFrameException;
import org.rumbledb.exceptions.OurBadException;
+import org.rumbledb.exceptions.RumbleException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.FunctionItem;
import org.rumbledb.items.structured.JSoundDataFrame;
@@ -29,6 +30,8 @@
import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import static sparksoniq.spark.ml.RumbleMLUtils.convertRumbleObjectItemToSparkMLParamMap;
@@ -53,6 +56,10 @@ public ApplyEstimatorRuntimeIterator(
this.estimator = estimator;
}
+ public Estimator> getEstimator() {
+ return this.estimator;
+ }
+
@Override
public Item materializeFirstItemOrNull(
DynamicContext dynamicContext
@@ -73,13 +80,117 @@ public Item materializeFirstItemOrNull(
try {
fittedModel = this.estimator.fit(this.inputDataset.getDataFrame(), paramMap);
} catch (IllegalArgumentException | NoSuchElementException e) {
- throw new InvalidRumbleMLParamException(
+ String message = e.getMessage();
+ Pattern pattern = Pattern.compile("(.* ]) does not exist. Available: (.*)");
+ Matcher matcher = pattern.matcher(message);
+ if (matcher.find()) {
+ RumbleException ex = new InvalidRumbleMLParamException(
+ "There is an issue with the parameters provided to the estimator "
+ + this.estimatorShortName
+ + "."
+ + "\nIt seems you provided an array of strings ("
+ + matcher.group(1)
+ + ") for parameter featuresCol, inputCol or similar."
+ + "\nHowever, this parameter should be a string, which is the name of the field associated with an array of features to train on or to transform."
+ + "\nIf you do not have such a field in your data, then you can build it with the VectorAssembler transformer by combining the fields you want to include."
+ + "\n\nFor example:"
+ + "\nlet $vector-assembler := get-transformer(\"VectorAssembler\")"
+ + "\nlet $data-with-features := $vector-assembler($data, {\"inputCols\" : [ \"age\", \"weight\" ], \"outputCol\" : \"features\" })"
+ + "\n\nand then"
+ + "\nlet $est := get-estimator(\""
+ + this.estimatorShortName
+ + "\")"
+ + "\nlet $model := $est($data-with-features, {\"featuresCol\" : \"features\" }) (: assuming featuresCol is the parameter :)"
+ + "\n\nIf the features are in already your data, you can specify that field name with the parameter 'featuresCol' or 'inputCol' (check the documentation of the estimator to be sure) passed to your estimator.",
+ getMetadata()
+ );
+ ex.initCause(e);
+ throw ex;
+ }
+ pattern = Pattern.compile("(.*) does not exist. Available: (.*)");
+ matcher = pattern.matcher(message);
+ if (matcher.find()) {
+ RumbleException ex = new InvalidRumbleMLParamException(
+ "There is an issue with the parameters provided to the estimator "
+ + this.estimatorShortName
+ + "."
+ + "\nIt seems you provided a field ("
+ + matcher.group(1)
+ + ") that does not exist"
+ + "\nThe available fields are: "
+ + matcher.group(2),
+ getMetadata()
+ );
+ ex.initCause(e);
+ throw ex;
+ }
+ pattern = Pattern.compile(
+ "requirement failed: Column (.*) must be of type struct,values:array> but was actually .*"
+ );
+ matcher = pattern.matcher(message);
+ if (matcher.find()) {
+ RumbleException ex = new InvalidRumbleMLParamException(
+ "There is an issue with the parameters provided to the estimator "
+ + this.estimatorShortName
+ + "."
+ + "\nIt seems you provided an field that is not an array of features for parameter featuresCol, inputCol or similar."
+ + "\nIf you do not have such a field in your data, then you can build it with the VectorAssembler transformer by combining the fields you want to include."
+ + "\n\nFor example:"
+ + "\nlet $vector-assembler := get-transformer(\"VectorAssembler\")"
+ + "\nlet $data-with-features := $vector-assembler($data, {\"inputCols\" : [ \"age\", \"weight\" ], \"outputCol\" : \"features\" })"
+ + "\n\nand then"
+ + "\nlet $est := get-estimator(\""
+ + this.estimatorShortName
+ + "\")"
+ + "\nlet $model := $est($data-with-features, {\"featuresCol\" : \"features\" }) (: assuming featuresCol is the parameter :)"
+ + "\n\nIf the features are already in your data, you can specify that field name with the parameter 'featuresCol' or 'inputCol' (check the documentation of the estimator to be sure) passed to your estimator.",
+ getMetadata()
+ );
+ ex.initCause(e);
+ throw ex;
+ }
+ pattern = Pattern.compile(
+ "requirement failed: Column (.*) must be of type struct,values:array> but was actually .*"
+ );
+ matcher = pattern.matcher(message);
+ if (matcher.find()) {
+ RumbleException ex = new InvalidRumbleMLParamException(
+ "There is an issue with the parameters provided to the estimator "
+ + this.estimatorShortName
+ + "."
+ + "\nIt seems you provided an field that is not an array of features for parameter featuresCol, inputCol or similar."
+ + "\nIf you do not have such a field in your data, then you can build it with the VectorAssembler transformer by combining the fields you want to include."
+ + "\n\nFor example:"
+ + "\nlet $vector-assembler := get-transformer(\"VectorAssembler\")"
+ + "\nlet $data-with-features := $vector-assembler($data, {\"inputCols\" : [ \"age\", \"weight\" ], \"outputCol\" : \"features\" })"
+ + "\n\nand then"
+ + "\nlet $est := get-estimator(\""
+ + this.estimatorShortName
+ + "\")"
+ + "\nlet $model := $est($data-with-features, {\"featuresCol\" : \"features\" }) (: assuming featuresCol is the parameter :)"
+ + "\n\nIf the features are already in your data, you can specify that field name with the parameter 'featuresCol' or 'inputCol' (check the documentation of the estimator to be sure) passed to your estimator.",
+ getMetadata()
+ );
+ ex.initCause(e);
+ throw ex;
+ }
+ RumbleException ex = new InvalidRumbleMLParamException(
"Parameters provided to "
+ this.estimatorShortName
+ " causes the following error: "
- + e.getMessage(),
+ + e.getMessage()
+ + "\n\nWe are happy to give you a few hints:"
+ + "\nBy default, we look for the features used to train the model in the field 'features'."
+ + "\nIf this field does not exist, you can build it with the VectorAssembler transformer by combining the fields you want to include."
+ + "\n\nFor example:"
+ + "\nlet $vector-assembler := get-transformer(\"VectorAssembler\")"
+ + "\nlet $data := $vector-assembler($data, {\"inputCols\" : [ \"age\", \"weight\" ], \"outputCol\" : \"features\" })"
+ + "\n\nIf the features are in your data, but in a different field than 'features', you can specify that different field name with the parameter 'featuresCol' or 'inputCol' (check the documentation of the estimator to be sure) passed to your estimator."
+ + "\n\nIf the error says that it must be of the type struct,values:array> but was actually something different, then it means you specified a field that is not an assembled features array. You need to use the VectorAssembler to prepare it.",
getMetadata()
);
+ ex.initCause(e);
+ throw ex;
}
return generateTransformerFunctionItem(fittedModel);
diff --git a/src/main/java/sparksoniq/spark/ml/ApplyTransformerRuntimeIterator.java b/src/main/java/sparksoniq/spark/ml/ApplyTransformerRuntimeIterator.java
index 08365639d9..dc6f2c2037 100644
--- a/src/main/java/sparksoniq/spark/ml/ApplyTransformerRuntimeIterator.java
+++ b/src/main/java/sparksoniq/spark/ml/ApplyTransformerRuntimeIterator.java
@@ -15,6 +15,7 @@
import org.rumbledb.exceptions.InvalidRumbleMLParamException;
import org.rumbledb.exceptions.MLNotADataFrameException;
import org.rumbledb.exceptions.OurBadException;
+import org.rumbledb.exceptions.RumbleException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.structured.JSoundDataFrame;
import org.rumbledb.runtime.DataFrameRuntimeIterator;
@@ -24,6 +25,8 @@
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import static sparksoniq.spark.ml.RumbleMLUtils.convertRumbleObjectItemToSparkMLParamMap;
@@ -49,6 +52,10 @@ public ApplyTransformerRuntimeIterator(
this.transformer = transformer;
}
+ public Transformer getTransformer() {
+ return this.transformer;
+ }
+
@Override
public JSoundDataFrame getDataFrame(DynamicContext context) {
this.inputDataset = getInputDataset(context);
@@ -80,13 +87,92 @@ public JSoundDataFrame getDataFrame(DynamicContext context) {
getMetadata()
);
}
- throw new InvalidRumbleMLParamException(
+ String message = e.getMessage();
+ Pattern pattern = Pattern.compile("(.* ]) does not exist. Available: (.*)");
+ Matcher matcher = pattern.matcher(message);
+ if (matcher.find()) {
+ RumbleException ex = new InvalidRumbleMLParamException(
+ "There is an issue with the parameters provided to the transformer "
+ + this.transformerShortName
+ + "."
+ + "\nIt seems you provided an array of strings ("
+ + matcher.group(1)
+ + ") for parameter featuresCol, inputCol or similar."
+ + "\nHowever, this parameter should be a string, which is the name of the field associated with an array of features to train on or to transform."
+ + "\nIf you do not have such a field in your data, then you can build it with the VectorAssembler transformer by combining the fields you want to include."
+ + "\n\nFor example:"
+ + "\nlet $vector-assembler := get-transformer(\"VectorAssembler\")"
+ + "\nlet $data-with-features := $vector-assembler($data, {\"inputCols\" : [ \"age\", \"weight\" ], \"outputCol\" : \"features\" })"
+ + "\n\nand then"
+ + "\nlet $est := get-transformer(\""
+ + this.transformerShortName
+ + "\")"
+ + "\nlet $model := $est($data-with-features, {\"inputCol\" : \"features\" }) (: assuming inputCol is the parameter :)"
+ + "\n\nIf the features are in already your data, you can specify that field name with the parameter 'featuresCol' or 'inputCol' (check the documentation of the estimator to be sure) passed to your estimator.",
+ getMetadata()
+ );
+ ex.initCause(e);
+ throw ex;
+ }
+ pattern = Pattern.compile("(.*) does not exist. Available: (.*)");
+ matcher = pattern.matcher(message);
+ if (matcher.find()) {
+ RumbleException ex = new InvalidRumbleMLParamException(
+ "There is an issue with the parameters provided to the transformer "
+ + this.transformerShortName
+ + "."
+ + "\nIt seems you provided a field ("
+ + matcher.group(1)
+ + ") that does not exist"
+ + "\nThe available fields are: "
+ + matcher.group(2),
+ getMetadata()
+ );
+ ex.initCause(e);
+ throw ex;
+ }
+ pattern = Pattern.compile(
+ "requirement failed: Column (.*) must be of type struct,values:array> but was actually .*"
+ );
+ matcher = pattern.matcher(message);
+ if (matcher.find()) {
+ RumbleException ex = new InvalidRumbleMLParamException(
+ "There is an issue with the parameters provided to the transformer "
+ + this.transformerShortName
+ + "."
+ + "\nIt seems you provided an field that is not an array of features for parameter featuresCol, inputCol or similar."
+ + "\nIf you do not have such a field in your data, then you can build it with the VectorAssembler transformer by combining the fields you want to include."
+ + "\n\nFor example:"
+ + "\nlet $vector-assembler := get-transformer(\"VectorAssembler\")"
+ + "\nlet $data-with-features := $vector-assembler($data, {\"inputCols\" : [ \"age\", \"weight\" ], \"outputCol\" : \"features\" })"
+ + "\n\nand then"
+ + "\nlet $est := get-estimator(\""
+ + this.transformerShortName
+ + "\")"
+ + "\nlet $model := $est($data-with-features, {\"inputCol\" : \"features\" }) (: assuming inputCol is the parameter :)"
+ + "\n\nIf the features are already in your data, you can specify that field name with the parameter 'featuresCol' or 'inputCol' (check the documentation of the estimator to be sure) passed to your estimator.",
+ getMetadata()
+ );
+ ex.initCause(e);
+ throw ex;
+ }
+ RumbleException ex = new InvalidRumbleMLParamException(
"Parameters provided to "
+ this.transformerShortName
+ " causes the following error: "
- + e.getMessage(),
+ + e.getMessage()
+ + "\n\nWe are happy to give you a few hints:"
+ + "\nBy default, we look for the features used to apply the model in the field 'features'."
+ + "\nIf this field does not exist, you can build it with the VectorAssembler transformer by combining the fields you want to include."
+ + "\n\nFor example:"
+ + "\nlet $vector-assembler := get-transformer(\"VectorAssembler\")"
+ + "\nlet $data := $vector-assembler($data, {\"inputCols\" : [ \"age\", \"weight\" ], \"outputCol\" : \"features\" })"
+ + "\n\nIf the features are in your data, but in a different field than 'features', you can specify that different field name with the parameter 'featuresCol' or 'inputCol' (check the documentation of the estimator to be sure) passed to your estimator."
+ + "\n\nIf the error says that it must be of the type struct,values:array> but was actually something different, then it means you specified a field that is not an assembled features array. You need to use the VectorAssembler to prepare it.",
getMetadata()
);
+ ex.initCause(e);
+ throw ex;
}
}
diff --git a/src/main/java/sparksoniq/spark/ml/GetEstimatorFunctionIterator.java b/src/main/java/sparksoniq/spark/ml/GetEstimatorFunctionIterator.java
index 011ba47834..2a5d1431c4 100644
--- a/src/main/java/sparksoniq/spark/ml/GetEstimatorFunctionIterator.java
+++ b/src/main/java/sparksoniq/spark/ml/GetEstimatorFunctionIterator.java
@@ -26,14 +26,11 @@
import org.rumbledb.context.FunctionIdentifier;
import org.rumbledb.context.Name;
import org.rumbledb.exceptions.ExceptionMetadata;
-import org.rumbledb.exceptions.IteratorFlowException;
import org.rumbledb.exceptions.OurBadException;
-import org.rumbledb.exceptions.UnexpectedTypeException;
import org.rumbledb.expressions.ExecutionMode;
import org.rumbledb.items.FunctionItem;
+import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator;
import org.rumbledb.runtime.RuntimeIterator;
-import org.rumbledb.runtime.functions.base.LocalFunctionCallIterator;
-import org.rumbledb.types.BuiltinTypesCatalogue;
import org.rumbledb.types.FunctionSignature;
import org.rumbledb.types.SequenceType;
@@ -42,7 +39,7 @@
import java.util.Collections;
import java.util.List;
-public class GetEstimatorFunctionIterator extends LocalFunctionCallIterator {
+public class GetEstimatorFunctionIterator extends AtMostOneItemLocalRuntimeIterator {
private static final long serialVersionUID = 1L;
public static final List