Merge branch 'master' into westmann/scratch
diff --git a/asterix-app/src/test/resources/runtimets/queries/leftouterjoin/query_issue658/query_issue658.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/leftouterjoin/query_issue658/query_issue658.1.ddl.aql
new file mode 100644
index 0000000..b1910fb
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/leftouterjoin/query_issue658/query_issue658.1.ddl.aql
@@ -0,0 +1,29 @@
+/*
+ * Description : Left-outer joins two datasets, DBLP and CSX, based on their authors and titles.
+ * Success : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use dataverse test;
+
+create type DBLPType as closed {
+ id: int32,
+ dblpid: string,
+ title: string,
+ authors: string,
+ misc: string
+}
+
+create type CSXType as closed {
+ id: int32,
+ csxid: string,
+ title: string,
+ authors: string,
+ misc: string
+}
+
+create dataset DBLP(DBLPType) primary key id;
+create dataset CSX(CSXType) primary key id;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/leftouterjoin/query_issue658/query_issue658.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/leftouterjoin/query_issue658/query_issue658.2.update.aql
new file mode 100644
index 0000000..4e2123a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/leftouterjoin/query_issue658/query_issue658.2.update.aql
@@ -0,0 +1,15 @@
+/*
+ * Description : Left-outer joins two datasets, DBLP and CSX, based on their authors and titles.
+ * Success : Yes
+ */
+
+use dataverse test;
+
+load dataset DBLP
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/pub-small/dblp-small-id.txt"),("format"="delimited-text"),("delimiter"=":"));
+
+load dataset CSX
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/pub-small/csx-small-id.txt"),("format"="delimited-text"),("delimiter"=":"));
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/leftouterjoin/query_issue658/query_issue658.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/leftouterjoin/query_issue658/query_issue658.3.query.aql
new file mode 100644
index 0000000..04816a7
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/leftouterjoin/query_issue658/query_issue658.3.query.aql
@@ -0,0 +1,16 @@
+/*
+ * Description : Left-outer joins two datasets, DBLP and CSX, based on their authors and titles.
+ * Success : Yes
+ */
+
+use dataverse test;
+
+for $a in dataset('DBLP')
+order by $a.id
+return {
+"aid": $a.id,
+"bids": for $b in dataset('CSX')
+where $a.authors = $b.authors and $a.title != $b.title
+order by $b.id
+return $b.id
+}
diff --git a/asterix-app/src/test/resources/runtimets/queries/types/type_promotion_0/type_promotion_0.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/types/type_promotion_0/type_promotion_0.1.ddl.aql
new file mode 100644
index 0000000..c74fd3c
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/types/type_promotion_0/type_promotion_0.1.ddl.aql
@@ -0,0 +1,19 @@
+drop dataverse TestVerse if exists;
+create dataverse TestVerse;
+use dataverse TestVerse;
+
+create type Int64TestType as open {
+ myint64: int64,
+ myoptint64: int64?,
+ myint32: int32,
+ myoptint32: int32?,
+ myint16: int16,
+ myoptint16: int16?,
+ mydouble: double,
+ myoptdouble: double?,
+ myfloat: float,
+ myoptfloat: float?
+};
+
+create dataset Int64Test(Int64TestType)
+ primary key myint64;
diff --git a/asterix-app/src/test/resources/runtimets/queries/types/type_promotion_0/type_promotion_0.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/types/type_promotion_0/type_promotion_0.2.update.aql
new file mode 100644
index 0000000..8505bff
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/types/type_promotion_0/type_promotion_0.2.update.aql
@@ -0,0 +1,13 @@
+use dataverse TestVerse;
+
+/* promotable type for optional field */
+insert into dataset Int64Test (
+ {"myint64": int64("13"), "myoptint64": 13, "myint32": int8("2"), "myoptint32": int16("3"), "myint16": int8("9"), "myoptint16": int8("10"), "mydouble": float("2.12"), "myoptdouble": int64("32"), "myfloat": int8("9"), "myoptfloat": int32("328")}
+);
+/* promotable type for non-optional field */
+insert into dataset Int64Test (
+ {"myint64": 12, "myoptint64": null, "myint32": int8("2"), "myoptint32": date(null), "myint16": int8("9"), "myoptint16": interval-starts(null, null), "mydouble": float("2.12"), "myoptdouble": time(null), "myfloat": int8("9"), "myoptfloat": datetime(null) }
+);
+insert into dataset Int64Test (
+ {"myint64": int16("11"), "myoptint64": int8("3"), "myint32": int8("2"), "myoptint32": int16("3"), "myint16": int8("9"), "myoptint16": int8("10"), "mydouble": int8("2"), "myoptdouble": int16("32"), "myfloat": int16("9"), "myoptfloat": datetime(null) }
+);
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/queries/types/type_promotion_0/type_promotion_0.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/types/type_promotion_0/type_promotion_0.3.query.aql
new file mode 100644
index 0000000..8948b49
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/types/type_promotion_0/type_promotion_0.3.query.aql
@@ -0,0 +1,4 @@
+use dataverse TestVerse;
+
+for $i in dataset Int64Test
+return $i
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/results/leftouterjoin/query_issue658/query_issue658.1.adm b/asterix-app/src/test/resources/runtimets/results/leftouterjoin/query_issue658/query_issue658.1.adm
new file mode 100644
index 0000000..62c427a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/leftouterjoin/query_issue658/query_issue658.1.adm
@@ -0,0 +1,100 @@
+{ "aid": 1, "bids": [ ] }
+{ "aid": 2, "bids": [ ] }
+{ "aid": 3, "bids": [ ] }
+{ "aid": 4, "bids": [ ] }
+{ "aid": 5, "bids": [ 98 ] }
+{ "aid": 6, "bids": [ ] }
+{ "aid": 7, "bids": [ ] }
+{ "aid": 8, "bids": [ ] }
+{ "aid": 9, "bids": [ ] }
+{ "aid": 10, "bids": [ ] }
+{ "aid": 11, "bids": [ ] }
+{ "aid": 12, "bids": [ ] }
+{ "aid": 13, "bids": [ ] }
+{ "aid": 14, "bids": [ ] }
+{ "aid": 15, "bids": [ ] }
+{ "aid": 16, "bids": [ ] }
+{ "aid": 17, "bids": [ ] }
+{ "aid": 18, "bids": [ ] }
+{ "aid": 19, "bids": [ ] }
+{ "aid": 20, "bids": [ ] }
+{ "aid": 21, "bids": [ ] }
+{ "aid": 22, "bids": [ ] }
+{ "aid": 23, "bids": [ ] }
+{ "aid": 24, "bids": [ ] }
+{ "aid": 25, "bids": [ ] }
+{ "aid": 26, "bids": [ ] }
+{ "aid": 27, "bids": [ ] }
+{ "aid": 28, "bids": [ ] }
+{ "aid": 29, "bids": [ ] }
+{ "aid": 30, "bids": [ ] }
+{ "aid": 31, "bids": [ ] }
+{ "aid": 32, "bids": [ ] }
+{ "aid": 33, "bids": [ ] }
+{ "aid": 34, "bids": [ 57 ] }
+{ "aid": 35, "bids": [ ] }
+{ "aid": 36, "bids": [ ] }
+{ "aid": 37, "bids": [ ] }
+{ "aid": 38, "bids": [ ] }
+{ "aid": 39, "bids": [ ] }
+{ "aid": 40, "bids": [ ] }
+{ "aid": 41, "bids": [ ] }
+{ "aid": 42, "bids": [ ] }
+{ "aid": 43, "bids": [ ] }
+{ "aid": 44, "bids": [ ] }
+{ "aid": 45, "bids": [ ] }
+{ "aid": 46, "bids": [ ] }
+{ "aid": 47, "bids": [ ] }
+{ "aid": 48, "bids": [ ] }
+{ "aid": 49, "bids": [ ] }
+{ "aid": 50, "bids": [ ] }
+{ "aid": 51, "bids": [ ] }
+{ "aid": 52, "bids": [ ] }
+{ "aid": 53, "bids": [ ] }
+{ "aid": 54, "bids": [ 91 ] }
+{ "aid": 55, "bids": [ ] }
+{ "aid": 56, "bids": [ ] }
+{ "aid": 57, "bids": [ ] }
+{ "aid": 58, "bids": [ ] }
+{ "aid": 59, "bids": [ ] }
+{ "aid": 60, "bids": [ ] }
+{ "aid": 61, "bids": [ ] }
+{ "aid": 62, "bids": [ ] }
+{ "aid": 63, "bids": [ ] }
+{ "aid": 64, "bids": [ ] }
+{ "aid": 65, "bids": [ ] }
+{ "aid": 66, "bids": [ ] }
+{ "aid": 67, "bids": [ ] }
+{ "aid": 68, "bids": [ 57 ] }
+{ "aid": 69, "bids": [ 57 ] }
+{ "aid": 70, "bids": [ ] }
+{ "aid": 71, "bids": [ ] }
+{ "aid": 72, "bids": [ ] }
+{ "aid": 73, "bids": [ ] }
+{ "aid": 74, "bids": [ ] }
+{ "aid": 75, "bids": [ ] }
+{ "aid": 76, "bids": [ ] }
+{ "aid": 77, "bids": [ ] }
+{ "aid": 78, "bids": [ ] }
+{ "aid": 79, "bids": [ ] }
+{ "aid": 80, "bids": [ ] }
+{ "aid": 81, "bids": [ ] }
+{ "aid": 82, "bids": [ ] }
+{ "aid": 83, "bids": [ ] }
+{ "aid": 84, "bids": [ ] }
+{ "aid": 85, "bids": [ ] }
+{ "aid": 86, "bids": [ ] }
+{ "aid": 87, "bids": [ ] }
+{ "aid": 88, "bids": [ ] }
+{ "aid": 89, "bids": [ ] }
+{ "aid": 90, "bids": [ ] }
+{ "aid": 91, "bids": [ ] }
+{ "aid": 92, "bids": [ ] }
+{ "aid": 93, "bids": [ ] }
+{ "aid": 94, "bids": [ ] }
+{ "aid": 95, "bids": [ ] }
+{ "aid": 96, "bids": [ ] }
+{ "aid": 97, "bids": [ ] }
+{ "aid": 98, "bids": [ ] }
+{ "aid": 99, "bids": [ ] }
+{ "aid": 100, "bids": [ ] }
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/results/types/type_promotion_0/type_promotion_0.1.adm b/asterix-app/src/test/resources/runtimets/results/types/type_promotion_0/type_promotion_0.1.adm
new file mode 100644
index 0000000..3c356ed
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/types/type_promotion_0/type_promotion_0.1.adm
@@ -0,0 +1,3 @@
+{ "myint64": 11i64, "myoptint64": 3i64, "myint32": 2, "myoptint32": 3, "myint16": 9i16, "myoptint16": 10i16, "mydouble": 2.0d, "myoptdouble": 32.0d, "myfloat": 9.0f, "myoptfloat": null }
+{ "myint64": 12i64, "myoptint64": null, "myint32": 2, "myoptint32": null, "myint16": 9i16, "myoptint16": null, "mydouble": 2.119999885559082d, "myoptdouble": null, "myfloat": 9.0f, "myoptfloat": null }
+{ "myint64": 13i64, "myoptint64": 13i64, "myint32": 2, "myoptint32": 3, "myint16": 9i16, "myoptint16": 10i16, "mydouble": 2.119999885559082d, "myoptdouble": 32.0d, "myfloat": 9.0f, "myoptfloat": 328.0f }
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/testsuite.xml b/asterix-app/src/test/resources/runtimets/testsuite.xml
index d36fbd4..b80a5b2 100644
--- a/asterix-app/src/test/resources/runtimets/testsuite.xml
+++ b/asterix-app/src/test/resources/runtimets/testsuite.xml
@@ -4533,6 +4533,11 @@
</test-group>
<test-group name="leftouterjoin">
<test-case FilePath="leftouterjoin">
+ <compilation-unit name="query_issue658">
+ <output-dir compare="Text">query_issue658</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="leftouterjoin">
<compilation-unit name="query_issue285">
<output-dir compare="Text">query_issue285</output-dir>
</compilation-unit>
@@ -4568,5 +4573,10 @@
<output-dir compare="Text">record01</output-dir>
</compilation-unit>
</test-case>
+ <test-case FilePath="types">
+ <compilation-unit name="type_promotion_0">
+ <output-dir compare="Text">type_promotion_0</output-dir>
+ </compilation-unit>
+ </test-case>
</test-group>
</test-suite>
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/dataset/adapter/FileSystemBasedAdapter.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/dataset/adapter/FileSystemBasedAdapter.java
index 33ee11f..753f7d1 100644
--- a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/dataset/adapter/FileSystemBasedAdapter.java
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/dataset/adapter/FileSystemBasedAdapter.java
@@ -16,7 +16,6 @@
import java.io.IOException;
import java.io.InputStream;
-import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -29,6 +28,7 @@
import edu.uci.ics.asterix.om.types.ATypeTag;
import edu.uci.ics.asterix.om.types.AUnionType;
import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.asterix.om.util.NonTaggedFormatUtil;
import edu.uci.ics.asterix.runtime.operators.file.AdmSchemafullRecordParserFactory;
import edu.uci.ics.asterix.runtime.operators.file.NtDelimitedDataTupleParserFactory;
import edu.uci.ics.hyracks.algebricks.common.constraints.AlgebricksPartitionConstraint;
@@ -108,11 +108,11 @@
for (int i = 0; i < n; i++) {
ATypeTag tag = null;
if (recordType.getFieldTypes()[i].getTypeTag() == ATypeTag.UNION) {
- List<IAType> unionTypes = ((AUnionType) recordType.getFieldTypes()[i]).getUnionList();
- if (unionTypes.size() != 2 && unionTypes.get(0).getTypeTag() != ATypeTag.NULL) {
+ if (!NonTaggedFormatUtil.isOptionalField(((AUnionType) recordType.getFieldTypes()[i]))) {
throw new NotImplementedException("Non-optional UNION type is not supported.");
}
- tag = unionTypes.get(1).getTypeTag();
+ tag = ((AUnionType) recordType.getFieldTypes()[i]).getUnionList()
+ .get(NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST).getTypeTag();
} else {
tag = recordType.getFieldTypes()[i].getTypeTag();
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ACastVisitor.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ACastVisitor.java
index 4e939ce..a711eb9 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ACastVisitor.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ACastVisitor.java
@@ -15,6 +15,7 @@
package edu.uci.ics.asterix.om.pointables.cast;
+import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@@ -28,8 +29,12 @@
import edu.uci.ics.asterix.om.types.ARecordType;
import edu.uci.ics.asterix.om.types.ATypeTag;
import edu.uci.ics.asterix.om.types.AbstractCollectionType;
+import edu.uci.ics.asterix.om.types.EnumDeserializer;
import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.asterix.om.types.hierachy.ATypeHierarchy;
+import edu.uci.ics.asterix.om.types.hierachy.ITypePromoteComputer;
import edu.uci.ics.hyracks.algebricks.common.utils.Triple;
+import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
/**
* This class is a IVisitablePointableVisitor implementation which recursively
@@ -86,10 +91,48 @@
}
@Override
- public Void visit(AFlatValuePointable accessor, Triple<IVisitablePointable, IAType, Boolean> arg) {
+ public Void visit(AFlatValuePointable accessor, Triple<IVisitablePointable, IAType, Boolean> arg)
+ throws AsterixException {
+ if (arg.second == null) {
+ // for open type case
+ arg.first.set(accessor);
+ return null;
+ }
// set the pointer for result
- arg.first.set(accessor);
+ ATypeTag reqTypeTag = ((IAType) (arg.second)).getTypeTag();
+ ATypeTag inputTypeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(accessor.getByteArray()[accessor
+ .getStartOffset()]);
+ if (!needPromote(inputTypeTag, reqTypeTag)) {
+ arg.first.set(accessor);
+ } else {
+ ArrayBackedValueStorage castBuffer = new ArrayBackedValueStorage();
+ ITypePromoteComputer promoteComputer = ATypeHierarchy.getTypePromoteComputer(inputTypeTag, reqTypeTag);
+ if (promoteComputer != null) {
+
+ try {
+ // do the promotion; note that the type tag field should be skipped
+ promoteComputer.promote(accessor.getByteArray(), accessor.getStartOffset() + 1,
+ accessor.getLength() - 1, castBuffer);
+ arg.first.set(castBuffer);
+ } catch (IOException e) {
+ throw new AsterixException(e);
+ }
+ } else {
+ throw new AsterixException("Type mismatch: cannot cast type " + inputTypeTag + " to " + reqTypeTag);
+ }
+ }
+
return null;
}
+ private boolean needPromote(ATypeTag tag0, ATypeTag tag1) {
+ if (tag0 == tag1) {
+ return false;
+ }
+ if (tag0 == ATypeTag.NULL) {
+ return false;
+ }
+ return true;
+ }
+
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ARecordCaster.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ARecordCaster.java
index 507b845..e7e0ef2 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ARecordCaster.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ARecordCaster.java
@@ -36,6 +36,7 @@
import edu.uci.ics.asterix.om.types.AUnionType;
import edu.uci.ics.asterix.om.types.EnumDeserializer;
import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.asterix.om.types.hierachy.ATypeHierarchy;
import edu.uci.ics.asterix.om.util.NonTaggedFormatUtil;
import edu.uci.ics.asterix.om.util.ResettableByteArrayOutputStream;
import edu.uci.ics.hyracks.algebricks.common.utils.Pair;
@@ -205,6 +206,17 @@
optionalFields[reqFnPos] && fieldTypeTag.equals(nullTypeTag))) {
fieldPermutation[reqFnPos] = fnPos;
openFields[fnPos] = false;
+ } else {
+ // if mismatch, check whether input type can be promoted to the required type
+ ATypeTag inputTypeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(fieldTypeTag
+ .getByteArray()[fieldTypeTag.getStartOffset()]);
+ ATypeTag requiredTypeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(reqFieldTypeTag
+ .getByteArray()[reqFieldTypeTag.getStartOffset()]);
+
+ if (ATypeHierarchy.canPromote(inputTypeTag, requiredTypeTag)) {
+ fieldPermutation[reqFnPos] = fnPos;
+ openFields[fnPos] = false;
+ }
}
fnStart++;
reqFnStart++;
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/types/ARecordType.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/types/ARecordType.java
index 0319c7c..28a41d1 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/types/ARecordType.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/types/ARecordType.java
@@ -66,6 +66,7 @@
* @throws AsterixException
* if there are duplicate field names or if there is an error serializing the field names
*/
+ @SuppressWarnings("resource")
public ARecordType(String typeName, String[] fieldNames, IAType[] fieldTypes, boolean isOpen)
throws AsterixException {
super(typeName);
@@ -96,6 +97,11 @@
hashCodeIndexPairs[i] = hashCodeIndexPairs[i] << 32;
hashCodeIndexPairs[i] = hashCodeIndexPairs[i] | i;
}
+ try {
+ dos.close();
+ } catch (IOException e) {
+ throw new AsterixException(e);
+ }
serializedFieldNames = baaos.getByteArray();
Arrays.sort(hashCodeIndexPairs);
@@ -336,7 +342,8 @@
break;
default:
throw new AlgebricksException("The field \"" + fieldName + "\" which is of type "
- + fieldType.getTypeTag() + " cannot be indexed using the Length Partitioned N-Gram index.");
+ + fieldType.getTypeTag()
+ + " cannot be indexed using the Length Partitioned N-Gram index.");
}
break;
case LENGTH_PARTITIONED_WORD_INVIX:
@@ -348,7 +355,8 @@
break;
default:
throw new AlgebricksException("The field \"" + fieldName + "\" which is of type "
- + fieldType.getTypeTag() + " cannot be indexed using the Length Partitioned Keyword index.");
+ + fieldType.getTypeTag()
+ + " cannot be indexed using the Length Partitioned Keyword index.");
}
break;
case SINGLE_PARTITION_NGRAM_INVIX:
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/operators/file/DelimitedDataParser.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/operators/file/DelimitedDataParser.java
index 5a639dc..23f7aab 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/operators/file/DelimitedDataParser.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/operators/file/DelimitedDataParser.java
@@ -29,6 +29,8 @@
import edu.uci.ics.asterix.om.base.ANull;
import edu.uci.ics.asterix.om.types.ARecordType;
import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.AUnionType;
+import edu.uci.ics.asterix.om.util.NonTaggedFormatUtil;
import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
import edu.uci.ics.hyracks.dataflow.common.data.parsers.IValueParser;
@@ -115,8 +117,9 @@
&& recordType.getFieldTypes()[i].getTypeTag() != ATypeTag.NULL) {
// if the field is empty and the type is optional, insert NULL
// note that string type can also process empty field as an empty string
- if (recordType.getFieldTypes()[i].getTypeTag() != ATypeTag.UNION) {
- throw new AsterixException("Field " + i + " cannot be NULL. ");
+ if (recordType.getFieldTypes()[i].getTypeTag() != ATypeTag.UNION
+ || !NonTaggedFormatUtil.isOptionalField((AUnionType) recordType.getFieldTypes()[i])) {
+ throw new AsterixException("Field " + i + " is not an optional type so it cannot accept null value. ");
}
fieldValueBufferOutput.writeByte(ATypeTag.NULL.serialize());
ANullSerializerDeserializer.INSTANCE.serialize(ANull.NULL, out);