about summary refs log tree commit diff stats
path: root/data/maps/the_double_sided/rooms/Obverse Blue Area.txtpb
blob: 1a219525319ce339f72577d144b0d2ce9eb16dc1 (plain) (blame)
1
name: "Obverse Blue Area"
me.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#ifndef QUERY_H_7CC5284C
#define QUERY_H_7CC5284C

#include <vector>
#include <stdexcept>
#include <string>
#include <list>
#include <sqlite3.h>
#include <iostream>
#include "statement.h"
#include "binding.h"
#include "order.h"

namespace verbly {

  class database_error : public std::logic_error {
  public:

    database_error(std::string msg, std::string sqlMsg) : std::logic_error(msg + " (" + sqlMsg + ")")
    {
    }
  };

  template <typename Object>
  class query {
  public:

    query(const database& db, sqlite3* ppdb, filter queryFilter, order sortOrder, int limit) : db_(&db)
    {
      if ((sortOrder.getType() == order::type::field)
        && (sortOrder.getSortField().getObject() != Object::objectType))
      {
        throw std::invalid_argument("Can only sort query by a field in the result table");
      }

      statement stmt(Object::objectType, std::move(queryFilter));

      std::string queryString = stmt.getQueryString(Object::select, std::move(sortOrder), limit);
      std::list<binding> bindings = stmt.getBindings();

      if (sqlite3_prepare_v2(ppdb, queryString.c_str(), queryString.length(), &ppstmt_, NULL) != SQLITE_OK)
      {
        std::string errorMsg = sqlite3_errmsg(ppdb);
        sqlite3_finalize(ppstmt_);

        throw database_error("Error preparing query", errorMsg);
      }

      int i = 1;
      for (const binding& value : bindings)
      {
        switch (value.getType())
        {
          case binding::type::integer:
          {
            if (sqlite3_bind_int(ppstmt_, i, value.getInteger()) != SQLITE_OK)
            {
              std::string errorMsg = sqlite3_errmsg(ppdb);
              sqlite3_finalize(ppstmt_);

              throw database_error("Error binding value to query", errorMsg);
            }

            break;
          }

          case binding::type::string:
          {
            if (sqlite3_bind_text(ppstmt_, i, value.getString().c_str(), value.getString().length(), SQLITE_TRANSIENT) != SQLITE_OK)
            {
              std::string errorMsg = sqlite3_errmsg(ppdb);
              sqlite3_finalize(ppstmt_);

              throw database_error("Error binding value to query", errorMsg);
            }

            break;
          }

          case binding::type::invalid:
          {
            throw std::logic_error("Cannot use invalid bindings");
          }

          case binding::type::field:
          {
            throw std::logic_error("Compare field binding made it past statement generation");
          }
        }

        i++;
      }
    }

    ~query()
    {
      sqlite3_finalize(ppstmt_);
    }

    std::vector<Object> all() const
    {
      std::vector<Object> result;

      while (sqlite3_step(ppstmt_) == SQLITE_ROW)
      {
        result.emplace_back(*db_, ppstmt_);
      }

      sqlite3_reset(ppstmt_);

      return result;
    }

    Object first() const
    {
      std::vector<Object> results = all();
      if (!results.empty())
      {
        return results.front();
      } else {
        throw std::logic_error("query returned empty dataset");
      }
    }

  private:
    const database* db_;
    sqlite3_stmt* ppstmt_;

  };

};

#endif /* end of include guard: QUERY_H_7CC5284C */