text: #ifndef NODE_SQLITE3_SRC_STATEMENT_H
  #define NODE_SQLITE3_SRC_STATEMENT_H
  
  #include <node.h>
  
  #include "database.h"
  #include "threading.h"
  
  #include <cstdlib>
  #include <cstring>
  #include <string>
  #include <queue>
  #include <vector>
  
  #include <sqlite3.h>
  #include "nan.h"
  
  using namespace v8;
  using namespace node;
  
  namespace node_sqlite3 {
  
  namespace Values {
      struct Field {
          inline Field(unsigned short _index, unsigned short _type = SQLITE_NULL) :
              type(_type), index(_index) {}
          inline Field(const char* _name, unsigned short _type = SQLITE_NULL) :
              type(_type), index(0), name(_name) {}
  
          unsigned short type;
          unsigned short index;
          std::string name;
      };
  
      struct Integer : Field {
          template <class T> inline Integer(T _name, int64_t val) :
              Field(_name, SQLITE_INTEGER), value(val) {}
          int64_t value;
      };
  
      struct Float : Field {
          template <class T> inline Float(T _name, double val) :
              Field(_name, SQLITE_FLOAT), value(val) {}
          double value;
      };
  
      struct Text : Field {
          template <class T> inline Text(T _name, size_t len, const char* val) :
              Field(_name, SQLITE_TEXT), value(val, len) {}
          std::string value;
      };
  
      struct Blob : Field {
          template <class T> inline Blob(T _name, size_t len, const void* val) :
                  Field(_name, SQLITE_BLOB), length(len) {
              value = (char*)malloc(len);
              memcpy(value, val, len);
          }
          inline ~Blob() {
              free(value);
          }
          int length;
          char* value;
      };
  
      typedef Field Null;
  }
  
  typedef std::vector<Values::Field*> Row;
  typedef std::vector<Row*> Rows;
  typedef Row Parameters;
  
  
  
  class Statement : public ObjectWrap {
  public:
      static Persistent<FunctionTemplate> constructor_template;
  
      static void Init(Handle<Object> target);
      static NAN_METHOD(New);
  
      struct Baton {
          uv_work_t request;
          Statement* stmt;
          Persistent<Function> callback;
          Parameters parameters;
  
          Baton(Statement* stmt_, Handle<Function> cb_) : stmt(stmt_) {
              stmt->Ref();
              request.data = this;
              NanAssignPersistent(callback, cb_);
          }
          virtual ~Baton() {
              for (unsigned int i = 0; i < parameters.size(); i++) {
                  Values::Field* field = parameters[i];
                  DELETE_FIELD(field);
              }
              stmt->Unref();
              NanDisposePersistent(callback);
          }
      };
  
      struct RowBaton : Baton {
          RowBaton(Statement* stmt_, Handle<Function> cb_) :
              Baton(stmt_, cb_) {}
          Row row;
      };
  
      struct RunBaton : Baton {
          RunBaton(Statement* stmt_, Handle<Function> cb_) :
              Baton(stmt_, cb_), inserted_id(0), changes(0) {}
          sqlite3_int64 inserted_id;
          int changes;
      };
  
      struct RowsBaton : Baton {
          RowsBaton(Statement* stmt_, Handle<Function> cb_) :
              Baton(stmt_, cb_) {}
          Rows rows;
      };
  
      struct Async;
  
      struct EachBaton : Baton {
          Persistent<Function> completed;
          Async* async; // Isn't deleted when the baton is deleted.
  
          EachBaton(Statement* stmt_, Handle<Function> cb_) :
              Baton(stmt_, cb_) {}
          virtual ~EachBaton() {
              NanDisposePersistent(completed);
          }
      };
  
      struct PrepareBaton : Database::Baton {
          Statement* stmt;
          std::string sql;
          PrepareBaton(Database* db_, Handle<Function> cb_, Statement* stmt_) :
              Baton(db_, cb_), stmt(stmt_) {
              stmt->Ref();
          }
          virtual ~PrepareBaton() {
              stmt->Unref();
              if (!db->IsOpen() && db->IsLocked()) {
                  // The database handle was closed before the statement could be
                  // prepared.
                  stmt->Finalize();
              }
          }
      };
  
      typedef void (*Work_Callback)(Baton* baton);
  
      struct Call {
          Call(Work_Callback cb_, Baton* baton_) : callback(cb_), baton(baton_) {};
          Work_Callback callback;
          Baton* baton;
      };
  
      struct Async {
          uv_async_t watcher;
          Statement* stmt;
          Rows data;
          NODE_SQLITE3_MUTEX_t;
          bool completed;
          int retrieved;
  
          // Store the callbacks here because we don't have
          // access to the baton in the async callback.
          Persistent<Function> item_cb;
          Persistent<Function> completed_cb;
  
          Async(Statement* st, uv_async_cb async_cb) :
                  stmt(st), completed(false), retrieved(0) {
              watcher.data = this;
              NODE_SQLITE3_MUTEX_INIT
              stmt->Ref();
              uv_async_init(uv_default_loop(), &watcher, async_cb);
          }
  
          ~Async() {
              stmt->Unref();
              NanDisposePersistent(item_cb);
              NanDisposePersistent(completed_cb);
              NODE_SQLITE3_MUTEX_DESTROY
          }
      };
  
      Statement(Database* db_) : ObjectWrap(),
              db(db_),
              _handle(NULL),
              status(SQLITE_OK),
              prepared(false),
              locked(true),
              finalized(false) {
          db->Ref();
      }
  
      ~Statement() {
          if (!finalized) Finalize();
      }
  
      WORK_DEFINITION(Bind);
      WORK_DEFINITION(Get);
      WORK_DEFINITION(Run);
      WORK_DEFINITION(All);
      WORK_DEFINITION(Each);
      WORK_DEFINITION(Reset);
  
      static NAN_METHOD(Finalize);
  
  protected:
      static void Work_BeginPrepare(Database::Baton* baton);
      static void Work_Prepare(uv_work_t* req);
      static void Work_AfterPrepare(uv_work_t* req);
  
      static void AsyncEach(uv_async_t* handle, int status);
      static void CloseCallback(uv_handle_t* handle);
  
      static void Finalize(Baton* baton);
      void Finalize();
  
      template <class T> inline Values::Field* BindParameter(const Handle<Value> source, T pos);
      template <class T> T* Bind(_NAN_METHOD_ARGS, int start = 0, int end = -1);
      bool Bind(const Parameters &parameters);
  
      static void GetRow(Row* row, sqlite3_stmt* stmt);
      static Local<Object> RowToJS(Row* row);
      void Schedule(Work_Callback callback, Baton* baton);
      void Process();
      void CleanQueue();
      template <class T> static void Error(T* baton);
  
  protected:
      Database* db;
  
      sqlite3_stmt* _handle;
      int status;
      std::string message;
  
      bool prepared;
      bool locked;
      bool finalized;
      std::queue<Call*> queue;
  };
  
  }
  
  #endif
  