blob: 10650dd4d191427cafa403f710c0e1ae60f55e3c [file] [log] [blame]
Nils Diewald6aa929e2014-09-17 13:30:34 +00001package de.ids_mannheim.korap.index.collector;
Nils Diewaldf04e1002014-09-24 22:52:59 +00002import de.ids_mannheim.korap.KorapNode;
Nils Diewald6aa929e2014-09-17 13:30:34 +00003import de.ids_mannheim.korap.KorapMatch;
4import de.ids_mannheim.korap.index.MatchCollector;
Nils Diewaldad3f3032014-09-24 01:42:47 +00005import com.fasterxml.jackson.annotation.*;
6import java.sql.Connection;
7import java.sql.PreparedStatement;
8import javax.sql.DataSource;
9import java.sql.SQLException;
Nils Diewald6aa929e2014-09-17 13:30:34 +000010import java.util.*;
11
Nils Diewaldf04e1002014-09-24 22:52:59 +000012import org.slf4j.Logger;
13import org.slf4j.LoggerFactory;
14
Nils Diewaldd723d812014-09-23 18:50:52 +000015public class MatchCollectorDB extends MatchCollector {
Nils Diewald6aa929e2014-09-17 13:30:34 +000016
Nils Diewaldf04e1002014-09-24 22:52:59 +000017 // Logger
18 private final static Logger log = LoggerFactory.getLogger(KorapNode.class);
19
Nils Diewald6aa929e2014-09-17 13:30:34 +000020 /*
Nils Diewald8d8641b2014-09-28 17:37:53 +000021 * Todo: In case there are multiple threads searching,
22 * the list should be synchrinized Collections.synchronizedList()
Nils Diewald6aa929e2014-09-17 13:30:34 +000023 */
Nils Diewaldad3f3032014-09-24 01:42:47 +000024 private String databaseType;
Nils Diewald6aa929e2014-09-17 13:30:34 +000025 private List matchCollector;
Nils Diewaldf04e1002014-09-24 22:52:59 +000026 private int bufferSize, docCollect;
Nils Diewaldad3f3032014-09-24 01:42:47 +000027 private String resultID;
Nils Diewald6aa929e2014-09-17 13:30:34 +000028
Nils Diewald8d8641b2014-09-28 17:37:53 +000029 // private Connection connection;
Nils Diewaldf04e1002014-09-24 22:52:59 +000030 private DataSource pool;
Nils Diewaldad3f3032014-09-24 01:42:47 +000031 private Connection connection;
32 private PreparedStatement prepared;
Nils Diewald6aa929e2014-09-17 13:30:34 +000033
34 /*
35 * Create a new collector for database connections
36 */
Nils Diewaldad3f3032014-09-24 01:42:47 +000037 public MatchCollectorDB (int bufferSize, String resultID) {
Nils Diewald6aa929e2014-09-17 13:30:34 +000038 this.bufferSize = bufferSize;
Nils Diewaldad3f3032014-09-24 01:42:47 +000039 this.resultID = resultID;
Nils Diewald6aa929e2014-09-17 13:30:34 +000040 this.matchCollector = new ArrayList<int[]>(bufferSize + 2);
41 };
42
43 /*
44 * Add matches till the bufferSize exceeds - then commit to the database.
45 */
Nils Diewaldad3f3032014-09-24 01:42:47 +000046 public void add (int UID, int matchCount) {
Nils Diewaldf04e1002014-09-24 22:52:59 +000047 if (this.docCollect == bufferSize)
48 this.commit();
49
Nils Diewaldd723d812014-09-23 18:50:52 +000050 this.incrTotalResultDocs(1);
Nils Diewaldad3f3032014-09-24 01:42:47 +000051 this.incrTotalResults(matchCount);
52 this.matchCollector.add(new int[]{UID, matchCount});
Nils Diewaldf04e1002014-09-24 22:52:59 +000053 this.docCollect++;
Nils Diewald6aa929e2014-09-17 13:30:34 +000054 };
55
Nils Diewaldad3f3032014-09-24 01:42:47 +000056 @JsonIgnore
57 public void setDatabaseType (String type) {
58 this.databaseType = type;
59 };
60
61 @JsonIgnore
62 public String getDatabaseType () {
63 return this.databaseType;
64 };
65
66 @JsonIgnore
Nils Diewald8d8641b2014-09-28 17:37:53 +000067 public void setDBPool (String type, DataSource ds, Connection conn) throws SQLException {
68 this.setDatabaseType(type);
69 this.connection = conn;
70 this.pool = ds;
71 };
72
73
74 @JsonIgnore
Nils Diewaldf04e1002014-09-24 22:52:59 +000075 public void setDBPool (String type, DataSource ds) throws SQLException {
Nils Diewaldad3f3032014-09-24 01:42:47 +000076 this.setDatabaseType(type);
Nils Diewaldf04e1002014-09-24 22:52:59 +000077 this.pool = ds;
Nils Diewaldad3f3032014-09-24 01:42:47 +000078 };
Nils Diewald8d8641b2014-09-28 17:37:53 +000079 /*
80 Create prepared statement for multiple requests
81 this.prepared = this.conn.prepareStatement(
82 "INSERT INTO people VALUES (?, ?);"
83 );
84 Only prepare if commit > buffersize!
85 Difference between mariadb and sqlite!
86 */
87
Nils Diewaldad3f3032014-09-24 01:42:47 +000088
Nils Diewaldf04e1002014-09-24 22:52:59 +000089 /* TODO: Ensure the commit was successful! */
Nils Diewaldad3f3032014-09-24 01:42:47 +000090 public void commit () {
Nils Diewaldf04e1002014-09-24 22:52:59 +000091 if (this.pool == null)
92 return;
Nils Diewaldad3f3032014-09-24 01:42:47 +000093
Nils Diewaldf04e1002014-09-24 22:52:59 +000094 try {
Nils Diewaldf04e1002014-09-24 22:52:59 +000095 /*
Nils Diewald8d8641b2014-09-28 17:37:53 +000096 * This should be heavily optimized! It's aweful!
Nils Diewaldf04e1002014-09-24 22:52:59 +000097 * ARGHHHHHHH!
98 */
99
Nils Diewald8d8641b2014-09-28 17:37:53 +0000100 if (this.connection.isClosed())
Nils Diewaldf04e1002014-09-24 22:52:59 +0000101 this.connection = this.pool.getConnection();
102
Nils Diewaldf04e1002014-09-24 22:52:59 +0000103 StringBuilder sb = new StringBuilder();
Nils Diewald8d8641b2014-09-28 17:37:53 +0000104 sb.append("INSERT INTO ")
105 .append(this.resultID)
106 .append(" (text_id, match_count) ");
Nils Diewaldf04e1002014-09-24 22:52:59 +0000107
Nils Diewald8d8641b2014-09-28 17:37:53 +0000108 // SQLite batch insertion idiom
Nils Diewaldf04e1002014-09-24 22:52:59 +0000109 if (this.getDatabaseType().equals("sqlite")) {
110 for (int i = 1; i < this.docCollect; i++) {
111 sb.append("SELECT ?, ? UNION ");
112 }
113 if (this.docCollect == 1)
114 sb.append("VALUES (?, ?)");
115 else
116 sb.append("SELECT ?, ?");
117 }
118
Nils Diewald8d8641b2014-09-28 17:37:53 +0000119 // MySQL batch insertion idiom
Nils Diewaldf04e1002014-09-24 22:52:59 +0000120 else if (this.getDatabaseType().equals("mysql")) {
121 sb.append(" VALUES ");
122 for (int i = 1; i < this.docCollect; i++) {
123 sb.append("(?,?),");
124 };
125 sb.append("(?,?)");
126 }
Nils Diewald8d8641b2014-09-28 17:37:53 +0000127
128 // Unknown idiom
Nils Diewaldf04e1002014-09-24 22:52:59 +0000129 else {
130 log.error("Unsupported Database type");
131 return;
132 };
133
Nils Diewald8d8641b2014-09-28 17:37:53 +0000134 // Prepare statement based on the string
135 PreparedStatement prep = this.connection.prepareStatement(sb.toString());
Nils Diewaldf04e1002014-09-24 22:52:59 +0000136
137 int i = 1;
138 ListIterator li = this.matchCollector.listIterator();
139 while (li.hasNext()) {
140 int[] v = (int[]) li.next();
Nils Diewaldf04e1002014-09-24 22:52:59 +0000141 prep.setInt(i++, v[0]);
Nils Diewaldf04e1002014-09-24 22:52:59 +0000142 prep.setInt(i++, v[1]);
Nils Diewaldf04e1002014-09-24 22:52:59 +0000143 };
144
Nils Diewaldf04e1002014-09-24 22:52:59 +0000145 prep.addBatch();
146 prep.executeBatch();
Nils Diewald8d8641b2014-09-28 17:37:53 +0000147 this.connection.commit();
Nils Diewaldf04e1002014-09-24 22:52:59 +0000148 }
Nils Diewald8d8641b2014-09-28 17:37:53 +0000149
150 // An SQL error occured ...
Nils Diewaldf04e1002014-09-24 22:52:59 +0000151 catch (SQLException e) {
Nils Diewaldf04e1002014-09-24 22:52:59 +0000152 log.error(e.getLocalizedMessage());
153 };
Nils Diewald8d8641b2014-09-28 17:37:53 +0000154
155 this.matchCollector.clear();
156 this.docCollect = 0;
Nils Diewaldf04e1002014-09-24 22:52:59 +0000157 return;
Nils Diewaldad3f3032014-09-24 01:42:47 +0000158 };
159
Nils Diewald8d8641b2014-09-28 17:37:53 +0000160 /*
161 * Close collector and connection
162 */
Nils Diewaldad3f3032014-09-24 01:42:47 +0000163 public void close () {
164 this.commit();
165 try {
166 this.connection.close();
167 }
Nils Diewald8d8641b2014-09-28 17:37:53 +0000168 catch (SQLException e) {
169 log.warn(e.getLocalizedMessage());
170 }
171 };
172
173 /*
174 * Close collector and probably connection
175 */
176 public void close (boolean close) {
177 if (close)
178 this.close();
179 else
180 this.commit();
Nils Diewald6aa929e2014-09-17 13:30:34 +0000181 };
182};