blob: 0c5a6044489c7880b355978e2162c0a66b8f44ef [file] [log] [blame]
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();
};
};