Skip to content

Commit

Permalink
[ASTERIXDB-2634][FUN] String functions to return null on data/type er…
Browse files Browse the repository at this point in the history
…rors

- user model changes: no
- storage format changes: no
- interface changes: no

Details:
- substring(string, int, int)
- codepoint-to-string([int])
- string-concat([string])

Change-Id: I17905ad9e767b43822d28a46123bc1390a159cc7
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/4083
Contrib: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Hussain Towaileb <hussainht@gmail.com>
  • Loading branch information
AliSolaiman committed Nov 21, 2019
1 parent 38649da commit 69a7af4
Show file tree
Hide file tree
Showing 20 changed files with 401 additions and 156 deletions.
@@ -0,0 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

drop dataverse test if exists;
create dataverse test;
use test;

create type dsType as {
id: int,
i8: int8,
i16: int16,
i32: int32,
i64: int64,
f: float,
d: double,
str1: string
};

create type openType as {
id: int
};

create dataset DS(dsType) primary key id;
create dataset openDS(openType) primary key id;
@@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

use test;

insert into DS([
{"id": 1, "i8": int8("-2"), "i16": int16("10"), "i32": int32("21"), "i64": int64("87"), "f": float("4.2"), "d": double("5.0"), "str1": "foo", "mixed": 7},
{"id": 2, "i8": int8("0"), "i16": int16("-10"), "i32": int32("21"), "i64": int64("87"), "f": float("4.2"), "d": double("5.3"), "str1": "foo", "mixed": "m"}
]);

insert into openDS([
{"id": 1, "i8": int8("-2"), "i16": int16("10"), "i32": int32("21"), "i64": int64("87"), "f": float("4.2"), "d": double("5.0"), "str1": "foo", "mixed": 7},
{"id": 2, "i8": int8("0"), "i16": int16("-10"), "i32": int32("21"), "i64": int64("87"), "f": float("4.2"), "d": double("5.3"), "str1": "foo", "mixed": "m"}
]);
@@ -0,0 +1,36 @@
/*
* 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.
*/

/*
* Description: tests that string functions do not throw exception on type/data errors
*/
// requesttype=application/json
// param max-warnings:json=1000

use test;

from DS as ds
select
`string-concat`([ds.str1, ds.i8]),
"str" || ds.mixed,
substring("hello world", ds.str1, ds.i8),
substring(ds.mixed, 0, 1),
`codepoint-to-string`(ds.str1),
`codepoint-to-string`([ds.mixed])
order by ds.id;
@@ -0,0 +1,36 @@
/*
* 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.
*/

/*
* Description: tests that string functions do not throw exception on type/data errors
*/
// requesttype=application/json
// param max-warnings:json=1000

use test;

from openDS as ds
select
`string-concat`([ds.str1, ds.i8]),
"str" || ds.mixed,
substring("hello world", ds.str1, ds.i8),
substring(ds.mixed, 0, 1),
`codepoint-to-string`(ds.str1),
`codepoint-to-string`([ds.mixed])
order by ds.id;
@@ -0,0 +1,35 @@
/*
* 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.
*/

/*
* Description: tests that string functions do not throw exception on type/data errors
*/
// requesttype=application/json
// param max-warnings:json=1000

use test;


select
`string-concat`(["str", 9]),
"str" || int8("9"),
substring("hello world", "str", 3),
`codepoint-to-string`("str"),
`codepoint-to-string`(["str"]),
`codepoint-to-string`([5.5]);
@@ -0,0 +1,20 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

drop dataverse test if exists;
@@ -0,0 +1,2 @@
{ "$1": null, "$2": null, "$3": null, "$4": null, "$5": null, "$6": "\u0007" }
{ "$1": null, "$2": "strm", "$3": null, "$4": "m", "$5": null, "$6": null }
@@ -0,0 +1,2 @@
{ "$1": null, "$2": null, "$3": null, "$4": null, "$5": null, "$6": "\u0007" }
{ "$1": null, "$2": "strm", "$3": null, "$4": "m", "$5": null, "$6": null }
@@ -0,0 +1 @@
{ "$1": null, "$2": null, "$3": null, "$4": null, "$5": null, "$6": null }
Expand Up @@ -13606,5 +13606,30 @@
<expected-warn>Invalid value: function substring expects its 2nd input parameter to be an integer value, got Infinity (in line 34, at column 1)</expected-warn>
</compilation-unit>
</test-case>
<test-case FilePath="fun_return_null/string_fun" check-warnings="true">
<compilation-unit name="string_fun_004">
<output-dir compare="Text">string_fun_004</output-dir>
<expected-warn>Unsupported type: string-concat cannot process input type tinyint (in line 30, at column 1)</expected-warn>
<expected-warn>Type mismatch: function substring expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string (in line 32, at column 1)</expected-warn>
<expected-warn>Type mismatch: function substring expects its 1st input parameter to be of type string, but the actual input type is bigint (in line 33, at column 1)</expected-warn>
<expected-warn>Unsupported type: string-concat cannot process input type bigint (in line 31, at column 7)</expected-warn>
<expected-warn>Type mismatch: function codepoint-to-string expects its 1st input parameter to be of type array, but the actual input type is string (in line 34, at column 1)</expected-warn>
<expected-warn>Unsupported type: codepoint-to-string cannot process input type string (in line 35, at column 1)</expected-warn>

