@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;
    }
 private void trackOther(String sql) {
   StatementNonDMLType nd = null;
   final String shrunk = CandidateParser.shrinkAnything(sql);
   if (shrunk != null) {
     nd = otherByShrunk.get(shrunk);
   }
   if (nd == null) {
     nd = otherByInput.get(sql);
   }
   if (nd == null) {
     nd = new StatementNonDMLType();
     nd.setStmt(sql);
     otherByInput.put(sql, nd);
     if (shrunk != null) {
       otherByShrunk.put(shrunk, nd);
     }
     corpus.getNonDml().add(nd);
   }
   nd.setFreq(nd.getFreq() + 1);
 }
  @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);
    }
  }