susumu.yata
null+****@clear*****
Tue May 27 13:53:46 JST 2014
susumu.yata 2014-05-27 13:53:46 +0900 (Tue, 27 May 2014) New Revision: 0c295a03df7473964200605c03a4e475b3780ca3 https://github.com/groonga/grnxx/commit/0c295a03df7473964200605c03a4e475b3780ca3 Message: Add a new interface candidate. Added files: new-interface/column.hpp new-interface/cursor.hpp new-interface/datum.hpp new-interface/db.hpp new-interface/error.hpp new-interface/expression.hpp new-interface/index.hpp new-interface/library.hpp new-interface/sorter.hpp new-interface/table.hpp new-interface/types.hpp Added: new-interface/column.hpp (+150 -0) 100644 =================================================================== --- /dev/null +++ new-interface/column.hpp 2014-05-27 13:53:46 +0900 (2de98f7) @@ -0,0 +1,150 @@ +#ifndef GRNXX_COLUMN_HPP +#define GRNXX_COLUMN_HPP + +#include "grnxx/types.hpp" + +namespace grnxx { + +class Column { + public: + // 所属するテーブルを取得する. + virtual Table *table() const = 0; + // 名前を取得する. + virtual const char *name() const = 0; + // カラムの種類を取得する. + virtual ColumnType type() const = 0; + // 索引 ID の最小値を取得する. + virtual IndexID min_index_id() const = 0; + // 索引 ID の最大値を取得する. + virtual IndexID max_index_id() const = 0; + // キーカラムかどうかを取得する. + virtual bool is_key() const = 0; + + // 索引を作成する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前が索引名の条件を満たさない. + // - 指定された名前の索引が存在する. + // - オプションの内容が不正である. + // - 十分なリソースを確保できない. + // - 索引の数が上限に達している. + virtual Index *create_index(const char *index_name, + IndexType index_type, + const IndexOptions &options, + Error *error) = 0; + // 索引を破棄する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // 破棄する索引を指す Index * を保持しているときは, + // 索引を破棄する前に nullptr を代入するなどしておいた方がよい. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前の索引が存在しない. + virtual bool drop_index(const char *index_name, Error *error) = 0; + + // 索引の名前を変更する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前の索引が存在しない. + // - 指定された名前(new)が索引名の条件を満たさない. + // - 指定された名前(new)の索引が存在する. + // - 変更前後の名前が同じときは何もせずに成功とする. + virtual bool rename_index(const char *index_name, + const char *new_index_name, + Error *error) = 0; + + // 索引の順番を変更する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // index_name で指定された索引を prev_index_name の後ろに移動する. + // ただし, index_name と prev_index_name が同じときは移動せずに成功とする. + // prev_index_name が nullptr もしくは空文字列のときは先頭に移動する. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前の索引が存在しない. + virtual bool reorder_index(const char *index_name, + const char *prev_index_name, + Error *error) = 0; + + // 索引を取得する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // min_index_id() 以上 max_index_id() 以下の索引 ID に対して + // 呼び出すことですべての索引を取得することができる. + // 索引 ID は削除や並び替えによって変化することに注意が必要である. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された ID が有効な範囲にない. + virtual Index *get_index(IndexID index_id, Error *error) const = 0; + + // 索引を検索する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前の索引が存在しない. + virtual Index *find_index(const char *index_name, Error *error) const = 0; + + // TODO: 機能から索引を検索する API が欲しい. + // たとえば,範囲検索に使える索引を探す,全文検索に使える索引を探すなど. + // 索引の種類(TREE_INDEX, HASH_INDEX, etc.)による検索で十分かもしれない. + + // 値を格納する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // 更新しようとしている値と指定された値が同じであれば,何もせずに成功とする. + // キーカラムでは,同じ値が存在しないか確認する. + // 索引があれば,それらも更新する. + // 参照型のカラムでは,あらかじめ行 ID にしておく必要がある. + // + // TODO: 参照先のキーで入力できると便利だが,そうすると ID 指定による + // 入力はできなくなってしまう. + // 何か良い解決法がないか検討する. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された行 ID が有効でない. + // - 指定された値をカラムの型に変換できない. + // - 指定された値がカラムの制約にかかる. + // - リソースが確保できない. + // - 索引の更新に失敗する. + virtual bool set(RowID row_id, const Datum &datum, Error *error) = 0; + + // 値を取得する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // 取得した値は *datum に格納する. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された行 ID が有効でない. + virtual bool get(RowID row_id, Datum *datum, Error *error) const = 0; + + // 指定された条件を持たす行の ID を取得するためのカーソルを作成する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 返り値は std::unique_ptr なので自動的に delete される. + // 自動で delete されて困るときは release() で生のポインタを取り出す必要がある. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - オプションが不正である. + // - リソースが確保できない. + virtual std::unique_ptr<Cursor> create_cursor( + const CursorOptions &options) const = 0; + + protected: + Column(); + virtual ~Column(); +}; + +} // namespace grnxx + +#endif // GRNXX_COLUMN_HPP Added: new-interface/cursor.hpp (+25 -0) 100644 =================================================================== --- /dev/null +++ new-interface/cursor.hpp 2014-05-27 13:53:46 +0900 (3b30c70) @@ -0,0 +1,25 @@ +#ifndef GRNXX_CURSOR_HPP +#define GRNXX_CURSOR_HPP + +#include "grnxx/types.hpp" + +namespace grnxx { + +class Cursor { + public: + Cursor(); + virtual ~Cursor(); + + // カーソルの位置を進めて移動量を返す. + // 途中で終端に到達したときは,そこで移動を停止し,それまでの移動量を返す. + virtual int64_t seek(int64_t count) = 0; + + // カーソルの位置を進めて移動量を返す. + // 途中で終端に到達したときは,そこで移動を停止し,それまでの移動量を返す. + // 移動中に取得した行 ID は *row_ids に格納する. + virtual int64_t read(int64_t count, RowID *row_ids) = 0; +}; + +} // namespace grnxx + +#endif // GRNXX_CURSOR_HPP Added: new-interface/datum.hpp (+148 -0) 100644 =================================================================== --- /dev/null +++ new-interface/datum.hpp 2014-05-27 13:53:46 +0900 (e73f556) @@ -0,0 +1,148 @@ +#ifndef GRNXX_DATUM_HPP +#define GRNXX_DATUM_HPP + +#include "grnxx/types.hpp" + +namespace grnxx { + +class Datum { + public: + // データを初期化する. + Datum() + : type_(NULL_DATUM), + null_() {} + Datum(bool value) + : type_(BOOL_DATUM), + bool_(value) {} + Datum(int64_t value) + : type_(INT_DATUM), + int_(value) {} + Datum(double value) + : type_(FLOAT_DATUM), + float_(value) {} + Datum(const std::string &value) + : type_(TEXT_DATUM), + text_(value) {} + Datum(std::string &&value) + : type_(TEXT_DATUM), + text_(value) {} + Datum(const std::vector<bool> &value) + : type_(BOOL_ARRAY_DATUM), + bool_array_(value) {} + Datum(std::vector<bool> &&value) + : type_(BOOL_ARRAY_DATUM), + bool_array_(value) {} + Datum(const std::vector<int64_t> &value) + : type_(INT_ARRAY_DATUM), + int_array_(value) {} + Datum(std::vector<int64_t> &&value) + : type_(INT_ARRAY_DATUM), + int_array_(value) {} + Datum(const std::vector<double> &value) + : type_(FLOAT_ARRAY_DATUM), + float_array_(value) {} + Datum(std::vector<double> &&value) + : type_(FLOAT_ARRAY_DATUM), + float_array_(value) {} + Datum(const std::vector<std::string> &value) + : type_(TEXT_ARRAY_DATUM), + text_array_(value) {} + Datum(std::vector<std::string> &&value) + : type_(TEXT_ARRAY_DATUM), + text_array_(value) {} + // データを破棄する. + ~Datum() { + clear(); + } + + // ムーブ. + Datum(Datum &&datum); + // ムーブ. + Datum &operator=(Datum &&datum); + + // 種類を返す. + DatumType type() const { + return type_; + } + + // 真偽値を代入する. + Datum &operator=(bool value); + // 整数を代入する. + Datum &operator=(int64_t value); + // 浮動小数点数を代入する. + Datum &operator=(double value); + // 文字列を代入する. + Datum &operator=(const std::string &value); + // 真偽値の配列を代入する. + Datum &operator=(const std::vector<bool> &value); + // 整数の配列を代入する. + Datum &operator=(const std::vector<int64_t> &value); + // 浮動小数点数の配列を代入する. + Datum &operator=(const std::vector<double> &value); + // 文字列の配列を代入する. + Datum &operator=(const std::vector<std::string> &value); + + Datum &operator=(std::string &&value); + // 真偽値の配列を代入する. + Datum &operator=(std::vector<bool> &&value); + // 整数の配列を代入する. + Datum &operator=(std::vector<int64_t> &&value); + // 浮動小数点数の配列を代入する. + Datum &operator=(std::vector<double> &&value); + // 文字列の配列を代入する. + Datum &operator=(std::vector<std::string> &&value); + + // 真偽値として参照する. + const bool &as_bool() const { + return bool_; + } + // 整数として参照する. + const int64_t &as_int() const { + return int_; + } + // 浮動小数点数として参照する. + const double &as_float() const { + return float_; + } + // 文字列として参照する. + const std::string &as_text() const { + return text_; + } + // 真偽値の配列として参照する. + const std::vector<bool> &as_bool_array() const { + return bool_array_; + } + // 整数の配列として参照する. + const std::vector<int64_t> &as_int_array() const { + return int_array_; + } + // 浮動小数点数の配列として参照する. + const std::vector<double> &as_float_array() const { + return float_array_; + } + // 文字列の配列として参照する. + const std::vector<std::string> &as_text_array() const { + return text_array_; + } + + // データを破棄する. + void clear(); + + private: + DatumType type_; + union { + std::nullptr_t null_; + bool bool_; + int64_t int_; + double float_; + std::string text_; + std::vector<bool> bool_array_; + std::vector<int64_t> int_array_; + std::vector<double> float_array_; + std::vector<std::string> text_array_; + }; +}; + +} // namespace grnxx + +#endif // GRNXX_DATUM_HPP Added: new-interface/db.hpp (+159 -0) 100644 =================================================================== --- /dev/null +++ new-interface/db.hpp 2014-05-27 13:53:46 +0900 (76c356f) @@ -0,0 +1,159 @@ +#ifndef GRNXX_DB_HPP +#define GRNXX_DB_HPP + +#include "grnxx/types.hpp" + +namespace grnxx { + +class DB { + public: + DB(); + virtual ~DB(); + + // テーブル ID の最小値を取得する. + virtual TableID min_table_id() const = 0; + // テーブル ID の最大値を取得する. + virtual TableID max_table_id() const = 0; + + // テーブルを作成する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前がテーブル名の条件を満たさない. + // - 指定された名前のテーブルが存在する. + // - オプションの内容が不正である. + // - 十分なリソースを確保できない. + // - テーブルの数が上限に達している. + virtual Table *create_table(const char *table_name, + const TableOptions &table_options, + Error *error) = 0; + + // テーブルを破棄する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // 破棄するテーブルを指す Table * を保持しているときは, + // テーブルを破棄する前に nullptr を代入するなどしておいた方がよい. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前のテーブルが存在しない. + // - 依存関係を解決できない. + virtual bool drop_table(const char *table_name, + Error *error) = 0; + + // テーブルの名前を変更する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前のテーブルが存在しない. + // - 指定された名前(new)がテーブル名の条件を満たさない. + // - 指定された名前(new)のテーブルが存在する. + // - 変更前後の名前が同じときは何もせずに成功とする. + // - 索引の更新に失敗する. + virtual bool rename_table(const char *table_name, + const char *new_table_name, + Error *error) = 0; + + // テーブルの順番を変更する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // table_name で指定されたテーブルを prev_table_name の後ろに移動する. + // ただし, table_name と prev_table_name が同じときは移動せずに成功とする. + // prev_table_name が nullptr もしくは空文字列のときは先頭に移動する. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前のテーブルが存在しない. + virtual bool reorder_table(const char *table_name, + const char *prev_table_name, + Error *error) = 0; + + // テーブルを取得する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // min_table_id() 以上 max_table_id() 以下のテーブル ID に対して + // 呼び出すことですべてのテーブルを取得することができる. + // テーブル ID は削除や並び替えによって変化することに注意が必要である. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された ID が有効な範囲にない. + virtual Table *get_table(TableID table_id, + Error *error) const = 0; + + // テーブルを検索する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前のテーブルが存在しない. + virtual Table *find_table(const char *table_name, Error *error) const = 0; + + // データベースの内容をファイルに出力する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // path が nullptr もしくは空文字列のときは関連付けられているパスを用いる. + // + // 上書き保存では,一時ファイルを作成してから名前を変更する. + // 別名で保存するときは,共有メモリの内容も保存する必要がある. + // 環境によっては Copy-on-Write なファイル・コピーが使えるかもしれない. + // + // ファイルへの保存という機会を利用して隙間を埋めることができる. + // 最適化の有無や圧縮方法などはオプションで指定するものとする. + // + // 共有メモリの内容をフラッシュするだけというオプションも考えられる. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前のファイルに到達できない. + // - ディレクトリを作成するオプションがあると便利かもしれない. + // - 指定された名前のファイルが存在する. + // - 上書きを許可するオプションは欲しい. + // - 指定された名前のファイルに対するアクセス権限がない. + // - 作業領域が確保できない. + // - ディスクの空き容量が足りない. + virtual bool save(const char *path, + const DBSaveOptions &options, + Error *error) const = 0; +}; + +// データベースを開く,もしくは作成する. +// 成功すれば有効なオブジェクトへのポインタを返す. +// 失敗したときは *error にその内容を格納し, nullptr を返す. +// +// path が nullptr もしくは空文字列のときは一時データベースを作成する. +// +// 返り値は std::unique_ptr なので自動的に delete される. +// 自動で delete されて困るときは release() で生のポインタを取り出す必要がある. +// +// 失敗する状況としては,以下のようなものが挙げられる. +// - データベースを開くように指示されたのに,指定された名前のファイルが存在しない. +// - データベースを作成するように指示されたのに,指定された名前のファイルが存在する. +// - 指定された名前のファイルに到達できない. +// - ディレクトリを作成するオプションがあると便利かもしれない. +// - 指定された名前のファイルに対するアクセス権限がない. +// - 指定された名前のファイルがデータベースのファイルではない. +// - データベースを構成するファイルが存在しない. +std::unique_ptr<DB> open_db(const char *path, + const OpenDBOptions &options, + Error *error); + +// データベースを削除する. +// 成功すれば true を返す. +// 失敗したときは *error にその内容を格納し, false を返す. +// +// 失敗する状況としては,以下のようなものが挙げられる. +// - 指定された名前のファイルが存在しない. +// - 指定された名前のファイルに対するアクセス権限がない. +// - 指定された名前のファイルがデータベースのファイルではない. +// - データベースを構成するファイルが存在しない. +// - 一部のファイルが欠けていても強制的に残りを削除するオプションは欲しい. +// - データベースを開かずにパスのみから推論して削除したいケースもありうる. +// - ファイルの削除に失敗する. +bool drop_db(const char *path, const DropDBOptions &options, Error *error); + +} // namespace grnxx + +#endif // GRNXX_DB_HPP Added: new-interface/error.hpp (+38 -0) 100644 =================================================================== --- /dev/null +++ new-interface/error.hpp 2014-05-27 13:53:46 +0900 (9da57f5) @@ -0,0 +1,38 @@ +#ifndef GRNXX_ERROR_HPP +#define GRNXX_ERROR_HPP + +#include "grnxx/types.hpp" + +namespace grnxx { + +// 以下の実装では, Error のサイズが大きいため,値渡しには向かない. +// また,再帰呼出しするような関数では,内部で Error を定義するのは危険かもしれない. +// スタック領域を使い切れば致命的なエラーになる. +// その代わり,基本的にはスタック領域を使うため, +// メモリ確保によるオーバーヘッドは発生しないというメリットがある. +// +// Error の中身はポインタだけにし,必要なときにメモリを確保するという実装も考えられる. +// メッセージの長さに制限を持たせる必要がなくなるものの, +// 代わりに Trivial でないコンストラクタとデストラクタが必要になる. +// +// find() の Not found や insert_row() の Key already exists みたいなのにも +// 使うのであれば, message_ の生成がネックになりうる. +class Error { + public: + int line() const; + const char *file() const; + const char *function() const; + const char *message() const; + +// private: +// constexpr int MESSAGE_SIZE = 256; + +// int line_; // __LINE__ +// const char *file_; // __FILE__ +// const char *function_; // __FUNCTION__ or __func__ +// char message_[MESSAGE_SIZE]; +}; + +} // namespace grnxx + +#endif // GRNXX_ERROR_HPP Added: new-interface/expression.hpp (+99 -0) 100644 =================================================================== --- /dev/null +++ new-interface/expression.hpp 2014-05-27 13:53:46 +0900 (2392390) @@ -0,0 +1,99 @@ +#ifndef GRNXX_EXPRESSION_HPP +#define GRNXX_EXPRESSION_HPP + +#include "grnxx/types.hpp" + +namespace grnxx { + +class ExpressionNode; + +class Expression { + public: + Expression(); + virtual ~Expression(); + + // 所属するテーブルを取得する. + virtual Table *table() const = 0; + // 評価結果の型を取得する. + virtual DataType data_type() const = 0; + + // 定数に対応するノードを作成する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された定数が異常値である. + // - リソースを確保できない. + virtual ExpressionNode *create_datum_node(const Datum &datum, + Error *error) = 0; + + // カラムに対応するノードを作成する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定されたカラムが存在しない. + // - リソースを確保できない. + virtual ExpressionNode *create_column_node(const char *column_name, + Error *error) = 0; + + // 演算子に対応するノードを作成する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 演算子と引数が対応していない. + // - 演算子が求める引数の型・数と実際の引数の型・数が異なる. + // - リソースを確保できない. + virtual ExpressionNode *create_operator_node(OperatorType operator_type, + Int64 num_args, + ExpressionNode *args, + Error *error) = 0; + + // 行の一覧をフィルタにかける. + // 成功すればフィルタにかけて残った行数を返す. + // 失敗したときは *error にその内容を格納し, -1 を返す. + // + // 評価結果が真になる行のみを残し,前方に詰めて隙間をなくす. + // フィルタにかける前後で順序関係は維持される. + // + // 有効でない行 ID を渡したときの動作は未定義である. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 評価結果の型が真偽値でない. + // - 演算において例外が発生する. + // - オーバーフローやアンダーフローが発生する. + // - ゼロによる除算が発生する. + // - NaN が発生する. + // - TODO: これらの取り扱いについては検討の余地がある. + virtual Int64 filter(Int64 num_row_ids, + RowID *row_ids, + Error *error) = 0; + + // 行の一覧に対する評価結果を取得する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // TODO: 汎用型を配列にするのは効率が悪いため,ほかの方法が望ましい. + // 専用の型を用意することも含めて検討したい. + // + // TODO: 整列などにも使うことを考えれば,ネイティブな型を返すインタフェースが欲しい. + // 少なくとも内部インタフェースとして用意する必要がある. + // + // 有効でない行 ID を渡したときの動作は未定義である. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 演算において例外が発生する. + // - オーバーフローやアンダーフローが発生する. + // - ゼロによる除算が発生する. + // - NaN が発生する. + // - TODO: これらの取り扱いについては検討の余地がある. + virtual bool evaluate(Int64 num_row_ids, + const RowID *row_ids, + Datum *values, + Error *error) = 0; +}; + +} // namespace grnxx + +#endif // GRNXX_EXPRESSION_HPP Added: new-interface/index.hpp (+36 -0) 100644 =================================================================== --- /dev/null +++ new-interface/index.hpp 2014-05-27 13:53:46 +0900 (5713156) @@ -0,0 +1,36 @@ +#ifndef GRNXX_INDEX_HPP +#define GRNXX_INDEX_HPP + +#include "grnxx/types.hpp" + +namespace grnxx { + +class Index { + public: + Index(); + virtual ~Index(); + + // 所属するカラムを取得する. + virtual Column *column() const = 0; + // 名前を取得する. + virtual const std::string &name() const = 0; + // 種類を取得する. + virtual IndexType type() const = 0; + + // 指定された条件を持たす行の ID を取得するためのカーソルを作成する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 返り値は std::unique_ptr なので自動的に delete される. + // 自動で delete されて困るときは release() で生のポインタを取り出す必要がある. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - オプションが不正である. + // - リソースが確保できない. + virtual std::unique_ptr<Cursor> create_cursor( + const CursorOptions &options) const = 0; +}; + +} // namespace grnxx + +#endif // GRNXX_INDEX_HPP Added: new-interface/library.hpp (+18 -0) 100644 =================================================================== --- /dev/null +++ new-interface/library.hpp 2014-05-27 13:53:46 +0900 (f1dae24) @@ -0,0 +1,18 @@ +#ifndef GRNXX_LIBRARY_HPP +#define GRNXX_LIBRARY_HPP + +#include "grnxx/types.hpp" + +namespace grnxx { + +class Library { + public: + // ライブラリの名前を返す. + static const char *package(); + // ライブラリのバージョンを返す. + static const char *version(); +}; + +} // namespace grnxx + +#endif // GRNXX_LIBRARY_HPP Added: new-interface/sorter.hpp (+35 -0) 100644 =================================================================== --- /dev/null +++ new-interface/sorter.hpp 2014-05-27 13:53:46 +0900 (dd3185d) @@ -0,0 +1,35 @@ +#ifndef GRNXX_SORTER_HPP +#define GRNXX_SORTER_HPP + +#include "grnxx/types.hpp" + +namespace grnxx { + +class Sorter { + public: + Sorter(); + virtual ~Sorter(); + + // 所属するテーブルを取得する. + virtual Table *table() const = 0; + + // 行の一覧を整列する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // 整列の結果が保証されるのは [offset, offset + limit) の範囲である. + // + // TODO: offset, limit により与えられる境界をまたいで同値が並ぶ場合, + // 同値が続く範囲を適切に返すべきである. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 演算において例外が発生する. + // - リソースを確保できない. + virtual bool sort(int64_t num_row_ids, RowID *row_ids, + int64_t offset, int64_t limit, + Error *error); +}; + +} // namespace grnxx + +#endif // GRNXX_SORTER_HPP Added: new-interface/table.hpp (+260 -0) 100644 =================================================================== --- /dev/null +++ new-interface/table.hpp 2014-05-27 13:53:46 +0900 (f293583) @@ -0,0 +1,260 @@ +#ifndef GRNXX_TABLE_HPP +#define GRNXX_TABLE_HPP + +#include "grnxx/types.hpp" + +namespace grnxx { + +class Table { + public: + // 所属するデータベースを取得する. + virtual DB *db() const = 0; + // 名前を取得する. + virtual const char *name() const = 0; + // カラム ID の最小値を取得する. + virtual ColumnID min_column_id() const = 0; + // カラム ID の最大値を取得する. + virtual ColumnID max_column_id() const = 0; + // キーカラムを取得する. + // キーカラムが存在しないときは nullptr を返す. + virtual Column *key_column() const = 0; + // 行 ID の最小値を取得する. + virtual RowID min_row_id() const = 0; + // 行 ID の最大値を取得する. + virtual RowID max_row_id() const = 0; + + // カラムを作成する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前がカラム名の条件を満たさない. + // - 指定された名前のカラムが存在する. + // - オプションの内容が不正である. + // - 十分なリソースを確保できない. + // - カラムの数が上限に達している. + virtual Column *create_column(const char *column_name, + ColumnType column_type, + const ColumnOptions &column_options, + Error *error) = 0; + // カラムを破棄する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // 破棄するカラムを指す Column * を保持しているときは, + // カラムを破棄する前に nullptr を代入するなどしておいた方がよい. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前のカラムが存在しない. + // - 依存関係を解決できない. + virtual bool drop_column(const char *column_name, Error *error) = 0; + + // カラムの名前を変更する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前のカラムが存在しない. + // - 指定された名前(new)がカラム名の条件を満たさない. + // - 指定された名前(new)のカラムが存在する. + // - 変更前後の名前が同じときは何もせずに成功とする. + // - 索引の更新に失敗する. + virtual bool rename_column(const char *column_name, + const char *new_column_name, + Error *error) = 0; + + // カラムの順番を変更する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // column_name で指定されたカラムを prev_column_name の後ろに移動する. + // ただし, column_name と prev_column_name が同じときは移動せずに成功とする. + // prev_column_name が nullptr もしくは空文字列のときは先頭に移動する. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前のカラムが存在しない. + virtual bool reorder_column(const char *column_name, + const char *prev_column_name, + Error *error) = 0; + + // カラムを取得する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // min_column_id() 以上 max_column_id() 以下のカラム ID に対して + // 呼び出すことですべてのカラムを取得することができる. + // カラム ID は削除や並び替えによって変化することに注意が必要である. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された ID が有効な範囲にない. + virtual Column *get_column(ColumnID column_id, Error *error) const = 0; + + // カラムを検索する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された名前のカラムが存在しない. + virtual Column *find_column(const char *column_name, Error *error) const = 0; + + // キーカラムを設定する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - キーカラムが存在している. + // - 指定された名前のカラムが存在しない. + // - 指定されたカラムの型がキーとしてサポートされていない. + // - 指定されたカラムに同じ値が複数存在する. + // - 一時領域を確保できない. + virtual bool set_key_column(const char *column_name, Error *error) = 0; + + // キーカラムを解除する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - キーカラムが存在しない. + virtual bool unset_key_column(Error *error) = 0; + + // 新しい行を追加する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // 指定された行 ID が有効な場合,もしくは指定されたキーを持つ行が存在する場合, + // その行 ID を *result_row_id に格納する. + // 指定された行 ID が NULL_ROW_ID であれば,追加する行の ID は自動で選択する. + // このとき,選択した行 ID を *result_row_id に格納する. + // ただし,指定された行が存在する以外の理由で行の追加に失敗したときは + // NULL_ROW_ID を *result_row_id に格納する. + // + // まとめると,返り値によって行の追加に成功したかどうかがわかり, + // *result_row_id により該当する行が存在するかどうかがわかる. + // + // TODO: 行 ID の再利用を無効化するオプションがあると便利かもしれない. + // 追加により割り当てられる行 ID は常に昇順という保証があれば, + // 行 ID を降順に取り出すだけで新しい行から順に走査することができる. + // 時刻カラムに対する索引で対応するより,ずっと効率的である. + // ただし,頻繁に削除すると隙間だらけになって効率が落ちる. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された ID が行 ID の最小値より小さいか最大値 + 1 より大きい. + // - キーカラムが存在しないとき + // - 指定された ID を持つ行が存在する. + // - キーカラムが存在するとき + // - 指定された ID を持つ行が存在する. + // - 指定されたキーをキーカラムの型に変換できない. + // - 指定されたキーを持つ行が存在する. + // - 行数が上限に達している. + // - 索引の更新に失敗する. + // - リソースを確保できない. + virtual bool insert_row(RowID request_row_id, + const Datum &key, + RowID *result_row_id, + Error *error) = 0; + + // 行を削除する. + // 成功すれば true を返す. + // 失敗したときは *error にその内容を格納し, false を返す. + // + // 依存関係の解決が許されているときは,参照元を NULL にする. + // 参照元が配列になっているときは,当該要素を取り除いて前方に詰める. + // + // TODO: 依存関係の解決に関する情報は,参照型のカラムに持たせることを検討中. + // SQL の ON DELETE + RESTRICT, CASCADE, SET NULL, NO ACTION に + // 相当するが, NO ACTION は本当に何もしないのもありかもしれない. + // + // TODO: 参照元が配列のときは別に検討する必要がある. + // Groonga の場合は各配列から該当する参照を取り除いて前に詰める. + // 位置によって意味が変わるような使い方では問題があるため, + // SET NULL も使えると嬉しいかもしれない. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - 指定された行が無効である. + // - 指定された行は参照されている. + // - 依存関係を解決できるときは削除をおこなう. + // - 依存関係の解決に失敗した. + // + // TODO: 不要になった(参照されなくなった)タグを削除するような用途を考えると, + // 削除可能な行をすべて削除するという操作が実現できると便利そうである. + // デフラグに似た専用のインタフェースを提供すべきかもしれない. + virtual bool delete_row(RowID row_id, Error *error) = 0; + + // 行の有効性を確認する. + // 指定された行が有効であれば true を返す. + // 指定された行が無効であれば false を返す. + // + // 更新する行を ID で指定されたときなどに用いる. + // + // 無効と判定される条件としては,以下のようなものが挙げられる. + // - 指定された行 ID が有効範囲にない. + // - 指定された行は削除されてから再利用されていない. + virtual bool test_row(RowID row_id, Error *error) const = 0; + + // キーカラムを持つテーブルから行を検索する. + // 成功すれば有効な行 ID を返す. + // 失敗したときは *error にその内容を格納し, NULL_ROW_ID を返す. + // + // 更新する行をキーで指定されたときなどに使う. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - キーカラムが存在しない. + // - 指定されたキーをキーカラムの型に変換できない. + // - 指定されたキーを持つ行が存在しない. + virtual RowID find_row(const Datum &key, Error *error) const = 0; + + // 行 ID を昇順もしくは降順に取得するためのカーソルを作成する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 返り値は std::unique_ptr なので自動的に delete される. + // 自動で delete されて困るときは release() で生のポインタを取り出す必要がある. + // + // 失敗する状況としては,以下のようなものが挙げられる. + // - オプションが不正である. + // - リソースが確保できない. + virtual std::unique_ptr<Cursor> create_cursor( + const CursorOptions &options) const = 0; + + // 行 ID の一覧に適用できる式を作成する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 索引による検索の後で絞り込むために用いる. + // ほかに,スコアの調整や出力の指定,整列条件やグループ化条件の指定にも用いる. + // + // 返り値は std::unique_ptr なので自動的に delete される. + // 自動で delete されて困るときは release() で生のポインタを取り出す必要がある. + // + // TODO: Expression のインタフェースを決める. + // + // TODO: 簡易なものでかまわないので,クエリ文字列をパースして式を構築してくれる + // インタフェースがあれば何かと便利かもしれない. + // テスト用と考えれば,最適化などは一切せず, + // 真っ正直にやってくれるのがベスト. + virtual std::unique_ptr<Expression> create_expression( + const ExpressionOptions &options) const = 0; + + // 整列器を作成する. + // 成功すれば有効なオブジェクトへのポインタを返す. + // 失敗したときは *error にその内容を格納し, nullptr を返す. + // + // 返り値は std::unique_ptr なので自動的に delete される. + // 自動で delete されて困るときは release() で生のポインタを取り出す必要がある. + // + // TODO: Sorter のインタフェースを決める. + // + // TODO: 索引,整列,グループ化の連携について検討する. + // たとえば,整列の途中経過をグループ化に利用するなど. + // 行の整列とグループの整列が考えられる. + virtual std::unique_ptr<Sorter> create_sorter( + const SorterOptions &options) const = 0; + + protected: + Table(); + virtual ~Table(); +}; + +} // namespace grnxx + +#endif // GRNXX_TABLE_HPP Added: new-interface/types.hpp (+90 -0) 100644 =================================================================== --- /dev/null +++ new-interface/types.hpp 2014-05-27 13:53:46 +0900 (9ff7ce1) @@ -0,0 +1,90 @@ +#ifndef GRNXX_TYPES_HPP +#define GRNXX_TYPES_HPP + +#include <algorithm> +#include <cstdint> +#include <cstring> +#include <iosfwd> +#include <limits> +#include <map> +#include <memory> +#include <set> +#include <string> +#include <unordered_map> +#include <vector> + +namespace grnxx { + +using std::int8_t; +using std::int16_t; +using std::int32_t; +using std::int64_t; + +using std::uint8_t; +using std::uint16_t; +using std::uint32_t; +using std::uint64_t; + +using std::size_t; + +using TableID = int64_t; +using ColumnID = int64_t; +using IndexID = int64_t; +using RowID = int64_t; + +constexpr RowID NULL_ROW_ID = RowID(0); +constexpr RowID MIN_ROW_ID = RowID(1); +constexpr RowID MAX_ROW_ID = (RowID(1) << 40) - 1; + +struct DBOptions; +struct TableOptions; +struct ColumnOptions; +struct IndexOptions; + +class DB; +class Table; +class Column; +class Index; +class Datum; + +enum ColumnType { + ID_COLUMN, + BOOL_COLUMN, + INT_COLUMN, + FLOAT_COLUMN, + TEXT_COLUMN, + REF_COLUMN, + BOOL_ARRAY_COLUMN, + INT_ARRAY_COLUMN, + FLOAT_ARRAY_COLUMN, + TEXT_ARRAY_COLUMN, + REF_ARRAY_COLUMN, + INDEX_COLUMN +}; + +std::ostream &operator<<(std::ostream &stream, ColumnType column_type); + +enum DatumType { + NULL_DATUM, + BOOL_DATUM, + INT_DATUM, + FLOAT_DATUM, + TEXT_DATUM, + BOOL_ARRAY_DATUM, + INT_ARRAY_DATUM, + FLOAT_ARRAY_DATUM, + TEXT_ARRAY_DATUM +}; + +std::ostream &operator<<(std::ostream &stream, DatumType datum_type); + +enum IndexType { + TREE_INDEX, + HASH_INDEX +}; + +std::ostream &operator<<(std::ostream &stream, IndexType index_type); + +} // namespace grnxx + +#endif // GRNXX_TYPES_HPP -------------- next part -------------- HTML����������������������������... Télécharger