[Groonga-commit] groonga/grnxx at 13bec8c [master] Rename grnxx::ColumnImpl to grnxx::impl::Column.

Back to archive index

susumu.yata null+****@clear*****
Tue Oct 7 13:33:14 JST 2014


susumu.yata	2014-10-07 13:33:14 +0900 (Tue, 07 Oct 2014)

  New Revision: 13bec8c270eed96f96487d345b1453fe654d8652
  https://github.com/groonga/grnxx/commit/13bec8c270eed96f96487d345b1453fe654d8652

  Message:
    Rename grnxx::ColumnImpl to grnxx::impl::Column.

  Added files:
    lib/grnxx/impl/column/column.cpp
    lib/grnxx/impl/column/column.hpp
    lib/grnxx/impl/column/column_bool.hpp
    lib/grnxx/impl/column/column_float.hpp
    lib/grnxx/impl/column/column_geo_point.hpp
    lib/grnxx/impl/column/column_int.cpp
    lib/grnxx/impl/column/column_int.hpp
    lib/grnxx/impl/column/column_text.cpp
    lib/grnxx/impl/column/column_text.hpp
    lib/grnxx/impl/column/column_vector_bool.hpp
    lib/grnxx/impl/column/column_vector_float.cpp
    lib/grnxx/impl/column/column_vector_float.hpp
    lib/grnxx/impl/column/column_vector_geo_point.cpp
    lib/grnxx/impl/column/column_vector_geo_point.hpp
    lib/grnxx/impl/column/column_vector_int.cpp
    lib/grnxx/impl/column/column_vector_int.hpp
    lib/grnxx/impl/column/column_vector_text.cpp
    lib/grnxx/impl/column/column_vector_text.hpp
  Removed files:
    lib/grnxx/column.cpp
    lib/grnxx/column_impl.hpp
  Modified files:
    lib/grnxx/Makefile.am
    lib/grnxx/expression.cpp
    lib/grnxx/impl/column.hpp
    lib/grnxx/impl/column/Makefile.am
    lib/grnxx/impl/column/column_base.cpp
    lib/grnxx/impl/column/column_base.hpp
    lib/grnxx/impl/table.hpp
    lib/grnxx/index.cpp

  Modified: lib/grnxx/Makefile.am (+0 -2)
===================================================================
--- lib/grnxx/Makefile.am    2014-10-07 11:30:11 +0900 (6eba8e2)
+++ lib/grnxx/Makefile.am    2014-10-07 13:33:14 +0900 (e7f9f19)
@@ -10,7 +10,6 @@ libgrnxx_la_LDFLAGS = @AM_LTLDFLAGS@
 
 libgrnxx_la_SOURCES =			\
 	array.cpp			\
-	column.cpp			\
 	cursor.cpp			\
 	db.cpp				\
 	error.cpp			\
@@ -25,7 +24,6 @@ libgrnxx_la_SOURCES =			\
 
 libgrnxx_includedir = ${includedir}/grnxx
 libgrnxx_include_HEADERS =		\
-	column_impl.hpp			\
 	name.hpp			\
 	tree_index.hpp			\
 	version.h

  Deleted: lib/grnxx/column.cpp (+0 -1055) 100644
