Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

DbiTableMetaData.cxx

Go to the documentation of this file.
00001 
00005 
00006 
00007 #include <cassert>
00008 #include <cctype>
00009 #include <sstream>
00010 
00011 #include "TString.h"
00012 
00013 #include "DatabaseInterface/Dbi.h"
00014 #include "DatabaseInterface/DbiString.h"
00015 #include "DatabaseInterface/DbiTableMetaData.h"
00016 #include "LeakChecker/Lea.h"
00017 #include "MessageService/MsgService.h"
00018 
00019 ClassImp(DbiTableMetaData)
00020 
00021 //   Definition of static data members
00022 //   *********************************
00023 
00024 CVSID("$Id: DbiTableMetaData.cxx,v 1.20 2007/04/26 14:19:57 west Exp $");
00025 
00026 DbiTableMetaData::ColumnAttributes DbiTableMetaData::fgDummy;
00027 
00028 //    Definition of all member functions (static or otherwise)
00029 //    *******************************************************
00030 //
00031 //    -  ordered: ctors, dtor, operators then in alphabetical order.
00032 
00033 //.....................................................................
00034 
00035 DbiTableMetaData::DbiTableMetaData(const string& tableName) :
00036 fNumCols(0),
00037 fTableName(tableName)
00038 {
00039 //
00040 //
00041 //  Purpose:  Default constructor
00042 
00043 //  Program Notes:-
00044 //  =============
00045 
00046 //  This is filled by the owning DbiTableProxy, as it is too low level to
00047 //  use the cascade to fill itself, hence the friend status granted to DbiDBProxy. 
00048 
00049   LEA_CTOR    //Leak Checker
00050 
00051   MSG("Dbi", Msg::kVerbose) << "Creating DbiTableMetaData" << endl;
00052 
00053 }
00054 
00055 //.....................................................................
00056 
00057 DbiTableMetaData::~DbiTableMetaData() {
00058 //
00059 //
00060 //  Purpose: Destructor
00061 
00062   LEA_DTOR    //Leak Checker
00063 
00064   MSG("Dbi", Msg::kVerbose) << "Destroying DbiTableMetaData" << endl;
00065 
00066 }
00067 
00069 
00070 void DbiTableMetaData::Clear() {
00071 //
00072 //
00073 //  Purpose: Clear out existing data (apart from table name)
00074 //
00075 //  Contact:   N. West
00076 
00077   fColAttr.clear();
00078   fNumCols = 0;
00079 
00080 }
00081 
00082 //.....................................................................
00083 
00084 void DbiTableMetaData::ExpandTo(UInt_t colNum) {
00085 //
00086 //
00087 //  Purpose: Expand table if required to specied colNum 
00088 //
00089 //  Arguments: 
00090 //    colNum       in    Column number to expand to (1,2...).
00091 //
00092 //  Return:    
00093 //
00094 //  Contact:   N. West
00095 //
00096 //  Specification:-
00097 //  =============
00098 //
00099 //  o 
00100 
00101 //  Program Notes:-
00102 //  =============
00103 
00104 //  None.
00105 
00106   assert ( colNum < MAXCOL );
00107   while ( fNumCols < colNum ) {
00108     fColAttr.push_back(ColumnAttributes());
00109     ++fNumCols;
00110   }
00111 }
00112 
00113 //.....................................................................
00114 
00115 const  DbiTableMetaData::ColumnAttributes&  DbiTableMetaData::GetAttributes(Int_t colNum) const {
00116 
00117 // Return a column attributes (will be dummy entry if requesting invalid column)
00118 
00119   if ( colNum > 0 && colNum <= (signed) fNumCols ) return fColAttr[colNum-1];
00120   fgDummy.SetDefault();
00121   return fgDummy;
00122 
00123 }
00124 
00125 //.....................................................................
00126 
00127 string DbiTableMetaData::GetToken(const char*& strPtr) {
00128 //
00129 //
00130 //  Purpose:  Skip spaces and return next token from string and move pointer on.
00131 
00132   string token;
00133 
00134 // Skip white space and quit if at EOS.
00135   while ( isspace(*strPtr) ) ++strPtr;
00136   if ( *strPtr == 0 ) return token;
00137 
00138 // Collect the first character whatever it is.
00139   char firstChar = *strPtr++;
00140   token = firstChar;
00141   if ( ! isalnum(firstChar) && firstChar != '_' ) return token;
00142 
00143 // Collect more if collecting alphanumeric + underscore string
00144   while ( isalnum(*strPtr) || *strPtr == '_' ) token += *strPtr++;
00145   return token;
00146 
00147 }
00148  
00149 //.....................................................................
00150 
00151  DbiTableMetaData::ColumnAttributes& DbiTableMetaData::SetAttributes(Int_t colNum) {
00152 
00153 // Return a column attributes (will be dummy entry if requesting invalid column)
00154 
00155   this->ExpandTo(colNum);
00156   // Using const metho so must cast away constness.
00157   return const_cast<DbiTableMetaData::ColumnAttributes&>(this->GetAttributes(colNum));
00158 
00159 }
00160 
00161 
00162 //.....................................................................
00163 
00164 void DbiTableMetaData::SetColFieldType(const DbiFieldType& fieldType,
00165                                        Int_t colNum) {
00166 //
00167 //
00168 //  Purpose:  Define field type for specified column.
00169 //
00170 //  Arguments: 
00171 //    fieldType    in    Column field type.
00172 //    colNum       in    Column number (1,2...)
00173 //
00174 
00175   ColumnAttributes&  attrib(this->SetAttributes(colNum));
00176   UInt_t concept     = fieldType.GetConcept();
00177   attrib.Type        = fieldType;
00178   attrib.MustDelimit = concept == Dbi::kString || concept == Dbi::kDate || concept == Dbi::kChar;
00179   attrib.Concept     = concept;
00180 
00181 }
00182 
00183 //.....................................................................
00184 
00185 void DbiTableMetaData::SetFromSql(const string& sql) {
00186 //
00187 //
00188 //  Purpose:  Reconstruct this object using SQL to create table.
00189 
00190 
00191   TString SqlUpper(sql);
00192   SqlUpper.ToUpper();
00193 
00194   const char* strPtr = SqlUpper.Data();
00195 
00196   string token1(DbiTableMetaData::GetToken(strPtr));
00197   string token2(DbiTableMetaData::GetToken(strPtr));
00198   string token3(DbiTableMetaData::GetToken(strPtr));
00199   string token4(DbiTableMetaData::GetToken(strPtr));
00200 
00201   if ( token1 != "CREATE" || token2 != "TABLE" || token4 != "(" ) {
00202     MSG("Dbi",Msg::kError) << "Cannot recreate: SQL " << SqlUpper 
00203                            << " does not start CREATE TABLE ... (" << endl;
00204     return;
00205   }
00206 
00207   this->Clear();
00208   fTableName = token3;
00209   MSG("Dbi",Msg::kSynopsis) << "Recreating  DbiTableMetaData for table " << fTableName << endl;
00210 
00211 // Loop processing column specifications.
00212   Int_t col = 0;
00213 
00214   string delim;
00215   while ( delim != ")" ) {
00216     string name = DbiTableMetaData::GetToken(strPtr);
00217 
00218 //  Deal with INDEX and PRIMARY KEY
00219     if ( name == "INDEX" ||  name == "KEY" || name == "PRIMARY" ) {
00220       if ( name == "PRIMARY" || name == "KEY" )delim = DbiTableMetaData::GetToken(strPtr);
00221       delim = DbiTableMetaData::GetToken(strPtr);
00222       if ( delim == "(" ) while ( delim != ")" ) delim = DbiTableMetaData::GetToken(strPtr);
00223       delim = DbiTableMetaData::GetToken(strPtr);
00224       continue;
00225     }
00226 
00227 //  Collect name and type.
00228     ++col;
00229     this->SetColName(name,col);
00230     this->SetColIsNullable(col);
00231 
00232     string type = DbiTableMetaData::GetToken(strPtr);
00233     int precision = 0;
00234     delim = DbiTableMetaData::GetToken(strPtr);
00235     if ( delim == "(" ) {
00236       delim = DbiTableMetaData::GetToken(strPtr);
00237       istringstream is(delim);
00238       is >> precision;
00239       delim = DbiTableMetaData::GetToken(strPtr);
00240       delim = DbiTableMetaData::GetToken(strPtr);
00241     }
00242     DbiFieldType ft(type,precision);
00243     this->SetColFieldType(ft,col);
00244     MSG("Dbi",Msg::kSynopsis) << "  Column: " << col << " name " << this->ColName(col) 
00245                           << " type " << this->ColFieldType(col).AsString() 
00246                           << " precision " << precision << endl;
00247 
00248 //  Collect optional qualifiers.
00249 
00250     while ( delim != ","  &&  delim != ")" ) {
00251       string opt2 = DbiTableMetaData::GetToken(strPtr);
00252       if ( delim == "NOT" && opt2 == "NULL") {
00253         this->SetColIsNullable(col,false);
00254         delim = DbiTableMetaData::GetToken(strPtr);
00255       }
00256       else if ( delim == "PRIMARY" && opt2 == "KEY") {
00257         delim = DbiTableMetaData::GetToken(strPtr);
00258       }
00259       else if ( delim == "AUTO_INCREMENT") {
00260         delim = opt2;
00261       }
00262       else if ( delim == "UNSIGNED") {
00263         delim = opt2;
00264       }
00265       else {
00266         MSG("Dbi",Msg::kWarning) <<"Column: " << col << " name " << name << " type " << ft.AsString()
00267                               << " ignoring unknown option: " << delim << endl;
00268         delim = opt2;
00269       }
00270     }
00271   }
00272 
00273 }
00274 
00275 
00276 //.....................................................................
00277 
00278 string DbiTableMetaData::Sql(Dbi::DbTypes dbType_target) const {
00279 //
00280 //
00281 //  Purpose:  Return SQL string to create table.
00282 //
00283 //  Arguments: 
00284 //    dbType_target  in    The target database type (either  kMySQL or kOracle)
00285 //    
00286 //
00287 //  Return:    SQL command to create required table.
00288 //             For an ORACLE target DB, there will be multiple semi-colon separated
00289 //             commands within the string.
00290 
00291   Bool_t mainTable = fTableName.substr(fTableName.size()-3,3) != "VLD";
00292   bool hasRowCounter = false;
00293 
00294   string tableName = fTableName;
00295   DbiString sql;
00296   sql.GetString() = "";
00297   sql << "create table " << tableName << "(";
00298 
00299 
00300 //  Assemble columns.
00301 
00302   int numCols = this->NumCols();
00303   for(int i=1; i<= numCols; i++) {
00304 
00305     if ( this->ColName(i) == "ROW_COUNTER" ) hasRowCounter = true;
00306     sql << this->ColName(i) << " " ;
00307     sql << this->ColFieldType(i).AsSQLString(dbType_target);
00308 
00309     if(    dbType_target == Dbi::kMySQL
00310         && this->ColName(i) == "SEQNO" 
00311         && ! mainTable )          sql << " not null primary key" ;
00312 
00313     else if( ! this->ColIsNullable(i)
00314             || this->ColName(i) == "SEQNO"
00315             || this->ColName(i) == "ROW_COUNTER"
00316            ) sql << " not null" ;
00317       
00318     if (i < numCols)              sql << ", ";
00319 
00320   }
00321 
00322 // Deal with key/index/constraint.
00323 
00324 // Nothing to do for the special xxxSEQNO tables.
00325   if ( fTableName == "GLOBALSEQNO" ||  fTableName == "LOCALSEQNO" ) {
00326     sql << ")";
00327   }
00328 
00329 // Deal with MySQL
00330   else if (dbType_target == Dbi::kMySQL ) {
00331     if ( mainTable ) {
00332       if ( hasRowCounter )  sql << ", primary key (SEQNO,ROW_COUNTER)";
00333       else                  sql << ", index (SEQNO)";
00334     }
00335     else {
00336       sql << ", key TIMESTART (TIMESTART), key TIMEEND (TIMEEND)";
00337     }
00338     sql << ")"; 
00339   }
00340 
00341 // Deal with ORACLE 
00342   else {
00343     if ( mainTable ) {
00344       sql << ", constraint FK_" << fTableName << " foreign key(SEQNO) references "
00345           << fTableName << "VLD(SEQNO)";
00346       if ( hasRowCounter ) 
00347         sql << ", constraint PK_" << fTableName 
00348             << "VLD primary key(SEQNO,ROW_COUNTER) using index tablespace MINOS_DEV_IDX";
00349     }
00350     else {
00351       sql << ", constraint PK_" << fTableName 
00352           << "VLD primary key(SEQNO) using index tablespace MINOS_DEV_IDX";
00353     }
00354     sql << ")tablespace MINOS_DEV_DATA";
00355 
00356     if ( mainTable) {
00357       if ( ! hasRowCounter ) 
00358         sql << "; create index " << tableName << "_idx  on " 
00359             << tableName << "(seqno) tablespace MINOS_DEV_IDX";
00360       sql << "; create index " << fTableName << "VLD_idx2 on " 
00361           << fTableName << "VLD(TIMESTART) tablespace MINOS_DEV_IDX";
00362       sql << "; create index " << fTableName << "VLD_idx3 on " 
00363           << fTableName << "VLD(TIMEEND) tablespace MINOS_DEV_IDX";
00364     }
00365     else {
00366 
00367     }
00368   }
00369 
00370 // For ORACLE, create public synonym and grant access.
00371 
00372   if ( dbType_target == Dbi::kOracle ) {
00373     sql << "; create public synonym " << tableName << " for " << tableName;
00374     sql << "; grant  select on " << tableName << " to minos_reader";
00375     sql << "; grant  select,insert,update on " << tableName << " to minos_writer";
00376   }
00377 
00378   return sql.GetString();
00379 
00380 }
00381 

Generated on Mon Feb 15 11:06:35 2010 for loon by  doxygen 1.3.9.1