BOSS 7.0.4
BESIII Offline Software System
Loading...
Searching...
No Matches
Table.cxx
Go to the documentation of this file.
1// $Header: /bes/bes/BossCvs/Calibration/rdbModel/src/Tables/Table.cxx,v 1.1.1.1 2005/10/17 06:10:53 maqm Exp $
2
3#include "rdbModel/Tables/Table.h"
4#include "rdbModel/Tables/Column.h"
5#include "rdbModel/Tables/Index.h"
6#include "rdbModel/Tables/Assertion.h"
7#include "rdbModel/Db/Connection.h"
8#include "rdbModel/Db/ResultHandle.h"
9#include "rdbModel/RdbException.h"
10#include "rdbModel/Tables/InsertNew.h"
11#include "rdbModel/Tables/InterRow.h"
12#include "rdbModel/Tables/Query.h"
13#include "rdbModel/Tables/Set.h"
14#include "rdbModel/Tables/Supersede.h"
15#include "facilities/Util.h"
16#include "facilities/Timestamp.h"
17#include <algorithm>
18
19namespace rdbModel {
20 Table::Table() : m_primaryKeyCol(""), m_sorted(false), m_nEndUser(0),
21 m_validRow(0), m_iNew(0), m_sup(0), m_connect(0) {
22 m_sortedCols.clear(); m_programCols.clear();
23 m_userCols.clear(); m_mayDefault.clear();
24 m_out = &std::cout; m_err = &std::cerr;
25 }
26
27
29 while (m_cols.size() ) {
30 Column* c = m_cols.back();
31 m_cols.pop_back();
32 delete c;
33 }
34
35 while (m_asserts.size() ) {
36 Assertion* a = m_asserts.back();
37 m_asserts.pop_back();
38 delete a;
39 }
40
41 while (m_indices.size() ) {
42 Index* i = m_indices.back();
43 m_indices.pop_back();
44 delete i;
45 }
46 }
47
48
50 m_connect = connect;
51 m_out = connect->getOut();
52 m_err = connect->getErrOut();
53 }
54 // Columns are stored in order; binary cuts should do better than
55 // just dumb compare one by one.
56 Column* Table::getColumnByName(const std::string& name) const {
57 unsigned nCol = m_sortedCols.size();
58 unsigned minI = 0;
59 unsigned maxI = nCol;
60
61 unsigned guess = maxI/2;
62 unsigned oldGuess = nCol;
63
64 int cmp = name.compare(m_sortedCols[guess]->getName());
65
66 while (cmp != 0) {
67 if (guess == oldGuess) return 0; // not found
68
69 if (cmp < 0 ) { // thing we tried is > colName, so decrease maxI
70 maxI = guess;
71 } else { // thing we tried is > colName, so increase minI
72 minI = guess;
73 }
74 oldGuess = guess;
75 guess = (minI + maxI)/2;
76 cmp = name.compare(m_sortedCols[guess]->getName());
77 }
78 return m_sortedCols[guess];
79
80 }
81
82 Index* Table::getIndexByName(const std::string& name) const {
83 unsigned nIx = m_indices.size();
84 for (unsigned iIx = 0; iIx < nIx; iIx++) {
85 Index* index = m_indices[iIx];
86 if (index->getName() == name) return index;
87 }
88 return 0;
89 }
90
91 Assertion* Table::getAssertionByName(const std::string& name) const {
92 unsigned nAssert = m_asserts.size();
93 for (unsigned i = 0; i < nAssert; i++) {
94 Assertion* a = m_asserts[i];
95 if (a->getName() == name) return a;
96 }
97 return 0;
98
99 }
100
101 // Traversal order is self, columns, indices, asserts
103
104 Visitor::VisitorState state = v->visitTable(this);
105 if (state == Visitor::VBRANCHDONE) return Visitor::VCONTINUE;
106 if (state != Visitor::VCONTINUE) return state;
107
108 unsigned n = m_cols.size();
109
110 for (unsigned i = 0; i < n; i++) {
111 state = m_cols[i]->accept(v);
112 if (state != Visitor::VCONTINUE) return state;
113 }
114
115 n = m_indices.size();
116 for (unsigned i = 0; i < n; i++) {
117 state = m_indices[i]->accept(v);
118 if (state != Visitor::VCONTINUE) return state;
119 }
120
121 n = m_asserts.size();
122 for (unsigned i = 0; i < n; i++) {
123 state = m_asserts[i]->accept(v);
124 if (state != Visitor::VCONTINUE) return state;
125 }
126 return state;
127 }
128
130 if (m_sorted) return;
131 m_sortedCols = m_cols;
132
133 ColCompare cmpObject;
134
135 // Keep around original set so that rdbGUI will display them in
136 // this order
137 std::sort (m_sortedCols.begin(), m_sortedCols.end(), cmpObject);
138 m_sorted = true;
139
140 }
141
142 void Table::addColumn(Column* c) {
143 m_cols.push_back(c);
145 m_nEndUser++;
146 // if not nullable and no default, user must supply it
147 if (!(c->nullAllowed()) && ((c->getDefault()).size() == 0)) {
148 m_userCols.push_back(c);
149 }
150 else {
151 m_mayDefault.push_back(c);
152 }
153 }
154 else if (c->getSourceType() == Column::FROMdefault) {
155 m_mayDefault.push_back(c);
156 }
157 else if (c->getSourceType() == Column::FROMprogram) {
158 m_programCols.push_back(c);
159 }
160 }
161
162 int Table::insertLatest(Row& row, int* serial) const {
163
164 if (!m_connect) {
165 throw RdbException("Table::insertLatest Need matching connection");
166 }
167 row.rowSort();
168
169 // Fill in columns in m_programCols list
170 fillProgramCols(row, true);
171
172 // Check that all required columns are there and not null
173 for (unsigned i = 0; i < m_userCols.size(); i++) {
174 FieldVal* f = row.find(m_userCols[i]->getName());
175 if ((!f) || (f->m_null)) {
176 std::string
177 msg("Table::insertLatest Row to be inserted missing req'd field ");
178 msg = msg + m_userCols[i]->getName();
179 throw RdbException(msg);
180 }
181 }
182 // Fill in defaults
183 fillDefaults(row);
184
185 // Check against consistency conditions specified by <insertNew>
186 const Assertion* cond = m_iNew->getInternal();
187 bool satisfied;
188
189 try {
190 satisfied = cond->verify(row, row);
191 }
192 catch (RdbException ex) {
193 (*m_out) << ex.getMsg() << std::endl;
194 return -1;
195 }
196
197 if (!satisfied) return -1; // or maybe throw exception here?
198
199 // Check against official conditions specified by <insertNew>
200 const Assertion* condO = m_iNew->getOfficial();
201 Row empty;
202 std::vector<std::string> colNames;
203 std::vector<std::string> colValues;
204 std::vector<std::string> nullCols;
205
206 row.regroup(colNames, colValues, nullCols);
207
208 satisfied = condO->verify(empty, row);
209
210 // If not official, do insert and exit
211 if (!satisfied) {
212 bool ok = m_connect->insertRow(m_name, colNames, colValues,
213 serial, &nullCols);
214 return (ok) ? 0 : -1;
215 }
216
217 const std::vector<InterRow* >& inter = m_iNew->getInterRow();
218
219 unsigned nInter = inter.size();
220 Assertion* subsAssert;
221 for (unsigned iInter = 0; iInter < nInter; iInter++) {
222 const Query* q = inter[iInter]->getQuery();
223 const std::vector<std::string>& toSelect = q->getToSelect();
224
225 // Need to make a new Assertion which substitues our proposed row
226 // values for all "toBe" entries
227 subsAssert = new Assertion(q->getAssertion(), &row);
228
229 std::vector<std::string> orderCols;
230 orderCols.clear();
231 ResultHandle* r = m_connect->select(m_name, toSelect, orderCols,
232 subsAssert);
233
234 if (r->getNRows() == 0) { // no conflicts found
235 delete subsAssert;
236 continue; // go on to next InterRow, if any.
237 }
238
239 // otherwise
240 // if quit go ahead and quit
241 if (inter[iInter]->getQuit()) {
242 delete subsAssert;
243 (*m_out) << "insert latest not done because of irreconcilable "
244 << std::endl << "conflict with existing rows" << std::endl;
245 return -1;
246 }
247 // else modify conflicting rows as specified in <interRow>.
248 // (i.e., do an update with where clause = subsAssert
249
250 std::vector<Set> sets = inter[iInter]->getSets();
251
252 bool iu = doInterUpdate(sets, subsAssert, row);
253 if (!iu) return -1;
254 }
255 // Insert and exit
256 bool ok = m_connect->insertRow(m_name, colNames, colValues,
257 serial, &nullCols);
258 return (ok) ? 0 : -1;
259 }
260
261 int Table::insertRow(Row& row, int* serial) const {
262
263 if (!m_connect) {
264 throw RdbException("Table::insertRow Need matching connection");
265 }
266 row.rowSort();
267
268 // Fill in columns in m_programCols list
269 fillProgramCols(row, true);
270
271
272 // Check that all required columns are there and not null
273 for (unsigned i = 0; i < m_userCols.size(); i++) {
274 FieldVal* f = row.find(m_userCols[i]->getName());
275 if ((!f) || (f->m_null)) {
276 std::string
277 msg("Table::insertRow Row to be inserted missing req'd field ");
278 msg = msg + m_userCols[i]->getName();
279 throw RdbException(msg);
280 }
281 }
282
283 // Fill in defaults
284 fillDefaults(row);
285
286 // Check standard valid row condition if there is one
287 if (m_validRow) {
288 bool satisfied;
289 try {
290 satisfied = m_validRow->verify(row, row);
291 }
292 catch (RdbException ex) {
293 (*m_out) << ex.getMsg() << std::endl;
294 return -1;
295 }
296 if (!satisfied) {
297 // throw RdbException("Table::insertRow Row to be inserted is not valid");
298 (*m_out) << "Table::insertRow Row to be inserted is not valid "
299 << std::endl;
300 m_out->flush();
301 return -1;
302 }
303 }
304 // Insert and exit
305 std::vector<std::string> colNames;
306 std::vector<std::string> colValues;
307 std::vector<std::string> nullCols;
308
309 row.regroup(colNames, colValues, nullCols);
310 bool ok = m_connect->insertRow(m_name, colNames, colValues,
311 serial, &nullCols);
312 return (ok) ? 0 : -1;
313 }
314
315 int Table::supersedeRow(Row& row, int oldKey, int* serial) const {
316 std::string oldKeyStr;
317 facilities::Util::itoa(oldKey, oldKeyStr);
318
319 if (m_primaryKeyCol.size() == 0) {
320 throw RdbException("Table::supersedeRow No primary key column!");
321 }
322
323 // Confirm that row does not contain any of the fixed or oldForced columns
324 row.rowSort();
325 const std::vector<std::string>& forced = m_sup->getForced();
326 for (unsigned i = 0; i < forced.size(); i++) {
327 if (row.find(forced[i])) {
328 // throw RdbException
329 // (std::string("Table::supersedeRow bad column in input row ") +
330 // forced[i]);
331 (*m_out) << "Table::supersedeRow bad column in input row '"
332 << forced[i] << "'" << std::endl;
333 m_out->flush();
334 return -1;
335 }
336 }
337 const std::vector<FieldVal>& fixed = m_sup->getFixed();
338 for (unsigned i = 0; i < fixed.size(); i++) {
339 if (row.find(fixed[i].m_colname)) {
340 // throw RdbException
341 // (std::string("Table::supersedeRow bad column in input row ") +
342 // fixed[i].m_colname);
343 (*m_out) << "Table::supersedeRow bad column in input row " <<
344 fixed[i].m_colname;
345 m_out->flush();
346 return -1;
347 }
348 }
349
350 // Check that old row is supersedable
351 if (!isSupersedable(oldKeyStr)) {
352 *m_out << "Row " << oldKey << " is not supersedable" << std::endl;
353 m_out->flush();
354 return -1;
355 }
356
357 // Fill in fixed fields
358 const std::vector<std::string>& fixedInterp = m_sup->getFixedInterp();
359 for (unsigned i = 0; i < fixed.size(); i++) {
360
361 FieldVal fv = fixed[i];
362 if (fixedInterp[i].size() > 0) {
363 Column* c = getColumnByName(fixed[i].m_colname);
364 c->interpret(fixedInterp[i], fv.m_val);
365 }
366 row.addField(fv);
367 }
368 row.rowSort();
369
370 // Fetch needed fields from row to be superseded (oldKey)
371 Assertion::Operator* whereOp =
372 new Assertion::Operator(OPTYPEequal, m_primaryKeyCol,
373 oldKeyStr, FIELDTYPEold, FIELDTYPElit);
374 Assertion* where = new Assertion(whereOp);
375
376 std::vector<std::string> noCols;
377 const std::vector<std::string>& fromOld = m_sup->getFromOld();
378 noCols.clear();
379 ResultHandle* results = m_connect->select(m_name, fromOld,
380 noCols, where);
381 // std::vector<std::string> vals;
382 // results->getRow(vals);
383 std::vector<std::string*> vals;
384 results->getRowPtrs(vals);
385 // Merge as needed into our row. First bunch may already be in the row
386 unsigned nDef = m_sup->getOldDefaulted().size();
387 for (unsigned i = 0; i < nDef; i++) {
388 if (!(row.find(fromOld[i])) ) {
389 if (vals[i] == 0) {
390 row.addField(FieldVal(fromOld[i], "", true));
391 }
392 else {
393 row.addField(FieldVal(fromOld[i], *vals[i]));
394 }
395 row.rowSort();
396 }
397 }
398 // Remainder definitely have to be merged in
399 for (unsigned i = nDef; i < fromOld.size(); i++) {
400 if (vals[i] == 0) {
401 row.addField(FieldVal(fromOld[i], "", true));
402 }
403 else {
404 row.addField(FieldVal(fromOld[i], *vals[i]));
405 }
406 }
407 results->cleanFieldPtrs(vals);
408
409 // Insert the row and update old row
410 int insRet;
411 try {
412 insRet = insertRow(row, serial);
413 }
414 catch (RdbException ex) {
415 (*m_out) << ex.getMsg() << std::endl;
416 insRet = -1;
417 }
418
419 if (insRet) { // something went wrong
420 delete where;
421 return insRet;
422 }
423
424 // Do the update of old row
425 const std::vector<Set*>& setOld = m_sup->getSetOld();
426 std::vector<FieldVal> oldFields;
427 oldFields.reserve(setOld.size());
428 for (unsigned i = 0; i < setOld.size(); i++) {
429 std::string src = setOld[i]->getSrcValue();
430 std::string col = setOld[i]->getDestColName();
431 if (setOld[i]->hasInterp() ) {
432 Column* c = getColumnByName(col);
433 c->interpret(setOld[i]->getInterp(), src);
434 }
435 oldFields.push_back(FieldVal(col, src));
436 }
437 Row updateArg(oldFields);
438 try {
439 int iUpdated = updateRows(updateArg, where);
440 if (iUpdated == 1) return 0;
441 return -1;
442 }
443 catch (RdbException uEx) {
444 (*m_out) << uEx.getMsg() << std::endl;
445 return -1;
446 }
447 }
448
449 int Table::updateRows(Row &row, Assertion* where) const {
450
451 if (!m_connect) {
452 throw RdbException("Table::insertLatest Need matching connection");
453 }
454 row.rowSort();
455
456 // Fill in columns in m_programCols list
457 fillProgramCols(row, false);
458
459 std::vector<std::string> colNames;
460 std::vector<std::string> colValues;
461 std::vector<std::string> nullCols;
462
463 row.regroup(colNames, colValues, nullCols);
464
465 return m_connect->update(m_name, colNames, colValues, where, &nullCols);
466 }
467
468 bool Table::fillProgramCols(Row& row, bool newRow) const {
469 std::string val;
470
471 for (unsigned i = 0; i < m_programCols.size(); i++) {
472 Column* col = m_programCols[i];
473 switch (col->getContentsType() ) {
475 val="rdbModel";
476 break;
478#ifdef __GNUG__
479 val = std::string("$(USER)");
480#else
481 val = std::string("$(USERNAME)");
482#endif
483
484 int nsub = facilities::Util::expandEnvVar(&val);
485 if (nsub != 1) {
486 val="no username";
487 }
488 break;
489 }
490
492 if (!newRow) continue; // otherwise, same as updateTime case
494 facilities::Timestamp curTime;
495 val = curTime.getString();
496 break;
497 }
498 default:
499 return false; // unrecognized type
500 }
501 // look for this field in Row input. If there, overwrite value
502 FieldVal* f = row.find(col->getName());
503 if (f) {
504 f->m_val = val;
505 f->m_null = false;
506 }
507 else {
508 FieldVal g(col->getName(), val, false);
509 row.addField(g);
510 row.rowSort();
511 }
512 }
513 return true;
514 }
515
516 void Table::fillDefaults(Row& row) const {
517 for (unsigned i = 0; i < m_mayDefault.size(); i++) {
518 Column* hasDef = m_mayDefault[i];
519 FieldVal* f = row.find(hasDef->getName());
520 if (f) continue;
521 // otherwise add it it
522 if ((hasDef->getDefault()).size() > 0) {
523 FieldVal g(hasDef->getName(), hasDef->getDefault());
524 row.addField(g);
525 }
526 else { // null
527 FieldVal g(hasDef->getName(), "", true);
528 row.addField(g);
529 }
530 row.rowSort();
531 }
532 }
533
534
535 // Source in <set>
536 // should either be FIELDTYPElit or FIELDTYPEtoBe. In latter
537 // case, substitute from row argument.
538 bool Table::doInterUpdate(const std::vector<Set>& sets,
539 Assertion* subsAssert, Row& toBe) const {
540 unsigned nSets = sets.size();
541 std::vector<FieldVal> fields;
542 fields.reserve(nSets);
543
544 for (unsigned iSet = 0; iSet < sets.size(); iSet++) {
545 std::string col = sets[iSet].getDestColName();
546 std::string src;
547 // updateCols.push_back(sets[iSet].getDestColName());
548 FIELDTYPE srcType = sets[iSet].getSrcType();
549 if ((srcType == FIELDTYPElit) || (srcType == FIELDTYPElitDef)) {
550 src = sets[iSet].getSrcValue();
551 // May require special handling
552 if (sets[iSet].hasInterp()) {
553 Column* c = getColumnByName(col);
554 c->interpret(sets[iSet].getInterp(), src);
555 /* should know how to substitute, e.g. val="NOW" should
556 be transformed into a timestamp */
557 }
558 }
559 else { // must be toBe
560 std::string toBeCol = sets[iSet].getSrcValue();
561 FieldVal* f = toBe.find(toBeCol);
562 if (f == 0) {
563 delete subsAssert;
564 (*m_out) << "Table::InsertNew Row argument missing needed field"
565 << toBeCol << std::endl;
566 m_out->flush();
567 return false;
568 // throw RdbException
569 // ("Table::InsertNew Row argument missing needed field");
570 }
571 src = f->m_val;
572 // updateVals.push_back(f->m_val);
573 }
574 FieldVal g(col, src);
575 fields.push_back(g);
576 }
577 Row row(fields);
578
579 fillProgramCols(row, false);
580
581 std::vector<std::string> updateCols;
582 std::vector<std::string> updateVals;
583 std::vector<std::string> nullCols;
584
585 row.regroup(updateCols, updateVals, nullCols);
586
587 // Make specified changes (update)
588 m_connect->update(m_name, updateCols, updateVals, subsAssert);
589
590 delete subsAssert;
591 return true;
592 }
593
594 const std::string& Table::setPrimaryKeyCol() {
595 static const std::string empty("");
596 if (m_primaryKeyCol.size() > 0) return m_primaryKeyCol;
597
598 for (unsigned iCol = 0; iCol < m_cols.size(); iCol++) {
599 if (m_cols[iCol]->isPrimaryKey()) {
600 m_primaryKeyCol = m_cols[iCol]->getName();
601 return m_primaryKeyCol;
602 }
603 }
604 return empty;
605 }
606
607 bool Table::isSupersedable(std::string oldKeyStr) const {
608 // Make a copy of supersedable condition
609 Row emptyRow;
610 Assertion::Operator* onlyIf =
611 new Assertion::Operator((m_sup->getOnlyIf())->getOperator(),
612 &emptyRow);
613 // Make operator for key == oldKey
614 Assertion::Operator* ser =
615 new Assertion::Operator(OPTYPEequal, m_primaryKeyCol,
616 oldKeyStr, FIELDTYPEold, FIELDTYPElit);
617 std::vector<Assertion::Operator*> children;
618 children.push_back(onlyIf);
619 children.push_back(ser);
620 Assertion::Operator* whereOp =
621 new Assertion::Operator(OPTYPEand, children);
622
623 std::vector<std::string> queryCols;
624 queryCols.push_back(m_primaryKeyCol);
625 Assertion* where = new Assertion(whereOp);
626 ResultHandle* results = m_connect->select(m_name, queryCols, queryCols,
627 where);
628 delete where;
629
630 return (results->getNRows() > 0);
631 }
632
633}
const Int_t n
****INTEGER imax DOUBLE PRECISION m_pi *DOUBLE PRECISION m_amfin DOUBLE PRECISION m_Chfin DOUBLE PRECISION m_Xenph DOUBLE PRECISION m_sinw2 DOUBLE PRECISION m_GFermi DOUBLE PRECISION m_MfinMin DOUBLE PRECISION m_ta2 INTEGER m_out INTEGER m_KeyFSR INTEGER m_KeyQCD *COMMON c_Semalib $ !copy of input $ !CMS energy $ !beam mass $ !final mass $ !beam charge $ !final charge $ !smallest final mass $ !Z mass $ !Z width $ !EW mixing angle $ !Gmu Fermi $ alphaQED at q
Definition: KKsem.h:33
**********Class see also m_nmax DOUBLE PRECISION m_amel DOUBLE PRECISION m_x2 DOUBLE PRECISION m_alfinv DOUBLE PRECISION m_Xenph INTEGER m_KeyWtm INTEGER m_idyfs DOUBLE PRECISION m_zini DOUBLE PRECISION m_q2 DOUBLE PRECISION m_Wt_KF DOUBLE PRECISION m_WtCut INTEGER m_KFfin *COMMON c_KarLud $ !Input CMS energy[GeV] $ !CMS energy after beam spread beam strahlung[GeV] $ !Beam energy spread[GeV] $ !z boost due to beam spread $ !electron beam mass *ff pair spectrum $ !minimum v
Definition: KarLud.h:35
std::string getString() const
Return string representation of time, not including nanoseconds;.
Definition: Timestamp.cxx:92
static int expandEnvVar(std::string *toExpand, const std::string &openDel=std::string("$("), const std::string &closeDel=std::string(")"))
static const char * itoa(int val, std::string &outStr)
Function object used to sort columns by column name.
bool nullAllowed() const
Returns true if column may take on value NULL.
bool interpret(const std::string &interpType, std::string &val)
Definition: Column.cxx:41
virtual ResultHandle * select(const std::string &tableName, const StringVector &getCols, const StringVector &orderCols, const Assertion *where=0, int rowLimit=0, int rowOffset=0)=0
virtual unsigned int update(const std::string &tableName, const StringVector &colNames, const StringVector &values, const Assertion *where=0, const StringVector *nullCols=0)=0
virtual std::ostream * getOut() const =0
virtual bool insertRow(const std::string &tableName, const StringVector &colNames, const StringVector &values, int *auto_value=0, const StringVector *nullCols=0)=0
virtual std::ostream * getErrOut() const =0
static void cleanFieldPtrs(std::vector< std::string * > &fields)
Definition: ResultHandle.cxx:7
virtual bool getRowPtrs(std::vector< std::string * > &fields, unsigned int i=0, bool clear=true)=0
virtual unsigned int getNRows() const =0
Return number of rows in results.
FieldVal * find(std::string colname)
Definition: Column.cxx:73
void rowSort()
Definition: Column.cxx:65
void regroup(std::vector< std::string > &colNames, std::vector< std::string > &colVals, std::vector< std::string > &nullCols) const
Reorder information suitable for Connection::insert.
Definition: Column.cxx:98
const std::vector< std::string > & getOldDefaulted() const
Visitor::VisitorState accept(Visitor *v)
Definition: Table.cxx:102
int insertRow(Row &row, int *serial=0) const
Definition: Table.cxx:261
Index * getIndexByName(const std::string &name) const
Definition: Table.cxx:82
int insertLatest(Row &row, int *serial=0) const
Definition: Table.cxx:162
int supersedeRow(Row &row, int oldKey, int *newKey=0) const
Definition: Table.cxx:315
Assertion * getAssertionByName(const std::string &name) const
Definition: Table.cxx:91
int updateRows(Row &row, Assertion *where) const
Definition: Table.cxx:449
void sortColumns()
Definition: Table.cxx:129
Column * getColumnByName(const std::string &name) const
Definition: Table.cxx:56
void setConnection(Connection *connect)
Definition: Table.cxx:49
TFile f("ana_bhabha660a_dqa_mcPat_zy_old.root")