00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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>
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
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
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
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
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
00242
00243
00244
00245 }
00246
00247
00248 #if MYSQLPL_PREP_STMT
00249
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
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
00308 MSqlConnection(const MSqlConnection&);
00309 };
00310
00311
00312
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
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
00379
00380 struct SqlInt : public SqlValue
00381 {
00382 SqlInt()
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
00411
00412 struct SqlInteger : public SqlValue
00413 {
00414 SqlInteger()
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;}
00479 char* str(int l) {resize(l); return _str;}
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
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)
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
00670
00671
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)
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
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
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;
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
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
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
01264
01265
01266
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
01278
01279 LONGLONG get_row_count() const;
01280
01281
01282
01283
01284 void bind_param(int idx, BindPar par);
01285
01286
01287
01288 void bind_params(const BindVector& params)
01289 {
01290 _param_bind_vector = params;
01291 }
01292
01293
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
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
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 }
01496
01497 #define _MYSQLPL_H
01498 #endif // _MYSQLPL_H