• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

mysqlpl.h

Go to the documentation of this file.
00001 
00002  //
00003  // mysqlpl.h
00004  //
00005  // Copyright (c) 2004, 2006, 2007, 2009, 2010, 2012 Martin Fuchs <martin-fuchs@gmx.net>
00006  //
00007 
00008 /*
00009 
00010   All rights reserved.
00011 
00012   Redistribution and use in source and binary forms, with or without
00013   modification, are permitted provided that the following conditions are met:
00014 
00015   * Redistributions of source code must retain the above copyright
00016     notice, this list of conditions and the following disclaimer.
00017   * Redistributions in binary form must reproduce the above copyright
00018     notice, this list of conditions and the following disclaimer in
00019     the documentation and/or other materials provided with the
00020     distribution.
00021 
00022   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00023   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00026   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00027   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00028   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00029   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00030   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00031   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032   POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #ifndef _MYSQLPL_H
00037 
00038 
00039 #ifdef _MSC_VER
00040 #pragma warning(disable: 4786)
00041 #endif
00042 
00043 #if defined(_WIN32) && !defined(_WINDOWS_)
00044 #include <windows.h>    // for LPCTSTR
00045 #else
00046 #include <stdlib.h>
00047 #include <string.h>
00048 #endif
00049 
00050 #include <map>
00051 #include <string>
00052 #include <vector>
00053 #include <ostream>
00054 #include <sstream>
00055 #include <exception>
00056 
00057 
00058  // tested with MySQL version 4.0.24 and above (needs MySQL 4.1 to use native prepared statements)
00059 #include <mysql.h>
00060 
00061 #ifdef _MSC_VER
00062 #ifndef _NO_COMMENT
00063 #pragma comment(lib, "libmySQL")
00064 
00065 #if defined(_DEBUG) && defined(_DLL)    // DEBUG version only supported with MSVCRTD
00066 #pragma comment(lib, "mysqlpld")
00067 #else
00068 #ifdef _DLL
00069 #pragma comment(lib, "mysqlpl")
00070 #elif defined(_MT)
00071 #pragma comment(lib, "mysqlplt")
00072 #else
00073 #pragma comment(lib, "mysqlpll")
00074 #endif
00075 #endif
00076 
00077 #endif // _NO_COMMENT
00078 
00079 #define LONGLONG __int64
00080 
00081 #else  // _MSC_VER
00082 
00083 #define LONGLONG long long
00084 
00085 #endif // _MSC_VER
00086 
00087 
00088 namespace MySqlPL {
00089 
00090 
00091 #ifndef MYSQLPL_PREP_STMT
00092 #if MYSQL_VERSION_ID>=41000
00093 #define MYSQLPL_PREP_STMT   1
00094 #else
00095 #define MYSQLPL_PREP_STMT   0
00096 #endif
00097 #endif
00098 
00099 
00100  /// MySQL Errorhandling
00101 
00102 struct SqlStatement;
00103 
00104 struct MSqlException : public std::exception
00105 {
00106     typedef std::exception super;
00107 
00108     MSqlException(MYSQL* db, const char* file, int line);
00109 #if MYSQLPL_PREP_STMT
00110     MSqlException(MYSQL_STMT* s, const char* file, int line);
00111     MSqlException(MYSQL_STMT* s, SqlStatement& stmt, const char* file, int line);
00112 #endif
00113     MSqlException(const char* msg, const char* file, int line);
00114 
00115     ~MSqlException() throw () {}
00116 
00117     virtual const char* what() const throw () {return _msg.c_str();}
00118 
00119     unsigned    _sql_error_code;
00120     std::string _msg;
00121 #if MYSQLPL_PREP_STMT
00122     std::string _sqlstate;
00123 #endif
00124     std::string _last_sql;
00125     const char* _file;
00126     int         _line;
00127 };
00128 
00129 #ifndef MYSQLPL_EXCEPTION
00130 #define MYSQLPL_EXCEPTION MySqlPL::MSqlException
00131 #endif
00132 
00133 #define THROW_MYSQLPL_EXCEPTION(par) throw MYSQLPL_EXCEPTION(par, __FILE__, __LINE__)
00134 
00135 
00136  /// error handling functions
00137 
00138 inline void mysqlpl_check_error(MYSQL* db)
00139 {
00140     unsigned int error = mysql_errno(db);
00141 
00142     if (error != 0)
00143         THROW_MYSQLPL_EXCEPTION(db);
00144 }
00145 
00146 inline void mysqlpl_check_error(MYSQL* db, int res)
00147 {
00148     if (res) {
00149         unsigned int error = mysql_errno(db);
00150 
00151         if (error != 0)
00152             THROW_MYSQLPL_EXCEPTION(db);
00153     }
00154 }
00155 
00156 inline void mysqlpl_check_error(MYSQL* db, my_bool b)
00157 {
00158     if (b) {
00159         unsigned int error = mysql_errno(db);
00160 
00161         if (error != 0)
00162             THROW_MYSQLPL_EXCEPTION(db);
00163     }
00164 }
00165 
00166 #if MYSQLPL_PREP_STMT
00167 inline void mysqlpl_check_error(MYSQL_STMT* s)
00168 {
00169     unsigned int error = mysql_stmt_errno(s);
00170 
00171     if (error != 0)
00172         THROW_MYSQLPL_EXCEPTION(s);
00173 }
00174 
00175 inline void mysqlpl_check_error(MYSQL_STMT* s, int res)
00176 {
00177     if (res) {
00178         unsigned int error = mysql_stmt_errno(s);
00179 
00180         if (error != 0)
00181             THROW_MYSQLPL_EXCEPTION(s);
00182     }
00183 }
00184 
00185 inline void mysqlpl_check_error(MYSQL_STMT* s, my_bool b)
00186 {
00187     if (b) {
00188         unsigned int error = mysql_stmt_errno(s);
00189 
00190         if (error != 0)
00191             THROW_MYSQLPL_EXCEPTION(s);
00192     }
00193 }
00194 #endif
00195 
00196 
00197 struct MSqlEnv
00198 {
00199     MSqlEnv(MYSQL* mysql=NULL)
00200     {
00201         _mysql = mysql_init(NULL);
00202     }
00203 
00204     ~MSqlEnv()
00205     {
00206         mysql_close(_mysql);
00207     }
00208 
00209     operator MYSQL*() const {return _mysql;}
00210 
00211 protected:
00212     MYSQL*  _mysql;
00213 };
00214 
00215 
00216  /// simple MySQL login to database
00217 
00218 struct MSqlConnection
00219 {
00220     MSqlConnection(MSqlEnv& env)
00221      :  _env(env),
00222         _db(NULL),
00223         _connected(false)
00224     {
00225     }
00226 
00227     MSqlConnection(MSqlEnv& env, const char* username, const char* password, const char* db_name,
00228                     const char* host="localhost", unsigned port=3306, unsigned long clientflag=0)
00229      :  _env(env),
00230         _db(NULL),
00231         _connected(false)
00232     {
00233         connect(username, password, db_name, host, port, clientflag);
00234     }
00235 
00236     void connect(const char* username, const char* password, const char* db_name,
00237                     const char* host="localhost", unsigned port=3306, unsigned long clientflag=0);
00238 
00239     ~MSqlConnection()
00240     {
00241         /*see MSqlEnv::~MSqlEnv()
00242         if (_connected)
00243             mysql_close(_mysql);
00244         */
00245     }
00246 
00247 
00248 #if MYSQLPL_PREP_STMT
00249      // get warnings
00250     unsigned get_warnings_count() const;
00251 
00252     std::string get_info() const;
00253 
00254     void print_warnings(std::ostream& out)
00255     {
00256         while(get_warnings_count())
00257             out << get_info() << std::endl;
00258     }
00259 #else
00260     const char* get_info() const;
00261 
00262     void print_warnings(std::ostream& out)
00263     {
00264         const char* info = get_info();
00265 
00266         if (info)
00267             out << info << std::endl;
00268     }
00269 #endif
00270 
00271      // get last generated insert ID
00272     LONGLONG get_insert_id() const
00273     {
00274         return mysql_insert_id(_db);
00275     }
00276 
00277 
00278     void commit()
00279     {
00280 #if MYSQLPL_PREP_STMT
00281         my_bool res = mysql_commit(_db);
00282 #else
00283         my_bool res = mysql_query(_db, "commit");
00284 #endif
00285         mysqlpl_check_error(_env, res);
00286     }
00287 
00288     void rollback()
00289     {
00290 #if MYSQLPL_PREP_STMT   //@@
00291         my_bool res = mysql_rollback(_db);
00292 #else
00293         my_bool res = mysql_query(_db, "rollback");
00294 #endif
00295         mysqlpl_check_error(_env, res);
00296     }
00297 
00298     operator MYSQL*() const {return _db;}
00299 
00300 protected:
00301     MSqlEnv& _env;
00302     MYSQL*  _db;
00303 
00304     bool    _connected;
00305 
00306 private:
00307      // disallow copy constructor usage
00308     MSqlConnection(const MSqlConnection&);
00309 };
00310 
00311 
00312  /// column description
00313 
00314 struct ColumnType
00315 {
00316     std::string     _table_name;
00317     std::string     _name;
00318     enum_field_types _data_type;
00319     int             _width;
00320     int             _decimals;
00321     int             _flags;
00322 
00323     ColumnType()
00324     {
00325         _data_type = (enum_field_types)-1;
00326         _width = 0;
00327         _decimals = 0;
00328         _flags = 0;
00329     }
00330 
00331     std::string get_type_str(bool show_null=false) const;
00332 
00333     void init(const MYSQL_FIELD*);
00334 };
00335 
00336 
00337  /// indicator variable
00338 
00339 struct SqlInd
00340 {
00341     SqlInd(my_bool is_null=1)
00342      : _is_null(is_null)
00343     {
00344     }
00345 
00346     operator my_bool() const {return _is_null;}
00347     operator my_bool*() {return &_is_null;}
00348 
00349     bool is_null() const {return _is_null!=0;}
00350     bool is_not_null() const {return _is_null==0;}
00351 
00352     void clear() {_is_null = 1;}
00353     void set() {_is_null = 0;}
00354 
00355 protected:
00356     my_bool _is_null;
00357 };
00358 
00359 
00360 struct SqlValue
00361 {
00362     SqlValue() {}
00363     SqlValue(const SqlValue& other) : _ind(other._ind) {}
00364 
00365     bool is_null() const {return _ind.is_null();}
00366     bool is_not_null() const {return _ind.is_not_null();}
00367 
00368     const SqlInd& ind() const {return _ind;}
00369     SqlInd& ind() {return _ind;}
00370 
00371 protected:
00372     SqlInd  _ind;
00373 };
00374 
00375 
00376 #if MYSQLPL_PREP_STMT
00377 
00378  /// int with indicator variable
00379 
00380 struct SqlInt : public SqlValue
00381 {
00382     SqlInt()    // NULL constructor
00383     {
00384     }
00385 
00386     SqlInt(int value)
00387      :  _value(value)
00388     {
00389         _ind.set();
00390     }
00391 
00392     SqlInt(const SqlInt& other)
00393      :  SqlValue(other),
00394         _value(other._value)
00395     {
00396     }
00397 
00398     enum {INT_NULL = -1};
00399 
00400     operator int() const {return _ind.is_null()? INT_NULL: _value;}
00401     int& get_ref() {return _value;}
00402 
00403     std::string str() const;
00404 
00405 protected:
00406     int     _value;
00407 };
00408 
00409 
00410  /// 64 bit integer with indicator variable
00411 
00412 struct SqlInteger : public SqlValue
00413 {
00414     SqlInteger()    // NULL constructor
00415     {
00416     }
00417 
00418     SqlInteger(int value)
00419      :  _value(value)
00420     {
00421         _ind.set();
00422     }
00423 
00424     SqlInteger(const SqlInteger& other)
00425      :  SqlValue(other),
00426         _value(other._value)
00427     {
00428     }
00429 
00430     enum {INT_NULL = -1};
00431 
00432     operator LONGLONG() const {return _ind.is_null()? INT_NULL: _value;}
00433     LONGLONG& get_ref() {return _value;}
00434 
00435     std::string str() const;
00436 
00437 protected:
00438     LONGLONG _value;
00439 };
00440 
00441 
00442 struct SqlString : public SqlValue
00443 {
00444     SqlString(int blen=2000)
00445      :  _blen(blen),
00446         _str((char*)malloc((blen+1)*sizeof(char)))
00447     {
00448         *_str = '\0';
00449     }
00450 
00451     SqlString(const char* s, int blen=2000)
00452      :  _blen(blen),
00453         _str((char*)malloc((blen+1)*sizeof(char)))
00454     {
00455         operator=(s);
00456     }
00457 
00458     SqlString(const SqlString& other)
00459      :  SqlValue(other),
00460         _blen(other._blen),
00461         _str((char*)malloc((other._blen+1)*sizeof(char)))
00462     {
00463         strcpyn(_str, other._str, _blen+1);
00464     }
00465 
00466     ~SqlString()
00467     {
00468         free(_str);
00469     }
00470 
00471     int len() const {return is_null()? 0: strlen(_str);}
00472     int blen() const {return _blen;}
00473     int alen() const {return _blen + 1;}
00474 
00475     void resize(int l) {_blen = l; _str = (char*)realloc(_str, (l+1)*sizeof(char));}
00476     void clear() {*_str = '\0'; _ind.clear();}
00477 
00478     char* str() {return _str;}  // Note: _ind is not checked by this function.
00479     char* str(int l) {resize(l); return _str;}  // Note: _ind is not changed by this function.
00480 
00481     const char* c_str() const {return is_null()? "": _str;}
00482     operator const char*() const {return is_null()? "": _str;}
00483 
00484     SqlString& operator=(const char* s)
00485     {
00486         if (s) {
00487 #ifdef __STDC_WANT_SECURE_LIB__
00488             strcpy_s(_str, (_blen+1)*sizeof(char), s);
00489 #else
00490             strcpy(_str, s);
00491 #endif
00492             _ind.set();
00493         } else {
00494             *_str = '\0';
00495             _ind.clear();
00496         }
00497 
00498         return *this;
00499     }
00500 
00501     SqlString& operator=(const std::string& s)
00502     {
00503         strcpyn(_str, c_str(), blen()+1);
00504         _ind.set();
00505 
00506         return *this;
00507     }
00508 
00509     friend std::ostream& operator<<(std::ostream& os, const SqlString& str) {if (str.is_not_null()) os << str._str; return os;}
00510 
00511     static inline char* strcpyn(char* dest, const char*source, size_t count)
00512     {
00513         char* d = dest;
00514 
00515         for(const char* s=source; count&&(*d++=*s++); )
00516             count--;
00517 
00518         return dest;
00519     }
00520 
00521 protected:
00522     short   _blen;
00523     char*   _str;
00524 };
00525 
00526 
00527  /// wrapper for MYSQL_TIME
00528 
00529 struct SqlDate : public MYSQL_TIME, public SqlValue
00530 {
00531     typedef MYSQL_TIME super;
00532 
00533     SqlDate(enum_mysql_timestamp_type type=MYSQL_TIMESTAMP_DATETIME) {super::time_type = type;}
00534     SqlDate(const char* str, enum_mysql_timestamp_type type=MYSQL_TIMESTAMP_DATETIME);
00535     SqlDate(const SqlDate& other, enum_mysql_timestamp_type type);
00536 
00537     enum_field_types get_data_type() const
00538     {
00539         switch(super::time_type) {
00540           case MYSQL_TIMESTAMP_NONE:        return MYSQL_TYPE_NULL;
00541           case MYSQL_TIMESTAMP_DATE:        return MYSQL_TYPE_DATE;
00542           case MYSQL_TIMESTAMP_TIME:        return MYSQL_TYPE_TIME;
00543           case MYSQL_TIMESTAMP_DATETIME:    return MYSQL_TYPE_DATETIME;
00544           default:                          return (enum_field_types)-1;
00545         }
00546     }
00547 
00548     std::string str() const;
00549 };
00550 
00551 
00552 struct SqlNumber : public SqlValue
00553 {
00554     SqlNumber() {}
00555     SqlNumber(int i) {_value = i; _ind.set();}
00556     SqlNumber(LONGLONG l) {_value = (double)l; _ind.set();}
00557     SqlNumber(double d) {_value = d; _ind.set();}
00558     SqlNumber(const char* s);
00559 
00560     void* get_ref() {return &_value;}
00561 
00562     std::string str() const;
00563 
00564     operator double*() {return &_value;}
00565     operator const double*() const {return &_value;}
00566 
00567     int get_int() const
00568     {
00569         return _ind.is_not_null()? (int)(_value+.5): 0;
00570     }
00571 
00572 #ifdef _MSC_VER
00573     LONGLONG get_int64() const
00574     {
00575         return _ind.is_not_null()? (LONGLONG)(_value+.5): 0;
00576     }
00577 #endif
00578 
00579     double get_double() const
00580     {
00581         return _ind.is_not_null()? _value: 0.;
00582     }
00583 
00584 protected:
00585     double  _value;
00586 };
00587 
00588 
00589 struct MSqlBlob : public SqlValue
00590 {
00591     MSqlBlob(int len=0x10000)
00592      :  _len(len),
00593         _ptr(NULL),
00594         _own(true)
00595     {
00596     }
00597 
00598     MSqlBlob(void* ptr, int len)
00599      :  _len(len),
00600         _ptr(ptr),
00601         _own(false)
00602     {
00603     }
00604 
00605     MSqlBlob(const MSqlBlob& other)
00606      :  SqlValue(other),
00607         _len(other._len),
00608         _own(true)
00609     {
00610         if (other._ptr)
00611             memcpy(_ptr=malloc(other._len), other._ptr, other._len);
00612         else
00613             _ptr = NULL;
00614     }
00615 
00616     ~MSqlBlob()
00617     {
00618         if (_own)
00619             free(_ptr);
00620     }
00621 
00622     void* get_ref()
00623     {
00624         if (_own && !_ptr)  // delayed buffer allocation
00625             _ptr = malloc(_len);
00626 
00627         return _ptr;
00628     }
00629 
00630     int get_len() const {return _len;}
00631     unsigned long& get_len_ref() {return _len;}
00632 
00633     std::string str() const;
00634 
00635 protected:
00636     unsigned long _len;
00637     void*   _ptr;
00638     bool    _own;
00639 };
00640 
00641 #endif
00642 
00643 
00644 #if MYSQL_VERSION_ID<41000  //@@
00645 #define MYSQL_TYPE_DECIMAL      FIELD_TYPE_DECIMAL
00646 #define MYSQL_TYPE_TINY         FIELD_TYPE_TINY
00647 #define MYSQL_TYPE_SHORT        FIELD_TYPE_SHORT
00648 #define MYSQL_TYPE_LONG         FIELD_TYPE_LONG
00649 #define MYSQL_TYPE_FLOAT        FIELD_TYPE_FLOAT
00650 #define MYSQL_TYPE_DOUBLE       FIELD_TYPE_DOUBLE
00651 #define MYSQL_TYPE_NULL         FIELD_TYPE_NULL
00652 #define MYSQL_TYPE_TIMESTAMP    FIELD_TYPE_TIMESTAMP
00653 #define MYSQL_TYPE_LONGLONG     FIELD_TYPE_LONGLONG
00654 #define MYSQL_TYPE_INT24        FIELD_TYPE_INT24
00655 #define MYSQL_TYPE_DATE         FIELD_TYPE_DATE
00656 #define MYSQL_TYPE_TIME         FIELD_TYPE_TIME
00657 #define MYSQL_TYPE_DATETIME     FIELD_TYPE_DATETIME
00658 #define MYSQL_TYPE_YEAR         FIELD_TYPE_YEAR
00659 #define MYSQL_TYPE_ENUM         FIELD_TYPE_ENUM
00660 #define MYSQL_TYPE_SET          FIELD_TYPE_SET
00661 #define MYSQL_TYPE_TINY_BLOB    FIELD_TYPE_TINY_BLOB
00662 #define MYSQL_TYPE_MEDIUM_BLOB  FIELD_TYPE_MEDIUM_BLOB
00663 #define MYSQL_TYPE_LONG_BLOB    FIELD_TYPE_LONG_BLOB
00664 #define MYSQL_TYPE_BLOB         FIELD_TYPE_BLOB
00665 #define MYSQL_TYPE_VAR_STRING   FIELD_TYPE_VAR_STRING
00666 #define MYSQL_TYPE_STRING       FIELD_TYPE_STRING
00667 #define MYSQL_TYPE_GEOMETRY     FIELD_TYPE_GEOMETRY
00668 #define MYSQL_TYPE_BIT          FIELD_TYPE_BIT
00669 /* only since MySQL 5.0
00670 #define MYSQL_TYPE_NEWDECIMAL   FIELD_TYPE_NEWDECIMAL
00671 #define MYSQL_TYPE_NEWDATE      FIELD_TYPE_NEWDATE
00672 */
00673 #endif
00674 
00675 struct BindPar
00676 {
00677     void*       _ptr;
00678     int         _len;
00679     enum_field_types _type;
00680     my_bool*    _pind;
00681     unsigned long*_plen;
00682 
00683     BindPar()
00684     {
00685         _ptr    = NULL;
00686         _len    = 0;
00687         _type   = (enum_field_types)-1;
00688         _pind   = NULL;
00689         _plen   = NULL;
00690     }
00691 
00692     BindPar(const char* buffer, int len=-1, enum_field_types type=MYSQL_TYPE_VAR_STRING, my_bool* pind=NULL)
00693     {
00694         _ptr    = (void*) buffer;
00695         if (len == -1)  // not applicable for OUT variables
00696             _len = strlen(buffer);
00697         else
00698             _len = len;
00699         _type   = type;
00700         _pind   = pind;
00701         _plen   = NULL;
00702     }
00703 
00704     BindPar(const std::string& str)
00705     {
00706         _ptr    = (void*) str.c_str();
00707         _len    = str.length();
00708         _type   = MYSQL_TYPE_VAR_STRING;
00709         _pind   = NULL;
00710         _plen   = NULL;
00711     }
00712 
00713 #ifdef ISSD_EXP
00714     BindPar(const String& str)
00715     {
00716         _ptr    = (void*) str.c_str();
00717         _len    = str.len();
00718         _type   = MYSQL_TYPE_VAR_STRING;
00719         _pind   = NULL;
00720         _plen   = NULL;
00721     }
00722 #endif
00723 
00724     BindPar(const int& var, my_bool* pind=NULL)
00725     {
00726         _ptr    = (void*)&var;
00727         _len    = sizeof(var);
00728         _type   = MYSQL_TYPE_LONG;
00729         _pind   = pind;
00730         _plen   = NULL;
00731     }
00732 
00733     BindPar(const LONGLONG& var, my_bool* pind=NULL)
00734     {
00735         _ptr    = (void*)&var;
00736         _len    = sizeof(var);
00737         _type   = MYSQL_TYPE_LONGLONG;
00738         _pind   = pind;
00739         _plen   = NULL;
00740     }
00741 
00742     BindPar(const double& var, my_bool* pind=NULL)
00743     {
00744         _ptr    = (void*)&var;
00745         _len    = sizeof(var);
00746         _type   = MYSQL_TYPE_DOUBLE;
00747         _pind   = pind;
00748         _plen   = NULL;
00749     }
00750 
00751 #if MYSQLPL_PREP_STMT
00752     BindPar(SqlInt& var)
00753     {
00754         int& ref = var.get_ref();
00755 
00756         _ptr    = &ref;
00757         _len    = sizeof(ref);
00758         _type   = MYSQL_TYPE_LONG;
00759         _pind   = var.ind();
00760         _plen   = NULL;
00761     }
00762 
00763     BindPar(SqlInteger& var)
00764     {
00765         LONGLONG& ref = var.get_ref();
00766 
00767         _ptr    = &ref;
00768         _len    = sizeof(ref);
00769         _type   = MYSQL_TYPE_LONGLONG;
00770         _pind   = var.ind();
00771         _plen   = NULL;
00772     }
00773 
00774     BindPar(const SqlString& str)
00775     {
00776         _ptr    = (void*) str.c_str();
00777         _len    = str.len();
00778         _type   = MYSQL_TYPE_VAR_STRING;
00779         _pind   = NULL;
00780         _plen   = NULL;
00781     }
00782 
00783     BindPar(SqlString& str)
00784     {
00785         _ptr    = (void*) str.str();
00786         _len    = str.alen();
00787         _type   = MYSQL_TYPE_VAR_STRING;
00788         _pind   = str.ind();
00789         _plen   = NULL;
00790     }
00791 
00792     BindPar(SqlDate& date)
00793     {
00794         _ptr    = &date;
00795         _len    = sizeof(MYSQL_TIME);
00796         _type   = date.get_data_type();
00797         _pind   = date.ind();
00798         _plen   = NULL;
00799     }
00800 
00801     BindPar(SqlNumber& num)
00802     {
00803         _ptr    = num.get_ref();
00804         _len    = sizeof(double);
00805         _type   = MYSQL_TYPE_DOUBLE;
00806         _pind   = num.ind();
00807         _plen   = NULL;
00808     }
00809 
00810     BindPar(MSqlBlob& blob)
00811     {
00812         _ptr    = blob.get_ref();
00813         _len    = blob.get_len();
00814         _type   = MYSQL_TYPE_BLOB;
00815         _pind   = blob.ind();
00816         _plen   = &blob.get_len_ref();
00817     }
00818 #endif
00819 };
00820 
00821 
00822 #if MYSQLPL_PREP_STMT
00823 
00824  /// factory for call parameters for MySQL define functions
00825 
00826 struct BindResultPar
00827 {
00828     void*       _ptr;
00829     int         _len;
00830     enum_field_types _type;
00831     my_bool*    _pind;
00832     unsigned long*_plen;
00833 
00834     BindResultPar(SqlInt& var)
00835     {
00836         int& ref = var.get_ref();
00837 
00838         _ptr    = &ref;
00839         _len    = sizeof(ref);
00840         _type   = MYSQL_TYPE_LONG;
00841         _pind   = var.ind();
00842         _plen   = NULL;
00843     }
00844 
00845     BindResultPar(SqlInteger& var)
00846     {
00847         LONGLONG& ref = var.get_ref();
00848 
00849         _ptr    = &ref;
00850         _len    = sizeof(ref);
00851         _type   = MYSQL_TYPE_LONGLONG;
00852         _pind   = var.ind();
00853         _plen   = NULL;
00854     }
00855 
00856     BindResultPar(int& var, my_bool* pind=NULL)
00857     {
00858         _ptr    = &var;
00859         _len    = sizeof(var);
00860         _type   = MYSQL_TYPE_LONG;
00861         _pind   = pind;
00862         _plen   = NULL;
00863     }
00864 
00865     BindResultPar(LONGLONG& var, my_bool* pind=NULL)
00866     {
00867         _ptr    = &var;
00868         _len    = sizeof(var);
00869         _type   = MYSQL_TYPE_LONGLONG;
00870         _pind   = pind;
00871         _plen   = NULL;
00872     }
00873 
00874     BindResultPar(const char* buffer, int len, enum_field_types type=MYSQL_TYPE_VAR_STRING, my_bool* pind=NULL)
00875     {
00876         _ptr    = (void*) buffer;
00877         _len    = len;
00878         _type   = type;
00879         _pind   = pind;
00880         _plen   = NULL;
00881     }
00882 
00883     BindResultPar(SqlString& str)
00884     {
00885         _ptr    = str.str();
00886         _len    = str.alen();
00887         _type   = MYSQL_TYPE_VAR_STRING;
00888         _pind   = str.ind();
00889         _plen   = NULL;
00890     }
00891 
00892     BindResultPar(SqlNumber& num)
00893     {
00894         _ptr    = num.get_ref();
00895         _len    = sizeof(double);
00896         _type   = MYSQL_TYPE_DOUBLE;
00897         _pind   = num.ind();
00898         _plen   = NULL;
00899     }
00900 
00901 #if MYSQLPL_PREP_STMT
00902     BindResultPar(SqlDate& date)
00903     {
00904         _ptr    = &date;
00905         _len    = sizeof(MYSQL_TIME);
00906         _type   = date.get_data_type();
00907         _pind   = date.ind();
00908         _plen   = NULL;
00909     }
00910 #endif
00911 
00912     BindResultPar(MSqlBlob& blob)
00913     {
00914         _ptr    = blob.get_ref();
00915         _len    = blob.get_len();
00916         _type   = MYSQL_TYPE_BLOB;
00917         _pind   = blob.ind();
00918         _plen   = &blob.get_len_ref();
00919     }
00920 };
00921 
00922 
00923 struct SqlVariant
00924 {
00925     SqlVariant()
00926      :  _data_type((enum_field_types)-1)
00927     {
00928     }
00929 
00930     SqlVariant(enum_field_types data_type);
00931 
00932     SqlVariant(const SqlVariant& other);
00933 
00934     ~SqlVariant() {clear();}
00935 
00936     SqlVariant(const SqlString& x)
00937     {
00938         _string = new SqlString(x);
00939         _data_type = MYSQL_TYPE_VAR_STRING;
00940     }
00941 
00942     SqlVariant(const char* x)
00943     {
00944         _string = new SqlString(x);
00945         _data_type = MYSQL_TYPE_VAR_STRING;
00946     }
00947 
00948     SqlVariant(const SqlInt& x)
00949     {
00950         _int = new SqlInt(x);
00951         _data_type = MYSQL_TYPE_LONG;
00952     }
00953 
00954     SqlVariant(const SqlInteger& x)
00955     {
00956         _integer = new SqlInteger(x);
00957         _data_type = MYSQL_TYPE_LONGLONG;
00958     }
00959 
00960     SqlVariant(const SqlNumber& x)
00961     {
00962         _number = new SqlNumber(x);
00963         _data_type = MYSQL_TYPE_DOUBLE;
00964     }
00965 
00966 #if MYSQLPL_PREP_STMT
00967     SqlVariant(const SqlDate& x)
00968     {
00969         _date = new SqlDate(x);
00970         _data_type = x.get_data_type();
00971     }
00972 #endif
00973 
00974     void clear();
00975     void assign(const SqlVariant& other);
00976 
00977     int get_data_type() const
00978         {return _data_type;}
00979 
00980     SqlVariant& operator=(const SqlVariant& other) {assign(other); return *this;}
00981 
00982     std::string str() const;
00983 
00984     SqlNumber number() const;
00985     int get_int() const;
00986 #ifdef _MSC_VER
00987     LONGLONG get_int64() const;
00988 #endif
00989     double get_double() const;
00990 
00991 #if MYSQLPL_PREP_STMT
00992     SqlDate date(enum_mysql_timestamp_type type=MYSQL_TIMESTAMP_DATE) const;
00993     SqlDate datetime() const {return date(MYSQL_TIMESTAMP_DATETIME);}
00994     SqlDate time() const {return date(MYSQL_TIMESTAMP_TIME);}
00995 #endif
00996 
00997     bool is_null() const;
00998     bool is_not_null() const {return !is_null();}
00999 
01000 #if MYSQLPL_PREP_STMT
01001     void bind_result_column(SqlStatement& stmt, MYSQL_BIND& bind);
01002 #endif
01003 
01004 protected:
01005     union {
01006         SqlString*  _string;
01007         SqlInt*     _int;
01008         SqlInteger* _integer;
01009         SqlNumber*  _number;
01010 #if MYSQLPL_PREP_STMT
01011         SqlDate*    _date;
01012 #endif
01013         MSqlBlob*   _blob;
01014     };
01015 
01016     enum_field_types _data_type;
01017 };
01018 
01019 #endif
01020 
01021 
01022 struct ColumnData {
01023 #if MYSQLPL_PREP_STMT
01024     SqlVariant  _column;
01025 #endif
01026     ColumnType  _type;
01027 };
01028 
01029 typedef std::vector<ColumnData> ColumnVector;
01030 
01031 
01032 struct BindVector : public std::vector<BindPar>
01033 {
01034     void    bind(int idx, const BindPar& par);
01035 };
01036 
01037 
01038 #if MYSQLPL_PREP_STMT
01039 typedef std::vector<MYSQL_BIND> MSqlBindVector;
01040 
01041 void mysql_bind_param(const BindPar& par, MYSQL_BIND& bind);
01042 #endif
01043 
01044 
01045  /// a record to hold return columns for a given statement
01046 
01047 struct SqlRecord
01048 {
01049     SqlRecord(SqlStatement& stmt);
01050 
01051     int get_column_count() const
01052         {return _columns.size();}
01053 
01054 #if MYSQLPL_PREP_STMT
01055     const SqlVariant& get_column(int idx) const
01056         {return _columns[idx]._column;}
01057 
01058     const SqlVariant& get_column(const std::string& col_name) const;
01059 #endif
01060 
01061     const ColumnType& get_column_type(int idx) const
01062         {return _columns[idx]._type;}
01063 
01064     const ColumnType& get_column_type(const std::string& col_name) const;
01065 
01066     void print_columns(std::ostream& out);
01067     void print_values(std::ostream& out);
01068 
01069 #ifdef _XMLSTORAGE_H
01070     void dump_values(XMLStorage::XMLPos& out);
01071 #endif
01072 
01073 protected:
01074     SqlStatement&   _stmt;
01075     ColumnVector    _columns;
01076 
01077     typedef std::map<std::string, int> NameMap;
01078     mutable NameMap _name_map;  // column index cache
01079 
01080     NameMap::const_iterator find_column(const std::string& col_name) const;
01081     int get_column_idx(const std::string& col_name) const;
01082 };
01083 
01084 
01085 #if !MYSQLPL_PREP_STMT
01086 
01087 struct SqlResult : public SqlRecord
01088 {
01089     MYSQL_ROW   _row;
01090 
01091     SqlResult(SqlStatement& stmt)
01092      :  SqlRecord(stmt),
01093         _row(NULL)
01094     {
01095     }
01096 
01097     bool is_null(int idx) const
01098     {
01099         return _row[idx] == NULL;
01100     }
01101     int is_null(const std::string& col_name) const
01102     {
01103         return is_null(get_column_idx(col_name));
01104     }
01105 
01106     bool is_not_null(int idx) const
01107     {
01108         return _row[idx] != NULL;
01109     }
01110     int is_not_null(const std::string& col_name) const
01111     {
01112         return is_not_null(get_column_idx(col_name));
01113     }
01114 
01115     int get_int(int idx) const
01116     {
01117         return atoi(_row[idx]);
01118     }
01119     int get_int(const std::string& col_name) const
01120     {
01121         return get_int(get_column_idx(col_name));
01122     }
01123 
01124 #ifdef _MSC_VER
01125     LONGLONG get_int64(int idx) const
01126     {
01127         return _atoi64(_row[idx]);
01128     }
01129     LONGLONG get_int64(const std::string& col_name) const
01130     {
01131         return get_int64(get_column_idx(col_name));
01132     }
01133 #endif
01134 
01135     double get_double(int idx) const
01136     {
01137         return atof(_row[idx]);
01138     }
01139     double get_double(const std::string& col_name) const
01140     {
01141         return get_double(get_column_idx(col_name));
01142     }
01143 
01144     std::string get_string(int idx) const
01145     {
01146         const char* str = _row[idx];
01147         return str? str: std::string();
01148     }
01149     std::string get_string(const std::string& col_name) const
01150     {
01151         return get_string(get_column_idx(col_name));
01152     }
01153 
01154 #if MYSQLPL_PREP_STMT // never used
01155     SqlDate get_date(int idx, enum_mysql_timestamp_type type=MYSQL_TIMESTAMP_DATE) const
01156     {
01157         return get_column(idx).date(type);
01158     }
01159     SqlDate get_date(const std::string& col_name, enum_mysql_timestamp_type type=MYSQL_TIMESTAMP_DATE) const
01160     {
01161         return get_date(get_column_idx(col_name));
01162     }
01163 
01164     SqlDate get_datetime(int idx) const
01165     {
01166         return get_column(idx).date(MYSQL_TIMESTAMP_DATETIME);
01167     }
01168     SqlDate get_datetime(const std::string& col_name) const
01169     {
01170         return get_column(col_name).date(MYSQL_TIMESTAMP_DATETIME);
01171     }
01172 #endif
01173 };
01174 
01175 #endif
01176 
01177 
01178 struct SqlQuery
01179 {
01180     explicit SqlQuery(const char* sql)
01181      :  _sql(sql)
01182     {
01183     }
01184 
01185     void where(const char* cond)
01186     {
01187         if (_cond.empty())
01188             _cond += "\nwhere   ";
01189         else
01190             _cond += "\nand ";
01191 
01192         _cond += cond;
01193     }
01194 
01195     std::string get_sql() const
01196     {
01197         return _sql + _cond;
01198     }
01199 
01200     void bind_param(BindPar par);
01201 
01202     const BindVector& get_params() const
01203     {
01204         return _param_bind_vector;
01205     }
01206 
01207 protected:
01208     std::string _sql;
01209     std::string _cond;
01210 
01211     BindVector  _param_bind_vector;
01212 };
01213 
01214 
01215  /// a MySQL SQL statement
01216 
01217 struct SqlStatement
01218 {
01219     SqlStatement(MSqlConnection& conn);
01220     SqlStatement(MSqlConnection& conn, const std::string& sql);
01221     SqlStatement(MSqlConnection& conn, const SqlQuery& query);
01222 
01223     ~SqlStatement();
01224 
01225 
01226 protected:
01227 
01228     MYSQL*  _db;
01229 
01230 #if MYSQLPL_PREP_STMT
01231     MYSQL_STMT* _stmt;
01232 
01233     MSqlBindVector  _result_bind_vector;
01234 #else
01235     std::string _sql;
01236 
01237     std::string create_bound_sql() const;
01238 #endif
01239 
01240     BindVector  _param_bind_vector;
01241 
01242     mutable MYSQL_RES* _result;
01243 
01244     enum STATE {
01245         UNINITIALIZED=0,
01246 #if MYSQLPL_PREP_STMT
01247         PREPARED=1, RESULT_BOUND=2,
01248 #endif
01249         EXECUTED=4, FETCHED=8,
01250         //EOF_DATA=16, STMT_ERROR=32
01251     };
01252     int _state;
01253 
01254     std::string _last_sql;
01255 
01256     struct SqlResult* _res;
01257 
01258     int _stmt_type;
01259 
01260 
01261 public:
01262 
01263     //bool eof() const {return _state < EOF_DATA;}
01264 
01265 
01266      // Preparation of a SQL statements
01267 
01268     void prepare(const std::string& sql);
01269 
01270 
01271     const std::string& get_last_sql() const
01272     {
01273         return _last_sql;
01274     }
01275 
01276 
01277      // get number of processed rows
01278 
01279     LONGLONG get_row_count() const;
01280 
01281 
01282      // Binding of input and output variables
01283 
01284     void bind_param(int idx, BindPar par);
01285 
01286 //TODO implement named parameter binding
01287 
01288     void bind_params(const BindVector& params)
01289     {
01290         _param_bind_vector = params;
01291     }
01292 
01293      // Definition of variables to receive query results
01294 
01295 #if MYSQLPL_PREP_STMT
01296     void bind_result_column(BindResultPar par, MYSQL_BIND& bind);
01297     void bind_result(MYSQL_BIND* bind_array);
01298 #endif
01299 
01300 
01301      // define all columns of a complete recordset
01302 
01303 #if MYSQLPL_PREP_STMT
01304     void bind_result(ColumnVector& columns);
01305 #endif
01306 
01307 
01308     void execute();
01309 
01310     void execute(const std::string& sql)
01311     {
01312         prepare(sql);
01313         execute();
01314     }
01315 
01316     void execute(const SqlQuery& query)
01317     {
01318         prepare(query.get_sql());
01319         bind_params(query.get_params());
01320         execute();
01321     }
01322 
01323     bool execute_fetch()
01324     {
01325         execute();
01326 
01327         return fetch();
01328     }
01329 
01330     bool execute_fetch(const std::string& sql)
01331     {
01332         prepare(sql);
01333 
01334         return execute_fetch();
01335     }
01336 
01337     bool fetch()
01338     {
01339         if (!(_state & EXECUTED))
01340             execute();
01341 
01342 #if MYSQLPL_PREP_STMT
01343         int res = mysql_stmt_fetch(_stmt);
01344 
01345         if (res == MYSQL_NO_DATA)
01346             return false;
01347 
01348         mysqlpl_check_error(_stmt, res);
01349 #else
01350         _res->_row = mysql_fetch_row(_result);
01351 
01352         if (!_res->_row)
01353             return false;
01354 #endif
01355 
01356         _state |= FETCHED;
01357 
01358         return true;
01359     }
01360 
01361     MYSQL_RES* get_meta_res() const;
01362 
01363     bool is_select() const;
01364 
01365     int get_column_count() const;
01366 
01367     void get_column_type(int idx, ColumnType& info) const;
01368 
01369     void print_results(std::ostream& out, bool header=true);
01370 
01371     void print_results(const std::string& sql, std::ostream& out, bool header=true)
01372     {
01373         execute(sql);
01374 
01375         print_results(out, header);
01376     }
01377 
01378 
01379 #ifdef _XMLSTORAGE_H
01380     void dump_results(XMLStorage::XMLPos& idx, const XMLStorage::XS_String& element_name);
01381 
01382     void dump_results(const std::string& sql, XMLStorage::XMLPos& idx, const XMLStorage::XS_String& element_name)
01383     {
01384         execute(sql);
01385 
01386         dump_results(idx, element_name);
01387     }
01388 #endif
01389 
01390 
01391     SqlResult* operator->()
01392     {
01393         if (!_res)
01394             fetch();
01395 
01396         return _res;
01397     }
01398 };
01399 
01400 
01401 #if MYSQLPL_PREP_STMT
01402 
01403  /// class to retrieve query result values
01404 
01405 struct SqlResult : public SqlRecord
01406 {
01407     SqlResult(SqlStatement& stmt)
01408      :  SqlRecord(stmt)
01409     {
01410 #if MYSQLPL_PREP_STMT
01411         stmt.bind_result(_columns);
01412 #endif
01413     }
01414 
01415     bool is_null(int idx) const
01416     {
01417         return get_column(idx).is_null();
01418     }
01419     int is_null(const std::string& col_name) const
01420     {
01421         return get_column(col_name).is_null();
01422     }
01423 
01424     bool is_not_null(int idx) const
01425     {
01426         return get_column(idx).is_not_null();
01427     }
01428     int is_not_null(const std::string& col_name) const
01429     {
01430         return get_column(col_name).is_not_null();
01431     }
01432 
01433     int get_int(int idx) const
01434     {
01435         return get_column(idx).get_int();
01436     }
01437     int get_int(const std::string& col_name) const
01438     {
01439         return get_column(col_name).get_int();
01440     }
01441 
01442 #ifdef _MSC_VER
01443     LONGLONG get_int64(int idx) const
01444     {
01445         return get_column(idx).get_int64();
01446     }
01447     LONGLONG get_int64(const std::string& col_name) const
01448     {
01449         return get_column(col_name).get_int64();
01450     }
01451 #endif
01452 
01453     double get_double(int idx) const
01454     {
01455         return get_column(idx).get_double();
01456     }
01457     double get_double(const std::string& col_name) const
01458     {
01459         return get_column(col_name).get_double();
01460     }
01461 
01462     std::string get_string(int idx) const
01463     {
01464         return get_column(idx).str();
01465     }
01466     std::string get_string(const std::string& col_name) const
01467     {
01468         return get_column(col_name).str();
01469     }
01470 
01471 #if MYSQLPL_PREP_STMT
01472     SqlDate get_date(int idx, enum_mysql_timestamp_type type=MYSQL_TIMESTAMP_DATE) const
01473     {
01474         return get_column(idx).date(type);
01475     }
01476     SqlDate get_date(const std::string& col_name, enum_mysql_timestamp_type type=MYSQL_TIMESTAMP_DATE) const
01477     {
01478         return get_column(col_name).date(type);
01479     }
01480 
01481     SqlDate get_datetime(int idx) const
01482     {
01483         return get_column(idx).date(MYSQL_TIMESTAMP_DATETIME);
01484     }
01485     SqlDate get_datetime(const std::string& col_name) const
01486     {
01487         return get_column(col_name).date(MYSQL_TIMESTAMP_DATETIME);
01488     }
01489 #endif
01490 };
01491 
01492 #endif // MYSQLPL_PREP_STMT
01493 
01494 
01495 } // namespace MySqlPL
01496 
01497 #define _MYSQLPL_H
01498 #endif  // _MYSQLPL_H

Generated on Fri Jan 31 2014 00:11:58 for MySQLPL/C++ by  doxygen 1.7.2