@Override public boolean omit(LineInfo info, String sql) { globalCounters.increment(GlobalCounters.LINES); final StatementCounter sc = (StatementCounter) sink; if (CandidateParser.isInsert(sql)) { return false; } final CandidateParser cp = new CandidateParser(sql); if (cp.shrink()) { final String shrunk = cp.getShrunk(); final NonInsertEntry se = sc.byShrunk.get(shrunk); if (se != null) { globalCounters.increment(GlobalCounters.SHRINK_CACHE_HITS); sc.saveIntermediateCheckpoint(); se.bump(dmlBreakout, literalCounts); return true; } globalCounters.increment(GlobalCounters.SHRINK_CACHE_MISSES); } return false; }
@Override public void onStatement(String sql, SourcePosition sp, Statement s) throws Throwable { saveIntermediateCheckpoint(); globalCounters.increment(GlobalCounters.PROCESSED_STATEMENTS); if (s instanceof EmptyStatement) { globalCounters.increment(GlobalCounters.EMPTY_STATEMENTS); return; } if (!s.isDML()) { trackNonDML(s, sql); return; } final Emitter emitter = Singletons.require(HostService.class).getDBNative().getEmitter(); emitter.setOptions(emitOptions); final StringBuilder buf = new StringBuilder(); final DMLStatement dmls = (DMLStatement) s; final DMLCounters incCounter = lookupDMLCounter(dmls); if (dmls instanceof InsertIntoValuesStatement) { final InsertIntoValuesStatement iivs = (InsertIntoValuesStatement) dmls; emitter.emitInsertPrefix(tee.getPersistenceContext(), iivs, buf); final String prefix = buf.toString(); InsertEntry ie = inserts.get(prefix); if (ie == null) { final Database<?> db = dmls.getDatabase(tee.getPersistenceContext()); ie = new InsertEntry( corpus, prefix, iivs.getColumnSpecification().size(), iivs.getClass().getSimpleName(), (db == null ? null : db.getName().get())); inserts.put(prefix, ie); } ie.bump(iivs.getValues().size()); } else { emitter.emitStatement(tee.getPersistenceContext(), dmls, buf); final String p = buf.toString(); NonInsertEntry se = byParam.get(p); if (se == null) { String shrunk = null; int litCount = -1; if (!(dmls instanceof InsertIntoValuesStatement)) { final CandidateParser cp = new CandidateParser(sql); if (cp.shrink()) { shrunk = cp.getShrunk(); // also verify we get the same number of literals final ValueManager valueManager = tee.getPersistenceContext().getValueManager(); litCount = cp.getLiterals().size(); if (litCount != valueManager.getNumberOfLiterals()) { final ValueManager.CacheStatus cacheStatus = valueManager.getCacheStatus(); String reason; switch (cacheStatus) { case NOCACHE_DYNAMIC_FUNCTION: reason = "contains a non-cacheable dynamic function"; break; case NOCACHE_TOO_MANY_LITERALS: reason = "literal count exceeded configured max_cached_plan_literals"; break; case CACHEABLE: default: reason = "unknown"; } logError( sql, sp, "Mismatched literal size; parse=" + valueManager.getNumberOfLiterals() + "/shrink=" + litCount + " , reason=" + reason, false); } } else { logError(sql, sp, "Unable to shrink", false); } } final Database<?> db = dmls.getDatabase(tee.getPersistenceContext()); se = new NonInsertEntry( corpus, sql, dmls.getClass().getSimpleName(), (db == null ? null : db.getName().get()), litCount, incCounter); byParam.put(p, se); if (shrunk != null) { globalCounters.increment(GlobalCounters.SHRINK_CACHE_ADDS); byShrunk.put(shrunk, se); } } if (se.populationObject.getLiteralCount() >= 0) { literalCounts.sample(se.populationObject.getLiteralCount()); } se.bump(dmlBreakout, literalCounts); } }