comparison PostgreSQL/UnitTests/PostgreSQLTests.cpp @ 0:7cea966b6829

initial commit
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 04 Jul 2018 08:16:29 +0200
parents
children 9e5e7a8314e0
comparison
equal deleted inserted replaced
-1:000000000000 0:7cea966b6829
1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2018 Osimis S.A., Belgium
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
22 #include <gtest/gtest.h>
23
24 #if defined(_WIN32)
25 // Fix redefinition of symbols on MinGW (these symbols are manually
26 // defined both by PostgreSQL and Google Test)
27 # undef S_IRGRP
28 # undef S_IROTH
29 # undef S_IRWXG
30 # undef S_IRWXO
31 # undef S_IWGRP
32 # undef S_IWOTH
33 # undef S_IXGRP
34 # undef S_IXOTH
35 #endif
36
37 #include "../../Framework/PostgreSQL/PostgreSQLTransaction.h"
38 #include "../../Framework/PostgreSQL/PostgreSQLResult.h"
39 #include "../../Framework/PostgreSQL/PostgreSQLLargeObject.h"
40
41 #include <Core/OrthancException.h>
42
43 #include <boost/lexical_cast.hpp>
44
45 using namespace OrthancDatabases;
46
47 extern const OrthancDatabases::PostgreSQLParameters globalParameters_;
48
49
50 static OrthancDatabases::PostgreSQLDatabase* CreateTestDatabase(bool clearAll)
51 {
52 std::auto_ptr<OrthancDatabases::PostgreSQLDatabase> pg
53 (new OrthancDatabases::PostgreSQLDatabase(globalParameters_));
54
55 pg->Open();
56
57 if (clearAll)
58 {
59 pg->ClearAll();
60 }
61
62 return pg.release();
63 }
64
65
66 static int64_t CountLargeObjects(PostgreSQLDatabase& db)
67 {
68 // Count the number of large objects in the DB
69 PostgreSQLTransaction t(db);
70 PostgreSQLStatement s(db, "SELECT COUNT(*) FROM pg_catalog.pg_largeobject", true);
71 PostgreSQLResult r(s);
72 return r.GetInteger64(0);
73 }
74
75
76 TEST(PostgreSQL, Basic)
77 {
78 std::auto_ptr<PostgreSQLDatabase> pg(CreateTestDatabase(true));
79
80 ASSERT_FALSE(pg->DoesTableExist("Test"));
81 pg->Execute("CREATE TABLE Test(name INTEGER, value BIGINT)");
82 ASSERT_TRUE(pg->DoesTableExist("Test"));
83
84 PostgreSQLStatement s(*pg, "INSERT INTO Test VALUES ($1,$2)", false);
85 s.DeclareInputInteger(0);
86 s.DeclareInputInteger64(1);
87
88 s.BindInteger(0, 43);
89 s.BindNull(0);
90 s.BindInteger(0, 42);
91 s.BindInteger64(1, -4242);
92 s.Run();
93
94 s.BindInteger(0, 43);
95 s.BindNull(1);
96 s.Run();
97
98 s.BindNull(0);
99 s.BindInteger64(1, 4444);
100 s.Run();
101
102 {
103 PostgreSQLStatement t(*pg, "SELECT name, value FROM Test ORDER BY name", true);
104 PostgreSQLResult r(t);
105
106 ASSERT_FALSE(r.IsDone());
107 ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(42, r.GetInteger(0));
108 ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ(-4242, r.GetInteger64(1));
109
110 r.Next();
111 ASSERT_FALSE(r.IsDone());
112 ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(43, r.GetInteger(0));
113 ASSERT_TRUE(r.IsNull(1));
114
115 r.Next();
116 ASSERT_FALSE(r.IsDone());
117 ASSERT_TRUE(r.IsNull(0));
118 ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ(4444, r.GetInteger64(1));
119
120 r.Next();
121 ASSERT_TRUE(r.IsDone());
122 }
123
124 {
125 PostgreSQLStatement t(*pg, "SELECT name, value FROM Test WHERE name=$1", true);
126 t.DeclareInputInteger(0);
127
128 {
129 t.BindInteger(0, 42);
130 PostgreSQLResult r(t);
131 ASSERT_FALSE(r.IsDone());
132 ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(42, r.GetInteger(0));
133 ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ(-4242, r.GetInteger64(1));
134
135 r.Next();
136 ASSERT_TRUE(r.IsDone());
137 }
138
139 {
140 t.BindInteger(0, 40);
141 PostgreSQLResult r(t);
142 ASSERT_TRUE(r.IsDone());
143 }
144 }
145
146 }
147
148
149 TEST(PostgreSQL, String)
150 {
151 std::auto_ptr<PostgreSQLDatabase> pg(CreateTestDatabase(true));
152
153 pg->Execute("CREATE TABLE Test(name INTEGER, value VARCHAR(40))");
154
155 PostgreSQLStatement s(*pg, "INSERT INTO Test VALUES ($1,$2)", false);
156 s.DeclareInputInteger(0);
157 s.DeclareInputString(1);
158
159 s.BindInteger(0, 42);
160 s.BindString(1, "Hello");
161 s.Run();
162
163 s.BindInteger(0, 43);
164 s.BindNull(1);
165 s.Run();
166
167 s.BindNull(0);
168 s.BindString(1, "");
169 s.Run();
170
171 {
172 PostgreSQLStatement t(*pg, "SELECT name, value FROM Test ORDER BY name", true);
173 PostgreSQLResult r(t);
174
175 ASSERT_FALSE(r.IsDone());
176 ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(42, r.GetInteger(0));
177 ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ("Hello", r.GetString(1));
178
179 r.Next();
180 ASSERT_FALSE(r.IsDone());
181 ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(43, r.GetInteger(0));
182 ASSERT_TRUE(r.IsNull(1));
183
184 r.Next();
185 ASSERT_FALSE(r.IsDone());
186 ASSERT_TRUE(r.IsNull(0));
187 ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ("", r.GetString(1));
188
189 r.Next();
190 ASSERT_TRUE(r.IsDone());
191 }
192 }
193
194
195 TEST(PostgreSQL, Transaction)
196 {
197 std::auto_ptr<PostgreSQLDatabase> pg(CreateTestDatabase(true));
198
199 pg->Execute("CREATE TABLE Test(name INTEGER, value INTEGER)");
200
201 {
202 PostgreSQLStatement s(*pg, "INSERT INTO Test VALUES ($1,$2)", false);
203 s.DeclareInputInteger(0);
204 s.DeclareInputInteger(1);
205 s.BindInteger(0, 42);
206 s.BindInteger(1, 4242);
207 s.Run();
208
209 {
210 PostgreSQLTransaction t(*pg);
211 s.BindInteger(0, 43);
212 s.BindInteger(1, 4343);
213 s.Run();
214 s.BindInteger(0, 44);
215 s.BindInteger(1, 4444);
216 s.Run();
217
218 PostgreSQLStatement u(*pg, "SELECT COUNT(*) FROM Test", true);
219 PostgreSQLResult r(u);
220 ASSERT_EQ(3, r.GetInteger64(0));
221
222 // No commit
223 }
224
225 {
226 PostgreSQLStatement u(*pg, "SELECT COUNT(*) FROM Test", true);
227 PostgreSQLResult r(u);
228 ASSERT_EQ(1, r.GetInteger64(0)); // Just "1" because of implicit rollback
229 }
230
231 {
232 PostgreSQLTransaction t(*pg);
233 s.BindInteger(0, 43);
234 s.BindInteger(1, 4343);
235 s.Run();
236 s.BindInteger(0, 44);
237 s.BindInteger(1, 4444);
238 s.Run();
239
240 {
241 PostgreSQLStatement u(*pg, "SELECT COUNT(*) FROM Test", true);
242 PostgreSQLResult r(u);
243 ASSERT_EQ(3, r.GetInteger64(0));
244
245 t.Commit();
246 ASSERT_THROW(t.Rollback(), Orthanc::OrthancException);
247 ASSERT_THROW(t.Commit(), Orthanc::OrthancException);
248 }
249 }
250
251 {
252 PostgreSQLStatement u(*pg, "SELECT COUNT(*) FROM Test", true);
253 PostgreSQLResult r(u);
254 ASSERT_EQ(3, r.GetInteger64(0));
255 }
256 }
257 }
258
259
260
261
262
263 TEST(PostgreSQL, LargeObject)
264 {
265 std::auto_ptr<PostgreSQLDatabase> pg(CreateTestDatabase(true));
266 ASSERT_EQ(0, CountLargeObjects(*pg));
267
268 pg->Execute("CREATE TABLE Test(name VARCHAR, value OID)");
269
270 // Automatically remove the large objects associated with the table
271 pg->Execute("CREATE RULE TestDelete AS ON DELETE TO Test DO SELECT lo_unlink(old.value);");
272
273 {
274 PostgreSQLStatement s(*pg, "INSERT INTO Test VALUES ($1,$2)", false);
275 s.DeclareInputString(0);
276 s.DeclareInputLargeObject(1);
277
278 for (int i = 0; i < 10; i++)
279 {
280 PostgreSQLTransaction t(*pg);
281
282 std::string value = "Value " + boost::lexical_cast<std::string>(i * 2);
283 PostgreSQLLargeObject obj(*pg, value);
284
285 s.BindString(0, "Index " + boost::lexical_cast<std::string>(i));
286 s.BindLargeObject(1, obj);
287 s.Run();
288
289 std::string tmp;
290 PostgreSQLLargeObject::Read(tmp, *pg, obj.GetOid());
291 ASSERT_EQ(value, tmp);
292
293 t.Commit();
294 }
295 }
296
297
298 ASSERT_EQ(10, CountLargeObjects(*pg));
299
300 {
301 PostgreSQLTransaction t(*pg);
302 PostgreSQLStatement s(*pg, "SELECT * FROM Test ORDER BY name DESC", true);
303 PostgreSQLResult r(s);
304
305 ASSERT_FALSE(r.IsDone());
306
307 ASSERT_FALSE(r.IsNull(0));
308 ASSERT_EQ("Index 9", r.GetString(0));
309
310 std::string data;
311 r.GetLargeObject(data, 1);
312 ASSERT_EQ("Value 18", data);
313
314 r.Next();
315 ASSERT_FALSE(r.IsDone());
316
317 //ASSERT_TRUE(r.IsString(0));
318 }
319
320
321 {
322 PostgreSQLTransaction t(*pg);
323 PostgreSQLStatement s(*pg, "DELETE FROM Test WHERE name='Index 9'", false);
324 s.Run();
325 t.Commit();
326 }
327
328
329 {
330 // Count the number of items in the DB
331 PostgreSQLTransaction t(*pg);
332 PostgreSQLStatement s(*pg, "SELECT COUNT(*) FROM Test", true);
333 PostgreSQLResult r(s);
334 ASSERT_EQ(9, r.GetInteger64(0));
335 }
336
337 ASSERT_EQ(9, CountLargeObjects(*pg));
338 }
339
340
341
342 #if ORTHANC_POSTGRESQL_STATIC == 1
343 # include <c.h> // PostgreSQL includes
344
345 TEST(PostgreSQL, Version)
346 {
347 ASSERT_STREQ("9.6.1", PG_VERSION);
348 }
349 #endif