Main Page   Class Hierarchy   File List  

openMyDB.cpp

00001 /*
00002    These classes define a
00003    mySQL implementation
00004    to the open database interfaces.
00005    ================================
00006 */
00007 
00008 #include "openMyDB.h"
00009 #include "ocString.h"
00010 #include <cstdlib>
00011 
00012 // #define DO_OPEN_LOGGING
00013 #include "openLogger.h"
00014 /*
00015   utility method to help insure the integrity of the result
00016 */
00017 
00018 bool mySqlDB::error( int state ) // defaulted to 0
00019 {
00020   bool bRet = true;
00021   // regardless, get any error in the buffer
00022   m_strErrors = mysql_error(&mysql);
00023   // state is the return from a query, error if non-zero
00024   // also check if the returned error buffer has length
00025   bRet = state != 0 || m_strErrors.length() > 0;
00026   return bRet;
00027 }
00028 
00029 
00030 /*
00031 
00032   The DB interface to the mySql Database
00033 
00034 */
00035 mySqlDB::mySqlDB( string strConnection )
00036 :openDB(strConnection)
00037 ,port(0)
00038 ,pchSocket(NULL)
00039 ,connection(NULL)
00040 ,transactioning(false)
00041 {
00042   m_bGood = true;
00043   m_strErrors = "";
00044   m_provider = MySQL;
00045   parseConnection(strConnection);
00046   // Initialize the database handler
00047   mysql_init(&mysql);
00048   // As opposed to a fake connect
00049   connection = mysql_real_connect( &mysql,
00050                                    host.c_str(),
00051                                    uid.c_str(),
00052                                    pwd.c_str(),
00053                                    db.c_str(),
00054                                    port,
00055                                    pchSocket,
00056                                    flags  );
00057   if( connection == NULL )
00058   {
00059     m_bGood = false;
00060     m_strErrors = "No Real Connection Possible at present: ";
00061     m_strErrors += mysql_error(&mysql);
00062   }
00063 }
00064 
00065 bool mySqlDB::parseConnection( string & strConnection )
00066 {
00067   bool bRet=false;
00068   host = "";
00069   uid = "";
00070   pwd = "";
00071   db = "";
00072   port = 0;
00073   socket = "";
00074   pchSocket = NULL;
00075   flags = 0;
00076 
00077   ocString connStr = strConnection;
00078   connStr.parseInit();
00079   for( string element=connStr.parse(";");
00080        !(element.length()==0 && connStr.endOfParse() );
00081        element=connStr.parse(";") )
00082   {
00083     ocString apair(element);
00084     string name = apair.parse("=");
00085     string value = apair.parse("=");
00086     /*
00087         parse params to connect:
00088         host,  uid,  pwd,  db, port,  socket, flags
00089     */
00090     transform(name.begin(),name.end(),name.begin(),(int(*)(int)) tolower );
00091     if( name == "host" )
00092     {
00093       host = value;
00094     }
00095     else if ( name == "uid" )
00096     {
00097       uid = value;
00098     }
00099     else if( name == "pwd" )
00100     {
00101       pwd = value;
00102     }
00103     else if( name == "db" )
00104     {
00105       db = value;
00106     }
00107     else if( name == "port" )
00108     {
00109       port = atol(value.c_str());
00110     }
00111     else if( name == "socket" )
00112     {
00113       socket = value;
00114       if( socket.length() )
00115       {
00116         pchSocket = socket.c_str();
00117       }
00118     }
00119     else if( name == "socket" )
00120     {
00121       socket = value;
00122     }
00123     else if( name == "flags" )
00124     {
00125       flags = atol(value.c_str());
00126     }
00127   } // end for
00128 
00129   // Minimum result for a good parse
00130   if( db.length() && uid.length() )
00131   {
00132     bRet = true;
00133   }
00134 
00135   return bRet;
00136 }
00137 dbProvider mySqlDB::getProvider( void )
00138 {
00139   return m_provider;
00140 }
00141 
00142 mySqlDB::~mySqlDB()
00143 {
00144   mysql_close( connection );
00145 }
00146 
00147 
00148 openCMD * mySqlDB::createCommand()
00149 {
00150   return new mySqlCMD( *this );
00151 }
00152 
00153 openRS * mySqlDB::createRecordset()
00154 {
00155   return new mySqlRS( *this );
00156 }
00157 
00158 
00159 /*
00160 
00161  This CMD class defines the mySql
00162    working interfaces to the SQL command
00163 
00164 */
00165 mySqlCMD::mySqlCMD( openDB & idb ):openCMD(idb),state(0),rows(0)
00166 {
00167   // we KNOW this is really a reference to a mySqlDB
00168   poDB = & dynamic_cast<mySqlDB &>(rdb);
00169 }
00170 
00171 mySqlCMD::~mySqlCMD()
00172 {
00173   ;  // nothing to do
00174 }
00175 
00176 bool mySqlCMD::beginTransaction()
00177 {
00178   // begin a transaction
00179   if( !m_bTransactioning )
00180   {
00181     m_bTransactioning = true;
00182   }
00183   return m_bTransactioning;
00184 }
00185 
00186 bool mySqlCMD::commit()
00187 {
00188   // commit the transaction
00189   if( m_bTransactioning )
00190   {
00191     m_bTransactioning = false;
00192   }
00193   return !m_bTransactioning;
00194 }
00195 
00196 bool mySqlCMD::rollback()
00197 {
00198   // commit the transaction
00199   if( m_bTransactioning )
00200   {
00201     m_bTransactioning = false;
00202   }
00203   return !m_bTransactioning;
00204 }
00205 
00206 bool mySqlCMD::execute( string sql )
00207 {
00208   bool bRet = false;
00209   if( poDB )
00210   {
00211     writelog2("mySqlRS::executetou: ", sql );
00212     state = mysql_real_query( poDB->getConnection(),
00213                               sql.c_str(),
00214                               sql.length() );
00215     bRet = poDB->error(state) == false;
00216     if( bRet )
00217     {
00218       // get the effected row count count
00219       rows = mysql_affected_rows(poDB->getConnection());
00220     }
00221   }
00222   return bRet;
00223 }
00224 int mySqlCMD::resultId( void )
00225 {
00226   return (int) mysql_insert_id(poDB->getConnection());
00227 }
00228 
00229 /*
00230   This RS class defines the working
00231   mySql interfaces to the recordset
00232 */
00233 mySqlRS::mySqlRS( openDB & idb )
00234 :openRS(idb),state(0),rows(0),result(NULL)
00235 {
00236   // we KNOW this is really a reference to a mySqlDB
00237   poDB = dynamic_cast<mySqlDB *>(&idb);
00238 }
00239 
00240 mySqlRS::~mySqlRS()
00241 {
00242   close();
00243 }
00244 
00245 bool mySqlRS::open( string sql )
00246 {
00247   // make sure it's closed first!
00248   close();
00249   m_iFields = 0;
00250   if( poDB )
00251   {
00252     //perform the query
00253     writelog2("mySqlRS::open: ", sql );
00254     state = mysql_real_query(poDB->getConnection(),sql.c_str(),sql.length());
00255     writelog2("mySqlRS::open mysql_real_query state is: ", state);
00256     m_bOpen = poDB->error(state) == false;
00257     writelog2("mySqlRS::open opened? ", m_bOpen);
00258     if( m_bOpen )
00259     {
00260       // set the base class field count
00261       m_iFields = mysql_field_count(poDB->getConnection());
00262       writelog2("mySqlRS::open field count: ", m_iFields );
00263 
00264       // get the results
00265       result = mysql_store_result(poDB->getConnection());
00266       // result = mysql_use_result(poDB->getConnection());
00267       writelog2("mySqlRS::open result: ", result );
00268 
00269       if( result )
00270       {
00271         // set the record count of the current set
00272         m_iRecords = mysql_num_rows( result );
00273         // return fields info
00274         MYSQL_FIELD * pFields = mysql_fetch_fields( result );
00275         // writelog2("mySqlRS::open field pointer: ", pFields );
00276 
00277         for( int icol = 0 ; icol < m_iFields; icol ++ )
00278         {
00279           mysqlColInfo * pInfo = new mysqlColInfo;
00280           // writelog2("mySqlRS::open col info pointer: ", pInfo );
00281           if(pInfo)
00282           {
00283             // Add the column info. to the back of the vector
00284             colInfo.push_back(pInfo);
00285 
00286             // Set the info properties
00287             pInfo->mySqlType = pFields[icol].type;
00288             pInfo->length = pFields[icol].length;
00289             pInfo->decimals = pFields[icol].decimals;
00290             pInfo->ColName = pFields[icol].name;
00291 
00292             // Get the map item based on sql type
00293             my_mapItem * pItem = colMap.data[pInfo->mySqlType];
00294 
00295             // Debug cout << " MapItem Allocated: "  << pItem << endl;
00296             if( pItem )
00297             {
00298               // create the right kind of field
00299               basicField * pField =  pItem->createField( pInfo );
00300               if( pField )
00301               {
00302                 // Add to the vector
00303                 ordinals.push_back(pField);
00304                 // Add to the map
00305                 associations.insert(make_pair(pInfo->ColName,pField));
00306                 // writelog3(pFields[icol].name, " Type", pField->getType() );
00307               }
00308             }
00309             else
00310             {
00311               poDB->errorString() += "\r\nUnable to find type in map\r\n";
00312               // writelog2("mySqlRS::open error: ", poDB->errorString() );
00313             }
00314           }
00315         }// end for all cols
00316         // get the first record values
00317         m_bOpen = next();
00318       } // end if result
00319     } // end if record opened
00320   } // end if db
00321   // cout << poDB->errorString();
00322   return m_bOpen;
00323 }
00324 
00325 bool mySqlRS::beginTransaction()
00326 {
00327   // begin a transaction
00328   if( !m_bTransactioning )
00329   {
00330     m_bTransactioning = true;
00331   }
00332   return m_bTransactioning;
00333 }
00334 
00335 bool mySqlRS::commit()
00336 {
00337   // commit the transaction
00338   if( m_bTransactioning )
00339   {
00340     m_bTransactioning = false;
00341   }
00342   return !m_bTransactioning;
00343 }
00344 
00345 bool mySqlRS::close( void )
00346 {
00347   writelog("mySqlRS::close: " );
00348   unsigned int i;
00349   // remove all from the collections
00350   for( i=0;i<ordinals.size();i++)
00351   {
00352     delete ordinals[i];
00353   }
00354   ordinals.clear();
00355   associations.clear();
00356   for( i=0;i<colInfo.size();i++)
00357   {
00358     // writelog2("mySqlRS::close delete info pointer: ", colInfo[i] );
00359     delete colInfo[i];
00360   }
00361   colInfo.clear();
00362   if( result )
00363   {
00364     mysql_free_result( result );
00365     result = NULL;
00366   }
00367   m_bOpen=false;
00368   return !m_bOpen;
00369 }
00370 
00371 bool mySqlRS::next( int )
00372 {
00373   // return row
00374   bool ret = false;
00375   MYSQL_ROW row = mysql_fetch_row(result);
00376   if( row )
00377   {
00378     ret = true;
00379     for( int icol = 0 ; icol < m_iFields; icol ++ )
00380     {
00381       // get the colInfo (by ordinal)
00382       mysqlColInfo * pInfo = colInfo[icol];
00383       // get the map item based on sql type
00384       my_mapItem * pItem = colMap.data[pInfo->mySqlType];
00385       // get the field (by ordinal)
00386       basicField * pField = ordinals[icol];
00387       //finally, set the field
00388       if(pInfo&&pItem&&pField)
00389       {
00390         // writelog2("Data Raw: ", row[icol] );
00391         pItem->setField( pField, row[icol] );
00392         // writelog2("Data After: ", pField->format() );
00393       }
00394     }
00395   }
00396   else
00397   {
00398     close();
00399     poDB->error();
00400   }
00401   return ret;
00402 }
00403 
00404 bool mySqlRS::previous( int )
00405 {
00406   // mySQL doesn't cursor in reverse
00407   return false;
00408 }

Generated on Tue Jan 20 09:06:56 2004 for OpenTools by doxygen1.2.18