[Feature](datatype) Add IPv4/v6 data type for doris (#24965)
This commit is contained in:
@ -329,6 +329,19 @@ public class BinaryPredicate extends Predicate implements Writable {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canCompareIP(PrimitiveType t1, PrimitiveType t2) {
|
||||
if (t1.isIPv4Type()) {
|
||||
return t2.isIPv4Type() || t2.isStringType();
|
||||
} else if (t2.isIPv4Type()) {
|
||||
return t1.isStringType();
|
||||
} else if (t1.isIPv6Type()) {
|
||||
return t2.isIPv6Type() || t2.isStringType();
|
||||
} else if (t2.isIPv6Type()) {
|
||||
return t1.isStringType();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Type dateV2ComparisonResultType(ScalarType t1, ScalarType t2) {
|
||||
if (!t1.isDatetimeV2() && !t2.isDatetimeV2()) {
|
||||
return Type.DATEV2;
|
||||
@ -411,6 +424,19 @@ public class BinaryPredicate extends Predicate implements Writable {
|
||||
}
|
||||
}
|
||||
|
||||
if (canCompareIP(getChild(0).getType().getPrimitiveType(), getChild(1).getType().getPrimitiveType())) {
|
||||
if ((getChild(0).getType().isIP() && getChild(1) instanceof StringLiteral)
|
||||
|| (getChild(1).getType().isIP() && getChild(0) instanceof StringLiteral)
|
||||
|| (getChild(0).getType().isIP() && getChild(1).getType().isIP())) {
|
||||
if (getChild(0).getType().isIPv4() || getChild(1).getType().isIPv4()) {
|
||||
return Type.IPV4;
|
||||
}
|
||||
if (getChild(0).getType().isIPv6() || getChild(1).getType().isIPv6()) {
|
||||
return Type.IPV6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Following logical is compatible with MySQL:
|
||||
// Cast to DOUBLE by default, because DOUBLE has the largest range of values.
|
||||
if (t1 == PrimitiveType.VARCHAR && t2 == PrimitiveType.VARCHAR) {
|
||||
|
||||
@ -0,0 +1,146 @@
|
||||
// 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.
|
||||
|
||||
package org.apache.doris.analysis;
|
||||
|
||||
import org.apache.doris.catalog.Type;
|
||||
import org.apache.doris.common.AnalysisException;
|
||||
import org.apache.doris.thrift.TExprNode;
|
||||
import org.apache.doris.thrift.TExprNodeType;
|
||||
import org.apache.doris.thrift.TIPv4Literal;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class IPv4Literal extends LiteralExpr {
|
||||
private static final Logger LOG = LogManager.getLogger(IPv4Literal.class);
|
||||
|
||||
public static final long IPV4_MIN = 0L; // 0.0.0.0
|
||||
public static final long IPV4_MAX = (2L << 31) - 1; // 255.255.255.255
|
||||
private static final Pattern IPV4_STD_REGEX =
|
||||
Pattern.compile("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
|
||||
|
||||
private long value;
|
||||
|
||||
/**
|
||||
* C'tor forcing type, e.g., due to implicit cast
|
||||
*/
|
||||
// for restore
|
||||
private IPv4Literal() {
|
||||
}
|
||||
|
||||
public IPv4Literal(long value) {
|
||||
super();
|
||||
this.value = value;
|
||||
this.type = Type.IPV4;
|
||||
analysisDone();
|
||||
}
|
||||
|
||||
public IPv4Literal(String value) throws AnalysisException {
|
||||
super();
|
||||
this.value = parseIPv4toLong(value);
|
||||
this.type = Type.IPV4;
|
||||
analysisDone();
|
||||
}
|
||||
|
||||
protected IPv4Literal(IPv4Literal other) {
|
||||
super(other);
|
||||
this.value = other.value;
|
||||
}
|
||||
|
||||
private static long parseIPv4toLong(String ipv4) {
|
||||
String[] parts = ipv4.split("\\.");
|
||||
if (parts.length != 4) {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
long value = 0L;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
short octet;
|
||||
try {
|
||||
octet = Short.parseShort(parts[i]);
|
||||
} catch (NumberFormatException e) {
|
||||
return 0L;
|
||||
}
|
||||
if (octet < 0 || octet > 255) {
|
||||
return 0L;
|
||||
}
|
||||
value = (value << 8) | octet;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static String parseLongToIPv4(long ipv4) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 3; i >= 0; i--) {
|
||||
short octet = (short) ((ipv4 >> (i * 8)) & 0xFF);
|
||||
sb.append(octet);
|
||||
if (i > 0) {
|
||||
sb.append(".");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void checkValueValid(String ipv4) throws AnalysisException {
|
||||
if (ipv4.length() > 15) {
|
||||
throw new AnalysisException("The length of IPv4 must not exceed 15. type: " + Type.IPV4);
|
||||
} else if (!IPV4_STD_REGEX.matcher(ipv4).matches()) {
|
||||
throw new AnalysisException("Invalid IPv4 format: " + ipv4 + ". type: " + Type.IPV4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Expr clone() {
|
||||
return new IPv4Literal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toSqlImpl() {
|
||||
return getStringValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void toThrift(TExprNode msg) {
|
||||
msg.node_type = TExprNodeType.IPV4_LITERAL;
|
||||
msg.ipv4_literal = new TIPv4Literal(this.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMinValue() {
|
||||
return this.value == IPV4_MIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareLiteral(LiteralExpr expr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStringValue() {
|
||||
return parseLongToIPv4(this.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStringValueForArray() {
|
||||
return "\"" + getStringValue() + "\"";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
// 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.
|
||||
|
||||
package org.apache.doris.analysis;
|
||||
|
||||
import org.apache.doris.catalog.Type;
|
||||
import org.apache.doris.common.AnalysisException;
|
||||
import org.apache.doris.thrift.TExprNode;
|
||||
import org.apache.doris.thrift.TExprNodeType;
|
||||
import org.apache.doris.thrift.TIPv6Literal;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class IPv6Literal extends LiteralExpr {
|
||||
private static final Logger LOG = LogManager.getLogger(IPv6Literal.class);
|
||||
|
||||
public static final String IPV6_MIN = "0:0:0:0:0:0:0:0";
|
||||
public static final String IPV6_MAX = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
|
||||
private static final Pattern IPV6_STD_REGEX =
|
||||
Pattern.compile("^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");
|
||||
private static final Pattern IPV6_COMPRESS_REGEX =
|
||||
Pattern.compile("^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4})*)?)::((([0-9A-Fa-f]{1,4}:)*[0-9A-Fa-f]{1,4})?)$");
|
||||
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* C'tor forcing type, e.g., due to implicit cast
|
||||
*/
|
||||
// for restore
|
||||
private IPv6Literal() {
|
||||
}
|
||||
|
||||
public IPv6Literal(String value) throws AnalysisException {
|
||||
super();
|
||||
checkValueValid(value);
|
||||
this.value = value;
|
||||
this.type = Type.IPV6;
|
||||
analysisDone();
|
||||
}
|
||||
|
||||
protected IPv6Literal(IPv6Literal other) {
|
||||
super(other);
|
||||
this.value = other.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkValueValid() throws AnalysisException {
|
||||
checkValueValid(this.value);
|
||||
}
|
||||
|
||||
private void checkValueValid(String ipv6) throws AnalysisException {
|
||||
if (ipv6.length() > 39) {
|
||||
throw new AnalysisException("The length of IPv6 must not exceed 39. type: " + Type.IPV6);
|
||||
} else if (!IPV6_STD_REGEX.matcher(ipv6).matches() && !IPV6_COMPRESS_REGEX.matcher(ipv6).matches()) {
|
||||
throw new AnalysisException("Invalid IPv6 format: " + ipv6 + ". type: " + Type.IPV6);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toSqlImpl() {
|
||||
return getStringValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void toThrift(TExprNode msg) {
|
||||
msg.node_type = TExprNodeType.IPV6_LITERAL;
|
||||
msg.ipv6_literal = new TIPv6Literal(this.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expr clone() {
|
||||
return new IPv6Literal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMinValue() {
|
||||
return IPV6_MIN.equals(this.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareLiteral(LiteralExpr expr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStringValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStringValueForArray() {
|
||||
return "\"" + getStringValue() + "\"";
|
||||
}
|
||||
}
|
||||
@ -94,6 +94,12 @@ public abstract class LiteralExpr extends Expr implements Comparable<LiteralExpr
|
||||
case DATETIMEV2:
|
||||
literalExpr = new DateLiteral(value, type);
|
||||
break;
|
||||
case IPV4:
|
||||
literalExpr = new IPv4Literal(value);
|
||||
break;
|
||||
case IPV6:
|
||||
literalExpr = new IPv6Literal(value);
|
||||
break;
|
||||
default:
|
||||
throw new AnalysisException("Type[" + type.toSql() + "] not supported.");
|
||||
}
|
||||
|
||||
@ -167,6 +167,40 @@ public class StringLiteral extends LiteralExpr {
|
||||
return getStringValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string literal to a IPv4 literal
|
||||
*
|
||||
* @return new converted literal (not null)
|
||||
* @throws AnalysisException when entire given string cannot be transformed into a date
|
||||
*/
|
||||
public LiteralExpr convertToIPv4() throws AnalysisException {
|
||||
LiteralExpr newLiteral;
|
||||
newLiteral = new IPv4Literal(value);
|
||||
try {
|
||||
newLiteral.checkValueValid();
|
||||
} catch (AnalysisException e) {
|
||||
return NullLiteral.create(newLiteral.getType());
|
||||
}
|
||||
return newLiteral;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string literal to a IPv6 literal
|
||||
*
|
||||
* @return new converted literal (not null)
|
||||
* @throws AnalysisException when entire given string cannot be transformed into a date
|
||||
*/
|
||||
public LiteralExpr convertToIPv6() throws AnalysisException {
|
||||
LiteralExpr newLiteral;
|
||||
newLiteral = new IPv6Literal(value);
|
||||
try {
|
||||
newLiteral.checkValueValid();
|
||||
} catch (AnalysisException e) {
|
||||
return NullLiteral.create(newLiteral.getType());
|
||||
}
|
||||
return newLiteral;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string literal to a date literal
|
||||
*
|
||||
@ -266,6 +300,10 @@ public class StringLiteral extends LiteralExpr {
|
||||
} catch (AnalysisException e) {
|
||||
// pass;
|
||||
}
|
||||
} else if (targetType.isIPv4()) {
|
||||
return convertToIPv4();
|
||||
} else if (targetType.isIPv6()) {
|
||||
return convertToIPv6();
|
||||
} else if (targetType.equals(type)) {
|
||||
return this;
|
||||
} else if (targetType.isStringType()) {
|
||||
|
||||
@ -0,0 +1,93 @@
|
||||
// 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.
|
||||
|
||||
package org.apache.doris.nereids.trees.expressions.literal;
|
||||
|
||||
import org.apache.doris.analysis.LiteralExpr;
|
||||
import org.apache.doris.nereids.exceptions.AnalysisException;
|
||||
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
|
||||
import org.apache.doris.nereids.types.IPv4Type;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Represents IPv4 literal
|
||||
*/
|
||||
public class IPv4Literal extends Literal {
|
||||
|
||||
private static final Pattern IPV4_STD_REGEX =
|
||||
Pattern.compile("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
|
||||
|
||||
private long value;
|
||||
|
||||
public IPv4Literal(String ipv4) throws AnalysisException {
|
||||
super(IPv4Type.INSTANCE);
|
||||
init(ipv4);
|
||||
}
|
||||
|
||||
protected IPv4Literal(long value) {
|
||||
super(IPv4Type.INSTANCE);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
|
||||
return visitor.visitIPv4Literal(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralExpr toLegacyLiteral() {
|
||||
return new org.apache.doris.analysis.IPv4Literal(value);
|
||||
}
|
||||
|
||||
void init(String ipv4) throws AnalysisException {
|
||||
checkValueValid(ipv4);
|
||||
|
||||
String[] parts = ipv4.split("\\.");
|
||||
if (parts.length != 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
long value = 0L;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
short octet;
|
||||
try {
|
||||
octet = Short.parseShort(parts[i]);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new AnalysisException("Invalid IPv4 format.");
|
||||
}
|
||||
if (octet < 0 || octet > 255) {
|
||||
throw new AnalysisException("Invalid IPv4 format.");
|
||||
}
|
||||
value = (value << 8) | octet;
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private void checkValueValid(String ipv4) throws AnalysisException {
|
||||
if (ipv4.length() > 15) {
|
||||
throw new AnalysisException("The length of IPv4 must not exceed 15.");
|
||||
} else if (!IPV4_STD_REGEX.matcher(ipv4).matches()) {
|
||||
throw new AnalysisException("Invalid IPv4 format.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
// 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.
|
||||
|
||||
package org.apache.doris.nereids.trees.expressions.literal;
|
||||
|
||||
import org.apache.doris.analysis.LiteralExpr;
|
||||
import org.apache.doris.nereids.exceptions.AnalysisException;
|
||||
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
|
||||
import org.apache.doris.nereids.types.IPv6Type;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Represents IPv6 literal
|
||||
*/
|
||||
public class IPv6Literal extends Literal {
|
||||
|
||||
private static final Pattern IPV6_STD_REGEX =
|
||||
Pattern.compile("^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");
|
||||
private static final Pattern IPV6_COMPRESS_REGEX =
|
||||
Pattern.compile("^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4})*)?)::((([0-9A-Fa-f]{1,4}:)*[0-9A-Fa-f]{1,4})?)$");
|
||||
|
||||
private final String value;
|
||||
|
||||
public IPv6Literal(String ipv6) throws AnalysisException {
|
||||
super(IPv6Type.INSTANCE);
|
||||
checkValueValid(ipv6);
|
||||
this.value = ipv6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
|
||||
return visitor.visitIPv6Literal(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralExpr toLegacyLiteral() {
|
||||
try {
|
||||
return new org.apache.doris.analysis.IPv6Literal(value);
|
||||
} catch (Exception e) {
|
||||
throw new AnalysisException("Invalid IPv6 format.");
|
||||
}
|
||||
}
|
||||
|
||||
public void checkValueValid(String ipv6) throws AnalysisException {
|
||||
if (ipv6.length() > 39) {
|
||||
throw new AnalysisException("The length of IPv6 must not exceed 39.");
|
||||
} else if (!IPV6_STD_REGEX.matcher(ipv6).matches() && !IPV6_COMPRESS_REGEX.matcher(ipv6).matches()) {
|
||||
throw new AnalysisException("Invalid IPv6 format.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -249,6 +249,10 @@ public abstract class Literal extends Expression implements LeafExpression, Comp
|
||||
return new DateTimeV2Literal((DateTimeV2Type) targetType, desc);
|
||||
} else if (targetType.isJsonType()) {
|
||||
return new JsonLiteral(desc);
|
||||
} else if (targetType.isIPv4Type()) {
|
||||
return new IPv4Literal(desc);
|
||||
} else if (targetType.isIPv6Type()) {
|
||||
return new IPv6Literal(desc);
|
||||
}
|
||||
throw new AnalysisException("cannot cast " + desc + " from type " + this.dataType + " to type " + targetType);
|
||||
}
|
||||
@ -296,6 +300,10 @@ public abstract class Literal extends Expression implements LeafExpression, Comp
|
||||
return new DateTimeV2Literal(stringValue);
|
||||
} else if (dataType.isJsonType()) {
|
||||
return new JsonLiteral(stringValue);
|
||||
} else if (dataType.isIPv4Type()) {
|
||||
return new IPv4Literal(stringValue);
|
||||
} else if (dataType.isIPv6Type()) {
|
||||
return new IPv6Literal(stringValue);
|
||||
} else {
|
||||
throw new AnalysisException("Unsupported convert the " + literalExpr.getType()
|
||||
+ " of legacy literal to nereids literal");
|
||||
|
||||
@ -100,6 +100,8 @@ import org.apache.doris.nereids.trees.expressions.literal.DecimalLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.DecimalV3Literal;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.DoubleLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.FloatLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.IPv4Literal;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.IPv6Literal;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.Interval;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.LargeIntLiteral;
|
||||
@ -303,6 +305,14 @@ public abstract class ExpressionVisitor<R, C>
|
||||
return visitLiteral(dateTimeV2Literal, context);
|
||||
}
|
||||
|
||||
public R visitIPv4Literal(IPv4Literal ipv4Literal, C context) {
|
||||
return visitLiteral(ipv4Literal, context);
|
||||
}
|
||||
|
||||
public R visitIPv6Literal(IPv6Literal ipv6Literal, C context) {
|
||||
return visitLiteral(ipv6Literal, context);
|
||||
}
|
||||
|
||||
public R visitArrayLiteral(ArrayLiteral arrayLiteral, C context) {
|
||||
return visitLiteral(arrayLiteral, context);
|
||||
}
|
||||
|
||||
@ -259,6 +259,12 @@ public abstract class DataType {
|
||||
case "jsonb":
|
||||
dataType = JsonType.INSTANCE;
|
||||
break;
|
||||
case "ipv4":
|
||||
dataType = IPv4Type.INSTANCE;
|
||||
break;
|
||||
case "ipv6":
|
||||
dataType = IPv6Type.INSTANCE;
|
||||
break;
|
||||
default:
|
||||
throw new AnalysisException("Nereids do not support type: " + type);
|
||||
}
|
||||
@ -358,6 +364,10 @@ public abstract class DataType {
|
||||
List<DataType> types = catalogType.getSubTypes().stream().map(DataType::fromCatalogType)
|
||||
.collect(Collectors.toList());
|
||||
return new AggStateType(catalogType.getFunctionName(), types, catalogType.getSubTypeNullables());
|
||||
} else if (type.isIPv4()) {
|
||||
return IPv4Type.INSTANCE;
|
||||
} else if (type.isIPv6()) {
|
||||
return IPv6Type.INSTANCE;
|
||||
} else {
|
||||
return UnsupportedType.INSTANCE;
|
||||
}
|
||||
@ -542,6 +552,14 @@ public abstract class DataType {
|
||||
return this instanceof DateTimeV2Type;
|
||||
}
|
||||
|
||||
public boolean isIPv4Type() {
|
||||
return this instanceof IPv4Type;
|
||||
}
|
||||
|
||||
public boolean isIPv6Type() {
|
||||
return this instanceof IPv6Type;
|
||||
}
|
||||
|
||||
public boolean isBitmapType() {
|
||||
return this instanceof BitmapType;
|
||||
}
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
// 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.
|
||||
|
||||
package org.apache.doris.nereids.types;
|
||||
|
||||
import org.apache.doris.catalog.Type;
|
||||
import org.apache.doris.nereids.types.coercion.PrimitiveType;
|
||||
|
||||
/**
|
||||
* IPv4 type in Nereids.
|
||||
*/
|
||||
public class IPv4Type extends PrimitiveType {
|
||||
|
||||
public static final IPv4Type INSTANCE = new IPv4Type();
|
||||
|
||||
public static final int WIDTH = 4;
|
||||
|
||||
private IPv4Type() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type toCatalogDataType() {
|
||||
return Type.IPV4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsType(DataType other) {
|
||||
return other instanceof IPv4Type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String simpleString() {
|
||||
return "ipv4";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType defaultConcreteType() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof IPv4Type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int width() {
|
||||
return WIDTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSql() {
|
||||
return "IPV4";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
// 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.
|
||||
|
||||
package org.apache.doris.nereids.types;
|
||||
|
||||
import org.apache.doris.catalog.Type;
|
||||
import org.apache.doris.nereids.types.coercion.PrimitiveType;
|
||||
|
||||
/**
|
||||
* IPv6 type in Nereids.
|
||||
*/
|
||||
public class IPv6Type extends PrimitiveType {
|
||||
|
||||
public static final IPv6Type INSTANCE = new IPv6Type();
|
||||
|
||||
public static final int WIDTH = 16;
|
||||
|
||||
private IPv6Type() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type toCatalogDataType() {
|
||||
return Type.IPV6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsType(DataType other) {
|
||||
return other instanceof IPv6Type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String simpleString() {
|
||||
return "ipv6";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType defaultConcreteType() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof IPv6Type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int width() {
|
||||
return WIDTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSql() {
|
||||
return "IPV6";
|
||||
}
|
||||
}
|
||||
@ -82,6 +82,8 @@ import org.apache.doris.nereids.types.DecimalV2Type;
|
||||
import org.apache.doris.nereids.types.DecimalV3Type;
|
||||
import org.apache.doris.nereids.types.DoubleType;
|
||||
import org.apache.doris.nereids.types.FloatType;
|
||||
import org.apache.doris.nereids.types.IPv4Type;
|
||||
import org.apache.doris.nereids.types.IPv6Type;
|
||||
import org.apache.doris.nereids.types.IntegerType;
|
||||
import org.apache.doris.nereids.types.JsonType;
|
||||
import org.apache.doris.nereids.types.LargeIntType;
|
||||
@ -227,6 +229,8 @@ public class TypeCoercionUtils {
|
||||
} else if (expected instanceof NumericType) {
|
||||
// For any other numeric types, implicitly cast to each other, e.g. bigint -> int, int -> bigint
|
||||
returnType = expected.defaultConcreteType();
|
||||
} else if (expected instanceof IPv4Type) {
|
||||
returnType = IPv4Type.INSTANCE;
|
||||
}
|
||||
} else if (input instanceof CharacterType) {
|
||||
if (expected instanceof DecimalV2Type) {
|
||||
@ -239,6 +243,10 @@ public class TypeCoercionUtils {
|
||||
returnType = DateTimeType.INSTANCE;
|
||||
} else if (expected instanceof JsonType) {
|
||||
returnType = JsonType.INSTANCE;
|
||||
} else if (expected instanceof IPv4Type) {
|
||||
returnType = IPv4Type.INSTANCE;
|
||||
} else if (expected instanceof IPv6Type) {
|
||||
returnType = IPv6Type.INSTANCE;
|
||||
}
|
||||
} else if (input.isDateType()) {
|
||||
if (expected instanceof DateTimeType) {
|
||||
@ -1205,6 +1213,16 @@ public class TypeCoercionUtils {
|
||||
return Optional.of(commonType);
|
||||
}
|
||||
|
||||
// ip type
|
||||
if ((leftType.isIPv4Type() && rightType.isStringLikeType())
|
||||
|| (rightType.isIPv4Type() && leftType.isStringLikeType())) {
|
||||
return Optional.of(IPv4Type.INSTANCE);
|
||||
}
|
||||
if ((leftType.isIPv6Type() && rightType.isStringLikeType())
|
||||
|| (rightType.isIPv6Type() && leftType.isStringLikeType())) {
|
||||
return Optional.of(IPv6Type.INSTANCE);
|
||||
}
|
||||
|
||||
return Optional.of(DoubleType.INSTANCE);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user