<expected-warn>Unsupported type: string-concat cannot process input type tinyint (in line 30, at column 1)</expected-warn>
<expected-warn>Type mismatch: function substring expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string (in line 32, at column 1)</expected-warn>
<expected-warn>Type mismatch: function substring expects its 1st input parameter to be of type string, but the actual input type is bigint (in line 33, at column 1)</expected-warn>
<expected-warn>Unsupported type: string-concat cannot process input type bigint (in line 31, at column 7)</expected-warn>
<expected-warn>Type mismatch: function codepoint-to-string expects its 1st input parameter to be of type array, but the actual input type is string (in line 34, at column 1)</expected-warn>
<expected-warn>Unsupported type: codepoint-to-string cannot process input type string (in line 35, at column 1)</expected-warn>

<expected-warn>Unsupported type: string-concat cannot process input type bigint (in line 30, at column 1)</expected-warn>
<expected-warn>Unsupported type: string-concat cannot process input type tinyint (in line 31, at column 7)</expected-warn>
<expected-warn>Type mismatch: function substring expects its 1st input parameter to be of type string, but the actual input type is bigint (in line 32, at column 1)</expected-warn>
<expected-warn>Type mismatch: function codepoint-to-string expects its 1st input parameter to be of type array, but the actual input type is string (in line 33, at column 1)</expected-warn>
<expected-warn>Unsupported type: codepoint-to-string cannot process input type string (in line 34, at column 1)</expected-warn>
<expected-warn>Unsupported type: codepoint-to-string cannot process input type double (in line 35, at column 1)</expected-warn>
</compilation-unit>
</test-case>
</test-group>
</test-suite>
Expand Up @@ -116,15 +116,18 @@ public void serialize(AOrderedList instance, DataOutput out) throws HyracksDataE
listBuilder.write(out, false);
}

/** {@code serOrderedList} is untagged. {@code offset} points to the list value (first byte is the item tag) */
public static int getOrderedListLength(byte[] serOrderedList, int offset) {
return AInt32SerializerDeserializer.getInt(serOrderedList, offset + 1);
}

/** {@code serOrderedList} is tagged. {@code offset} points to the list tag */
public static int getNumberOfItems(byte[] serOrderedList, int offset) {
// 6 = tag (1) + itemTag (1) + list size (4)
return AInt32SerializerDeserializer.getInt(serOrderedList, offset + 6);
}

