ledger-core
soci-proxy.h
1 /*
2  *
3  * soci-proxy.h
4  * ledger-core
5  *
6  * Created by Pierre Pollastri on 13/11/2018.
7  *
8  * The MIT License (MIT)
9  *
10  * Copyright (c) 2017 Ledger
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy
13  * of this software and associated documentation files (the "Software"), to deal
14  * in the Software without restriction, including without limitation the rights
15  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  * copies of the Software, and to permit persons to whom the Software is
17  * furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in all
20  * copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  * SOFTWARE.
29  *
30  */
31 
32 #ifndef SOCI_PROXY_H_INCLUDED
33 #define SOCI_PROXY_H_INCLUDED
34 
35 // If SOCI_PROXY_DECL isn't defined yet define it now
36 #ifndef SOCI_PROXY_DECL
37 # define SOCI_PROXY_DECL
38 #endif
39 
40 #include <soci-backend.h>
41 #include <api/DatabaseEngine.hpp>
42 #include <api/DatabaseConnectionPool.hpp>
43 #include <api/DatabaseConnection.hpp>
44 #include <api/DatabaseStatement.hpp>
45 #include <api/DatabaseError.hpp>
46 #include <api/DatabaseBlob.hpp>
47 #include <api/DatabaseResultSet.hpp>
48 #include <api/DatabaseValueType.hpp>
49 #include <api/DatabaseColumn.hpp>
50 #include <api/DatabaseResultRow.hpp>
51 
52 #include <cstddef>
53 #include <string>
54 #include <unordered_map>
55 #include <utils/Either.hpp>
56 #include <soci.h>
57 
58 #ifndef SOCI_OVERRIDE
59 # define SOCI_OVERRIDE override
60 #endif
61 
62 #ifdef SOCI_PROXY_DEBUG
63 #define SP_PRINT(p) std::cout << p << std::endl;
64 #else
65 #define SP_PRINT(p)
66 #endif
67 
68 /***
69  * \file soci-proxy.h
70  * A soci backend to use with the ledger::core::api::DatabaseEngine
71  * \link http://soci.sourceforge.net/doc/3.2/backends.html
72  */
73 namespace soci
74 {
75 
76  struct proxy_statement_backend;
77 
78  struct SOCI_PROXY_DECL proxy_standard_into_type_backend : details::standard_into_type_backend
79  {
81  : _statement(st)
82  {}
83 
84  void define_by_pos(int& position, void* data, details::exchange_type type) SOCI_OVERRIDE;
85 
86  void pre_fetch() SOCI_OVERRIDE;
87  void post_fetch(bool gotData, bool calledFromFetch, indicator* ind) SOCI_OVERRIDE;
88 
89  void clean_up() SOCI_OVERRIDE;
90 
91  proxy_statement_backend& _statement;
92  void* _data;
93  int _position;
94  details::exchange_type _type;
95  };
96 
97  struct SOCI_PROXY_DECL proxy_standard_use_type_backend : details::standard_use_type_backend
98  {
100  : statement_(st), _position(-1)
101  {}
102 
103  void bind_by_pos(int& position, void* data, details::exchange_type type, bool readOnly) SOCI_OVERRIDE;
104  void bind_by_name(std::string const& name, void* data, details::exchange_type type, bool readOnly) SOCI_OVERRIDE;
105 
106  void pre_use(indicator const* ind) SOCI_OVERRIDE;
107  void post_use(bool gotData, indicator* ind) SOCI_OVERRIDE;
108 
109  void clean_up() SOCI_OVERRIDE;
110 
111  proxy_statement_backend& statement_;
113  void* _data;
114  details::exchange_type _type;
115  };
116 
117  struct proxy_session_backend;
118  struct SOCI_PROXY_DECL proxy_statement_backend : details::statement_backend
119  {
120  proxy_statement_backend(proxy_session_backend &session) : _session(session) {};
121 
122  void alloc() SOCI_OVERRIDE;
123  void clean_up() SOCI_OVERRIDE;
124  void prepare(std::string const& query, details::statement_type eType) SOCI_OVERRIDE;
125 
126  exec_fetch_result execute(int number) SOCI_OVERRIDE;
127  exec_fetch_result fetch(int number) SOCI_OVERRIDE;
128 
129  exec_fetch_result batch_fetch(int number);
130  exec_fetch_result single_row_fetch();
131 
132  long long get_affected_rows() SOCI_OVERRIDE;
133  int get_number_of_rows() SOCI_OVERRIDE;
134  std::string get_parameter_name(int index) const;
135 
136  std::string rewrite_for_procedure_call(std::string const& query) SOCI_OVERRIDE;
137 
138  int prepare_for_describe() SOCI_OVERRIDE;
139  void describe_column(int colNum, data_type& dtype, std::string& columnName) SOCI_OVERRIDE;
140 
141  proxy_standard_into_type_backend* make_into_type_backend() SOCI_OVERRIDE;
142  proxy_standard_use_type_backend* make_use_type_backend() SOCI_OVERRIDE;
143  details::vector_into_type_backend* make_vector_into_type_backend() SOCI_OVERRIDE;
144  details::vector_use_type_backend* make_vector_use_type_backend() SOCI_OVERRIDE;
145 
146  bool reset_if_necessary();
147 
148  proxy_session_backend& _session;
149  std::shared_ptr<ledger::core::api::DatabaseStatement> _stmt;
150  std::shared_ptr<ledger::core::api::DatabaseResultSet> _results;
151  std::shared_ptr<ledger::core::api::DatabaseResultRow> _lastRow;
152  };
153 
154  struct proxy_rowid_backend : details::rowid_backend
155  {
156  proxy_rowid_backend(proxy_session_backend &session) {throw soci::soci_error("row id not supported for DatabaseEngine");};
157 
158  ~proxy_rowid_backend() SOCI_OVERRIDE;
159 
160  };
161 
162  struct proxy_blob_backend : details::blob_backend
163  {
164  proxy_blob_backend(const std::shared_ptr<ledger::core::api::DatabaseBlob>& backend) : _backend(backend) {};
165 
166  ~proxy_blob_backend() SOCI_OVERRIDE {};
167 
168  std::size_t get_len() SOCI_OVERRIDE;
169  std::size_t read(std::size_t offset, char* buf, std::size_t toRead) SOCI_OVERRIDE;
170  std::size_t write(std::size_t offset, char const* buf, std::size_t toWrite) SOCI_OVERRIDE;
171  std::size_t append(char const* buf, std::size_t toWrite) SOCI_OVERRIDE;
172  const std::shared_ptr<ledger::core::api::DatabaseBlob> getBlob() const { return _backend; };
173  void setBlob(const std::shared_ptr<ledger::core::api::DatabaseBlob>& blob) {
174  _backend = blob;
175  }
176  void trim(std::size_t newLen) SOCI_OVERRIDE;
177 
178  std::shared_ptr<ledger::core::api::DatabaseBlob> _backend;
179 
180  };
181 
182  struct proxy_session_backend : details::session_backend
183  {
184  proxy_session_backend(const std::shared_ptr<ledger::core::api::DatabaseConnection>& pool);
185 
186  ~proxy_session_backend() SOCI_OVERRIDE;
187 
188  void begin() SOCI_OVERRIDE;
189  void commit() SOCI_OVERRIDE;
190  void rollback() SOCI_OVERRIDE;
191 
192  std::string get_dummy_from_table() const { return std::string(); }
193 
194  std::string get_backend_name() const SOCI_OVERRIDE { return "proxy"; }
195  std::shared_ptr<ledger::core::api::DatabaseConnection> get_connection() const { return _conn; };
196  void clean_up();
197 
198  proxy_statement_backend* make_statement_backend() SOCI_OVERRIDE;
199  proxy_rowid_backend* make_rowid_backend() SOCI_OVERRIDE;
200  proxy_blob_backend* make_blob_backend() SOCI_OVERRIDE;
201 
202  private:
203  std::shared_ptr<ledger::core::api::DatabaseConnection> _conn;
204  };
205 
206  struct SOCI_PROXY_DECL proxy_backend_factory : backend_factory
207  {
208  proxy_backend_factory(const std::shared_ptr<ledger::core::api::DatabaseEngine>& engine) : _engine(engine) {}
209  proxy_session_backend* make_session(connection_parameters const& parameters) const SOCI_OVERRIDE;
210  const std::shared_ptr<ledger::core::api::DatabaseEngine>& getEngine() const;
211  ~proxy_backend_factory();
212 
213  private:
214 
215  std::shared_ptr<ledger::core::api::DatabaseConnectionPool> get_pool(connection_parameters const& parameters) const; // Workaround to make the god damn adapter match the interface
216 
217  std::shared_ptr<ledger::core::api::DatabaseEngine> _engine;
218  mutable std::unordered_map<std::string, std::shared_ptr<ledger::core::api::DatabaseConnectionPool>> _pools; // Yep ugly
219  };
220 
221  extern SOCI_PROXY_DECL proxy_backend_factory const proxy;
222 
223  SOCI_PROXY_DECL backend_factory const* factory_proxy(const std::shared_ptr<ledger::core::api::DatabaseEngine>& engine);
224  SOCI_PROXY_DECL void register_factory_proxy();
225 
226 } // namespace soci
227 
228 #undef SOCI_OVERRIDE
229 #endif // SOCI_PROXY_H_INCLUDED
Definition: soci-proxy.h:182
Definition: soci-proxy.h:78
Definition: soci-proxy.h:162
Definition: soci-proxy.h:206
Definition: soci-proxy.h:154
Definition: soci-proxy.h:118
Definition: soci-proxy.h:73
Definition: soci-proxy.h:97