===================================================================
--- lib/grnxx/column.cpp    2014-10-07 11:30:11 +0900 (cd4945e)
+++ /dev/null
@@ -1,1055 +0,0 @@
-#include "grnxx/column.hpp"
-
-#include "grnxx/column_impl.hpp"
-#include "grnxx/cursor.hpp"
-#include "grnxx/impl/db.hpp"
-#include "grnxx/impl/table.hpp"
-#include "grnxx/index.hpp"
-
-#include <set>
-#include <unordered_set>
-
-namespace grnxx {
-
-// -- ColumnImpl<T> --
-
-template <typename T>
-bool ColumnImpl<T>::set(Error *error, Int row_id, const Datum &datum) {
-  if (datum.type() != TypeTraits<T>::data_type()) {
-    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
-    return false;
-  }
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  // Note that a Bool object does not have its own address.
-  T old_value = get(row_id);
-  T new_value;
-  datum.force(&new_value);
-  // TODO: Note that NaN != NaN.
-  if (new_value != old_value) {
-    for (Int i = 0; i < num_indexes(); ++i) {
-      if (!indexes_[i]->insert(error, row_id, datum)) {
-        for (Int j = 0; j < i; ++i) {
-          indexes_[j]->remove(nullptr, row_id, datum);
-        }
-        return false;
-      }
-    }
-    for (Int i = 0; i < num_indexes(); ++i) {
-      indexes_[i]->remove(nullptr, row_id, old_value);
-    }
-  }
-  values_.set(row_id, new_value);
-  return true;
-}
-
-template <typename T>
-bool ColumnImpl<T>::get(Error *error, Int row_id, Datum *datum) const {
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  *datum = values_[row_id];
-  return true;
-}
-
-template <typename T>
-unique_ptr<ColumnImpl<T>> ColumnImpl<T>::create(Error *error,
-                                                impl::Table *table,
-                                                const StringCRef &name,
-                                                const ColumnOptions &options) {
-  unique_ptr<ColumnImpl> column(new (nothrow) ColumnImpl);
-  if (!column) {
-    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
-    return nullptr;
-  }
-  if (!column->initialize_base(error, table, name,
-                               TypeTraits<T>::data_type(), options)) {
-    return nullptr;
-  }
-  if (!column->values_.resize(error, table->max_row_id() + 1,
-                              TypeTraits<T>::default_value())) {
-    return nullptr;
-  }
-  return column;
-}
-
-template <typename T>
-ColumnImpl<T>::~ColumnImpl() {}
-
-template <typename T>
-bool ColumnImpl<T>::set_default_value(Error *error, Int row_id) {
-  if (row_id >= values_.size()) {
-    if (!values_.resize(error, row_id + 1, TypeTraits<T>::default_value())) {
-      return false;
-    }
-  }
-  T value = TypeTraits<T>::default_value();
-  for (Int i = 0; i < num_indexes(); ++i) {
-    if (!indexes_[i]->insert(error, row_id, value)) {
-      for (Int j = 0; j < i; ++j) {
-        indexes_[j]->remove(nullptr, row_id, value);
-      }
-      return false;
-    }
-  }
-  values_.set(row_id, value);
-  return true;
-}
-
-template <typename T>
-void ColumnImpl<T>::unset(Int row_id) {
-  for (Int i = 0; i < num_indexes(); ++i) {
-    indexes_[i]->remove(nullptr, row_id, get(row_id));
-  }
-  values_.set(row_id, TypeTraits<T>::default_value());
-}
-
-template <typename T>
-ColumnImpl<T>::ColumnImpl() : ColumnBase(), values_() {}
-
-template class ColumnImpl<Bool>;
-template class ColumnImpl<Float>;
-template class ColumnImpl<GeoPoint>;
-template class ColumnImpl<Vector<Bool>>;
-
-// -- ColumnImpl<Int> --
-
-bool ColumnImpl<Int>::set(Error *error, Int row_id, const Datum &datum) {
-  if (datum.type() != INT_DATA) {
-    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
-    return false;
-  }
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  if (ref_table_) {
-    if (!ref_table_->test_row(error, datum.force_int())) {
-      return false;
-    }
-  }
-  Int old_value = get(row_id);
-  Int new_value = datum.force_int();
-  if (new_value != old_value) {
-    if (has_key_attribute_ && contains(datum)) {
-      GRNXX_ERROR_SET(error, ALREADY_EXISTS, "Key duplicate");
-      return false;
-    }
-    for (Int i = 0; i < num_indexes(); ++i) {
-      if (!indexes_[i]->insert(error, row_id, datum)) {
-        for (Int j = 0; j < i; ++i) {
-          indexes_[j]->remove(nullptr, row_id, datum);
-        }
-        return false;
-      }
-    }
-    for (Int i = 0; i < num_indexes(); ++i) {
-      indexes_[i]->remove(nullptr, row_id, old_value);
-    }
-  }
-  values_.set(row_id, new_value);
-  return true;
-}
-
-bool ColumnImpl<Int>::get(Error *error, Int row_id, Datum *datum) const {
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  *datum = values_[row_id];
-  return true;
-}
-
-unique_ptr<ColumnImpl<Int>> ColumnImpl<Int>::create(
-    Error *error,
-    impl::Table *table,
-    const StringCRef &name,
-    const ColumnOptions &options) {
-  unique_ptr<ColumnImpl> column(new (nothrow) ColumnImpl);
-  if (!column) {
-    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
-    return nullptr;
-  }
-  if (!column->initialize_base(error, table, name, INT_DATA, options)) {
-    return nullptr;
-  }
-  if (!column->values_.resize(error, table->max_row_id() + 1,
-                              TypeTraits<Int>::default_value())) {
-    return nullptr;
-  }
-  if (column->ref_table()) {
-    if (!column->ref_table_->append_referrer_column(error, column.get())) {
-      return nullptr;
-    }
-  }
-  return column;
-}
-
-ColumnImpl<Int>::~ColumnImpl() {}
-
-bool ColumnImpl<Int>::set_key_attribute(Error *error) {
-  if (has_key_attribute_) {
-    GRNXX_ERROR_SET(error, INVALID_OPERATION,
-                    "This column is a key column");
-    return false;
-  }
-  // TODO: An index should be used if possible.
-  try {
-    std::unordered_set<Int> set;
-    // TODO: Functor-based inline callback may be better in this case,
-    //       because it does not require memory allocation.
-    auto cursor = table_->create_cursor(nullptr);
-    if (!cursor) {
-      return false;
-    }
-    Array<Record> records;
-    for ( ; ; ) {
-      auto result = cursor->read(nullptr, 1024, &records);
-      if (!result.is_ok) {
-        return false;
-      } else {
-        break;
-      }
-      for (Int i = 0; i < result.count; ++i) {
-        if (!set.insert(values_[records.get_row_id(i)]).second) {
-          GRNXX_ERROR_SET(error, INVALID_OPERATION, "Key duplicate");
-          return false;
-        }
-      }
-      records.clear();
-    }
-  } catch (...) {
-    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
-    return false;
-  }
-  has_key_attribute_ = true;
-  return true;
-}
-
-bool ColumnImpl<Int>::unset_key_attribute(Error *error) {
-  if (!has_key_attribute_) {
-    GRNXX_ERROR_SET(error, INVALID_OPERATION,
-                    "This column is not a key column");
-    return false;
-  }
-  has_key_attribute_ = false;
-  return true;
-}
-
-bool ColumnImpl<Int>::set_initial_key(Error *error,
-                                      Int row_id,
-                                      const Datum &key) {
-  if (!has_key_attribute_) {
-    GRNXX_ERROR_SET(error, INVALID_OPERATION,
-                    "This column is not a key column");
-    return false;
-  }
-  if (has_key_attribute_ && contains(key)) {
-    GRNXX_ERROR_SET(error, ALREADY_EXISTS, "Key duplicate");
-    return false;
-  }
-  if (row_id >= values_.size()) {
-    if (!values_.resize(error, row_id + 1, TypeTraits<Int>::default_value())) {
-      return false;
-    }
-  }
-  Int value = key.force_int();
-  for (Int i = 0; i < num_indexes(); ++i) {
-    if (!indexes_[i]->insert(error, row_id, value)) {
-      for (Int j = 0; j < i; ++j) {
-        indexes_[j]->remove(nullptr, row_id, value);
-      }
-      return false;
-    }
-  }
-  values_.set(row_id, value);
-  return true;
-}
-
-bool ColumnImpl<Int>::set_default_value(Error *error, Int row_id) {
-  if (has_key_attribute_) {
-    GRNXX_ERROR_SET(error, INVALID_OPERATION,
-                    "This column is a key column");
-    return false;
-  }
-  if (row_id >= values_.size()) {
-    if (!values_.resize(error, row_id + 1, TypeTraits<Int>::default_value())) {
-      return false;
-    }
-  }
-  Int value = TypeTraits<Int>::default_value();
-  for (Int i = 0; i < num_indexes(); ++i) {
-    if (!indexes_[i]->insert(error, row_id, value)) {
-      for (Int j = 0; j < i; ++j) {
-        indexes_[j]->remove(nullptr, row_id, value);
-      }
-      return false;
-    }
-  }
-  values_.set(row_id, value);
-  return true;
-}
-
-void ColumnImpl<Int>::unset(Int row_id) {
-  for (Int i = 0; i < num_indexes(); ++i) {
-    indexes_[i]->remove(nullptr, row_id, get(row_id));
-  }
-  values_.set(row_id, TypeTraits<Int>::default_value());
-}
-
-Int ColumnImpl<Int>::find_one(const Datum &datum) const {
-  // TODO: Cursor should not be used because it takes time.
-  //       Also, cursor operations can fail due to memory allocation.
-  Int value = datum.force_int();
-  if (indexes_.size() != 0) {
-    return indexes_[0]->find_one(datum);
-  } else {
-    // TODO: A full scan takes time.
-    //       An index should be required for a key column.
-
-    // TODO: Functor-based inline callback may be better in this case,
-    //       because it does not require memory allocation.
-
-    // Scan the column to find "value".
-    auto cursor = table_->create_cursor(nullptr);
-    if (!cursor) {
-      return NULL_ROW_ID;
-    }
-    Array<Record> records;
-    for ( ; ; ) {
-      auto result = cursor->read(nullptr, 1024, &records);
-      if (!result.is_ok || result.count == 0) {
-        return NULL_ROW_ID;
-      }
-      for (Int i = 0; i < result.count; ++i) {
-        if (values_[records.get_row_id(i)] == value) {
-          return records.get_row_id(i);
-        }
-      }
-      records.clear();
-    }
-  }
-  return NULL_ROW_ID;
-}
-
-void ColumnImpl<Int>::clear_references(Int row_id) {
-  // TODO: Cursor should not be used to avoid errors.
-  if (indexes_.size() != 0) {
-    auto cursor = indexes_[0]->find(nullptr, Int(0));
-    if (!cursor) {
-      // Error.
-      return;
-    }
-    Array<Record> records;
-    for ( ; ; ) {
-      auto result = cursor->read(nullptr, 1024, &records);
-      if (!result.is_ok) {
-        // Error.
-        return;
-      } else if (result.count == 0) {
-        return;
-      }
-      for (Int i = 0; i < records.size(); ++i) {
-        set(nullptr, row_id, NULL_ROW_ID);
-      }
-      records.clear();
-    }
-  } else {
-    auto cursor = table_->create_cursor(nullptr);
-    if (!cursor) {
-      // Error.
-      return;
-    }
-    Array<Record> records;
-    for ( ; ; ) {
-      auto result = cursor->read(nullptr, 1024, &records);
-      if (!result.is_ok) {
-        // Error.
-        return;
-      } else if (result.count == 0) {
-        return;
-      }
-      for (Int i = 0; i < records.size(); ++i) {
-        if (values_[records.get_row_id(i)] == row_id) {
-          values_[records.get_row_id(i)] = NULL_ROW_ID;
-        }
-      }
-      records.clear();
-    }
-  }
-}
-
-ColumnImpl<Int>::ColumnImpl() : ColumnBase(), values_() {}
-
-// -- ColumnImpl<Text> --
-
-bool ColumnImpl<Text>::set(Error *error, Int row_id, const Datum &datum) {
-  if (datum.type() != TEXT_DATA) {
-    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
-    return false;
-  }
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  Text old_value = get(row_id);
-  Text new_value = datum.force_text();
-  if (new_value != old_value) {
-    if (has_key_attribute_ && contains(datum)) {
-      GRNXX_ERROR_SET(error, ALREADY_EXISTS, "Key duplicate");
-      return false;
-    }
-    for (Int i = 0; i < num_indexes(); ++i) {
-      if (!indexes_[i]->insert(error, row_id, datum)) {
-        for (Int j = 0; j < i; ++i) {
-          indexes_[j]->remove(nullptr, row_id, datum);
-        }
-        return false;
-      }
-    }
-    Int offset = bodies_.size();
-    UInt new_header;
-    if (new_value.size() < 0xFFFF) {
-      if (!bodies_.resize(error, offset + new_value.size())) {
-        return false;
-      }
-      std::memcpy(&bodies_[offset], new_value.data(), new_value.size());
-      new_header = (offset << 16) | new_value.size();
-    } else {
-      // The size of a long text is stored in front of the body.
-      if ((offset % sizeof(Int)) != 0) {
-        offset += sizeof(Int) - (offset % sizeof(Int));
-      }
-      if (!bodies_.resize(error, offset + sizeof(Int) + new_value.size())) {
-        return false;
-      }
-      *reinterpret_cast<Int *>(&bodies_[offset]) = new_value.size();
-      std::memcpy(&bodies_[offset + sizeof(Int)],
-                  new_value.data(), new_value.size());
-      new_header = (offset << 16) | 0xFFFF;
-    }
-    for (Int i = 0; i < num_indexes(); ++i) {
-      indexes_[i]->remove(nullptr, row_id, old_value);
-    }
-    headers_[row_id] = new_header;
-  }
-  return true;
-}
-
-bool ColumnImpl<Text>::get(Error *error, Int row_id, Datum *datum) const {
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  *datum = get(row_id);
-  return true;
-}
-
-unique_ptr<ColumnImpl<Text>> ColumnImpl<Text>::create(
-    Error *error,
-    impl::Table *table,
-    const StringCRef &name,
-    const ColumnOptions &options) {
-  unique_ptr<ColumnImpl> column(new (nothrow) ColumnImpl);
-  if (!column) {
-    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
-    return nullptr;
-  }
-  if (!column->initialize_base(error, table, name, TEXT_DATA, options)) {
-    return nullptr;
-  }
-  if (!column->headers_.resize(error, table->max_row_id() + 1, 0)) {
-    return nullptr;
-  }
-  return column;
-}
-
-ColumnImpl<Text>::~ColumnImpl() {}
-
-bool ColumnImpl<Text>::set_key_attribute(Error *error) {
-  if (has_key_attribute_) {
-    GRNXX_ERROR_SET(error, INVALID_OPERATION,
-                    "This column is a key column");
-    return false;
-  }
-  // TODO: An index should be used if possible.
-  try {
-    std::set<Text> set;
-    // TODO: Functor-based inline callback may be better in this case,
-    //       because it does not require memory allocation.
-    auto cursor = table_->create_cursor(nullptr);
-    if (!cursor) {
-      return false;
-    }
-    Array<Record> records;
-    for ( ; ; ) {
-      auto result = cursor->read(nullptr, 1024, &records);
-      if (!result.is_ok) {
-        return false;
-      } else {
-        break;
-      }
-      for (Int i = 0; i < result.count; ++i) {
-        if (!set.insert(get(records.get_row_id(i))).second) {
-          GRNXX_ERROR_SET(error, INVALID_OPERATION, "Key duplicate");
-          return false;
-        }
-      }
-      records.clear();
-    }
-  } catch (...) {
-    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
-    return false;
-  }
-  has_key_attribute_ = true;
-  return true;
-}
-
-bool ColumnImpl<Text>::unset_key_attribute(Error *error) {
-  if (!has_key_attribute_) {
-    GRNXX_ERROR_SET(error, INVALID_OPERATION,
-                    "This column is not a key column");
-    return false;
-  }
-  has_key_attribute_ = false;
-  return true;
-}
-
-bool ColumnImpl<Text>::set_initial_key(Error *error,
-    Int row_id,
-    const Datum &key) {
-  if (!has_key_attribute_) {
-    GRNXX_ERROR_SET(error, INVALID_OPERATION,
-                    "This column is not a key column");
-    return false;
-  }
-  if (has_key_attribute_ && contains(key)) {
-    GRNXX_ERROR_SET(error, ALREADY_EXISTS, "Key duplicate");
-    return false;
-  }
-  if (row_id >= headers_.size()) {
-    if (!headers_.resize(error, row_id + 1, 0)) {
-      return false;
-    }
-  }
-  Text value = key.force_text();
-  for (Int i = 0; i < num_indexes(); ++i) {
-    if (!indexes_[i]->insert(error, row_id, value)) {
-      for (Int j = 0; j < i; ++j) {
-        indexes_[j]->remove(nullptr, row_id, value);
-      }
-      return false;
-    }
-  }
-  Int offset = bodies_.size();
-  UInt header;
-  if (value.size() < 0xFFFF) {
-    if (!bodies_.resize(error, offset + value.size())) {
-      return false;
-    }
-    std::memcpy(&bodies_[offset], value.data(), value.size());
-    header = (offset << 16) | value.size();
-  } else {
-    // The size of a long text is stored in front of the body.
-    if ((offset % sizeof(Int)) != 0) {
-      offset += sizeof(Int) - (offset % sizeof(Int));
-    }
-    if (!bodies_.resize(error, offset + sizeof(Int) + value.size())) {
-      return false;
-    }
-    *reinterpret_cast<Int *>(&bodies_[offset]) = value.size();
-    std::memcpy(&bodies_[offset + sizeof(Int)], value.data(), value.size());
-    header = (offset << 16) | 0xFFFF;
-  }
-  headers_[row_id] = header;
-  return true;
-}
-
-bool ColumnImpl<Text>::set_default_value(Error *error, Int row_id) {
-  if (has_key_attribute_) {
-    GRNXX_ERROR_SET(error, INVALID_OPERATION,
-                    "This column is a key column");
-    return false;
-  }
-  if (row_id >= headers_.size()) {
-    if (!headers_.resize(error, row_id + 1)) {
-      return false;
-    }
-  }
-  Text value = TypeTraits<Text>::default_value();
-  for (Int i = 0; i < num_indexes(); ++i) {
-    if (!indexes_[i]->insert(error, row_id, value)) {
-      for (Int j = 0; j < i; ++j) {
-        indexes_[j]->remove(nullptr, row_id, value);
-      }
-      return false;
-    }
-  }
-  headers_[row_id] = 0;
-  return true;
-}
-
-void ColumnImpl<Text>::unset(Int row_id) {
-  for (Int i = 0; i < num_indexes(); ++i) {
-    indexes_[i]->remove(nullptr, row_id, get(row_id));
-  }
-  headers_[row_id] = 0;
-}
-
-Int ColumnImpl<Text>::find_one(const Datum &datum) const {
-  // TODO: Cursor should not be used because it takes time.
-  // Also, cursor operations can fail due to memory allocation.
-  Text value = datum.force_text();
-  if (indexes_.size() != 0) {
-    auto cursor = indexes_[0]->find(nullptr, value);
-    Array<Record> records;
-    auto result = cursor->read(nullptr, 1, &records);
-    if (!result.is_ok || (result.count == 0)) {
-      return NULL_ROW_ID;
-    }
-    return true;
-  } else {
-    // TODO: A full scan takes time.
-    // An index should be required for a key column.
-
-    // TODO: Functor-based inline callback may be better in this case,
-    // because it does not require memory allocation.
-
-    // Scan the column to find "value".
-    auto cursor = table_->create_cursor(nullptr);
-    if (!cursor) {
-      return NULL_ROW_ID;
-    }
-    Array<Record> records;
-    for ( ; ; ) {
-      auto result = cursor->read(nullptr, 1024, &records);
-      if (!result.is_ok || result.count == 0) {
-        return NULL_ROW_ID;
-      }
-      for (Int i = 0; i < result.count; ++i) {
-        if (get(records.get_row_id(i)) == value) {
-          return records.get_row_id(i);
-        }
-      }
-      records.clear();
-    }
-  }
-  return NULL_ROW_ID;
-}
-
-ColumnImpl<Text>::ColumnImpl() : ColumnBase(), headers_(), bodies_() {}
-
-// -- ColumnImpl<Vector<Int>> --
-
-bool ColumnImpl<Vector<Int>>::set(Error *error, Int row_id,
-                                  const Datum &datum) {
-  if (datum.type() != INT_VECTOR_DATA) {
-    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
-    return false;
-  }
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  Vector<Int> value = datum.force_int_vector();
-  if (value.size() == 0) {
-    headers_[row_id] = 0;
-    return true;
-  }
-  if (ref_table_) {
-    for (Int i = 0; i < value.size(); ++i) {
-      if (!ref_table_->test_row(error, value[i])) {
-        return false;
-      }
-    }
-  }
-  Int offset = bodies_.size();
-  if (value.size() < 0xFFFF) {
-    if (!bodies_.resize(error, offset + value.size())) {
-      return false;
-    }
-    for (Int i = 0; i < value.size(); ++i) {
-      bodies_[offset + i] = value[i];
-    }
-    headers_[row_id] = (offset << 16) | value.size();
-  } else {
-    // The size of a long vector is stored in front of the body.
-    if (!bodies_.resize(error, offset + 1 + value.size())) {
-      return false;
-    }
-    bodies_[offset] = value.size();
-    for (Int i = 0; i < value.size(); ++i) {
-      bodies_[offset + 1 + i] = value[i];
-    }
-    headers_[row_id] = (offset << 16) | 0xFFFF;
-  }
-  return true;
-}
-
-bool ColumnImpl<Vector<Int>>::get(Error *error, Int row_id,
-                                  Datum *datum) const {
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  *datum = get(row_id);
-  return true;
-}
-
-unique_ptr<ColumnImpl<Vector<Int>>> ColumnImpl<Vector<Int>>::create(
-    Error *error,
-    impl::Table *table,
-    const StringCRef &name,
-    const ColumnOptions &options) {
-  unique_ptr<ColumnImpl> column(new (nothrow) ColumnImpl);
-  if (!column) {
-    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
-    return nullptr;
-  }
-  if (!column->initialize_base(error, table, name, INT_VECTOR_DATA, options)) {
-    return nullptr;
-  }
-  if (!column->headers_.resize(error, table->max_row_id() + 1, 0)) {
-    return nullptr;
-  }
-  if (column->ref_table()) {
-    if (!column->ref_table_->append_referrer_column(error, column.get())) {
-      return nullptr;
-    }
-  }
-  return column;
-}
-
-ColumnImpl<Vector<Int>>::~ColumnImpl() {}
-
-bool ColumnImpl<Vector<Int>>::set_default_value(Error *error, Int row_id) {
-  if (row_id >= headers_.size()) {
-    if (!headers_.resize(error, row_id + 1)) {
-      return false;
-    }
-  }
-  headers_[row_id] = 0;
-  return true;
-}
-
-void ColumnImpl<Vector<Int>>::unset(Int row_id) {
-  headers_[row_id] = 0;
-}
-
-void ColumnImpl<Vector<Int>>::clear_references(Int row_id) {
-  auto cursor = table_->create_cursor(nullptr);
-  if (!cursor) {
-    // Error.
-    return;
-  }
-  Array<Record> records;
-  for ( ; ; ) {
-    auto result = cursor->read(nullptr, 1024, &records);
-    if (!result.is_ok) {
-      // Error.
-      return;
-    } else if (result.count == 0) {
-      return;
-    }
-    for (Int i = 0; i < records.size(); ++i) {
-      Int value_row_id = records.get_row_id(i);
-      Int value_size = static_cast<Int>(headers_[value_row_id] & 0xFFFF);
-      if (value_size == 0) {
-        continue;
-      }
-      Int value_offset = static_cast<Int>(headers_[value_row_id] >> 16);
-      if (value_size >= 0xFFFF) {
-        value_size = bodies_[value_offset];
-        ++value_offset;
-      }
-      Int count = 0;
-      for (Int j = 0; j < value_size; ++j) {
-        if (bodies_[value_offset + j] != row_id) {
-          bodies_[value_offset + count] = bodies_[value_offset + j];
-          ++count;
-        }
-      }
-      if (count < value_size) {
-        if (count == 0) {
-          headers_[value_row_id] = 0;
-        } else if (count < 0xFFFF) {
-          headers_[value_row_id] = count | (value_offset << 16);
-        } else {
-          bodies_[value_offset - 1] = count;
-        }
-      }
-    }
-    records.clear();
-  }
-}
-
-ColumnImpl<Vector<Int>>::ColumnImpl() : ColumnBase(), headers_(), bodies_() {}
-
-// -- ColumnImpl<Vector<Float>> --
-
-bool ColumnImpl<Vector<Float>>::set(Error *error, Int row_id,
-                                    const Datum &datum) {
-  if (datum.type() != FLOAT_VECTOR_DATA) {
-    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
-    return false;
-  }
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  Vector<Float> value = datum.force_float_vector();
-  if (value.size() == 0) {
-    headers_[row_id] = 0;
-    return true;
-  }
-  Int offset = bodies_.size();
-  if (value.size() < 0xFFFF) {
-    if (!bodies_.resize(error, offset + value.size())) {
-      return false;
-    }
-    for (Int i = 0; i < value.size(); ++i) {
-      bodies_[offset + i] = value[i];
-    }
-    headers_[row_id] = (offset << 16) | value.size();
-  } else {
-    // The size of a long vector is stored in front of the body.
-    if (!bodies_.resize(error, offset + 1 + value.size())) {
-      return false;
-    }
-    Int size_for_copy = value.size();
-    std::memcpy(&bodies_[offset], &size_for_copy, sizeof(Int));
-    for (Int i = 0; i < value.size(); ++i) {
-      bodies_[offset + 1 + i] = value[i];
-    }
-    headers_[row_id] = (offset << 16) | 0xFFFF;
-  }
-  return true;
-}
-
-bool ColumnImpl<Vector<Float>>::get(Error *error, Int row_id,
-                                    Datum *datum) const {
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  *datum = get(row_id);
-  return true;
-}
-
-unique_ptr<ColumnImpl<Vector<Float>>> ColumnImpl<Vector<Float>>::create(
-    Error *error,
-    impl::Table *table,
-    const StringCRef &name,
-    const ColumnOptions &options) {
-  unique_ptr<ColumnImpl> column(new (nothrow) ColumnImpl);
-  if (!column) {
-    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
-    return nullptr;
-  }
-  if (!column->initialize_base(error, table, name,
-                               FLOAT_VECTOR_DATA, options)) {
-    return nullptr;
-  }
-  if (!column->headers_.resize(error, table->max_row_id() + 1, 0)) {
-    return nullptr;
-  }
-  return column;
-}
-
-ColumnImpl<Vector<Float>>::~ColumnImpl() {}
-
-bool ColumnImpl<Vector<Float>>::set_default_value(Error *error, Int row_id) {
-  if (row_id >= headers_.size()) {
-    if (!headers_.resize(error, row_id + 1)) {
-      return false;
-    }
-  }
-  headers_[row_id] = 0;
-  return true;
-}
-
-void ColumnImpl<Vector<Float>>::unset(Int row_id) {
-  headers_[row_id] = 0;
-}
-
-ColumnImpl<Vector<Float>>::ColumnImpl()
-    : ColumnBase(),
-      headers_(),
-      bodies_() {}
-
-// -- ColumnImpl<Vector<GeoPoint>> --
-
-bool ColumnImpl<Vector<GeoPoint>>::set(Error *error, Int row_id,
-                                       const Datum &datum) {
-  if (datum.type() != GEO_POINT_VECTOR_DATA) {
-    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
-    return false;
-  }
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  Vector<GeoPoint> value = datum.force_geo_point_vector();
-  if (value.size() == 0) {
-    headers_[row_id] = 0;
-    return true;
-  }
-  Int offset = bodies_.size();
-  if (value.size() < 0xFFFF) {
-    if (!bodies_.resize(error, offset + value.size())) {
-      return false;
-    }
-    for (Int i = 0; i < value.size(); ++i) {
-      bodies_[offset + i] = value[i];
-    }
-    headers_[row_id] = (offset << 16) | value.size();
-  } else {
-    // The size of a long vector is stored in front of the body.
-    if (!bodies_.resize(error, offset + 1 + value.size())) {
-      return false;
-    }
-    Int size_for_copy = value.size();
-    std::memcpy(&bodies_[offset], &size_for_copy, sizeof(Int));
-    for (Int i = 0; i < value.size(); ++i) {
-      bodies_[offset + 1 + i] = value[i];
-    }
-    headers_[row_id] = (offset << 16) | 0xFFFF;
-  }
-  return true;
-}
-
-bool ColumnImpl<Vector<GeoPoint>>::get(Error *error, Int row_id,
-                                       Datum *datum) const {
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  *datum = get(row_id);
-  return true;
-}
-
-unique_ptr<ColumnImpl<Vector<GeoPoint>>> ColumnImpl<Vector<GeoPoint>>::create(
-    Error *error,
-    impl::Table *table,
-    const StringCRef &name,
-    const ColumnOptions &options) {
-  unique_ptr<ColumnImpl> column(new (nothrow) ColumnImpl);
-  if (!column) {
-    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
-    return nullptr;
-  }
-  if (!column->initialize_base(error, table, name,
-                               GEO_POINT_VECTOR_DATA, options)) {
-    return nullptr;
-  }
-  if (!column->headers_.resize(error, table->max_row_id() + 1, 0)) {
-    return nullptr;
-  }
-  return column;
-}
-
-ColumnImpl<Vector<GeoPoint>>::~ColumnImpl() {}
-
-bool ColumnImpl<Vector<GeoPoint>>::set_default_value(Error *error,
-                                                     Int row_id) {
-  if (row_id >= headers_.size()) {
-    if (!headers_.resize(error, row_id + 1)) {
-      return false;
-    }
-  }
-  headers_[row_id] = 0;
-  return true;
-}
-
-void ColumnImpl<Vector<GeoPoint>>::unset(Int row_id) {
-  headers_[row_id] = 0;
-}
-
-ColumnImpl<Vector<GeoPoint>>::ColumnImpl()
-    : ColumnBase(),
-      headers_(),
-      bodies_() {}
-
-// -- ColumnImpl<Vector<Text>> --
-
-bool ColumnImpl<Vector<Text>>::set(Error *error, Int row_id,
-                                   const Datum &datum) {
-  if (datum.type() != TEXT_VECTOR_DATA) {
-    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
-    return false;
-  }
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  Vector<Text> value = datum.force_text_vector();
-  if (value.size() == 0) {
-    headers_[row_id] = Header{ 0, 0 };
-    return true;
-  }
-  Int text_headers_offset = text_headers_.size();
-  if (!text_headers_.resize(error, text_headers_offset + value.size())) {
-    return false;
-  }
-  Int total_size = 0;
-  for (Int i = 0; i < value.size(); ++i) {
-    total_size += value[i].size();
-  }
-  Int bodies_offset = bodies_.size();
-  if (!bodies_.resize(error, bodies_offset + total_size)) {
-    return false;
-  }
-  headers_[row_id] = Header{ text_headers_offset, value.size() };
-  for (Int i = 0; i < value.size(); ++i) {
-    text_headers_[text_headers_offset + i].offset = bodies_offset;
-    text_headers_[text_headers_offset + i].size = value[i].size();
-    std::memcpy(&bodies_[bodies_offset], value[i].data(), value[i].size());
-    bodies_offset += value[i].size();
-  }
-  return true;
-}
-
-bool ColumnImpl<Vector<Text>>::get(Error *error, Int row_id,
-                                   Datum *datum) const {
-  if (!table_->test_row(error, row_id)) {
-    return false;
-  }
-  *datum = get(row_id);
-  return true;
-}
-
-unique_ptr<ColumnImpl<Vector<Text>>> ColumnImpl<Vector<Text>>::create(
-    Error *error,
-    impl::Table *table,
-    const StringCRef &name,
-    const ColumnOptions &options) {
-  unique_ptr<ColumnImpl> column(new (nothrow) ColumnImpl);
-  if (!column) {
-    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
-    return nullptr;
-  }
-  if (!column->initialize_base(error, table, name,
-                               TEXT_VECTOR_DATA, options)) {
-    return nullptr;
-  }
-  if (!column->headers_.resize(error, table->max_row_id() + 1,
-                               Header{ 0, 0 })) {
-    return nullptr;
-  }
-  return column;
-}
-
-ColumnImpl<Vector<Text>>::~ColumnImpl() {}
-
-bool ColumnImpl<Vector<Text>>::set_default_value(Error *error,
-                                                     Int row_id) {
-  if (row_id >= headers_.size()) {
-    if (!headers_.resize(error, row_id + 1)) {
-      return false;
-    }
-  }
-  headers_[row_id] = Header{ 0, 0 };
-  return true;
-}
-
-void ColumnImpl<Vector<Text>>::unset(Int row_id) {
-  headers_[row_id] = Header{ 0, 0 };
-}
-
-ColumnImpl<Vector<Text>>::ColumnImpl()
-    : ColumnBase(),
-      headers_(),
-      text_headers_(),
-      bodies_() {}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/column_impl.hpp (+0 -396) 100644
===================================================================
--- lib/grnxx/column_impl.hpp    2014-10-07 11:30:11 +0900 (68b5a6c)
+++ /dev/null
@@ -1,396 +0,0 @@
-#ifndef GRNXX_COLUMN_IMPL_HPP
-#define GRNXX_COLUMN_IMPL_HPP
-
-#include "grnxx/impl/column/column_base.hpp"
-
-namespace grnxx {
-
-template <typename T>
-class ColumnImpl : public impl::ColumnBase {
- public:
-  // -- Public API --
-
-  bool set(Error *error, Int row_id, const Datum &datum);
-  bool get(Error *error, Int row_id, Datum *datum) const;
-
-  // -- Internal API --
-
-  // Create a new column.
-  //
-  // Returns a pointer to the column on success.
-  // On failure, returns nullptr and stores error information into "*error" if
-  // "error" != nullptr.
-  static unique_ptr<ColumnImpl> create(Error *error,
-                                       impl::Table *table,
-                                       const StringCRef &name,
-                                       const ColumnOptions &options);
-
-  ~ColumnImpl();
-
-  bool set_default_value(Error *error, Int row_id);
-  void unset(Int row_id);
-
-  // Return a value identified by "row_id".
-  //
-  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
-  T get(Int row_id) const {
-    return values_[row_id];
-  }
-
-  // Read values.
-  void read(ArrayCRef<Record> records, ArrayRef<T> values) const {
-    for (Int i = 0; i < records.size(); ++i) {
-      values.set(i, get(records.get_row_id(i)));
-    }
-  }
-
- private:
-  Array<T> values_;
-
-  ColumnImpl();
-};
-
-template <>
-class ColumnImpl<Int> : public impl::ColumnBase {
- public:
-  // -- Public API --
-
-  bool set(Error *error, Int row_id, const Datum &datum);
-  bool get(Error *error, Int row_id, Datum *datum) const;
-
-  // -- Internal API --
-
-  // Create a new column.
-  //
-  // Returns a pointer to the column on success.
-  // On failure, returns nullptr and stores error information into "*error" if
-  // "error" != nullptr.
-  static unique_ptr<ColumnImpl> create(Error *error,
-                                       impl::Table *table,
-                                       const StringCRef &name,
-                                       const ColumnOptions &options);
-
-  ~ColumnImpl();
-
-  bool set_key_attribute(Error *error);
-  bool unset_key_attribute(Error *error);
-
-  bool set_initial_key(Error *error, Int row_id, const Datum &key);
-  bool set_default_value(Error *error, Int row_id);
-  void unset(Int row_id);
-  Int find_one(const Datum &datum) const;
-
-  void clear_references(Int row_id);
-
-  // Return a value identified by "row_id".
-  //
-  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
-  Int get(Int row_id) const {
-    return values_[row_id];
-  }
-
-  // Read values.
-  void read(ArrayCRef<Record> records, ArrayRef<Int> values) const {
-    for (Int i = 0; i < records.size(); ++i) {
-      values.set(i, get(records.get_row_id(i)));
-    }
-  }
-
- private:
-  Array<Int> values_;
-
-  ColumnImpl();
-};
-
-template <>
-class ColumnImpl<Text> : public impl::ColumnBase {
- public:
-  // -- Public API --
-
-  bool set(Error *error, Int row_id, const Datum &datum);
-  bool get(Error *error, Int row_id, Datum *datum) const;
-
-  // -- Internal API --
-
-  // Create a new column.
-  //
-  // Returns a pointer to the column on success.
-  // On failure, returns nullptr and stores error information into "*error" if
-  // "error" != nullptr.
-  static unique_ptr<ColumnImpl> create(Error *error,
-                                       impl::Table *table,
-                                       const StringCRef &name,
-                                       const ColumnOptions &options);
-
-  ~ColumnImpl();
-
-  bool set_key_attribute(Error *error);
-  bool unset_key_attribute(Error *error);
-
-  bool set_initial_key(Error *error, Int row_id, const Datum &key);
-  bool set_default_value(Error *error, Int row_id);
-  void unset(Int row_id);
-  Int find_one(const Datum &datum) const;
-
-  // Return a value identified by "row_id".
-  //
-  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
-  Text get(Int row_id) const {
-    Int size = static_cast<Int>(headers_[row_id] & 0xFFFF);
-    if (size == 0) {
-      return Text("", 0);
-    }
-    Int offset = static_cast<Int>(headers_[row_id] >> 16);
-    if (size < 0xFFFF) {
-      return Text(&bodies_[offset], size);
-    } else {
-      // The size of a long text is stored in front of the body.
-      size = *reinterpret_cast<const Int *>(&bodies_[offset]);
-      return StringCRef(&bodies_[offset + sizeof(Int)], size);
-    }
-  }
-
-  // Read values.
-  void read(ArrayCRef<Record> records, ArrayRef<Text> values) const {
-    for (Int i = 0; i < records.size(); ++i) {
-      values.set(i, get(records.get_row_id(i)));
-    }
-  }
-
- private:
-  Array<UInt> headers_;
-  Array<char> bodies_;
-
-  ColumnImpl();
-};
-
-template <>
-class ColumnImpl<Vector<Int>> : public impl::ColumnBase {
- public:
-  // -- Public API --
-
-  bool set(Error *error, Int row_id, const Datum &datum);
-  bool get(Error *error, Int row_id, Datum *datum) const;
-
-  // -- Internal API --
-
-  // Create a new column.
-  //
-  // Returns a pointer to the column on success.
-  // On failure, returns nullptr and stores error information into "*error" if
-  // "error" != nullptr.
-  static unique_ptr<ColumnImpl> create(Error *error,
-                                       impl::Table *table,
-                                       const StringCRef &name,
-                                       const ColumnOptions &options);
-
-  ~ColumnImpl();
-
-  bool set_default_value(Error *error, Int row_id);
-  void unset(Int row_id);
-
-  void clear_references(Int row_id);
-
-  // Return a value identified by "row_id".
-  //
-  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
-  Vector<Int> get(Int row_id) const {
-    Int size = static_cast<Int>(headers_[row_id] & 0xFFFF);
-    if (size == 0) {
-      return Vector<Int>(nullptr, 0);
-    }
-    Int offset = static_cast<Int>(headers_[row_id] >> 16);
-    if (size < 0xFFFF) {
-      return Vector<Int>(&bodies_[offset], size);
-    } else {
-      // The size of a long vector is stored in front of the body.
-      size = bodies_[offset];
-      return Vector<Int>(&bodies_[offset + 1], size);
-    }
-  }
-
-  // Read values.
-  void read(ArrayCRef<Record> records, ArrayRef<Vector<Int>> values) const {
-    for (Int i = 0; i < records.size(); ++i) {
-      values.set(i, get(records.get_row_id(i)));
-    }
-  }
-
- private:
-  Array<UInt> headers_;
-  Array<Int> bodies_;
-
-  ColumnImpl();
-};
-
-template <>
-class ColumnImpl<Vector<Float>> : public impl::ColumnBase {
- public:
-  // -- Public API --
-
-  bool set(Error *error, Int row_id, const Datum &datum);
-  bool get(Error *error, Int row_id, Datum *datum) const;
-
-  // -- Internal API --
-
-  // Create a new column.
-  //
-  // Returns a pointer to the column on success.
-  // On failure, returns nullptr and stores error information into "*error" if
-  // "error" != nullptr.
-  static unique_ptr<ColumnImpl> create(Error *error,
-                                       impl::Table *table,
-                                       const StringCRef &name,
-                                       const ColumnOptions &options);
-
-  ~ColumnImpl();
-
-  bool set_default_value(Error *error, Int row_id);
-  void unset(Int row_id);
-
-  // Return a value identified by "row_id".
-  //
-  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
-  Vector<Float> get(Int row_id) const {
-    Int size = static_cast<Int>(headers_[row_id] & 0xFFFF);
-    if (size == 0) {
-      return Vector<Float>(nullptr, 0);
-    }
-    Int offset = static_cast<Int>(headers_[row_id] >> 16);
-    if (size < 0xFFFF) {
-      return Vector<Float>(&bodies_[offset], size);
-    } else {
-      // The size of a long vector is stored in front of the body.
-      std::memcpy(&size, &bodies_[offset], sizeof(Int));
-      return Vector<Float>(&bodies_[offset + 1], size);
-    }
-  }
-
-  // Read values.
-  void read(ArrayCRef<Record> records, ArrayRef<Vector<Float>> values) const {
-    for (Int i = 0; i < records.size(); ++i) {
-      values.set(i, get(records.get_row_id(i)));
-    }
-  }
-
- private:
-  Array<UInt> headers_;
-  Array<Float> bodies_;
-
-  ColumnImpl();
-};
-
-template <>
-class ColumnImpl<Vector<GeoPoint>> : public impl::ColumnBase {
- public:
-  // -- Public API --
-
-  bool set(Error *error, Int row_id, const Datum &datum);
-  bool get(Error *error, Int row_id, Datum *datum) const;
-
-  // -- Internal API --
-
-  // Create a new column.
-  //
-  // Returns a pointer to the column on success.
-  // On failure, returns nullptr and stores error information into "*error" if
-  // "error" != nullptr.
-  static unique_ptr<ColumnImpl> create(Error *error,
-                                       impl::Table *table,
-                                       const StringCRef &name,
-                                       const ColumnOptions &options);
-
-  ~ColumnImpl();
-
-  bool set_default_value(Error *error, Int row_id);
-  void unset(Int row_id);
-
-  // Return a value identified by "row_id".
-  //
-  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
-  Vector<GeoPoint> get(Int row_id) const {
-    Int size = static_cast<Int>(headers_[row_id] & 0xFFFF);
-    if (size == 0) {
-      return Vector<GeoPoint>(nullptr, 0);
-    }
-    Int offset = static_cast<Int>(headers_[row_id] >> 16);
-    if (size < 0xFFFF) {
-      return Vector<GeoPoint>(&bodies_[offset], size);
-    } else {
-      // The size of a long vector is stored in front of the body.
-      std::memcpy(&size, &bodies_[offset], sizeof(Int));
-      return Vector<GeoPoint>(&bodies_[offset + 1], size);
-    }
-  }
-
-  // Read values.
-  void read(ArrayCRef<Record> records,
-            ArrayRef<Vector<GeoPoint>> values) const {
-    for (Int i = 0; i < records.size(); ++i) {
-      values.set(i, get(records.get_row_id(i)));
-    }
-  }
-
- private:
-  Array<UInt> headers_;
-  Array<GeoPoint> bodies_;
-
-  ColumnImpl();
-};
-
-// TODO: Improve the implementation.
-template <>
-class ColumnImpl<Vector<Text>> : public impl::ColumnBase {
- public:
-  // -- Public API --
-
-  bool set(Error *error, Int row_id, const Datum &datum);
-  bool get(Error *error, Int row_id, Datum *datum) const;
-
-  // -- Internal API --
-
-  // Create a new column.
-  //
-  // Returns a pointer to the column on success.
-  // On failure, returns nullptr and stores error information into "*error" if
-  // "error" != nullptr.
-  static unique_ptr<ColumnImpl> create(Error *error,
-                                       impl::Table *table,
-                                       const StringCRef &name,
-                                       const ColumnOptions &options);
-
-  ~ColumnImpl();
-
-  bool set_default_value(Error *error, Int row_id);
-  void unset(Int row_id);
-
-  // Return a value identified by "row_id".
-  //
-  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
-  Vector<Text> get(Int row_id) const {
-    return Vector<Text>(&text_headers_[headers_[row_id].offset],
-                        bodies_.data(), headers_[row_id].size);
-  }
-
-  // Read values.
-  void read(ArrayCRef<Record> records, ArrayRef<Vector<Text>> values) const {
-    for (Int i = 0; i < records.size(); ++i) {
-      values.set(i, get(records.get_row_id(i)));
-    }
-  }
-
- private:
-  struct Header {
-    Int offset;
-    Int size;
-  };
-  Array<Header> headers_;
-  Array<Header> text_headers_;
-  Array<char> bodies_;
-
-  ColumnImpl();
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_COLUMN_IMPL_HPP

  Modified: lib/grnxx/expression.cpp (+7 -7)
===================================================================
--- lib/grnxx/expression.cpp    2014-10-07 11:30:11 +0900 (46145b3)
+++ lib/grnxx/expression.cpp    2014-10-07 13:33:14 +0900 (ed88cca)
@@ -1,6 +1,6 @@
 #include "grnxx/expression.hpp"
 
-#include "grnxx/column_impl.hpp"
+#include "grnxx/impl/column.hpp"
 #include "grnxx/table.hpp"
 
 #include <iostream>  // For debugging.
@@ -625,7 +625,7 @@ class ColumnNode : public TypedNode<T> {
 
   explicit ColumnNode(const Column *column)
       : TypedNode<Value>(),
-        column_(static_cast<const ColumnImpl<Value> *>(column)) {}
+        column_(static_cast<const impl::Column<Value> *>(column)) {}
 
   NodeType node_type() const {
     return COLUMN_NODE;
@@ -642,7 +642,7 @@ class ColumnNode : public TypedNode<T> {
   }
 
  private:
-  const ColumnImpl<T> *column_;
+  const impl::Column<T> *column_;
 };
 
 template <>
@@ -660,7 +660,7 @@ class ColumnNode<Bool> : public TypedNode<Bool> {
 
   explicit ColumnNode(const Column *column)
       : TypedNode<Value>(),
-        column_(static_cast<const ColumnImpl<Value> *>(column)) {}
+        column_(static_cast<const impl::Column<Value> *>(column)) {}
 
   NodeType node_type() const {
     return COLUMN_NODE;
@@ -677,7 +677,7 @@ class ColumnNode<Bool> : public TypedNode<Bool> {
   }
 
  private:
-  const ColumnImpl<Value> *column_;
+  const impl::Column<Value> *column_;
 };
 
 bool ColumnNode<Bool>::filter(Error *,
@@ -709,7 +709,7 @@ class ColumnNode<Float> : public TypedNode<Float> {
 
   explicit ColumnNode(const Column *column)
       : TypedNode<Value>(),
-        column_(static_cast<const ColumnImpl<Value> *>(column)) {}
+        column_(static_cast<const impl::Column<Value> *>(column)) {}
 
   NodeType node_type() const {
     return COLUMN_NODE;
@@ -729,7 +729,7 @@ class ColumnNode<Float> : public TypedNode<Float> {
   }
 
  private:
-  const ColumnImpl<Value> *column_;
+  const impl::Column<Value> *column_;
 };
 
 // -- OperatorNode --

  Modified: lib/grnxx/impl/column.hpp (+10 -11)
===================================================================
--- lib/grnxx/impl/column.hpp    2014-10-07 11:30:11 +0900 (16eb144)
+++ lib/grnxx/impl/column.hpp    2014-10-07 13:33:14 +0900 (8ea542d)
@@ -1,16 +1,15 @@
 #ifndef GRNXX_IMPL_COLUMN_HPP
 #define GRNXX_IMPL_COLUMN_HPP
 
-#include "grnxx/impl/column/column_base.hpp"
-//#include "grnxx/impl/column/column_bool.hpp"
-//#include "grnxx/impl/column/column_int.hpp"
-//#include "grnxx/impl/column/column_float.hpp"
-//#include "grnxx/impl/column/column_geo_point.hpp"
-//#include "grnxx/impl/column/column_text.hpp"
-//#include "grnxx/impl/column/column_vector_bool.hpp"
-//#include "grnxx/impl/column/column_vector_int.hpp"
-//#include "grnxx/impl/column/column_vector_float.hpp"
-//#include "grnxx/impl/column/column_vector_geo_point.hpp"
-//#include "grnxx/impl/column/column_vector_text.hpp"
+#include "grnxx/impl/column/column_bool.hpp"
+#include "grnxx/impl/column/column_int.hpp"
+#include "grnxx/impl/column/column_float.hpp"
+#include "grnxx/impl/column/column_geo_point.hpp"
+#include "grnxx/impl/column/column_text.hpp"
+#include "grnxx/impl/column/column_vector_bool.hpp"
+#include "grnxx/impl/column/column_vector_int.hpp"
+#include "grnxx/impl/column/column_vector_float.hpp"
+#include "grnxx/impl/column/column_vector_geo_point.hpp"
+#include "grnxx/impl/column/column_vector_text.hpp"
 
 #endif  // GRNXX_IMPL_COLUMN_HPP

  Modified: lib/grnxx/impl/column/Makefile.am (+24 -2)
===================================================================
--- lib/grnxx/impl/column/Makefile.am    2014-10-07 11:30:11 +0900 (8a5ffdc)
+++ lib/grnxx/impl/column/Makefile.am    2014-10-07 13:33:14 +0900 (f97bf8f)
@@ -9,8 +9,30 @@ lib_LTLIBRARIES = libgrnxx_impl_column.la
 libgrnxx_impl_column_la_LDFLAGS = @AM_LTLDFLAGS@
 
 libgrnxx_impl_column_la_SOURCES =		\
-	column_base.cpp
+	column.cpp				\
+	column_base.cpp				\
+	column_int.cpp				\
+	column_text.cpp				\
+	column_vector_int.cpp			\
+	column_vector_float.cpp			\
+	column_vector_geo_point.cpp		\
+	column_vector_text.cpp
+
+#	column_bool.cpp				\
+#	column_float.cpp			\
+#	column_geo_point.cpp			\
+#	column_vector_bool.cpp
 
 libgrnxx_impl_column_includedir = ${includedir}/grnxx/impl/column
 libgrnxx_impl_column_include_HEADERS =		\
-	column_base.hpp
+	column.hpp				\
+	column_base.hpp				\
+	column_bool.hpp				\
+	column_float.hpp			\
+	column_geo_point.hpp			\
+	column_int.hpp				\
+	column_vector_bool.hpp			\
+	column_vector_float.hpp			\
+	column_vector_geo_point.hpp		\
+	column_vector_int.hpp			\
+	column_vector_text.hpp

  Added: lib/grnxx/impl/column/column.cpp (+114 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column.cpp    2014-10-07 13:33:14 +0900 (993d55b)
@@ -0,0 +1,114 @@
+#include "grnxx/impl/column/column.hpp"
+
+#include "grnxx/cursor.hpp"
+#include "grnxx/impl/db.hpp"
+#include "grnxx/impl/table.hpp"
+#include "grnxx/index.hpp"
+
+#include <set>
+
+namespace grnxx {
+namespace impl {
+
+template <typename T>
+bool Column<T>::set(Error *error, Int row_id, const Datum &datum) {
+  if (datum.type() != TypeTraits<T>::data_type()) {
+    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
+    return false;
+  }
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  // Note that a Bool object does not have its own address.
+  T old_value = get(row_id);
+  T new_value;
+  datum.force(&new_value);
+  // TODO: Note that NaN != NaN.
+  if (new_value != old_value) {
+    for (Int i = 0; i < num_indexes(); ++i) {
+      if (!indexes_[i]->insert(error, row_id, datum)) {
+        for (Int j = 0; j < i; ++i) {
+          indexes_[j]->remove(nullptr, row_id, datum);
+        }
+        return false;
+      }
+    }
+    for (Int i = 0; i < num_indexes(); ++i) {
+      indexes_[i]->remove(nullptr, row_id, old_value);
+    }
+  }
+  values_.set(row_id, new_value);
+  return true;
+}
+
+template <typename T>
+bool Column<T>::get(Error *error, Int row_id, Datum *datum) const {
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  *datum = values_[row_id];
+  return true;
+}
+
+template <typename T>
+unique_ptr<Column<T>> Column<T>::create(Error *error,
+                                        Table *table,
+                                        const StringCRef &name,
+                                        const ColumnOptions &options) {
+  unique_ptr<Column> column(new (nothrow) Column);
+  if (!column) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  if (!column->initialize_base(error, table, name,
+                               TypeTraits<T>::data_type(), options)) {
+    return nullptr;
+  }
+  if (!column->values_.resize(error, table->max_row_id() + 1,
+                              TypeTraits<T>::default_value())) {
+    return nullptr;
+  }
+  return column;
+}
+
+template <typename T>
+Column<T>::~Column() {}
+
+template <typename T>
+bool Column<T>::set_default_value(Error *error, Int row_id) {
+  if (row_id >= values_.size()) {
+    if (!values_.resize(error, row_id + 1, TypeTraits<T>::default_value())) {
+      return false;
+    }
+  }
+  T value = TypeTraits<T>::default_value();
+  for (Int i = 0; i < num_indexes(); ++i) {
+    if (!indexes_[i]->insert(error, row_id, value)) {
+      for (Int j = 0; j < i; ++j) {
+        indexes_[j]->remove(nullptr, row_id, value);
+      }
+      return false;
+    }
+  }
+  values_.set(row_id, value);
+  return true;
+}
+
+template <typename T>
+void Column<T>::unset(Int row_id) {
+  for (Int i = 0; i < num_indexes(); ++i) {
+    indexes_[i]->remove(nullptr, row_id, get(row_id));
+  }
+  values_.set(row_id, TypeTraits<T>::default_value());
+}
+
+template <typename T>
+Column<T>::Column() : ColumnBase(), values_() {}
+
+template class Column<Bool>;
+template class Column<Float>;
+template class Column<GeoPoint>;
+template class Column<Vector<Bool>>;
+
+}  // namespace impl
+}  // namespace grnxx

  Added: lib/grnxx/impl/column/column.hpp (+61 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column.hpp    2014-10-07 13:33:14 +0900 (a440562)
@@ -0,0 +1,61 @@
+#ifndef GRNXX_IMPL_COLUMN_COLUMN_HPP
+#define GRNXX_IMPL_COLUMN_COLUMN_HPP
+
+#include "grnxx/impl/column/column_base.hpp"
+
+namespace grnxx {
+namespace impl {
+
+//template <typename T> class Column;
+
+template <typename T>
+class Column : public ColumnBase {
+ public:
+  // -- Public API (grnxx/column.hpp) --
+
+  bool set(Error *error, Int row_id, const Datum &datum);
+  bool get(Error *error, Int row_id, Datum *datum) const;
+
+  // -- Internal API (grnxx/impl/column/column_base.hpp) --
+
+  ~Column();
+
+  bool set_default_value(Error *error, Int row_id);
+  void unset(Int row_id);
+
+  // -- Internal API --
+
+  // Create a new column.
+  //
+  // Returns a pointer to the column on success.
+  // On failure, returns nullptr and stores error information into "*error" if
+  // "error" != nullptr.
+  static unique_ptr<Column> create(Error *error,
+                                   Table *table,
+                                   const StringCRef &name,
+                                   const ColumnOptions &options);
+
+  // Return a value identified by "row_id".
+  //
+  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
+  T get(Int row_id) const {
+    return values_[row_id];
+  }
+
+  // Read values.
+  void read(ArrayCRef<Record> records, ArrayRef<T> values) const {
+    for (Int i = 0; i < records.size(); ++i) {
+      values.set(i, get(records.get_row_id(i)));
+    }
+  }
+
+ private:
+  Array<T> values_;
+
+  Column();
+};
+
+}  // namespace impl
+}  // namespace grnxx
+
+#endif  // GRNXX_IMPL_COLUMN_COLUMN_HPP

  Modified: lib/grnxx/impl/column/column_base.cpp (+51 -42)
===================================================================
--- lib/grnxx/impl/column/column_base.cpp    2014-10-07 11:30:11 +0900 (2f11e61)
+++ lib/grnxx/impl/column/column_base.cpp    2014-10-07 13:33:14 +0900 (6f2817e)
@@ -1,7 +1,16 @@
 #include "grnxx/impl/column/column_base.hpp"
 
-#include "grnxx/column_impl.hpp"
-#include "grnxx/cursor.hpp"
+#include "grnxx/impl/column/column.hpp"
+#include "grnxx/impl/column/column_bool.hpp"
+#include "grnxx/impl/column/column_int.hpp"
+#include "grnxx/impl/column/column_float.hpp"
+#include "grnxx/impl/column/column_geo_point.hpp"
+#include "grnxx/impl/column/column_text.hpp"
+#include "grnxx/impl/column/column_vector_bool.hpp"
+#include "grnxx/impl/column/column_vector_int.hpp"
+#include "grnxx/impl/column/column_vector_float.hpp"
+#include "grnxx/impl/column/column_vector_geo_point.hpp"
+#include "grnxx/impl/column/column_vector_text.hpp"
 #include "grnxx/impl/db.hpp"
 #include "grnxx/impl/table.hpp"
 #include "grnxx/index.hpp"
@@ -140,9 +149,6 @@ Int ColumnBase::find_one(const Datum &) const {
   return NULL_ROW_ID;
 }
 
-void ColumnBase::clear_references(Int) {
-}
-
 unique_ptr<ColumnBase> ColumnBase::create(Error *error,
                                           Table *table,
                                           const StringCRef &name,
@@ -150,34 +156,34 @@ unique_ptr<ColumnBase> ColumnBase::create(Error *error,
                                           const ColumnOptions &options) {
   switch (data_type) {
     case BOOL_DATA: {
-      return ColumnImpl<Bool>::create(error, table, name, options);
+      return impl::Column<Bool>::create(error, table, name, options);
     }
     case INT_DATA: {
-      return ColumnImpl<Int>::create(error, table, name, options);
+      return impl::Column<Int>::create(error, table, name, options);
     }
     case FLOAT_DATA: {
-      return ColumnImpl<Float>::create(error, table, name, options);
+      return impl::Column<Float>::create(error, table, name, options);
     }
     case GEO_POINT_DATA: {
-      return ColumnImpl<GeoPoint>::create(error, table, name, options);
+      return impl::Column<GeoPoint>::create(error, table, name, options);
     }
     case TEXT_DATA: {
-      return ColumnImpl<Text>::create(error, table, name, options);
+      return impl::Column<Text>::create(error, table, name, options);
     }
     case BOOL_VECTOR_DATA: {
-      return ColumnImpl<Vector<Bool>>::create(error, table, name, options);
+      return impl::Column<Vector<Bool>>::create(error, table, name, options);
     }
     case INT_VECTOR_DATA: {
-      return ColumnImpl<Vector<Int>>::create(error, table, name, options);
+      return impl::Column<Vector<Int>>::create(error, table, name, options);
     }
     case FLOAT_VECTOR_DATA: {
-      return ColumnImpl<Vector<Float>>::create(error, table, name, options);
+      return impl::Column<Vector<Float>>::create(error, table, name, options);
     }
     case GEO_POINT_VECTOR_DATA: {
-      return ColumnImpl<Vector<GeoPoint>>::create(error, table, name, options);
+      return impl::Column<Vector<GeoPoint>>::create(error, table, name, options);
     }
     case TEXT_VECTOR_DATA: {
-      return ColumnImpl<Vector<Text>>::create(error, table, name, options);
+      return impl::Column<Vector<Text>>::create(error, table, name, options);
     }
     default: {
       // TODO: Other data types are not supported yet.
@@ -187,12 +193,40 @@ unique_ptr<ColumnBase> ColumnBase::create(Error *error,
   }
 }
 
+bool ColumnBase::rename(Error *error, const StringCRef &new_name) {
+  return name_.assign(error, new_name);
+}
+
+bool ColumnBase::is_removable() {
+  // TODO: Reference column is not supported yet.
+  return true;
+}
+
+bool ColumnBase::set_key_attribute(Error *error) {
+  GRNXX_ERROR_SET(error, INVALID_OPERATION, "This type does not support Key");
+  return false;
+}
+
+bool ColumnBase::unset_key_attribute(Error *error) {
+  GRNXX_ERROR_SET(error, INVALID_OPERATION, "This type does not support Key");
+  return false;
+}
+
+bool ColumnBase::set_initial_key(Error *error, Int, const Datum &) {
+  // TODO: Key column is not supported yet.
+  GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not suported yet");
+  return false;
+}
+
+void ColumnBase::clear_references(Int) {
+}
+
 bool ColumnBase::initialize_base(Error *error,
                                  Table *table,
                                  const StringCRef &name,
                                  DataType data_type,
                                  const ColumnOptions &options) {
-  table_ = static_cast<impl::Table *>(table);
+  table_ = table;
   if (!name_.assign(error, name)) {
     return false;
   }
@@ -203,37 +237,12 @@ bool ColumnBase::initialize_base(Error *error,
       if (!ref_table) {
         return false;
       }
-      ref_table_ = static_cast<impl::Table *>(ref_table);
+      ref_table_ = ref_table;
     }
   }
   return true;
 }
 
-bool ColumnBase::rename(Error *error, const StringCRef &new_name) {
-  return name_.assign(error, new_name);
-}
-
-bool ColumnBase::is_removable() {
-  // TODO: Reference column is not supported yet.
-  return true;
-}
-
-bool ColumnBase::set_initial_key(Error *error, Int, const Datum &) {
-  // TODO: Key column is not supported yet.
-  GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not suported yet");
-  return false;
-}
-
-bool ColumnBase::set_key_attribute(Error *error) {
-  GRNXX_ERROR_SET(error, INVALID_OPERATION, "This type does not support Key");
-  return false;
-}
-
-bool ColumnBase::unset_key_attribute(Error *error) {
-  GRNXX_ERROR_SET(error, INVALID_OPERATION, "This type does not support Key");
-  return false;
-}
-
 Index *ColumnBase::find_index_with_id(Error *error,
                                       const StringCRef &name,
                                       Int *index_id) const {

  Modified: lib/grnxx/impl/column/column_base.hpp (+14 -28)
===================================================================
--- lib/grnxx/impl/column/column_base.hpp    2014-10-07 11:30:11 +0900 (db2ca3d)
+++ lib/grnxx/impl/column/column_base.hpp    2014-10-07 13:33:14 +0900 (ad32fdb)
@@ -53,6 +53,12 @@ class ColumnBase : public ColumnInterface {
   }
   Index *find_index(Error *error, const StringCRef &name) const;
 
+  bool set(Error *error, Int row_id, const Datum &datum);
+  bool get(Error *error, Int row_id, Datum *datum) const;
+
+  bool contains(const Datum &datum) const;
+  Int find_one(const Datum &datum) const;
+
   // -- Internal API --
 
   // Create a new column.
@@ -77,34 +83,6 @@ class ColumnBase : public ColumnInterface {
     return ref_table_;
   }
 
-  // Set a value.
-  //
-  // On success, returns true.
-  // On failure, returns false and stores error information into "*error" if
-  // "error" != nullptr.
-  virtual bool set(Error *error, Int row_id, const Datum &datum);
-
-  // Get a value.
-  //
-  // Stores a value identified by "row_id" into "*datum".
-  //
-  // On success, returns true.
-  // On failure, returns false and stores error information into "*error" if
-  // "error" != nullptr.
-  virtual bool get(Error *error, Int row_id, Datum *datum) const;
-
-  // Check if "datum" exists in the column or not.
-  //
-  // If exists, returns true.
-  // Otherwise, returns false.
-  virtual bool contains(const Datum &datum) const;
-
-  // Find "datum" in the column.
-  //
-  // If found, returns the row ID of the matched value.
-  // Otherwise, returns NULL_ROW_ID.
-  virtual Int find_one(const Datum &datum) const;
-
   // Change the column name.
   //
   // On success, returns true.
@@ -116,8 +94,16 @@ class ColumnBase : public ColumnInterface {
   bool is_removable();
 
   // Set the key attribute.
+  //
+  // On success, returns true.
+  // On failure, returns false and stores error information into "*error" if
+  // "error" != nullptr.
   virtual bool set_key_attribute(Error *error);
   // Unset the key attribute.
+  //
+  // On success, returns true.
+  // On failure, returns false and stores error information into "*error" if
+  // "error" != nullptr.
   virtual bool unset_key_attribute(Error *error);
 
   // Set the initial key.

  Added: lib/grnxx/impl/column/column_bool.hpp (+14 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_bool.hpp    2014-10-07 13:33:14 +0900 (0a36846)
@@ -0,0 +1,14 @@
+#ifndef GRNXX_IMPL_COLUMN_COLUMN_BOOL_HPP
+#define GRNXX_IMPL_COLUMN_COLUMN_BOOL_HPP
+
+#include "grnxx/impl/column/column.hpp"
+
+namespace grnxx {
+namespace impl {
+
+// TODO
+
+}  // namespace impl
+}  // namespace grnxx
+
+#endif  // GRNXX_IMPL_COLUMN_COLUMN_BOOL_HPP

  Added: lib/grnxx/impl/column/column_float.hpp (+14 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_float.hpp    2014-10-07 13:33:14 +0900 (9fb732c)
@@ -0,0 +1,14 @@
+#ifndef GRNXX_IMPL_COLUMN_COLUMN_FLOAT_HPP
+#define GRNXX_IMPL_COLUMN_COLUMN_FLOAT_HPP
+
+#include "grnxx/impl/column/column.hpp"
+
+namespace grnxx {
+namespace impl {
+
+// TODO
+
+}  // namespace impl
+}  // namespace grnxx
+
+#endif  // GRNXX_IMPL_COLUMN_COLUMN_FLOAT_HPP

  Added: lib/grnxx/impl/column/column_geo_point.hpp (+14 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_geo_point.hpp    2014-10-07 13:33:14 +0900 (98d7a58)
@@ -0,0 +1,14 @@
+#ifndef GRNXX_IMPL_COLUMN_COLUMN_GEO_POINT_HPP
+#define GRNXX_IMPL_COLUMN_COLUMN_GEO_POINT_HPP
+
+#include "grnxx/impl/column/column.hpp"
+
+namespace grnxx {
+namespace impl {
+
+// TODO
+
+}  // namespace impl
+}  // namespace grnxx
+
+#endif  // GRNXX_IMPL_COLUMN_COLUMN_GEO_POINT_HPP

  Added: lib/grnxx/impl/column/column_int.cpp (+279 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_int.cpp    2014-10-07 13:33:14 +0900 (bb80bfa)
@@ -0,0 +1,279 @@
+#include "grnxx/impl/column/column_int.hpp"
+
+#include "grnxx/cursor.hpp"
+#include "grnxx/impl/db.hpp"
+#include "grnxx/impl/table.hpp"
+#include "grnxx/index.hpp"
+
+#include <unordered_set>
+
+namespace grnxx {
+namespace impl {
+
+bool Column<Int>::set(Error *error, Int row_id, const Datum &datum) {
+  if (datum.type() != INT_DATA) {
+    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
+    return false;
+  }
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  if (ref_table_) {
+    if (!ref_table_->test_row(error, datum.force_int())) {
+      return false;
+    }
+  }
+  Int old_value = get(row_id);
+  Int new_value = datum.force_int();
+  if (new_value != old_value) {
+    if (has_key_attribute_ && contains(datum)) {
+      GRNXX_ERROR_SET(error, ALREADY_EXISTS, "Key duplicate");
+      return false;
+    }
+    for (Int i = 0; i < num_indexes(); ++i) {
+      if (!indexes_[i]->insert(error, row_id, datum)) {
+        for (Int j = 0; j < i; ++i) {
+          indexes_[j]->remove(nullptr, row_id, datum);
+        }
+        return false;
+      }
+    }
+    for (Int i = 0; i < num_indexes(); ++i) {
+      indexes_[i]->remove(nullptr, row_id, old_value);
+    }
+  }
+  values_.set(row_id, new_value);
+  return true;
+}
+
+bool Column<Int>::get(Error *error, Int row_id, Datum *datum) const {
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  *datum = values_[row_id];
+  return true;
+}
+
+unique_ptr<Column<Int>> Column<Int>::create(
+    Error *error,
+    Table *table,
+    const StringCRef &name,
+    const ColumnOptions &options) {
+  unique_ptr<Column> column(new (nothrow) Column);
+  if (!column) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  if (!column->initialize_base(error, table, name, INT_DATA, options)) {
+    return nullptr;
+  }
+  if (!column->values_.resize(error, table->max_row_id() + 1,
+                              TypeTraits<Int>::default_value())) {
+    return nullptr;
+  }
+  if (column->ref_table()) {
+    if (!column->ref_table_->append_referrer_column(error, column.get())) {
+      return nullptr;
+    }
+  }
+  return column;
+}
+
+Column<Int>::~Column() {}
+
+bool Column<Int>::set_key_attribute(Error *error) {
+  if (has_key_attribute_) {
+    GRNXX_ERROR_SET(error, INVALID_OPERATION,
+                    "This column is a key column");
+    return false;
+  }
+  // TODO: An index should be used if possible.
+  try {
+    std::unordered_set<Int> set;
+    // TODO: Functor-based inline callback may be better in this case,
+    //       because it does not require memory allocation.
+    auto cursor = table_->create_cursor(nullptr);
+    if (!cursor) {
+      return false;
+    }
+    Array<Record> records;
+    for ( ; ; ) {
+      auto result = cursor->read(nullptr, 1024, &records);
+      if (!result.is_ok) {
+        return false;
+      } else {
+        break;
+      }
+      for (Int i = 0; i < result.count; ++i) {
+        if (!set.insert(values_[records.get_row_id(i)]).second) {
+          GRNXX_ERROR_SET(error, INVALID_OPERATION, "Key duplicate");
+          return false;
+        }
+      }
+      records.clear();
+    }
+  } catch (...) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return false;
+  }
+  has_key_attribute_ = true;
+  return true;
+}
+
+bool Column<Int>::unset_key_attribute(Error *error) {
+  if (!has_key_attribute_) {
+    GRNXX_ERROR_SET(error, INVALID_OPERATION,
+                    "This column is not a key column");
+    return false;
+  }
+  has_key_attribute_ = false;
+  return true;
+}
+
+bool Column<Int>::set_initial_key(Error *error,
+                                  Int row_id,
+                                  const Datum &key) {
+  if (!has_key_attribute_) {
+    GRNXX_ERROR_SET(error, INVALID_OPERATION,
+                    "This column is not a key column");
+    return false;
+  }
+  if (has_key_attribute_ && contains(key)) {
+    GRNXX_ERROR_SET(error, ALREADY_EXISTS, "Key duplicate");
+    return false;
+  }
+  if (row_id >= values_.size()) {
+    if (!values_.resize(error, row_id + 1, TypeTraits<Int>::default_value())) {
+      return false;
+    }
+  }
+  Int value = key.force_int();
+  for (Int i = 0; i < num_indexes(); ++i) {
+    if (!indexes_[i]->insert(error, row_id, value)) {
+      for (Int j = 0; j < i; ++j) {
+        indexes_[j]->remove(nullptr, row_id, value);
+      }
+      return false;
+    }
+  }
+  values_.set(row_id, value);
+  return true;
+}
+
+bool Column<Int>::set_default_value(Error *error, Int row_id) {
+  if (has_key_attribute_) {
+    GRNXX_ERROR_SET(error, INVALID_OPERATION,
+                    "This column is a key column");
+    return false;
+  }
+  if (row_id >= values_.size()) {
+    if (!values_.resize(error, row_id + 1, TypeTraits<Int>::default_value())) {
+      return false;
+    }
+  }
+  Int value = TypeTraits<Int>::default_value();
+  for (Int i = 0; i < num_indexes(); ++i) {
+    if (!indexes_[i]->insert(error, row_id, value)) {
+      for (Int j = 0; j < i; ++j) {
+        indexes_[j]->remove(nullptr, row_id, value);
+      }
+      return false;
+    }
+  }
+  values_.set(row_id, value);
+  return true;
+}
+
+void Column<Int>::unset(Int row_id) {
+  for (Int i = 0; i < num_indexes(); ++i) {
+    indexes_[i]->remove(nullptr, row_id, get(row_id));
+  }
+  values_.set(row_id, TypeTraits<Int>::default_value());
+}
+
+Int Column<Int>::find_one(const Datum &datum) const {
+  // TODO: Cursor should not be used because it takes time.
+  //       Also, cursor operations can fail due to memory allocation.
+  Int value = datum.force_int();
+  if (indexes_.size() != 0) {
+    return indexes_[0]->find_one(datum);
+  } else {
+    // TODO: A full scan takes time.
+    //       An index should be required for a key column.
+
+    // TODO: Functor-based inline callback may be better in this case,
+    //       because it does not require memory allocation.
+
+    // Scan the column to find "value".
+    auto cursor = table_->create_cursor(nullptr);
+    if (!cursor) {
+      return NULL_ROW_ID;
+    }
+    Array<Record> records;
+    for ( ; ; ) {
+      auto result = cursor->read(nullptr, 1024, &records);
+      if (!result.is_ok || result.count == 0) {
+        return NULL_ROW_ID;
+      }
+      for (Int i = 0; i < result.count; ++i) {
+        if (values_[records.get_row_id(i)] == value) {
+          return records.get_row_id(i);
+        }
+      }
+      records.clear();
+    }
+  }
+  return NULL_ROW_ID;
+}
+
+void Column<Int>::clear_references(Int row_id) {
+  // TODO: Cursor should not be used to avoid errors.
+  if (indexes_.size() != 0) {
+    auto cursor = indexes_[0]->find(nullptr, Int(0));
+    if (!cursor) {
+      // Error.
+      return;
+    }
+    Array<Record> records;
+    for ( ; ; ) {
+      auto result = cursor->read(nullptr, 1024, &records);
+      if (!result.is_ok) {
+        // Error.
+        return;
+      } else if (result.count == 0) {
+        return;
+      }
+      for (Int i = 0; i < records.size(); ++i) {
+        set(nullptr, row_id, NULL_ROW_ID);
+      }
+      records.clear();
+    }
+  } else {
+    auto cursor = table_->create_cursor(nullptr);
+    if (!cursor) {
+      // Error.
+      return;
+    }
+    Array<Record> records;
+    for ( ; ; ) {
+      auto result = cursor->read(nullptr, 1024, &records);
+      if (!result.is_ok) {
+        // Error.
+        return;
+      } else if (result.count == 0) {
+        return;
+      }
+      for (Int i = 0; i < records.size(); ++i) {
+        if (values_[records.get_row_id(i)] == row_id) {
+          values_[records.get_row_id(i)] = NULL_ROW_ID;
+        }
+      }
+      records.clear();
+    }
+  }
+}
+
+Column<Int>::Column() : ColumnBase(), values_() {}
+
+}  // namespace impl
+}  // namespace grnxx

  Added: lib/grnxx/impl/column/column_int.hpp (+65 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_int.hpp    2014-10-07 13:33:14 +0900 (7ca0b23)
@@ -0,0 +1,65 @@
+#ifndef GRNXX_IMPL_COLUMN_COLUMN_INT_HPP
+#define GRNXX_IMPL_COLUMN_COLUMN_INT_HPP
+
+#include "grnxx/impl/column/column.hpp"
+
+namespace grnxx {
+namespace impl {
+
+template <>
+class Column<Int> : public ColumnBase {
+ public:
+  // -- Public API --
+
+  bool set(Error *error, Int row_id, const Datum &datum);
+  bool get(Error *error, Int row_id, Datum *datum) const;
+
+  // -- Internal API --
+
+  // Create a new column.
+  //
+  // Returns a pointer to the column on success.
+  // On failure, returns nullptr and stores error information into "*error" if
+  // "error" != nullptr.
+  static unique_ptr<Column> create(Error *error,
+                                   Table *table,
+                                   const StringCRef &name,
+                                   const ColumnOptions &options);
+
+  ~Column();
+
+  bool set_key_attribute(Error *error);
+  bool unset_key_attribute(Error *error);
+
+  bool set_initial_key(Error *error, Int row_id, const Datum &key);
+  bool set_default_value(Error *error, Int row_id);
+  void unset(Int row_id);
+
+  Int find_one(const Datum &datum) const;
+
+  void clear_references(Int row_id);
+
+  // Return a value identified by "row_id".
+  //
+  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
+  Int get(Int row_id) const {
+    return values_[row_id];
+  }
+
+  // Read values.
+  void read(ArrayCRef<Record> records, ArrayRef<Int> values) const {
+    for (Int i = 0; i < records.size(); ++i) {
+      values.set(i, get(records.get_row_id(i)));
+    }
+  }
+
+ private:
+  Array<Int> values_;
+
+  Column();
+};
+
+}  // namespace impl
+}  // namespace grnxx
+
+#endif  // GRNXX_IMPL_COLUMN_COLUMN_INT_HPP

  Added: lib/grnxx/impl/column/column_text.cpp (+268 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_text.cpp    2014-10-07 13:33:14 +0900 (2db612a)
@@ -0,0 +1,268 @@
+#include "grnxx/impl/column/column_text.hpp"
+
+#include "grnxx/cursor.hpp"
+#include "grnxx/impl/db.hpp"
+#include "grnxx/impl/table.hpp"
+#include "grnxx/index.hpp"
+
+#include <set>
+
+namespace grnxx {
+namespace impl {
+
+bool Column<Text>::set(Error *error, Int row_id, const Datum &datum) {
+  if (datum.type() != TEXT_DATA) {
+    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
+    return false;
+  }
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  Text old_value = get(row_id);
+  Text new_value = datum.force_text();
+  if (new_value != old_value) {
+    if (has_key_attribute_ && contains(datum)) {
+      GRNXX_ERROR_SET(error, ALREADY_EXISTS, "Key duplicate");
+      return false;
+    }
+    for (Int i = 0; i < num_indexes(); ++i) {
+      if (!indexes_[i]->insert(error, row_id, datum)) {
+        for (Int j = 0; j < i; ++i) {
+          indexes_[j]->remove(nullptr, row_id, datum);
+        }
+        return false;
+      }
+    }
+    Int offset = bodies_.size();
+    UInt new_header;
+    if (new_value.size() < 0xFFFF) {
+      if (!bodies_.resize(error, offset + new_value.size())) {
+        return false;
+      }
+      std::memcpy(&bodies_[offset], new_value.data(), new_value.size());
+      new_header = (offset << 16) | new_value.size();
+    } else {
+      // The size of a long text is stored in front of the body.
+      if ((offset % sizeof(Int)) != 0) {
+        offset += sizeof(Int) - (offset % sizeof(Int));
+      }
+      if (!bodies_.resize(error, offset + sizeof(Int) + new_value.size())) {
+        return false;
+      }
+      *reinterpret_cast<Int *>(&bodies_[offset]) = new_value.size();
+      std::memcpy(&bodies_[offset + sizeof(Int)],
+                  new_value.data(), new_value.size());
+      new_header = (offset << 16) | 0xFFFF;
+    }
+    for (Int i = 0; i < num_indexes(); ++i) {
+      indexes_[i]->remove(nullptr, row_id, old_value);
+    }
+    headers_[row_id] = new_header;
+  }
+  return true;
+}
+
+bool Column<Text>::get(Error *error, Int row_id, Datum *datum) const {
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  *datum = get(row_id);
+  return true;
+}
+
+unique_ptr<Column<Text>> Column<Text>::create(
+    Error *error,
+    Table *table,
+    const StringCRef &name,
+    const ColumnOptions &options) {
+  unique_ptr<Column> column(new (nothrow) Column);
+  if (!column) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  if (!column->initialize_base(error, table, name, TEXT_DATA, options)) {
+    return nullptr;
+  }
+  if (!column->headers_.resize(error, table->max_row_id() + 1, 0)) {
+    return nullptr;
+  }
+  return column;
+}
+
+Column<Text>::~Column() {}
+
+bool Column<Text>::set_key_attribute(Error *error) {
+  if (has_key_attribute_) {
+    GRNXX_ERROR_SET(error, INVALID_OPERATION,
+                    "This column is a key column");
+    return false;
+  }
+  // TODO: An index should be used if possible.
+  try {
+    std::set<Text> set;
+    // TODO: Functor-based inline callback may be better in this case,
+    //       because it does not require memory allocation.
+    auto cursor = table_->create_cursor(nullptr);
+    if (!cursor) {
+      return false;
+    }
+    Array<Record> records;
+    for ( ; ; ) {
+      auto result = cursor->read(nullptr, 1024, &records);
+      if (!result.is_ok) {
+        return false;
+      } else {
+        break;
+      }
+      for (Int i = 0; i < result.count; ++i) {
+        if (!set.insert(get(records.get_row_id(i))).second) {
+          GRNXX_ERROR_SET(error, INVALID_OPERATION, "Key duplicate");
+          return false;
+        }
+      }
+      records.clear();
+    }
+  } catch (...) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return false;
+  }
+  has_key_attribute_ = true;
+  return true;
+}
+
+bool Column<Text>::unset_key_attribute(Error *error) {
+  if (!has_key_attribute_) {
+    GRNXX_ERROR_SET(error, INVALID_OPERATION,
+                    "This column is not a key column");
+    return false;
+  }
+  has_key_attribute_ = false;
+  return true;
+}
+
+bool Column<Text>::set_initial_key(Error *error,
+    Int row_id,
+    const Datum &key) {
+  if (!has_key_attribute_) {
+    GRNXX_ERROR_SET(error, INVALID_OPERATION,
+                    "This column is not a key column");
+    return false;
+  }
+  if (has_key_attribute_ && contains(key)) {
+    GRNXX_ERROR_SET(error, ALREADY_EXISTS, "Key duplicate");
+    return false;
+  }
+  if (row_id >= headers_.size()) {
+    if (!headers_.resize(error, row_id + 1, 0)) {
+      return false;
+    }
+  }
+  Text value = key.force_text();
+  for (Int i = 0; i < num_indexes(); ++i) {
+    if (!indexes_[i]->insert(error, row_id, value)) {
+      for (Int j = 0; j < i; ++j) {
+        indexes_[j]->remove(nullptr, row_id, value);
+      }
+      return false;
+    }
+  }
+  Int offset = bodies_.size();
+  UInt header;
+  if (value.size() < 0xFFFF) {
+    if (!bodies_.resize(error, offset + value.size())) {
+      return false;
+    }
+    std::memcpy(&bodies_[offset], value.data(), value.size());
+    header = (offset << 16) | value.size();
+  } else {
+    // The size of a long text is stored in front of the body.
+    if ((offset % sizeof(Int)) != 0) {
+      offset += sizeof(Int) - (offset % sizeof(Int));
+    }
+    if (!bodies_.resize(error, offset + sizeof(Int) + value.size())) {
+      return false;
+    }
+    *reinterpret_cast<Int *>(&bodies_[offset]) = value.size();
+    std::memcpy(&bodies_[offset + sizeof(Int)], value.data(), value.size());
+    header = (offset << 16) | 0xFFFF;
+  }
+  headers_[row_id] = header;
+  return true;
+}
+
+bool Column<Text>::set_default_value(Error *error, Int row_id) {
+  if (has_key_attribute_) {
+    GRNXX_ERROR_SET(error, INVALID_OPERATION,
+                    "This column is a key column");
+    return false;
+  }
+  if (row_id >= headers_.size()) {
+    if (!headers_.resize(error, row_id + 1)) {
+      return false;
+    }
+  }
+  Text value = TypeTraits<Text>::default_value();
+  for (Int i = 0; i < num_indexes(); ++i) {
+    if (!indexes_[i]->insert(error, row_id, value)) {
+      for (Int j = 0; j < i; ++j) {
+        indexes_[j]->remove(nullptr, row_id, value);
+      }
+      return false;
+    }
+  }
+  headers_[row_id] = 0;
+  return true;
+}
+
+void Column<Text>::unset(Int row_id) {
+  for (Int i = 0; i < num_indexes(); ++i) {
+    indexes_[i]->remove(nullptr, row_id, get(row_id));
+  }
+  headers_[row_id] = 0;
+}
+
+Int Column<Text>::find_one(const Datum &datum) const {
+  // TODO: Cursor should not be used because it takes time.
+  // Also, cursor operations can fail due to memory allocation.
+  Text value = datum.force_text();
+  if (indexes_.size() != 0) {
+    auto cursor = indexes_[0]->find(nullptr, value);
+    Array<Record> records;
+    auto result = cursor->read(nullptr, 1, &records);
+    if (!result.is_ok || (result.count == 0)) {
+      return NULL_ROW_ID;
+    }
+    return true;
+  } else {
+    // TODO: A full scan takes time.
+    // An index should be required for a key column.
+
+    // TODO: Functor-based inline callback may be better in this case,
+    // because it does not require memory allocation.
+
+    // Scan the column to find "value".
+    auto cursor = table_->create_cursor(nullptr);
+    if (!cursor) {
+      return NULL_ROW_ID;
+    }
+    Array<Record> records;
+    for ( ; ; ) {
+      auto result = cursor->read(nullptr, 1024, &records);
+      if (!result.is_ok || result.count == 0) {
+        return NULL_ROW_ID;
+      }
+      for (Int i = 0; i < result.count; ++i) {
+        if (get(records.get_row_id(i)) == value) {
+          return records.get_row_id(i);
+        }
+      }
+      records.clear();
+    }
+  }
+  return NULL_ROW_ID;
+}
+
+Column<Text>::Column() : ColumnBase(), headers_(), bodies_() {}
+
+}  // namespace impl
+}  // namespace grnxx

  Added: lib/grnxx/impl/column/column_text.hpp (+74 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_text.hpp    2014-10-07 13:33:14 +0900 (493a5ed)
@@ -0,0 +1,74 @@
+#ifndef GRNXX_IMPL_COLUMN_COLUMN_TEXT_HPP
+#define GRNXX_IMPL_COLUMN_COLUMN_TEXT_HPP
+
+#include "grnxx/impl/column/column.hpp"
+
+namespace grnxx {
+namespace impl {
+
+template <>
+class Column<Text> : public impl::ColumnBase {
+ public:
+  // -- Public API --
+
+  bool set(Error *error, Int row_id, const Datum &datum);
+  bool get(Error *error, Int row_id, Datum *datum) const;
+
+  // -- Internal API --
+
+  // Create a new column.
+  //
+  // Returns a pointer to the column on success.
+  // On failure, returns nullptr and stores error information into "*error" if
+  // "error" != nullptr.
+  static unique_ptr<Column> create(Error *error,
+                                   Table *table,
+                                   const StringCRef &name,
+                                   const ColumnOptions &options);
+
+  ~Column();
+
+  bool set_key_attribute(Error *error);
+  bool unset_key_attribute(Error *error);
+
+  bool set_initial_key(Error *error, Int row_id, const Datum &key);
+  bool set_default_value(Error *error, Int row_id);
+  void unset(Int row_id);
+  Int find_one(const Datum &datum) const;
+
+  // Return a value identified by "row_id".
+  //
+  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
+  Text get(Int row_id) const {
+    Int size = static_cast<Int>(headers_[row_id] & 0xFFFF);
+    if (size == 0) {
+      return Text("", 0);
+    }
+    Int offset = static_cast<Int>(headers_[row_id] >> 16);
+    if (size < 0xFFFF) {
+      return Text(&bodies_[offset], size);
+    } else {
+      // The size of a long text is stored in front of the body.
+      size = *reinterpret_cast<const Int *>(&bodies_[offset]);
+      return StringCRef(&bodies_[offset + sizeof(Int)], size);
+    }
+  }
+
+  // Read values.
+  void read(ArrayCRef<Record> records, ArrayRef<Text> values) const {
+    for (Int i = 0; i < records.size(); ++i) {
+      values.set(i, get(records.get_row_id(i)));
+    }
+  }
+
+ private:
+  Array<UInt> headers_;
+  Array<char> bodies_;
+
+  Column();
+};
+
+}  // namespace impl
+}  // namespace grnxx
+
+#endif  // GRNXX_IMPL_COLUMN_COLUMN_TEXT_HPP

  Added: lib/grnxx/impl/column/column_vector_bool.hpp (+14 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_vector_bool.hpp    2014-10-07 13:33:14 +0900 (94fbb93)
@@ -0,0 +1,14 @@
+#ifndef GRNXX_IMPL_COLUMN_COLUMN_VECTOR_BOOL_HPP
+#define GRNXX_IMPL_COLUMN_COLUMN_VECTOR_BOOL_HPP
+
+#include "grnxx/impl/column/column.hpp"
+
+namespace grnxx {
+namespace impl {
+
+// TODO
+
+}  // namespace impl
+}  // namespace grnxx
+
+#endif  // GRNXX_IMPL_COLUMN_COLUMN_VECTOR_BOOL_HPP

  Added: lib/grnxx/impl/column/column_vector_float.cpp (+98 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_vector_float.cpp    2014-10-07 13:33:14 +0900 (ca6b184)
@@ -0,0 +1,98 @@
+#include "grnxx/impl/column/column_vector_float.hpp"
+
+#include "grnxx/cursor.hpp"
+#include "grnxx/impl/db.hpp"
+#include "grnxx/impl/table.hpp"
+
+namespace grnxx {
+namespace impl {
+
+
+bool Column<Vector<Float>>::set(Error *error, Int row_id, const Datum &datum) {
+  if (datum.type() != FLOAT_VECTOR_DATA) {
+    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
+    return false;
+  }
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  Vector<Float> value = datum.force_float_vector();
+  if (value.size() == 0) {
+    headers_[row_id] = 0;
+    return true;
+  }
+  Int offset = bodies_.size();
+  if (value.size() < 0xFFFF) {
+    if (!bodies_.resize(error, offset + value.size())) {
+      return false;
+    }
+    for (Int i = 0; i < value.size(); ++i) {
+      bodies_[offset + i] = value[i];
+    }
+    headers_[row_id] = (offset << 16) | value.size();
+  } else {
+    // The size of a long vector is stored in front of the body.
+    if (!bodies_.resize(error, offset + 1 + value.size())) {
+      return false;
+    }
+    Int size_for_copy = value.size();
+    std::memcpy(&bodies_[offset], &size_for_copy, sizeof(Int));
+    for (Int i = 0; i < value.size(); ++i) {
+      bodies_[offset + 1 + i] = value[i];
+    }
+    headers_[row_id] = (offset << 16) | 0xFFFF;
+  }
+  return true;
+}
+
+bool Column<Vector<Float>>::get(Error *error, Int row_id, Datum *datum) const {
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  *datum = get(row_id);
+  return true;
+}
+
+unique_ptr<Column<Vector<Float>>> Column<Vector<Float>>::create(
+    Error *error,
+    Table *table,
+    const StringCRef &name,
+    const ColumnOptions &options) {
+  unique_ptr<Column> column(new (nothrow) Column);
+  if (!column) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  if (!column->initialize_base(error, table, name,
+                               FLOAT_VECTOR_DATA, options)) {
+    return nullptr;
+  }
+  if (!column->headers_.resize(error, table->max_row_id() + 1, 0)) {
+    return nullptr;
+  }
+  return column;
+}
+
+Column<Vector<Float>>::~Column() {}
+
+bool Column<Vector<Float>>::set_default_value(Error *error, Int row_id) {
+  if (row_id >= headers_.size()) {
+    if (!headers_.resize(error, row_id + 1)) {
+      return false;
+    }
+  }
+  headers_[row_id] = 0;
+  return true;
+}
+
+void Column<Vector<Float>>::unset(Int row_id) {
+  headers_[row_id] = 0;
+}
+
+Column<Vector<Float>>::Column()
+    : ColumnBase(),
+      headers_(),
+      bodies_() {}
+
+}  // namespace impl
+}  // namespace grnxx

  Added: lib/grnxx/impl/column/column_vector_float.hpp (+69 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_vector_float.hpp    2014-10-07 13:33:14 +0900 (1e76db5)
@@ -0,0 +1,69 @@
+#ifndef GRNXX_IMPL_COLUMN_COLUMN_VECTOR_FLOAT_HPP
+#define GRNXX_IMPL_COLUMN_COLUMN_VECTOR_FLOAT_HPP
+
+#include "grnxx/impl/column/column.hpp"
+
+namespace grnxx {
+namespace impl {
+
+template <>
+class Column<Vector<Float>> : public ColumnBase {
+ public:
+  // -- Public API --
+
+  bool set(Error *error, Int row_id, const Datum &datum);
+  bool get(Error *error, Int row_id, Datum *datum) const;
+
+  // -- Internal API --
+
+  // Create a new column.
+  //
+  // Returns a pointer to the column on success.
+  // On failure, returns nullptr and stores error information into "*error" if
+  // "error" != nullptr.
+  static unique_ptr<Column> create(Error *error,
+                                   Table *table,
+                                   const StringCRef &name,
+                                   const ColumnOptions &options);
+
+  ~Column();
+
+  bool set_default_value(Error *error, Int row_id);
+  void unset(Int row_id);
+
+  // Return a value identified by "row_id".
+  //
+  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
+  Vector<Float> get(Int row_id) const {
+    Int size = static_cast<Int>(headers_[row_id] & 0xFFFF);
+    if (size == 0) {
+      return Vector<Float>(nullptr, 0);
+    }
+    Int offset = static_cast<Int>(headers_[row_id] >> 16);
+    if (size < 0xFFFF) {
+      return Vector<Float>(&bodies_[offset], size);
+    } else {
+      // The size of a long vector is stored in front of the body.
+      std::memcpy(&size, &bodies_[offset], sizeof(Int));
+      return Vector<Float>(&bodies_[offset + 1], size);
+    }
+  }
+
+  // Read values.
+  void read(ArrayCRef<Record> records, ArrayRef<Vector<Float>> values) const {
+    for (Int i = 0; i < records.size(); ++i) {
+      values.set(i, get(records.get_row_id(i)));
+    }
+  }
+
+ private:
+  Array<UInt> headers_;
+  Array<Float> bodies_;
+
+  Column();
+};
+
+}  // namespace impl
+}  // namespace grnxx
+
+#endif  // GRNXX_IMPL_COLUMN_COLUMN_VECTOR_FLOAT_HPP

  Added: lib/grnxx/impl/column/column_vector_geo_point.cpp (+100 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_vector_geo_point.cpp    2014-10-07 13:33:14 +0900 (3eaceaa)
@@ -0,0 +1,100 @@
+#include "grnxx/impl/column/column_vector_geo_point.hpp"
+
+#include "grnxx/cursor.hpp"
+#include "grnxx/impl/db.hpp"
+#include "grnxx/impl/table.hpp"
+
+namespace grnxx {
+namespace impl {
+
+bool Column<Vector<GeoPoint>>::set(Error *error, Int row_id,
+                                   const Datum &datum) {
+  if (datum.type() != GEO_POINT_VECTOR_DATA) {
+    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
+    return false;
+  }
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  Vector<GeoPoint> value = datum.force_geo_point_vector();
+  if (value.size() == 0) {
+    headers_[row_id] = 0;
+    return true;
+  }
+  Int offset = bodies_.size();
+  if (value.size() < 0xFFFF) {
+    if (!bodies_.resize(error, offset + value.size())) {
+      return false;
+    }
+    for (Int i = 0; i < value.size(); ++i) {
+      bodies_[offset + i] = value[i];
+    }
+    headers_[row_id] = (offset << 16) | value.size();
+  } else {
+    // The size of a long vector is stored in front of the body.
+    if (!bodies_.resize(error, offset + 1 + value.size())) {
+      return false;
+    }
+    Int size_for_copy = value.size();
+    std::memcpy(&bodies_[offset], &size_for_copy, sizeof(Int));
+    for (Int i = 0; i < value.size(); ++i) {
+      bodies_[offset + 1 + i] = value[i];
+    }
+    headers_[row_id] = (offset << 16) | 0xFFFF;
+  }
+  return true;
+}
+
+bool Column<Vector<GeoPoint>>::get(Error *error, Int row_id,
+                                   Datum *datum) const {
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  *datum = get(row_id);
+  return true;
+}
+
+unique_ptr<Column<Vector<GeoPoint>>> Column<Vector<GeoPoint>>::create(
+    Error *error,
+    Table *table,
+    const StringCRef &name,
+    const ColumnOptions &options) {
+  unique_ptr<Column> column(new (nothrow) Column);
+  if (!column) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  if (!column->initialize_base(error, table, name,
+                               GEO_POINT_VECTOR_DATA, options)) {
+    return nullptr;
+  }
+  if (!column->headers_.resize(error, table->max_row_id() + 1, 0)) {
+    return nullptr;
+  }
+  return column;
+}
+
+Column<Vector<GeoPoint>>::~Column() {}
+
+bool Column<Vector<GeoPoint>>::set_default_value(Error *error,
+                                                     Int row_id) {
+  if (row_id >= headers_.size()) {
+    if (!headers_.resize(error, row_id + 1)) {
+      return false;
+    }
+  }
+  headers_[row_id] = 0;
+  return true;
+}
+
+void Column<Vector<GeoPoint>>::unset(Int row_id) {
+  headers_[row_id] = 0;
+}
+
+Column<Vector<GeoPoint>>::Column()
+    : ColumnBase(),
+      headers_(),
+      bodies_() {}
+
+}  // namespace impl
+}  // namespace grnxx

  Added: lib/grnxx/impl/column/column_vector_geo_point.hpp (+71 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_vector_geo_point.hpp    2014-10-07 13:33:14 +0900 (3911e4d)
@@ -0,0 +1,71 @@
+#ifndef GRNXX_IMPL_COLUMN_COLUMN_VECTOR_GEO_POINT_HPP
+#define GRNXX_IMPL_COLUMN_COLUMN_VECTOR_GEO_POINT_HPP
+
+#include "grnxx/impl/column/column.hpp"
+
+namespace grnxx {
+namespace impl {
+
+// TODO
+template <>
+class Column<Vector<GeoPoint>> : public ColumnBase {
+ public:
+  // -- Public API --
+
+  bool set(Error *error, Int row_id, const Datum &datum);
+  bool get(Error *error, Int row_id, Datum *datum) const;
+
+  // -- Internal API --
+
+  // Create a new column.
+  //
+  // Returns a pointer to the column on success.
+  // On failure, returns nullptr and stores error information into "*error" if
+  // "error" != nullptr.
+  static unique_ptr<Column> create(Error *error,
+                                   Table *table,
+                                   const StringCRef &name,
+                                   const ColumnOptions &options);
+
+  ~Column();
+
+  bool set_default_value(Error *error, Int row_id);
+  void unset(Int row_id);
+
+  // Return a value identified by "row_id".
+  //
+  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
+  Vector<GeoPoint> get(Int row_id) const {
+    Int size = static_cast<Int>(headers_[row_id] & 0xFFFF);
+    if (size == 0) {
+      return Vector<GeoPoint>(nullptr, 0);
+    }
+    Int offset = static_cast<Int>(headers_[row_id] >> 16);
+    if (size < 0xFFFF) {
+      return Vector<GeoPoint>(&bodies_[offset], size);
+    } else {
+      // The size of a long vector is stored in front of the body.
+      std::memcpy(&size, &bodies_[offset], sizeof(Int));
+      return Vector<GeoPoint>(&bodies_[offset + 1], size);
+    }
+  }
+
+  // Read values.
+  void read(ArrayCRef<Record> records,
+            ArrayRef<Vector<GeoPoint>> values) const {
+    for (Int i = 0; i < records.size(); ++i) {
+      values.set(i, get(records.get_row_id(i)));
+    }
+  }
+
+ private:
+  Array<UInt> headers_;
+  Array<GeoPoint> bodies_;
+
+  Column();
+};
+
+}  // namespace impl
+}  // namespace grnxx
+
+#endif  // GRNXX_IMPL_COLUMN_COLUMN_VECTOR_GEO_POINT_HPP

  Added: lib/grnxx/impl/column/column_vector_int.cpp (+152 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_vector_int.cpp    2014-10-07 13:33:14 +0900 (c743c08)
@@ -0,0 +1,152 @@
+#include "grnxx/impl/column/column_vector_int.hpp"
+
+#include "grnxx/cursor.hpp"
+#include "grnxx/impl/db.hpp"
+#include "grnxx/impl/table.hpp"
+
+namespace grnxx {
+namespace impl {
+
+bool Column<Vector<Int>>::set(Error *error, Int row_id,
+                              const Datum &datum) {
+  if (datum.type() != INT_VECTOR_DATA) {
+    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
+    return false;
+  }
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  Vector<Int> value = datum.force_int_vector();
+  if (value.size() == 0) {
+    headers_[row_id] = 0;
+    return true;
+  }
+  if (ref_table_) {
+    for (Int i = 0; i < value.size(); ++i) {
+      if (!ref_table_->test_row(error, value[i])) {
+        return false;
+      }
+    }
+  }
+  Int offset = bodies_.size();
+  if (value.size() < 0xFFFF) {
+    if (!bodies_.resize(error, offset + value.size())) {
+      return false;
+    }
+    for (Int i = 0; i < value.size(); ++i) {
+      bodies_[offset + i] = value[i];
+    }
+    headers_[row_id] = (offset << 16) | value.size();
+  } else {
+    // The size of a long vector is stored in front of the body.
+    if (!bodies_.resize(error, offset + 1 + value.size())) {
+      return false;
+    }
+    bodies_[offset] = value.size();
+    for (Int i = 0; i < value.size(); ++i) {
+      bodies_[offset + 1 + i] = value[i];
+    }
+    headers_[row_id] = (offset << 16) | 0xFFFF;
+  }
+  return true;
+}
+
+bool Column<Vector<Int>>::get(Error *error, Int row_id, Datum *datum) const {
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  *datum = get(row_id);
+  return true;
+}
+
+unique_ptr<Column<Vector<Int>>> Column<Vector<Int>>::create(
+    Error *error,
+    Table *table,
+    const StringCRef &name,
+    const ColumnOptions &options) {
+  unique_ptr<Column> column(new (nothrow) Column);
+  if (!column) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  if (!column->initialize_base(error, table, name, INT_VECTOR_DATA, options)) {
+    return nullptr;
+  }
+  if (!column->headers_.resize(error, table->max_row_id() + 1, 0)) {
+    return nullptr;
+  }
+  if (column->ref_table()) {
+    if (!column->ref_table_->append_referrer_column(error, column.get())) {
+      return nullptr;
+    }
+  }
+  return column;
+}
+
+Column<Vector<Int>>::~Column() {}
+
+bool Column<Vector<Int>>::set_default_value(Error *error, Int row_id) {
+  if (row_id >= headers_.size()) {
+    if (!headers_.resize(error, row_id + 1)) {
+      return false;
+    }
+  }
+  headers_[row_id] = 0;
+  return true;
+}
+
+void Column<Vector<Int>>::unset(Int row_id) {
+  headers_[row_id] = 0;
+}
+
+void Column<Vector<Int>>::clear_references(Int row_id) {
+  auto cursor = table_->create_cursor(nullptr);
+  if (!cursor) {
+    // Error.
+    return;
+  }
+  Array<Record> records;
+  for ( ; ; ) {
+    auto result = cursor->read(nullptr, 1024, &records);
+    if (!result.is_ok) {
+      // Error.
+      return;
+    } else if (result.count == 0) {
+      return;
+    }
+    for (Int i = 0; i < records.size(); ++i) {
+      Int value_row_id = records.get_row_id(i);
+      Int value_size = static_cast<Int>(headers_[value_row_id] & 0xFFFF);
+      if (value_size == 0) {
+        continue;
+      }
+      Int value_offset = static_cast<Int>(headers_[value_row_id] >> 16);
+      if (value_size >= 0xFFFF) {
+        value_size = bodies_[value_offset];
+        ++value_offset;
+      }
+      Int count = 0;
+      for (Int j = 0; j < value_size; ++j) {
+        if (bodies_[value_offset + j] != row_id) {
+          bodies_[value_offset + count] = bodies_[value_offset + j];
+          ++count;
+        }
+      }
+      if (count < value_size) {
+        if (count == 0) {
+          headers_[value_row_id] = 0;
+        } else if (count < 0xFFFF) {
+          headers_[value_row_id] = count | (value_offset << 16);
+        } else {
+          bodies_[value_offset - 1] = count;
+        }
+      }
+    }
+    records.clear();
+  }
+}
+
+Column<Vector<Int>>::Column() : ColumnBase(), headers_(), bodies_() {}
+
+}  // namespace impl
+}  // namespace grnxx

  Added: lib/grnxx/impl/column/column_vector_int.hpp (+72 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_vector_int.hpp    2014-10-07 13:33:14 +0900 (773d7e7)
@@ -0,0 +1,72 @@
+#ifndef GRNXX_IMPL_COLUMN_COLUMN_VECTOR_INT_HPP
+#define GRNXX_IMPL_COLUMN_COLUMN_VECTOR_INT_HPP
+
+#include "grnxx/impl/column/column.hpp"
+
+namespace grnxx {
+namespace impl {
+
+// TODO
+template <>
+class Column<Vector<Int>> : public ColumnBase {
+ public:
+  // -- Public API --
+
+  bool set(Error *error, Int row_id, const Datum &datum);
+  bool get(Error *error, Int row_id, Datum *datum) const;
+
+  // -- Internal API --
+
+  // Create a new column.
+  //
+  // Returns a pointer to the column on success.
+  // On failure, returns nullptr and stores error information into "*error" if
+  // "error" != nullptr.
+  static unique_ptr<Column> create(Error *error,
+                                   Table *table,
+                                   const StringCRef &name,
+                                   const ColumnOptions &options);
+
+  ~Column();
+
+  bool set_default_value(Error *error, Int row_id);
+  void unset(Int row_id);
+
+  void clear_references(Int row_id);
+
+  // Return a value identified by "row_id".
+  //
+  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
+  Vector<Int> get(Int row_id) const {
+    Int size = static_cast<Int>(headers_[row_id] & 0xFFFF);
+    if (size == 0) {
+      return Vector<Int>(nullptr, 0);
+    }
+    Int offset = static_cast<Int>(headers_[row_id] >> 16);
+    if (size < 0xFFFF) {
+      return Vector<Int>(&bodies_[offset], size);
+    } else {
+      // The size of a long vector is stored in front of the body.
+      size = bodies_[offset];
+      return Vector<Int>(&bodies_[offset + 1], size);
+    }
+  }
+
+  // Read values.
+  void read(ArrayCRef<Record> records, ArrayRef<Vector<Int>> values) const {
+    for (Int i = 0; i < records.size(); ++i) {
+      values.set(i, get(records.get_row_id(i)));
+    }
+  }
+
+ private:
+  Array<UInt> headers_;
+  Array<Int> bodies_;
+
+  Column();
+};
+
+}  // namespace impl
+}  // namespace grnxx
+
+#endif  // GRNXX_IMPL_COLUMN_COLUMN_VECTOR_INT_HPP

  Added: lib/grnxx/impl/column/column_vector_text.cpp (+100 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_vector_text.cpp    2014-10-07 13:33:14 +0900 (8bae356)
@@ -0,0 +1,100 @@
+#include "grnxx/impl/column/column_vector_text.hpp"
+
+#include "grnxx/cursor.hpp"
+#include "grnxx/impl/db.hpp"
+#include "grnxx/impl/table.hpp"
+
+namespace grnxx {
+namespace impl {
+
+bool Column<Vector<Text>>::set(Error *error, Int row_id,
+                               const Datum &datum) {
+  if (datum.type() != TEXT_VECTOR_DATA) {
+    GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type");
+    return false;
+  }
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  Vector<Text> value = datum.force_text_vector();
+  if (value.size() == 0) {
+    headers_[row_id] = Header{ 0, 0 };
+    return true;
+  }
+  Int text_headers_offset = text_headers_.size();
+  if (!text_headers_.resize(error, text_headers_offset + value.size())) {
+    return false;
+  }
+  Int total_size = 0;
+  for (Int i = 0; i < value.size(); ++i) {
+    total_size += value[i].size();
+  }
+  Int bodies_offset = bodies_.size();
+  if (!bodies_.resize(error, bodies_offset + total_size)) {
+    return false;
+  }
+  headers_[row_id] = Header{ text_headers_offset, value.size() };
+  for (Int i = 0; i < value.size(); ++i) {
+    text_headers_[text_headers_offset + i].offset = bodies_offset;
+    text_headers_[text_headers_offset + i].size = value[i].size();
+    std::memcpy(&bodies_[bodies_offset], value[i].data(), value[i].size());
+    bodies_offset += value[i].size();
+  }
+  return true;
+}
+
+bool Column<Vector<Text>>::get(Error *error, Int row_id,
+                               Datum *datum) const {
+  if (!table_->test_row(error, row_id)) {
+    return false;
+  }
+  *datum = get(row_id);
+  return true;
+}
+
+unique_ptr<Column<Vector<Text>>> Column<Vector<Text>>::create(
+    Error *error,
+    Table *table,
+    const StringCRef &name,
+    const ColumnOptions &options) {
+  unique_ptr<Column> column(new (nothrow) Column);
+  if (!column) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  if (!column->initialize_base(error, table, name,
+                               TEXT_VECTOR_DATA, options)) {
+    return nullptr;
+  }
+  if (!column->headers_.resize(error, table->max_row_id() + 1,
+                               Header{ 0, 0 })) {
+    return nullptr;
+  }
+  return column;
+}
+
+Column<Vector<Text>>::~Column() {}
+
+bool Column<Vector<Text>>::set_default_value(Error *error,
+                                                     Int row_id) {
+  if (row_id >= headers_.size()) {
+    if (!headers_.resize(error, row_id + 1)) {
+      return false;
+    }
+  }
+  headers_[row_id] = Header{ 0, 0 };
+  return true;
+}
+
+void Column<Vector<Text>>::unset(Int row_id) {
+  headers_[row_id] = Header{ 0, 0 };
+}
+
+Column<Vector<Text>>::Column()
+    : ColumnBase(),
+      headers_(),
+      text_headers_(),
+      bodies_() {}
+
+}  // namespace impl
+}  // namespace grnxx

  Added: lib/grnxx/impl/column/column_vector_text.hpp (+64 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/impl/column/column_vector_text.hpp    2014-10-07 13:33:14 +0900 (bb33ebe)
@@ -0,0 +1,64 @@
+#ifndef GRNXX_IMPL_COLUMN_COLUMN_VECTOR_TEXT_HPP
+#define GRNXX_IMPL_COLUMN_COLUMN_VECTOR_TEXT_HPP
+
+#include "grnxx/impl/column/column.hpp"
+
+namespace grnxx {
+namespace impl {
+
+template <>
+class Column<Vector<Text>> : public ColumnBase {
+ public:
+  // -- Public API --
+
+  bool set(Error *error, Int row_id, const Datum &datum);
+  bool get(Error *error, Int row_id, Datum *datum) const;
+
+  // -- Internal API --
+
+  // Create a new column.
+  //
+  // Returns a pointer to the column on success.
+  // On failure, returns nullptr and stores error information into "*error" if
+  // "error" != nullptr.
+  static unique_ptr<Column> create(Error *error,
+                                   Table *table,
+                                   const StringCRef &name,
+                                   const ColumnOptions &options);
+
+  ~Column();
+
+  bool set_default_value(Error *error, Int row_id);
+  void unset(Int row_id);
+
+  // Return a value identified by "row_id".
+  //
+  // Assumes that "row_id" is valid. Otherwise, the result is undefined.
+  Vector<Text> get(Int row_id) const {
+    return Vector<Text>(&text_headers_[headers_[row_id].offset],
+                        bodies_.data(), headers_[row_id].size);
+  }
+
+  // Read values.
+  void read(ArrayCRef<Record> records, ArrayRef<Vector<Text>> values) const {
+    for (Int i = 0; i < records.size(); ++i) {
+      values.set(i, get(records.get_row_id(i)));
+    }
+  }
+
+ private:
+  struct Header {
+    Int offset;
+    Int size;
+  };
+  Array<Header> headers_;
+  Array<Header> text_headers_;
+  Array<char> bodies_;
+
+  Column();
+};
+
+}  // namespace impl
+}  // namespace grnxx
+
+#endif  // GRNXX_IMPL_COLUMN_COLUMN_VECTOR_TEXT_HPP

  Modified: lib/grnxx/impl/table.hpp (+1 -1)
===================================================================
--- lib/grnxx/impl/table.hpp    2014-10-07 11:30:11 +0900 (b9ed720)
+++ lib/grnxx/impl/table.hpp    2014-10-07 13:33:14 +0900 (59863ee)
@@ -3,7 +3,7 @@
 
 #include "grnxx/name.hpp"
 #include "grnxx/db.hpp"
-#include "grnxx/impl/column/column_base.hpp"
+#include "grnxx/impl/column.hpp"
 #include "grnxx/table.hpp"
 
 namespace grnxx {

  Modified: lib/grnxx/index.cpp (+5 -6)
===================================================================
--- lib/grnxx/index.cpp    2014-10-07 11:30:11 +0900 (6ac6930)
+++ lib/grnxx/index.cpp    2014-10-07 13:33:14 +0900 (7edb446)
@@ -1,8 +1,7 @@
 #include "grnxx/index.hpp"
 
-#include "grnxx/column.hpp"
-#include "grnxx/column_impl.hpp"
 #include "grnxx/cursor.hpp"
+#include "grnxx/impl/column.hpp"
 #include "grnxx/table.hpp"
 #include "grnxx/tree_index.hpp"
 
@@ -452,7 +451,7 @@ unique_ptr<TreeIndex<Bool>> TreeIndex<Bool>::create(
   if (!cursor) {
     return nullptr;
   }
-  auto typed_column = static_cast<ColumnImpl<Bool> *>(column);
+  auto typed_column = static_cast<impl::Column<Bool> *>(column);
   Array<Record> records;
   for ( ; ; ) {
     auto result = cursor->read(error, 1024, &records);
@@ -610,7 +609,7 @@ unique_ptr<TreeIndex<Int>> TreeIndex<Int>::create(
   if (!cursor) {
     return nullptr;
   }
-  auto typed_column = static_cast<ColumnImpl<Int> *>(column);
+  auto typed_column = static_cast<impl::Column<Int> *>(column);
   Array<Record> records;
   for ( ; ; ) {
     auto result = cursor->read(error, 1024, &records);
@@ -768,7 +767,7 @@ unique_ptr<TreeIndex<Float>> TreeIndex<Float>::create(
   if (!cursor) {
     return nullptr;
   }
-  auto typed_column = static_cast<ColumnImpl<Float> *>(column);
+  auto typed_column = static_cast<impl::Column<Float> *>(column);
   Array<Record> records;
   for ( ; ; ) {
     auto result = cursor->read(error, 1024, &records);
@@ -937,7 +936,7 @@ unique_ptr<TreeIndex<Text>> TreeIndex<Text>::create(
   if (!cursor) {
     return nullptr;
   }
-  auto typed_column = static_cast<ColumnImpl<Text> *>(column);
+  auto typed_column = static_cast<impl::Column<Text> *>(column);
   Array<Record> records;
   for ( ; ; ) {
     auto result = cursor->read(error, 1024, &records);




More information about the Groonga-commit mailing list
Back to archive index