Mercurial > hg > orthanc-databases
comparison PostgreSQL/Plugins/PostgreSQLIndex.cpp @ 97:66fd0d587773
integration db-changes->mainline
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 21 Jan 2019 14:38:12 +0100 |
parents | e61587582cef |
children | cc3dc759c989 |
comparison
equal
deleted
inserted
replaced
91:1bd538a5a783 | 97:66fd0d587773 |
---|---|
33 | 33 |
34 namespace Orthanc | 34 namespace Orthanc |
35 { | 35 { |
36 // Some aliases for internal properties | 36 // Some aliases for internal properties |
37 static const GlobalProperty GlobalProperty_HasTrigramIndex = GlobalProperty_DatabaseInternal0; | 37 static const GlobalProperty GlobalProperty_HasTrigramIndex = GlobalProperty_DatabaseInternal0; |
38 static const GlobalProperty GlobalProperty_HasCreateInstance = GlobalProperty_DatabaseInternal1; | |
39 static const GlobalProperty GlobalProperty_HasFastCountResources = GlobalProperty_DatabaseInternal2; | |
40 static const GlobalProperty GlobalProperty_GetLastChangeIndex = GlobalProperty_DatabaseInternal3; | |
38 } | 41 } |
39 | 42 |
40 | 43 |
41 namespace OrthancDatabases | 44 namespace OrthancDatabases |
42 { | 45 { |
124 | 127 |
125 { | 128 { |
126 PostgreSQLTransaction t(*db); | 129 PostgreSQLTransaction t(*db); |
127 | 130 |
128 int hasTrigram = 0; | 131 int hasTrigram = 0; |
129 if (!LookupGlobalIntegerProperty(hasTrigram, *db, t, Orthanc::GlobalProperty_HasTrigramIndex) || | 132 if (!LookupGlobalIntegerProperty(hasTrigram, *db, t, |
133 Orthanc::GlobalProperty_HasTrigramIndex) || | |
130 hasTrigram != 1) | 134 hasTrigram != 1) |
131 { | 135 { |
132 /** | 136 /** |
133 * Apply fix for performance issue (speed up wildcard search | 137 * Apply fix for performance issue (speed up wildcard search |
134 * by using GIN trigrams). This implements the patch suggested | 138 * by using GIN trigrams). This implements the patch suggested |
160 << "not support trigram matching"; | 164 << "not support trigram matching"; |
161 LOG(WARNING) << "-> Consider installing the \"pg_trgm\" extension on the " | 165 LOG(WARNING) << "-> Consider installing the \"pg_trgm\" extension on the " |
162 << "PostgreSQL server, e.g. on Debian: sudo apt install postgresql-contrib"; | 166 << "PostgreSQL server, e.g. on Debian: sudo apt install postgresql-contrib"; |
163 } | 167 } |
164 } | 168 } |
169 else | |
170 { | |
171 t.Commit(); | |
172 } | |
173 } | |
174 | |
175 { | |
176 PostgreSQLTransaction t(*db); | |
177 | |
178 int property = 0; | |
179 if (!LookupGlobalIntegerProperty(property, *db, t, | |
180 Orthanc::GlobalProperty_HasCreateInstance) || | |
181 property != 2) | |
182 { | |
183 LOG(INFO) << "Installing the CreateInstance extension"; | |
184 | |
185 if (property == 1) | |
186 { | |
187 // Drop older, experimental versions of this extension | |
188 db->Execute("DROP FUNCTION CreateInstance(" | |
189 "IN patient TEXT, IN study TEXT, IN series TEXT, in instance TEXT)"); | |
190 } | |
191 | |
192 std::string query; | |
193 Orthanc::EmbeddedResources::GetFileResource | |
194 (query, Orthanc::EmbeddedResources::POSTGRESQL_CREATE_INSTANCE); | |
195 db->Execute(query); | |
196 | |
197 SetGlobalIntegerProperty(*db, t, Orthanc::GlobalProperty_HasCreateInstance, 2); | |
198 } | |
199 | |
200 | |
201 if (!LookupGlobalIntegerProperty(property, *db, t, | |
202 Orthanc::GlobalProperty_GetTotalSizeIsFast) || | |
203 property != 1) | |
204 { | |
205 LOG(INFO) << "Installing the FastTotalSize extension"; | |
206 | |
207 std::string query; | |
208 Orthanc::EmbeddedResources::GetFileResource | |
209 (query, Orthanc::EmbeddedResources::POSTGRESQL_FAST_TOTAL_SIZE); | |
210 db->Execute(query); | |
211 | |
212 SetGlobalIntegerProperty(*db, t, Orthanc::GlobalProperty_GetTotalSizeIsFast, 1); | |
213 } | |
214 | |
215 | |
216 // Installing this extension requires the "GlobalIntegers" table | |
217 // created by the "FastTotalSize" extension | |
218 property = 0; | |
219 if (!LookupGlobalIntegerProperty(property, *db, t, | |
220 Orthanc::GlobalProperty_HasFastCountResources) || | |
221 property != 1) | |
222 { | |
223 LOG(INFO) << "Installing the FastCountResources extension"; | |
224 | |
225 std::string query; | |
226 Orthanc::EmbeddedResources::GetFileResource | |
227 (query, Orthanc::EmbeddedResources::POSTGRESQL_FAST_COUNT_RESOURCES); | |
228 db->Execute(query); | |
229 | |
230 SetGlobalIntegerProperty(*db, t, Orthanc::GlobalProperty_HasFastCountResources, 1); | |
231 } | |
232 | |
233 | |
234 // Installing this extension requires the "GlobalIntegers" table | |
235 // created by the "GetLastChangeIndex" extension | |
236 property = 0; | |
237 if (!LookupGlobalIntegerProperty(property, *db, t, | |
238 Orthanc::GlobalProperty_GetLastChangeIndex) || | |
239 property != 1) | |
240 { | |
241 LOG(INFO) << "Installing the GetLastChangeIndex extension"; | |
242 | |
243 std::string query; | |
244 Orthanc::EmbeddedResources::GetFileResource | |
245 (query, Orthanc::EmbeddedResources::POSTGRESQL_GET_LAST_CHANGE_INDEX); | |
246 db->Execute(query); | |
247 | |
248 SetGlobalIntegerProperty(*db, t, Orthanc::GlobalProperty_GetLastChangeIndex, 1); | |
249 } | |
250 | |
251 t.Commit(); | |
165 } | 252 } |
166 | 253 |
167 return db.release(); | 254 return db.release(); |
168 } | 255 } |
169 | 256 |
193 | 280 |
194 statement.Execute(args); | 281 statement.Execute(args); |
195 | 282 |
196 return ReadInteger64(statement, 0); | 283 return ReadInteger64(statement, 0); |
197 } | 284 } |
285 | |
286 | |
287 uint64_t PostgreSQLIndex::GetTotalCompressedSize() | |
288 { | |
289 // Fast version if extension "./FastTotalSize.sql" is installed | |
290 uint64_t result; | |
291 | |
292 { | |
293 DatabaseManager::CachedStatement statement( | |
294 STATEMENT_FROM_HERE, GetManager(), | |
295 "SELECT value FROM GlobalIntegers WHERE key = 0"); | |
296 | |
297 statement.SetReadOnly(true); | |
298 statement.Execute(); | |
299 | |
300 result = static_cast<uint64_t>(ReadInteger64(statement, 0)); | |
301 } | |
302 | |
303 assert(result == IndexBackend::GetTotalCompressedSize()); | |
304 return result; | |
305 } | |
306 | |
307 | |
308 uint64_t PostgreSQLIndex::GetTotalUncompressedSize() | |
309 { | |
310 // Fast version if extension "./FastTotalSize.sql" is installed | |
311 uint64_t result; | |
312 | |
313 { | |
314 DatabaseManager::CachedStatement statement( | |
315 STATEMENT_FROM_HERE, GetManager(), | |
316 "SELECT value FROM GlobalIntegers WHERE key = 1"); | |
317 | |
318 statement.SetReadOnly(true); | |
319 statement.Execute(); | |
320 | |
321 result = static_cast<uint64_t>(ReadInteger64(statement, 0)); | |
322 } | |
323 | |
324 assert(result == IndexBackend::GetTotalUncompressedSize()); | |
325 return result; | |
326 } | |
327 | |
328 | |
329 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 | |
330 void PostgreSQLIndex::CreateInstance(OrthancPluginCreateInstanceResult& result, | |
331 const char* hashPatient, | |
332 const char* hashStudy, | |
333 const char* hashSeries, | |
334 const char* hashInstance) | |
335 { | |
336 DatabaseManager::CachedStatement statement( | |
337 STATEMENT_FROM_HERE, GetManager(), | |
338 "SELECT * FROM CreateInstance(${patient}, ${study}, ${series}, ${instance})"); | |
339 | |
340 statement.SetParameterType("patient", ValueType_Utf8String); | |
341 statement.SetParameterType("study", ValueType_Utf8String); | |
342 statement.SetParameterType("series", ValueType_Utf8String); | |
343 statement.SetParameterType("instance", ValueType_Utf8String); | |
344 | |
345 Dictionary args; | |
346 args.SetUtf8Value("patient", hashPatient); | |
347 args.SetUtf8Value("study", hashStudy); | |
348 args.SetUtf8Value("series", hashSeries); | |
349 args.SetUtf8Value("instance", hashInstance); | |
350 | |
351 statement.Execute(args); | |
352 | |
353 if (statement.IsDone() || | |
354 statement.GetResultFieldsCount() != 8) | |
355 { | |
356 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | |
357 } | |
358 | |
359 for (size_t i = 0; i < 8; i++) | |
360 { | |
361 statement.SetResultFieldType(i, ValueType_Integer64); | |
362 } | |
363 | |
364 result.isNewInstance = (ReadInteger64(statement, 3) == 1); | |
365 result.instanceId = ReadInteger64(statement, 7); | |
366 | |
367 if (result.isNewInstance) | |
368 { | |
369 result.isNewPatient = (ReadInteger64(statement, 0) == 1); | |
370 result.isNewStudy = (ReadInteger64(statement, 1) == 1); | |
371 result.isNewSeries = (ReadInteger64(statement, 2) == 1); | |
372 result.patientId = ReadInteger64(statement, 4); | |
373 result.studyId = ReadInteger64(statement, 5); | |
374 result.seriesId = ReadInteger64(statement, 6); | |
375 } | |
376 } | |
377 #endif | |
378 | |
379 | |
380 uint64_t PostgreSQLIndex::GetResourceCount(OrthancPluginResourceType resourceType) | |
381 { | |
382 // Optimized version thanks to the "FastCountResources.sql" extension | |
383 | |
384 assert(OrthancPluginResourceType_Patient == 0 && | |
385 OrthancPluginResourceType_Study == 1 && | |
386 OrthancPluginResourceType_Series == 2 && | |
387 OrthancPluginResourceType_Instance == 3); | |
388 | |
389 uint64_t result; | |
390 | |
391 { | |
392 DatabaseManager::CachedStatement statement( | |
393 STATEMENT_FROM_HERE, GetManager(), | |
394 "SELECT value FROM GlobalIntegers WHERE key = ${key}"); | |
395 | |
396 statement.SetParameterType("key", ValueType_Integer64); | |
397 | |
398 Dictionary args; | |
399 | |
400 // For an explanation of the "+ 2" below, check out "FastCountResources.sql" | |
401 args.SetIntegerValue("key", static_cast<int>(resourceType + 2)); | |
402 | |
403 statement.SetReadOnly(true); | |
404 statement.Execute(args); | |
405 | |
406 result = static_cast<uint64_t>(ReadInteger64(statement, 0)); | |
407 } | |
408 | |
409 assert(result == IndexBackend::GetResourceCount(resourceType)); | |
410 return result; | |
411 } | |
412 | |
413 | |
414 int64_t PostgreSQLIndex::GetLastChangeIndex() | |
415 { | |
416 DatabaseManager::CachedStatement statement( | |
417 STATEMENT_FROM_HERE, GetManager(), | |
418 "SELECT value FROM GlobalIntegers WHERE key = 6"); | |
419 | |
420 statement.SetReadOnly(true); | |
421 statement.Execute(); | |
422 | |
423 return ReadInteger64(statement, 0); | |
424 } | |
425 | |
426 | |
427 void PostgreSQLIndex::TagMostRecentPatient(int64_t patient) | |
428 { | |
429 // This behavior is implemented in "CreateInstance()", and no | |
430 // backward compatibility is necessary | |
431 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | |
432 } | |
198 } | 433 } |