📄 database.java
字号:
/* MetricsAnalyzer * Copyright (C) 2002 TIKE (tike.mmm.fi) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston, MA 02111-1307, USA. */package metricsanalyzer.api;import java.sql.ResultSet;import java.sql.Timestamp;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import javax.swing.JOptionPane;import javax.swing.table.TableModel;import metricsanalyzer.api.data.Attr;import metricsanalyzer.api.data.Relation;import metricsanalyzer.detail.MetricsBuilder;import metricsanalyzer.detail.Relations;import metricsanalyzer.util.ArraysExt;import metricsanalyzer.util.StringBuilder;import metricsanalyzer.util.Strings;import metricsanalyzer.util.fun.ObjectToObject;import metricsanalyzer.util.fun.VoidToVoid;import metricsanalyzer.util.gui.AbstractCachedListModel;import metricsanalyzer.util.gui.ActionCancelledException;import metricsanalyzer.util.sql.JDBC;import metricsanalyzer.util.sql.ResultSetTable;import minijlisp.interpreter.Lisp;import minijlisp.util.Env;import minijlisp.util.Pair;import minijlisp.util.Symbol;/** * Provides access to a relational metrics database. */public class Database extends metricsanalyzer.util.sql.Database { public Database(String driver, String url, String user, String password, String basename) throws Exception { super(driver,url,user,password); this.basename = basename; } public class HistoryList extends AbstractCachedListModel { public class Entry { Entry(int idx, Timestamp timestamp, String name) { this.idx = idx; this.timestamp = timestamp; this.name = name; } public String toString() { return timestamp + " -- " + name; } public final int idx; public final Timestamp timestamp; public final String name; } protected void fillCache() throws Exception { for (ResultSet rs = query("SELECT * FROM " + withBasename(HISTORY_RELATION) + " ORDER BY " + IDX_ATTR.name + " DESC"); rs.next();) cache.add(new Entry(rs.getInt(1), rs.getTimestamp(2), rs.getString(3))); } public void add(final String name, final ImportList importList) throws Exception { updateCache(); final MetricsBuilder mb = doImport(importList); final Relation[] mergedRelations = mb.getMergedRelations(); final Map relationToTable = mb.getRelationToTable(); final int idx = getNextIdx(); final StrTable strTable = new StrTable(); final StringBuilder sb = new StringBuilder(); executeTransaction(new VoidToVoid() { public void with() throws Exception { update("INSERT INTO " + withBasename(HISTORY_RELATION) + " VALUES " + "( " + idx + ", " + JDBC.formatLit(new Timestamp(System.currentTimeMillis())) + ", '" + name + "'" + ")"); for (int i=0; i<mergedRelations.length; ++i) { update(formatCreateTable(mergedRelations, mergedRelations[i], idx)); MetricsBuilder.Table table = (MetricsBuilder.Table)relationToTable.get(mergedRelations[i]); String prefix = "INSERT INTO " + withBasenameAndIdx(table.relation, idx) + " VALUES ("; for (Iterator ite = table.keysToValues.entrySet().iterator(); ite.hasNext();) { Map.Entry entry = (Map.Entry)ite.next(); sb.p(prefix); appendCols( "", ", ", (Object[])entry.getKey(), table.relation.keys); appendCols(", ", ", ", (Object[])entry.getValue(), table.relation.values); sb.p(")"); update(sb.extract()); } } } private final void appendCols(String firstSep, String restSep, Object[] values, Attr[] attrs) throws Exception { for (int i=0; i<values.length; ++i) { sb.p(0==i ? firstSep : restSep); if ("shared_str".equals(attrs[i].type)) sb.p(strTable.put((String)values[i])); else sb.p(JDBC.formatLit(values[i])); } } }); updateCache(); } private int getNextIdx() { return 0 != cache.size() ? ((Entry)cache.get(0)).idx + 1 : 1; } public void remove(final int[] indices) throws Exception { executeTransaction(new VoidToVoid() { public void with() throws Exception { for (int ii=0; ii<indices.length; ++ii) { int idx = ((Entry)cache.get(indices[ii])).idx; update("DELETE FROM " + withBasename(HISTORY_RELATION) + " WHERE " + IDX_ATTR.name + " = " + idx); String[] tableNames = findTableNames(withBasenameAndIdx("%", idx)); for (int i=0; i<tableNames.length; ++i) update("DROP TABLE " + tableNames[i]); } } }); updateCache(); } } public TableModel[] executeQuery(String unpreparedQuery, int selectedIndex, int[] selectedIndices) throws Exception { return executeQueries(prepareQueries(unpreparedQuery, selectedIndex, selectedIndices)); } public void createTables() throws Exception { executeTransaction(new VoidToVoid() { public void with() throws Exception { for (int i=0; i<RELATIONS.length; ++i) update(formatCreateTable(RELATIONS, RELATIONS[i], -1)); } }); } public void dropTables() throws Exception { executeTransaction(new VoidToVoid() { public void with() throws Exception { if (0 != queryInt("SELECT COUNT(*) FROM " + withBasename(HISTORY_RELATION))) throw new ActionCancelledException("The history table is not empty. Remove all snapshots first.", "Error", JOptionPane.ERROR_MESSAGE); for (int i=0; i<RELATIONS.length; ++i) update("DROP TABLE " + withBasename(RELATIONS[i].name)); } }); } // *** Utility functions *** private TableModel[] executeQueries(String[] queries) throws Exception { TableModel[] results = new TableModel[queries.length]; for (int i=0; i<queries.length; ++i) { log(queries[i] + ";\n"); results[i] = new ResultSetTable(createStatement().executeQuery(queries[i])); } return results; } private String[] prepareQueries(String unpreparedQuery, int selectedIndex, int[] selectedIndices) throws Exception { StringBuffer result = new StringBuffer(); Lisp.eval(markup(unpreparedQuery, "<#", "#>"), createEnv(result, selectedIndex, selectedIndices)); return Strings.splitAndTrim(result.toString(), ';'); } private static MetricsBuilder doImport(ImportList importList) throws Exception { MetricsBuilder mb = new MetricsBuilder(importList.getRelations()); importList.doImport(mb); return mb; } private String formatCreateTable(Relation[] possibleSubSets, Relation relation, int idx) throws Exception { StringBuilder result = new StringBuilder(); result.p("CREATE TABLE ").p(withBasenameAndIdx(relation, idx)).p(" ("); appendWithSep(result, "\n ", "\n, ", relation.keys, FORMAT_TYPED_ATTR); appendWithSep(result, "\n, ", "\n, ", relation.values, FORMAT_TYPED_ATTR); result.p("\n, PRIMARY KEY ("); appendWithSep(result, "", ", ", relation.keys, FORMAT_UNTYPED_ATTR); result.p(")"); appendForeignKeys(result, possibleSubSets, relation, idx); if (possibleSubSets != RELATIONS) appendForeignKeys(result, RELATIONS, relation, -1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -