EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FairDbTableMetaData.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file FairDbTableMetaData.cxx
1 
2 #include <cassert>
3 #include <cctype>
4 #include <sstream>
5 
6 #include "TString.h"
7 
8 #include "FairDb.h"
9 #include "FairDbString.h"
10 #include "FairDbTableMetaData.h"
11 
13 
14 
15 FairDbTableMetaData::ColumnAttributes FairDbTableMetaData::fgDummy;
16 
17 FairDbTableMetaData::FairDbTableMetaData(const string& tableName) :
18  fColAttr(),
19  fNumCols(0),
20  fTableName(tableName)
21 {
22 
23 }
24 
25 
27 {
28 
29 }
30 
31 
33 {
34 
35  fColAttr.clear();
36  fNumCols = 0;
37 
38 }
39 
40 
41 void FairDbTableMetaData::ExpandTo(UInt_t colNum)
42 {
43 
44  assert ( colNum < MAXCOL );
45  while ( fNumCols < colNum ) {
46  fColAttr.push_back(ColumnAttributes());
47  ++fNumCols;
48  }
49 }
50 
51 
53 {
54 
55  if ( colNum > 0 && colNum <= (signed) fNumCols ) { return fColAttr[colNum-1]; }
57  return fgDummy;
58 
59 }
60 
61 
62 string FairDbTableMetaData::GetToken(const char*& strPtr)
63 {
64  string token;
65 
66 // Skip white space and quit if at EOS.
67  while ( isspace(*strPtr) ) { ++strPtr; }
68  if ( *strPtr == 0 ) { return token; }
69 
70 // Collect the first character whatever it is.
71  char firstChar = *strPtr++;
72  token = firstChar;
73  if ( ! isalnum(firstChar) && firstChar != '_' ) { return token; }
74 
75 // Collect more if collecting alphanumeric + underscore string
76  while ( isalnum(*strPtr) || *strPtr == '_' ) { token += *strPtr++; }
77  return token;
78 
79 }
81 {
82 
83  // Return a column attributes
84  //(will be dummy entry if requesting invalid column)
85  this->ExpandTo(colNum);
86  // Using const metho so must cast away constness.
87  return const_cast<FairDbTableMetaData::ColumnAttributes&>(this->GetAttributes(colNum));
88 
89 }
90 
92  Int_t colNum)
93 {
94  ColumnAttributes& attrib(this->SetAttributes(colNum));
95  UInt_t concept = fieldType.GetConcept();
96  attrib.Type = fieldType;
97  attrib.MustDelimit = concept == FairDb::kString || concept == FairDb::kDate || concept == FairDb::kChar;
98  attrib.Concept = concept;
99 
100 }
101 
102 void FairDbTableMetaData::SetFromSql(const string& sql)
103 {
104 
105  TString SqlUpper(sql);
106  SqlUpper.ToUpper();
107 
108  const char* strPtr = SqlUpper.Data();
109 
110  string token1(FairDbTableMetaData::GetToken(strPtr));
111  string token2(FairDbTableMetaData::GetToken(strPtr));
112  string token3(FairDbTableMetaData::GetToken(strPtr));
113  string token4(FairDbTableMetaData::GetToken(strPtr));
114 
115  if ( token1 != "CREATE" || token2 != "TABLE" || token4 != "(" ) {
116  cout << "Cannot recreate: SQL " << SqlUpper
117  << " does not start CREATE TABLE ... (" << endl;
118  return;
119  }
120 
121  this->Clear();
122  fTableName = token3;
123  cout << "Recreating FairDbTableMetaData for table " << fTableName << endl;
124 
125 // Loop processing column specifications.
126  Int_t col = 0;
127 
128  string delim;
129  while ( delim != ")" ) {
130  string name = FairDbTableMetaData::GetToken(strPtr);
131 
132 // Deal with INDEX and PRIMARY KEY
133  if ( name == "INDEX" || name == "KEY" || name == "PRIMARY" ) {
134  if ( name == "PRIMARY" || name == "KEY" ) { delim = FairDbTableMetaData::GetToken(strPtr); }
135  delim = FairDbTableMetaData::GetToken(strPtr);
136  if ( delim == "(" ) while ( delim != ")" ) { delim = FairDbTableMetaData::GetToken(strPtr); }
137  delim = FairDbTableMetaData::GetToken(strPtr);
138  continue;
139  }
140 
141 // Collect name and type.
142  ++col;
143  this->SetColName(name,col);
144  this->SetColIsNullable(col);
145 
146  string type = FairDbTableMetaData::GetToken(strPtr);
147  int precision = 0;
148  delim = FairDbTableMetaData::GetToken(strPtr);
149  if ( delim == "(" ) {
150  delim = FairDbTableMetaData::GetToken(strPtr);
151  istringstream is(delim);
152  is >> precision;
153  delim = FairDbTableMetaData::GetToken(strPtr);
154  delim = FairDbTableMetaData::GetToken(strPtr);
155  }
156  FairDbFieldType ft(type,precision);
157  this->SetColFieldType(ft,col);
158  cout << " Column: " << col << " name " << this->ColName(col)
159  << " type " << this->ColFieldType(col).AsString()
160  << " precision " << precision << endl;
161 
162 // Collect optional qualifiers.
163 
164  while ( delim != "," && delim != ")" ) {
165  string opt2 = FairDbTableMetaData::GetToken(strPtr);
166  if ( delim == "NOT" && opt2 == "NULL") {
167  this->SetColIsNullable(col,false);
168  delim = FairDbTableMetaData::GetToken(strPtr);
169  } else if ( delim == "PRIMARY" && opt2 == "KEY") {
170  delim = FairDbTableMetaData::GetToken(strPtr);
171  } else if ( delim == "AUTO_INCREMENT") {
172  delim = opt2;
173  } else if ( delim == "UNSIGNED") {
174  delim = opt2;
175  } else {
176  cout <<"Column: " << col << " name " << name << " type " << ft.AsString()
177  << " ignoring unknown option: " << delim << endl;
178  delim = opt2;
179  }
180  }
181  }
182 
183 }
184 
185 
186 string FairDbTableMetaData::Sql(FairDb::DbTypes dbType_target) const
187 {
188 
189  Bool_t mainTable = fTableName.substr(fTableName.size()-3,3) != "VAL";
190  bool hasRowCounter = false;
191 
192  string tableName = fTableName;
193  FairDbString sql;
194  sql.GetString() = "";
195  sql << "create table " << tableName << "(";
196 
197 // Assemble columns.
198  int numCols = this->NumCols();
199  for(int i=1; i<= numCols; i++) {
200 
201  if ( this->ColName(i) == "ROW_COUNTER" ) { hasRowCounter = true; }
202  sql << this->ColName(i) << " " ;
203  sql << this->ColFieldType(i).AsSQLString(dbType_target);
204 
205  if( dbType_target == FairDb::kMySQL
206  && this->ColName(i) == "SEQNO"
207  && ! mainTable ) { sql << " not null primary key" ; }
208 
209  else if( ! this->ColIsNullable(i)
210  || this->ColName(i) == "SEQNO"
211  || this->ColName(i) == "ROW_COUNTER"
212  ) { sql << " not null" ; }
213 
214  if (i < numCols) { sql << ", "; }
215 
216  }
217 
218 // Deal with key/index/constraint.
219 
220 // Nothing to do for the special xxxSEQNO tables.
221  if ( fTableName == "GLOBALSEQNO" || fTableName == "LOCALSEQNO" ) {
222  sql << ")";
223  }
224 
225 // Deal with MySQL
226  else if (dbType_target == FairDb::kMySQL ) {
227  if ( mainTable ) {
228  if ( hasRowCounter ) { sql << ", primary key (SEQNO,ROW_COUNTER)"; }
229  else { sql << ", index (SEQNO)"; }
230  } else {
231  sql << ", key TIMESTART (TIMESTART), key TIMEEND (TIMEEND)";
232  }
233  sql << ")";
234  }
235 
236 // Deal with ORACLE
237  else {
238  if ( mainTable ) {
239  sql << ", constraint FK_" << fTableName << " foreign key(SEQNO) references "
240  << fTableName << "VAL(SEQNO)";
241  if ( hasRowCounter )
242  sql << ", constraint PK_" << fTableName
243  << "VAL primary key(SEQNO,ROW_COUNTER) using index tablespace R3B_DEV_IDX";
244  } else {
245  sql << ", constraint PK_" << fTableName
246  << "VAL primary key(SEQNO) using index tablespace R3B_DEV_IDX";
247  }
248  sql << ")tablespace R3B_DEV_DATA";
249 
250  if ( mainTable) {
251  if ( ! hasRowCounter )
252  sql << "; create index " << tableName << "_idx on "
253  << tableName << "(seqno) tablespace R3B_DEV_IDX";
254  sql << "; create index " << fTableName << "VAL_idx2 on "
255  << fTableName << "VAL(TIMESTART) tablespace R3B_DEV_IDX";
256  sql << "; create index " << fTableName << "VAL_idx3 on "
257  << fTableName << "VAL(TIMEEND) tablespace R3B_DEV_IDX";
258  } else {
259 
260  }
261  }
262 
263 // For ORACLE, create public synonym and grant access.
264 
265  if ( dbType_target == FairDb::kOracle ) {
266  sql << "; create public synonym " << tableName << " for " << tableName;
267  sql << "; grant select on " << tableName << " to r3b_reader";
268  sql << "; grant select,insert,update on " << tableName << " to r3b_writer";
269  }
270 
271  return sql.GetString();
272 
273 }
274