00001 #ifndef MYSQLPP_RESULT_H
00002 #define MYSQLPP_RESULT_H
00003
00006
00007 #include "defs.h"
00008
00009 #include "exceptions.h"
00010 #include "fields.h"
00011 #include "field_names.h"
00012 #include "field_types.h"
00013 #include "resiter.h"
00014 #include "row.h"
00015
00016 #include <mysql.h>
00017
00018 #include <map>
00019 #include <set>
00020 #include <string>
00021
00022 namespace mysqlpp {
00023
00024 class Connection;
00025
00035
00036 class ResUse {
00037 protected:
00038 Connection *mysql;
00039 mutable MYSQL_RES *mysql_res;
00040 bool throw_exceptions, initialized;
00041 mutable FieldNames *_names;
00042 mutable FieldTypes *_types;
00043 Fields _fields;
00044 std::string _table;
00045
00049 void copy(const ResUse& other);
00050
00051 public:
00052 ResUse () : mysql(0), mysql_res(0), throw_exceptions(false),initialized(false), _names(NULL), _types(NULL), _fields(this) {}
00053 ResUse (MYSQL_RES *result, Connection *m = NULL, bool te = false);
00054 ResUse (const ResUse &other) : initialized(false) {copy(other);}
00055 ~ResUse ();
00056
00057 inline ResUse& operator = (const ResUse &other);
00058
00059 MYSQL_RES *mysql_result (void) {return mysql_res;}
00060
00065 Row fetch_row()
00066 {
00067 if (!mysql_res) { if (throw_exceptions) throw BadQuery("Results not fetched");
00068 else return Row();}
00069 MYSQL_ROW row = mysql_fetch_row(mysql_res);
00070 unsigned long* length = mysql_fetch_lengths(mysql_res);
00071 if (!row || !length) { if (throw_exceptions) throw BadQuery("Bad row");
00072 else return Row();}
00073 return Row(row, this, length, throw_exceptions);
00074 }
00075
00077 bool eof () const {return mysql_eof(mysql_res) != 0;}
00078
00080 unsigned long* fetch_lengths () const {return mysql_fetch_lengths(mysql_res);}
00081
00083 Field& fetch_field () const {return *mysql_fetch_field(mysql_res);}
00084
00086 void field_seek (int field) {mysql_field_seek (mysql_res, field);}
00087
00089 int num_fields() const {return mysql_num_fields(mysql_res);}
00090
00091 void parent_leaving() {mysql = NULL;}
00092
00093 void purge(void)
00094 { if (mysql_res) mysql_free_result(mysql_res); mysql_res=0; if (_names) delete _names; if (_types) delete _types; _names=0; _types=0; _table.erase(); }
00095
00096 operator bool() const {if (mysql_res) return true; return false;}
00097 unsigned int columns() const {return num_fields();}
00098
00100 std::string& table() {return _table;}
00101 const std::string& table() const {return _table;}
00102
00106 inline int field_num(const std::string&) const;
00107
00111 inline std::string& field_name(int);
00112 inline const std::string& field_name(int) const;
00113
00115 inline FieldNames& field_names();
00116 inline const FieldNames& field_names() const;
00117
00119 inline void reset_field_names();
00120
00122 inline mysql_type_info& field_type(int i);
00123 inline const mysql_type_info& field_type(int) const;
00124
00127 inline FieldTypes& field_types();
00128 inline const FieldTypes& field_types() const;
00129
00131 inline void reset_field_types();
00132
00134 inline int names(const std::string& s) const;
00135
00137 inline std::string& names(int i);
00138 inline const std::string& names(int i) const;
00139
00141 inline FieldNames& names();
00142 inline const FieldNames& names() const;
00143
00145 inline void reset_names();
00146
00148 inline mysql_type_info& types(int i);
00149 inline const mysql_type_info& types(int i) const;
00150
00152 inline FieldTypes& types();
00153 inline const FieldTypes& types() const;
00154
00156 inline void reset_types();
00157
00159 const Fields& fields() const {return _fields;}
00160
00162 const Field& fields(unsigned int i) const {return _fields[i];}
00163
00164 bool operator == (const ResUse &other) const
00165 {return mysql_res == other.mysql_res;}
00166
00167 bool operator != (const ResUse &other) const
00168 {return mysql_res != other.mysql_res;}
00169 };
00170
00171
00183
00184 class Result : public ResUse,
00185 public const_subscript_container<Result,Row,const Row>
00186 {
00187 public:
00188 Result () {}
00189 Result (MYSQL_RES *result, bool te = false)
00190 : ResUse(result, NULL, te) {mysql = NULL;}
00191 Result (const Result &other)
00192 : ResUse(other),
00193 const_subscript_container<Result,Row,const Row>()
00194 {mysql = NULL;}
00195 virtual ~Result() {}
00196
00202 const Row fetch_row() const
00203 {
00204 if (!mysql_res) { if (throw_exceptions) throw BadQuery("Results not fetched");
00205 else return Row();}
00206 MYSQL_ROW row = mysql_fetch_row(mysql_res);
00207 unsigned long* length = mysql_fetch_lengths(mysql_res);
00208 if (!row || !length) { if (throw_exceptions) throw BadQuery("Bad row");
00209 else return Row();}
00210 return Row(row, this, length, throw_exceptions);
00211 }
00212
00214 my_ulonglong num_rows() const {
00215 if (initialized) return mysql_num_rows(mysql_res);
00216 else return 0;
00217 }
00218
00220 void data_seek (uint offset) const
00221 {
00222 mysql_data_seek(mysql_res, offset);
00223 }
00224
00226 size_type size() const { return size_type(num_rows()); }
00227
00229 size_type rows() const { return size_type(num_rows()); }
00230
00232 const Row operator [] (size_type i) const {data_seek(i); return fetch_row();}
00233 };
00234
00235
00236 inline void swap (ResUse &x, ResUse &y)
00237 {
00238 ResUse tmp = x;
00239 x = y;
00240 y = tmp;
00241 }
00242
00243 inline void swap (Result &x, Result &y)
00244 {
00245 Result tmp = x;
00246 x = y;
00247 y = tmp;
00248 }
00249
00252 class ResNSel {
00253 public:
00254 bool success;
00255 my_ulonglong insert_id;
00256 my_ulonglong rows;
00257 std::string info;
00258
00259 ResNSel() : success(false) {};
00260 ResNSel (Connection *q);
00261
00262 operator bool() {return success;}
00263 };
00264
00265
00266 inline int ResUse::field_num(const std::string &i) const
00267 {
00268 if (!_names) _names = new FieldNames(this);
00269 return (*_names)[i];
00270 }
00271
00272 inline std::string& ResUse::field_name(int i)
00273 {
00274 if (!_names) _names = new FieldNames(this);
00275 return (*_names)[i];
00276 }
00277
00278 inline const std::string& ResUse::field_name(int i) const
00279 {
00280 if (!_names) _names = new FieldNames(this);
00281 return (*_names)[i];
00282 }
00283
00284 inline FieldNames& ResUse::field_names()
00285 {
00286 if (!_names) _names = new FieldNames(this);
00287 return *_names;
00288 }
00289
00290 inline const FieldNames& ResUse::field_names() const
00291 {
00292 if (!_names) _names = new FieldNames(this);
00293 return *_names;
00294 }
00295
00296 inline void ResUse::reset_field_names()
00297 {
00298 delete _names;
00299 _names = new FieldNames(this);
00300 }
00301
00302
00303 inline mysql_type_info& ResUse::field_type(int i)
00304 {
00305 if (!_types) _types = new FieldTypes(this);
00306 return (*_types)[i];
00307 }
00308
00309 inline const mysql_type_info& ResUse::field_type(int i) const
00310 {
00311 if (!_types) _types = new FieldTypes(this);
00312 return (*_types)[i];
00313 }
00314
00315 inline FieldTypes& ResUse::field_types()
00316 {
00317 if (!_types) _types = new FieldTypes(this);
00318 return *_types;
00319 }
00320
00321 inline const FieldTypes& ResUse::field_types() const
00322 {
00323 if (!_types) _types = new FieldTypes(this);
00324 return *_types;
00325 }
00326
00327 inline void ResUse::reset_field_types()
00328 {
00329 delete _types;
00330 _types = new FieldTypes(this);
00331 }
00332
00333 inline int ResUse::names(const std::string& s) const {return field_num(s);}
00334 inline std::string& ResUse::names(int i) {return field_name(i);}
00335 inline const std::string& ResUse::names(int i) const {return field_name(i);}
00336 inline FieldNames& ResUse::names() {return field_names();}
00337 inline const FieldNames& ResUse::names() const {return field_names();}
00338 inline void ResUse::reset_names() {reset_field_names();}
00339
00340 inline mysql_type_info& ResUse::types(int i) {return field_type(i);}
00341 inline const mysql_type_info& ResUse::types(int i) const {return field_type(i);}
00342 inline FieldTypes& ResUse::types() {return field_types();}
00343 inline const FieldTypes& ResUse::types() const {return field_types();}
00344 inline void ResUse::reset_types() {reset_field_types();}
00345
00346
00347 inline ResUse& ResUse::operator = (const ResUse &other)
00348 {
00349 if (this == &other) return *this;
00350 copy(other); other.mysql_res=NULL;
00351 return *this;
00352 }
00353
00354 }
00355
00356 #endif
00357