summaryrefslogtreecommitdiff
path: root/ext/librethinkdbxx/src/term.cc
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2017-11-02 07:05:11 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2017-11-02 07:05:11 -0700
commit4e88c80a22b6ca982341413ee806ade0df57b4b7 (patch)
tree82c2daaac597f74595bc83c18646280a56898e1a /ext/librethinkdbxx/src/term.cc
parenta6203ed0389c1b995ebe94935b2d1ddeb01f36ee (diff)
downloadinfinitytier-4e88c80a22b6ca982341413ee806ade0df57b4b7.tar.gz
infinitytier-4e88c80a22b6ca982341413ee806ade0df57b4b7.zip
RethinkDB native connector work, minor fixes.
Diffstat (limited to 'ext/librethinkdbxx/src/term.cc')
-rw-r--r--ext/librethinkdbxx/src/term.cc285
1 files changed, 285 insertions, 0 deletions
diff --git a/ext/librethinkdbxx/src/term.cc b/ext/librethinkdbxx/src/term.cc
new file mode 100644
index 00000000..711ef27d
--- /dev/null
+++ b/ext/librethinkdbxx/src/term.cc
@@ -0,0 +1,285 @@
+#include <cstdlib>
+#include <set>
+
+#include "term.h"
+#include "json_p.h"
+
+namespace RethinkDB {
+
+using TT = Protocol::Term::TermType;
+
+struct {
+ Datum operator() (const Array& array) {
+ Array copy;
+ copy.reserve(array.size());
+ for (const auto& it : array) {
+ copy.emplace_back(it.apply<Datum>(*this));
+ }
+ return Datum(Array{TT::MAKE_ARRAY, std::move(copy)});
+ }
+ Datum operator() (const Object& object) {
+ Object copy;
+ for (const auto& it : object) {
+ copy.emplace(it.first, it.second.apply<Datum>(*this));
+ }
+ return std::move(copy);
+ }
+ template<class T>
+ Datum operator() (T&& atomic) {
+ return Datum(std::forward<T>(atomic));
+ }
+} datum_to_term;
+
+Term::Term(Datum&& datum_) : datum(datum_.apply<Datum>(datum_to_term)) { }
+Term::Term(const Datum& datum_) : datum(datum_.apply<Datum>(datum_to_term)) { }
+
+Term::Term(Term&& orig, OptArgs&& new_optargs) : datum(Nil()) {
+ Datum* cur = orig.datum.get_nth(2);
+ Object optargs;
+ free_vars = std::move(orig.free_vars);
+ if (cur) {
+ optargs = std::move(cur->extract_object());
+ }
+ for (auto& it : new_optargs) {
+ optargs.emplace(std::move(it.first), alpha_rename(std::move(it.second)));
+ }
+ datum = Array{ std::move(orig.datum.extract_nth(0)), std::move(orig.datum.extract_nth(1)), std::move(optargs) };
+}
+
+Term nil() {
+ return Term(Nil());
+}
+
+Cursor Term::run(Connection& conn, OptArgs&& opts) {
+ if (!free_vars.empty()) {
+ throw Error("run: term has free variables");
+ }
+
+ return conn.start_query(this, std::move(opts));
+}
+
+struct {
+ Datum operator() (Object&& object, const std::map<int, int>& subst, bool) {
+ Object ret;
+ for (auto& it : object) {
+ ret.emplace(std::move(it.first), std::move(it.second).apply<Datum>(*this, subst, false));
+ }
+ return ret;
+ }
+ Datum operator() (Array&& array, const std::map<int, int>& subst, bool args) {
+ if (!args) {
+ double cmd = array[0].extract_number();
+ if (cmd == static_cast<int>(TT::VAR)) {
+ double var = array[1].extract_nth(0).extract_number();
+ auto it = subst.find(static_cast<int>(var));
+ if (it != subst.end()) {
+ return Array{ TT::VAR, { it->second }};
+ }
+ }
+ if (array.size() == 2) {
+ return Array{ std::move(array[0]), std::move(array[1]).apply<Datum>(*this, subst, true) };
+ } else {
+ return Array{
+ std::move(array[0]),
+ std::move(array[1]).apply<Datum>(*this, subst, true),
+ std::move(array[2]).apply<Datum>(*this, subst, false) };
+ }
+ } else {
+ Array ret;
+ for (auto& it : array) {
+ ret.emplace_back(std::move(it).apply<Datum>(*this, subst, false));
+ }
+ return ret;
+ }
+ }
+ template <class T>
+ Datum operator() (T&& a, const std::map<int, int>&, bool) {
+ return std::move(a);
+ }
+} alpha_renamer;
+
+static int new_var_id(const std::map<int, int*>& vars) {
+ while (true) {
+ int id = gen_var_id();
+ if (vars.find(id) == vars.end()) {
+ return id;
+ }
+ }
+}
+
+Datum Term::alpha_rename(Term&& term) {
+ if (free_vars.empty()) {
+ free_vars = std::move(term.free_vars);
+ return std::move(term.datum);
+ }
+
+ std::map<int, int> subst;
+ for (auto it = term.free_vars.begin(); it != term.free_vars.end(); ++it) {
+ auto var = free_vars.find(it->first);
+ if (var == free_vars.end()) {
+ free_vars.emplace(it->first, it->second);
+ } else if (var->second != it->second) {
+ int id = new_var_id(free_vars);
+ subst.emplace(it->first, id);
+ free_vars.emplace(id, it->second);
+ }
+ }
+ if (subst.empty()) {
+ return std::move(term.datum);
+ } else {
+ return term.datum.apply<Datum>(alpha_renamer, subst, false);
+ }
+}
+
+int gen_var_id() {
+ return ::random() % (1<<30);
+}
+
+C0_IMPL(db_list, DB_LIST)
+C0_IMPL(table_list, TABLE_LIST)
+C0_IMPL(random, RANDOM)
+C0_IMPL(now, NOW)
+C0_IMPL(range, RANGE)
+C0_IMPL(error, ERROR)
+C0_IMPL(uuid, UUID)
+C0_IMPL(literal, LITERAL)
+CO0_IMPL(wait, WAIT)
+C0_IMPL(rebalance, REBALANCE)
+CO0_IMPL(random, RANDOM)
+
+Term row(TT::IMPLICIT_VAR, {});
+Term minval(TT::MINVAL, {});
+Term maxval(TT::MAXVAL, {});
+
+Term binary(const std::string& data) {
+ return expr(Binary(data));
+}
+
+Term binary(std::string&& data) {
+ return expr(Binary(data));
+}
+
+Term binary(const char* data) {
+ return expr(Binary(data));
+}
+
+struct {
+ bool operator() (const Object& object) {
+ for (const auto& it : object) {
+ if (it.second.apply<bool>(*this)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ bool operator() (const Array& array) {
+ int type = *array[0].get_number();
+ if (type == static_cast<int>(TT::IMPLICIT_VAR)) {
+ return true;
+ }
+ if (type == static_cast<int>(TT::FUNC)) {
+ return false;
+ }
+ for (const auto& it : *array[1].get_array()) {
+ if (it.apply<bool>(*this)) {
+ return true;
+ }
+ }
+ if (array.size() == 3) {
+ return array[2].apply<bool>(*this);
+ } else {
+ return false;
+ }
+ }
+ template <class T>
+ bool operator() (T) {
+ return false;
+ }
+} needs_func_wrap;
+
+Term Term::func_wrap(Term&& term) {
+ if (term.datum.apply<bool>(needs_func_wrap)) {
+ return Term(TT::FUNC, {expr(Array{new_var_id(term.free_vars)}), std::move(term)});
+ }
+ return term;
+}
+
+Term Term::func_wrap(const Term& term) {
+ if (term.datum.apply<bool>(needs_func_wrap)) {
+ // TODO return Term(TT::FUNC, {expr(Array{new_var_id(Term.free_vars)}), Term.copy()});
+ return Term(Nil());
+ }
+ return term;
+}
+
+Term Term::make_object(std::vector<Term>&& args) {
+ if (args.size() % 2 != 0) {
+ return Term(TT::OBJECT, std::move(args));
+ }
+ std::set<std::string> keys;
+ for (auto it = args.begin(); it != args.end() && it + 1 != args.end(); it += 2) {
+ std::string* key = it->datum.get_string();
+ if (!key || keys.count(*key)) {
+ return Term(TT::OBJECT, std::move(args));
+ }
+ keys.insert(*key);
+ }
+ Term ret{Nil()};
+ Object object;
+ for (auto it = args.begin(); it != args.end(); it += 2) {
+ std::string* key = it->datum.get_string();
+ object.emplace(std::move(*key), ret.alpha_rename(std::move(*(it + 1))));
+ }
+ ret.datum = std::move(object);
+ return ret;
+}
+
+Term Term::make_binary(Term&& term) {
+ std::string* string = term.datum.get_string();
+ if (string) {
+ return expr(Binary(std::move(*string)));
+ }
+ return Term(TT::BINARY, std::vector<Term>{term});
+}
+
+Term::Term(OptArgs&& optargs) : datum(Nil()) {
+ Object oargs;
+ for (auto& it : optargs) {
+ oargs.emplace(it.first, alpha_rename(std::move(it.second)));
+ }
+ datum = std::move(oargs);
+}
+
+OptArgs optargs() {
+ return OptArgs{};
+}
+
+Term january(TT::JANUARY, {});
+Term february(TT::FEBRUARY, {});
+Term march(TT::MARCH, {});
+Term april(TT::APRIL, {});
+Term may(TT::MAY, {});
+Term june(TT::JUNE, {});
+Term july(TT::JULY, {});
+Term august(TT::AUGUST, {});
+Term september(TT::SEPTEMBER, {});
+Term october(TT::OCTOBER, {});
+Term november(TT::NOVEMBER, {});
+Term december(TT::DECEMBER, {});
+Term monday(TT::MONDAY, {});
+Term tuesday(TT::TUESDAY, {});
+Term wednesday(TT::WEDNESDAY, {});
+Term thursday(TT::THURSDAY, {});
+Term friday(TT::FRIDAY, {});
+Term saturday(TT::SATURDAY, {});
+Term sunday(TT::SUNDAY, {});
+
+Term Term::copy() const {
+ return *this;
+}
+
+Datum Term::get_datum() const {
+ return datum;
+}
+
+}