Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 #ifndef PSQLCURSOR_H_
00009 #define PSQLCURSOR_H_
00010
00011 namespace psql
00012 {
00013
00014 class ICursor
00015 {
00016 };
00017
00024 template<typename BTypes, typename RTypes>
00025 class Cursor : ICursor
00026 {
00027 public:
00034 Cursor(Database& db, std::string const& name, Statement<BTypes, RTypes> const& s):
00035 db(&db),
00036 name(name),
00037 decl_curs("DECLARE " + name + " CURSOR FOR " + s.get_sql(), db),
00038 close_curs("CLOSE " + name, db),
00039 opened(false)
00040 {
00041 }
00047 template<typename... Args>
00048 void open(Args... a)
00049 {
00050 if (db == NULL)
00051 throw PgSqlException("You can't call open on empty cursor");
00052 decl_curs.execute(a...);
00053 db->add_cursor(this);
00054 opened = true;
00055 }
00056
00061 std::vector<typename RTypes::RowType> const& get_buffer()
00062 {
00063 return buffer;
00064 }
00065
00070 void fetch(int count)
00071 {
00072 if (!opened)
00073 throw PgSqlException("You need to open cursor prior to fetching");
00074 Statement<BindTypes<>, RTypes > st(util::concatenate(" ", "FETCH", count, "FROM", name), *db);
00075 buffer = exec_statement(st);
00076 }
00077 virtual ~Cursor()
00078 {
00079 close();
00080 }
00081 Cursor(Cursor const&) = delete;
00082 Cursor& operator=(Cursor const&) = delete;
00086 Cursor():
00087 db(NULL),
00088 opened(false)
00089 {
00090 }
00095 Cursor(Cursor && other):
00096 db(NULL),
00097 opened(false)
00098 {
00099 *this = std::move(other);
00100 }
00106 Cursor& operator=(Cursor && other)
00107 {
00108 if (this == &other)
00109 return *this;
00110 close();
00111 decl_curs = std::move(other.decl_curs);
00112 close_curs = std::move(other.close_curs);
00113 name = std::move(other.name);
00114 db = other.db;
00115 other.db = NULL;
00116 opened = other.opened;
00117 buffer = std::move(other.buffer);
00118 return *this;
00119 }
00120
00124 void close()
00125 {
00126 if (db != NULL && opened && db->in_transaction() && db->is_cursor(this))
00127 {
00128 close_curs.execute();
00129 db->remove_cursor(this);
00130 }
00131 opened = false;
00132 }
00133 private:
00134 Database* db;
00135 std::string name;
00136 Statement<BTypes, RetTypes<> > decl_curs;
00137 Statement<BindTypes<>, RetTypes<> > close_curs;
00138 std::vector<typename RTypes::RowType> buffer;
00139 bool opened;
00140 };
00141
00150 template<typename BTypes, typename RTypes>
00151 Cursor<BTypes, RTypes> make_cursor(Database& db, std::string const& name, Statement<BTypes, RTypes> const& st)
00152 {
00153 return Cursor<BTypes, RTypes>(db, name, st);
00154 }
00155
00156 }
00157 #endif