|
16 | 16 | import static org.junit.Assert.assertTrue; |
17 | 17 |
|
18 | 18 | import java.io.IOException; |
| 19 | +import java.io.StringReader; |
19 | 20 | import java.nio.charset.StandardCharsets; |
20 | 21 |
|
21 | 22 | import org.apache.commons.io.IOUtils; |
@@ -85,7 +86,7 @@ public class QueryPlanRetrievalTest { |
85 | 86 | "\n" + |
86 | 87 | "\n" + |
87 | 88 | " {\n" + |
88 | | - " SELECT DISTINCT ?buyerrole ?countryID WHERE {\n" + |
| 89 | + " SELECT DISTINCT ?buyerrole ?countryID WHERE {\n" + |
89 | 90 | " ?org epo:hasBuyerType ?buytype .\n" + |
90 | 91 | " FILTER (?buytype != <http://publications.europa.eu/resource/authority/buyer-legal-type/eu-int-org> )\n" |
91 | 92 | + |
@@ -1153,4 +1154,174 @@ public void testArbitraryLengthPath() { |
1153 | 1154 |
|
1154 | 1155 | } |
1155 | 1156 |
|
| 1157 | + @Test |
| 1158 | + public void testHaving() { |
| 1159 | + |
| 1160 | + String expected = "Order (resultSizeActual=4)\n" + |
| 1161 | + " OrderElem (ASC)\n" + |
| 1162 | + " Var (name=nbTerm)\n" + |
| 1163 | + " OrderElem (ASC)\n" + |
| 1164 | + " Var (name=nameSjb1)\n" + |
| 1165 | + " OrderElem (ASC)\n" + |
| 1166 | + " Var (name=idTerm3)\n" + |
| 1167 | + " Projection (resultSizeActual=4)\n" + |
| 1168 | + " ├── ProjectionElemList\n" + |
| 1169 | + " │ ProjectionElem \"nameSjb1\"\n" + |
| 1170 | + " │ ProjectionElem \"idCN1\"\n" + |
| 1171 | + " │ ProjectionElem \"nbTerm\"\n" + |
| 1172 | + " │ ProjectionElem \"idTerm3\"\n" + |
| 1173 | + " └── Join (JoinIterator) (resultSizeActual=4)\n" + |
| 1174 | + " ╠══ Projection (new scope) (resultSizeActual=2) [left]\n" + |
| 1175 | + " ║ ├── ProjectionElemList\n" + |
| 1176 | + " ║ │ ProjectionElem \"nameSjb1\"\n" + |
| 1177 | + " ║ │ ProjectionElem \"idCN1\"\n" + |
| 1178 | + " ║ │ ProjectionElem \"nbTerm\"\n" + |
| 1179 | + " ║ └── Extension (resultSizeActual=2)\n" + |
| 1180 | + " ║ ╠══ Extension (resultSizeActual=2)\n" + |
| 1181 | + " ║ ║ Filter (resultSizeActual=2)\n" + |
| 1182 | + " ║ ║ ╠══ Compare (<)\n" + |
| 1183 | + " ║ ║ ║ Var (name=nbTerm)\n" + |
| 1184 | + " ║ ║ ║ ValueConstant (value=\"3\"^^<http://www.w3.org/2001/XMLSchema#integer>)\n" + |
| 1185 | + " ║ ║ ╚══ Group (nameSjb1, idCN1) (resultSizeActual=4)\n" + |
| 1186 | + " ║ ║ ├── LeftJoin (LeftJoinIterator) (resultSizeActual=11)\n" + |
| 1187 | + " ║ ║ │ ╠══ Join (JoinIterator) (resultSizeActual=11) [left]\n" + |
| 1188 | + " ║ ║ │ ║ ├── StatementPattern (costEstimate=54, resultSizeEstimate=4.00, resultSizeActual=4) [left]\n" |
| 1189 | + + |
| 1190 | + " ║ ║ │ ║ │ s: Var (name=idTerm1)\n" + |
| 1191 | + " ║ ║ │ ║ │ p: Var (name=_const_c6e40399_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#Terminal.ConductingEquipment, anonymous)\n" |
| 1192 | + + |
| 1193 | + " ║ ║ │ ║ │ o: Var (name=idSjb1)\n" + |
| 1194 | + " ║ ║ │ ║ └── Join (JoinIterator) (resultSizeActual=11) [right]\n" + |
| 1195 | + " ║ ║ │ ║ ╠══ StatementPattern (costEstimate=1.00, resultSizeEstimate=4.00, resultSizeActual=4) [left]\n" |
| 1196 | + + |
| 1197 | + " ║ ║ │ ║ ║ s: Var (name=idSjb1)\n" + |
| 1198 | + " ║ ║ │ ║ ║ p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n" |
| 1199 | + + |
| 1200 | + " ║ ║ │ ║ ║ o: Var (name=_const_6965b017_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#BusbarSection, anonymous)\n" |
| 1201 | + + |
| 1202 | + " ║ ║ │ ║ ╚══ Join (JoinIterator) (resultSizeActual=11) [right]\n" + |
| 1203 | + " ║ ║ │ ║ ├── StatementPattern (costEstimate=2.12, resultSizeEstimate=13, resultSizeActual=4) [left]\n" |
| 1204 | + + |
| 1205 | + " ║ ║ │ ║ │ s: Var (name=idTerm1)\n" + |
| 1206 | + " ║ ║ │ ║ │ p: Var (name=_const_4395d870_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#Terminal.ConnectivityNode, anonymous)\n" |
| 1207 | + + |
| 1208 | + " ║ ║ │ ║ │ o: Var (name=idCN1)\n" + |
| 1209 | + " ║ ║ │ ║ └── StatementPattern (costEstimate=4.24, resultSizeEstimate=13, resultSizeActual=11) [right]\n" |
| 1210 | + + |
| 1211 | + " ║ ║ │ ║ s: Var (name=idTermOfCN)\n" + |
| 1212 | + " ║ ║ │ ║ p: Var (name=_const_4395d870_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#Terminal.ConnectivityNode, anonymous)\n" |
| 1213 | + + |
| 1214 | + " ║ ║ │ ║ o: Var (name=idCN1)\n" + |
| 1215 | + " ║ ║ │ ╚══ StatementPattern (resultSizeEstimate=4.00, resultSizeActual=11) [right]\n" |
| 1216 | + + |
| 1217 | + " ║ ║ │ s: Var (name=idSjb1)\n" + |
| 1218 | + " ║ ║ │ p: Var (name=_const_857da984_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#IdentifiedObject.name, anonymous)\n" |
| 1219 | + + |
| 1220 | + " ║ ║ │ o: Var (name=nameSjb1)\n" + |
| 1221 | + " ║ ║ └── GroupElem (nbTerm)\n" + |
| 1222 | + " ║ ║ Count\n" + |
| 1223 | + " ║ ║ Var (name=idTermOfCN)\n" + |
| 1224 | + " ║ ╚══ ExtensionElem (nbTerm)\n" + |
| 1225 | + " ║ Count\n" + |
| 1226 | + " ║ Var (name=idTermOfCN)\n" + |
| 1227 | + " ╚══ StatementPattern (costEstimate=18, resultSizeEstimate=13, resultSizeActual=4) [right]\n" + |
| 1228 | + " s: Var (name=idTerm3)\n" + |
| 1229 | + " p: Var (name=_const_4395d870_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#Terminal.ConnectivityNode, anonymous)\n" |
| 1230 | + + |
| 1231 | + " o: Var (name=idCN1)\n"; |
| 1232 | + SailRepository sailRepository = new SailRepository(new MemoryStore()); |
| 1233 | + |
| 1234 | + try (SailRepositoryConnection connection = sailRepository.getConnection()) { |
| 1235 | + connection.add(new StringReader("@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" + |
| 1236 | + "@prefix cim: <http://iec.ch/TC57/2013/CIM-schema-cim16#> .\n" + |
| 1237 | + "@prefix : <http://example.org/> .\n" + |
| 1238 | + "\n" + |
| 1239 | + "# Busbar Sections\n" + |
| 1240 | + ":BusbarSection1 rdf:type cim:BusbarSection ;\n" + |
| 1241 | + " cim:IdentifiedObject.name \"Busbar1\" .\n" + |
| 1242 | + "\n" + |
| 1243 | + ":BusbarSection2 rdf:type cim:BusbarSection ;\n" + |
| 1244 | + " cim:IdentifiedObject.name \"Busbar2\" .\n" + |
| 1245 | + "\n" + |
| 1246 | + ":BusbarSection3 rdf:type cim:BusbarSection ;\n" + |
| 1247 | + " cim:IdentifiedObject.name \"Busbar3\" .\n" + |
| 1248 | + "\n" + |
| 1249 | + ":BusbarSection4 rdf:type cim:BusbarSection ;\n" + |
| 1250 | + " cim:IdentifiedObject.name \"Busbar4\" .\n" + |
| 1251 | + "\n" + |
| 1252 | + "# Connectivity Nodes\n" + |
| 1253 | + ":ConnectivityNode1 a cim:ConnectivityNode .\n" + |
| 1254 | + ":ConnectivityNode2 a cim:ConnectivityNode .\n" + |
| 1255 | + ":ConnectivityNode3 a cim:ConnectivityNode .\n" + |
| 1256 | + ":ConnectivityNode4 a cim:ConnectivityNode .\n" + |
| 1257 | + ":ConnectivityNode5 a cim:ConnectivityNode .\n" + |
| 1258 | + ":ConnectivityNode6 a cim:ConnectivityNode .\n" + |
| 1259 | + "\n" + |
| 1260 | + "# Terminals connected to ConnectivityNode1 (3 terminals)\n" + |
| 1261 | + ":Terminal1 cim:Terminal.ConductingEquipment :BusbarSection1 ;\n" + |
| 1262 | + " cim:Terminal.ConnectivityNode :ConnectivityNode1 .\n" + |
| 1263 | + "\n" + |
| 1264 | + ":Terminal2 cim:Terminal.ConnectivityNode :ConnectivityNode1 .\n" + |
| 1265 | + ":Terminal3 cim:Terminal.ConnectivityNode :ConnectivityNode1 .\n" + |
| 1266 | + "\n" + |
| 1267 | + "# Terminals connected to ConnectivityNode2 (2 terminals)\n" + |
| 1268 | + ":Terminal4 cim:Terminal.ConductingEquipment :BusbarSection2 ;\n" + |
| 1269 | + " cim:Terminal.ConnectivityNode :ConnectivityNode2 .\n" + |
| 1270 | + "\n" + |
| 1271 | + ":Terminal5 cim:Terminal.ConnectivityNode :ConnectivityNode2 .\n" + |
| 1272 | + "\n" + |
| 1273 | + "# Terminal connected to ConnectivityNode3 (1 terminal)\n" + |
| 1274 | + ":Terminal6 cim:Terminal.ConnectivityNode :ConnectivityNode3 .\n" + |
| 1275 | + "\n" + |
| 1276 | + "# Terminals connected to ConnectivityNode4 (4 terminals)\n" + |
| 1277 | + ":Terminal7 cim:Terminal.ConductingEquipment :BusbarSection3 ;\n" + |
| 1278 | + " cim:Terminal.ConnectivityNode :ConnectivityNode4 .\n" + |
| 1279 | + "\n" + |
| 1280 | + ":Terminal8 cim:Terminal.ConnectivityNode :ConnectivityNode4 .\n" + |
| 1281 | + ":Terminal9 cim:Terminal.ConnectivityNode :ConnectivityNode4 .\n" + |
| 1282 | + ":Terminal10 cim:Terminal.ConnectivityNode :ConnectivityNode4 .\n" + |
| 1283 | + "\n" + |
| 1284 | + "# Terminals connected to ConnectivityNode5 (2 terminals)\n" + |
| 1285 | + ":Terminal11 cim:Terminal.ConductingEquipment :BusbarSection4 ;\n" + |
| 1286 | + " cim:Terminal.ConnectivityNode :ConnectivityNode5 .\n" + |
| 1287 | + "\n" + |
| 1288 | + ":Terminal12 cim:Terminal.ConnectivityNode :ConnectivityNode5 .\n" + |
| 1289 | + "\n" + |
| 1290 | + "# Terminal connected to ConnectivityNode6 (1 terminal)\n" + |
| 1291 | + ":Terminal13 cim:Terminal.ConnectivityNode :ConnectivityNode6 ."), "", RDFFormat.TURTLE); |
| 1292 | + } catch (IOException e) { |
| 1293 | + throw new RuntimeException(e); |
| 1294 | + } |
| 1295 | + |
| 1296 | + try (SailRepositoryConnection connection = sailRepository.getConnection()) { |
| 1297 | + TupleQuery query = connection.prepareTupleQuery( |
| 1298 | + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n" + |
| 1299 | + "PREFIX cim: <http://iec.ch/TC57/2013/CIM-schema-cim16#>\n" + |
| 1300 | + "" + |
| 1301 | + "select ?nameSjb1 ?idCN1 ?nbTerm ?idTerm3\n" + |
| 1302 | + "where {\n" + |
| 1303 | + " {\n" + |
| 1304 | + " select ?nameSjb1 ?idCN1 (count(?idTermOfCN) as ?nbTerm)\n" + |
| 1305 | + " where {\n" + |
| 1306 | + " ?idSjb1 rdf:type cim:BusbarSection .\n" + |
| 1307 | + " ?idTerm1 cim:Terminal.ConductingEquipment ?idSjb1 .\n" + |
| 1308 | + " ?idTerm1 cim:Terminal.ConnectivityNode ?idCN1 .\n" + |
| 1309 | + " ?idTermOfCN cim:Terminal.ConnectivityNode ?idCN1\n" + |
| 1310 | + " OPTIONAL { ?idSjb1 cim:IdentifiedObject.name ?nameSjb1 . }\n" + |
| 1311 | + " }\n" + |
| 1312 | + " group by ?nameSjb1 ?idCN1\n" + |
| 1313 | + " having (?nbTerm < 3)\n" + |
| 1314 | + " }\n" + |
| 1315 | + " ?idTerm3 cim:Terminal.ConnectivityNode ?idCN1\n" + |
| 1316 | + "}\n" + |
| 1317 | + "order by ?nbTerm ?nameSjb1 ?idTerm3"); |
| 1318 | + String actual = query.explain(Explanation.Level.Executed).toString(); |
| 1319 | + |
| 1320 | + assertThat(actual).isEqualToNormalizingNewlines(expected); |
| 1321 | + |
| 1322 | + } |
| 1323 | + sailRepository.shutDown(); |
| 1324 | + |
| 1325 | + } |
| 1326 | + |
1156 | 1327 | } |
0 commit comments