
impl.H2DatabaseConnection Maven / Gradle / Ivy
package impl;
import api.Column;
import api.Table;
import api.sql.SQLDatabaseConnection;
import api.sql.SQLSchema;
import api.sql.SQLTable;
import api.sql.constraint.Constraint;
import api.sql.constraint.NotNull;
import api.sql.constraint.PrimaryKey;
import java.sql.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public abstract class H2DatabaseConnection implements SQLDatabaseConnection {
protected abstract String buildDatabaseUrl();
/**
* Initializes the database according to the given schema. Tables which are mentioned in the
* schema will be dropped if they already exist. All other tables will not be touched by this
* commmand.
* @param schema The schema that the database have to fulfill
* @param moreSchemas (Optional) More schemas the database have to fulfill
*/
@Override
public void init(SQLSchema schema, SQLSchema... moreSchemas) {
try(Connection connection = DriverManager.getConnection(buildDatabaseUrl())) {
initDatabase(schema, connection);
for (SQLSchema moreSchema : moreSchemas) {
initDatabase(moreSchema, connection);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
private void initDatabase(SQLSchema schema, Connection connection) {
schema.getTables().forEach(table -> {
try(Statement statement = connection.createStatement()){
statement.execute(String.format("DROP TABLE IF EXISTS %s CASCADE", table.getName()));
} catch (SQLException e) {
throw new RuntimeException(e);
}
List columns = new ArrayList<>(table.getColumns());
StringBuilder columnDefinition = new StringBuilder();
for (int i = 0; i < columns.size(); i++){
if (i > 0){
columnDefinition.append(",");
}
columnDefinition.append(String.format("%s %s", columns.get(i).getName(), columns.get(i).getDatatype()));
appendConstraints(table, columnDefinition, columns.get(i));
}
try(Statement statement = connection.createStatement()){
String queryString = String.format("CREATE TABLE %s (%s)", table.getName(), columnDefinition);
statement.execute(queryString);
} catch (SQLException e) {
throw new RuntimeException(e);
}
});
}
@Override
public void insert(Table table, Row row) {
try(Connection connection = DriverManager.getConnection(buildDatabaseUrl())){
StringBuilder columnNames = new StringBuilder();
StringBuilder valuesHolder = new StringBuilder();
List values = new ArrayList<>(row.getColumns().size());
final boolean[] isFirstRow = {true};
row.getColumns().forEach(column -> {
if (!isFirstRow[0]){
columnNames.append(",");
valuesHolder.append(",");
}
columnNames.append(column.getName());
valuesHolder.append("?");
Optional value = row.get(column);
assert value.isPresent();
values.add(value.get());
isFirstRow[0] = false;
});
String query = String.format("INSERT INTO %s (%s) VALUES (%s)", table.getName(), columnNames, valuesHolder);
try(PreparedStatement statement = connection.prepareStatement(query)){
for (int i = 0; i < values.size(); i++){
statement.setString(i+1, values.get(i).get());
}
statement.execute();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public Stream readTable(Table table) {
try(Connection connection = DriverManager.getConnection(buildDatabaseUrl())){
try(Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE)){
StringBuilder columns = new StringBuilder();
final boolean[] isFirstRow = {true};
table.getColumns().forEach(column -> {
if (!isFirstRow[0]){
columns.append(",");
}
columns.append(String.format("%s", column.getName()));
isFirstRow[0] = false;
});
String query = String.format("SELECT %s FROM %s GROUP BY %s", columns, table.getName(), columns);
ResultSet queryResult = statement.executeQuery(query);
if (!queryResult.last()){
return Stream.empty();
}
int rowCount = queryResult.getRow();
queryResult.beforeFirst();
List rows = new ArrayList<>(rowCount);
while(queryResult.next()){
Map columnValues = new HashMap<>();
table.getColumns().forEach(column -> {
try {
String value = queryResult.getString(column.getName());
if (value == null){
value = "";
}
columnValues.put(column, new Value(value));
} catch (SQLException e) {
throw new RuntimeException(e);
}
});
Row row = new Row(columnValues);
rows.add(row);
}
return rows.parallelStream();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* Appends the constraint string to the given column definition string
* @param table The table containing the constraints
* @param columnDefinition The column definition string the constraints shall be appended to
* @param column The column the constraints refer to
*/
private void appendConstraints(SQLTable table, StringBuilder columnDefinition, Column column) {
Set constraints = table.getConstraints().stream().filter(
constraint -> Objects.equals(constraint.getConstrainedColumn(), column)
).collect(Collectors.toSet());
constraints.forEach(constraint -> {
if (constraint instanceof PrimaryKey){
columnDefinition.append(" PRIMARY KEY");
}
if (constraint instanceof NotNull){
columnDefinition.append(" NOT NULL");
}
});
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy