blob: bb2af97586734632ca62e816fbdb22d29d1e34f2 [file] [log] [blame]
/**
* 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.
**/
#ifndef QUICKSTEP_TYPES_OPERATIONS_COMPARISONS_PATTERN_MATCHING_COMPARATORS_HPP_
#define QUICKSTEP_TYPES_OPERATIONS_COMPARISONS_PATTERN_MATCHING_COMPARATORS_HPP_
#include <cstddef>
#include <string>
#include "catalog/CatalogTypedefs.hpp"
#include "types/TypedValue.hpp"
#include "types/operations/comparisons/Comparison.hpp"
#include "types/port/strnlen.hpp"
#include "re2/stringpiece.h"
#include "re2/re2.h"
namespace quickstep {
class ColumnVector;
class TupleIdSequence;
class ValueAccessor;
/** \addtogroup Types
* @{
*/
/**
* @brief Base class for UncheckedComparators which does pattern matching.
**/
template <bool is_like_pattern, bool is_negation,
bool left_nullable, bool right_nullable>
class PatternMatchingUncheckedComparator : public UncheckedComparator {
public:
/**
* @brief Constructor.
**/
PatternMatchingUncheckedComparator(const std::size_t left_length,
const std::size_t right_length)
: left_length_(left_length),
right_length_(right_length) {
}
inline bool compareDataPtrs(const void *left,
const void *right) const override {
return compareDataPtrsInl(left, right);
}
inline bool compareDataPtrsInl(const void *left,
const void *right) const {
if ((left_nullable && (left == nullptr))
|| (right_nullable && (right == nullptr))) {
return false;
}
const char* text = static_cast<const char*>(left);
const re2::StringPiece text_piece(text, strnlen(text, left_length_));
const char* pattern = static_cast<const char*>(right);
std::string regex_pattern;
re2::StringPiece pattern_piece;
int orig_pattern_len = strnlen(pattern, right_length_);
if (is_like_pattern) {
regex_pattern = transformLikeToRegex(pattern, orig_pattern_len);
pattern_piece.set(regex_pattern.c_str(), regex_pattern.size());
} else {
pattern_piece.set(pattern, orig_pattern_len);
}
const re2::RE2 re2_pattern(pattern_piece);
return match(text_piece, re2_pattern);
}
inline bool compareTypedValues(const TypedValue &left,
const TypedValue &right) const override {
return compareDataPtrsInl(left.getOutOfLineData(), right.getOutOfLineData());
}
inline bool compareTypedValueWithDataPtr(const TypedValue &left,
const void *right) const override {
return compareDataPtrsInl(left.getOutOfLineData(), right);
}
inline bool compareDataPtrWithTypedValue(const void *left,
const TypedValue &right) const override {
return compareDataPtrsInl(left, right.getOutOfLineData());
}
TupleIdSequence* compareColumnVectors(
const ColumnVector &left,
const ColumnVector &right,
const TupleIdSequence *filter,
const TupleIdSequence *existence_bitmap) const override;
TupleIdSequence* compareColumnVectorAndStaticValue(
const ColumnVector &left,
const TypedValue &right,
const TupleIdSequence *filter,
const TupleIdSequence *existence_bitmap) const override;
TupleIdSequence* compareStaticValueAndColumnVector(
const TypedValue &left,
const ColumnVector &right,
const TupleIdSequence *filter,
const TupleIdSequence *existence_bitmap) const override;
#ifdef QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION
TupleIdSequence* compareSingleValueAccessor(
ValueAccessor *accessor,
const attribute_id left_id,
const attribute_id right_id,
const TupleIdSequence *filter) const override;
TupleIdSequence* compareValueAccessorAndStaticValue(
ValueAccessor *left_accessor,
const attribute_id left_id,
const TypedValue &right,
const TupleIdSequence *filter) const override;
TupleIdSequence* compareStaticValueAndValueAccessor(
const TypedValue &left,
ValueAccessor *right_accessor,
const attribute_id right_id,
const TupleIdSequence *filter) const override;
TupleIdSequence* compareColumnVectorAndValueAccessor(
const ColumnVector &left,
ValueAccessor *right_accessor,
const attribute_id right_id,
const TupleIdSequence *filter,
const TupleIdSequence *existence_bitmap) const override;
TupleIdSequence* compareValueAccessorAndColumnVector(
ValueAccessor *left_accessor,
const attribute_id left_id,
const ColumnVector &right,
const TupleIdSequence *filter,
const TupleIdSequence *existence_bitmap) const override;
TypedValue accumulateValueAccessor(
const TypedValue &current,
ValueAccessor *accessor,
const attribute_id value_accessor_id) const override;
#endif // QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION
TypedValue accumulateColumnVector(
const TypedValue &current,
const ColumnVector &column_vector) const override;
private:
/**
* @brief Checks whether the raw text matches pattern.
*
* @param text The raw text to be checked, must be not null.
* @param pattern The pattern to be matched against.
*
* @return Whether text matches pattern.
**/
inline bool matchDataPtrWithPattern(const void *text,
const re2::RE2 &pattern) const {
const char* c_text = static_cast<const char*>(text);
const re2::StringPiece text_piece(c_text, strnlen(c_text, left_length_));
return match(text_piece, pattern);
}
/**
* @brief Checks whether text matches pattern.
*
* @param text The text to be checked.
* @param pattern The pattern to be matched against.
*
* @return Whether text matches pattern.
**/
inline bool match(const re2::StringPiece &text,
const re2::RE2 &pattern) const {
if (is_negation) {
return !(re2::RE2::FullMatch(text, pattern));
} else {
return re2::RE2::FullMatch(text, pattern);
}
}
/**
* @brief Tranform a LIKE pattern to the corresponding regular expression
* pattern.
*
* @param like_pattern The original LIKE pattern.
* @param len The length of the LIKE pattern.
*
* @return The transformed regular expression pattern.
*/
inline std::string transformLikeToRegex(const char *like_pattern,
const std::size_t len) const {
std::string regex_pattern;
for (std::size_t i = 0; i < len; i++) {
char c = like_pattern[i];
switch (c) {
case '_':
regex_pattern.append("(.|\n)");
break;
case '%':
regex_pattern.append("(.|\n)*");
break;
default:
// Escape special characters
if ((c < 'a' || c > 'z')
&& (c < 'A' || c > 'Z')
&& (c < '0' || c > '9')
&& !(c & 128)) {
regex_pattern.push_back('\\');
}
regex_pattern.push_back(c);
break;
}
}
return regex_pattern;
}
const std::size_t left_length_;
const std::size_t right_length_;
};
/** @} */
} // namespace quickstep
#endif // QUICKSTEP_TYPES_OPERATIONS_COMPARISONS_PATTERN_MATCHING_COMPARATORS_HPP_