package com.tesora.dve.tools.analyzer.sources; /* * #%L * Tesora Inc. * Database Virtualization Engine * %% * Copyright (C) 2011 - 2014 Tesora Inc. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ import java.io.PrintStream; import com.tesora.dve.sql.parser.ParserInvoker; import com.tesora.dve.sql.parser.ParserInvoker.LineInfo; import com.tesora.dve.sql.statement.dml.InsertIntoValuesStatement; import com.tesora.dve.tools.analyzer.Analyzer; import com.tesora.dve.tools.analyzer.AnalyzerSource; import com.tesora.dve.tools.analyzer.Emulator; import com.tesora.dve.tools.analyzer.SourcePosition; import com.tesora.dve.tools.analyzer.jaxb.DbAnalyzerCorpus; import com.tesora.dve.tools.analyzer.jaxb.InsertTuples; import com.tesora.dve.tools.analyzer.jaxb.StatementInsertIntoValuesType; import com.tesora.dve.tools.analyzer.jaxb.StatementNonInsertType; import com.tesora.dve.tools.analyzer.jaxb.StatementPopulationType; public class FrequenciesSource extends AnalyzerSource { public static final String FREQUENCY_TAG = "freq"; public static final String DB_TAG = "db"; private final DbAnalyzerCorpus freqs; private final String descr; public FrequenciesSource(DbAnalyzerCorpus sft) { this.freqs = sft; this.descr = "FrequenciesSource using corpus:" + sft.getDescription(); } @Override public String getDescription() { return descr; } @Override public void analyze(Analyzer a) throws Throwable { final boolean emulator = a instanceof Emulator; a.setSource(this); final ParserInvoker pi = a.getInvoker(); String cdb = null; int counter = 0; for (final StatementPopulationType spt : freqs.getPopulation()) { final LineInfo li = new LineInfo(++counter, null, 1); if ((cdb == null) || !cdb.equals(spt.getDb())) { cdb = spt.getDb(); pi.parseOneLine(li, "use " + cdb); } if (InsertIntoValuesStatement.class.getSimpleName().equals(spt.getKind())) { /* * Corpus files do not store INSERT values. * We can ignore INSERTs in the Emulator (replay) mode. * For other Analyzer types we rebuild the statements * replacing values with parameters. */ final StatementInsertIntoValuesType siivt = (StatementInsertIntoValuesType) spt; if (emulator) { a.onNotice(siivt.getInsertPrefix() + " VALUES (...)", new SourcePosition(li), "INSERT satement ignored"); continue; } final StringBuilder paramBuf = new StringBuilder(); paramBuf.append("("); for (int c = 0; c < siivt.getColWidth(); c++) { if (c > 0) { paramBuf.append(","); } paramBuf.append("?"); } paramBuf.append(")"); final String params = paramBuf.toString(); for (final InsertTuples it : siivt.getPopulation()) { li.addIntOption(FREQUENCY_TAG, it.getTuplePop()); li.addStringOption(DB_TAG, cdb); final StringBuilder buf = new StringBuilder(); buf.append(siivt.getInsertPrefix()).append(" VALUES "); for (int i = 0; i < it.getTupleCount(); i++) { if (i > 0) { buf.append(", "); } buf.append(params); } pi.parseOneLine(li, buf.toString()); } } else { li.addIntOption(FREQUENCY_TAG, spt.getFreq()); li.addStringOption(DB_TAG, cdb); final StatementNonInsertType snit = (StatementNonInsertType) spt; pi.parseOneLine(li, snit.getStmt()); } } a.onFinished(); a.setSource(null); } @Override public void closeSource() { // noop } @Override public SourcePosition convert(LineInfo li) { return new FrequenciesSourcePosition(li); } private static class FrequenciesSourcePosition extends SourcePosition { public FrequenciesSourcePosition(LineInfo li) { super(li); } @Override public void describe(PrintStream ps) { final Integer freqObj = getLineInfo().getIntOption(FREQUENCY_TAG); final int v = (freqObj == null ? 1 : freqObj.intValue()); final String db = getLineInfo().getStringOption(DB_TAG); ps.println(); ps.println("-- Found " + v + " times in corpus (on db " + db + ")--------------------------"); } } }