//*-- AUTHOR : Ilse Koenig //*-- Modified : 15/09/2000 //_HADES_CLASS_DESCRIPTION ///////////////////////////////////////////////////////////// // HDbColumnTable // // Class for an Oracle table // ///////////////////////////////////////////////////////////// using namespace std; #include "hdbtable.h" #include "hdbconn.h" #include "hdbfileutil.h" #include "hdbcolumn.h" #include "hdbcolumntype.h" #include #include #include #define SQLCA_STORAGE_CLASS extern #define ORACA_STORAGE_CLASS extern // Oracle communication area #include // SQL Communications Area #include ClassImp(HDbTable) #define MAXCOLNUM 254 #define MAXROWS 200 HDbTable::HDbTable() { // Default constructor dbConn=0; dbUtil=0; tabColumns=new TList; nColumns=0; tempTable=kFALSE; existing=kTRUE; } HDbTable::HDbTable(HDbConn* p, HDbFileUtil* u, const Char_t* tName) { // Constructor // Parameters: pointer to the Oracle connection class, the Oracle utility class // and the name of the table dbConn=p; dbUtil=u; setNames(tName); tabColumns=new TList; nColumns=0; tempTable=kFALSE; existing=kTRUE; } HDbTable::HDbTable(HDbConn* p, HDbFileUtil* u, HDbTable& t) { // Copy constructor // Parameters: pointer to the Oracle connection class, the Oracle utility class // and reference to an other table dbConn=p; dbUtil=u; setNames(t.GetName()); tabColumns=new TList; nColumns=t.getNColumns(); for(Int_t i=0;iAdd(c); } tempTable=t.isTempTable(); existing=t.isExisting(); } HDbTable::~HDbTable() { // Destructor if (tabColumns) { tabColumns->Delete(); delete tabColumns; } } HDbColumn* HDbTable::getColumn(Int_t n) { // Returns the column number n (starting with index 0) return (HDbColumn*)tabColumns->At(n); } HDbColumn* HDbTable::getColumn(const Char_t* colName) { // Returns the column with the specified name if (colName) { TString c(colName); c=c.Strip(c.kBoth); if (c.Length()>0) c.ToUpper(); return (HDbColumn*)tabColumns->FindObject(c.Data()); } return 0; } HDbColumn* HDbTable::addColumn(const Char_t* colName, const Char_t* columnType) { // Adds a column to the list. The type of the column is optional and needed // only for the creation of a non-existing table with non default types. HDbColumn* p=0; TString c(colName); c=c.Strip(c.kBoth); c.ToUpper(); if (tabColumns->FindObject(c.Data())) cout<<"Column "<setColType(columnType); tabColumns->Add(p); nColumns++; } return p; } void HDbTable::addColumn(HDbColumn* p) { // Adds a copy of the column p to the list if (!p) return; if (!tabColumns->FindObject(p->GetName())) { HDbColumn* c=new HDbColumn(*p); // copies the column tabColumns->Add(c); nColumns++; } else cout<<"Column "<GetName()<<" already exists!"<Remove(p); delete p; nColumns--; } } void HDbTable::clearColumns() { // Clears the list of columns tabColumns->Delete(); nColumns=0; } void HDbTable::setColumns(const Char_t* colNames, const Char_t* colTypes) { // Sets a list of columns and types(optional). The lists must be comma separated. TString sNames, sTypes; Int_t nlen=0, tlen=0; if (colNames) { sNames=colNames; sNames.Strip(sNames.kBoth); sNames.ToUpper(); nlen=sNames.Length(); } if (colTypes) { sTypes=colTypes; sTypes.Strip(sTypes.kBoth); sTypes.ToUpper(); tlen=sTypes.Length(); } if (nlen==0) { Error("HDbTable::setColumns","List of column is empty "); return; } TString ssn, sst; while (nlen>0) { nlen=dbUtil->getTokString(sNames,ssn,","); if (tlen>0) { tlen=dbUtil->getTokString(sTypes,sst,","); if (sst.First("(")>0 && sst.First(")")<0) { TString s; tlen=dbUtil->getTokString(sTypes,s,","); sst=sst + "," + s; } addColumn(ssn.Data(),sst.Data()); } else addColumn(ssn.Data(),colDefaultType); } } void HDbTable::setCondition(const Char_t* s) { // Sets the condition for a SELECT statement ("WHERE" is added internally!) if (s) { cond=s; cond=cond.Strip(cond.kBoth); cond.ToUpper(); } else cond=""; } void HDbTable::setOrderBy(const Char_t* s) { // Sets the ORDER BY clause for a SELECT statement // Multiple columns must by separated by commas. // ("ORDER BY" is added internally!) if (s) { orderClause=s; orderClause=orderClause.Strip(orderClause.kBoth); orderClause.ToUpper(); } else orderClause=""; } Bool_t HDbTable::describeTable() { // Gets the table definition (columns, types, nullable) from Oracle if (!dbConn->isOpen()) return kFALSE; tempTable=kFALSE; existing=kTRUE; clearColumns(); EXEC SQL BEGIN DECLARE SECTION; char* dynstmt; varchar colName[MAXCOLNUM][30]; int colId[MAXCOLNUM]; int dLen[MAXCOLNUM]; varchar colType[MAXCOLNUM][30]; int dPrec[MAXCOLNUM]; int dScale[MAXCOLNUM]; varchar nn[MAXCOLNUM][1]; EXEC SQL END DECLARE SECTION; EXEC SQL WHENEVER SQLERROR GOTO errorFound; EXEC SQL WHENEVER NOT FOUND CONTINUE; TString s(("select column_name,column_id,data_length,data_type," "nvl(data_precision,0),nvl(data_scale,0), nullable " "from all_tab_columns where table_name='")); s=s + tabName + "' and owner='" + tabOwner +"' order by column_id"; dynstmt=(Char_t*)s.Data(); EXEC SQL PREPARE S FROM :dynstmt; EXEC SQL DECLARE C CURSOR FOR S; EXEC SQL OPEN C; EXEC SQL FETCH C INTO :colName, :colId, :dLen, :colType, : dPrec, :dScale, :nn; nColumns=sqlca.sqlerrd[2]; if (nColumns<=0) { cout<<"Table "<setColumnId(colId[i]); p->setColType((const Char_t*)colType[i].arr,dLen[i],dPrec[i],dScale[i]); if (nn[i].arr[0]=='N') p->setNullable(kFALSE); tabColumns->Add(p); } return kTRUE; errorFound: dbUtil->showSqlError("HDbTable::describeTable"); EXEC SQL CLOSE C; return kFALSE; } Bool_t HDbTable::createTable() { // Creates the table in Oracle (created only in the account of the connected user) if (!dbConn->isOpen() || dbConn->isReadonly()) return kFALSE; if (nColumns==0) { Error("HDbTable::createTable()","No columns defined"); return kFALSE; } if (tabOwner.CompareTo(dbConn->getUserName())!=0) { Error("HDbTable::createTable()","Table cannot be created in an other user account"); return kFALSE; } TString str="create table "; str=str + GetName() + " (\n "; TIter next(tabColumns); HDbColumn* p; Int_t n=0; while ((p=(HDbColumn*)next())) { str=str + p->GetName() + " " + p->getColType()->getTypeString(); if (!p->isNullable()) str=str + " " + "NOT NULL"; if (++nconfirm("creation")==kFALSE) return kFALSE; Bool_t rc=dbUtil->executeDirect(str); if (rc) { cout<<"Temporary table "<isOpen() || dbConn->isReadonly()) return kFALSE; if (!tempTable) { Error("HDbTable::dropTable","\nCannot drop permanent table %s", GetName()); return kFALSE; } if (!existing) { Error("HDbTable::dropTable","Table does not exist"); return kFALSE; } if (tabOwner.CompareTo(dbConn->getUserName())!=0) { Error("HDbTable::dropTable","\nA table in an other user account cannot be dropped"); return kFALSE; } TString s("drop table "); s=s + GetName(); TString tabOwner; // Owner of the table cout<<"-----------------------------------------"<confirm("drop")==kFALSE) return kFALSE; Bool_t rc=dbUtil->executeDirect(s); if (rc) cout<<"Temporary table "<show(); } } Int_t HDbTable::writeTable(ostream& pout, const Char_t* colDelim, const Char_t* textDelim, const Char_t* nullString) { // Writes the content of the table to a stream. // Fetches the table in batches of 200 rows. if (!dbConn->isOpen()) { cout<<"Connection closed before end of reading!"<At(i); if (p->isNullable()) c=p->getColType()->getNvlSelectString(p->GetName(),textDelim,nullString); else c=p->getColType()->getSelectString(p->GetName(),textDelim); if (c.Length()==0) return -1; stm=stm + c; if (i<(nColumns-1)) stm=stm + "||'" + colDelim + "'||"; } stm=stm + "from " + GetName(); if (cond.Length()>0) { stm=stm + " where " + cond; pout<<"// Condition: "<0) { stm=stm + " order by " + orderClause; pout<<"// Order by: "<showSqlError("HDbTable::writeTable"); EXEC SQL CLOSE CW; cout<<"SQL statement:"<0) { SetName(s.Data()); tabOwner=s(0,n); tabName=s(++n,s.Length()-n); } else { tabOwner=dbConn->getUserName(); tabName=s; s=tabOwner; s=s + "." + tabName; SetName(s.Data()); } }