Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,49 @@ public abstract boolean deleteFromTable(String tableName, String courtLocation)
public abstract List<NameAndCode> getCaseTypeNamesFor(
String courtLocationId, String caseCategoryCode, Optional<Boolean> initial);

protected void validTable(String tableName) throws SQLException {
if (tableName.contains("(")
|| tableName.contains(")")
|| tableName.contains(" ")
|| tableName.contains(";")) {
log.warn("Must be a valid table name: {} is not", tableName);
throw new CodeDatabaseUtils.UnsupportedTableException(
"Must be a valid table name: " + tableName + " is not");
}
}

protected boolean tableExists(String tableName) throws SQLException {
if (conn == null) {
throw new SQLException();
}
validTable(tableName);
String tableExistsQuery = CodeDatabaseUtils.getTableExists();
try (PreparedStatement existsSt = conn.prepareStatement(tableExistsQuery)) {
existsSt.setString(1, tableName);
ResultSet rs = existsSt.executeQuery();
boolean next = rs.next();
int firstVal = rs.getInt(1);
rs.close();
return (next && firstVal > 0);
}
}

protected boolean indiciesExists(String tableName) throws SQLException {
if (conn == null) {
throw new SQLException();
}
validTable(tableName);

String indicesExist = CodeDatabaseUtils.getIndicesExist();
try (PreparedStatement existsSt = conn.prepareStatement(indicesExist)) {
existsSt.setString(1, tableName);
ResultSet rs = existsSt.executeQuery();
boolean next = rs.next();
int firstVal = rs.getInt(1);
return (next && firstVal > 0);
}
}

/** Runs all of the logic for search queries (both name searches and court coverage searches). */
protected List<String> genericSearch(
String searchTerm, SQLFunction<String, PreparedStatement> queryMaker) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package edu.suffolk.litlab.efsp.ecfcodes;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class CodeDatabaseUtils {
/** This exception is returned when a given table name isn't in the pre-approved list of names. */
Expand Down Expand Up @@ -35,4 +40,113 @@ public static String likeWildcard(String searchTerm) {
}
return "%" + searchTerm + "%";
}

public static record TableColumns(
List<Column> mainList, List<String> primaryKeys, boolean needsExtraLocCol) {}

public static record Column(String name, String type) {}

/**
* Returns an INSERT statement for the given table + court. The statement includes a ON CONFLICT
* (all columns...) DO NOTHING clause.
*
* @param tableName The name of the DB table (i.e. code list) to insert into
* @param courtName The Court Location ID to add codes for
*/
public static String createInsertQuery(String tableName, TableColumns tc) {
StringBuilder insertLocation = new StringBuilder();
insertLocation.append("INSERT INTO \"" + tableName + "\" (");
StringBuilder colNames = new StringBuilder();
boolean isFirst = true;
for (Column col : tc.mainList()) {
if (isFirst) {
isFirst = false;
} else {
colNames.append(", ");
}
colNames.append("\"" + col.name() + "\"");
}
if (tc.needsExtraLocCol()) {
colNames.append(", location");
}
colNames.append(", jurisdiction");
insertLocation.append(colNames.toString());
insertLocation.append(") VALUES (");
for (int i = 0; i < tc.mainList().size(); i++) {
if (i > 0) {
insertLocation.append(", ");
}
insertLocation.append("?");
}
if (tc.needsExtraLocCol()) {
insertLocation.append(", ?");
}
insertLocation.append(", ?");
insertLocation.append(")");
return insertLocation.toString();
}

public static String createTableQuery(String tableName, TableColumns tc) {
StringBuilder createLocation = new StringBuilder();
createLocation.append("CREATE TABLE " + tableName + "(");
boolean isFirst = true;
for (Column col : tc.mainList()) {
if (isFirst) {
isFirst = false;
} else {
createLocation.append(", ");
}
createLocation.append("\"" + col.name() + "\" " + col.type());
}
if (tc.needsExtraLocCol()) {
createLocation.append(", \"location\" varchar(80)");
}
createLocation.append(", \"jurisdiction\" varchar(80)");

if (!tc.primaryKeys().isEmpty()) {
createLocation.append(
", PRIMARY KEY(" + tc.primaryKeys().stream().collect(Collectors.joining(",")) + ")");
}
createLocation.append(")");
return createLocation.toString();
}

