blob: 62bc4c71252562218afde1a35f133964686c0a28 [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 /*
21 Todo: In case there are multiple threads searching,
22 the list should be synchrinized Collections.synchronizedList()
23 */
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 Diewaldf04e1002014-09-24 22:52:59 +000029 // private Connection connection;
30 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 Diewaldf04e1002014-09-24 22:52:59 +000067 public void setDBPool (String type, DataSource ds) throws SQLException {
Nils Diewaldad3f3032014-09-24 01:42:47 +000068 this.setDatabaseType(type);
Nils Diewaldf04e1002014-09-24 22:52:59 +000069 this.pool = ds;
Nils Diewaldad3f3032014-09-24 01:42:47 +000070
71 // Create prepared statement for multiple requests
72
73 /*
74 this.prepared = this.conn.prepareStatement(
75 "INSERT INTO people VALUES (?, ?);"
76 );
77
78 Only prepare if commit > buffersize!
79Difference between mariadb and sqlite!
80 */
81
82 };
83
Nils Diewaldf04e1002014-09-24 22:52:59 +000084 /* TODO: Ensure the commit was successful! */
Nils Diewaldad3f3032014-09-24 01:42:47 +000085 public void commit () {
Nils Diewaldf04e1002014-09-24 22:52:59 +000086 if (this.pool == null)
87 return;
Nils Diewaldad3f3032014-09-24 01:42:47 +000088
Nils Diewaldf04e1002014-09-24 22:52:59 +000089 try {
90 // This should be heavily optimized! It's aweful!
91 /*
92 * ARGHHHHHHH!
93 */
94
95 if (this.connection == null)
96 this.connection = this.pool.getConnection();
97
98 // TODO: Create a BEGIN ... COMMIT Transaction
99 // connection.setAutoCommit(true);
100
101 StringBuilder sb = new StringBuilder();
102 sb.append("INSERT INTO ");
103 sb.append(this.resultID);
104 sb.append(" (text_id, match_count) ");
105
106 // SQLite insertion idiom
107 if (this.getDatabaseType().equals("sqlite")) {
108 for (int i = 1; i < this.docCollect; i++) {
109 sb.append("SELECT ?, ? UNION ");
110 }
111 if (this.docCollect == 1)
112 sb.append("VALUES (?, ?)");
113 else
114 sb.append("SELECT ?, ?");
115 }
116
117 // MySQL insertion idiom
118 else if (this.getDatabaseType().equals("mysql")) {
119 sb.append(" VALUES ");
120 for (int i = 1; i < this.docCollect; i++) {
121 sb.append("(?,?),");
122 };
123 sb.append("(?,?)");
124 }
125 else {
126 log.error("Unsupported Database type");
127 return;
128 };
129
130 // System.err.println(sb.toString());
131
132 PreparedStatement prep = connection.prepareStatement(sb.toString());
133
134 int i = 1;
135 ListIterator li = this.matchCollector.listIterator();
136 while (li.hasNext()) {
137 int[] v = (int[]) li.next();
138 // System.err.println("Has " + i + ":" + v[0]);
139 prep.setInt(i++, v[0]);
140 // System.err.println("Has " + i + ":" + v[1]);
141 prep.setInt(i++, v[1]);
142 // System.err.println("-");
143 };
144
145 // System.err.println(sb.toString());
146
147 prep.addBatch();
148 prep.executeBatch();
149 // connection.setAutoCommit(false);
150 // connection.close();
151 this.matchCollector.clear();
152 this.docCollect = 0;
153 }
154 catch (SQLException e) {
155 this.matchCollector.clear();
156 this.docCollect = 0;
157 System.err.println("Error: " + e.getLocalizedMessage());
158 log.error(e.getLocalizedMessage());
159 };
160 return;
Nils Diewaldad3f3032014-09-24 01:42:47 +0000161 };
162
163 public void close () {
164 this.commit();
Nils Diewaldf04e1002014-09-24 22:52:59 +0000165 /*
Nils Diewaldad3f3032014-09-24 01:42:47 +0000166 try {
167 this.connection.close();
168 }
169 catch (SQLException e) {
170 };
Nils Diewaldf04e1002014-09-24 22:52:59 +0000171 */
Nils Diewald6aa929e2014-09-17 13:30:34 +0000172 };
173};