OmniSciDB  8a228a1076
SqliteConnector.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 MapD Technologies, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
23 #include "SqliteConnector.h"
24 
25 #include <iostream>
26 
27 #include "Logger/Logger.h"
28 
29 using std::cout;
30 using std::endl;
31 using std::runtime_error;
32 using std::string;
33 
34 SqliteConnector::SqliteConnector(const string& dbName, const string& dir)
35  : dbName_(dbName) {
36  string connectString(dir);
37  if (connectString.size() > 0 && connectString[connectString.size() - 1] != '/') {
38  connectString.push_back('/');
39  }
40  connectString += dbName;
41  int returnCode = sqlite3_open(connectString.c_str(), &db_);
42  if (returnCode != SQLITE_OK) {
43  throwError();
44  }
45 }
46 
47 SqliteConnector::SqliteConnector(sqlite3* db) : db_(db) {}
48 
50  if (!dbName_.empty()) {
51  sqlite3_close(db_);
52  }
53 }
54 
56  string errorMsg(sqlite3_errmsg(db_));
57  throw runtime_error("Sqlite3 Error: " + errorMsg);
58 }
59 
60 std::string get_column_datum(int column_type, sqlite3_stmt* stmt, size_t column_index) {
61  const char* datum_ptr;
62  if (column_type == SQLITE_BLOB) {
63  datum_ptr = static_cast<const char*>(sqlite3_column_blob(stmt, column_index));
64  } else {
65  datum_ptr = reinterpret_cast<const char*>(sqlite3_column_text(stmt, column_index));
66  }
67  size_t datum_size = sqlite3_column_bytes(stmt, column_index);
68  return {datum_ptr, datum_size};
69 }
70 
71 void SqliteConnector::query_with_text_params(const std::string& queryString,
72  const std::vector<std::string>& text_params,
73  const std::vector<BindType>& bind_types) {
74  if (!bind_types.empty()) {
75  CHECK_EQ(text_params.size(), bind_types.size());
76  }
77 
78  atFirstResult_ = true;
79  numRows_ = 0;
80  numCols_ = 0;
81  columnNames.clear();
82  columnTypes.clear();
83  results_.clear();
84  sqlite3_stmt* stmt;
85  int returnCode = sqlite3_prepare_v2(db_, queryString.c_str(), -1, &stmt, nullptr);
86  if (returnCode != SQLITE_OK) {
87  throwError();
88  }
89 
90  int num_params = 1;
91  for (auto text_param : text_params) {
92  if (!bind_types.empty() && bind_types[num_params - 1] == BindType::BLOB) {
93  returnCode = sqlite3_bind_blob(
94  stmt, num_params++, text_param.c_str(), text_param.size(), SQLITE_TRANSIENT);
95  } else {
96  returnCode = sqlite3_bind_text(
97  stmt, num_params++, text_param.c_str(), text_param.size(), SQLITE_TRANSIENT);
98  }
99  if (returnCode != SQLITE_OK) {
100  throwError();
101  }
102  }
103 
104  do {
105  returnCode = sqlite3_step(stmt);
106  if (returnCode != SQLITE_ROW && returnCode != SQLITE_DONE) {
107  throwError();
108  }
109  if (returnCode == SQLITE_DONE) {
110  break;
111  }
112  if (atFirstResult_) {
113  numCols_ = sqlite3_column_count(stmt);
114  for (size_t c = 0; c < numCols_; ++c) {
115  columnNames.emplace_back(sqlite3_column_name(stmt, c));
116  columnTypes.push_back(sqlite3_column_type(stmt, c));
117  }
118  results_.resize(numCols_);
119  atFirstResult_ = false;
120  }
121  numRows_++;
122  for (size_t c = 0; c < numCols_; ++c) {
123  auto column_type = sqlite3_column_type(stmt, c);
124  bool is_null = (column_type == SQLITE_NULL);
125  auto col_text = get_column_datum(column_type, stmt, c);
126  if (is_null) {
127  CHECK(col_text.empty());
128  }
129  results_[c].emplace_back(NullableResult{col_text, is_null});
130  }
131  } while (1 == 1); // Loop control in break statement above
132 
133  sqlite3_finalize(stmt);
134 }
135 
137  const std::string& queryString,
138  const std::vector<std::string>& text_params) {
139  query_with_text_params(queryString, text_params, {});
140 }
141 
142 void SqliteConnector::query_with_text_param(const std::string& queryString,
143  const std::string& text_param) {
144  query_with_text_params(queryString, std::vector<std::string>{text_param});
145 }
146 
147 void SqliteConnector::query(const std::string& queryString) {
148  query_with_text_params(queryString, std::vector<std::string>{});
149 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
virtual void query_with_text_params(std::string const &query_only)
virtual void query(const std::string &queryString)
std::string get_column_datum(int column_type, sqlite3_stmt *stmt, size_t column_index)
std::vector< std::vector< NullableResult > > results_
std::vector< int > columnTypes
std::string dbName_
bool is_null(const T &v, const SQLTypeInfo &t)
SqliteConnector(const std::string &dbName, const std::string &dir=".")
virtual ~SqliteConnector()
#define CHECK(condition)
Definition: Logger.h:197
std::vector< std::string > columnNames
virtual void query_with_text_param(const std::string &queryString, const std::string &text_param)