IODA Bundle
MetaData.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 1996-2012 ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation nor
8  * does it submit to any jurisdiction.
9  */
10 
11 #include "odc/core/MetaData.h"
12 
13 #include <algorithm>
14 
15 using namespace eckit;
16 using namespace odc::api;
17 
18 namespace odc {
19 namespace core {
20 
21 //----------------------------------------------------------------------------------------------------------------------
22 
23 MetaData::MetaData() : std::vector<Column*>(), rowsNumber_(0) {}
24 MetaData::MetaData(int i) : std::vector<Column*>(i), rowsNumber_(0) {}
25 MetaData::MetaData(int i, Column *p) : std::vector<Column*>(i, p), rowsNumber_(0) {}
26 
27 // SDS: n.b. this is changed from before. We
29  std::vector<Column*>(0),
30  rowsNumber_(md.rowsNumber_),
31  dataSize_(md.dataSize_) {
32  *this += md;
33 }
34 
35 ColumnType MetaData::convertType(const std::string& t)
36 {
37  std::string type(t);
38  std::transform(type.begin(), type.end(), type.begin(), ::toupper);
39 
40  if (type == "INTEGER") return INTEGER;
41  else if (type == "YYYYMMDD") return INTEGER;
42  else if (type == "HHMMSS") return INTEGER;
43  else if (type == "PK1INT") return INTEGER;
44  else if (type == "PK9INT") return INTEGER;
45  else if (type == "@LINK") return INTEGER;
46  else if (type == "REAL") return REAL;
47  else if (type == "FLOAT") return REAL;
48  else if (type == "DOUBLE") return DOUBLE;
49  else if (type == "PK9REAL") return DOUBLE;
50  else if (type == "STRING") return STRING;
51  else if (type.find("BITFIELD") != std::string::npos) return BITFIELD;
52  else throw eckit::UserError("Unsupported column type: " + type);
53 
54  return IGNORE; // never reached
55 }
56 
58  MetaData* md = new MetaData(*this);
59  for (size_t i = 0; i < size(); ++i)
60  (*md)[i]->coder((*this)[i]->coder().clone());
61  return md;
62 }
63 
64 void MetaData::setSize(size_t n)
65 {
66  size_t oldSize = size();
67 
68  for (size_t i = n; i < oldSize; ++i)
69  delete at(i);
70 
71  std::vector<Column*>::resize(n, 0);
72 
73  for (size_t i = oldSize; i < n; ++i)
74  at(i) = new Column(*this);
75 }
76 
78 {
79  for (size_type i = 0; i < size(); i++)
80  delete at(i);
81 }
82 
83 //const
84 Column* MetaData::columnByName(const std::string& name) const
85 { return at(columnIndex(name)); }
86 
87 bool MetaData::hasColumn(const std::string& name) const
88 {
89  for (size_t i = 0; i < size(); i++)
90  if (at(i)->name() == name || at(i)->name().find(name + "@") == 0)
91  return true;
92  return false;
93 }
94 
95 size_t MetaData::columnIndex(const std::string& name) const
96 {
97  std::vector<size_t> indices;
98 
99  for (size_t i = 0; i < size(); i++)
100  if (at(i)->name() == name || at(i)->name().find(name + "@") == 0)
101  indices.push_back(i);
102 
103  if (indices.size() > 1)
104  throw eckit::UserError(std::string("Ambiguous column name: '") + name + "'");
105 
106  if (indices.size() == 0)
107  throw eckit::UserError(std::string("Column '") + name + "' not found.");
108 
109  return indices[0];
110 }
111 
113 {
114  if(this == &other)
115  return *this;
116 
117  if (size() != other.size())
118  {
119  for (size_type i=0; i < size(); i++)
120  delete (*this)[i];
121  clear();
122 
123  typedef Column* PColumn;
124  resize(other.size(), PColumn(0));
125 
126  for (size_type i=0; i < size(); i++)
127  (*this)[i] = new Column(*this);
128  }
129 
130  for (size_type i=0; i < size(); i++)
131  *(*this)[i] = *other[i];
132 
133  return *this;
134 }
135 
137 {
138  for (size_t i = 0; i < rhs.size(); ++i)
139  {
140  Column& rhsColumn = *rhs[i];
141 
142  //Log::debug() << "MetaData::operator+=: adding " << rhsColumn << std::endl;
143 
144  Column* c = new Column(rhsColumn);
145  ASSERT(c);
146  push_back(c);
147  }
148  return *this;
149 }
150 
151 void MetaData::operator|=(const MetaData& other)
152 {
153  ASSERT(size() == other.size());
154  for (size_t i = 0; i < size(); ++i)
155  {
156  ASSERT((*this)[i]->name() == other[i]->name());
157  ASSERT((*this)[i]->type() == other[i]->type());
158 
159  (*this)[i]->coder().gatherStats(other[i]->max());
160  (*this)[i]->coder().gatherStats(other[i]->min());
161  }
162 }
163 
165 {
166  MetaData r = *this;
167  r += rhs;
168  return r;
169 }
170 
171 bool MetaData::equalsIncludingConstants(const MetaData& other, const std::vector<std::string>& constColumns) const
172 {
173  std::ostream& L = Log::debug();
174  for (size_t i = 0; i < constColumns.size(); ++i)
175  {
176  const std::string& columnName = constColumns[i];
177  L << "MetaData::equalsIncludingConstants: check " << columnName << std::endl;
178 
179  if ( !hasColumn(columnName) && !other.hasColumn(columnName))
180  continue;
181 
182  Column& c1 = *(columnByName(columnName));
183  Column& c2 = *(other.columnByName(columnName));
184 
185  if ( ! c1.isConstant() || ! c2.isConstant())
186  {
187  L << "MetaData::equalsIncludingConstants: c1 " << c1 << " " << c1.coder() << std::endl;
188  L << "MetaData::equalsIncludingConstants: c2 " << c2 << " " << c2.coder() << std::endl;
189  L << "MetaData::equalsIncludingConstants: column '" << columnName << "'" << std::endl;
190  return false;
191  }
192  else
193  {
194  Codec& codec1 = c1.coder();
195  Codec& codec2 = c2.coder();
196  if ( codec1.min() != codec2.min() )
197  {
198  L << "MetaData::equalsIncludingConstants: column '" << columnName << "'" << std::endl;
199  L << "MetaData::equalsIncludingConstants: min1=" << codec1.min() << ", max1=" << codec1.max() << std::endl;
200  L << "MetaData::equalsIncludingConstants: min2=" << codec2.min() << ", max2=" << codec2.max() << std::endl;
201  L << "MetaData::equalsIncludingConstants: c1.coder: " << codec1 << std::endl;
202  L << "MetaData::equalsIncludingConstants: c2.coder: " << codec2 << std::endl;
203  return false;
204  }
205  }
206  }
207 
208  L << "MetaData::equalsIncludingConstants: yes" << std::endl;
209  return true;
210 }
211 
212 bool MetaData::operator==(const MetaData& other) const {
213  return equals(other);
214 }
215 
216 bool MetaData::equals(const MetaData& other, bool compareDataSizes) const
217 {
218  if (size() != other.size()) {
219  return false;
220  }
221 
222  for (size_t i = 0; i < size(); ++i) {
223  if (!at(i)->equals(*other[i], compareDataSizes)) {
224  return false;
225  }
226  }
227 
228  return true;
229 }
230 
231 bool MetaData::compatible(const MetaData& other) const {
232 
233  // Normal case will be equality --> try O[N] check first.
234 
235  if (size() != other.size()) return false;
236 
237  bool equal = true;
238  for (size_t i = 0; i < size(); ++i) {
239  if (*(*this)[i] != *other[i]) {
240  equal = false;
241  break;
242  }
243  }
244 
245  if (equal) return true;
246 
247  // Build a lookup so not O[N^2] to do match
248 
249  std::map<std::string, Column*> columnLookup;
250  for (Column* col : *this) {
251  columnLookup.emplace(col->name(), col);
252  }
253 
254  for (Column* col : other) {
255  auto it = columnLookup.find(col->name());
256  if (it == columnLookup.end()) return false;
257  if (*it->second != *col) return false;
258  }
259 
260  return true;
261 }
262 
264 {
265  //Log::debug() << "MetaData::resetStats" << std::endl;
266  for (size_t i = 0; i < size(); i++) {
267  (*this)[i]->resetStats();
268  }
269  rowsNumber_ = 0;
270 }
271 
272 void MetaData::print(std::ostream& s) const
273 {
274  for (size_t i = 0; i < size(); i++) {
275  s << i << ". " << *at(i) << std::endl;
276  }
277 }
278 
279 MetaData& MetaData::addColumn(const std::string& name, const std::string& type)
280 {
281  return addColumnPrivate<SameByteOrder>(name, type);
282 }
283 
285 
286  if (empty())
287  return false;
288 
289  for (size_t i = 0; i < size(); i++) {
290  if (!(*this)[i]->hasInitialisedCoder())
291  return false;
292  }
293 
294  return true;
295 }
296 
297 MetaData& MetaData::addBitfield(const std::string& name, const eckit::sql::BitfieldDef& bf)
298 {
299  return addBitfieldPrivate<SameByteOrder>(name, bf);
300 }
301 
302 //----------------------------------------------------------------------------------------------------------------------
303 
304 } // namespace core
305 } // namespace odc
306 
void max(double m)
Definition: Codec.h:69
void min(double m)
Definition: Codec.h:66
Codec & coder() const
Definition: Column.h:51
void name(const std::string name)
Definition: Column.h:57
bool isConstant()
Definition: Column.cc:89
bool operator==(const MetaData &) const
Check if number of columns, column names and column types are equal. Values not checked.
Definition: MetaData.cc:212
void setSize(size_t)
Definition: MetaData.cc:64
size_t columnIndex(const std::string &) const
Definition: MetaData.cc:95
MetaData & addBitfield(const std::string &name, const eckit::sql::BitfieldDef &)
Definition: MetaData.cc:297
static api::ColumnType convertType(const std::string &)
Definition: MetaData.cc:35
bool hasColumn(const std::string &) const
Definition: MetaData.cc:87
MetaData operator+(const MetaData &)
Definition: MetaData.cc:164
unsigned long long rowsNumber_
Definition: MetaData.h:106
bool compatible(const MetaData &other) const
Definition: MetaData.cc:231
MetaData & operator=(const MetaData &)
Definition: MetaData.cc:112
bool equalsIncludingConstants(const MetaData &, const std::vector< std::string > &constColumns) const
Definition: MetaData.cc:171
virtual void print(std::ostream &s) const
Definition: MetaData.cc:272
virtual ~MetaData()
Definition: MetaData.cc:77
MetaData * clone() const
Definition: MetaData.cc:57
MetaData & operator+=(const MetaData &)
Definition: MetaData.cc:136
bool equals(const MetaData &md, bool compareDataSizes=true) const
Definition: MetaData.cc:216
MetaData & addColumn(const std::string &name, const std::string &type)
Definition: MetaData.cc:279
bool allColumnsInitialised() const
Definition: MetaData.cc:284
Column * columnByName(const std::string &) const
Definition: MetaData.cc:84
void operator|=(const MetaData &other)
Definition: MetaData.cc:151
@ BITFIELD
Definition: ColumnType.h:27
Definition: ColumnInfo.h:23
Definition: encode.cc:30