IODA Bundle
ODAHeaderTool.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 <sstream>
12 
13 #include "ODAHeaderTool.h"
14 #include "odc/core/TablesReader.h"
15 
16 using namespace eckit;
17 using namespace odc::core;
18 
19 namespace odc {
20 namespace tool {
21 
22 class MDPrinter {
23 public:
24  virtual void print(std::ostream&, const core::Table&) = 0;
25  virtual void printSummary(std::ostream&) {}
26 };
27 
28 class VerbosePrinter : public MDPrinter {
29 public:
30  VerbosePrinter() : headerCount_() {}
31  void print(std::ostream& o, const core::Table& tbl)
32  {
33  o << std::endl << "Header " << ++headerCount_ << ". "
34  << "Begin offset: " << tbl.startPosition() << ", end offset: " << tbl.nextPosition()
35  << ", number of rows in block: " << tbl.rowCount()
36  << ", byteOrder: " << ((tbl.byteOrder() == 1) ? "same" : "other")
37  << std::endl
38  << tbl.columns();
39  }
40 private:
41  unsigned long headerCount_;
42 };
43 
44 class OffsetsPrinter : public MDPrinter {
45 public:
47  void print(std::ostream& o, const core::Table& tbl)
48  {
49  Offset offset (tbl.startPosition());
50  Length length (tbl.nextPosition() - tbl.startPosition());
51  o << offset << " " << length << " " << tbl.rowCount() << " " << tbl.columnCount() << std::endl;
52  }
53 private:
54  unsigned long headerCount_;
55 };
56 
57 class DDLPrinter : public MDPrinter {
58 public:
59 
60  DDLPrinter(const std::string& path, const std::string& tableName)
61  : path_(path), tableName_(tableName) {}
62 
63  void print(std::ostream& o, const core::Table& tbl)
64  {
65  if (md_.empty() || md_.back() != tbl.columns())
66  {
67  md_.push_back(tbl.columns());
68  return;
69  }
70  }
71 
72  void printSummary(std::ostream& o)
73  {
74  for (size_t i(0); i < md_.size(); ++i)
75  printTable(o, md_[i], tableName_, path_);
76  }
77 
78  static std::string typeName(const Column& c)
79  {
80  using namespace api;
81  switch (c.type())
82  {
83  case STRING: return "STRING";
84  case INTEGER: return "INTEGER";
85  case BITFIELD: return "INTEGER";
86  case REAL: return "REAL";
87  case DOUBLE: return "DOUBLE";
88  default:
89  throw new Exception("unknown type");
90  }
91  }
92 
93  static std::pair<std::string,std::string> typeDefinitionAndName(const std::string& tableName, const Column& c)
94  {
95  std::stringstream definition;
96  std::string type_name (typeName(c));
97 
98  if (c.type() == api::BITFIELD)
99  {
100  const eckit::sql::BitfieldDef& bd (c.bitfieldDef());
101  const std::vector<std::string>& fieldNames (bd.first);
102  const std::vector<int>& sizes (bd.second);
103 
104  type_name = stripAtTable(tableName, c.name()) + "_at_" + tableName + "_t";
105 
106  definition << "CREATE TYPE " << type_name << " AS (";
107  for (size_t i(0); i < sizes.size(); ++i)
108  definition << fieldNames[i] << " bit" << sizes[i]
109  << ((i+1 < sizes.size()) ? ", " : "");
110  definition << ");\n";
111  }
112 
113  return make_pair(definition.str(), type_name);
114  }
115 
116 
117  static std::string stripAtTable(const std::string& tableName, const std::string& columnName)
118  {
119  std::string suffix ( std::string("@") + tableName );
120 
121  if (columnName.size() >= suffix.size()
122  && columnName.compare(columnName.size() - suffix.size(), suffix.size(), suffix) == 0)
123  return columnName.substr(0, columnName.size() - suffix.size());
124 
125  return columnName;
126  }
127 
128  static void printTable(std::ostream& s, const MetaData& md, const std::string& tableName, const std::string& path)
129  {
130  std::stringstream create_type, create_table;
131 
132  create_table << "CREATE TABLE " << tableName << " AS (\n";
133  for (size_t i (0); i < md.size(); ++i)
134  {
135  std::pair<std::string,std::string> p (typeDefinitionAndName(tableName, *md[i]));
136  const std::string& def (p.first),
137  type (p.second);
138 
139  create_type << def;
140  create_table << " " << stripAtTable(tableName, md[i]->name()) << " " << type << ",\n";
141  }
142  create_table << ") ON '" << path << "';\n";
143 
144  s << create_type.str();
145  s << create_table.str();
146  }
147 
148 private:
149  std::vector<MetaData> md_;
150  const std::string path_;
151  const std::string tableName_;
152 };
153 
154 HeaderTool::HeaderTool (int argc, char *argv[]) : Tool(argc, argv) {}
155 
157 {
158  registerOptionWithArgument("-table");
159  if (parameters().size() < 2)
160  {
161  Log::error() << "Usage: ";
162  usage(parameters(0), Log::error());
163  Log::error() << std::endl;
164  return;
165  }
166 
167  const std::string db (parameters(1));
168  std::ostream& o (std::cout);
169 
170  VerbosePrinter verbosePrinter;
171  OffsetsPrinter offsetsPrinter;
172  DDLPrinter ddlPrinter (db, optionArgument("-table", std::string("foo")));
173 
174  MDPrinter& printer(*
175  (optionIsSet("-offsets") ? static_cast<MDPrinter*>(&offsetsPrinter) :
176  optionIsSet("-ddl") ? static_cast<MDPrinter*>(&ddlPrinter) :
177  static_cast<MDPrinter*>(&verbosePrinter)));
178 
179 
180  core::TablesReader reader(db);
181  auto it = reader.begin();
182  auto end = reader.end();
183 
184  for(; it != end; ++it)
185  {
186  printer.print(o, *it);
187  }
188  printer.printSummary(o);
189 }
190 
191 } // namespace tool
192 } // namespace odc
193 
size_t columnCount() const
Definition: Table.cc:54
eckit::Offset nextPosition() const
Definition: Table.cc:42
size_t rowCount() const
Definition: Table.cc:50
int32_t byteOrder() const
Definition: Table.cc:58
const MetaData & columns() const
Definition: Table.cc:66
eckit::Offset startPosition() const
Definition: Table.cc:37
bool optionIsSet(const std::string &)
T optionArgument(const std::string &, T defaultValue)
void registerOptionWithArgument(const std::string &)
const std::vector< std::string > parameters()
DDLPrinter(const std::string &path, const std::string &tableName)
const std::string path_
const std::string tableName_
static void printTable(std::ostream &s, const MetaData &md, const std::string &tableName, const std::string &path)
void print(std::ostream &o, const core::Table &tbl)
std::vector< MetaData > md_
static std::string stripAtTable(const std::string &tableName, const std::string &columnName)
void printSummary(std::ostream &o)
static std::pair< std::string, std::string > typeDefinitionAndName(const std::string &tableName, const Column &c)
static std::string typeName(const Column &c)
static void usage(const std::string &name, std::ostream &o)
Definition: ODAHeaderTool.h:29
virtual void printSummary(std::ostream &)
virtual void print(std::ostream &, const core::Table &)=0
void print(std::ostream &o, const core::Table &tbl)
void print(std::ostream &o, const core::Table &tbl)
@ BITFIELD
Definition: ColumnType.h:27
Definition: ColumnInfo.h:23