/** {@code serOrderedList} is tagged. {@code offset} points to the list tag */
public static int getItemOffset(byte[] serOrderedList, int offset, int itemIndex) throws HyracksDataException {
return SerializerDeserializerUtil.getItemOffset(serOrderedList, offset, itemIndex);
}
Expand Down
Expand Up @@ -94,6 +94,7 @@
import org.apache.asterix.om.typecomputer.impl.IfNanOrInfTypeComputer;
import org.apache.asterix.om.typecomputer.impl.IfNullTypeComputer;
import org.apache.asterix.om.typecomputer.impl.InjectFailureTypeComputer;
import org.apache.asterix.om.typecomputer.impl.Int64ArrayToStringTypeComputer;
import org.apache.asterix.om.typecomputer.impl.LocalAvgTypeComputer;
import org.apache.asterix.om.typecomputer.impl.LocalSingleVarStatisticsTypeComputer;
import org.apache.asterix.om.typecomputer.impl.MinMaxAggTypeComputer;
Expand Down Expand Up @@ -127,7 +128,6 @@
import org.apache.asterix.om.typecomputer.impl.SleepTypeComputer;
import org.apache.asterix.om.typecomputer.impl.StringJoinTypeComputer;
import org.apache.asterix.om.typecomputer.impl.SubsetCollectionTypeComputer;
import org.apache.asterix.om.typecomputer.impl.SubstringTypeComputer;
import org.apache.asterix.om.typecomputer.impl.SwitchCaseComputer;
import org.apache.asterix.om.typecomputer.impl.ToArrayTypeComputer;
import org.apache.asterix.om.typecomputer.impl.ToBigIntTypeComputer;
Expand Down Expand Up @@ -1709,14 +1709,14 @@ public static FunctionInfo lookupFunction(FunctionIdentifier fid) {
addFunction(IS_BIT_SET_WITH_ALL_FLAG, BitValuePositionFlagTypeComputer.INSTANCE_TEST_WITH_FLAG, true);

// string functions
addFunction(STRING_CONSTRUCTOR, AStringTypeComputer.INSTANCE, true); // TODO
addFunction(STRING_CONSTRUCTOR, AStringTypeComputer.INSTANCE, true); // TODO(ali)
addFunction(STRING_LIKE, BooleanFunctionTypeComputer.INSTANCE, true);
addFunction(STRING_CONTAINS, UniformInputTypeComputer.STRING_BOOLEAN_INSTANCE, true);
addFunction(STRING_TO_CODEPOINT, UniformInputTypeComputer.STRING_INT64_LIST_INSTANCE, true);
addFunction(CODEPOINT_TO_STRING, AStringTypeComputer.INSTANCE, true); // TODO
addFunction(STRING_CONCAT, ConcatTypeComputer.INSTANCE_STRING, true); // TODO
addFunction(SUBSTRING, SubstringTypeComputer.INSTANCE, true); // TODO
addFunction(SUBSTRING_OFFSET_1, SubstringTypeComputer.INSTANCE, true); // TODO
addFunction(CODEPOINT_TO_STRING, Int64ArrayToStringTypeComputer.INSTANCE, true);
addFunction(STRING_CONCAT, ConcatTypeComputer.INSTANCE_STRING, true);
addFunction(SUBSTRING, AStringTypeComputer.INSTANCE_NULLABLE, true);
addFunction(SUBSTRING_OFFSET_1, AStringTypeComputer.INSTANCE_NULLABLE, true);
addFunction(SUBSTRING2, AStringTypeComputer.INSTANCE_NULLABLE, true);
addFunction(SUBSTRING2_OFFSET_1, AStringTypeComputer.INSTANCE_NULLABLE, true);
addFunction(STRING_LENGTH, UniformInputTypeComputer.STRING_INT64_INSTANCE, true);
Expand Down
Expand Up @@ -27,17 +27,18 @@

public class AStringTypeComputer extends AbstractResultTypeComputer {

public static final AStringTypeComputer INSTANCE = new AStringTypeComputer(false);
public static final AStringTypeComputer INSTANCE_NULLABLE = new AStringTypeComputer(true);
public static final AStringTypeComputer INSTANCE = new AStringTypeComputer(BuiltinType.ASTRING);
public static final AStringTypeComputer INSTANCE_NULLABLE =
new AStringTypeComputer(AUnionType.createNullableType(BuiltinType.ASTRING));

private final boolean nullable;
private final IAType outputType;

private AStringTypeComputer(boolean nullable) {
this.nullable = nullable;
private AStringTypeComputer(IAType outputType) {
this.outputType = outputType;
}

@Override
protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
return nullable ? AUnionType.createNullableType(BuiltinType.ASTRING) : BuiltinType.ASTRING;
return outputType;
}
}
Expand Up @@ -43,22 +43,10 @@ private ConcatTypeComputer(IAType resultType) {
protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
IAType argType = strippedInputTypes[0];
IAType outputType = resultType;
if (!argType.getTypeTag().isListType() || isUnknownable(((AbstractCollectionType) argType).getItemType())) {
if (!argType.getTypeTag().isListType()
|| ((AbstractCollectionType) argType).getItemType().getTypeTag() != outputType.getTypeTag()) {
outputType = AUnionType.createUnknownableType(outputType);
}
return outputType;
}

private boolean isUnknownable(IAType type) {
switch (type.getTypeTag()) {
case ANY:
case MISSING:
case NULL:
return true;
case UNION:
return ((AUnionType) type).isUnknownableType();
default:
return false;
}
}
}

0 comments on commit 69a7af4

Please sign in to comment.