susumu.yata
null+****@clear*****
Tue Dec 16 10:54:29 JST 2014
susumu.yata 2014-11-17 17:13:49 +0900 (Mon, 17 Nov 2014) New Revision: 8fa63b869f78608d28a6178f0c469af6a867324a https://github.com/groonga/grnxx/commit/8fa63b869f78608d28a6178f0c469af6a867324a Message: Add Column<Vector<Bool>>. (#110) Modified files: lib/grnxx/impl/column/base.cpp lib/grnxx/impl/column/vector.hpp lib/grnxx/impl/column/vector/Makefile.am lib/grnxx/impl/column/vector/bool.cpp lib/grnxx/impl/column/vector/bool.hpp Modified: lib/grnxx/impl/column/base.cpp (+4 -4) =================================================================== --- lib/grnxx/impl/column/base.cpp 2014-11-17 16:25:48 +0900 (797c86f) +++ lib/grnxx/impl/column/base.cpp 2014-11-17 17:13:49 +0900 (97d4f55) @@ -199,10 +199,10 @@ std::unique_ptr<ColumnBase> ColumnBase::create( column.reset(new impl::Column<Text>(table, name, options)); break; } -// case BOOL_VECTOR_DATA: { -// column.reset(new impl::Column<Vector<Bool>>(table, name, options)); -// break; -// } + case BOOL_VECTOR_DATA: { + column.reset(new impl::Column<Vector<Bool>>(table, name, options)); + break; + } // case INT_VECTOR_DATA: { // column.reset(new impl::Column<Vector<Int>>(table, name, options)); // break; Modified: lib/grnxx/impl/column/vector.hpp (+1 -1) =================================================================== --- lib/grnxx/impl/column/vector.hpp 2014-11-17 16:25:48 +0900 (1e2876c) +++ lib/grnxx/impl/column/vector.hpp 2014-11-17 17:13:49 +0900 (1721cf5) @@ -1,7 +1,7 @@ #ifndef GRNXX_IMPL_COLUMN_VECTOR_HPP #define GRNXX_IMPL_COLUMN_VECTOR_HPP -//#include "grnxx/impl/column/vector/bool.hpp" +#include "grnxx/impl/column/vector/bool.hpp" //#include "grnxx/impl/column/vector/float.hpp" //#include "grnxx/impl/column/vector/geo_point.hpp" //#include "grnxx/impl/column/vector/int.hpp" Modified: lib/grnxx/impl/column/vector/Makefile.am (+2 -2) =================================================================== --- lib/grnxx/impl/column/vector/Makefile.am 2014-11-17 16:25:48 +0900 (4c68d73) +++ lib/grnxx/impl/column/vector/Makefile.am 2014-11-17 17:13:49 +0900 (01b77d1) @@ -8,9 +8,9 @@ lib_LTLIBRARIES = libgrnxx_impl_column_vector.la libgrnxx_impl_column_vector_la_LDFLAGS = @AM_LTLDFLAGS@ -libgrnxx_impl_column_vector_la_SOURCES = +libgrnxx_impl_column_vector_la_SOURCES = \ + bool.cpp -# bool.cpp \ # float.cpp \ # geo_point.cpp \ # int.cpp \ Modified: lib/grnxx/impl/column/vector/bool.cpp (+160 -0) =================================================================== --- lib/grnxx/impl/column/vector/bool.cpp 2014-11-17 16:25:48 +0900 (e69de29) +++ lib/grnxx/impl/column/vector/bool.cpp 2014-11-17 17:13:49 +0900 (80ffd9f) @@ -0,0 +1,160 @@ +#include "grnxx/impl/column/vector/bool.hpp" + +#include <cstring> + +#include "grnxx/impl/db.hpp" +#include "grnxx/impl/table.hpp" +//#include "grnxx/impl/index.hpp" + +namespace grnxx { +namespace impl { + +Column<Vector<Bool>>::Column(Table *table, + const String &name, + const ColumnOptions &) + : ColumnBase(table, name, BOOL_VECTOR_DATA), + headers_(), + bodies_() {} + +Column<Vector<Bool>>::~Column() {} + +void Column<Vector<Bool>>::set(Int row_id, const Datum &datum) { + Vector<Bool> new_value = parse_datum(datum); + if (!table_->test_row(row_id)) { + throw "Invalid row ID"; // TODO + } + if (new_value.is_na()) { + unset(row_id); + return; + } + Vector<Bool> old_value = get(row_id); + if ((old_value == new_value).is_true()) { + return; + } + if (!old_value.is_na()) { + // TODO: Remove the old value from indexes. +// for (size_t i = 0; i < num_indexes(); ++i) { +// indexes_[i]->remove(row_id, old_value); +// } + } + size_t value_id = row_id.value(); + if (value_id >= headers_.size()) { + headers_.resize(value_id + 1, na_header()); + } + // TODO: Insert the new value into indexes. +// for (size_t i = 0; i < num_indexes(); ++i) try { +// indexes_[i]->insert(row_id, datum)) { +// } catch (...) { +// for (size_t j = 0; j < i; ++i) { +// indexes_[j]->remove(row_id, datum); +// } +// throw; +// } + // TODO: Error handling. + size_t offset = bodies_.size(); + size_t size = new_value.size().value(); + uint64_t header; + if (size < 0xFFFF) { + bodies_.resize(offset + size); + std::memcpy(&bodies_[offset], new_value.data(), size); + header = (offset << 16) | size; + } else { + // The size of a long vector is stored in front of the body. + if ((offset % sizeof(uint64_t)) != 0) { + offset += sizeof(uint64_t) - (offset % sizeof(uint64_t)); + } + bodies_.resize(offset + sizeof(uint64_t) + size); + *reinterpret_cast<uint64_t *>(&bodies_[offset]) = size; + std::memcpy(&bodies_[offset + sizeof(uint64_t)], new_value.data(), size); + header = (offset << 16) | 0xFFFF; + } + headers_[value_id] = header; +} + +void Column<Vector<Bool>>::get(Int row_id, Datum *datum) const { + size_t value_id = row_id.value(); + if (value_id >= headers_.size()) { + *datum = Vector<Bool>::na(); + } else { + // TODO + *datum = get(row_id); + } +} + +bool Column<Vector<Bool>>::contains(const Datum &datum) const { + // TODO: Use an index if exists. + Vector<Bool> value = parse_datum(datum); + if (value.is_na()) { + for (size_t i = 0; i < headers_.size(); ++i) { + if (headers_[i] == na_header()) { + return true; + } + } + } else { + for (size_t i = 0; i < headers_.size(); ++i) { + // TODO: Improve this. + if ((get(Int(i)) == value).is_true()) { + return true; + } + } + } + return false; +} + +Int Column<Vector<Bool>>::find_one(const Datum &datum) const { + // TODO: Use an index if exists. + Vector<Bool> value = parse_datum(datum); + if (value.is_na()) { + for (size_t i = 0; i < headers_.size(); ++i) { + if (headers_[i] == na_header()) { + return Int(i); + } + } + } else { + for (size_t i = 0; i < headers_.size(); ++i) { + // TODO: Improve this. + if ((get(Int(i)) == value).is_true()) { + return Int(i); + } + } + } + return Int::na(); +} + +void Column<Vector<Bool>>::unset(Int row_id) { + Vector<Bool> value = get(row_id); + if (!value.is_na()) { + // TODO: Update indexes if exist. +// for (size_t i = 0; i < num_indexes(); ++i) { +// indexes_[i]->remove(row_id, value); +// } + headers_[row_id.value()] = na_header(); + } +} + +void Column<Vector<Bool>>::read(ArrayCRef<Record> records, + ArrayRef<Vector<Bool>> values) const { + if (records.size() != values.size()) { + throw "Data size conflict"; // TODO + } + for (size_t i = 0; i < records.size(); ++i) { + values.set(i, get(records[i].row_id)); + } +} + +Vector<Bool> Column<Vector<Bool>>::parse_datum(const Datum &datum) { + switch (datum.type()) { + case NA_DATA: { + return Vector<Bool>::na(); + } + case BOOL_VECTOR_DATA: { + return datum.as_bool_vector(); + } + default: { + throw "Wrong data type"; // TODO + } + } +} + +} // namespace impl +} // namespace grnxx Modified: lib/grnxx/impl/column/vector/bool.hpp (+68 -2) =================================================================== --- lib/grnxx/impl/column/vector/bool.hpp 2014-11-17 16:25:48 +0900 (6aa01ac) +++ lib/grnxx/impl/column/vector/bool.hpp 2014-11-17 17:13:49 +0900 (992a656) @@ -1,12 +1,78 @@ #ifndef GRNXX_IMPL_COLUMN_VECTOR_BOOL_HPP #define GRNXX_IMPL_COLUMN_VECTOR_BOOL_HPP -#include "grnxx/impl/column/column.hpp" +#include <limits> +#include <cstdint> + +#include "grnxx/impl/column/base.hpp" namespace grnxx { namespace impl { -// TODO +template <typename T> class Column; + +template <> +class Column<Vector<Bool>> : public ColumnBase { + public: + // -- Public API (grnxx/column.hpp) -- + + Column(Table *table, const String &name, const ColumnOptions &options); + ~Column(); + + void set(Int row_id, const Datum &datum); + void get(Int row_id, Datum *datum) const; + + bool contains(const Datum &datum) const; + Int find_one(const Datum &datum) const; + + // -- Internal API (grnxx/impl/column/base.hpp) -- + + void unset(Int row_id); + + // -- Internal API -- + + // Return a value. + // + // If "row_id" is valid, returns the stored value. + // If "row_id" is invalid, returns N/A. + // + // TODO: Vector cannot reuse allocated memory because of this interface. + Vector<Bool> get(Int row_id) const { + size_t value_id = row_id.value(); + if (value_id >= headers_.size()) { + return Vector<Bool>::na(); + } + if (headers_[value_id] == na_header()) { + return Vector<Bool>::na(); + } + size_t size = headers_[value_id] & 0xFFFF; + if (size == 0) { + return Vector<Bool>(nullptr, 0); + } + size_t offset = headers_[value_id] >> 16; + if (size < 0xFFFF) { + return Vector<Bool>(&bodies_[offset], size); + } else { + // The size of a long text is stored in front of the body. + size = *reinterpret_cast<const uint64_t *>(&bodies_[offset]); + return Vector<Bool>(&bodies_[offset + sizeof(uint64_t)], size); + } + } + // Read values. + // + // On failure, throws an exception. + void read(ArrayCRef<Record> records, ArrayRef<Vector<Bool>> values) const; + + private: + Array<uint64_t> headers_; + Array<Bool> bodies_; + + static constexpr uint64_t na_header() { + return std::numeric_limits<uint64_t>::max(); + } + + static Vector<Bool> parse_datum(const Datum &datum); +}; } // namespace impl } // namespace grnxx -------------- next part -------------- HTML����������������������������... 다운로드