comparison OrthancServer/SQLiteDatabaseWrapper.cpp @ 3025:039a9d262d64 db-changes

preparing to speed up find in databases
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 17 Dec 2018 17:05:28 +0100
parents d207f6ac1f86
children fd587cf51a89
comparison
equal deleted inserted replaced
3024:ef17a587e10d 3025:039a9d262d64
52 private: 52 private:
53 IDatabaseListener& listener_; 53 IDatabaseListener& listener_;
54 54
55 public: 55 public:
56 SignalFileDeleted(IDatabaseListener& listener) : 56 SignalFileDeleted(IDatabaseListener& listener) :
57 listener_(listener) 57 listener_(listener)
58 { 58 {
59 } 59 }
60 60
61 virtual const char* GetName() const 61 virtual const char* GetName() const
62 { 62 {
99 private: 99 private:
100 IDatabaseListener& listener_; 100 IDatabaseListener& listener_;
101 101
102 public: 102 public:
103 SignalResourceDeleted(IDatabaseListener& listener) : 103 SignalResourceDeleted(IDatabaseListener& listener) :
104 listener_(listener) 104 listener_(listener)
105 { 105 {
106 } 106 }
107 107
108 virtual const char* GetName() const 108 virtual const char* GetName() const
109 { 109 {
1199 1199
1200 bool SQLiteDatabaseWrapper::IsDiskSizeAbove(uint64_t threshold) 1200 bool SQLiteDatabaseWrapper::IsDiskSizeAbove(uint64_t threshold)
1201 { 1201 {
1202 return GetTotalCompressedSize() > threshold; 1202 return GetTotalCompressedSize() > threshold;
1203 } 1203 }
1204
1205
1206 namespace
1207 {
1208 class MainDicomTagsRegistry : public boost::noncopyable
1209 {
1210 private:
1211 class TagInfo
1212 {
1213 private:
1214 ResourceType level_;
1215 DicomTagType type_;
1216
1217 public:
1218 TagInfo()
1219 {
1220 }
1221
1222 TagInfo(ResourceType level,
1223 DicomTagType type) :
1224 level_(level),
1225 type_(type)
1226 {
1227 }
1228
1229 ResourceType GetLevel() const
1230 {
1231 return level_;
1232 }
1233
1234 DicomTagType GetType() const
1235 {
1236 return type_;
1237 }
1238 };
1239
1240 typedef std::map<DicomTag, TagInfo> Registry;
1241
1242
1243 Registry registry_;
1244
1245 void LoadTags(ResourceType level)
1246 {
1247 const DicomTag* tags = NULL;
1248 size_t size;
1249
1250 ServerToolbox::LoadIdentifiers(tags, size, level);
1251
1252 for (size_t i = 0; i < size; i++)
1253 {
1254 if (registry_.find(tags[i]) == registry_.end())
1255 {
1256 registry_[tags[i]] = TagInfo(level, DicomTagType_Identifier);
1257 }
1258 else
1259 {
1260 // These patient-level tags are copied in the study level
1261 assert(level == ResourceType_Study &&
1262 (tags[i] == DICOM_TAG_PATIENT_ID ||
1263 tags[i] == DICOM_TAG_PATIENT_NAME ||
1264 tags[i] == DICOM_TAG_PATIENT_BIRTH_DATE));
1265 }
1266 }
1267
1268 DicomMap::LoadMainDicomTags(tags, size, level);
1269
1270 for (size_t i = 0; i < size; i++)
1271 {
1272 if (registry_.find(tags[i]) == registry_.end())
1273 {
1274 registry_[tags[i]] = TagInfo(level, DicomTagType_Main);
1275 }
1276 }
1277 }
1278
1279 public:
1280 MainDicomTagsRegistry()
1281 {
1282 LoadTags(ResourceType_Patient);
1283 LoadTags(ResourceType_Study);
1284 LoadTags(ResourceType_Series);
1285 LoadTags(ResourceType_Instance);
1286 }
1287
1288 void LookupTag(ResourceType& level,
1289 DicomTagType& type,
1290 const DicomTag& tag) const
1291 {
1292 Registry::const_iterator it = registry_.find(tag);
1293
1294 if (it == registry_.end())
1295 {
1296 // Default values
1297 level = ResourceType_Instance;
1298 type = DicomTagType_Generic;
1299 }
1300 else
1301 {
1302 level = it->second.GetLevel();
1303 type = it->second.GetType();
1304 }
1305 }
1306 };
1307 }
1308
1309
1310 void SQLiteDatabaseWrapper::FindOneChildInstance(std::vector<std::string>& instancesId,
1311 const std::vector<std::string>& resourcesId,
1312 ResourceType level)
1313 {
1314 printf("ICI 3\n");
1315
1316 throw OrthancException(ErrorCode_NotImplemented);
1317 }
1318
1319
1320 void SQLiteDatabaseWrapper::ApplyLookupPatients(std::vector<std::string>& patientsId,
1321 const DatabaseLookup& lookup,
1322 size_t limit)
1323 {
1324 static const MainDicomTagsRegistry registry;
1325
1326 printf("ICI 1\n");
1327
1328 std::string heading = "SELECT patient.publicId FROM Resources AS patient ";
1329 std::string trailer;
1330 std::vector<std::string> parameters;
1331
1332 for (size_t i = 0; i < lookup.GetConstraintsCount(); i++)
1333 {
1334 const DicomTagConstraint& constraint = lookup.GetConstraint(i);
1335
1336 ResourceType level;
1337 DicomTagType type;
1338 registry.LookupTag(level, type, constraint.GetTag());
1339
1340 if (level != ResourceType_Patient)
1341 {
1342 throw OrthancException(ErrorCode_ParameterOutOfRange,
1343 "Not a patient-level tag: (" +
1344 lookup.GetConstraint(i).GetTag().Format() + ")");
1345 }
1346
1347 if (type == DicomTagType_Identifier ||
1348 type == DicomTagType_Main)
1349 {
1350 std::string table = (type == DicomTagType_Identifier ? "DicomIdentifiers" : "MainDicomTags");
1351 std::string tag = "t" + boost::lexical_cast<std::string>(i);
1352
1353 char on[128];
1354 sprintf(on, " %s ON %s.id = patient.internalId AND %s.tagGroup = 0x%04x AND %s.tagElement = 0x%04x ",
1355 tag.c_str(), tag.c_str(), tag.c_str(), constraint.GetTag().GetGroup(),
1356 tag.c_str(), constraint.GetTag().GetElement());
1357
1358 if (constraint.IsMandatory())
1359 {
1360 heading += "INNER JOIN " + table + std::string(on);
1361 }
1362 else
1363 {
1364 heading += "LEFT JOIN " + table + std::string(on);
1365 }
1366
1367 trailer += "AND (";
1368
1369 if (!constraint.IsMandatory())
1370 {
1371 trailer += tag + ".value IS NULL OR ";
1372 }
1373
1374 if (constraint.IsCaseSensitive())
1375 {
1376 trailer += tag + ".value ";
1377 }
1378 else
1379 {
1380 trailer += "lower(" + tag + ".value) ";
1381 }
1382
1383 switch (constraint.GetType())
1384 {
1385 case ConstraintType_Equal:
1386 parameters.push_back(constraint.GetValue());
1387
1388 if (constraint.IsCaseSensitive())
1389 {
1390 trailer += "= ?";
1391 }
1392 else
1393 {
1394 trailer += "= lower(?)";
1395 }
1396
1397 break;
1398
1399 default:
1400 throw OrthancException(ErrorCode_NotImplemented);
1401 }
1402
1403 trailer += ") ";
1404 }
1405 }
1406
1407 if (limit != 0)
1408 {
1409 trailer += " LIMIT " + boost::lexical_cast<std::string>(limit);
1410 }
1411
1412 std::string sql = (heading + "WHERE patient.resourceType = " +
1413 boost::lexical_cast<std::string>(ResourceType_Patient) + " " + trailer);
1414
1415 SQLite::Statement s(db_, sql);
1416
1417 printf("[%s]\n", sql.c_str());
1418
1419 for (size_t i = 0; i < parameters.size(); i++)
1420 {
1421 printf(" %d = '%s'\n", i, parameters[i].c_str());
1422 s.BindString(i, parameters[i]);
1423 }
1424
1425 patientsId.clear();
1426
1427 while (s.Step())
1428 {
1429 std::string publicId = s.ColumnString(0);
1430 patientsId.push_back(publicId);
1431 printf("** [%s]\n", publicId.c_str());
1432 }
1433
1434 throw OrthancException(ErrorCode_NotImplemented);
1435 }
1436
1437
1438 void SQLiteDatabaseWrapper::ApplyLookupResources(std::vector<std::string>& resourcesId,
1439 const DatabaseLookup& lookup,
1440 ResourceType queryLevel,
1441 size_t limit)
1442 {
1443 printf("ICI 2\n");
1444
1445 throw OrthancException(ErrorCode_NotImplemented);
1446 }
1204 } 1447 }