////////////////////////////////////////////////////////////////////////// //////////////////////////// ROOT API //////////////////////////// ////////////////////////////////////////////////////////////////////////// #include #include #include #include "TString.h" #include "IDbi.hxx" #include "IDbiString.hxx" #include "IDbiTableMetaData.hxx" #include #include using std::endl; ClassImp(COMET::IDbiTableMetaData) // Definition of static data members // ********************************* COMET::IDbiTableMetaData::ColumnAttributes COMET::IDbiTableMetaData::fgDummy; // Definition of all member functions (static or otherwise) // ******************************************************* // // - ordered: ctors, dtor, operators then in alphabetical order. //..................................................................... COMET::IDbiTableMetaData::IDbiTableMetaData(const string& tableName) : fNumCols(0), fTableName(tableName) { // // // Purpose: Default constructor // Program Notes:- // ============= // This is filled by the owning COMET::IDbiTableProxy, as it is too low level to // use the cascade to fill itself, hence the friend status granted to COMET::IDbiDBProxy. COMETTrace( "Creating COMET::IDbiTableMetaData" << " "); } //..................................................................... COMET::IDbiTableMetaData::~IDbiTableMetaData() { // // // Purpose: Destructor COMETTrace( "Destroying COMET::IDbiTableMetaData" << " "); } ///..................................................................... void COMET::IDbiTableMetaData::Clear() { // // // Purpose: Clear out existing data (apart from table name) // // Contact: N. West fColAttr.clear(); fNumCols = 0; } //..................................................................... void COMET::IDbiTableMetaData::ExpandTo(UInt_t colNum) { // // // Purpose: Expand table if required to specied colNum // // Arguments: // colNum in Column number to expand to (1,2...). // // Return: // // Contact: N. West // // Specification:- // ============= // // o // Program Notes:- // ============= // None. assert ( colNum < MAXCOL ); while ( fNumCols < colNum ) { fColAttr.push_back(ColumnAttributes()); ++fNumCols; } } //..................................................................... const COMET::IDbiTableMetaData::ColumnAttributes& COMET::IDbiTableMetaData::GetAttributes(Int_t colNum) const { // Return a column attributes (will be dummy entry if requesting invalid column) if ( colNum > 0 && colNum <= (signed) fNumCols ) return fColAttr[colNum-1]; fgDummy.SetDefault(); return fgDummy; } //..................................................................... string COMET::IDbiTableMetaData::GetToken(const char*& strPtr) { // // // Purpose: Skip spaces and return next token from string and move pointer on. string token; // Skip white space and quit if at EOS. while ( isspace(*strPtr) ) ++strPtr; if ( *strPtr == 0 ) return token; // Collect the first character whatever it is. char firstChar = *strPtr++; token = firstChar; if ( ! isalnum(firstChar) && firstChar != '_' ) return token; // Collect more if collecting alphanumeric + underscore string while ( isalnum(*strPtr) || *strPtr == '_' ) token += *strPtr++; return token; } //..................................................................... COMET::IDbiTableMetaData::ColumnAttributes& COMET::IDbiTableMetaData::SetAttributes(Int_t colNum) { // Return a column attributes (will be dummy entry if requesting invalid column) this->ExpandTo(colNum); // Using const metho so must cast away constness. return const_cast(this->GetAttributes(colNum)); } //..................................................................... void COMET::IDbiTableMetaData::SetColFieldType(const COMET::IDbiFieldType& fieldType, Int_t colNum) { // // // Purpose: Define field type for specified column. // // Arguments: // fieldType in Column field type. // colNum in Column number (1,2...) // ColumnAttributes& attrib(this->SetAttributes(colNum)); UInt_t concept = fieldType.GetConcept(); attrib.Type = fieldType; attrib.MustDelimit = concept == IDbi::kString || concept == IDbi::kDate || concept == IDbi::kChar; attrib.Concept = concept; } //..................................................................... void COMET::IDbiTableMetaData::SetFromSql(const string& sql) { // // // Purpose: Reconstruct this object using SQL to create table. TString SqlUpper(sql); SqlUpper.ToUpper(); const char* strPtr = SqlUpper.Data(); string token1(COMET::IDbiTableMetaData::GetToken(strPtr)); string token2(COMET::IDbiTableMetaData::GetToken(strPtr)); string token3(COMET::IDbiTableMetaData::GetToken(strPtr)); string token4(COMET::IDbiTableMetaData::GetToken(strPtr)); if ( token1 != "CREATE" || token2 != "TABLE" || token4 != "(" ) { COMETSevere( "Cannot recreate: SQL " << SqlUpper << " does not start CREATE TABLE ... (" << " "); return; } this->Clear(); fTableName = token3; COMETLog( "Recreating COMET::IDbiTableMetaData for table " << fTableName << " "); // Loop processing column specifications. Int_t col = 0; string delim; while ( delim != ")" ) { string name = COMET::IDbiTableMetaData::GetToken(strPtr); // Deal with INDEX and PRIMARY KEY if ( name == "INDEX" || name == "KEY" || name == "PRIMARY" ) { if ( name == "PRIMARY" || name == "KEY" )delim = COMET::IDbiTableMetaData::GetToken(strPtr); delim = COMET::IDbiTableMetaData::GetToken(strPtr); if ( delim == "(" ) while ( delim != ")" ) delim = COMET::IDbiTableMetaData::GetToken(strPtr); delim = COMET::IDbiTableMetaData::GetToken(strPtr); continue; } // Collect name and type. ++col; this->SetColName(name,col); this->SetColIsNullable(col); string type = COMET::IDbiTableMetaData::GetToken(strPtr); int precision = 0; delim = COMET::IDbiTableMetaData::GetToken(strPtr); if ( delim == "(" ) { delim = COMET::IDbiTableMetaData::GetToken(strPtr); istringstream is(delim); is >> precision; delim = COMET::IDbiTableMetaData::GetToken(strPtr); delim = COMET::IDbiTableMetaData::GetToken(strPtr); } COMET::IDbiFieldType ft(type,precision); this->SetColFieldType(ft,col); COMETLog( " Column: " << col << " name " << this->ColName(col) << " type " << this->ColFieldType(col).AsString() << " precision " << precision << " "); // Collect optional qualifiers. while ( delim != "," && delim != ")" ) { string opt2 = COMET::IDbiTableMetaData::GetToken(strPtr); if ( delim == "NOT" && opt2 == "NULL") { this->SetColIsNullable(col,false); delim = COMET::IDbiTableMetaData::GetToken(strPtr); } else if ( delim == "PRIMARY" && opt2 == "KEY") { delim = COMET::IDbiTableMetaData::GetToken(strPtr); } else if ( delim == "AUTO_INCREMENT") { delim = opt2; } else if ( delim == "UNSIGNED") { delim = opt2; } else { COMETWarn( "Column: " << col << " name " << name << " type " << ft.AsString() << " ignoring unknown option: " << delim << " "); delim = opt2; } } } } //..................................................................... string COMET::IDbiTableMetaData::Sql() const { // // // Purpose: Return SQL string to create table. // // Return: SQL command to create required table. Bool_t mainTable = fTableName.substr(fTableName.size()-3,3) != "VLD"; string tableName = fTableName; COMET::IDbiString sql; sql.GetString() = ""; sql << "create table " << tableName << "("; // Assemble columns. int numCols = this->NumCols(); for(int i=1; i<= numCols; i++) { sql << this->ColName(i) << " " ; sql << this->ColFieldType(i).AsSQLString(); if( this->ColName(i) == "SEQNO" && ! mainTable ) sql << " not null primary key" ; else if( ! this->ColIsNullable(i) || this->ColName(i) == "SEQNO" || this->ColName(i) == "ROW_COUNTER" ) sql << " not null" ; if (i < numCols) sql << ", "; } // Deal with key/index/constraint. // Nothing to do for the special xxxSEQNO tables. if ( fTableName == "GLOBALSEQNO" || fTableName == "LOCALSEQNO" ) { sql << ")"; } else { if ( mainTable ) { sql << ", primary key (SEQNO,ROW_COUNTER)"; } else { sql << ", key TIMESTART (TIMESTART), key TIMEEND (TIMEEND)"; } sql << ")"; } return sql.GetString(); }