| package de.ids_mannheim.korap.response.collector; |
| |
| import de.ids_mannheim.korap.server.Node; |
| import de.ids_mannheim.korap.response.Match; |
| import de.ids_mannheim.korap.response.MatchCollector; |
| import com.fasterxml.jackson.annotation.*; |
| import java.sql.Connection; |
| import java.sql.PreparedStatement; |
| import javax.sql.DataSource; |
| import java.sql.SQLException; |
| import java.util.*; |
| |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public final class MatchCollectorDB extends MatchCollector { |
| |
| // Logger |
| private final static Logger log = LoggerFactory.getLogger(Node.class); |
| |
| /* |
| * Todo: In case there are multiple threads searching, |
| * the list should be synchrinized Collections.synchronizedList() |
| */ |
| private String databaseType; |
| private final List matchCollector; |
| private final int bufferSize; |
| private int docCollect; |
| private final String resultID; |
| |
| // private Connection connection; |
| private DataSource pool; |
| private Connection connection; |
| private PreparedStatement prepared; |
| |
| |
| /* |
| * Create a new collector for database connections |
| */ |
| public MatchCollectorDB (int bufferSize, String resultID) { |
| this.bufferSize = bufferSize; |
| this.resultID = resultID; |
| this.matchCollector = new ArrayList<int[]>(bufferSize + 2); |
| }; |
| |
| |
| /* |
| * Add matches till the bufferSize exceeds - then commit to the database. |
| */ |
| public void add (int UID, int matchCount) { |
| if (this.docCollect == bufferSize) |
| this.commit(); |
| |
| this.incrTotalResultDocs(1); |
| this.incrTotalResults(matchCount); |
| this.matchCollector.add(new int[] { UID, matchCount }); |
| this.docCollect++; |
| }; |
| |
| |
| @JsonIgnore |
| public void setDatabaseType (String type) { |
| this.databaseType = type; |
| }; |
| |
| |
| @JsonIgnore |
| public String getDatabaseType () { |
| return this.databaseType; |
| }; |
| |
| |
| @JsonIgnore |
| public void setDBPool (String type, DataSource ds, Connection conn) |
| throws SQLException { |
| this.setDatabaseType(type); |
| this.connection = conn; |
| this.pool = ds; |
| }; |
| |
| |
| @JsonIgnore |
| public void setDBPool (String type, DataSource ds) throws SQLException { |
| this.setDatabaseType(type); |
| this.pool = ds; |
| }; |
| |
| |
| /* |
| Create prepared statement for multiple requests |
| this.prepared = this.conn.prepareStatement( |
| "INSERT INTO people VALUES (?, ?);" |
| ); |
| Only prepare if commit > buffersize! |
| Difference between mariadb and sqlite! |
| */ |
| |
| |
| /* TODO: Ensure the commit was successful! */ |
| public void commit () { |
| if (this.pool == null) |
| return; |
| |
| try { |
| /* |
| * This should be heavily optimized! It's aweful! |
| * ARGHHHHHHH! |
| */ |
| if (this.connection.isClosed()) |
| this.connection = this.pool.getConnection(); |
| |
| StringBuilder sb = new StringBuilder(); |
| sb.append("INSERT INTO ").append(this.resultID) |
| .append(" (text_id, match_count) "); |
| |
| // SQLite batch insertion idiom |
| if (this.getDatabaseType().equals("sqlite")) { |
| for (int i = 1; i < this.docCollect; i++) { |
| sb.append("SELECT ?, ? UNION "); |
| } |
| if (this.docCollect == 1) |
| sb.append("VALUES (?, ?)"); |
| else |
| sb.append("SELECT ?, ?"); |
| } |
| |
| // MySQL batch insertion idiom |
| else if (this.getDatabaseType().equals("mysql")) { |
| sb.append(" VALUES "); |
| for (int i = 1; i < this.docCollect; i++) { |
| sb.append("(?,?),"); |
| }; |
| sb.append("(?,?)"); |
| } |
| |
| // Unknown idiom |
| else { |
| log.error("Unsupported Database type"); |
| return; |
| }; |
| |
| // Prepare statement based on the string |
| PreparedStatement prep = this.connection.prepareStatement(sb |
| .toString()); |
| |
| int i = 1; |
| ListIterator li = this.matchCollector.listIterator(); |
| while (li.hasNext()) { |
| int[] v = (int[]) li.next(); |
| prep.setInt(i++, v[0]); |
| prep.setInt(i++, v[1]); |
| }; |
| |
| prep.addBatch(); |
| prep.executeBatch(); |
| this.connection.commit(); |
| } |
| |
| // An SQL error occured ... |
| catch (SQLException e) { |
| log.error(e.getLocalizedMessage()); |
| }; |
| |
| this.matchCollector.clear(); |
| this.docCollect = 0; |
| return; |
| }; |
| |
| |
| /* |
| * Close collector and connection |
| */ |
| public void close () { |
| this.commit(); |
| try { |
| this.connection.close(); |
| } |
| catch (SQLException e) { |
| log.warn(e.getLocalizedMessage()); |
| } |
| }; |
| |
| |
| /* |
| * Close collector and probably connection |
| */ |
| public void close (boolean close) { |
| if (close) |
| this.close(); |
| |
| this.commit(); |
| }; |
| }; |