public static PreparedStatement singleInsert(
PreparedStatement stmt,
TableColumns columns,
Map<String, String> rowVals,
String courtName,
String jurisStr)
throws SQLException {
int idx = 1;
for (var col : columns.mainList) {
if (col.type.equalsIgnoreCase("boolean")) {
if (rowVals.containsKey(col.name)) {
stmt.setBoolean(idx, Boolean.parseBoolean(rowVals.get(col.name)));
} else {
stmt.setNull(idx, Types.BOOLEAN);
}
} else if (col.type.equalsIgnoreCase("integer")) {
if (rowVals.containsKey(col.name)) {
stmt.setInt(idx, Integer.parseInt(rowVals.get(col.name)));
} else {
stmt.setNull(idx, Types.INTEGER);
}
} else {
// colType.equalsIgnoreCase("text") || colType.startsWith("varchar")
if (rowVals.containsKey(col.name)) {
stmt.setString(idx, rowVals.get(col.name));
} else {
stmt.setString(idx, null);
}
}
idx += 1;
}
if (columns.needsExtraLocCol) {
stmt.setString(idx, courtName);
idx += 1;
}
stmt.setString(idx, jurisStr);
return stmt;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
Expand All @@ -24,7 +23,6 @@
import java.util.Optional;
import java.util.Set;
import javax.sql.DataSource;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -117,20 +115,7 @@ public static CodeDatabase fromDS(Jurisdiction jurisdiction, DataSource ds) {
}

public boolean tablesExist() throws SQLException {
String tableExistsQuery = CodeDatabaseUtils.getTableExists();
boolean locationExists = false;
boolean installedExists = false;
try (PreparedStatement existsSt = conn.prepareStatement(tableExistsQuery)) {
existsSt.setString(1, "location");
ResultSet rs = existsSt.executeQuery();
locationExists = rs.next() && rs.getInt(1) > 0;
}
try (PreparedStatement existsSt = conn.prepareStatement(tableExistsQuery)) {
existsSt.setString(1, "installedversion");
ResultSet rs = existsSt.executeQuery();
installedExists = rs.next() && rs.getInt(1) > 0;
}
return locationExists && installedExists;
return tableExists("location") && tableExists("installedversion");
}

@Override
Expand All @@ -149,63 +134,35 @@ private String jurisStr() {
}

public void createTableIfAbsent(String tableName) throws SQLException {
if (conn == null) {
throw new SQLException();
}
if (tableName.contains("(") || tableName.contains(")") || tableName.contains(" ")) {
log.warn("Must be valid table name: {} is not", tableName);
return;
}
boolean exists = tableExists(tableName);

// TODO(brycew-later): eventually make the create tables have foreign keys and
// required from the Id / columnRefs
String tableExistsQuery = CodeDatabaseUtils.getTableExists();
try (PreparedStatement existsSt = conn.prepareStatement(tableExistsQuery)) {
existsSt.setString(1, tableName);
ResultSet rs = existsSt.executeQuery();
boolean next = rs.next();
int firstVal = rs.getInt(1);
if (!next || firstVal <= 0) { // There's no table! Make one
if (tableName.equals("optionalservices")) {
log.info("Creating optionalservices");
OptionalServiceCode.createFromOptionalServiceTable(conn);
} else {
String createQuery = CodeTableConstants.getCreateTable(tableName);
try (Statement createSt = conn.createStatement()) {
log.info("Full statement: {}", createQuery);
createSt.executeUpdate(createQuery);
}
if (!exists) { // There's no table! Make one
if (tableName.equals("optionalservices")) {
log.info("Creating optionalservices");
OptionalServiceCode.createFromOptionalServiceTable(conn);
} else {
String createQuery = CodeTableConstants.getCreateTable(tableName);
try (Statement createSt = conn.createStatement()) {
log.info("Full statement: {}", createQuery);
createSt.executeUpdate(createQuery);
}
}
rs.close();
}
}

public void createIndicesIfAbsent(String tableName) throws SQLException {
if (conn == null) {
throw new SQLException();
}
if (tableName.contains("(") || tableName.contains(")") || tableName.contains(" ")) {
log.warn("Must be a valid table name: {} is not", tableName);
return;
}

String indicesExist = CodeDatabaseUtils.getIndicesExist();
try (PreparedStatement existsSt = conn.prepareStatement(indicesExist)) {
existsSt.setString(1, tableName);
ResultSet rs = existsSt.executeQuery();
boolean next = rs.next();
int firstVal = rs.getInt(1);
if (!next || firstVal <= 0) {
if (tableName.equals("optionalservices")) {
OptionalServiceCode.createIndices(conn);
} else {
// Create the indices: might take a while
List<String> createIndices = CodeTableConstants.getCreateIndex(tableName);
for (String createIndex : createIndices) {
try (PreparedStatement createSt = conn.prepareStatement(createIndex)) {
createSt.executeUpdate();
}
boolean exists = indiciesExists(tableName);
if (!exists) {
if (tableName.equals("optionalservices")) {
OptionalServiceCode.createIndices(conn);
} else {
// Create the indices: might take a while
List<String> createIndices = CodeTableConstants.getCreateIndex(tableName);
for (String createIndex : createIndices) {
try (PreparedStatement createSt = conn.prepareStatement(createIndex)) {
createSt.executeUpdate();
}
}
}
Expand All @@ -217,10 +174,7 @@ public void updateTable(String tableName, String courtName, InputStream inStream
if (conn == null) {
throw new SQLException("Null connection!");
}
if (tableName.contains("(") || tableName.contains(")") || tableName.contains(" ")) {
log.warn("Must be valid table name: {} is not", tableName);
return;
}
validTable(tableName);

createTableIfAbsent(tableName);
createIndicesIfAbsent(tableName);
Expand Down Expand Up @@ -266,51 +220,14 @@ private void updateTableInner(
// ColumnSet cs = rows.getColumnSet();
while (rows.hasNext()) {
Map<String, String> rowsVals = rows.next();
singleInsert(stmt, tableName, courtName, rowsVals);
CodeDatabaseUtils.singleInsert(
stmt, CodeTableConstants.getTableColumns(tableName), rowsVals, courtName, jurisStr());
stmt.addBatch();
}
stmt.executeBatch();
}
}

private PreparedStatement singleInsert(
PreparedStatement stmt, String tableName, String courtName, Map<String, String> rowsVals)
throws SQLException {
int idx = 1;
List<Pair<String, String>> tc = CodeTableConstants.getTableColumnsWithType(tableName);
for (Pair<String, String> col : tc) {
String colName = col.getLeft();
String colType = col.getRight();
if (colType.equalsIgnoreCase("boolean")) {
if (rowsVals.containsKey(colName)) {
stmt.setBoolean(idx, Boolean.parseBoolean(rowsVals.get(colName)));
} else {
stmt.setNull(idx, Types.BOOLEAN);
}
} else if (colType.equalsIgnoreCase("integer")) {
if (rowsVals.containsKey(colName)) {
stmt.setInt(idx, Integer.parseInt(rowsVals.get(colName)));
} else {
stmt.setNull(idx, Types.INTEGER);
}
} else {
// colType.equalsIgnoreCase("text") || colType.startsWith("varchar")
if (rowsVals.containsKey(colName)) {
stmt.setString(idx, rowsVals.get(colName));
} else {
stmt.setString(idx, null);
}
}
idx += 1;
}
if (CodeTableConstants.isCourtTable(tableName)) {
stmt.setString(idx, courtName);
idx += 1;
}
stmt.setString(idx, jurisStr());
return stmt;
}

@Override
public List<String> searchCaseCategory(String searchTerm) {
return genericSearch(
Expand Down
Loading
Loading