Mercurial > hg > orthanc-databases
annotate Framework/PostgreSQL/PostgreSQLResult.cpp @ 161:2ccde9c7311b optimized-routes
added new optimized REST routes. this is a temporary work to try to speed up some routes (used by LRO). This way, we avoid another app to access the Orthanc DB and we skip the plugin SDK update for a very specific route
author | Alain Mazy <alain@mazy.be> |
---|---|
date | Fri, 10 Jul 2020 13:26:47 +0200 |
parents | 275e14f57f1e |
children | 0246923d4df9 |
rev | line source |
---|---|
0 | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
140
4cd7e45b671e
upgrade to year 2020
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
107
diff
changeset
|
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium |
0 | 6 * |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
21 | |
107
5765cc5fd268
reverted fix for OS X that breaks other targets
Sebastien Jodogne <s.jodogne@orthanc-labs.com>
parents:
105
diff
changeset
|
22 #include "PostgreSQLIncludes.h" // Must be the first |
105 | 23 #include "PostgreSQLResult.h" |
0 | 24 |
25 #include "../Common/BinaryStringValue.h" | |
14
9774802fd05f
PostgreSQLStorageArea working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
26 #include "../Common/FileValue.h" |
0 | 27 #include "../Common/Integer64Value.h" |
28 #include "../Common/NullValue.h" | |
29 #include "../Common/Utf8StringValue.h" | |
30 | |
157
275e14f57f1e
replacing deprecated std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
152
diff
changeset
|
31 #include <Compatibility.h> // For std::unique_ptr<> |
152 | 32 #include <OrthancException.h> |
33 #include <Logging.h> | |
34 #include <Endianness.h> | |
0 | 35 |
36 #include <cassert> | |
37 #include <boost/lexical_cast.hpp> | |
38 | |
39 | |
40 namespace OrthancDatabases | |
41 { | |
42 void PostgreSQLResult::Clear() | |
43 { | |
44 if (result_ != NULL) | |
45 { | |
46 PQclear(reinterpret_cast<PGresult*>(result_)); | |
47 result_ = NULL; | |
48 } | |
49 } | |
50 | |
51 | |
52 void PostgreSQLResult::CheckDone() | |
53 { | |
54 if (position_ >= PQntuples(reinterpret_cast<PGresult*>(result_))) | |
55 { | |
56 // We are at the end of the result set | |
57 Clear(); | |
58 } | |
59 } | |
60 | |
61 | |
62 void PostgreSQLResult::CheckColumn(unsigned int column, unsigned int /*Oid*/ expectedType) const | |
63 { | |
64 if (IsDone()) | |
65 { | |
66 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
67 } | |
68 | |
69 if (column >= static_cast<unsigned int>(PQnfields(reinterpret_cast<PGresult*>(result_)))) | |
70 { | |
71 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
72 } | |
73 | |
74 if (expectedType != 0 && | |
75 expectedType != PQftype(reinterpret_cast<PGresult*>(result_), column)) | |
76 { | |
77 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadParameterType); | |
78 } | |
79 } | |
80 | |
81 | |
82 PostgreSQLResult::PostgreSQLResult(PostgreSQLStatement& statement) : | |
83 position_(0), | |
84 database_(statement.GetDatabase()) | |
85 { | |
86 result_ = statement.Execute(); | |
87 assert(result_ != NULL); // An exception would have been thrown otherwise | |
88 | |
89 // This is the first call to "Next()" | |
90 if (PQresultStatus(reinterpret_cast<PGresult*>(result_)) == PGRES_TUPLES_OK) | |
91 { | |
92 CheckDone(); | |
93 columnsCount_ = static_cast<unsigned int>(PQnfields(reinterpret_cast<PGresult*>(result_))); | |
94 } | |
95 else | |
96 { | |
97 // This is not a SELECT request, we're done | |
98 Clear(); | |
99 columnsCount_ = 0; | |
100 } | |
101 } | |
102 | |
103 | |
46
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
14
diff
changeset
|
104 PostgreSQLResult::~PostgreSQLResult() |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
14
diff
changeset
|
105 { |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
14
diff
changeset
|
106 try |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
14
diff
changeset
|
107 { |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
14
diff
changeset
|
108 Clear(); |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
14
diff
changeset
|
109 } |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
14
diff
changeset
|
110 catch (Orthanc::OrthancException&) |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
14
diff
changeset
|
111 { |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
14
diff
changeset
|
112 // Ignore possible exceptions due to connection loss |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
14
diff
changeset
|
113 } |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
14
diff
changeset
|
114 } |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
14
diff
changeset
|
115 |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
14
diff
changeset
|
116 |
0 | 117 void PostgreSQLResult::Next() |
118 { | |
119 position_++; | |
120 CheckDone(); | |
121 } | |
122 | |
123 | |
124 bool PostgreSQLResult::IsNull(unsigned int column) const | |
125 { | |
126 CheckColumn(column, 0); | |
127 return PQgetisnull(reinterpret_cast<PGresult*>(result_), position_, column) != 0; | |
128 } | |
129 | |
130 | |
131 bool PostgreSQLResult::GetBoolean(unsigned int column) const | |
132 { | |
133 CheckColumn(column, BOOLOID); | |
134 assert(PQfsize(reinterpret_cast<PGresult*>(result_), column) == 1); | |
135 const uint8_t *v = reinterpret_cast<const uint8_t*> | |
136 (PQgetvalue(reinterpret_cast<PGresult*>(result_), position_, column)); | |
137 return (v[0] != 0); | |
138 } | |
139 | |
140 | |
141 int PostgreSQLResult::GetInteger(unsigned int column) const | |
142 { | |
143 CheckColumn(column, INT4OID); | |
144 assert(PQfsize(reinterpret_cast<PGresult*>(result_), column) == 4); | |
145 char *v = PQgetvalue(reinterpret_cast<PGresult*>(result_), position_, column); | |
146 return htobe32(*reinterpret_cast<int32_t*>(v)); | |
147 } | |
148 | |
149 | |
150 int64_t PostgreSQLResult::GetInteger64(unsigned int column) const | |
151 { | |
152 CheckColumn(column, INT8OID); | |
153 assert(PQfsize(reinterpret_cast<PGresult*>(result_), column) == 8); | |
154 char *v = PQgetvalue(reinterpret_cast<PGresult*>(result_), position_, column); | |
155 return htobe64(*reinterpret_cast<int64_t*>(v)); | |
156 } | |
157 | |
158 | |
159 std::string PostgreSQLResult::GetString(unsigned int column) const | |
160 { | |
161 CheckColumn(column, 0); | |
162 | |
163 Oid oid = PQftype(reinterpret_cast<PGresult*>(result_), column); | |
164 if (oid != TEXTOID && oid != VARCHAROID && oid != BYTEAOID) | |
165 { | |
166 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadParameterType); | |
167 } | |
168 | |
169 return std::string(PQgetvalue(reinterpret_cast<PGresult*>(result_), position_, column)); | |
170 } | |
171 | |
172 | |
173 void PostgreSQLResult::GetLargeObject(std::string& result, | |
174 unsigned int column) const | |
175 { | |
176 CheckColumn(column, OIDOID); | |
177 | |
178 Oid oid; | |
179 assert(PQfsize(reinterpret_cast<PGresult*>(result_), column) == sizeof(oid)); | |
180 | |
181 oid = *(const Oid*) PQgetvalue(reinterpret_cast<PGresult*>(result_), position_, column); | |
182 oid = ntohl(oid); | |
183 | |
184 PostgreSQLLargeObject::Read(result, database_, boost::lexical_cast<std::string>(oid)); | |
185 } | |
186 | |
187 | |
188 void PostgreSQLResult::GetLargeObject(void*& result, | |
189 size_t& size, | |
190 unsigned int column) const | |
191 { | |
192 CheckColumn(column, OIDOID); | |
193 | |
194 Oid oid; | |
195 assert(PQfsize(reinterpret_cast<PGresult*>(result_), column) == sizeof(oid)); | |
196 | |
197 oid = *(const Oid*) PQgetvalue(reinterpret_cast<PGresult*>(result_), position_, column); | |
198 oid = ntohl(oid); | |
199 | |
200 PostgreSQLLargeObject::Read(result, size, database_, boost::lexical_cast<std::string>(oid)); | |
201 } | |
202 | |
203 | |
204 IValue* PostgreSQLResult::GetValue(unsigned int column) const | |
205 { | |
206 if (IsNull(column)) | |
207 { | |
208 return new NullValue; | |
209 } | |
210 | |
211 Oid type = PQftype(reinterpret_cast<PGresult*>(result_), column); | |
212 | |
213 switch (type) | |
214 { | |
215 case BOOLOID: | |
216 // Convert Boolean values as integers | |
217 return new Integer64Value(GetBoolean(column) ? 1 : 0); | |
218 | |
219 case INT4OID: | |
220 return new Integer64Value(GetInteger(column)); | |
221 | |
222 case INT8OID: | |
223 return new Integer64Value(GetInteger64(column)); | |
224 | |
225 case TEXTOID: | |
226 case VARCHAROID: | |
227 return new Utf8StringValue(GetString(column)); | |
228 | |
229 case BYTEAOID: | |
230 return new BinaryStringValue(GetString(column)); | |
231 | |
232 case OIDOID: | |
233 { | |
157
275e14f57f1e
replacing deprecated std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
152
diff
changeset
|
234 std::unique_ptr<FileValue> value(new FileValue); |
0 | 235 GetLargeObject(value->GetContent(), column); |
236 return value.release(); | |
237 } | |
238 | |
239 default: | |
240 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
241 } | |
242 } | |
243 } |