MCPcopy Create free account
hub / github.com/BaseXdb/basex / optCount

Method optCount

basex-core/src/main/java/org/basex/query/expr/Cmp.java:236–307  ·  view source on GitHub ↗

Tries to rewrite fn:count. @param op operator @param cc compilation context @return optimized or original expression @throws QueryException query exception

(final CmpOp op, final CompileContext cc)

Source from the content-addressed store, hash-verified

234 * @throws QueryException query exception
235 */
236 private Expr optCount(final CmpOp op, final CompileContext cc) throws QueryException {
237 final Expr expr1 = exprs[0];
238 if(!COUNT.is(expr1)) return this;
239
240 // distinct values checks
241 final Expr arg = expr1.arg(0), count = exprs[1];
242 if(COUNT.is(count)) {
243 final Expr carg = count.arg(0);
244 // count(E) = count(distinct-values(E))
245 if(DISTINCT_VALUES.is(carg) && arg.equals(carg.arg(0)))
246 return ((FnDistinctValues) carg).duplicates(op, cc);
247 // count(distinct-values(E)) = count(E)
248 if(DISTINCT_VALUES.is(arg) && arg.arg(0).equals(carg))
249 return ((FnDistinctValues) arg).duplicates(op.swap(), cc);
250 }
251 // count(distinct-values(E)) = int
252 if(DISTINCT_VALUES.is(arg) && count instanceof final Itr itr) {
253 final long size1 = arg.arg(0).size(), size2 = itr.itr();
254 if(size1 != -1 && size1 == size2) return ((FnDistinctValues) arg).duplicates(op.swap(), cc);
255 }
256
257 final ExprList args = new ExprList(3);
258 if(count instanceof final ANum num) {
259 final double cnt = num.dbl();
260 if(arg.seqType().zeroOrOne()) {
261 // count(ZeroOrOne) < 2 → true()
262 if(cnt > 1) {
263 return Bln.get(op.oneOf(CmpOp.LT, CmpOp.LE, CmpOp.NE));
264 }
265 // count(ZeroOrOne) < 1 → empty(ZeroOrOne)
266 // count(ZeroOrOne) = 1 → exists(ZeroOrOne)
267 // count(ZeroOrOne) <= 1 → true()
268 if(cnt == 1) {
269 return op.oneOf(CmpOp.NE, CmpOp.LT) ? cc.function(EMPTY, info, arg) :
270 op.oneOf(CmpOp.EQ, CmpOp.GE) ? cc.function(EXISTS, info, arg) :
271 Bln.get(op == CmpOp.LE);
272 }
273 }
274 final long[] counts = countRange(op, cnt);
275 // count(A) >= 0 → true()
276 if(counts == COUNT_TRUE) return Bln.TRUE;
277 if(counts == COUNT_FALSE) return Bln.FALSE;
278 // count(A) > 0 → exists(A)
279 if(counts == COUNT_EMPTY) return cc.function(EMPTY, info, arg);
280 if(counts == COUNT_EXISTS) return cc.function(EXISTS, info, arg);
281 // count(A) > 1 → util:within(A, 2)
282 // count(A) < 5 → util:within(A, 0, 4)
283 if(counts != null) {
284 for(final long c : counts) args.add(Itr.get(c));
285 }
286 } else if(op.oneOf(CmpOp.EQ, CmpOp.GE, CmpOp.LE)) {
287 final SeqType st2 = count.seqType();
288 if(st2.type.instanceOf(BasicType.INTEGER)) {
289 if(count instanceof final RangeSeq rs) {
290 // count(A) = 3 to 5 → util:within(A, 3, 5)
291 args.add(Itr.get(rs.min())).add(Itr.get(rs.max()));
292 } else if(st2.one() && (count instanceof VarRef || count instanceof ContextValue)) {
293 // count(A) = $c → util:within(A, $c)

Callers 1

optMethod · 0.95

Calls 15

argMethod · 0.95
equalsMethod · 0.95
seqTypeMethod · 0.95
getMethod · 0.95
countRangeMethod · 0.95
getMethod · 0.95
oneMethod · 0.95
zeroOrOneMethod · 0.80
isMethod · 0.65
sizeMethod · 0.65
oneOfMethod · 0.65
addMethod · 0.65

Tested by

no test coverage detected