Coverage Report - org.galagosearch.core.store.SQLDocumentStore
 
Classes in this File Line Coverage Branch Coverage Complexity
SQLDocumentStore
0%
0/183
0%
0/34
0
SQLDocumentStore$1
0%
0/16
0%
0/4
0
 
 1  
 // BSD License (http://www.galagosearch.org/license)
 2  
 package org.galagosearch.core.store;
 3  
 
 4  
 import java.io.IOException;
 5  
 import java.sql.Connection;
 6  
 import java.sql.DriverManager;
 7  
 import java.sql.PreparedStatement;
 8  
 import java.sql.ResultSet;
 9  
 import java.sql.SQLException;
 10  
 import java.sql.Statement;
 11  
 import java.util.ArrayList;
 12  
 import java.util.Collection;
 13  
 import java.util.HashMap;
 14  
 import java.util.Iterator;
 15  
 import java.util.Map.Entry;
 16  
 import org.galagosearch.core.parse.Document;
 17  
 import org.galagosearch.tupleflow.Parameters;
 18  
 import org.galagosearch.tupleflow.TupleFlowParameters;
 19  
 
 20  
 /**
 21  
  *
 22  
  * @author trevor
 23  
  */
 24  0
 public class SQLDocumentStore implements Collection<Document>, DocumentStore {
 25  
     Connection connection;
 26  
     PreparedStatement insertDocument;
 27  
     PreparedStatement insertMetadata;
 28  
     PreparedStatement selectDocument;
 29  
     PreparedStatement selectDocumentByID;
 30  
     PreparedStatement selectMetadata;
 31  
     PreparedStatement insertByMetadata;
 32  
 
 33  
     public SQLDocumentStore(TupleFlowParameters parameters) throws SQLException, ClassNotFoundException {
 34  0
         this(parameters.getXML());
 35  0
     }
 36  
 
 37  
     public SQLDocumentStore(Parameters parameters) throws SQLException, ClassNotFoundException {
 38  0
         this(parameters.get("driverName"), parameters.get("databaseUrl"));
 39  0
     }
 40  
 
 41  0
     public SQLDocumentStore(String driverName, String databaseUrl) throws SQLException, ClassNotFoundException {
 42  0
         connection = connect(driverName, databaseUrl);
 43  0
         createStatements();
 44  0
     }
 45  
 
 46  
     private void createStatements() throws SQLException {
 47  
         String sql;
 48  0
         sql = "insert into documents(documentText)" +
 49  
                 "               values(?)";
 50  0
         insertDocument = connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
 51  
 
 52  0
         sql = "insert into documentMetadata(documentID, metadataKey, metadataValue)" +
 53  
                 "                      values(?, ?, ?)";
 54  0
         insertMetadata = connection.prepareStatement(sql);
 55  
 
 56  0
         sql = "select documents.documentID, documents.documentText                             " +
 57  
                 "  from documents                                                                " +
 58  
                 "  join documentMetadata on (documents.documentID = documentMetadata.documentID) " +
 59  
                 " where documentMetadata.metadataKey = ?                                         " +
 60  
                 "   and documentMetadata.metadataValue = ?                                       ";
 61  0
         selectDocument = connection.prepareStatement(sql);
 62  
 
 63  0
         sql = "select documents.documentText           " +
 64  
                 "  from documents                        " +
 65  
                 " where documentID = ?                   ";
 66  0
         selectDocumentByID = connection.prepareStatement(sql);
 67  
 
 68  0
         sql = "select metadataKey, metadataValue       " +
 69  
                 "  from documentMetadata " +
 70  
                 " where documentID = ?   ";
 71  
 
 72  0
         selectMetadata = connection.prepareStatement(sql);
 73  
 
 74  0
         sql = "insert into documentMetadata(documentID, metadataKey, metadataValue) " +
 75  
                 "select documentID, ?, ?                     " +
 76  
                 "  from documentMetadata                     " +
 77  
                 " where metadataKey = ? and metadataValue = ?";
 78  
 
 79  0
         insertByMetadata = connection.prepareStatement(sql);
 80  0
     }
 81  
 
 82  
     private static void unconditionalUpdate(Connection c, String sql) {
 83  
         try {
 84  0
             Statement s = c.createStatement();
 85  0
             s.executeUpdate(sql);
 86  0
             s.close();
 87  0
         } catch (Exception e) {
 88  0
         }
 89  0
     }
 90  
 
 91  
     public static Connection connect(String driverName, String databaseUrl) throws SQLException, ClassNotFoundException {
 92  0
         Class.forName(driverName);
 93  0
         return DriverManager.getConnection(databaseUrl);
 94  
     }
 95  
 
 96  
     public static void dropDatabase(String driverName, String databaseUrl) throws SQLException, ClassNotFoundException {
 97  0
         Connection connection = connect(driverName, databaseUrl);
 98  
 
 99  0
         unconditionalUpdate(connection, "drop table documents");
 100  0
         unconditionalUpdate(connection, "drop table documentMetadata");
 101  0
     }
 102  
 
 103  
     public static void createDatabase(String driverName, String databaseUrl) throws SQLException, ClassNotFoundException {
 104  0
         Connection connection = connect(driverName, databaseUrl);
 105  
 
 106  0
         String documentsSql = "create table documents (" +
 107  
                 "     documentID int PRIMARY KEY AUTO_INCREMENT, " +
 108  
                 "     documentText LONGTEXT                      " +
 109  
                 ") ";
 110  
 
 111  0
         String metadataSql = "create table documentMetadata (   " +
 112  
                 "     documentID int,               " +
 113  
                 "     metadataKey varchar(50),      " +
 114  
                 "     metadataValue varchar(1000)   " +
 115  
                 ") ";
 116  
 
 117  0
         unconditionalUpdate(connection, documentsSql);
 118  0
         unconditionalUpdate(connection, metadataSql);
 119  0
     }
 120  
 
 121  
     public void close() throws IOException {
 122  
         try {
 123  0
             insertMetadata.close();
 124  0
             insertDocument.close();
 125  0
             connection.close();
 126  0
         } catch (SQLException e) {
 127  0
             throw new IOException("Caught exception while closing stuff.");
 128  0
         }
 129  0
     }
 130  
 
 131  
     public synchronized boolean add(Document document) {
 132  
         try {
 133  0
             insertDocument.setString(1, document.text);
 134  0
             insertDocument.executeUpdate();
 135  
 
 136  
             // got the key set
 137  0
             ResultSet keySet = insertDocument.getGeneratedKeys();
 138  0
             if (!keySet.next()) {
 139  0
                 return false;
 140  
             }
 141  0
             long documentID = keySet.getInt(1);
 142  0
             keySet.close();
 143  
 
 144  
             // now, add in rows for the metadata
 145  0
             for (Entry<String, String> entry : document.metadata.entrySet()) {
 146  0
                 String key = entry.getKey();
 147  0
                 String value = entry.getValue();
 148  
 
 149  0
                 insertMetadata.setLong(1, documentID);
 150  0
                 insertMetadata.setString(2, key);
 151  0
                 insertMetadata.setString(3, value);
 152  0
                 insertMetadata.executeUpdate();
 153  0
                 insertMetadata.clearParameters();
 154  0
             }
 155  0
         } catch (SQLException e) {
 156  0
             throw new RuntimeException("Failed to add a document to the DocumentStore", e);
 157  0
         }
 158  
 
 159  0
         return true;
 160  
     }
 161  
 
 162  
     public synchronized void addMetadata(
 163  
             String oldKey, String oldValue,
 164  
             String newKey, String newValue) throws SQLException {
 165  0
         insertByMetadata.setString(1, newKey);
 166  0
         insertByMetadata.setString(2, newValue);
 167  
 
 168  0
         insertByMetadata.setString(3, oldKey);
 169  0
         insertByMetadata.setString(4, oldValue);
 170  
 
 171  0
         insertByMetadata.execute();
 172  0
     }
 173  
 
 174  
     public Iterator<Document> iterator() {
 175  
         final ResultSet rs;
 176  
         final boolean hn;
 177  
         final Statement statement;
 178  
 
 179  
         try {
 180  0
             String sql = "select documents.documentID " +
 181  
                     "  from documents            ";
 182  0
             statement = connection.createStatement();
 183  0
             rs = statement.executeQuery(sql);
 184  0
             hn = rs.next();
 185  
 
 186  0
             if (hn == false) {
 187  0
                 rs.close();
 188  
             }
 189  0
         } catch (SQLException e) {
 190  0
             throw new RuntimeException("Couldn't create an iterator for the DocumentStore", e);
 191  0
         }
 192  
 
 193  0
         return new Iterator<Document>() {
 194  0
             ResultSet resultSet = rs;
 195  0
             boolean hasNext = hn;
 196  
 
 197  
             public boolean hasNext() {
 198  0
                 return hasNext;
 199  
             }
 200  
 
 201  
             public Document next() {
 202  0
                 if (hasNext == false) {
 203  0
                     return null;
 204  
                 }
 205  
                 Document document;
 206  
 
 207  
                 try {
 208  0
                     long documentID = resultSet.getLong(1);
 209  0
                     document = get(documentID);
 210  0
                     hasNext = resultSet.next();
 211  
 
 212  0
                     if (hasNext == false) {
 213  0
                         resultSet.close();
 214  
                     }
 215  0
                 } catch (SQLException e) {
 216  0
                     throw new RuntimeException("Couldn't get next Document from the database", e);
 217  0
                 }
 218  
 
 219  0
                 return document;
 220  
             }
 221  
 
 222  0
             public void remove() {
 223  0
                 throw new UnsupportedOperationException(
 224  
                         "Removing documents is not supported by the DocumentStore iterator.");
 225  
             }
 226  
         };
 227  
     }
 228  
 
 229  
     public synchronized void addMetadata(long documentID, Document document) throws SQLException {
 230  0
         selectMetadata.setLong(1, documentID);
 231  0
         document.metadata = new HashMap();
 232  0
         ResultSet metadata = selectMetadata.executeQuery();
 233  
 
 234  0
         while (metadata.next()) {
 235  0
             String key = metadata.getString(1);
 236  0
             String value = metadata.getString(2);
 237  0
             document.metadata.put(key, value);
 238  0
         }
 239  
 
 240  0
         metadata.close();
 241  0
     }
 242  
 
 243  
     public synchronized Document get(String identifier) throws IOException {
 244  
         try {
 245  0
             return get("identifier", identifier);
 246  0
         } catch(SQLException e) {
 247  0
             IOException exception = new IOException("Caught a SQLException");
 248  0
             exception.initCause(e);
 249  0
             throw exception;
 250  
         }
 251  
     }
 252  
 
 253  
     public synchronized Document get(long documentID) throws SQLException {
 254  0
         Document result = new Document();
 255  0
         selectDocumentByID.setLong(1, documentID);
 256  0
         ResultSet document = selectDocumentByID.executeQuery();
 257  
         String text;
 258  
 
 259  0
         if (document.next()) {
 260  0
             text = document.getString(1);
 261  
 
 262  0
             result.text = text;
 263  0
             document.close();
 264  
         } else {
 265  0
             document.close();
 266  0
             return null;
 267  
         }
 268  
 
 269  0
         addMetadata(documentID, result);
 270  0
         return result;
 271  
     }
 272  
 
 273  
     public synchronized Document get(String metadataKey, String metadataValue) throws SQLException {
 274  0
         Document result = new Document();
 275  
 
 276  0
         selectDocument.setString(1, metadataKey);
 277  0
         selectDocument.setString(2, metadataValue);
 278  0
         ResultSet document = selectDocument.executeQuery();
 279  
 
 280  
         long documentID;
 281  
         String text;
 282  
 
 283  0
         if (document.next()) {
 284  0
             documentID = document.getLong(1);
 285  0
             text = document.getString(2);
 286  
 
 287  0
             result.text = text;
 288  0
             document.close();
 289  
         } else {
 290  0
             document.close();
 291  0
             return null;
 292  
         }
 293  
 
 294  0
         addMetadata(documentID, result);
 295  0
         return result;
 296  
     }
 297  
 
 298  
     public int size() {
 299  0
         ResultSet resultSet = null;
 300  0
         Statement statement = null;
 301  0
         int size = 0;
 302  
 
 303  
         try {
 304  0
             statement = connection.createStatement();
 305  0
             String sql = "select count(*) from documents";
 306  0
             resultSet = statement.executeQuery(sql);
 307  
 
 308  0
             if (resultSet.next()) {
 309  0
                 size = resultSet.getInt(1);
 310  0
                 resultSet.close();
 311  
             }
 312  
 
 313  0
         } catch (SQLException e) {
 314  0
             throw new RuntimeException("Size operation failed", e);
 315  
         } finally {
 316  0
             try {
 317  0
                 if (resultSet != null) {
 318  0
                     resultSet.close();
 319  
                 }
 320  0
                 if (statement != null) {
 321  0
                     statement.close();
 322  
                 }
 323  0
             } catch (SQLException e) {
 324  
                 // ignore this exception
 325  0
             }
 326  0
         }
 327  
 
 328  0
         return size;
 329  
     }
 330  
 
 331  
     public boolean isEmpty() {
 332  0
         return size() != 0;
 333  
     }
 334  
 
 335  
     public boolean contains(Document d) {
 336  0
         throw new RuntimeException("contains() is not supported by SQLDocumentStore");
 337  
     }
 338  
 
 339  
     public Document[] toArray() {
 340  0
         return toArray(new Document[0]);
 341  
     }
 342  
 
 343  
     public <T> T[] toArray(T[] example) {
 344  0
         ArrayList<Document> list = new ArrayList();
 345  
 
 346  0
         for (Document d : this) {
 347  0
             list.add(d);
 348  
         }
 349  
 
 350  0
         return list.toArray(example);
 351  
     }
 352  
 
 353  
     public boolean remove(Object o) {
 354  0
         throw new RuntimeException("remove() is not supported by SQLDocumentStore");
 355  
     }
 356  
 
 357  
     public boolean contains(Object o) {
 358  0
         throw new RuntimeException("contains() is not supported by SQLDocumentStore");
 359  
     }
 360  
 
 361  
     public boolean containsAll(Collection<?> documents) {
 362  0
         boolean doesContain = true;
 363  0
         for (Object d : documents) {
 364  0
             if (!contains(d)) {
 365  0
                 return false;
 366  
             }
 367  
         }
 368  0
         return true;
 369  
     }
 370  
 
 371  
     public boolean addAll(Collection<? extends Document> documents) {
 372  0
         for (Object d : documents) {
 373  0
             if (d instanceof Document) {
 374  0
                 add((Document) d);
 375  
             } else {
 376  0
                 return false;
 377  
             }
 378  
         }
 379  0
         return true;
 380  
     }
 381  
 
 382  
     public boolean removeAll(Collection<?> objects) {
 383  0
         for (Object o : objects) {
 384  0
             remove(o);
 385  
         }
 386  0
         return true;
 387  
     }
 388  
 
 389  
     public boolean retainAll(Collection<?> objects) {
 390  0
         throw new RuntimeException("retainAll() is not supported by SQLDocumentStore");
 391  
     }
 392  
 
 393  
     public void clear() {
 394  0
         throw new RuntimeException("clear() is not supported by SQLDocumentStore");
 395  
     }
 396  
 
 397  
     public static void main(String[] args) throws SQLException, ClassNotFoundException, IOException {
 398  0
         String driver = "com.mysql.jdbc.Driver";
 399  0
         String url = "jdbc:mysql:///document_store?user=root";
 400  
 
 401  0
         SQLDocumentStore.dropDatabase(driver, url);
 402  0
         SQLDocumentStore.createDatabase(driver, url);
 403  
 
 404  0
         SQLDocumentStore s = new SQLDocumentStore(driver, url);
 405  
 
 406  0
         Document document = new Document();
 407  0
         document.identifier = "WTX000-000-00";
 408  0
         document.metadata.put("identifier", document.identifier);
 409  0
         document.metadata.put("hi", "mom");
 410  0
         document.text = "hello!  hello!";
 411  0
         s.add(document);
 412  
 
 413  0
         s.addMetadata("hi", "mom", "initial", "test");
 414  0
         Document d = s.get("hi", "mom");
 415  
 
 416  0
         for (Document e : s) {
 417  0
             System.out.println(e.text);
 418  
         }
 419  
 
 420  0
         s.close();
 421  0
     }
 422  
 }