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
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
00029
00030
00031
00032
00033
00034
00035 DbiTableMetaData::DbiTableMetaData(const string& tableName) :
00036 fNumCols(0),
00037 fTableName(tableName)
00038 {
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 LEA_CTOR
00050
00051 MSG("Dbi", Msg::kVerbose) << "Creating DbiTableMetaData" << endl;
00052
00053 }
00054
00055
00056
00057 DbiTableMetaData::~DbiTableMetaData() {
00058
00059
00060
00061
00062 LEA_DTOR
00063
00064 MSG("Dbi", Msg::kVerbose) << "Destroying DbiTableMetaData" << endl;
00065
00066 }
00067
00069
00070 void DbiTableMetaData::Clear() {
00071
00072
00073
00074
00075
00076
00077 fColAttr.clear();
00078 fNumCols = 0;
00079
00080 }
00081
00082
00083
00084 void DbiTableMetaData::ExpandTo(UInt_t colNum) {
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
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
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
00131
00132 string token;
00133
00134
00135 while ( isspace(*strPtr) ) ++strPtr;
00136 if ( *strPtr == 0 ) return token;
00137
00138
00139 char firstChar = *strPtr++;
00140 token = firstChar;
00141 if ( ! isalnum(firstChar) && firstChar != '_' ) return token;
00142
00143
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
00154
00155 this->ExpandTo(colNum);
00156
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
00169
00170
00171
00172
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
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
00212 Int_t col = 0;
00213
00214 string delim;
00215 while ( delim != ")" ) {
00216 string name = DbiTableMetaData::GetToken(strPtr);
00217
00218
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
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
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
00282
00283
00284
00285
00286
00287
00288
00289
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
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
00323
00324
00325 if ( fTableName == "GLOBALSEQNO" || fTableName == "LOCALSEQNO" ) {
00326 sql << ")";
00327 }
00328
00329
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
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
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