Optimize PackedRowStoreValueAccessor & BasicColumnStoreValueAccessor by 
removing redundant computations and clearly exposing a strided memory access 
pattern


Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/743f6b0a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/743f6b0a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/743f6b0a

Branch: refs/heads/lip-refactor
Commit: 743f6b0acc769a0f2eedb0daf8ed6f535dc1c4b0
Parents: 80af233
Author: Saket Saurabh <ssaur...@cs.wisc.edu>
Authored: Wed Sep 21 03:17:19 2016 -0500
Committer: Saket Saurabh <ssaur...@cs.wisc.edu>
Committed: Tue Oct 11 11:36:57 2016 -0500

----------------------------------------------------------------------
 .gitignore                                      |   1 +
 storage/BasicColumnStoreValueAccessor.hpp       |  55 +++++++
 storage/CompressedColumnStoreValueAccessor.hpp  |  33 +++++
 .../CompressedPackedRowStoreValueAccessor.hpp   |  33 +++++
 storage/PackedRowStoreValueAccessor.hpp         |  54 +++++++
 storage/SplitRowStoreValueAccessor.hpp          |  18 +++
 storage/ValueAccessor.hpp                       | 143 +++++++++++++++++++
 types/containers/ColumnVectorsValueAccessor.hpp |  18 +++
 .../comparisons/AsciiStringComparators-inl.hpp  | 101 ++++++++++---
 types/operations/comparisons/Comparison-inl.hpp |  27 +++-
 .../comparisons/LiteralComparators-inl.hpp      | 129 +++++++++++++----
 .../PatternMatchingComparators-inl.hpp          |  24 +++-
 12 files changed, 574 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 37a361f..5dea02f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,5 @@
 Makefile.in
 autom4te.cache
 .DS_Store
+.idea
 *~

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/storage/BasicColumnStoreValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/BasicColumnStoreValueAccessor.hpp 
b/storage/BasicColumnStoreValueAccessor.hpp
index 0560d99..22d3c0b 100644
--- a/storage/BasicColumnStoreValueAccessor.hpp
+++ b/storage/BasicColumnStoreValueAccessor.hpp
@@ -52,6 +52,61 @@ class BasicColumnStoreValueAccessorHelper {
     return num_tuples_;
   }
 
