comparison OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp @ 5568:b0b5546f1b9f find-refactoring

find refactor: re-use existing code. /studies?expand is almost fully implemented with new code
author Alain Mazy <am@orthanc.team>
date Thu, 25 Apr 2024 09:22:07 +0200
parents f3562c1a150d
children 5a13483d12c5
comparison
equal deleted inserted replaced
5567:f3562c1a150d 5568:b0b5546f1b9f
1139 } 1139 }
1140 } 1140 }
1141 1141
1142 1142
1143 virtual void ExecuteFind(FindResponse& response, 1143 virtual void ExecuteFind(FindResponse& response,
1144 const FindRequest& request) ORTHANC_OVERRIDE 1144 const FindRequest& request,
1145 { 1145 const std::vector<DatabaseConstraint>& normalized) ORTHANC_OVERRIDE
1146 #if 1 1146 {
1147 #if 0
1147 Compatibility::GenericFind find(*this); 1148 Compatibility::GenericFind find(*this);
1148 find.Execute(response, request); 1149 find.Execute(response, request);
1149 #else 1150 #else
1150 { 1151 {
1151 SQLite::Statement s(db_, SQLITE_FROM_HERE, "DROP TABLE IF EXISTS FilteredResourcesIds"); 1152 SQLite::Statement s(db_, SQLITE_FROM_HERE, "DROP TABLE IF EXISTS FilteredResourcesIds");
1152 s.Run(); 1153 s.Run();
1153 } 1154 }
1154 1155
1155 { 1156 {
1156 std::string sql; 1157
1157 // sql = "CREATE TEMPORARY TABLE FilteredResourcesIds AS "; 1158 LookupFormatter formatter;
1158 sql = ".."; 1159
1159 SQLite::Statement s(db_, SQLITE_FROM_HERE_DYNAMIC(sql), sql); 1160 std::string sqlLookup;
1160 } 1161 LookupFormatter::Apply(sqlLookup,
1162 formatter,
1163 normalized,
1164 request.GetLevel(),
1165 request.GetLabels(),
1166 request.GetLabelsConstraint(),
1167 (request.HasLimits() ? request.GetLimitsCount() : 0)); // TODO: handles since and count
1168
1169 if (request.IsResponseIdentifiersOnly())
1170 {
1171 SQLite::Statement statement(db_, SQLITE_FROM_HERE_DYNAMIC(sqlLookup), sqlLookup);
1172 formatter.Bind(statement);
1173
1174 while (statement.Step())
1175 {
1176 FindResponse::Item* item = new FindResponse::Item(request.GetResponseContent(),
1177 request.GetLevel(),
1178 statement.ColumnString(0));
1179 response.Add(item);
1180 }
1181 }
1182 else
1183 {
1184 std::map<std::string, FindResponse::Item*> items; // cache to the response items
1185
1186 {// first create a temporary table that with the filtered and ordered results
1187 sqlLookup = "CREATE TEMPORARY TABLE FilteredResourcesIds AS " + sqlLookup;
1188
1189 SQLite::Statement statement(db_, SQLITE_FROM_HERE_DYNAMIC(sqlLookup), sqlLookup);
1190 formatter.Bind(statement);
1191 statement.Run();
1192 }
1193
1194 {
1195 // create the response item with the public ids only
1196 SQLite::Statement statement(db_, SQLITE_FROM_HERE, "SELECT publicId FROM FilteredResourcesIds");
1197 formatter.Bind(statement);
1198
1199 while (statement.Step())
1200 {
1201 const std::string& resourceId = statement.ColumnString(0);
1202 FindResponse::Item* item = new FindResponse::Item(request.GetResponseContent(),
1203 request.GetLevel(),
1204 resourceId);
1205 items[resourceId] = item;
1206 response.Add(item);
1207 }
1208 }
1209
1210 // request Each response content through INNER JOIN with the temporary table
1211 if (request.HasResponseContent(FindRequest::ResponseContent_MainDicomTags))
1212 {
1213 // TODO-FIND: handle the case where we request tags from multiple levels
1214 SQLite::Statement statement(db_, SQLITE_FROM_HERE,
1215 "SELECT publicId, tagGroup, tagElement, value FROM MainDicomTags AS tags "
1216 " INNER JOIN FilteredResourcesIds ON tags.id = FilteredResourcesIds.internalId");
1217 formatter.Bind(statement);
1218
1219 while (statement.Step())
1220 {
1221 const std::string& resourceId = statement.ColumnString(0);
1222 items[resourceId]->AddDicomTag(statement.ColumnInt(1),
1223 statement.ColumnInt(2),
1224 statement.ColumnString(3), false);
1225 }
1226 }
1227
1228 if (request.HasResponseContent(FindRequest::ResponseContent_Children))
1229 {
1230 SQLite::Statement statement(db_, SQLITE_FROM_HERE,
1231 "SELECT filtered.publicId, childLevel.publicId AS childPublicId "
1232 "FROM Resources as currentLevel "
1233 " INNER JOIN FilteredResourcesIds filtered ON filtered.internalId = currentLevel.internalId "
1234 " INNER JOIN Resources childLevel ON childLevel.parentId = currentLevel.internalId");
1235 formatter.Bind(statement);
1236
1237 while (statement.Step())
1238 {
1239 const std::string& resourceId = statement.ColumnString(0);
1240 items[resourceId]->AddChild(statement.ColumnString(1));
1241 }
1242 }
1243
1244 if (request.HasResponseContent(FindRequest::ResponseContent_Parent))
1245 {
1246 SQLite::Statement statement(db_, SQLITE_FROM_HERE,
1247 "SELECT filtered.publicId, parentLevel.publicId AS parentPublicId "
1248 "FROM Resources as currentLevel "
1249 " INNER JOIN FilteredResourcesIds filtered ON filtered.internalId = currentLevel.internalId "
1250 " INNER JOIN Resources parentLevel ON currentLevel.parentId = parentLevel.internalId");
1251
1252 while (statement.Step())
1253 {
1254 const std::string& resourceId = statement.ColumnString(0);
1255 items[resourceId]->SetParent(statement.ColumnString(1));
1256 }
1257 }
1258
1259 if (request.HasResponseContent(FindRequest::ResponseContent_Metadata))
1260 {
1261 SQLite::Statement statement(db_, SQLITE_FROM_HERE,
1262 "SELECT filtered.publicId, metadata.type, metadata.value "
1263 "FROM Metadata "
1264 " INNER JOIN FilteredResourcesIds filtered ON filtered.internalId = Metadata.id");
1265
1266 while (statement.Step())
1267 {
1268 const std::string& resourceId = statement.ColumnString(0);
1269 items[resourceId]->AddMetadata(static_cast<MetadataType>(statement.ColumnInt(1)),
1270 statement.ColumnString(2));
1271 }
1272 }
1273
1274 if (request.HasResponseContent(FindRequest::ResponseContent_Labels))
1275 {
1276 SQLite::Statement statement(db_, SQLITE_FROM_HERE,
1277 "SELECT filtered.publicId, label "
1278 "FROM Labels "
1279 " INNER JOIN FilteredResourcesIds filtered ON filtered.internalId = Labels.id");
1280
1281 while (statement.Step())
1282 {
1283 const std::string& resourceId = statement.ColumnString(0);
1284 items[resourceId]->AddLabel(statement.ColumnString(1));
1285 }
1286 }
1287
1288 // TODO-FIND: implement other responseContent: ResponseContent_ChildInstanceId, ResponseContent_Attachments, (later: ResponseContent_IsStable)
1289
1290 }
1291 }
1292
1161 #endif 1293 #endif
1162 } 1294 }
1163 }; 1295 };
1164 1296
1165 1297