//# TBTableDriver.cc: Driver for interacting with the table on disk. //# Copyright (C) 2007-2008 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id: $ #include <casaqt/QtBrowser/TBTableDriver.h> #include <casaqt/QtBrowser/TBConstants.h> #include <casaqt/QtBrowser/TBField.h> #include <casaqt/QtBrowser/TBKeyword.h> #include <casaqt/QtBrowser/TBArray.h> #include <casaqt/QtBrowser/TBXMLDriver.h> #include <casaqt/QtBrowser/TBParser.h> #include <casaqt/QtBrowser/QProgressPanel.qo.h> #include <casaqt/QtBrowser/TBData.h> #include <tables/TaQL/TableParse.h> #include <tables/Tables/TableRow.h> #include <tables/TaQL/ExprNode.h> #include <tables/Tables/ScalarColumn.h> #include <tables/Tables/ArrayColumn.h> #include <tables/Tables/ArrColDesc.h> #include <tables/Tables/TableColumn.h> #include <casa/Containers/RecordField.h> #include <casa/Arrays/Vector.h> #include <casa/Exceptions/Error.h> #include <sstream> using namespace casacore; namespace casa { /////////////////////////////// // TBTABLEDRIVER DEFINITIONS // /////////////////////////////// // Constructors/Destructors // TBTableDriver::TBTableDriver(TableParams* tp, TBTable* t): location(tp->location), insertRow(tp->insertRow), removeRow(tp->removeRow), data(tp->data), fields(tp->fields), keywords(tp->keywords), subtableRows(tp->subtableRows), totalRows(tp->totalRows), loadedRows(tp->loadedRows), writable(tp->writable), taql(tp->taql), dp(tp->dParams), printdebug(true), table(t) { } TBTableDriver::~TBTableDriver() { } // Accessors/Mutators // void TBTableDriver::setPrintDebug(bool pdb) { printdebug = pdb; } // Protected Methods // /* Result TBTableDriver::query(String type, String query) { String str = "send.table." + type; int l = query.length(); int n = 0; if(l < 100) { str += " "; n = 1; } stringstream ss; ss << str << " " << l << query << " "; // sometimes the last few characters are changed, // so add some spaces at the end so it doesn't matter String s = ss.str(); const char* q = s.c_str(); if(printdebug) TBConstants::dprint(TBConstants::DEBUG_HIGH, q); String xml = TBXMLDriver::dowork(q); Result r(xml); if((type == TBConstants::QUERY_QUERY && xml.find('<') == String::npos) || (type == TBConstants::QUERY_ARRAY && xml.find('[') == String::npos)) // there was an error r.valid = false; return r; } */ ///////////////////////////////////// // TBTABLEDRIVERDIRECT DEFINITIONS // ///////////////////////////////////// // Constructors/Destructors // TBTableDriverDirect::TBTableDriverDirect(TableParams* tp, TBTable* t) : TBTableDriver(tp, t) { if(taql) m_table = Table(tableCommand(location).table( )); else m_table = Table(location); } TBTableDriverDirect::~TBTableDriverDirect() { } // Public Methods // bool TBTableDriverDirect::canRead() { return m_table.hasLock(FileLocker::Read); } bool TBTableDriverDirect::canWrite() { return m_table.hasLock(FileLocker::Write); } bool TBTableDriverDirect::tryWriteLock() { if(!m_table.lock(FileLocker::Write, 1)) return false; try { m_table.reopenRW(); return true; } catch(...) { releaseWriteLock(); return false; } } bool TBTableDriverDirect::releaseWriteLock() { if(!m_table.hasLock(FileLocker::Write)) return true; // nothing to release m_table.unlock(); // release write lock return m_table.lock(FileLocker::Read); // re-acquire read lock } Result TBTableDriverDirect::loadRows(int start, int num, bool full, vector<String>* f, bool parsedata, ProgressHelper* pp) { try { int steps = 1 + fields.size(); if(parsedata && pp != NULL) { int n = taql ? num : totalRowsOf(location); if(num < n) n = num; steps += n / 10; } if(pp != NULL) { pp->reset("Loading rows..."); pp->setSteps(steps); } Table table; // open/reference table appropriately if(f == NULL || f->size() == 0) { table = m_table; } else { Block<String> cols(f->size()); for(unsigned int i = 0; i < f->size(); i++) cols[i] = f->at(i); table = m_table.project(cols); /* if(taql) { TableExprNode cols = m_table.col(f->at(0)); for(unsigned int i = 1; i < f->size(); i++) cols = cols && m_table.col(f->at(i)); table = m_table(cols); } else { stringstream ss; ss << "SELECT "; for(unsigned int i = 0; i < f->size(); i++) { ss << f->at(i); if(i < f->size() - 1) ss << ','; } ss << " FROM " << location; String query = ss.str(); if(printdebug) TBConstants::dprint(TBConstants::DEBUG_HIGH, query); table = tableCommand(query); } */ } if(pp != NULL) pp->step(); totalRows = table.nrow(); if(start < 0) start = 0; int end = start + num; if(num == 0 || end >= totalRows) end = totalRows; if(end <= start) return Result(TBConstants::ERROR_EMPTY, false); // Update table parameters insertRow = !taql && table.canAddRow(); removeRow = !taql && table.canRemoveRow(); unsigned int subtableCount = 0; // Update table keywords TableRecord kws = table.keywordSet(); if(kws.nfields() != keywords.size()) { steps += kws.nfields(); if(pp != NULL) pp->setSteps(steps); // Clear out old keywords for(unsigned int i = 0; i < keywords.size(); i++) delete keywords.at(i); keywords.clear(); if(pp != NULL) pp->step(); vector<TBKeyword*>* v = getKeywords(kws); // Put into keywords for(unsigned int i = 0; i < v->size(); i++) { TBKeyword* kw = v->at(i); if(kw->getType() == TBConstants::TYPE_TABLE) subtableCount++; keywords.push_back(kw); if(pp != NULL) pp->step(); } delete v; } // Update table fields ROTableRow row(table); Vector<String> colNames = row.columnNames(); TableDesc tdesc = table.tableDesc(); void** fieldPtrs = (void**) new unsigned int*[colNames.nelements()]; bool updateFields = colNames.nelements() != fields.size(); if(updateFields) { steps -= fields.size(); steps += 2 * colNames.nelements(); if(pp != NULL) pp->setSteps(steps); // Clear out old fields for(unsigned int i = 0; i < fields.size(); i++) delete fields.at(i); fields.clear(); } for(unsigned int i = 0; i < colNames.nelements(); i++) { ColumnDesc cdesc = tdesc.columnDesc(i); DataType t = row.record().type(row.record().fieldNumber(colNames(i))); String type = TBConstants::typeName(t); bool valid = true; if(t == TpString) fieldPtrs[i] = new RORecordFieldPtr<String>(row.record(), colNames(i)); else if(t == TpInt) fieldPtrs[i] = new RORecordFieldPtr<Int>(row.record(), colNames(i)); else if(t == TpFloat) fieldPtrs[i] = new RORecordFieldPtr<Float>(row.record(), colNames(i)); else if(t == TpDouble) fieldPtrs[i] = new RORecordFieldPtr<Double>(row.record(), colNames(i)); else if(t == TpBool) fieldPtrs[i] = new RORecordFieldPtr<Bool>(row.record(), colNames(i)); else if(t == TpUChar) fieldPtrs[i] = new RORecordFieldPtr<uChar>(row.record(), colNames(i)); else if(t == TpShort) fieldPtrs[i] = new RORecordFieldPtr<Short>(row.record(), colNames(i)); else if(t == TpUInt) fieldPtrs[i] = new RORecordFieldPtr<uInt>(row.record(), colNames(i)); else if(t == TpComplex) fieldPtrs[i] = new RORecordFieldPtr<Complex>(row.record(), colNames(i)); else if(t == TpDComplex) fieldPtrs[i] = new RORecordFieldPtr<DComplex>(row.record(), colNames(i)); else if(t == TpArrayDouble) fieldPtrs[i] = new RORecordFieldPtr<Array<Double> >(row.record(), colNames(i)); else if(t == TpArrayBool) fieldPtrs[i] = new RORecordFieldPtr<Array<Bool> >(row.record(), colNames(i)); else if(t == TpArrayUChar) fieldPtrs[i] = new RORecordFieldPtr<Array<uChar> >(row.record(), colNames(i)); else if(t == TpArrayShort) fieldPtrs[i] = new RORecordFieldPtr<Array<Short> >(row.record(), colNames(i)); else if(t == TpArrayInt) fieldPtrs[i] = new RORecordFieldPtr<Array<Int> >(row.record(), colNames(i)); else if(t == TpArrayUInt) fieldPtrs[i] = new RORecordFieldPtr<Array<uInt> >(row.record(), colNames(i)); else if(t == TpArrayFloat) fieldPtrs[i] = new RORecordFieldPtr<Array<Float> >(row.record(), colNames(i)); else if(t == TpArrayComplex) fieldPtrs[i] = new RORecordFieldPtr<Array<Complex> >(row.record(), colNames(i)); else if(t == TpArrayDComplex) fieldPtrs[i] = new RORecordFieldPtr<Array<DComplex> >(row.record(), colNames(i)); else if(t == TpArrayString) fieldPtrs[i] = new RORecordFieldPtr<Array<String> >(row.record(), colNames(i)); else {valid = false; } if(updateFields && t == TpDouble) { // Check if it's a date. String comment = cdesc.comment(); // Wouldn't it be better to look // for an epoch ref? if(TBConstants::equalsIgnoreCase(comment, TBConstants::COMMENT_DATE) || TBConstants::equalsIgnoreCase(comment, TBConstants::COMMENT_TIMP) || TBConstants::equalsIgnoreCase(comment, TBConstants::COMMENT_TIMP2)){ type = TBConstants::TYPE_DATE; } } if(pp != NULL) pp->step(); if(updateFields && !valid && printdebug) TBConstants::dprint(TBConstants::DEBUG_HIGH,"Invalid field type."); if(updateFields) { TableRecord tr = cdesc.keywordSet(); vector<TBKeyword*>* v = getKeywords(tr); String name = colNames[i]; TBField* field = new TBField(name, type); // Add keywords to field for(unsigned int i = 0; i < v->size(); i++) field->addKeyword(v->at(i)); delete v; fields.push_back(field); if(pp != NULL) pp->step(); } } // Update writable vector writable.clear(); writable.resize(fields.size(), false); try { table.reopenRW(); for(unsigned int i = 0; i < fields.size(); i++) { writable[i] = table.isColumnWritable(fields[i]->getName()); } } catch(...) { } // Update subtable rows if(subtableCount != subtableRows.size()) { steps += subtableCount; if(pp != NULL) pp->setSteps(steps); subtableRows.clear(); subtableRows.resize(subtableCount); for(unsigned int i = 0; i < subtableRows.size(); i++) subtableRows[i] = -1; int j = -1; for(unsigned int i = 0; i < keywords.size(); i++) { TBKeyword* kw = keywords.at(i); if(kw->getType() == TBConstants::TYPE_TABLE) { j++; int r = totalRowsOf(kw->getValue()->asString()); subtableRows[j] = r; if(pp != NULL) pp->step(); } } } // Update data loadedRows = 0; for(unsigned int i = 0; i < data.size(); i++) { vector<TBData*>* dr = data.at(i); for(unsigned int j = 0; j < data.at(i)->size(); j++) { delete dr->at(j); } delete dr; } data.clear(); if(parsedata) { for(int i = start; i < end; i++) { row.get(i); vector<TBData*>* r2 = new vector<TBData*>(); for(unsigned int j = 0; j < colNames.nelements(); j++) { DataType t = row.record().type(j); TBData* val = NULL; if(t == TpString) { val = new TBDataString(**((RORecordFieldPtr<String>*) fieldPtrs[j])); } else if(t == TpFloat) { val = new TBDataFloat(**((RORecordFieldPtr<Float>*) fieldPtrs[j])); } else if(t == TpInt) { val = new TBDataInt(**((RORecordFieldPtr<Int>*) fieldPtrs[j])); } else if(t == TpDouble) { String comment = tdesc.columnDesc(j).comment(); double v = **((RORecordFieldPtr<Double>*)fieldPtrs[j]); if(TBConstants::equalsIgnoreCase(comment, TBConstants::COMMENT_DATE) || TBConstants::equalsIgnoreCase(comment, TBConstants::COMMENT_TIMP) || TBConstants::equalsIgnoreCase(comment, TBConstants::COMMENT_TIMP2)) { val = new TBDataDate(v); } else { val = new TBDataDouble(v); } } else if(t == TpBool) { val = new TBDataBool(**((RORecordFieldPtr<Bool>*) fieldPtrs[j])); } else if(t == TpChar) { val = new TBDataChar(**((RORecordFieldPtr<Char>*) fieldPtrs[j])); } else if(t == TpUChar) { val = new TBDataUChar(**((RORecordFieldPtr<uChar>*) fieldPtrs[j])); } else if(t == TpShort) { val = new TBDataShort(**((RORecordFieldPtr<Short>*) fieldPtrs[j])); } else if(t == TpUInt) { val = new TBDataUInt(**((RORecordFieldPtr<uInt>*) fieldPtrs[j])); } else if(t == TpComplex) { val = new TBDataComplex(**((RORecordFieldPtr<Complex>*) fieldPtrs[j])); } else if(t == TpDComplex) { val = new TBDataDComplex(**((RORecordFieldPtr<DComplex>*) fieldPtrs[j])); } else if(t == TpArrayDouble) { val = new TBArrayDataDouble( **((RORecordFieldPtr<Array<Double> >*) fieldPtrs[j]), full); } else if(t == TpArrayBool) { val = new TBArrayDataBool( **((RORecordFieldPtr<Array<Bool> >*) fieldPtrs[j]), full); } else if(t == TpArrayUChar) { val = new TBArrayDataUChar( **((RORecordFieldPtr<Array<uChar> >*) fieldPtrs[j]), full); } else if(t == TpArrayChar) { val = new TBArrayDataChar( **((RORecordFieldPtr<Array<Char> >*) fieldPtrs[j])); } else if(t == TpArrayShort) { val = new TBArrayDataShort( **((RORecordFieldPtr<Array<Short> >*) fieldPtrs[j]), full); } else if(t == TpArrayInt) { val = new TBArrayDataInt( **((RORecordFieldPtr<Array<Int> >*) fieldPtrs[j]), full); } else if(t == TpArrayUInt) { val = new TBArrayDataUInt( **((RORecordFieldPtr<Array<uInt> >*) fieldPtrs[j]), full); } else if(t == TpArrayFloat) { val = new TBArrayDataFloat( **((RORecordFieldPtr<Array<Float> >*) fieldPtrs[j]), full); } else if(t == TpArrayComplex) { val = new TBArrayDataComplex( **((RORecordFieldPtr<Array<Complex> >*) fieldPtrs[j]), full); } else if(t == TpArrayDComplex) { val = new TBArrayDataDComplex( **((RORecordFieldPtr<Array<DComplex> >*) fieldPtrs[j]), full); } else if(t == TpArrayString) { val = new TBArrayDataString( **((RORecordFieldPtr<Array<String> >*) fieldPtrs[j]), full); } r2->push_back(val); } data.push_back(r2); loadedRows++; if(pp != NULL && ((i - start) % 10) == 0) pp->step(); } } delete [] fieldPtrs; if(pp != NULL) pp->done(); return Result("", true); } catch(const AipsError& x) { return Result(x.getMesg(), false); } catch(...) { return Result("Unknown error occured during load!", false); } } void TBTableDriverDirect::loadArray(TBArrayData* d, unsigned int r, unsigned int c) { //checkTaqlTable(); Table table = m_table; ROTableRow row(table); row.get(r); DataType t = row.record().type(c); if(t == TpArrayDouble) { RORecordFieldPtr<Array<Double> > p(row.record(), c); ((TBArrayDataDouble*)d)->load(*p); } else if(t == TpArrayBool) { RORecordFieldPtr<Array<Bool> > p(row.record(), c); ((TBArrayDataBool*)d)->load(*p); } else if(t == TpArrayChar) { RORecordFieldPtr<Array<Char> > p(row.record(), c); ((TBArrayDataChar*)d)->load(*p); } else if(t == TpArrayUChar) { RORecordFieldPtr<Array<uChar> > p(row.record(), c); ((TBArrayDataUChar*)d)->load(*p); } else if(t == TpArrayShort) { RORecordFieldPtr<Array<Short> > p(row.record(), c); ((TBArrayDataShort*)d)->load(*p); } else if(t == TpArrayInt) { RORecordFieldPtr<Array<Int> > p(row.record(), c); ((TBArrayDataInt*)d)->load(*p); } else if(t == TpArrayUInt) { RORecordFieldPtr<Array<uInt> > p(row.record(), c); ((TBArrayDataUInt*)d)->load(*p); } else if(t == TpArrayFloat) { RORecordFieldPtr<Array<Float> > p(row.record(), c); ((TBArrayDataFloat*)d)->load(*p); } else if(t == TpArrayComplex) { RORecordFieldPtr<Array<Complex> > p(row.record(), c); ((TBArrayDataComplex*)d)->load(*p); } else if(t == TpArrayDComplex) { RORecordFieldPtr<Array<DComplex> > p(row.record(), c); ((TBArrayDataDComplex*)d)->load(*p); } else if(t == TpArrayString) { RORecordFieldPtr<Array<String> > p(row.record(), c); ((TBArrayDataString*)d)->load(*p); } } vector<int> TBTableDriverDirect::dimensionsOf(unsigned int col) { vector<int> d; if(col >= fields.size()) return d; String type = fields.at(col)->getType(); if(!TBConstants::typeIsArray(type)) return d; Table table = m_table; ColumnDesc acd = table.tableDesc().columnDesc(col); IPosition shape = acd.shape(); // If the shape is variable, take a guess by loading the first row if(shape.size() == 0) { ROTableRow row(table); row.get(0); if(type == TBConstants::TYPE_ARRAY_DOUBLE) { RORecordFieldPtr<Array<Double> > p(row.record(), col); shape = (*p).shape(); } else if(type == TBConstants::TYPE_ARRAY_BOOL) { RORecordFieldPtr<Array<Bool> > p(row.record(), col); shape = (*p).shape(); } else if(type == TBConstants::TYPE_ARRAY_UCHAR) { RORecordFieldPtr<Array<uChar> > p(row.record(), col); shape = (*p).shape(); } else if(type == TBConstants::TYPE_ARRAY_SHORT) { RORecordFieldPtr<Array<Short> > p(row.record(), col); shape = (*p).shape(); } else if(type == TBConstants::TYPE_ARRAY_INT) { RORecordFieldPtr<Array<Int> > p(row.record(), col); shape = (*p).shape(); } else if(type == TBConstants::TYPE_ARRAY_UINT) { RORecordFieldPtr<Array<uInt> > p(row.record(), col); shape = (*p).shape(); } else if(type == TBConstants::TYPE_ARRAY_FLOAT) { RORecordFieldPtr<Array<Float> > p(row.record(), col); shape = (*p).shape(); } else if(type == TBConstants::TYPE_ARRAY_COMPLEX) { RORecordFieldPtr<Array<Complex> > p(row.record(), col); shape = (*p).shape(); } else if(type == TBConstants::TYPE_ARRAY_DCOMPLEX) { RORecordFieldPtr<Array<DComplex> > p(row.record(), col); shape = (*p).shape(); } else if(type == TBConstants::TYPE_ARRAY_STRING) { RORecordFieldPtr<Array<String> > p(row.record(), col); shape = (*p).shape(); } } for(unsigned int i = 0; i < shape.size(); i++) d.push_back(shape(i)); return d; } Result TBTableDriverDirect::editData(unsigned int row, unsigned int col, TBData* newVal, vector<int>* d) { if(taql) return Result("Cannot edit TaQL tables.", false); Table table = m_table; table.reopenRW(); TableColumn column(table, col); String fName = fields.at(col)->getName(); String type = newVal->getType(); bool a = d != NULL && d->size() > 0; IPosition* pos = NULL; if(a) { pos = new IPosition(d->size()); for(unsigned int i = 0; i < d->size(); i++) (*pos)[i] = d->at(i); } if(type == TBConstants::TYPE_STRING || type == TBConstants::TYPE_TABLE) { if(!a) column.putScalar(row, newVal->asString()); else { ArrayColumn<String> arrayCol(table, fName); Array<String> array = arrayCol(row); array(*pos) = newVal->asString(); arrayCol.put(row, array); } } else if(type == TBConstants::TYPE_FLOAT) { if(!a) column.putScalar(row, newVal->asFloat()); else { ArrayColumn<Float> arrayCol(table, fName); Array<Float> array = arrayCol(row); array(*pos) = newVal->asFloat(); arrayCol.put(row, array); } } else if(type == TBConstants::TYPE_DOUBLE || type == TBConstants::TYPE_DATE) { if(!a) column.putScalar(row, newVal->asDouble()); else { ArrayColumn<Double> arrayCol(table, fName); Array<Double> array = arrayCol(row); array(*pos) = newVal->asDouble(); arrayCol.put(row, array); } } else if(type == TBConstants::TYPE_INT) { if(!a) column.putScalar(row, newVal->asInt()); else { ArrayColumn<Int> arrayCol(table, fName); Array<Int> array = arrayCol(row); array(*pos) = newVal->asInt(); arrayCol.put(row, array); } } else if(type == TBConstants::TYPE_UINT) { if(!a) column.putScalar(row, newVal->asUInt()); else { ArrayColumn<uInt> arrayCol(table, fName); Array<uInt> array = arrayCol(row); array(*pos) = newVal->asUInt(); arrayCol.put(row, array); } } else if(type == TBConstants::TYPE_BOOL) { if(!a) column.putScalar(row, newVal->asBool()); else { ArrayColumn<Bool> arrayCol(table, fName); Array<Bool> array = arrayCol(row); array(*pos) = newVal->asBool(); arrayCol.put(row, array); } } else if(type == TBConstants::TYPE_UCHAR) { if(!a) column.putScalar(row, newVal->asUChar()); else { ArrayColumn<uChar> arrayCol(table, fName); Array<uChar> array = arrayCol(row); array(*pos) = newVal->asUChar(); arrayCol.put(row, array); } } else if(type == TBConstants::TYPE_CHAR) { if(!a) column.putScalar(row, newVal->asChar()); else return Result("Char ArrayColumn not supported by CASA.", false); } else if(type == TBConstants::TYPE_SHORT) { if(!a) column.putScalar(row, newVal->asShort()); else { ArrayColumn<Short> arrayCol(table, fName); Array<Short> array = arrayCol(row); array(*pos) = newVal->asShort(); arrayCol.put(row, array); } } else if(type == TBConstants::TYPE_COMPLEX) { pair<float, float> c = newVal->asComplex(); if(!a) column.putScalar(row, Complex(c.first, c.second)); else { ArrayColumn<Complex> arrayCol(table, fName); Array<Complex> array = arrayCol(row); array(*pos) = Complex(c.first, c.second); arrayCol.put(row, array); } } else if(type == TBConstants::TYPE_DCOMPLEX) { pair<double, double> c = newVal->asDComplex(); if(!a) column.putScalar(row, DComplex(c.first, c.second)); else { ArrayColumn<DComplex> arrayCol(table, fName); Array<DComplex> array = arrayCol(row); array(*pos) = DComplex(c.first, c.second); arrayCol.put(row, array); } } else return Result("Type not supported.", false); if(!a) { row %= data.size(); data.at(row)->at(col)->setValue(*newVal); } if(pos != NULL) delete pos; return Result("", true); } int TBTableDriverDirect::totalRowsOf(String location) { if(location == m_table.tableName()) return m_table.nrow(); else return Table(location).nrow(); } Result TBTableDriverDirect::insertRows(int n) { if(taql) return Result("Cannot edit TaQL tables.", false); try { Table table = m_table; if(!table.canAddRow()) return Result("Table does not support insertion of rows.", false); table.reopenRW(); table.addRow(n, true); return Result("", true); } catch(const AipsError& er) { return Result(er.getMesg(), false); } catch(...) { return Result("Unknown exception.", false); } } Result TBTableDriverDirect::deleteRows(vector<int> r) { if(taql) return Result("Cannot edit TaQL tables.", false); try { Table table = m_table; if(!table.canRemoveRow()) return Result("Table does not support deletion of rows.", false); table.reopenRW(); for(unsigned int i = 0; i < r.size(); i++) { table.removeRow(r.at(i)); } // update totalRows totalRows = table.nrow(); return Result("", true); } catch(const AipsError& er) { return Result(er.getMesg(), false); } catch(...) { return Result("Unknown exception.", false); } } vector<TBKeyword*>* TBTableDriverDirect::getKeywords(RecordInterface& kws) { vector<TBKeyword*>* v = new vector<TBKeyword*>(); for(unsigned int i = 0; i < kws.nfields(); i++) { RecordFieldId rfid(i); DataType t = kws.type(i); String type = TBConstants::typeName(t); String name = kws.name(rfid); bool valid = true; TBData* d = NULL; if(t == TpString) d = new TBDataString(kws.asString(rfid)); else if(t == TpFloat) d = new TBDataFloat(kws.asFloat(rfid)); else if(t == TpDouble) d = new TBDataDouble(kws.asDouble(rfid)); else if(t == TpInt) d = new TBDataInt(kws.asInt(rfid)); else if(t == TpUInt) d = new TBDataUInt(kws.asuInt(rfid)); else if(t == TpBool) d = new TBDataBool(kws.asBool(rfid)); else if(t == TpChar) d = new TBDataChar(kws.asuChar(rfid)); else if(t == TpUChar) d = new TBDataUChar(kws.asuChar(rfid)); else if(t == TpShort) d = new TBDataShort(kws.asShort(rfid)); else if(t == TpComplex) d = new TBDataComplex(kws.asComplex(rfid)); else if(t == TpDComplex) d = new TBDataDComplex(kws.asDComplex(rfid)); else if(t == TpTable) { TableRecord* tr = static_cast<TableRecord*>(&kws); if(tr != NULL){ d = new TBDataTable(tr->asTable(rfid).tableName()); }else{ valid = false; } } else if(t == TpRecord){ try { d = new TBDataRecord(kws.asRecord(rfid)); } catch (...) { } } else if(t == TpArrayBool) { Array<Bool> arr = kws.asArrayBool(rfid); d = new TBArrayDataBool(arr); ((TBArrayDataBool*)d)->load(arr); } else if(t == TpArrayFloat) { Array<Float> arr = kws.asArrayFloat(rfid); d = new TBArrayDataFloat(arr); ((TBArrayDataFloat*)d)->load(arr); } else if(t == TpArrayDouble) { Array<Double> arr = kws.asArrayDouble(rfid); d = new TBArrayDataDouble(arr); ((TBArrayDataDouble*)d)->load(arr); } else if(t == TpArrayUChar) { Array<uChar> arr = kws.asArrayuChar(rfid); d = new TBArrayDataUChar(arr); ((TBArrayDataUChar*)d)->load(arr); } else if(t == TpArrayShort) { Array<Short> arr = kws.asArrayShort(rfid); d = new TBArrayDataShort(arr); ((TBArrayDataShort*)d)->load(arr); } else if(t == TpArrayInt) { Array<Int> arr = kws.asArrayInt(rfid); d = new TBArrayDataInt(arr); ((TBArrayDataInt*)d)->load(arr); } else if(t == TpArrayUInt) { Array<uInt> arr = kws.asArrayuInt(rfid); d = new TBArrayDataUInt(arr); ((TBArrayDataUInt*)d)->load(arr); } else if(t == TpArrayComplex) { Array<Complex> arr = kws.asArrayComplex(rfid); d = new TBArrayDataComplex(arr); ((TBArrayDataComplex*)d)->load(arr); } else if(t == TpArrayDComplex) { Array<DComplex> arr = kws.asArrayDComplex(rfid); d = new TBArrayDataDComplex(arr); ((TBArrayDataDComplex*)d)->load(arr); } else if(t == TpArrayString) { Array<String> arr = kws.asArrayString(rfid); d = new TBArrayDataString(arr); ((TBArrayDataString*)d)->load(arr); } else { valid = false; } if(!valid) TBConstants::dprint(TBConstants::DEBUG_HIGH, "Keyword type not supported."); if(valid && d != NULL) { TBKeyword* keyword = new TBKeyword(name, *d); delete d; v->push_back(keyword); } } return v; } /* ////////////////////////////////// // TBTABLEDRIVERXML DEFINITIONS // ////////////////////////////////// // Constructors/Destructors // TBTableDriverXML::TBTableDriverXML(TableParams* tp, TBTable* t) : TBTableDriver(tp, t) { if(tp->dParams->parser == HOME) parser = new TBHomeParser(tp); else if(tp->dParams->parser == XERCES_DOM) parser =new TBXercesDOMParser(tp); else if(tp->dParams->parser == XERCES_SAX) parser = new TBXercesSAXParser(tp); else throw "Unsupported Parser Class."; } TBTableDriverXML::~TBTableDriverXML() { delete parser; } // Public Methods // Result TBTableDriverXML::loadRows(int start, int num, bool full, vector<String>* f, bool parsedata, ProgressHelper* pp) { int steps = 3; if(pp != NULL) { pp->reset("Loading rows..."); pp->setSteps(steps); } stringstream ss; ss << "SELECT"; if(f != NULL && f->size() > 0) { for(unsigned int i = 0; i < f->size(); i++) { ss << " " << f->at(i); if(i < f->size() - 1) ss << ','; } } ss << " FROM " << location << " <START = " << start; ss << " number = " << num << " >"; String q = full ? TBConstants::QUERY_FULL : TBConstants::QUERY_QUERY; Result r = query(q, ss.str()); if(pp != NULL) pp->step(); if(r.valid) { String xml = r.result; if(printdebug) { TBConstants::dprint(TBConstants::DEBUG_MED, "DataDriver returned XML string."); TBConstants::dprint(TBConstants::DEBUG_LOW, xml); } insertRow = false; removeRow = false; for(unsigned int i = 0; i < fields.size(); i++) delete fields.at(i); fields.clear(); for(unsigned int i = 0; i < keywords.size(); i++) delete keywords.at(i); keywords.clear(); for(unsigned int i = 0; i < data.size(); i++) { vector<TBData*>* dr = data.at(i); for(unsigned int j = 0; j < dr->size(); j++) delete dr->at(j); delete dr; } data.clear(); totalRows = 0; loadedRows = 0; bool ready; if(pp != NULL) pp->step(); Result r = parser->parse(&xml, parsedata); if(pp != NULL) pp->step(); ready = r.valid; if(!r.valid) return r; // Update subtableRows int subtableCount = 0; steps += keywords.size(); if(pp != NULL) pp->setSteps(steps); for(unsigned int i = 0; i < keywords.size(); i++) { String type = keywords.at(i)->getType(); if(TBConstants::typeIsTable(type)) subtableCount++; if(pp != NULL) pp->step(); } if(parsedata && subtableCount != (int)subtableRows.size()) { steps += subtableCount; if(pp != NULL) pp->setSteps(steps); subtableRows.clear(); subtableRows.resize(subtableCount); for(unsigned int i = 0; i < subtableRows.size(); i++) subtableRows[i] = -1; int j = -1; for(unsigned int i = 0; i < keywords.size(); i++) { TBKeyword* kw = keywords.at(i); if(kw->getType() == TBConstants::TYPE_TABLE) { j++; int r = totalRowsOf(kw->getValue()->asString()); subtableRows[j] = r; if(pp != NULL) pp->step(); } } } if(parsedata) { // parse data into data vector<vector<String>*>* data = parser->getData(); data.resize(data->size()); for(unsigned int i = 0; i < data->size(); i++) { vector<TBData*>* v = new vector<TBData*>(fields.size()); for(unsigned int j = 0; j < fields.size(); j++) { String d = data->at(i)->at(j); TBData* td = TBData::create(d, fields.at(j)->getType()); (*v)[j] = td; } data[i] = v; } } return Result("", true); } else { return r; } } void TBTableDriverXML::loadArray(TBArrayData* d, unsigned int row, unsigned int col) { } vector<int> TBTableDriverXML::dimensionsOf(unsigned int col) { vector<int> d; String type = fields.at(col)->getType(); if(TBConstants::typeIsArray(type)) { if(data.size() > 0) { TBArrayData* sd = (TBArrayData*)data.at(0)->at(col); return sd->getShape(); } else { TBTable t(location, dp); vector<String> c; c.push_back(fields.at(col)->getName()); Result r = t.loadRows(0, 1, true, &c); if(r.valid && t.getLoadedRows() == 1 && t.getNumFields() == 1) { TBArrayData* sd = (TBArrayData*)t.dataAt(0, 0); if(sd != NULL) return sd->getShape(); } } } return d; } Result TBTableDriverXML::editData(unsigned int row, unsigned int col, TBData* newVal, vector<int>* d) { stringstream ss; ss << "<QUERY> SELECT FROM " << location << " </QUERY>\n<COMMAND>\n"; if(d == NULL || d->size() == 0) { ss << "<UPDATE row = " << row << " col = " << col << " val = \""; ss << newVal->asString() << "\" >"; } else { ss << "<ARRAYUPDATE row = " << row << " col = " << col << " >\n"; ss << "<ARRAYCELLUPDATE coordinates = [ "; for(unsigned int i = 0; i < d->size(); i++) ss << d->at(i) << ' '; ss << "] val = " << newVal->asString() << " >\n</ARRAYUPDATE>"; } ss << "\n</COMMAND>"; Result r = query(TBConstants::QUERY_UPDATE, ss.str()); if(r.valid && (d == NULL || d->size() == 0)) { // Update internal data representation int r = row; if(r >= (int)data.size()) r -= table->getRowIndex(); if(d == NULL || d->size() == 0) { TBData* dat = TBData::create(*newVal); (*data.at(r))[col]->setValue(*dat); delete dat; } } return r; } int TBTableDriverXML::totalRowsOf(String location) { try { TBTable t(location, new DriverParams(dp), false); t.setPrintDebug(false); Result r = t.loadRows(0, 1, false, NULL, false); int tr = 0; if(r.valid) tr = t.getTotalRows(); return tr; } catch(const char* s) { TBConstants::dprint(TBConstants::DEBUG_HIGH, "Table " + location + " threw: " + s); return 0; } catch(...) { TBConstants::dprint(TBConstants::DEBUG_HIGH, "Unknown exception thrown."); return 0; } } void TBTableDriverXML::setPrintDebug(bool pdb) { printdebug = pdb; parser->setPrintDebug(pdb); } Result TBTableDriverXML::insertRows(int n) { stringstream ss; ss << "<QUERY> SELECT FROM " << location << " </QUERY>\n<COMMAND>\n"; for(int i = 0; i < n; i++) ss << "<ADDROW>"; ss << "\n</COMMAND>"; return query(TBConstants::QUERY_UPDATE, ss.str()); } Result TBTableDriverXML::deleteRows(vector<int> r) { stringstream ss; ss << "<QUERY> SELECT FROM " << location << " </QUERY>\n<COMMAND>\n"; for(unsigned int i = 0; i < r.size(); i++) { ss << "<DELROW " << r.at(i) << " >"; } ss << "\n</COMMAND>"; Result res = query(TBConstants::QUERY_UPDATE, ss.str()); if(res.valid) { totalRows = totalRowsOf(location); } return res; } */ }