+  /**
+   * @brief Returns whether this accessor has a fast strided ColumnAccessor 
available
+   *        that can be used to optimize memory access in a tight loop 
iteration
+   *        over the underlying storage block.
+   *
+   * @return true if fast ColumnAccessor is supported, otherwise false.
+   */
+  inline bool isColumnAccessorSupported() const {
+    return true;
+  }
+
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast 
strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() 
method
+   *          returned true. If ColumnAccessor is not supported this method 
will return a nullptr.
+   *
+   * @param current_tuple_position A constant reference to the tuple position 
in the containing
+   *        ValueAccessor. This reference value is shared between the 
containing ValueAccessor &
+   *        a ColumnAccessor. However, a ColumnAccessor *CANNOT* modify this 
tuple position.
+   * @param attr_id The attribute id on which this ColumnAccessor will be 
created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set 
that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const tuple_id 
&current_tuple_position,
+                                                             const 
attribute_id attr_id) const {
+    DEBUG_ASSERT(relation_.hasAttributeWithId(attr_id));
+    const void* base_location = static_cast<const 
char*>(column_stripes_[attr_id]);
+    const std::size_t stride = 
relation_.getAttributeById(attr_id)->getType().maximumByteLength();
+    std::unique_ptr<ColumnAccessor<check_null>> column_accessor;
+    if (check_null) {
+      // The nullable_base might get initialized to -1 if column_null_bitmaps 
returns false for
+      // the given attribute. Setting the nullable_base to -1 will mean that
+      // column accessor will always evaluate null check to false.
+      const int nullable_base = (!column_null_bitmaps_.elementIsNull(attr_id)) 
? 0 : -1;
+      const unsigned nullable_stride = 1;
+      column_accessor.reset(new 
ColumnAccessor<check_null>(current_tuple_position,
+                                                           num_tuples_,
+                                                           base_location,
+                                                           stride,
+                                                           
&(column_null_bitmaps_[attr_id]),
+                                                           nullable_base,
+                                                           nullable_stride));
+    } else {
+      column_accessor.reset(new 
ColumnAccessor<check_null>(current_tuple_position,
+                                                           num_tuples_,
+                                                           base_location,
+                                                           stride));
+    }
+    return column_accessor.release();
+  }
+
   template <bool check_null>
   inline const void* getAttributeValue(const tuple_id tuple,
                                        const attribute_id attr) const {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/storage/CompressedColumnStoreValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/CompressedColumnStoreValueAccessor.hpp 
b/storage/CompressedColumnStoreValueAccessor.hpp
index 25e5eed..366d4c6 100644
--- a/storage/CompressedColumnStoreValueAccessor.hpp
+++ b/storage/CompressedColumnStoreValueAccessor.hpp
@@ -67,6 +67,39 @@ class CompressedColumnStoreValueAccessorHelper {
     return num_tuples_;
   }
 
+  /**
+   * @brief Returns whether this accessor has a fast strided ColumnAccessor 
available
+   *        that can be used to optimize memory access in a tight loop 
iteration
+   *        over the underlying storage block.
+   *
+   * @return true if fast ColumnAccessor is supported, otherwise false.
+   */
+  inline bool isColumnAccessorSupported() const {
+    return false;
+  }
+
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast 
strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() 
method
+   *          returned true. If ColumnAccessor is not supported this method 
will return a nullptr.
+   *
+   * @param current_tuple_position A constant reference to the tuple position 
in the containing
+   *        ValueAccessor. This reference value is shared between the 
containing ValueAccessor &
+   *        a ColumnAccessor. However, a ColumnAccessor *CANNOT* modify this 
tuple position.
+   * @param attr_id The attribute id on which this ColumnAccessor will be 
created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set 
that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const tuple_id 
&current_tuple_position,
+                                                             const 
attribute_id attr_id) const {
+    // Return nullptr because this value accessor does not support column 
accessor yet.
+    return nullptr;
+  }
+
   template <bool check_null>
   inline const void* getAttributeValue(const tuple_id tuple,
                                        const attribute_id attr) const {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/storage/CompressedPackedRowStoreValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/CompressedPackedRowStoreValueAccessor.hpp 
b/storage/CompressedPackedRowStoreValueAccessor.hpp
index 8858175..aeff2e1 100644
--- a/storage/CompressedPackedRowStoreValueAccessor.hpp
+++ b/storage/CompressedPackedRowStoreValueAccessor.hpp
@@ -75,6 +75,39 @@ class CompressedPackedRowStoreValueAccessorHelper {
     return num_tuples_;
   }
 
+  /**
+   * @brief Returns whether this accessor has a fast strided ColumnAccessor 
available
+   *        that can be used to optimize memory access in a tight loop 
iteration
+   *        over the underlying storage block.
+   *
+   * @return true if fast ColumnAccessor is supported, otherwise false.
+   */
+  inline bool isColumnAccessorSupported() const {
+    return false;
+  }
+
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast 
strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() 
method
+   *          returned true. If ColumnAccessor is not supported this method 
will return a nullptr.
+   *
+   * @param current_tuple_position A constant reference to the tuple position 
in the containing
+   *        ValueAccessor. This reference value is shared between the 
containing ValueAccessor &
+   *        a ColumnAccessor. However, a ColumnAccessor *CANNOT* modify this 
tuple position.
+   * @param attr_id The attribute id on which this ColumnAccessor will be 
created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set 
that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const tuple_id 
&current_tuple_position,
+                                                             const 
attribute_id attr_id) const {
+    // Return nullptr because this value accessor does not support column 
accessor yet.
+    return nullptr;
+  }
+
   template <bool check_null>
   inline const void* getAttributeValue(const tuple_id tuple,
                                        const attribute_id attr) const {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/storage/PackedRowStoreValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/PackedRowStoreValueAccessor.hpp 
b/storage/PackedRowStoreValueAccessor.hpp
index 80edecd..7eb2d41 100644
--- a/storage/PackedRowStoreValueAccessor.hpp
+++ b/storage/PackedRowStoreValueAccessor.hpp
@@ -49,6 +49,60 @@ class PackedRowStoreValueAccessorHelper {
     return num_tuples_;
   }
 
+  /**
+   * @brief Returns whether this accessor has a fast strided ColumnAccessor 
available
+   *        that can be used to optimize memory access in a tight loop 
iteration
+   *        over the underlying storage block.
+   *
+   * @return true if fast ColumnAccessor is supported, otherwise false.
+   */
+  inline bool isColumnAccessorSupported() const {
+    return true;
+  }
+
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast 
strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() 
method
+   *          returned true. If ColumnAccessor is not supported this method 
will return a nullptr.
+   *
+   * @param current_tuple_position A constant reference to the tuple position 
in the containing
+   *        ValueAccessor. This reference value is shared between the 
containing ValueAccessor &
+   *        a ColumnAccessor. However, a ColumnAccessor *CANNOT* modify this 
tuple position.
+   * @param attr_id The attribute id on which this ColumnAccessor will be 
created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set 
that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const tuple_id 
&current_tuple_position,
+                                                             const 
attribute_id attr_id) const {
+    DEBUG_ASSERT(relation_.hasAttributeWithId(attr_id));
+    const void* base_location = static_cast<const char*>(tuple_storage_)
+        + relation_.getFixedLengthAttributeOffset(attr_id);
+    const std::size_t stride = relation_.getFixedByteLength();
+
+    std::unique_ptr<ColumnAccessor<check_null>> column_accessor;
+    if (check_null) {
+      const int nullable_base = relation_.getNullableAttributeIndex(attr_id);
+      const unsigned nullable_stride = relation_.numNullableAttributes();
+      column_accessor.reset(new 
ColumnAccessor<check_null>(current_tuple_position,
+                                                           num_tuples_,
+                                                           base_location,
+                                                           stride,
+                                                           null_bitmap_,
+                                                           nullable_base,
+                                                           nullable_stride));
+    } else {
+      column_accessor.reset(new 
ColumnAccessor<check_null>(current_tuple_position,
+                                                           num_tuples_,
+                                                           base_location,
+                                                           stride));
+    }
+    return column_accessor.release();
+  }
+
   template <bool check_null>
   inline const void* getAttributeValue(const tuple_id tuple,
                                        const attribute_id attr) const {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/storage/SplitRowStoreValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/SplitRowStoreValueAccessor.hpp 
b/storage/SplitRowStoreValueAccessor.hpp
index 61bb7bf..951a20a 100644
--- a/storage/SplitRowStoreValueAccessor.hpp
+++ b/storage/SplitRowStoreValueAccessor.hpp
@@ -97,6 +97,24 @@ class SplitRowStoreValueAccessor : public ValueAccessor {
     return num_tuples_;
   }
 
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast 
strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() 
method
+   *          returned true. If ColumnAccessor is not supported this method 
will return a nullptr.
+   *
+   * @param attr_id The attribute id on which this ColumnAccessor will be 
created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set 
that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const 
attribute_id attr_id) const {
+    // Column Accessors are currently unsupported for this value accessor, 
hence nullptr.
+    return nullptr;
+  }
+
   template <bool check_null = true>
   inline const void* getUntypedValue(const attribute_id attr_id) const {
     return getUntypedValueAtAbsolutePosition<check_null>(attr_id, 
current_position_);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/storage/ValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/ValueAccessor.hpp b/storage/ValueAccessor.hpp
index 70d4405..3b58a7c 100644
--- a/storage/ValueAccessor.hpp
+++ b/storage/ValueAccessor.hpp
@@ -41,6 +41,9 @@ namespace quickstep {
 
 class TupleStorageSubBlock;
 
+template <bool check_null = true>
+class ColumnAccessor;
+
 // TODO(chasseur): Iteration on ValueAccessors is row-at-a-time, but in some
 // cases column-wise data movement may be more efficient.
 
@@ -182,6 +185,18 @@ class ValueAccessor {
   virtual tuple_id getNumTuplesVirtual() const = 0;
 
   /**
+   * @brief Returns whether this accessor has a fast strided ColumnAccessor 
available
+   *        that can be used to optimize memory access in a tight loop 
iteration
+   *        over the underlying storage block. Specific derived classes should 
override
+   *        this method if they support ColumnAccessor.
+   *
+   * @return true if fast ColumnAccessor is supported, otherwise false.
+   */
+  virtual inline bool isColumnAccessorSupported() const {
+    return false;
+  }
+
+  /**
    * @brief Get a pointer to an untyped value for the current tuple in stateful
    *        iteration.
    * @note The inline version of this method provided by subclasses,
@@ -372,6 +387,24 @@ class TupleIdSequenceAdapterValueAccessor : public 
ValueAccessor {
     return id_sequence_.numTuples();
   }
 
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast 
strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() 
method
+   *          returned true. If ColumnAccessor is not supported this method 
will return a nullptr.
+   *
+   * @param attr_id The attribute id on which this ColumnAccessor will be 
created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set 
that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const 
attribute_id attr_id) const {
+    // Column Accessors are currently unsupported for this accessor, hence 
nullptr.
+    return nullptr;
+  }
+
   template <bool check_null = true>
   inline const void* getUntypedValue(const attribute_id attr_id) const {
     return accessor_->template 
getUntypedValueAtAbsolutePosition<check_null>(attr_id, *current_position_);
@@ -556,6 +589,24 @@ class OrderedTupleIdSequenceAdapterValueAccessor : public 
ValueAccessor {
     return id_sequence_.size();
   }
 
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast 
strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() 
method
+   *          returned true. If ColumnAccessor is not supported this method 
will return a nullptr.
+   *
+   * @param attr_id The attribute id on which this ColumnAccessor will be 
created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set 
that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const 
attribute_id attr_id) const {
+    // Column Accessors are currently unsupported for this accessor, hence 
nullptr.
+    return nullptr;
+  }
+
   template <bool check_null = true>
   inline const void* getUntypedValue(const attribute_id attr_id) const {
     return accessor_->template 
getUntypedValueAtAbsolutePosition<check_null>(attr_id,
@@ -743,6 +794,27 @@ class PackedTupleStorageSubBlockValueAccessor : public 
ValueAccessor {
     return getTypedValueAtAbsolutePosition(attr_id, current_tuple_);
   }
 
+  inline bool isColumnAccessorSupported() const override {
+    return helper_.isColumnAccessorSupported();
+  }
+
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast 
strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() 
method
+   *          returned true. If ColumnAccessor is not supported this method 
will return a nullptr.
+   *
+   * @param attr_id The attribute id on which this ColumnAccessor will be 
created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set 
that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const 
attribute_id attr_id) const {
+    return helper_.template getColumnAccessor<check_null>(current_tuple_, 
attr_id);
+  }
+
   template <bool check_null = true>
   inline const void* getUntypedValueAtAbsolutePosition(const attribute_id 
attr_id,
                                                        const tuple_id tid) 
const {
@@ -896,6 +968,77 @@ class PackedTupleStorageSubBlockValueAccessor : public 
ValueAccessor {
   DISALLOW_COPY_AND_ASSIGN(PackedTupleStorageSubBlockValueAccessor);
 };
 
+
+/**
+ * @brief ColumnAccessor is a helper template class that is used to optimize 
memory
+ *        access patterns for a ValueAccessor when it is used in a tight loop
+ *        to extract values for a given attribute from a given storage block.
+ **/
+template <bool check_null>
+class ColumnAccessor {
+ public:
+  /**
+   * @brief Constructor.
+   *
+   * @param current_tuple_position A constant reference to the tuple position 
in the containing
+   *        ValueAccessor. This reference value is shared between the 
containing ValueAccessor &
+   *        a ColumnAccessor. However, a ColumnAccessor *CANNOT* modify this 
tuple position.
+   * @param num_tuples Number of tuples for this block.
+   * @param base_address The starting address in memory for the first column 
value.
+   * @param stride The memory offset at which other column values will be 
found.
+   * @param null_bitmap The bitmap that will be referred in case of nullable 
attributes.
+   * @param nullable_base The starting index for the first nullable attribute 
in the bitmap.
+   *        Note that setting this value to -1 will essentially cause null 
checks to always
+   *        return false.
+   * @param nullable_stride The offset at which null bits will be found for
+   *        different attribute values.
+   **/
+  ColumnAccessor(const tuple_id &current_tuple_position,
+                 const std::size_t num_tuples,
+                 const void *base_address,
+                 const std::size_t stride,
+                 const BitVector<false> *null_bitmap = nullptr,
+                 const int nullable_base = -1,
+                 const unsigned nullable_stride = 0)
+      : current_tuple_position_(current_tuple_position),
+        num_tuples_(num_tuples),
+        base_address_(base_address),
+        stride_(stride),
+        null_bitmap_(null_bitmap),
+        nullable_base_(nullable_base),
+        nullable_stride_(nullable_stride) {
+  }
+
+  /**
+   * @brief Get a pointer to an untyped value for the current tuple in stateful
+   *        iteration over the given column.
+   *
+   * @return An untyped pointer to the attribute value for the current tuple.
+   **/
+  inline const void* getUntypedValue() const {
+    DEBUG_ASSERT(current_tuple_position_ < num_tuples_);
+    if (check_null) {
+      DEBUG_ASSERT(null_bitmap_ != nullptr);
+      if ((nullable_base_ != -1)
+          && null_bitmap_->getBit(current_tuple_position_ * nullable_stride_ + 
nullable_base_)) {
+        return nullptr;
+      }
+    }
+    return static_cast<const char*>(base_address_) + current_tuple_position_ * 
stride_;
+  }
+
+ private:
+  const tuple_id &current_tuple_position_;
+  const tuple_id num_tuples_;
+  const void *base_address_;
+  const std::size_t stride_;
+  const BitVector<false> *null_bitmap_;
+  const int nullable_base_;
+  const unsigned nullable_stride_;
+
+  DISALLOW_COPY_AND_ASSIGN(ColumnAccessor);
+};
+
 /** @} */
 
 }  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/types/containers/ColumnVectorsValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/types/containers/ColumnVectorsValueAccessor.hpp 
b/types/containers/ColumnVectorsValueAccessor.hpp
index 2300f3b..fe413a0 100644
--- a/types/containers/ColumnVectorsValueAccessor.hpp
+++ b/types/containers/ColumnVectorsValueAccessor.hpp
@@ -121,6 +121,24 @@ class ColumnVectorsValueAccessor : public ValueAccessor {
     return column_length_;
   }
 
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast 
strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() 
method
+   *          returned true. If ColumnAccessor is not supported this method 
will return a nullptr.
+   *
+   * @param attr_id The attribute id on which this ColumnAccessor will be 
created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set 
that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const 
attribute_id attr_id) const {
+    // Column Accessors are currently unsupported for this value accessor, 
hence nullptr.
+    return nullptr;
+  }
+
   template <bool check_null = true>
   inline const void* getUntypedValue(const attribute_id attr_id) const {
     return getUntypedValueAtAbsolutePosition<check_null>(attr_id, 
current_position_);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/types/operations/comparisons/AsciiStringComparators-inl.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/AsciiStringComparators-inl.hpp 
b/types/operations/comparisons/AsciiStringComparators-inl.hpp
index cde03c3..b048c60 100644
--- a/types/operations/comparisons/AsciiStringComparators-inl.hpp
+++ b/types/operations/comparisons/AsciiStringComparators-inl.hpp
@@ -273,13 +273,32 @@ TupleIdSequence* 
AsciiStringUncheckedComparator<ComparisonFunctor,
       }
     } else {
       accessor->beginIteration();
-      while (accessor->next()) {
-        const void *left_value = accessor->template 
getUntypedValue<left_nullable>(left_id);
-        const void *right_value = accessor->template 
getUntypedValue<right_nullable>(right_id);
-        result->set(accessor->getCurrentPosition(),
-                    (!(left_nullable && (left_value == nullptr))
-                        || (right_nullable && (right_value == nullptr)))
-                            && this->compareDataPtrsHelper<true>(left_value, 
right_value));
+      if (accessor->isColumnAccessorSupported()) {
+        // If ColumnAccessor is supported on the underlying accessor, we have 
a fast strided
+        // column accessor available for the iteration on the underlying block.
+        std::unique_ptr<const ColumnAccessor<left_nullable>>
+            left_column_accessor(accessor->template 
getColumnAccessor<left_nullable>(left_id));
+        std::unique_ptr<const ColumnAccessor<right_nullable>>
+            right_column_accessor(accessor->template 
getColumnAccessor<right_nullable>(right_id));
+        DEBUG_ASSERT(left_column_accessor != nullptr);
+        DEBUG_ASSERT(right_column_accessor != nullptr);
+        while (accessor->next()) {
+          const void *left_value = left_column_accessor->getUntypedValue();
+          const void *right_value = right_column_accessor->getUntypedValue();
+          result->set(accessor->getCurrentPosition(),
+                      (!(left_nullable && (left_value == nullptr))
+                          || (right_nullable && (right_value == nullptr)))
+                          && this->compareDataPtrsHelper<true>(left_value, 
right_value));
+        }
+      } else {
+        while (accessor->next()) {
+          const void *left_value = accessor->template 
getUntypedValue<left_nullable>(left_id);
+          const void *right_value = accessor->template 
getUntypedValue<right_nullable>(right_id);
+          result->set(accessor->getCurrentPosition(),
+                      (!(left_nullable && (left_value == nullptr))
+                          || (right_nullable && (right_value == nullptr)))
+                          && this->compareDataPtrsHelper<true>(left_value, 
right_value));
+        }
       }
       if (!short_circuit && (filter != nullptr)) {
         result->intersectWith(*filter);
@@ -333,12 +352,28 @@ TupleIdSequence* 
AsciiStringUncheckedComparator<ComparisonFunctor,
       }
     } else {
       accessor->beginIteration();
-      while (accessor->next()) {
-        const void *va_value
-            = accessor->template 
getUntypedValue<va_nullable>(value_accessor_attr_id);
-        result->set(accessor->getCurrentPosition(),
-                    !(va_nullable && (va_value == nullptr))
-                        && 
this->compareDataPtrsHelper<value_accessor_on_left>(va_value, static_string));
+      if (accessor->isColumnAccessorSupported()) {
+        // If ColumnAccessor is supported on the underlying accessor, we have 
a fast strided
+        // column accessor available for the iteration on the underlying block.
+        std::unique_ptr<const ColumnAccessor<va_nullable>>
+            column_accessor(accessor->template 
getColumnAccessor<va_nullable>(value_accessor_attr_id));
+        DEBUG_ASSERT(column_accessor != nullptr);
+        while (accessor->next()) {
+          const void *va_value = column_accessor->getUntypedValue();
+          result->set(accessor->getCurrentPosition(),
+                      !(va_nullable && (va_value == nullptr))
+                          && 
this->compareDataPtrsHelper<value_accessor_on_left>(va_value,
+                                                                               
  static_string));
+        }
+      } else {
+        while (accessor->next()) {
+          const void *va_value
+              = accessor->template 
getUntypedValue<va_nullable>(value_accessor_attr_id);
+          result->set(accessor->getCurrentPosition(),
+                      !(va_nullable && (va_value == nullptr))
+                          && 
this->compareDataPtrsHelper<value_accessor_on_left>(va_value,
+                                                                               
  static_string));
+        }
       }
       if (!short_circuit && (filter != nullptr)) {
         result->intersectWith(*filter);
@@ -448,16 +483,36 @@ TupleIdSequence* 
AsciiStringUncheckedComparator<ComparisonFunctor,
         } else {
           accessor->beginIteration();
           std::size_t cv_pos = 0;
-          while (accessor->next()) {
-            const void *cv_value
-                = column_vector.template getUntypedValue<cv_nullable>(cv_pos);
-            const void *va_value
-                = accessor->template 
getUntypedValue<va_nullable>(value_accessor_attr_id);
-            result->set(cv_pos,
-                        (!((cv_nullable && (cv_value == nullptr))
-                            || (va_nullable && (va_value == nullptr))))
-                                && 
this->compareDataPtrsHelper<column_vector_on_left>(cv_value, va_value));
-            ++cv_pos;
+          if (accessor->isColumnAccessorSupported()) {
+            // If ColumnAccessor is supported on the underlying accessor, we 
have a fast strided
+            // column accessor available for the iteration on the underlying 
block.
+            std::unique_ptr<const ColumnAccessor<va_nullable>>
+                column_accessor(accessor->template 
getColumnAccessor<va_nullable>(value_accessor_attr_id));
+            DEBUG_ASSERT(column_accessor != nullptr);
+            while (accessor->next()) {
+              const void *cv_value
+                  = column_vector.template 
getUntypedValue<cv_nullable>(cv_pos);
+              const void *va_value = column_accessor->getUntypedValue();
+              result->set(cv_pos,
+                          (!((cv_nullable && (cv_value == nullptr))
+                              || (va_nullable && (va_value == nullptr))))
+                              && 
this->compareDataPtrsHelper<column_vector_on_left>(cv_value,
+                                                                               
     va_value));
+              ++cv_pos;
+            }
+          } else {
+            while (accessor->next()) {
+              const void *cv_value
+                  = column_vector.template 
getUntypedValue<cv_nullable>(cv_pos);
+              const void *va_value
+                  = accessor->template 
getUntypedValue<va_nullable>(value_accessor_attr_id);
+              result->set(cv_pos,
+                          (!((cv_nullable && (cv_value == nullptr))
+                              || (va_nullable && (va_value == nullptr))))
+                              && 
this->compareDataPtrsHelper<column_vector_on_left>(cv_value,
+                                                                               
     va_value));
+              ++cv_pos;
+            }
           }
         }
         if (!short_circuit && (filter != nullptr)) {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/types/operations/comparisons/Comparison-inl.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/Comparison-inl.hpp 
b/types/operations/comparisons/Comparison-inl.hpp
index 25f5f15..96771bf 100644
--- a/types/operations/comparisons/Comparison-inl.hpp
+++ b/types/operations/comparisons/Comparison-inl.hpp
@@ -309,11 +309,28 @@ TupleIdSequence* 
UncheckedComparator::compareSingleValueAccessorDefaultImpl(
       }
     } else {
       accessor->beginIteration();
-      while (accessor->next()) {
-        result->set(accessor->getCurrentPosition(),
-                    this->compareDataPtrs(
-                        accessor->template 
getUntypedValue<left_nullable>(left_id),
-                        accessor->template 
getUntypedValue<right_nullable>(right_id)));
+      if (accessor->isColumnAccessorSupported()) {
+        // If ColumnAccessor is supported on the underlying accessor, we have 
a fast strided
+        // column accessor available for the iteration on the underlying block.
+        std::unique_ptr<const ColumnAccessor<left_nullable>>
+            left_column_accessor(accessor->template 
getColumnAccessor<left_nullable>(left_id));
+        std::unique_ptr<const ColumnAccessor<right_nullable>>
+            right_column_accessor(accessor->template 
getColumnAccessor<right_nullable>(right_id));
+        DEBUG_ASSERT(left_column_accessor != nullptr);
+        DEBUG_ASSERT(right_column_accessor != nullptr);
+        while (accessor->next()) {
+          result->set(accessor->getCurrentPosition(),
+                      this->compareDataPtrs(
+                          left_column_accessor->getUntypedValue(),
+                          right_column_accessor->getUntypedValue()));
+        }
+      } else {
+        while (accessor->next()) {
+          result->set(accessor->getCurrentPosition(),
+                      this->compareDataPtrs(
+                          accessor->template 
getUntypedValue<left_nullable>(left_id),
+                          accessor->template 
getUntypedValue<right_nullable>(right_id)));
+        }
       }
       if (!short_circuit && (filter != nullptr)) {
         result->intersectWith(*filter);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/types/operations/comparisons/LiteralComparators-inl.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/LiteralComparators-inl.hpp 
b/types/operations/comparisons/LiteralComparators-inl.hpp
index 14844ac..31eec13 100644
--- a/types/operations/comparisons/LiteralComparators-inl.hpp
+++ b/types/operations/comparisons/LiteralComparators-inl.hpp
@@ -273,13 +273,32 @@ TupleIdSequence* 
LiteralUncheckedComparator<ComparisonFunctor,
       }
     } else {
       accessor->beginIteration();
-      while (accessor->next()) {
-        const void *left_value = accessor->template 
getUntypedValue<left_nullable>(left_id);
-        const void *right_value = accessor->template 
getUntypedValue<right_nullable>(right_id);
-        result->set(accessor->getCurrentPosition(),
-                    (!((left_nullable && (left_value == nullptr))
-                        || (right_nullable && (right_value == nullptr))))
-                            && this->compareDataPtrsHelper<true>(left_value, 
right_value));
+      if (accessor->isColumnAccessorSupported()) {
+        // If ColumnAccessor is supported on the underlying accessor, we have 
a fast strided
+        // column accessor available for the iteration on the underlying block.
+        std::unique_ptr<const ColumnAccessor<left_nullable>>
+            left_column_accessor(accessor->template 
getColumnAccessor<left_nullable>(left_id));
+        std::unique_ptr<const ColumnAccessor<right_nullable>>
+            right_column_accessor(accessor->template 
getColumnAccessor<right_nullable>(right_id));
+        DEBUG_ASSERT(left_column_accessor != nullptr);
+        DEBUG_ASSERT(right_column_accessor != nullptr);
+        while (accessor->next()) {
+          const void *left_value = left_column_accessor->getUntypedValue();
+          const void *right_value = right_column_accessor->getUntypedValue();
+          result->set(accessor->getCurrentPosition(),
+                      (!((left_nullable && (left_value == nullptr))
+                          || (right_nullable && (right_value == nullptr))))
+                          && this->compareDataPtrsHelper<true>(left_value, 
right_value));
+        }
+      } else {
+        while (accessor->next()) {
+          const void *left_value = accessor->template 
getUntypedValue<left_nullable>(left_id);
+          const void *right_value = accessor->template 
getUntypedValue<right_nullable>(right_id);
+          result->set(accessor->getCurrentPosition(),
+                      (!((left_nullable && (left_value == nullptr))
+                          || (right_nullable && (right_value == nullptr))))
+                          && this->compareDataPtrsHelper<true>(left_value, 
right_value));
+        }
       }
       if (!short_circuit && (filter != nullptr)) {
         result->intersectWith(*filter);
@@ -339,12 +358,27 @@ TupleIdSequence* 
LiteralUncheckedComparator<ComparisonFunctor,
       }
     } else {
       accessor->beginIteration();
-      while (accessor->next()) {
-        const void *va_value
-            = accessor->template 
getUntypedValue<va_nullable>(value_accessor_attr_id);
-        result->set(accessor->getCurrentPosition(),
-                    !(va_nullable && (va_value == nullptr))
-                        && 
this->compareDataPtrsHelper<value_accessor_on_left>(va_value, &literal));
+      if (accessor->isColumnAccessorSupported()) {
+        // If ColumnAccessor is supported on the underlying accessor, we have 
a fast strided
+        // column accessor available for the iteration on the underlying block.
+        std::unique_ptr<const ColumnAccessor<va_nullable>>
+            column_accessor(accessor->template 
getColumnAccessor<va_nullable>(value_accessor_attr_id));
+        DEBUG_ASSERT(column_accessor != nullptr);
+        while (accessor->next()) {
+          const void *va_value = column_accessor->getUntypedValue();
+          result->set(accessor->getCurrentPosition(),
+                      !(va_nullable && (va_value == nullptr))
+                          && 
this->compareDataPtrsHelper<value_accessor_on_left>(va_value, &literal));
+        }
+      } else {
+        while (accessor->next()) {
+          const void *va_value
+              = accessor->template 
getUntypedValue<va_nullable>(value_accessor_attr_id);
+          result->set(accessor->getCurrentPosition(),
+                      !(va_nullable && (va_value == nullptr))
+                          && 
this->compareDataPtrsHelper<value_accessor_on_left>(va_value,
+                                                                               
  &literal));
+        }
       }
       if (!short_circuit && (filter != nullptr)) {
         result->intersectWith(*filter);
@@ -458,16 +492,36 @@ TupleIdSequence* 
LiteralUncheckedComparator<ComparisonFunctor,
       } else {
         accessor->beginIteration();
         std::size_t cv_pos = 0;
-        while (accessor->next()) {
-          const void *cv_value
-              = native_column_vector.getUntypedValue<cv_nullable>(cv_pos);
-          const void *va_value
-              = accessor->template 
getUntypedValue<va_nullable>(value_accessor_attr_id);
-          result->set(cv_pos,
-                      (!((cv_nullable && (cv_value == nullptr))
-                          || (va_nullable && (va_value == nullptr))))
-                              && 
this->compareDataPtrsHelper<column_vector_on_left>(cv_value, va_value));
-          ++cv_pos;
+        if (accessor->isColumnAccessorSupported()) {
+          // If ColumnAccessor is supported on the underlying accessor, we 
have a fast strided
+          // column accessor available for the iteration on the underlying 
block.
+          std::unique_ptr<const ColumnAccessor<va_nullable>>
+              column_accessor(accessor->template 
getColumnAccessor<va_nullable>(value_accessor_attr_id));
+          DEBUG_ASSERT(column_accessor != nullptr);
+          while (accessor->next()) {
+            const void *cv_value
+                = native_column_vector.getUntypedValue<cv_nullable>(cv_pos);
+            const void *va_value = column_accessor->getUntypedValue();
+            result->set(cv_pos,
+                        (!((cv_nullable && (cv_value == nullptr))
+                            || (va_nullable && (va_value == nullptr))))
+                            && 
this->compareDataPtrsHelper<column_vector_on_left>(cv_value,
+                                                                               
   va_value));
+            ++cv_pos;
+          }
+        } else {
+          while (accessor->next()) {
+            const void *cv_value
+                = native_column_vector.getUntypedValue<cv_nullable>(cv_pos);
+            const void *va_value
+                = accessor->template 
getUntypedValue<va_nullable>(value_accessor_attr_id);
+            result->set(cv_pos,
+                        (!((cv_nullable && (cv_value == nullptr))
+                            || (va_nullable && (va_value == nullptr))))
+                            && 
this->compareDataPtrsHelper<column_vector_on_left>(cv_value,
+                                                                               
   va_value));
+            ++cv_pos;
+          }
         }
       }
       if (!short_circuit && (filter != nullptr)) {
@@ -495,13 +549,30 @@ TypedValue LiteralUncheckedComparator<ComparisonFunctor,
       accessor,
       [&](auto *accessor) -> void {  // NOLINT(build/c++11)
     accessor->beginIteration();
-    while (accessor->next()) {
-      const void *va_value = accessor->template 
getUntypedValue<left_nullable>(value_accessor_id);
-      if (left_nullable && !va_value) {
-        continue;
+    if (accessor->isColumnAccessorSupported()) {
+      // If ColumnAccessor is supported on the underlying accessor, we have a 
fast strided
+      // column accessor available for the iteration on the underlying block.
+      std::unique_ptr<const ColumnAccessor<left_nullable>>
+          column_accessor(accessor->template 
getColumnAccessor<left_nullable>(value_accessor_id));
+      DEBUG_ASSERT(column_accessor != nullptr);
+      while (accessor->next()) {
+        const void *va_value = column_accessor->getUntypedValue();
+        if (left_nullable && !va_value) {
+          continue;
+        }
+        if (!current_literal || this->compareDataPtrsHelper<true>(va_value, 
current_literal)) {
+          current_literal = va_value;
+        }
       }
-      if (!current_literal || this->compareDataPtrsHelper<true>(va_value, 
current_literal)) {
-        current_literal = va_value;
+    } else {
+      while (accessor->next()) {
+        const void *va_value = accessor->template 
getUntypedValue<left_nullable>(value_accessor_id);
+        if (left_nullable && !va_value) {
+          continue;
+        }
+        if (!current_literal || this->compareDataPtrsHelper<true>(va_value, 
current_literal)) {
+          current_literal = va_value;
+        }
       }
     }
   });

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/types/operations/comparisons/PatternMatchingComparators-inl.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/PatternMatchingComparators-inl.hpp 
b/types/operations/comparisons/PatternMatchingComparators-inl.hpp
index 617eadf..ca0f45e 100644
--- a/types/operations/comparisons/PatternMatchingComparators-inl.hpp
+++ b/types/operations/comparisons/PatternMatchingComparators-inl.hpp
@@ -241,11 +241,25 @@ TupleIdSequence* 
PatternMatchingUncheckedComparator<is_like_pattern, is_negation
       }
     } else {
       accessor->beginIteration();
-      while (accessor->next()) {
-        const void *va_value
-            = accessor->template 
getUntypedValue<left_nullable>(value_accessor_attr_id);
-        result->set(accessor->getCurrentPosition(),
-                    this->matchDataPtrWithPattern(va_value, re2_pattern));
+      if (accessor->isColumnAccessorSupported()) {
+        // If ColumnAccessor is supported on the underlying accessor, we have 
a fast strided
+        // column accessor available for the iteration on the underlying block.
+        std::unique_ptr<const ColumnAccessor<left_nullable>>
+            column_accessor
+            (accessor->template 
getColumnAccessor<left_nullable>(value_accessor_attr_id));
+        DEBUG_ASSERT(column_accessor != nullptr);
+        while (accessor->next()) {
+          const void *va_value = column_accessor->getUntypedValue();
+          result->set(accessor->getCurrentPosition(),
+                      this->matchDataPtrWithPattern(va_value, re2_pattern));
+        }
+      } else {
+        while (accessor->next()) {
+          const void *va_value
+              = accessor->template 
getUntypedValue<left_nullable>(value_accessor_attr_id);
+          result->set(accessor->getCurrentPosition(),
+                      this->matchDataPtrWithPattern(va_value, re2_pattern));
+        }
       }
       if (!short_circuit && (filter != nullptr)) {
         result->intersectWith(*filter);


Reply via email to