/Users/deen/code/yugabyte-db/src/yb/yql/pgwrapper/libpq_utils.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) YugaByte, Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
4 | | // in compliance with the License. You may obtain a copy of the License at |
5 | | // |
6 | | // http://www.apache.org/licenses/LICENSE-2.0 |
7 | | // |
8 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
9 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
10 | | // or implied. See the License for the specific language governing permissions and limitations |
11 | | // under the License. |
12 | | // |
13 | | |
14 | | #ifndef YB_YQL_PGWRAPPER_LIBPQ_UTILS_H |
15 | | #define YB_YQL_PGWRAPPER_LIBPQ_UTILS_H |
16 | | |
17 | | #include <memory> |
18 | | #include <string> |
19 | | |
20 | | #include "libpq-fe.h" // NOLINT |
21 | | |
22 | | #include "yb/common/transaction.pb.h" |
23 | | |
24 | | #include "yb/util/format.h" |
25 | | #include "yb/util/monotime.h" |
26 | | #include "yb/util/net/net_fwd.h" |
27 | | #include "yb/util/result.h" |
28 | | |
29 | | namespace yb { |
30 | | namespace pgwrapper { |
31 | | |
32 | | struct PGConnClose { |
33 | | void operator()(PGconn* conn) const; |
34 | | }; |
35 | | |
36 | | struct PGResultClear { |
37 | | void operator()(PGresult* result) const; |
38 | | }; |
39 | | |
40 | | typedef std::unique_ptr<PGconn, PGConnClose> PGConnPtr; |
41 | | typedef std::unique_ptr<PGresult, PGResultClear> PGResultPtr; |
42 | | |
43 | | Result<bool> GetBool(PGresult* result, int row, int column); |
44 | | |
45 | | Result<int32_t> GetInt32(PGresult* result, int row, int column); |
46 | | |
47 | | Result<int64_t> GetInt64(PGresult* result, int row, int column); |
48 | | |
49 | | Result<double> GetDouble(PGresult* result, int row, int column); |
50 | | |
51 | | Result<std::string> GetString(PGresult* result, int row, int column); |
52 | | |
53 | 0 | inline Result<int32_t> GetValueImpl(PGresult* result, int row, int column, int32_t*) { |
54 | 0 | return GetInt32(result, row, column); |
55 | 0 | } |
56 | | |
57 | | inline Result<int64_t> GetValueImpl(PGresult* result, int row, int column, int64_t*) { |
58 | | return GetInt64(result, row, column); |
59 | | } |
60 | | |
61 | | inline Result<std::string> GetValueImpl(PGresult* result, int row, int column, std::string*) { |
62 | | return GetString(result, row, column); |
63 | | } |
64 | | |
65 | | template<class T> |
66 | | Result<T> GetValue(PGresult* result, int row, int column) { |
67 | | // static_cast<T*>(nullptr) is a trick to use function overload from template. |
68 | | return GetValueImpl(result, row, column, static_cast<T*>(nullptr)); |
69 | | } |
70 | | |
71 | | Result<std::string> ToString(PGresult* result, int row, int column); |
72 | | void LogResult(PGresult* result); |
73 | | |
74 | | std::string PqEscapeLiteral(const std::string& input); |
75 | | std::string PqEscapeIdentifier(const std::string& input); |
76 | | |
77 | | class PGConn { |
78 | | public: |
79 | | ~PGConn(); |
80 | | |
81 | | PGConn(PGConn&& rhs); |
82 | | PGConn& operator=(PGConn&& rhs); |
83 | | |
84 | | static Result<PGConn> Connect( |
85 | | const HostPort& host_port, |
86 | 267 | bool simple_query_protocol = false) { |
87 | 267 | return Connect(host_port, "" /* db_name */, simple_query_protocol); |
88 | 267 | } |
89 | | static Result<PGConn> Connect( |
90 | | const HostPort& host_port, |
91 | | const std::string& db_name, |
92 | 354 | bool simple_query_protocol = false) { |
93 | 354 | return Connect(host_port, db_name, "postgres" /* user */, simple_query_protocol); |
94 | 354 | } |
95 | | static Result<PGConn> Connect( |
96 | | const HostPort& host_port, |
97 | | const std::string& db_name, |
98 | | const std::string& user, |
99 | | bool simple_query_protocol = false); |
100 | | static Result<PGConn> Connect( |
101 | | const std::string& conn_str, |
102 | 382 | bool simple_query_protocol = false) { |
103 | 382 | return Connect(conn_str, |
104 | 382 | CoarseMonoClock::Now() + MonoDelta::FromSeconds(60) /* deadline */, |
105 | 382 | simple_query_protocol); |
106 | 382 | } |
107 | | static Result<PGConn> Connect( |
108 | | const std::string& conn_str, |
109 | | CoarseTimePoint deadline, |
110 | | bool simple_query_protocol = false); |
111 | | |
112 | | CHECKED_STATUS Execute(const std::string& command, bool show_query_in_error = true); |
113 | | |
114 | | template <class... Args> |
115 | 4.78k | CHECKED_STATUS ExecuteFormat(const std::string& format, Args&&... args) { |
116 | 4.78k | return Execute(Format(format, std::forward<Args>(args)...)); |
117 | 4.78k | } Unexecuted instantiation: yb::Status yb::pgwrapper::PGConn::ExecuteFormat<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const*>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const*&&) Unexecuted instantiation: yb::Status yb::pgwrapper::PGConn::ExecuteFormat<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const* const&, char const*, char const* const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, bool&, unsigned int const&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const* const&, char const*&&, char const* const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, bool&, unsigned int const&) yb::Status yb::pgwrapper::PGConn::ExecuteFormat<int, int>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int&&, int&&) Line | Count | Source | 115 | 12 | CHECKED_STATUS ExecuteFormat(const std::string& format, Args&&... args) { | 116 | 12 | return Execute(Format(format, std::forward<Args>(args)...)); | 117 | 12 | } |
yb::Status yb::pgwrapper::PGConn::ExecuteFormat<int&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int&) Line | Count | Source | 115 | 4.56k | CHECKED_STATUS ExecuteFormat(const std::string& format, Args&&... args) { | 116 | 4.56k | return Execute(Format(format, std::forward<Args>(args)...)); | 117 | 4.56k | } |
yb::Status yb::pgwrapper::PGConn::ExecuteFormat<int const&, int const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int const&, int const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 115 | 213 | CHECKED_STATUS ExecuteFormat(const std::string& format, Args&&... args) { | 116 | 213 | return Execute(Format(format, std::forward<Args>(args)...)); | 117 | 213 | } |
|
118 | | |
119 | | Result<PGResultPtr> Fetch(const std::string& command); |
120 | | |
121 | | template <class... Args> |
122 | 638 | Result<PGResultPtr> FetchFormat(const std::string& format, Args&&... args) { |
123 | 638 | return Fetch(Format(format, std::forward<Args>(args)...)); |
124 | 638 | } |
125 | | |
126 | | // Fetches data matrix of specified size. I.e. exact number of rows and columns are expected. |
127 | | Result<PGResultPtr> FetchMatrix(const std::string& command, int rows, int columns); |
128 | | |
129 | | template <class T> |
130 | | Result<T> FetchValue(const std::string& command) { |
131 | | auto res = VERIFY_RESULT(FetchMatrix(command, 1, 1)); |
132 | | return GetValue<T>(res.get(), 0, 0); |
133 | | } |
134 | | |
135 | | CHECKED_STATUS StartTransaction(IsolationLevel isolation_level); |
136 | | CHECKED_STATUS CommitTransaction(); |
137 | | CHECKED_STATUS RollbackTransaction(); |
138 | | |
139 | | // Would this query use an index [only] scan? |
140 | | Result<bool> HasIndexScan(const std::string& query); |
141 | | |
142 | | CHECKED_STATUS CopyBegin(const std::string& command); |
143 | | Result<PGResultPtr> CopyEnd(); |
144 | | |
145 | | void CopyStartRow(int16_t columns); |
146 | | |
147 | | void CopyPutInt16(int16_t value); |
148 | | void CopyPutInt32(int32_t value); |
149 | | void CopyPutInt64(int64_t value); |
150 | | void CopyPut(const char* value, size_t len); |
151 | | |
152 | | void CopyPutString(const std::string& value) { |
153 | | CopyPut(value.c_str(), value.length()); |
154 | | } |
155 | | |
156 | 0 | PGconn* get() { |
157 | 0 | return impl_.get(); |
158 | 0 | } |
159 | | |
160 | | private: |
161 | | struct CopyData; |
162 | | |
163 | | PGConn(PGConnPtr ptr, bool simple_query_protocol); |
164 | | |
165 | | bool CopyEnsureBuffer(size_t len); |
166 | | bool CopyFlushBuffer(); |
167 | | |
168 | | PGConnPtr impl_; |
169 | | bool simple_query_protocol_; |
170 | | std::unique_ptr<CopyData> copy_data_; |
171 | | }; |
172 | | |
173 | | bool HasTryAgain(const Status& status); |
174 | | |
175 | | } // namespace pgwrapper |
176 | | } // namespace yb |
177 | | |
178 | | #endif // YB_YQL_PGWRAPPER_LIBPQ_UTILS_H |