IODA Bundle
ImportTool.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/tools/ImportTool.h"
12 
13 #include "eckit/filesystem/PathName.h"
14 #include "eckit/io/FileHandle.h"
15 #include "eckit/log/Log.h"
16 #include "eckit/utils/StringTools.h"
17 #include "eckit/sql/SQLParser.h"
18 #include "eckit/sql/SQLSession.h"
19 #include "eckit/sql/SQLStatement.h"
20 
21 #include "odc/api/Odb.h"
23 #include "odc/sql/TODATable.h"
24 
25 
26 using namespace std;
27 using namespace eckit;
28 
29 namespace odc {
30 namespace tool {
31 
32 // TODO: A test with wide strings
33 // TODO: A test with SQL filtering
34 // TODO: A test with non-comma delimiters
35 
36 ImportTool::ImportTool(int argc, char *parameters[])
37 : Tool(argc, parameters)
38 {
39  registerOptionWithArgument("-d"); // Delimiter
40  registerOptionWithArgument("-sql"); // SQL to filter input CSV with
41 }
42 
43 void ImportTool::help(std::ostream &o) {
44  o << "Imports data from a text file";
45 }
46 
47 void ImportTool::usage(const std::string& name, std::ostream &o) {
48  o << name
49  << "\t[-d delimiter] <input.file> <output.file>" << std::endl
50  << std::endl
51  << "\tdelimiter can be a single character (e.g.: ',') or TAB. As a data example:" << std::endl
52  << std::endl
53  << "\tcol1:INTEGER,col2:REAL" << std::endl
54  << "\t1,2.0" << std::endl
55  << "\t3,4.0" << std::endl;
56 }
57 
58 
60 {
61  if (parameters().size() != 3)
62  {
63  Log::error() << "Usage: ";
65  Log::error() << std::endl;
66  return;
67  }
68 
69  PathName inFile (parameters(1)),
70  outFile (parameters(2));
71 
72  Log::info() << "ImportTool::run: inFile: " << inFile << ", outFile: " << outFile << std::endl;
73 
74  std::string delimiter (StringTools::upper(optionArgument("-d", defaultDelimiter())));
75  delimiter = delimiter == "TAB" ? "\t"
76  : delimiter == "SPACE" ? " "
77  : delimiter;
78 
79  std::string sql (optionArgument("-sql", std::string("select *;")));
80 
81  if (sql == "select *;") {
82  FileHandle dh_in(inFile);
83  FileHandle dh_out(outFile);
84  dh_in.openForRead();
85  AutoClose close_in(dh_in);
86  dh_out.openForWrite(0);
87  AutoClose close_out(dh_out);
88  size_t n = api::odbFromCSV(dh_in, dh_out);
89  Log::info() << "ImportTool::odbFromCSV: Copied " << n << " rows." << std::endl;
90  } else {
91  filterAndImportFile (inFile, outFile, sql, delimiter);
92  }
93 }
94 
95 void ImportTool::importFile(const PathName& in, const PathName& out, const std::string& delimiter)
96 {
97  filterAndImportFile(in, out, "select *;", delimiter);
98 }
99 
100 void ImportTool::filterAndImportFile(const PathName& in, const PathName& out, const std::string& sql, const std::string& delimiter)
101 {
102  // TODO: Why are we not using the ODAOutput directly, rather than going via a Select, Writer combination?
103 
104  eckit::sql::SQLSession session(std::unique_ptr<odc::sql::SQLOutputConfig>(new odc::sql::SQLOutputConfig(out)));
105 
106  eckit::sql::SQLDatabase& db(session.currentDatabase());
107  db.addImplicitTable(new odc::sql::ODBCSVTable(db, in, in, delimiter));
108  session.currentDatabase();
109 
110  eckit::sql::SQLParser().parseString(session, sql);
111  size_t n = session.statement().execute();
112 
113  Log::info() << "ImportTool::importFile: Copied " << n << " rows." << std::endl;
114 }
115 
116 } // namespace tool
117 } // namespace odc
118 
T optionArgument(const std::string &, T defaultValue)
void registerOptionWithArgument(const std::string &)
const std::vector< std::string > parameters()
static void importFile(const eckit::PathName &in, const eckit::PathName &out, const std::string &delimiter=defaultDelimiter())
Definition: ImportTool.cc:95
static void filterAndImportFile(const eckit::PathName &in, const eckit::PathName &out, const std::string &sql, const std::string &delimiter=defaultDelimiter())
Definition: ImportTool.cc:100
static void usage(const std::string &name, std::ostream &o)
Definition: ImportTool.cc:47
static std::string defaultDelimiter()
Definition: ImportTool.h:33
static void help(std::ostream &o)
Definition: ImportTool.cc:43
std::string name()
Definition: Tool.h:34
size_t odbFromCSV(DataHandle &dh_in, DataHandle &dh_out, const std::string &delimiter)
odbFromCSV returns number of lines imported
Definition: Odb.cc:375
Definition: ColumnInfo.h:23
Definition: encode.cc:30