SqlPosixRegexOperator.java
/*
* 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.calcite.sql.fun;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.sql.SqlBinaryOperator;
import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlCallBinding;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlOperandCountRange;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlWriter;
import org.apache.calcite.sql.type.InferTypes;
import org.apache.calcite.sql.type.OperandTypes;
import org.apache.calcite.sql.type.ReturnTypes;
import org.apache.calcite.sql.type.SqlOperandCountRanges;
import org.apache.calcite.sql.type.SqlTypeUtil;
/**
* An operator describing the <code>~</code> operator.
*
* <p> Syntax: <code>src-value [!] ~ [*] pattern-value</code>
*/
public class SqlPosixRegexOperator extends SqlBinaryOperator {
// ~ Instance fields --------------------------------------------------------
private final boolean caseSensitive;
private final boolean negated;
private final String operatorString;
// ~ Constructors -----------------------------------------------------------
/**
* Creates a SqlPosixRegexOperator.
*
* @param name Operator name
* @param kind Kind
* @param negated Whether this is '!~' or '!~*'
*/
SqlPosixRegexOperator(
String name,
SqlKind kind,
boolean caseSensitive,
boolean negated) {
super(
name,
kind,
32,
true,
ReturnTypes.BOOLEAN_NULLABLE,
InferTypes.FIRST_KNOWN,
OperandTypes.STRING_SAME_SAME_SAME);
this.caseSensitive = caseSensitive;
this.negated = negated;
final StringBuilder sb = new StringBuilder(3);
if (this.negated) {
sb.append("!");
}
sb.append("~");
if (!this.caseSensitive) {
sb.append("*");
}
this.operatorString = sb.toString();
}
// ~ Methods ----------------------------------------------------------------
@Override public SqlOperator not() {
return of(!negated, caseSensitive);
}
private static SqlOperator of(boolean negated, boolean ignoreCase) {
if (ignoreCase) {
return negated
? SqlStdOperatorTable.NEGATED_POSIX_REGEX_CASE_SENSITIVE
: SqlStdOperatorTable.POSIX_REGEX_CASE_SENSITIVE;
} else {
return negated
? SqlStdOperatorTable.NEGATED_POSIX_REGEX_CASE_INSENSITIVE
: SqlStdOperatorTable.POSIX_REGEX_CASE_INSENSITIVE;
}
}
@Override public SqlOperandCountRange getOperandCountRange() {
return SqlOperandCountRanges.of(2);
}
@Override public boolean checkOperandTypes(
SqlCallBinding callBinding,
boolean throwOnFailure) {
int operandCount = callBinding.getOperandCount();
if (operandCount != 2) {
throw new AssertionError(
"Unexpected number of args to " + callBinding.getCall() + ": " + operandCount);
}
RelDataType op1Type = callBinding.getOperandType(0);
RelDataType op2Type = callBinding.getOperandType(1);
if (!SqlTypeUtil.isComparable(op1Type, op2Type)) {
throw new AssertionError(
"Incompatible first two operand types " + op1Type + " and " + op2Type);
}
return SqlTypeUtil.isCharTypeComparable(
callBinding,
callBinding.operands().subList(0, 2),
throwOnFailure);
}
@Override public void unparse(
SqlWriter writer,
SqlCall call,
int leftPrec,
int rightPrec) {
final SqlWriter.Frame frame = writer.startList("", "");
call.operand(0).unparse(writer, getLeftPrec(), getRightPrec());
writer.print(this.operatorString);
writer.print(" ");
call.operand(1).unparse(writer, getLeftPrec(), getRightPrec());
writer.endList(frame);
}
/**
* Returns whether this operator matches the case of its operands.
*
* @return whether this operator matches the case of its operands
*/
public boolean isCaseSensitive() {
return caseSensitive;
}
/**
* Returns whether this is 'NOT' variant of an operator.
*
* @see #not()
*/
public boolean isNegated() {
return negated;
}
}