comparison PostgreSQL/Plugins/PostgreSQLIndex.cpp @ 237:35598014f140

refactoring to remove GlobalProperties.cpp
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 08 Apr 2021 19:09:04 +0200
parents a4918d57435c
children a063bbf10a3e
comparison
equal deleted inserted replaced
236:d1d2edbbe6fb 237:35598014f140
58 { 58 {
59 return PostgreSQLDatabase::OpenDatabaseConnection(parameters_); 59 return PostgreSQLDatabase::OpenDatabaseConnection(parameters_);
60 } 60 }
61 61
62 62
63 void PostgreSQLIndex::ConfigureDatabase(IDatabase& database) 63 void PostgreSQLIndex::ConfigureDatabase(DatabaseManager& manager)
64 { 64 {
65 uint32_t expectedVersion = 6; 65 uint32_t expectedVersion = 6;
66 66
67 if (GetContext()) // "GetContext()" can possibly be NULL in the unit tests 67 if (GetContext()) // "GetContext()" can possibly be NULL in the unit tests
68 { 68 {
76 << "expecting the DB schema version " << expectedVersion 76 << "expecting the DB schema version " << expectedVersion
77 << ", but this plugin is only compatible with version 6"; 77 << ", but this plugin is only compatible with version 6";
78 throw Orthanc::OrthancException(Orthanc::ErrorCode_Plugin); 78 throw Orthanc::OrthancException(Orthanc::ErrorCode_Plugin);
79 } 79 }
80 80
81 PostgreSQLDatabase& db = dynamic_cast<PostgreSQLDatabase&>(database); 81 PostgreSQLDatabase& db = dynamic_cast<PostgreSQLDatabase&>(manager.GetDatabase());
82 82
83 if (parameters_.HasLock()) 83 if (parameters_.HasLock())
84 { 84 {
85 db.AdvisoryLock(POSTGRESQL_LOCK_INDEX); 85 db.AdvisoryLock(POSTGRESQL_LOCK_INDEX);
86 } 86 }
92 { 92 {
93 db.ClearAll(); 93 db.ClearAll();
94 } 94 }
95 95
96 { 96 {
97 PostgreSQLTransaction t(db, TransactionType_ReadWrite); 97 DatabaseManager::Transaction t(manager, TransactionType_ReadWrite);
98 98
99 if (!db.DoesTableExist("Resources")) 99 if (!t.DoesTableExist("Resources"))
100 { 100 {
101 std::string query; 101 std::string query;
102 102
103 Orthanc::EmbeddedResources::GetFileResource 103 Orthanc::EmbeddedResources::GetFileResource
104 (query, Orthanc::EmbeddedResources::POSTGRESQL_PREPARE_INDEX); 104 (query, Orthanc::EmbeddedResources::POSTGRESQL_PREPARE_INDEX);
105 db.Execute(query); 105 t.ExecuteMultiLines(query);
106 106
107 SetGlobalIntegerProperty(db, t, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabaseSchemaVersion, expectedVersion); 107 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabaseSchemaVersion, expectedVersion);
108 SetGlobalIntegerProperty(db, t, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabasePatchLevel, 1); 108 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabasePatchLevel, 1);
109 SetGlobalIntegerProperty(db, t, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_HasTrigramIndex, 0); 109 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_HasTrigramIndex, 0);
110 } 110 }
111 111
112 if (!db.DoesTableExist("Resources")) 112 if (!t.DoesTableExist("Resources"))
113 { 113 {
114 LOG(ERROR) << "Corrupted PostgreSQL database"; 114 LOG(ERROR) << "Corrupted PostgreSQL database";
115 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); 115 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
116 } 116 }
117 117
118 int version = 0; 118 int version = 0;
119 if (!LookupGlobalIntegerProperty(version, db, t, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabaseSchemaVersion) || 119 if (!LookupGlobalIntegerProperty(version, manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabaseSchemaVersion) ||
120 version != 6) 120 version != 6)
121 { 121 {
122 LOG(ERROR) << "PostgreSQL plugin is incompatible with database schema version: " << version; 122 LOG(ERROR) << "PostgreSQL plugin is incompatible with database schema version: " << version;
123 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); 123 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database);
124 } 124 }
125 125
126 int revision; 126 int revision;
127 if (!LookupGlobalIntegerProperty(revision, db, t, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabasePatchLevel)) 127 if (!LookupGlobalIntegerProperty(revision, manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabasePatchLevel))
128 { 128 {
129 revision = 1; 129 revision = 1;
130 SetGlobalIntegerProperty(db, t, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabasePatchLevel, revision); 130 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabasePatchLevel, revision);
131 } 131 }
132 132
133 if (revision != 1) 133 if (revision != 1)
134 { 134 {
135 LOG(ERROR) << "PostgreSQL plugin is incompatible with database schema revision: " << revision; 135 LOG(ERROR) << "PostgreSQL plugin is incompatible with database schema revision: " << revision;
138 138
139 t.Commit(); 139 t.Commit();
140 } 140 }
141 141
142 { 142 {
143 PostgreSQLTransaction t(db, TransactionType_ReadWrite); 143 DatabaseManager::Transaction t(manager, TransactionType_ReadWrite);
144 144
145 int hasTrigram = 0; 145 int hasTrigram = 0;
146 if (!LookupGlobalIntegerProperty(hasTrigram, db, t, MISSING_SERVER_IDENTIFIER, 146 if (!LookupGlobalIntegerProperty(hasTrigram, manager, MISSING_SERVER_IDENTIFIER,
147 Orthanc::GlobalProperty_HasTrigramIndex) || 147 Orthanc::GlobalProperty_HasTrigramIndex) ||
148 hasTrigram != 1) 148 hasTrigram != 1)
149 { 149 {
150 /** 150 /**
151 * Apply fix for performance issue (speed up wildcard search 151 * Apply fix for performance issue (speed up wildcard search
161 { 161 {
162 // We've observed 9 minutes on DB with 100000 studies 162 // We've observed 9 minutes on DB with 100000 studies
163 LOG(WARNING) << "Trying to enable trigram matching on the PostgreSQL database " 163 LOG(WARNING) << "Trying to enable trigram matching on the PostgreSQL database "
164 << "to speed up wildcard searches. This may take several minutes"; 164 << "to speed up wildcard searches. This may take several minutes";
165 165
166 db.Execute( 166 t.ExecuteMultiLines(
167 "CREATE EXTENSION IF NOT EXISTS pg_trgm; " 167 "CREATE EXTENSION IF NOT EXISTS pg_trgm; "
168 "CREATE INDEX DicomIdentifiersIndexValues2 ON DicomIdentifiers USING gin(value gin_trgm_ops);"); 168 "CREATE INDEX DicomIdentifiersIndexValues2 ON DicomIdentifiers USING gin(value gin_trgm_ops);");
169 169
170 SetGlobalIntegerProperty(db, t, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_HasTrigramIndex, 1); 170 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_HasTrigramIndex, 1);
171 LOG(WARNING) << "Trigram index has been created"; 171 LOG(WARNING) << "Trigram index has been created";
172 172
173 t.Commit(); 173 t.Commit();
174 } 174 }
175 catch (Orthanc::OrthancException&) 175 catch (Orthanc::OrthancException&)
185 t.Commit(); 185 t.Commit();
186 } 186 }
187 } 187 }
188 188
189 { 189 {
190 PostgreSQLTransaction t(db, TransactionType_ReadWrite); 190 DatabaseManager::Transaction t(manager, TransactionType_ReadWrite);
191 191
192 int property = 0; 192 int property = 0;
193 if (!LookupGlobalIntegerProperty(property, db, t, MISSING_SERVER_IDENTIFIER, 193 if (!LookupGlobalIntegerProperty(property, manager, MISSING_SERVER_IDENTIFIER,
194 Orthanc::GlobalProperty_HasCreateInstance) || 194 Orthanc::GlobalProperty_HasCreateInstance) ||
195 property != 2) 195 property != 2)
196 { 196 {
197 LOG(INFO) << "Installing the CreateInstance extension"; 197 LOG(INFO) << "Installing the CreateInstance extension";
198 198
199 if (property == 1) 199 if (property == 1)
200 { 200 {
201 // Drop older, experimental versions of this extension 201 // Drop older, experimental versions of this extension
202 db.Execute("DROP FUNCTION CreateInstance(" 202 t.ExecuteMultiLines("DROP FUNCTION CreateInstance("
203 "IN patient TEXT, IN study TEXT, IN series TEXT, in instance TEXT)"); 203 "IN patient TEXT, IN study TEXT, IN series TEXT, in instance TEXT)");
204 } 204 }
205 205
206 std::string query; 206 std::string query;
207 Orthanc::EmbeddedResources::GetFileResource 207 Orthanc::EmbeddedResources::GetFileResource
208 (query, Orthanc::EmbeddedResources::POSTGRESQL_CREATE_INSTANCE); 208 (query, Orthanc::EmbeddedResources::POSTGRESQL_CREATE_INSTANCE);
209 db.Execute(query); 209 t.ExecuteMultiLines(query);
210 210
211 SetGlobalIntegerProperty(db, t, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_HasCreateInstance, 2); 211 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_HasCreateInstance, 2);
212 } 212 }
213 213
214 214
215 if (!LookupGlobalIntegerProperty(property, db, t, MISSING_SERVER_IDENTIFIER, 215 if (!LookupGlobalIntegerProperty(property, manager, MISSING_SERVER_IDENTIFIER,
216 Orthanc::GlobalProperty_GetTotalSizeIsFast) || 216 Orthanc::GlobalProperty_GetTotalSizeIsFast) ||
217 property != 1) 217 property != 1)
218 { 218 {
219 LOG(INFO) << "Installing the FastTotalSize extension"; 219 LOG(INFO) << "Installing the FastTotalSize extension";
220 220
221 std::string query; 221 std::string query;
222 Orthanc::EmbeddedResources::GetFileResource 222 Orthanc::EmbeddedResources::GetFileResource
223 (query, Orthanc::EmbeddedResources::POSTGRESQL_FAST_TOTAL_SIZE); 223 (query, Orthanc::EmbeddedResources::POSTGRESQL_FAST_TOTAL_SIZE);
224 db.Execute(query); 224 t.ExecuteMultiLines(query);
225 225
226 SetGlobalIntegerProperty(db, t, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_GetTotalSizeIsFast, 1); 226 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_GetTotalSizeIsFast, 1);
227 } 227 }
228 228
229 229
230 // Installing this extension requires the "GlobalIntegers" table 230 // Installing this extension requires the "GlobalIntegers" table
231 // created by the "FastTotalSize" extension 231 // created by the "FastTotalSize" extension
232 property = 0; 232 property = 0;
233 if (!LookupGlobalIntegerProperty(property, db, t, MISSING_SERVER_IDENTIFIER, 233 if (!LookupGlobalIntegerProperty(property, manager, MISSING_SERVER_IDENTIFIER,
234 Orthanc::GlobalProperty_HasFastCountResources) || 234 Orthanc::GlobalProperty_HasFastCountResources) ||
235 property != 1) 235 property != 1)
236 { 236 {
237 LOG(INFO) << "Installing the FastCountResources extension"; 237 LOG(INFO) << "Installing the FastCountResources extension";
238 238
239 std::string query; 239 std::string query;
240 Orthanc::EmbeddedResources::GetFileResource 240 Orthanc::EmbeddedResources::GetFileResource
241 (query, Orthanc::EmbeddedResources::POSTGRESQL_FAST_COUNT_RESOURCES); 241 (query, Orthanc::EmbeddedResources::POSTGRESQL_FAST_COUNT_RESOURCES);
242 db.Execute(query); 242 t.ExecuteMultiLines(query);
243 243
244 SetGlobalIntegerProperty(db, t, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_HasFastCountResources, 1); 244 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_HasFastCountResources, 1);
245 } 245 }
246 246
247 247
248 // Installing this extension requires the "GlobalIntegers" table 248 // Installing this extension requires the "GlobalIntegers" table
249 // created by the "GetLastChangeIndex" extension 249 // created by the "GetLastChangeIndex" extension
250 property = 0; 250 property = 0;
251 if (!LookupGlobalIntegerProperty(property, db, t, MISSING_SERVER_IDENTIFIER, 251 if (!LookupGlobalIntegerProperty(property, manager, MISSING_SERVER_IDENTIFIER,
252 Orthanc::GlobalProperty_GetLastChangeIndex) || 252 Orthanc::GlobalProperty_GetLastChangeIndex) ||
253 property != 1) 253 property != 1)
254 { 254 {
255 LOG(INFO) << "Installing the GetLastChangeIndex extension"; 255 LOG(INFO) << "Installing the GetLastChangeIndex extension";
256 256
257 std::string query; 257 std::string query;
258 Orthanc::EmbeddedResources::GetFileResource 258 Orthanc::EmbeddedResources::GetFileResource
259 (query, Orthanc::EmbeddedResources::POSTGRESQL_GET_LAST_CHANGE_INDEX); 259 (query, Orthanc::EmbeddedResources::POSTGRESQL_GET_LAST_CHANGE_INDEX);
260 db.Execute(query); 260 t.ExecuteMultiLines(query);
261 261
262 SetGlobalIntegerProperty(db, t, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_GetLastChangeIndex, 1); 262 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_GetLastChangeIndex, 1);
263 }
264
265 t.Commit();
266 }
267
268
269 {
270 // New in release 4.0 to deal with multiple writers
271 DatabaseManager::Transaction t(manager, TransactionType_ReadWrite);
272
273 if (!t.DoesTableExist("ServerProperties"))
274 {
275 t.ExecuteMultiLines("CREATE TABLE ServerProperties(server VARCHAR(64) NOT NULL, "
276 "property INTEGER, value TEXT, PRIMARY KEY(server, property))");
263 } 277 }
264 278
265 t.Commit(); 279 t.Commit();
266 } 280 }
267 } 281 }