Added EVERYTHING
This commit is contained in:
parent
6670c245c2
commit
d6e84f47e7
|
@ -0,0 +1 @@
|
|||
select * from primes;
|
|
@ -0,0 +1,7 @@
|
|||
CREATE TABLE primes (
|
||||
id SERIAL NOT NULL,
|
||||
value INT NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO primes(value) VALUES
|
||||
(2), (3), (5), (7), (11);
|
|
@ -0,0 +1 @@
|
|||
select * from primes;
|
|
@ -0,0 +1,123 @@
|
|||
package nl.andrewlalis;
|
||||
|
||||
import nl.andrewlalis.log.ExecutionLog;
|
||||
import nl.andrewlalis.log.QueryAction;
|
||||
import nl.andrewlalis.log.UpdateAction;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DatabaseHelper {
|
||||
|
||||
private String host;
|
||||
private int port;
|
||||
private String user;
|
||||
private String password;
|
||||
private Window window;
|
||||
|
||||
private ExecutionLog executionLog;
|
||||
|
||||
public DatabaseHelper(String host, int port, String user, String password, Window window) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.user = user;
|
||||
this.password = password;
|
||||
this.window = window;
|
||||
|
||||
this.executionLog = new ExecutionLog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes possibly many queries which are contained in one string.
|
||||
* @param database The database name to connect to, or an empty string to connect to the user's database.
|
||||
* @param queriesString The string of queries.
|
||||
*/
|
||||
public void executeQueries(String database, String queriesString) {
|
||||
String url = String.format(
|
||||
"jdbc:postgresql://%s:%4d/%s?user=%s&password=%s",
|
||||
host,
|
||||
port,
|
||||
database,
|
||||
user,
|
||||
password);
|
||||
try {
|
||||
Connection conn = DriverManager.getConnection(url);
|
||||
|
||||
if (!conn.isValid(1000)) {
|
||||
throw new SQLException("Invalid connection.");
|
||||
}
|
||||
|
||||
List<String> queries = splitQueries(queriesString);
|
||||
|
||||
Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
|
||||
|
||||
for (String query : queries) {
|
||||
try {
|
||||
executeQuery(query, st);
|
||||
} catch (SQLException e) {
|
||||
window.appendOutput("Exception while executing statement: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
int previousChannel = window.getOutputChannel();
|
||||
window.setOutputChannel(Window.OUTPUT_GENERAL);
|
||||
window.appendOutput("Unexpected SQL Exception occurred. URL:\n" + url + "\n\tException: " + e.getMessage() + "\n\tSQL State: " + e.getSQLState());
|
||||
window.setOutputChannel(previousChannel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a single query and outputs the results.
|
||||
* @param query The query to execute. Must be only one query in the string.
|
||||
* @param statement The statement used to execute the query.
|
||||
*/
|
||||
private void executeQuery(String query, Statement statement) throws SQLException {
|
||||
if (isSQLStatementQuery(query)) {
|
||||
// A result set is expected.
|
||||
window.appendOutput("Executing query:\n" + query);
|
||||
|
||||
QueryAction action = new QueryAction(statement.executeQuery(query));
|
||||
window.appendOutput(action.toString());
|
||||
this.executionLog.recordAction(action);
|
||||
} else {
|
||||
// A result set is not expected.
|
||||
window.appendOutput("Executing update:\n" + query);
|
||||
UpdateAction action = new UpdateAction(statement.executeUpdate(query), query);
|
||||
window.appendOutput(action.toString());
|
||||
this.executionLog.recordAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits and cleans each query so that it will run properly.
|
||||
* @param queriesString A string containing one or more queries to execute.
|
||||
* @return A list of individual queries.
|
||||
*/
|
||||
private static List<String> splitQueries(String queriesString) {
|
||||
String[] sections = queriesString.split(";");
|
||||
List<String> strings = new ArrayList<>();
|
||||
|
||||
for (String section : sections) {
|
||||
String s = section.trim();
|
||||
if (!s.isEmpty()) {
|
||||
strings.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
return strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an SQL string is a query (it should return a result set)
|
||||
* @param str The string to check.
|
||||
* @return True if this is a query, or false if it is an update.
|
||||
*/
|
||||
private static boolean isSQLStatementQuery(String str) {
|
||||
String upper = str.toUpperCase();
|
||||
return upper.startsWith("SELECT");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package nl.andrewlalis;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static final String APPLICATION_NAME = "SQL-Assesser";
|
||||
|
||||
public static void main(String[] args) {
|
||||
Window window = new Window(APPLICATION_NAME);
|
||||
window.pack();
|
||||
window.setSize(1000, 800);
|
||||
window.setVisible(true);
|
||||
window.setLocationRelativeTo(null);
|
||||
window.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,381 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="nl.andrewlalis.Window">
|
||||
<grid id="27dc6" binding="mainPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="1195" height="814"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="3de6c" class="javax.swing.JLabel">
|
||||
<constraints border-constraint="North"/>
|
||||
<properties>
|
||||
<horizontalAlignment value="0"/>
|
||||
<text value="SQL-Assesser"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="e44a4" binding="inputPanel" layout-manager="GridBagLayout">
|
||||
<constraints border-constraint="Center"/>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="bfff3" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<gridbag weightx="1.0" weighty="1.0"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="bevel-lowered"/>
|
||||
<children>
|
||||
<component id="5a36e" class="javax.swing.JLabel">
|
||||
<constraints border-constraint="North"/>
|
||||
<properties>
|
||||
<horizontalAlignment value="0"/>
|
||||
<text value="Template"/>
|
||||
</properties>
|
||||
</component>
|
||||
<scrollpane id="4a4c7">
|
||||
<constraints border-constraint="Center"/>
|
||||
<properties>
|
||||
<verticalScrollBarPolicy value="22"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="c2e9b" class="javax.swing.JTextArea" binding="templateTextArea">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<text value="select * from primes;"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</scrollpane>
|
||||
<grid id="2493e" layout-manager="FlowLayout" hgap="5" vgap="5" flow-align="1">
|
||||
<constraints border-constraint="South"/>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="15c71" class="javax.swing.JButton" binding="loadTemplateFromFileButton">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<text value="Load From File"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="ce988" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<gridbag weightx="1.0" weighty="1.0"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="bevel-lowered"/>
|
||||
<children>
|
||||
<component id="e3b9a" class="javax.swing.JLabel">
|
||||
<constraints border-constraint="North"/>
|
||||
<properties>
|
||||
<horizontalAlignment value="0"/>
|
||||
<text value="Testing"/>
|
||||
</properties>
|
||||
</component>
|
||||
<scrollpane id="28e0d">
|
||||
<constraints border-constraint="Center"/>
|
||||
<properties>
|
||||
<verticalScrollBarPolicy value="22"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="17867" class="javax.swing.JTextArea" binding="testingTextArea">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<text value="select * from primes;"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</scrollpane>
|
||||
<grid id="7bdad" layout-manager="FlowLayout" hgap="5" vgap="5" flow-align="1">
|
||||
<constraints border-constraint="South"/>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="781f9" class="javax.swing.JButton" binding="loadTestingFromFileButton">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<text value="Load From File"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="a5211" layout-manager="FlowLayout" hgap="5" vgap="5" flow-align="1">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<gridbag weightx="1.0" weighty="0.0"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="bevel-lowered"/>
|
||||
<children>
|
||||
<grid id="a0bad" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints/>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="1ff5c" class="javax.swing.JLabel">
|
||||
<constraints border-constraint="North"/>
|
||||
<properties>
|
||||
<text value="Host"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="99396" class="javax.swing.JTextField" binding="hostTextField">
|
||||
<constraints border-constraint="Center"/>
|
||||
<properties>
|
||||
<text value="localhost"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="87583" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints/>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="274c3" class="javax.swing.JLabel">
|
||||
<constraints border-constraint="North"/>
|
||||
<properties>
|
||||
<text value="Port"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="44d44" class="javax.swing.JTextField" binding="portTextField">
|
||||
<constraints border-constraint="Center"/>
|
||||
<properties>
|
||||
<text value="5432"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="881cf" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints/>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="a2ebb" class="javax.swing.JLabel">
|
||||
<constraints border-constraint="North"/>
|
||||
<properties>
|
||||
<text value="User"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="c33e3" class="javax.swing.JTextField" binding="userTextField">
|
||||
<constraints border-constraint="Center"/>
|
||||
<properties>
|
||||
<text value="andrew"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="2eb2f" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints/>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="bf4a1" class="javax.swing.JLabel">
|
||||
<constraints border-constraint="North"/>
|
||||
<properties>
|
||||
<text value="Password"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="e2839" class="javax.swing.JTextField" binding="passwordTextField">
|
||||
<constraints border-constraint="Center"/>
|
||||
<properties>
|
||||
<text value="root"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="5241a" binding="outputPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints border-constraint="South"/>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="4eed0" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints border-constraint="South"/>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<scrollpane id="adb12" binding="outputScrollPane">
|
||||
<constraints border-constraint="Center"/>
|
||||
<properties>
|
||||
<preferredSize width="2" height="300"/>
|
||||
<verticalScrollBarPolicy value="22"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="aca43" class="javax.swing.JTextArea" binding="outputTextArea">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<editable value="false"/>
|
||||
<lineWrap value="true"/>
|
||||
<wrapStyleWord value="true"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</scrollpane>
|
||||
<component id="730ad" class="javax.swing.JLabel">
|
||||
<constraints border-constraint="North"/>
|
||||
<properties>
|
||||
<font style="1"/>
|
||||
<horizontalAlignment value="0"/>
|
||||
<text value="General Output"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="6c3b1" layout-manager="FlowLayout" hgap="5" vgap="5" flow-align="1">
|
||||
<constraints border-constraint="South"/>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="cfab2" class="javax.swing.JButton" binding="executeButton" default-binding="true">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<text value="Execute"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="167c9" class="javax.swing.JButton" binding="clearOutputButton" default-binding="true">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<text value="Clear Output"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="4fb1a" layout-manager="GridBagLayout">
|
||||
<constraints border-constraint="Center"/>
|
||||
<properties>
|
||||
<preferredSize width="70" height="200"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="60b96" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<gridbag weightx="1.0" weighty="1.0"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<preferredSize width="105" height="300"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="a32af" class="javax.swing.JLabel">
|
||||
<constraints border-constraint="North"/>
|
||||
<properties>
|
||||
<horizontalAlignment value="0"/>
|
||||
<text value="Template Output"/>
|
||||
</properties>
|
||||
</component>
|
||||
<scrollpane id="ae321">
|
||||
<constraints border-constraint="Center"/>
|
||||
<properties>
|
||||
<verticalScrollBarPolicy value="22"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="1e89d" class="javax.swing.JTextArea" binding="templateOutputTextArea">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<editable value="false"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</scrollpane>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="f3ff1" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<gridbag weightx="1.0" weighty="1.0"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<preferredSize width="93" height="300"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="67bc9" class="javax.swing.JLabel">
|
||||
<constraints border-constraint="North"/>
|
||||
<properties>
|
||||
<horizontalAlignment value="0"/>
|
||||
<text value="Testing Output"/>
|
||||
</properties>
|
||||
</component>
|
||||
<scrollpane id="c31b2">
|
||||
<constraints border-constraint="Center"/>
|
||||
<properties>
|
||||
<verticalScrollBarPolicy value="22"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="f0d22" class="javax.swing.JTextArea" binding="testingOutputTextArea">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<editable value="false"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</scrollpane>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="1e3e8" binding="initializationPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints border-constraint="West"/>
|
||||
<properties/>
|
||||
<border type="bevel-lowered"/>
|
||||
<children>
|
||||
<component id="3f0fa" class="javax.swing.JLabel">
|
||||
<constraints border-constraint="North"/>
|
||||
<properties>
|
||||
<horizontalAlignment value="0"/>
|
||||
<text value="Initialization"/>
|
||||
</properties>
|
||||
</component>
|
||||
<scrollpane id="27433">
|
||||
<constraints border-constraint="Center"/>
|
||||
<properties>
|
||||
<preferredSize width="400" height="18"/>
|
||||
<verticalScrollBarPolicy value="22"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="cc50b" class="javax.swing.JTextArea" binding="initializationTextArea">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<text value="CREATE TABLE primes ( 	id SERIAL NOT NULL, 	value INT NOT NULL ); INSERT INTO primes(value) VALUES (2), (3), (5), (7), (11);" noi18n="true"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</scrollpane>
|
||||
<grid id="2ca80" layout-manager="FlowLayout" hgap="5" vgap="5" flow-align="1">
|
||||
<constraints border-constraint="South"/>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="ffb59" class="javax.swing.JButton" binding="loadInitializationFromFileButton">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<text value="Load From File"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
|
@ -0,0 +1,150 @@
|
|||
package nl.andrewlalis;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public class Window extends JFrame {
|
||||
private JPanel mainPanel;
|
||||
private JPanel inputPanel;
|
||||
private JPanel outputPanel;
|
||||
private JTextArea outputTextArea;
|
||||
private JButton executeButton;
|
||||
private JTextArea templateTextArea;
|
||||
private JTextArea testingTextArea;
|
||||
private JTextField hostTextField;
|
||||
private JTextField portTextField;
|
||||
private JTextField userTextField;
|
||||
private JTextField passwordTextField;
|
||||
private JScrollPane outputScrollPane;
|
||||
private JTextArea testingOutputTextArea;
|
||||
private JTextArea templateOutputTextArea;
|
||||
private JTextArea initializationTextArea;
|
||||
private JPanel initializationPanel;
|
||||
private JButton clearOutputButton;
|
||||
private JButton loadTemplateFromFileButton;
|
||||
private JButton loadTestingFromFileButton;
|
||||
private JButton loadInitializationFromFileButton;
|
||||
|
||||
public static final int OUTPUT_GENERAL = 0;
|
||||
public static final int OUTPUT_TEMPLATE = 1;
|
||||
public static final int OUTPUT_TESTING = 2;
|
||||
|
||||
public static final String DB_TEMPLATE = "sql_assess_template";
|
||||
public static final String DB_TESTING = "sql_assess_testing";
|
||||
|
||||
private int outputChannel;
|
||||
private int outputIndent;
|
||||
|
||||
public Window(String applicationName) {
|
||||
super(applicationName);
|
||||
|
||||
this.setOutputChannel(OUTPUT_GENERAL);
|
||||
|
||||
this.setContentPane(mainPanel);
|
||||
|
||||
executeButton.addActionListener(actionEvent -> {
|
||||
this.executeSQL();
|
||||
});
|
||||
|
||||
clearOutputButton.addActionListener(actionEvent -> {
|
||||
this.templateOutputTextArea.setText(null);
|
||||
this.testingOutputTextArea.setText(null);
|
||||
this.outputTextArea.setText(null);
|
||||
});
|
||||
|
||||
loadInitializationFromFileButton.addActionListener(actionEvent -> {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the SQL in the two text areas, and provides output.
|
||||
*/
|
||||
private void executeSQL() {
|
||||
this.setOutputChannel(OUTPUT_GENERAL);
|
||||
String host = this.hostTextField.getText();
|
||||
int port = Integer.parseInt(this.portTextField.getText());
|
||||
String user = this.userTextField.getText();
|
||||
String password = this.passwordTextField.getText();
|
||||
String initialization = this.initializationTextArea.getText();
|
||||
|
||||
// Run the database code in a separate thread to update the UI quickly.
|
||||
Thread t = new Thread(() -> {
|
||||
DatabaseHelper dbHelper = new DatabaseHelper(host, port, user, password, this);
|
||||
|
||||
// Setup both databases.
|
||||
this.appendOutput("Dropping old databases and re-creating them...");
|
||||
this.indentOutput();
|
||||
String dropDatabases = "DROP DATABASE " + DB_TEMPLATE + "; " +
|
||||
"DROP DATABASE " + DB_TESTING + ";";
|
||||
String createDatabases = "CREATE DATABASE " + DB_TEMPLATE + "; " +
|
||||
"CREATE DATABASE " + DB_TESTING + ";";
|
||||
dbHelper.executeQueries("", dropDatabases);
|
||||
dbHelper.executeQueries("", createDatabases);
|
||||
this.unindentOutput();
|
||||
|
||||
// Run initialization script on each database.
|
||||
this.appendOutput("Running initialization SQL on databases...");
|
||||
this.indentOutput();
|
||||
dbHelper.executeQueries(DB_TEMPLATE, initialization);
|
||||
dbHelper.executeQueries(DB_TESTING, initialization);
|
||||
this.unindentOutput();
|
||||
|
||||
// Template-specific output.
|
||||
this.setOutputChannel(OUTPUT_TEMPLATE);
|
||||
dbHelper.executeQueries(DB_TEMPLATE, this.templateTextArea.getText());
|
||||
|
||||
// Testing-specific output.
|
||||
this.setOutputChannel(OUTPUT_TESTING);
|
||||
dbHelper.executeQueries(DB_TESTING, this.testingTextArea.getText());
|
||||
});
|
||||
t.start();
|
||||
}
|
||||
|
||||
int getOutputChannel() {
|
||||
return this.outputChannel;
|
||||
}
|
||||
|
||||
void setOutputChannel(int channel) {
|
||||
this.outputChannel = channel;
|
||||
}
|
||||
|
||||
void indentOutput() {
|
||||
this.outputIndent++;
|
||||
}
|
||||
|
||||
void unindentOutput() {
|
||||
this.outputIndent--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds some text to the current output channel, followed by a new line.
|
||||
* @param text The text to append.
|
||||
*/
|
||||
void appendOutput(String text) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < this.outputIndent; i++) {
|
||||
sb.append('\t');
|
||||
}
|
||||
String tabs = sb.toString();
|
||||
StringBuilder resultSb = new StringBuilder();
|
||||
for (String line : text.split("\n")) {
|
||||
resultSb.append(tabs).append(line).append('\n');
|
||||
}
|
||||
String result = resultSb.toString();
|
||||
switch (this.outputChannel) {
|
||||
case OUTPUT_GENERAL:
|
||||
this.outputTextArea.append(result);
|
||||
break;
|
||||
|
||||
case OUTPUT_TEMPLATE:
|
||||
this.templateOutputTextArea.append(result);
|
||||
break;
|
||||
|
||||
case OUTPUT_TESTING:
|
||||
this.testingOutputTextArea.append(result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package nl.andrewlalis.log;
|
||||
|
||||
/**
|
||||
* Represents an action performed on a database.
|
||||
*/
|
||||
public abstract class ExecutionAction {
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package nl.andrewlalis.log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Contains a log of all actions performed to a database.
|
||||
*/
|
||||
public class ExecutionLog {
|
||||
|
||||
private List<ExecutionAction> actions;
|
||||
|
||||
public ExecutionLog() {
|
||||
this.actions = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void recordAction(ExecutionAction action) {
|
||||
this.actions.add(action);
|
||||
}
|
||||
|
||||
public List<ExecutionAction> getActions() {
|
||||
return this.actions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof ExecutionLog)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ExecutionLog otherLog = (ExecutionLog) other;
|
||||
|
||||
if (otherLog.getActions().size() != this.getActions().size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<ExecutionAction> otherLogActions = otherLog.getActions();
|
||||
|
||||
for (int i = 0; i < this.getActions().size(); i++) {
|
||||
if (!this.getActions().get(i).equals(otherLogActions.get(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package nl.andrewlalis.log;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An action in which a query result set is returned.
|
||||
*/
|
||||
public class QueryAction extends ExecutionAction {
|
||||
|
||||
private String[] columns;
|
||||
private String[][] values;
|
||||
|
||||
public QueryAction(ResultSet resultSet) throws SQLException {
|
||||
// Read the columns into this object's memory.
|
||||
ResultSetMetaData metaData = resultSet.getMetaData();
|
||||
this.columns = new String[metaData.getColumnCount()];
|
||||
for (int i = 0; i < metaData.getColumnCount(); i++) {
|
||||
columns[i] = metaData.getColumnName(i + 1);
|
||||
}
|
||||
|
||||
resultSet.absolute(1);// Ensure that this result set cursor is at the beginning.
|
||||
|
||||
// Read the rows into this object's memory.
|
||||
List<String[]> rows = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
String[] row = new String[columns.length];
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
row[i] = resultSet.getString(i + 1);
|
||||
}
|
||||
rows.add(row);
|
||||
}
|
||||
this.values = new String[rows.size()][];
|
||||
rows.toArray(this.values);
|
||||
}
|
||||
|
||||
public String[] getColumns() {
|
||||
return this.columns;
|
||||
}
|
||||
|
||||
public String[][] getValues() {
|
||||
return this.values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof QueryAction)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QueryAction action = (QueryAction) other;
|
||||
|
||||
if (action.getColumns().length != this.columns.length || action.getValues().length != this.values.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.values.length; i++) {
|
||||
Map<String, String> thisColumnValues = new HashMap<>();
|
||||
Map<String, String> otherColumnValues = new HashMap<>();
|
||||
for (int k = 0; k < this.values[i].length; k++) {
|
||||
thisColumnValues.put(this.columns[k], this.values[i][k]);
|
||||
otherColumnValues.put(action.getColumns()[k], action.getValues()[i][k]);
|
||||
}
|
||||
for (String column : this.columns) {
|
||||
if (thisColumnValues.get(column).equals(otherColumnValues.get(column))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// First build a list of columns.
|
||||
StringBuilder sb = new StringBuilder("Query Result:\n\tColumns: (");
|
||||
for (int i = 0; i < this.columns.length; i++) {
|
||||
sb.append(this.columns[i]);
|
||||
if (i < this.columns.length - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(")\n\tValues:\n");
|
||||
|
||||
// Then build a list of the rows.
|
||||
for (int i = 0; i < this.values.length; i++) {
|
||||
sb.append("\t(");
|
||||
for (int k = 0; k < this.values[i].length; k++) {
|
||||
sb.append(this.values[i][k]);
|
||||
if (k < this.values[i].length - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(")\n");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package nl.andrewlalis.log;
|
||||
|
||||
/**
|
||||
* Represents an action in which the schema or data was updated and no result set was returned.
|
||||
*/
|
||||
public class UpdateAction extends ExecutionAction {
|
||||
|
||||
private int rowsAffected;
|
||||
|
||||
public UpdateAction(int rowsAffected, String statement) {
|
||||
this.rowsAffected = rowsAffected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof UpdateAction)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateAction action = (UpdateAction) other;
|
||||
|
||||
return action.rowsAffected == this.rowsAffected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Update result:\n\tRows affected: " + this.rowsAffected + "\n";
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue