13 #include "eckit/io/FileHandle.h"
14 #include "eckit/utils/StringTools.h"
15 #include "eckit/sql/SQLTableFactory.h"
16 #include "eckit/sql/type/SQLBitfield.h"
17 #include "eckit/utils/Translator.h"
18 #include "eckit/sql/SQLColumn.h"
26 using namespace eckit;
27 using namespace eckit::sql;
41 class ODAFactory :
public eckit::sql::SQLTableFactoryBase {
42 virtual SQLTable*
build(SQLDatabase& owner,
const std::string&
name,
const std::string& location)
const override {
44 PathName path(location);
45 if (!path.exists())
return 0;
48 FileHandle fh(path,
false);
52 char oda[5] {
'\xff',
'\xff',
'O',
'D',
'A'};
53 if (fh.read(buf, 5) != 5 || ::memcmp(buf,
oda, 5) != 0)
return 0;
66 template <
typename READER>
68 SQLTable(owner, path,
name),
75 template <
typename READER>
78 template <
typename READER>
84 template <
typename READER>
87 auto it = oda_.begin();
89 size_t count = it->columns().size();
93 Column& column (*it->columns()[
i]);
95 const std::string
name (column.
name());
101 size_t typeSizeDoubles = it->dataSizeDoubles(
i);
103 switch(column.
type()) {
104 case INTEGER: sqlType =
"integer";
break;
105 case STRING: sqlType =
"string";
break;
106 case REAL: sqlType =
"real";
break;
107 case DOUBLE: sqlType =
"double";
break;
109 std::string typeSignature = type::SQLBitfield::make(
"Bitfield", bitfieldDef.first, bitfieldDef.second,
"DummyTypeAlias");
110 addColumn(
name,
i, type::SQLType::lookup(typeSignature), hasMissing, missing,
true, bitfieldDef);
114 throw SeriousBug(
"Unknown type: " + Translator<int, std::string>()(column.
type()), Here());
117 addColumn(
name,
i, type::SQLType::lookup(sqlType, typeSizeDoubles), hasMissing, missing, column.
type() ==
BITFIELD, bitfieldDef);
166 template <
typename READER>
171 if (SQLTable::hasColumn(
name)) {
177 std::string colName (
name +
"@");
180 for (
const auto& column : columnsByName_) {
181 const std::string& s (column.first);
182 if (StringTools::startsWith(s, colName)) {
187 if (n == 1)
return true;
189 throw UserError(std::string(
"TODATable:hasColumn(\"") +
name +
"\"): ambiguous name");
195 template <
typename READER>
200 if (SQLTable::hasColumn(
name)) {
201 return SQLTable::column(
name);
206 const std::string colName (
name +
"@");
207 SQLColumn* column = 0;
209 for (
const auto& col : columnsByName_) {
210 const std::string& s (col.first);
211 if (StringTools::startsWith(s, colName)) {
212 if (column)
throw UserError(std::string(
"TODATable:hasColumn(\"") +
name +
"\"): ambiguous name");
217 if (!column)
throw SeriousBug(
"Requesting column \"" +
name +
"\": not found", Here());
222 template <
typename READER>
224 std::function<
void(eckit::sql::SQLTableIterator&)> metadataUpdateCallback)
const {
228 template <
typename READER>
230 s <<
"TODATable(" << path_ <<
")";
static void count(void *counter, const double *data, size_t n)
void bitfieldDef(const eckit::sql::BitfieldDef &b)
void hasMissing(bool h)
Delegations to Codec:
void missingValue(double v)
void name(const std::string name)
static api::ColumnType type(const std::string &)
virtual bool hasColumn(const std::string &) const override
const READER & oda() const
virtual const eckit::sql::SQLColumn & column(const std::string &) const override
virtual void print(std::ostream &s) const override
virtual eckit::sql::SQLTableIterator * iterator(const std::vector< std::reference_wrapper< const eckit::sql::SQLColumn >> &, std::function< void(eckit::sql::SQLTableIterator &)> metadataUpdateCallback) const override
virtual SQLTable * build(SQLDatabase &owner, const std::string &name, const std::string &location) const override
ODAFactory odaFactoryInstance