import static java.util.Collections.emptyList;
import static java.util.Collections.nCopies;
import static javax.swing.KeyStroke.getKeyStroke;
+import static net.argius.stew.text.TextUtilities.join;
import static net.argius.stew.ui.window.AnyActionKey.copy;
import static net.argius.stew.ui.window.AnyActionKey.refresh;
import static net.argius.stew.ui.window.DatabaseInfoTree.ActionKey.*;
import static net.argius.stew.ui.window.WindowOutputProcessor.showInformationMessageDialog;
-
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.List;
-
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
-
import net.argius.stew.*;
-import net.argius.stew.text.*;
/**
* The Database Information Tree is a tree pane that provides to
private static final Logger log = Logger.getLogger(DatabaseInfoTree.class);
private static final ResourceManager res = ResourceManager.getInstance(DatabaseInfoTree.class);
+ private static final String TABLE_TYPE_TABLE = "TABLE";
+ private static final String TABLE_TYPE_VIEW = "VIEW";
+ private static final String TABLE_TYPE_INDEX = "INDEX";
+ private static final String TABLE_TYPE_SEQUENCE = "SEQUENCE";
+ private static final List<String> DEFAULT_TABLE_TYPES = //
+ Arrays.asList(TABLE_TYPE_TABLE, TABLE_TYPE_VIEW, TABLE_TYPE_INDEX, TABLE_TYPE_SEQUENCE);
+
static volatile boolean showColumnNumber;
private Connector currentConnector;
@Override
public void anyActionPerformed(AnyActionEvent ev) {
log.atEnter("anyActionPerformed", ev);
- if (ev.isAnyOf(copySimpleName)) {
+ if (ev.isAnyOf(copy)) {
+ final String cmd = ev.getActionCommand();
+ Action action = getActionMap().get(cmd);
+ if (action != null) {
+ action.actionPerformed(new ActionEvent(this, 1001, cmd));
+ }
+ } else if (ev.isAnyOf(copySimpleName)) {
copySimpleName();
} else if (ev.isAnyOf(copyFullName)) {
copyFullName();
refresh((InfoNode)path.getLastPathComponent());
}
} else if (ev.isAnyOf(generateWherePhrase)) {
- TreePath[] paths = getSelectionPaths();
- List<ColumnNode> columns = collectColumnNode(paths);
- String[] tableNames = collectTableName(columns);
- if (tableNames.length != 0) {
- insertTextToTextArea(generateEquivalentJoinClause(columns));
+ List<ColumnNode> columnNodes = new ArrayList<ColumnNode>();
+ for (TreeNode node : getSelectionNodes()) {
+ if (node instanceof ColumnNode) {
+ columnNodes.add((ColumnNode)node);
+ }
+ }
+ final String phrase = generateEquivalentJoinClause(columnNodes);
+ if (phrase.length() > 0) {
+ insertTextIntoTextArea(addCommas(phrase));
}
} else if (ev.isAnyOf(generateSelectPhrase)) {
- TreePath[] paths = getSelectionPaths();
- List<ColumnNode> columns = collectColumnNode(paths);
- String[] tableNames = collectTableName(columns);
- if (tableNames.length != 0) {
- List<String> columnNames = new ArrayList<String>();
- final boolean one = tableNames.length == 1;
- for (ColumnNode node : columns) {
- columnNames.add(one ? node.getName() : node.getNodeFullName());
- }
- final String columnString = (columnNames.isEmpty())
- ? "*"
- : TextUtilities.join(", ", columnNames);
- final String tableString = joinByComma(Arrays.asList(tableNames));
- insertTextToTextArea(String.format("SELECT %s FROM %s WHERE ", columnString, tableString));
- }
- } else if (ev.isAnyOf(generateUpdateStatement)) {
- TreePath[] paths = getSelectionPaths();
- List<ColumnNode> columns = collectColumnNode(paths);
- String[] tableNames = collectTableName(columns);
- if (tableNames.length == 0) {
- return;
- }
- if (tableNames.length != 1 || columns.isEmpty()) {
- showInformationMessageDialog(this, res.get("e.enables-select-just-1-table"), "");
- } else {
- final String tableName = tableNames[0];
- List<String> columnExpressions = new ArrayList<String>();
- for (ColumnNode columnNode : columns) {
- columnExpressions.add(columnNode.getName() + "=?");
+ final String phrase = generateSelectPhrase(getSelectionNodes());
+ if (phrase.length() > 0) {
+ insertTextIntoTextArea(phrase + " WHERE ");
+ }
+ } else if (ev.isAnyOf(generateUpdateStatement, generateInsertStatement)) {
+ final boolean isInsert = ev.isAnyOf(generateInsertStatement);
+ try {
+ final String phrase = generateUpdateOrInsertPhrase(getSelectionNodes(), isInsert);
+ if (phrase.length() > 0) {
+ if (isInsert) {
+ insertTextIntoTextArea(addCommas(phrase));
+ } else {
+ insertTextIntoTextArea(phrase + " WHERE ");
+ }
}
- insertTextToTextArea(String.format("UPDATE %s SET %s WHERE ",
- tableName,
- joinByComma(columnExpressions)));
+ } catch (IllegalArgumentException ex) {
+ showInformationMessageDialog(this, ex.getMessage(), "");
}
- } else if (ev.isAnyOf(generateInsertStatement)) {
- generateInsertStatement();
} else if (ev.isAnyOf(jumpToColumnByName)) {
jumpToColumnByName();
} else if (ev.isAnyOf(toggleShowColumnNumber)) {
log.atExit("anyActionPerformed");
}
- private void insertTextToTextArea(String s) {
- AnyActionEvent ev = new AnyActionEvent(this, ConsoleTextArea.ActionKey.insertText, s);
- anyActionListener.anyActionPerformed(ev);
+ @Override
+ public TreePath[] getSelectionPaths() {
+ TreePath[] a = super.getSelectionPaths();
+ if (a == null) {
+ return new TreePath[0];
+ }
+ return a;
}
- private static String joinByComma(List<?> a) {
- StringBuilder buffer = new StringBuilder();
- for (int i = 0, n = a.size(); i < n; i++) {
- if (i != 0) {
- buffer.append(", ");
- }
- buffer.append(a.get(i));
+ List<TreeNode> getSelectionNodes() {
+ List<TreeNode> a = new ArrayList<TreeNode>();
+ for (TreePath path : getSelectionPaths()) {
+ a.add((TreeNode)path.getLastPathComponent());
}
- return buffer.toString();
+ return a;
+ }
+
+ private void insertTextIntoTextArea(String s) {
+ AnyActionEvent ev = new AnyActionEvent(this, ConsoleTextArea.ActionKey.insertText, s);
+ anyActionListener.anyActionPerformed(ev);
}
private void copySimpleName() {
ClipboardHelper.setStrings(names);
}
- private static List<ColumnNode> collectColumnNode(TreePath[] paths) {
- List<ColumnNode> a = new ArrayList<ColumnNode>();
- if (paths != null) {
- for (TreePath path : paths) {
- InfoNode node = (InfoNode)path.getLastPathComponent();
- if (node instanceof ColumnNode) {
- ColumnNode columnNode = (ColumnNode)node;
- a.add(columnNode);
- }
- }
+ private void jumpToColumnByName() {
+ TreePath[] paths = getSelectionPaths();
+ if (paths == null || paths.length == 0) {
+ return;
+ }
+ final TreePath path = paths[0];
+ Object o = path.getLastPathComponent();
+ if (o instanceof ColumnNode) {
+ ColumnNode node = (ColumnNode)o;
+ AnyActionEvent ev = new AnyActionEvent(this,
+ ResultSetTable.ActionKey.jumpToColumn,
+ node.getName());
+ anyActionListener.anyActionPerformed(ev);
}
- return a;
}
- private static List<TableNode> collectTableNode(TreePath[] paths) {
- List<TableNode> a = new ArrayList<TableNode>();
- if (paths != null) {
- for (TreePath path : paths) {
- InfoNode node = (InfoNode)path.getLastPathComponent();
- if (node instanceof TableNode) {
- TableNode columnNode = (TableNode)node;
- a.add(columnNode);
- }
+ private static String addCommas(String phrase) {
+ int c = 0;
+ for (final char ch : phrase.toCharArray()) {
+ if (ch == '?') {
+ ++c;
}
}
- return a;
+ if (c >= 1) {
+ return String.format("%s;%s", phrase, join("", nCopies(c - 1, ",")));
+ }
+ return phrase;
}
- private static String[] collectTableName(List<ColumnNode> columnNodes) {
+ static String generateEquivalentJoinClause(List<ColumnNode> nodes) {
+ if (nodes.isEmpty()) {
+ return "";
+ }
Set<String> tableNames = new LinkedHashSet<String>();
- for (final ColumnNode node : columnNodes) {
- tableNames.add(node.getTableNode().getNodeFullName());
+ ListMap columnMap = new ListMap();
+ for (ColumnNode node : nodes) {
+ final String tableName = node.getTableNode().getNodeFullName();
+ final String columnName = node.getName();
+ tableNames.add(tableName);
+ columnMap.add(columnName, String.format("%s.%s", tableName, columnName));
}
- return tableNames.toArray(new String[tableNames.size()]);
- }
-
- private void generateInsertStatement() {
- TreePath[] paths = getSelectionPaths();
- List<ColumnNode> columns = collectColumnNode(paths);
- final String tableName;
- final int tableCount;
- if (columns.isEmpty()) {
- List<TableNode> tables = collectTableNode(paths);
- if (tables.isEmpty()) {
- return;
- }
- TableNode tableNode = tables.get(0);
- if (tableNode.getChildCount() == 0) {
- showInformationMessageDialog(this,
- res.get("i.can-only-use-after-tablenode-expanded"),
- "");
- return;
+ assert tableNames.size() >= 1;
+ List<String> expressions = new ArrayList<String>();
+ if (tableNames.size() == 1) {
+ for (ColumnNode node : nodes) {
+ expressions.add(String.format("%s=?", node.getName()));
}
- @SuppressWarnings("unchecked")
- List<ColumnNode> list = Collections.list(tableNode.children());
- columns.addAll(list);
- tableName = tableNode.getNodeFullName();
- tableCount = tables.size();
- } else {
- String[] tableNames = collectTableName(columns);
- tableCount = tableNames.length;
- if (tableCount == 0) {
- return;
+ } else { // size >= 2
+ List<String> expressions2 = new ArrayList<String>();
+ for (Entry<String, List<String>> entry : columnMap.entrySet()) {
+ List<String> a = entry.getValue();
+ final int n = a.size();
+ assert n >= 1;
+ expressions2.add(String.format("%s=?", a.get(0)));
+ if (n >= 2) {
+ for (int i = 0; i < n; i++) {
+ for (int j = i + 1; j < n; j++) {
+ expressions.add(String.format("%s=%s", a.get(i), a.get(j)));
+ }
+ }
+ }
}
- tableName = tableNames[0];
+ expressions.addAll(expressions2);
}
- if (tableCount != 1) {
- showInformationMessageDialog(this, res.get("e.enables-select-just-1-table"), "");
- return;
+ return String.format("%s", join(" AND ", expressions));
+ }
+
+ static String generateSelectPhrase(List<TreeNode> nodes) {
+ Set<String> tableNames = new LinkedHashSet<String>();
+ ListMap columnMap = new ListMap();
+ for (TreeNode node : nodes) {
+ if (node instanceof TableNode) {
+ final String tableFullName = ((TableNode)node).getNodeFullName();
+ tableNames.add(tableFullName);
+ columnMap.add(tableFullName);
+ } else if (node instanceof ColumnNode) {
+ ColumnNode cn = (ColumnNode)node;
+ final String tableFullName = cn.getTableNode().getNodeFullName();
+ tableNames.add(tableFullName);
+ columnMap.add(tableFullName, cn.getNodeFullName());
+ }
+ }
+ if (tableNames.isEmpty()) {
+ return "";
}
List<String> columnNames = new ArrayList<String>();
- for (ColumnNode node : columns) {
- columnNames.add(node.getName());
+ if (tableNames.size() == 1) {
+ List<String> a = new ArrayList<String>();
+ for (TreeNode node : nodes) {
+ if (node instanceof ColumnNode) {
+ ColumnNode cn = (ColumnNode)node;
+ a.add(cn.getName());
+ }
+ }
+ if (a.isEmpty()) {
+ columnNames.add("*");
+ } else {
+ columnNames.addAll(a);
+ }
+ } else { // size >= 2
+ for (Entry<String, List<String>> entry : columnMap.entrySet()) {
+ final List<String> columnsInTable = entry.getValue();
+ if (columnsInTable.isEmpty()) {
+ columnNames.add(entry.getKey() + ".*");
+ } else {
+ columnNames.addAll(columnsInTable);
+ }
+ }
}
- final int columnCount = columnNames.size();
- insertTextToTextArea(String.format("INSERT INTO %s (%s) VALUES (%s);%s",
- tableName,
- joinByComma(columnNames),
- joinByComma(nCopies(columnCount, "?")),
- TextUtilities.join(",", nCopies(columnCount, ""))));
+ return String.format("SELECT %s FROM %s", join(", ", columnNames), join(", ", tableNames));
}
- private void jumpToColumnByName() {
- TreePath[] paths = getSelectionPaths();
- if (paths == null || paths.length == 0) {
- return;
+ static String generateUpdateOrInsertPhrase(List<TreeNode> nodes, boolean isInsert) {
+ Set<String> tableNames = new LinkedHashSet<String>();
+ ListMap columnMap = new ListMap();
+ for (TreeNode node : nodes) {
+ if (node instanceof TableNode) {
+ final String tableFullName = ((TableNode)node).getNodeFullName();
+ tableNames.add(tableFullName);
+ columnMap.add(tableFullName);
+ } else if (node instanceof ColumnNode) {
+ ColumnNode cn = (ColumnNode)node;
+ final String tableFullName = cn.getTableNode().getNodeFullName();
+ tableNames.add(tableFullName);
+ columnMap.add(tableFullName, cn.getName());
+ }
+ }
+ if (tableNames.isEmpty()) {
+ return "";
}
- final TreePath path = paths[0];
- Object o = path.getLastPathComponent();
- if (o instanceof ColumnNode) {
- ColumnNode node = (ColumnNode)o;
- AnyActionEvent ev = new AnyActionEvent(this,
- ResultSetTable.ActionKey.jumpToColumn,
- node.getName());
- anyActionListener.anyActionPerformed(ev);
+ if (tableNames.size() >= 2) {
+ throw new IllegalArgumentException(res.get("e.enables-select-just-1-table"));
+ }
+ final String tableName = join("", tableNames);
+ List<String> columnsInTable = columnMap.get(tableName);
+ if (columnsInTable.isEmpty()) {
+ if (isInsert) {
+ List<TableNode> tableNodes = new ArrayList<TableNode>();
+ for (TreeNode node : nodes) {
+ if (node instanceof TableNode) {
+ tableNodes.add((TableNode)node);
+ break;
+ }
+ }
+ TableNode tableNode = tableNodes.get(0);
+ if (tableNode.getChildCount() == 0) {
+ throw new IllegalArgumentException(res.get("i.can-only-use-after-tablenode-expanded"));
+ }
+ for (int i = 0, n = tableNode.getChildCount(); i < n; i++) {
+ ColumnNode child = (ColumnNode)tableNode.getChildAt(i);
+ columnsInTable.add(child.getName());
+ }
+ } else {
+ return "";
+ }
}
+ final String phrase;
+ if (isInsert) {
+ final int columnCount = columnsInTable.size();
+ phrase = String.format("INSERT INTO %s (%s) VALUES (%s)",
+ tableName,
+ join(",", columnsInTable),
+ join(",", nCopies(columnCount, "?")));
+ } else {
+ List<String> columnExpressions = new ArrayList<String>();
+ for (final String columnName : columnsInTable) {
+ columnExpressions.add(columnName + "=?");
+ }
+ phrase = String.format("UPDATE %s SET %s", tableName, join(", ", columnExpressions));
+ }
+ return phrase;
}
+ // text-search
+
@Override
public boolean search(Matcher matcher) {
return search(resolveTargetPath(getSelectionPath()), matcher);
// empty
}
+ // node expansion
+
/**
* Refreshes the root and its children.
* @param env Environment
this.currentConnector = c;
// auto-expansion
try {
- File confFile = new File(Bootstrap.getDirectory(), "autoexpansion.tsv");
+ File confFile = Bootstrap.getSystemFile("autoexpansion.tsv");
if (confFile.exists() && confFile.length() > 0) {
AnyAction aa = new AnyAction(this);
Scanner r = new Scanner(confFile);
}
});
} catch (SQLException ex) {
+ try {
+ if (dbmeta.getConnection().isClosed())
+ return;
+ } catch (SQLException exx) {
+ ex.setNextException(exx);
+ }
throw new RuntimeException(ex);
}
}
}
}
- static String generateEquivalentJoinClause(List<ColumnNode> nodes) {
- if (nodes.isEmpty()) {
- return "";
- }
- ListMap tm = new ListMap();
- ListMap cm = new ListMap();
- for (ColumnNode node : nodes) {
- final String tableName = node.getTableNode().getName();
- final String columnName = node.getName();
- tm.add(tableName, columnName);
- cm.add(columnName, String.format("%s.%s", tableName, columnName));
- }
- List<String> expressions = new ArrayList<String>();
- if (tm.size() == 1) {
- for (ColumnNode node : nodes) {
- expressions.add(String.format("%s=?", node.getName()));
- }
- } else {
- final String tableName = nodes.get(0).getTableNode().getName();
- for (String c : tm.get(tableName)) {
- expressions.add(String.format("%s.%s=?", tableName, c));
- }
- for (Entry<String, List<String>> entry : cm.entrySet()) {
- if (!entry.getKey().equals(tableName) && entry.getValue().size() == 1) {
- expressions.add(String.format("%s=?", entry.getValue().get(0)));
- }
- }
- for (Entry<String, List<String>> entry : cm.entrySet()) {
- Object[] a = entry.getValue().toArray();
- final int n = a.length;
- for (int i = 0; i < n; i++) {
- for (int j = i + 1; j < n; j++) {
- expressions.add(String.format("%s=%s", a[i], a[j]));
- }
- }
- }
- }
- return TextUtilities.join(" AND ", expressions) + ';';
- }
-
- @Override
- public TreePath[] getSelectionPaths() {
- TreePath[] a = super.getSelectionPaths();
- if (a == null) {
- return new TreePath[0];
- }
- return a;
- }
-
// subclasses
private static final class ListMap extends LinkedHashMap<String, List<String>> {
// empty
}
- void add(String key, String value) {
+ void add(String key, String... values) {
if (get(key) == null) {
put(key, new ArrayList<String>());
}
- get(key).add(value);
+ for (String value : values) {
+ get(key).add(value);
+ }
}
}
static List<TableTypeNode> getTableTypeNodes(DatabaseMetaData dbmeta,
String catalog,
String schema) throws SQLException {
- List<TableTypeNode> a = new ArrayList<TableTypeNode>();
- ResultSet rs = dbmeta.getTableTypes();
+ List<String> tableTypes = new ArrayList<String>(DEFAULT_TABLE_TYPES);
try {
- while (rs.next()) {
- TableTypeNode typeNode = new TableTypeNode(catalog, schema, rs.getString(1));
- if (typeNode.hasItems(dbmeta)) {
- a.add(typeNode);
+ ResultSet rs = dbmeta.getTableTypes();
+ try {
+ while (rs.next()) {
+ final String tableType = rs.getString(1);
+ if (!DEFAULT_TABLE_TYPES.contains(tableType)) {
+ tableTypes.add(tableType);
+ }
}
+ } finally {
+ rs.close();
}
- } finally {
- rs.close();
+ } catch (SQLException ex) {
+ log.warn("getTableTypes at getTableTypeNodes", ex);
}
- if (a.isEmpty()) {
- a.add(new TableTypeNode(catalog, schema, "TABLE"));
+ List<TableTypeNode> a = new ArrayList<TableTypeNode>();
+ for (final String tableType : tableTypes) {
+ TableTypeNode typeNode = new TableTypeNode(catalog, schema, tableType);
+ if (typeNode.hasItems(dbmeta)) {
+ a.add(typeNode);
+ }
}
return a;
}
while (rs.next()) {
final String table = rs.getString(3);
final String type = rs.getString(4);
- final boolean kindOfTable = type.matches("TABLE|VIEW|SYNONYM");
- a.add(new TableNode(catalog, schema, table, kindOfTable));
+ a.add(new TableNode(catalog, schema, table, type));
}
} finally {
rs.close();
private final String catalog;
private final String schema;
private final String name;
- private final boolean kindOfTable;
+ private final String tableType;
- TableNode(String catalog, String schema, String name, boolean kindOfTable) {
+ TableNode(String catalog, String schema, String name, String tableType) {
super(name);
this.catalog = catalog;
this.schema = schema;
this.name = name;
- this.kindOfTable = kindOfTable;
+ this.tableType = tableType;
}
@Override
@Override
public boolean isLeaf() {
+ if (TABLE_TYPE_SEQUENCE.equals(tableType)) {
+ return true;
+ }
return false;
}
a.add(schema);
}
a.add(name);
- return TextUtilities.join(".", a);
+ return join(".", a);
}
String getName() {
return name;
}
- boolean isKindOfTable() {
- return kindOfTable;
- }
-
}
static final class ColumnNode extends InfoNode {