//*-- AUTHOR : Ilse Koenig //*-- Modified : 15/09/2000 //_HADES_CLASS_DESCRIPTION ///////////////////////////////////////////////////////////////////////////// // HDbFileIo // // Oracle I/O class to load data from a client-side file into an Oracle table // or to write data from an Oracle table to a client-side file // (uses the Oracle C/C++ precompiler) // // Description of the program: // http://www-hades.gsi.de/persons/ilse/orafileio.htm // ///////////////////////////////////////////////////////////////////////////// #include "hdbfileio.h" #include "hdbfileutil.h" #include "hdbtable.h" #include "hdbcolumn.h" #include "TStopwatch.h" #include #include ClassImp(HDbFileIo) HDbFileIo::HDbFileIo() { // Constructor creates the Oracle connection class, but does not open a connection dbConn=new HDbConn; dbUtil=0; fin=0; fout=0; colDelim=" "; textDelim="'"; nullValue="null"; maxBufLen=4000; maxStmLen=8000; autoCommit=kFALSE; autoNull=kTRUE; tempTables=new TList; refTable=0; curTable=0; needsCommit=kFALSE; } HDbFileIo::~HDbFileIo() { // Destructor closes the Oracle connection and a file not yet closed if (dbConn) { closeDbConn(); delete dbConn; } if (tempTables) delete tempTables; if (dbUtil) delete dbUtil; closeFile(); if (fin) delete fin; if (fout) delete fout; } Bool_t HDbFileIo::connectDb(TString userName, TString dbName) { // Opens an Oracle connection (e.g.with: "hades","db-hades") if (dbConn->isOpen()) dbConn->closeDbConn(); Bool_t rc=dbConn->connectDb(userName,dbName); if (rc) { dbUtil=new HDbFileUtil(dbConn); setDateMask(); } return rc; } void HDbFileIo::closeDbConn() { // Closes the Oracle connection // Asks for committing all not yet saved transactions if (needsCommit) confirmCommit(); dbConn->closeDbConn(); // makes rollback automatically if (curTable) { delete curTable; curTable=0; defTableName=""; } if (refTable) { delete refTable; refTable=0; } if (tempTables) tempTables->Delete(); if (dbUtil) { delete dbUtil; dbUtil=0; } } Bool_t HDbFileIo::openFile(const Char_t* fName,const Char_t* ioMode) { // Closes an open file and opens the new file // Possible I/O modes are "in", "out", "app" closeFile(); defTableName=""; TString m(ioMode); m.ToLower(); if (m.CompareTo("in")==0) return openInput(fName); if (m.CompareTo("out")==0 || m.CompareTo("app")==0) return openOutput(fName,m.Data()); Error("HDbFileIo::openFile", "Wrong I/O mode! Possible modes are \"in\", \"out\", \"app\""); return kFALSE; } void HDbFileIo::closeFile() { // Closes the file if (fin && fin->rdbuf()->is_open()!=0) fin->close(); if (fout && fout->rdbuf()->is_open()!=0) fout->close(); } Bool_t HDbFileIo::fileIsOpen() { // Returns kTRUE in case the file is open if ((fin && fin->rdbuf()->is_open()!=0) || (fout && fout->rdbuf()->is_open()!=0)) return kTRUE; return kFALSE; } Bool_t HDbFileIo::fileIsWritable() { // Returns kTRUE in case the file is writable if (fout && fout->rdbuf()->is_open()!=0) return kTRUE; return kFALSE; } HDbTable* HDbFileIo::setTableName(const Char_t* tableName) { // Sets the name of the Oracle table. // Checks if a table with this name exists already. // Returns a pointer to a table. // For an existing table this form contains all columns of this table. If the // table does not exist the list of columns is empty. This table can be used // to define the columns for an insert/update. // (You can call the HDbTable::clear() function to remove all columns from the // list. Then all or only some columns can be added again in the order needed // for the file I/O.) clear(); if (dbConn->isOpen()) { TString t(tableName); t=t.Strip(t.kBoth); t.ToUpper(); Int_t n=t.First("."); if (n<0) { t.Insert(0,"."); t.Insert(0,dbConn->getUserName()); } refTable=getTempTable(t); if (!refTable) { refTable=new HDbTable(dbConn,dbUtil,t); refTable->describeTable(); } curTable=new HDbTable(dbConn,dbUtil,*refTable); } else Error("HDbFileIo::setTableName","No connection to Oracle"); return curTable; } void HDbFileIo::setColumnDelimiter(const Char_t* s) { // Sets the delimiter beween columns (default value: " ") colDelim=s; if (colDelim.Length()>1) { colDelim.Strip(colDelim.kBoth); if (colDelim.Length()==0) colDelim=" "; } else { if (colDelim.Length()==0) { Error("HDbFileIo::setColumnDelimiter", "\n Delimter for columns is empty, replaced by default delimiter whitespace"); colDelim=" "; } } } Bool_t HDbFileIo::setDateMask(const Char_t* mask) { // Sets a date mask in Oracle if (dbConn->isOpen()) { actDateMask=mask; TString stm("begin hades_oper.hdate.set_datemask("); if (mask && strlen(mask)>2) stm=stm + "'" + mask + "'); end;"; else stm=stm + "); end;"; return dbUtil->executeDirect(stm); } actDateMask=""; Error("HDbFileIo::setDateMask","No connection to Oracle"); return kFALSE; } Bool_t HDbFileIo::setSearchDate(const Char_t* time) { // Sets the search date in Oracle used to select data from views which // require a date specified before retrieving results. // The default value is the actual time on the server. if (dbConn->isOpen()) { TString stm("begin hades_oper.run_query.set_date("); stm=stm + "'" + time + "'); end;"; return dbUtil->executeDirect(stm); } else Error("HDbFileIo::setSearchDate","No connection to Oracle"); return kFALSE; } Bool_t HDbFileIo::setRun(const Char_t* daqFile) { // Sets the run in Oracle used to select data from views which require // a run specified before retrieving results. if (dbConn->isOpen()) { TString stm("begin hades_oper.run_query.set_run("); stm=stm + "'" + daqFile + "'); end;"; return dbUtil->executeDirect(stm); } else Error("HDbFileIo::setRun","No connection to Oracle"); return kFALSE; } HDbTable* HDbFileIo::getTempTable(const Char_t* tableName) { // Returns a pointer to a temporary table created inside the current // Oracle session TString t(tableName); t=t.Strip(t.kBoth); t.ToUpper(); HDbTable* table=(HDbTable*)tempTables->FindObject(tableName); return table; } void HDbFileIo::showTemporaryTables() { // Shows all temporary tables created inside the current Oracle session if (tempTables->Last()==0) { cout<<"The list of temporary tables is empty!"<show(); } } void HDbFileIo::dropTemporaryTable(const Char_t* tableName) { // Drops a temporary table created inside the current Oracle session. // Each Drop must be confirmed. if (needsCommit) confirmCommit(); Bool_t rc=kFALSE; HDbTable* t=getTempTable(tableName); if (t) { rc=t->dropTable(); if (rc) removeTempTable(t); } else cout<<"Table does not exist or is not a temporary table"<Last()==0) { cout<<"List of temporary tables is empty!"<dropTable(); if (rc) removeTempTable(t); } } void HDbFileIo::commit(void) { // Commits Oracle transactions if (dbUtil) dbUtil->commit(); needsCommit=kFALSE; } void HDbFileIo::rollback(void) { // Rolls back Oracle transactions if (dbUtil) dbUtil->rollback(); needsCommit=kFALSE; } void HDbFileIo::showExistingTable() { // Shows the table definition of the existing table if (refTable) { if (refTable->isExisting()) refTable->show(); else cout<<"Table "<GetName()<< "is not a permanent table and might not exist."<isOpen()) { Error("HDbFileIo::readFile","No connection to Oracle"); return kFALSE; } if (!fin || fin->rdbuf()->is_open()==0) { Error("HDbFileIo::readFile","No file open"); return kFALSE; } fin->seekg(0,ios::beg); fin->clear(); TString stm; TString insert("insert into "); Bool_t all=kFALSE; Bool_t tabChecked=kFALSE; Int_t nInserts=0; Int_t i, nData, nColumns=0, l1=0, l2=0; TString line(maxBufLen); // TStopwatch timer; // timer.Reset(); // timer.Start(); do { l1=l2; i=0; stm="begin "; while (stm.Length()eof() || l2>nLineEnd) { all=kTRUE; break; } if (l2GetName() + "("; nColumns=curTable->getNColumns(); for(Int_t j=0;jgetColumn(j)->GetName(); if (j<(nColumns-1)) insert=insert + ","; } insert=insert + ")"; if (!curTable->isTempTable()) { cout<<"-----------------------------------------"<confirm("insert")) return kFALSE; } insert=insert +" values ("; } else nData=getValues(line,nColumns); if (nData==nColumns) stm = stm + insert + line + ");"; else { if (autoNull) { stm = stm + insert + line + ","; for(Int_t k=++nData;k0) { if (dbUtil->executeDirect(stm)==kFALSE) { Error("HDbFileInput::readData","Error in lines %i - %i",(l1+1),l2); rollback(); return kFALSE; } nInserts+=i; } } while (all==kFALSE); cout<<"-----------------------------------------"<GetName()<GetName(); if (cols[0]=='*') stm=stm + " values (" + colValues + ")"; else stm=stm + "(" + cols + ") values (" + colValues + ")"; if (!curTable->isTempTable()) { cout<<"-----------------------------------------"<confirm("insert")) return kFALSE; } if (dbUtil->executeDirect(stm)==kFALSE) { rollback(); return kFALSE; } checkCommit(); return kTRUE; } Bool_t HDbFileIo::makeUpdate(const Char_t* setVal, const Char_t* condition) { // Updates one or more rows in a temporary table // setVal : SET part of an update statement (col1=val1, col2=val2, ...) // condition: Condition for the columns to be updated // WARNING: An empty condition will update all columns! if (!curTable->isTempTable()) { cout<<"The update of an existing table is forbidden in this program"<GetName() + " set " + setVal ; if (con.Length()>0) stm=stm + " where " + con; if (dbUtil->executeDirect(stm)==kFALSE) { rollback(); return kFALSE; } checkCommit(); return kTRUE; } Bool_t HDbFileIo::writeFile() { // Writes the data from an Oracle table into a file Bool_t rc=kFALSE; if (fout && fout->rdbuf()->is_open()!=0) { rc=write(*fout); closeFile(); } else Error("HDbFileIo::writeFile()","No output file open"); return rc; } Bool_t HDbFileIo::printResult() { // Prints the data from an Oracle table on the screen return write(cout); } //////////////////////////// private functions ////////////////////// Bool_t HDbFileIo::openInput(const Char_t* fileName) { // Opens a file for input and generates the default table name if (needsCommit) confirmCommit(); clear(); defTableName=""; if (!fin) fin=new ifstream; fin->clear(); fin->open(fileName,ios::in); if (fin && fin->rdbuf()->is_open()!=0) { defTableName=fileName; defTableName.Remove(0,(defTableName.Last('/')+1)); Int_t n=defTableName.First('.'); if (n>0) defTableName.Remove(n,defTableName.Length()-n); defTableName.ToUpper(); defTableName.Insert(0,"TMP_"); return kTRUE; } Error("HDbFileIo::openInput","File not found"); return kFALSE; } Bool_t HDbFileIo::openOutput(const Char_t* fileName, const Char_t* oMode) { // Opens a file for output if (!fout) fout=new ofstream; if (strcmp(oMode,"out")==0) { if (access(fileName,F_OK)!=0) fout->open(fileName,ios::out); else { cout<<"File "<confirm("Recreate file")==kFALSE) return kFALSE; fout->open(fileName,ios::out); } } else fout->open(fileName,ios::app); if (fout && fout->rdbuf()->is_open()!=0) return kTRUE; Error("HDbFileIo::openOutput","File not found or not writable"); return kFALSE; } Int_t HDbFileIo::checkTable(TString& line) { // Sets the default table name and table definition if necessary. Checks if // the table exists and creates it otherwise. A newly created table is added // in the list of temporary tables. Int_t nData=0; Int_t nColumns=0; Char_t buf[4]; if (!curTable) { curTable=setTableName(defTableName.Data()); nColumns=curTable->getNColumns(); if (nColumns==0) { nData=getValues(line,254); TString s1="Col"; for(Int_t i=1;i<=nData;i++) { sprintf(buf,"%i",i); TString s=s1 + buf; curTable->addColumn(s.Data()); } if (!curTable->createTable()) return 0; addTempTable(curTable); } else nData=getValues(line,nColumns); } else { nColumns=curTable->getNColumns(); nData=getValues(line,nColumns); if (!curTable->isExisting()) { if (!curTable->createTable()) return 0; addTempTable(curTable); } } return nData; } void HDbFileIo::addTempTable(HDbTable* table) { // Adds a temporary table to the list of temporary tables if (!tempTables) tempTables=new TList; HDbTable* t=new HDbTable(dbConn,dbUtil,*table); tempTables->Add(t); } void HDbFileIo::removeTempTable(HDbTable* table) { // Removes a table from the list of temporary tables and deletes it. // Deletes also the actual tables when they have identical names. tempTables->Remove(table); if (curTable && strcmp(curTable->GetName(),table->GetName())==0) { delete curTable; curTable=0; delete refTable; refTable=0; } delete table; table=0; } Int_t HDbFileIo::getValues(TString& str, Int_t nColumns) { // Gets the column values from a line read from file TString s1(str.Strip(str.kBoth)); Int_t slen=s1.Length(); if (slen==0) return 0; TString s2, s3; Int_t n=0; str=""; while (slen>0 && ngetTokString(s1,s2,textDelim); str=str + "'" + s2 + "'"; if (slen>0 && colDelim[0]!=' ') { s1.Remove(0,colDelim.Length()); // remove delimiter s1=s1.Strip(s1.kLeading,' '); slen=s1.Length(); } } else { slen=dbUtil->getTokString(s1,s2,colDelim); if (s2.Length()==0 || s2.CompareTo(nullValue)==0) str=str + "null"; else str=str + "'" + s2 + "'"; } n++; if (slen>0 && nisExisting()) { Error("HDbFileIo::write","Table does not exist!"); return kFALSE; } Int_t n=curTable->getNColumns(); Int_t r=refTable->getNColumns(); if (r>0) { if (n>0) { for(Int_t i=0;igetColumn(i); HDbColumn* refCol=refTable->getColumn(col->GetName()); if (refCol) col->copyColumn(refCol); else { Error("HDbFileIo::write","Column %s does not exist!",col->GetName()); return kFALSE; } } } else { for(Int_t i=0;igetColumn(i); HDbColumn* col=curTable->addColumn(refCol->GetName()); col->copyColumn(refCol); } } } pout<<"// -----------------------------------------"<GetName()<getColumn(i)->GetName()<<" "; pout<getColumn(n-1)->GetName()<writeTable(pout,colDelim.Data(),textDelim.Data(), nullValue.Data()); if (l<0) return kFALSE; cout<<"-----------------------------------------"<GetName()<confirm("commit")) commit(); else rollback(); }