001: /*
002: (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: [See end of file]
004: $Id: PSet_TripleStore_RDB.java,v 1.58 2008/01/02 12:08:23 andy_seaborne Exp $
005: */
006:
007: package com.hp.hpl.jena.db.impl;
008:
009: import java.sql.BatchUpdateException;
010: import java.sql.PreparedStatement;
011: import java.sql.ResultSet;
012: import java.sql.SQLException;
013: import java.util.*;
014:
015: import com.hp.hpl.jena.db.RDFRDBException;
016: import com.hp.hpl.jena.db.impl.DriverRDB;
017: import com.hp.hpl.jena.graph.*;
018: import com.hp.hpl.jena.shared.*;
019: import com.hp.hpl.jena.util.iterator.ExtendedIterator;
020:
021: import org.apache.commons.logging.Log;
022: import org.apache.commons.logging.LogFactory;
023:
024: //=======================================================================
025: /**
026: * Handles Physical storage for implementing SpecializedGraphs.
027: * Different PSet classes are needed for different databases and different
028: * layout schemes.
029: * <p>
030: * This class is a base implemention from which database-specific
031: * drivers can inherit. It is not generic in the sense that it will work
032: * on any minimal SQL store and so should be treated as if it were
033: * an abstract class.
034: * <p>The SQL statements which implement each of the functions are
035: * loaded in a separate file etc/[layout]_[database].sql from the classpath.
036: * See {@link SQLCache SQLCache documentation} for more information on the
037: * format of this file.
038: *
039: * Based on Driver* classes by Dave Reynolds.
040: *
041: * @author <a href="mailto:harumi.kuno@hp.com">Harumi Kuno</a>
042: * @version $Revision: 1.58 $ on $Date: 2008/01/02 12:08:23 $
043: */
044:
045: public class PSet_TripleStore_RDB implements IPSet {
046:
047: //=======================================================================
048: // Cutomization variables
049:
050: /**
051: * Holds name of AssertedStatement table (defaults to JENA_SYS_AssStatements).
052: * Every triple store has at least one tables for AssertedStatements.
053: */
054: public String m_tblName = null;
055:
056: /** The SQL type to use for storing ids (compatible with wrapDBID) */
057: protected String ID_SQL_TYPE = null;
058:
059: /** Set to true if the insert operations already check for duplications */
060: protected boolean SKIP_DUPLICATE_CHECK = false;
061:
062: /** Set to true to enable cache of pre-prepared statements */
063: protected boolean CACHE_PREPARED_STATEMENTS = true;
064:
065: /** The table of sql driver statements */
066: protected SQLCache m_sql = null;
067:
068: //=======================================================================
069: // Internal variables
070:
071: /** default size for literal and resource caches */
072: protected final static int DEFAULT_CACHE = 1000;
073:
074: /** Cache of literals */
075: protected ICache literalCache = new SimpleCache(DEFAULT_CACHE);
076:
077: /** Cache of resources */
078: protected ICache resourceCache = new SimpleCache(DEFAULT_CACHE);
079:
080: /**
081: * The IRDBDriver for the database.
082: */
083: protected IRDBDriver m_driver = null;
084:
085: //=======================================================================
086: // Constructors and accessors
087:
088: /**
089: * Constructor.
090: */
091: public PSet_TripleStore_RDB() {
092: }
093:
094: /**
095: * Link an existing instance of the IPSet to a specific driver
096: */
097: public void setDriver(IRDBDriver driver) throws RDFRDBException {
098: m_driver = driver;
099: }
100:
101: protected static Log logger = LogFactory
102: .getLog(PSet_TripleStore_RDB.class);
103:
104: public void setSQLType(String value) {
105: ID_SQL_TYPE = value;
106: }
107:
108: public void setSkipDuplicateCheck(boolean value) {
109: SKIP_DUPLICATE_CHECK = value;
110: }
111:
112: public void setSQLCache(SQLCache cache) {
113: m_sql = cache;
114: }
115:
116: public SQLCache getSQLCache() {
117: return m_sql;
118: }
119:
120: public void setCachePreparedStatements(boolean value) {
121: CACHE_PREPARED_STATEMENTS = value;
122: }
123:
124: /**
125: * Sets m_tblName variable.
126: * @param tblName the name of the Statement Table
127: */
128: public void setTblName(String tblName) {
129: m_tblName = tblName;
130: }
131:
132: /**
133: * Accessor for m_tblName.
134: * @return name of the Statement table.
135: */
136: public String getTblName() {
137: return m_tblName;
138: }
139:
140: /**
141: * Close this PSet
142: */
143: public void close() {
144: // no need to do anything here for now
145: }
146:
147: /**
148: * @return the database driver.
149: */
150:
151: public IRDBDriver driver() {
152: return m_driver;
153: }
154:
155: /**
156: * Remove all RDF information about this pset from a database.
157: */
158: public void cleanDB() {
159:
160: // drop my own table(s)
161: try {
162: m_sql.runSQLGroup("dropStatementTable", getTblName());
163: } catch (SQLException e) {
164: logger.warn("Problem dropping table " + getTblName(), e);
165: throw new RDFRDBException("Failed to drop table ", e);
166: }
167:
168: }
169:
170: /**
171: * Printable name for the driver configuration
172: */
173: public String toString() {
174: return this .getClass().getPackage().getName();
175: }
176:
177: /**
178: * Fetch a literal from the cache just knowing its literal rdb-id.
179: * If it is not in the cache, do not attempt to retrieve it from the database.
180: */
181: public Node_Literal getLiteralFromCache(IDBID id) {
182: return (Node_Literal) literalCache.get(id);
183: }
184:
185: /**
186: * Convert the raw SQL object used to store a database identifier into a java object
187: * which meets the IDBID interface.
188: */
189: public IDBID wrapDBID(Object id) throws RDFRDBException {
190: if (id instanceof Number) {
191: return new DBIDInt(((Number) id).intValue());
192: } else if (id == null) {
193: return null;
194: } else {
195: throw new RDFRDBException("Unexpected DB identifier type: "
196: + id);
197: //return null;
198: }
199: }
200:
201: /**
202: * Compute the number of rows in a table.
203: *
204: * @return int count.
205: */
206: public int rowCount(int gid) {
207: String tName = getTblName();
208: int result = 0;
209: ResultSet rs = null;
210:
211: try {
212: String op = "getRowCount";
213: PreparedStatement ps = m_sql.getPreparedSQLStatement(op,
214: tName);
215: ps.setInt(1, gid);
216: rs = ps.executeQuery();
217: while (rs.next())
218: result = rs.getInt(1);
219: m_sql.returnPreparedSQLStatement(ps);
220: } catch (SQLException e) {
221: logger.debug("tried to count rows in " + tName);
222: logger.debug("Caught exception: ", e);
223: throw new JenaException("Exception during database access",
224: e); // Rethrow in case there is a recovery option
225: } finally {
226: if (rs != null)
227: try {
228: rs.close();
229: } catch (SQLException e1) {
230: throw new RDFRDBException(
231: "Failed to get last inserted ID: " + e1);
232: }
233: }
234: return result;
235: }
236:
237: //=======================================================================
238: // Patched functions to adapt to oracle jdbc driver expectations
239:
240: /**
241: * Convert the current row of a result set from a ResultSet
242: * to a Triple.
243: * Expects row to contain:
244: * S.SubjRes, S.PropRes, S.ObjRes, S.ObjStr, S.ObjLiteral
245: * @param rs the resultSet to be processed.
246: */
247: public Triple extractTripleFromRowData(String subj, String pred,
248: String obj) {
249:
250: Node subjNode = subj == null ? null : m_driver
251: .RDBStringToNode(subj);
252: Node predNode = pred == null ? null : m_driver
253: .RDBStringToNode(pred);
254: Node objNode = obj == null ? null : m_driver
255: .RDBStringToNode(obj);
256:
257: return (Triple.create(subjNode, predNode, objNode));
258: }
259:
260: /**
261: * Wrap up a boolean flag as a object which the jdbc driver can assert into a boolean/short column.
262: */
263: public Object wrapFlag(boolean flag) {
264: return flag ? new Short((short) 1) : new Short((short) 0);
265: }
266:
267: /**
268: *
269: * Attempt to remove a statement from an Asserted_Statement table,
270: * if it is present. Return without error if the statement is not
271: * present.
272: *
273: * @param subj_uri is the URI of the subject
274: * @param pred_uri is the URI of the predicate (property)
275: * @param obj_node is the URI of the object (can be URI or literal)
276: * @param graphID is the ID of the graph
277: * @param complete is true if this handler is capable of adding this triple.
278: *
279: **/
280: public void deleteTriple(Triple t, IDBID graphID) {
281: deleteTriple(t, graphID, false, null);
282: }
283:
284: /**
285: *
286: * Attempt to remove a statement from an Asserted_Statement table,
287: * if it is present. Return without error if the statement is not
288: * present.
289: *
290: * @param subj_uri is the URI of the subject
291: * @param pred_uri is the URI of the predicate (property)
292: * @param obj_node is the URI of the object (can be URI or literal)
293: * @param graphID is the ID of the graph
294: * @param complete is true if this handler is capable of adding this triple.
295: *
296: **/
297: public void deleteTriple(Triple t, IDBID graphID, boolean isBatch,
298: Hashtable batchedPreparedStatements) {
299: deleteTripleAR(t, graphID, null, isBatch,
300: batchedPreparedStatements);
301: }
302:
303: /**
304: *
305: * Attempt to remove a statement from an Asserted_Statement table,
306: * if it is present. Return without error if the statement is not
307: * present.
308: *
309: * @param subj_uri is the URI of the subject
310: * @param pred_uri is the URI of the predicate (property)
311: * @param obj_node is the URI of the object (can be URI or literal)
312: * @param stmtURI is the URI of the statement if reified, null for asserted
313: * @param graphID is the ID of the graph
314: * @param complete is true if this handler is capable of adding this triple.
315: *
316: **/
317: public void deleteTripleAR(Triple t, IDBID graphID, Node reifNode,
318: boolean isBatch, Hashtable batchedPreparedStatements) {
319: boolean isReif = reifNode != null;
320:
321: String subj = t.getSubject().equals(Node.NULL) ? null
322: : m_driver.nodeToRDBString(t.getSubject(), false);
323: String pred = t.getPredicate().equals(Node.NULL) ? null
324: : m_driver.nodeToRDBString(t.getPredicate(), false);
325: String obj = t.getObject() == Node.ANY ? null : m_driver
326: .nodeToRDBString(t.getObject(), false);
327: // String gid = graphID.getID().toString();
328: int gid = ((DBIDInt) graphID).getIntID();
329: int argc = 1;
330: String stmtStr;
331:
332: if ((subj == null) || (pred == null) || (obj == null)) {
333: // throw new JenaException("Attempt to delete triple with missing values");
334: // used to think this was an exception. i guess it's not.
335: return;
336: }
337:
338: // get statement string
339: PreparedStatement ps = null;
340: stmtStr = isReif ? "deleteReified" : "deleteStatement";
341: try {
342: ps = getPreparedStatement(stmtStr, getTblName(), isBatch,
343: batchedPreparedStatements);
344: //ps.clearParameters();
345:
346: } catch (SQLException e1) {
347: logger
348: .debug("SQLException caught " + e1.getErrorCode(),
349: e1);
350: throw new JenaException("Exception during database access",
351: e1); // Rethrow in case there is a recovery option
352: }
353:
354: // now fill in parameters
355: try {
356: ps.setString(argc++, subj);
357: ps.setString(argc++, pred);
358: ps.setString(argc++, obj);
359:
360: ps.setInt(argc++, gid);
361:
362: if (isReif) {
363: String stmtURI = m_driver.nodeToRDBString(reifNode,
364: false);
365: ps.setString(argc++, stmtURI);
366: ps.setString(argc++, "T");
367: }
368: } catch (SQLException e1) {
369: logger.debug("(in delete) SQLException caught ", e1);
370: throw new JenaException("Exception during database access",
371: e1); // Rethrow in case there is a recovery option
372: }
373:
374: try {
375: if (isBatch) {
376: ps.addBatch();
377: } else {
378: ps.executeUpdate();
379: m_sql.returnPreparedSQLStatement(ps);
380: }
381: } catch (SQLException e1) {
382: logger.error("Exception executing delete: ", e1);
383: throw new JenaException("Exception during database access",
384: e1); // Rethrow in case there is a recovery option
385: }
386: }
387:
388: /**
389: *
390: * Attempt to store a statement into an Asserted_Statement table.
391: *
392: * @param subj_uri is the URI of the subject
393: * @param pred_uri is the URI of the predicate (property)
394: * @param obj_node is the URI of the object (can be URI or literal)
395: * @param graphID is the ID of the graph
396: * @param complete is true if this handler is capable of adding this triple.
397: *
398: **/
399: public void storeTriple(Triple t, IDBID graphID) {
400: storeTriple(t, graphID, false, null);
401: }
402:
403: /**
404: * Given an operation name, a table name, whether or not this operation is part of a batched update, and
405: * a table of batched prepared statements, find or create an appropriate PreparedStatement.
406: *
407: * @param op
408: * @param tableName
409: * @param isBatch
410: * @param batchedPreparedStatements
411: * @return the prepared statement
412: * @throws SQLException
413: */
414: public PreparedStatement getPreparedStatement(String op,
415: String tableName, boolean isBatch,
416: Hashtable batchedPreparedStatements) throws SQLException {
417: PreparedStatement ps = null;
418: String opname = SQLCache.concatOpName(op, tableName);
419: if (isBatch) {
420: ps = (PreparedStatement) batchedPreparedStatements
421: .get(opname);
422: if (ps == null) {
423: ps = m_sql.getPreparedSQLStatement(op, tableName);
424: batchedPreparedStatements.put(opname, ps);
425: }
426: } else {
427: ps = m_sql.getPreparedSQLStatement(op, tableName);
428: }
429:
430: if (ps == null) {
431: logger.error("prepared statement not found for " + opname);
432: }
433: return ps;
434: }
435:
436: /**
437: *
438: * Attempt to store a statement into an Asserted_Statement table.
439: *
440: * @param subj_uri is the URI of the subject
441: * @param pred_uri is the URI of the predicate (property)
442: * @param obj_node is the URI of the object (can be URI or literal)
443: * @param graphID is the ID of the graph
444: * @param isBatch is true if this request is part of a batch operation.
445: *
446: **/
447: public void storeTriple(Triple t, IDBID graphID, boolean isBatch,
448: Hashtable batchedPreparedStatements) {
449: storeTripleAR(t, graphID, null, false, isBatch,
450: batchedPreparedStatements);
451: }
452:
453: /**
454: *
455: * Attempt to store a statement into an Asserted_Statement table.
456: *
457: * @param subj_uri is the URI of the subject
458: * @param pred_uri is the URI of the predicate (property)
459: * @param obj_node is the URI of the object (can be URI or literal)
460: * @param stmtURI is the URI of the statement if reified, null for asserted
461: * @param hasType is true if the hasType flag should be set for a reified stmt
462: * @param graphID is the ID of the graph
463: * @param isBatch is true if this request is part of a batch operation.
464: *
465: **/
466: public void storeTripleAR(Triple t, IDBID graphID, Node reifNode,
467: boolean hasType, boolean isBatch,
468: Hashtable batchedPreparedStatements) {
469: String objURI;
470: Object obj_val;
471: boolean isReif = reifNode != null;
472:
473: // if database doesn't perform duplicate check
474: if (!SKIP_DUPLICATE_CHECK && !isReif) {
475: // if statement already in table
476: if (statementTableContains(graphID, t)) {
477: return;
478: }
479: }
480:
481: String obj_res, obj_lex, obj_lit;
482: // TODO: Node.NULL is only valid for reif triple stores. should check this.
483: String subj = t.getSubject().equals(Node.NULL) ? null
484: : m_driver.nodeToRDBString(t.getSubject(), true);
485: String pred = t.getPredicate().equals(Node.NULL) ? null
486: : m_driver.nodeToRDBString(t.getPredicate(), true);
487: String obj = t.getObject().equals(Node.NULL) ? null : m_driver
488: .nodeToRDBString(t.getObject(), true);
489: // String gid = graphID.getID().toString();
490: int gid = ((DBIDInt) graphID).getIntID();
491:
492: int argc = 1;
493: String stmtStr;
494:
495: if ((subj == null) || (pred == null) || (obj == null)) {
496: if (!isReif)
497: throw new JenaException(
498: "Attempt to assert triple with missing values");
499: }
500: // get statement string
501:
502: PreparedStatement ps = null;
503: stmtStr = isReif ? "insertReified" : "insertStatement";
504: try {
505: ps = getPreparedStatement(stmtStr, getTblName(), isBatch,
506: batchedPreparedStatements);
507: //ps.clearParameters();
508:
509: } catch (SQLException e1) {
510: logger
511: .debug("SQLException caught " + e1.getErrorCode(),
512: e1);
513: throw new JenaException("Exception during database access",
514: e1); // Rethrow in case there is a recovery option
515: }
516: // now fill in parameters
517: try {
518: if (subj == null)
519: ps.setNull(argc++, java.sql.Types.VARCHAR);
520: else
521: ps.setString(argc++, subj);
522: if (pred == null)
523: ps.setNull(argc++, java.sql.Types.VARCHAR);
524: else
525: ps.setString(argc++, pred);
526: if (obj == null)
527: ps.setNull(argc++, java.sql.Types.VARCHAR);
528: else
529: ps.setString(argc++, obj);
530:
531: // add graph id and, if reifying, stmturi and hastype
532: ps.setInt(argc++, gid);
533: if (isReif) {
534: String stmtURI = m_driver.nodeToRDBString(reifNode,
535: true);
536: ps.setString(argc++, stmtURI);
537: if (hasType == true)
538: ps.setString(argc++, "T");
539: else
540: ps.setString(argc++, " "); // not nullable
541: }
542:
543: } catch (SQLException e1) {
544: logger
545: .debug("SQLException caught " + e1.getErrorCode(),
546: e1);
547: throw new JenaException("Exception during database access",
548: e1); // Rethrow in case there is a recovery option
549: }
550:
551: try {
552: if (isBatch) {
553: ps.addBatch();
554: } else {
555: ps.executeUpdate();
556: m_sql.returnPreparedSQLStatement(ps);
557: }
558: //ps.close();
559: } catch (SQLException e1) {
560: // we let Oracle handle duplicate checking
561: if (!((e1.getErrorCode() == 1) && (m_driver
562: .getDatabaseType().equalsIgnoreCase("oracle")))) {
563: logger.error("SQLException caught during insert"
564: + e1.getErrorCode(), e1);
565: throw new JenaException(
566: "Exception during database access", e1);
567: }
568: }
569: }
570:
571: /**
572: * Attempt to add a list of triples to the specialized graph.
573: *
574: * As each triple is successfully added it is removed from the List. If
575: * complete is true then the entire List was added and the List will be
576: * empty upon return. if complete is false, then at least one triple remains
577: * in the List.
578: *
579: * If a triple can't be stored for any reason other than incompatability
580: * (for example, a lack of disk space) then the implemenation should throw a
581: * runtime exception.
582: *
583: * @param triples
584: * List of triples to be added. This is modified by the call.
585: * @param my_GID
586: * ID of the graph.
587: */
588: public void storeTripleList(List triples, IDBID my_GID) {
589: // for relational dbs, there are two styles for bulk inserts.
590: // JDBC 2.0 supports batched updates.
591: // MySQL also supports a multiple-row insert.
592: // For now, we support only jdbc 2.0 batched updates
593: /** Set of PreparedStatements that need executeBatch() * */
594: Triple t;
595: String cmd;
596: boolean autoState = false;
597: DriverRDB drvr = (DriverRDB) m_driver;
598: Iterator it = triples.iterator();
599: Hashtable batchedPreparedStatements = null;
600:
601: if (SKIP_DUPLICATE_CHECK == false) {
602: // if ( false ) {
603: while (it.hasNext()) {
604: t = (Triple) it.next();
605: storeTriple(t, my_GID, false, null);
606: }
607: } else
608: try {
609: autoState = drvr.xactOp(DriverRDB.xactAutoOff);
610: batchedPreparedStatements = new Hashtable();
611: while (it.hasNext()) {
612: t = (Triple) it.next();
613: storeTriple(t, my_GID, true,
614: batchedPreparedStatements);
615: }
616:
617: Enumeration en = batchedPreparedStatements.keys();
618: while (en.hasMoreElements()) {
619: String op = (String) en.nextElement();
620: PreparedStatement p = (PreparedStatement) batchedPreparedStatements
621: .get(op);
622: p.executeBatch();
623: batchedPreparedStatements.remove(op);
624: m_sql.returnPreparedSQLStatement(p);
625: }
626: if (autoState) {
627: drvr.xactOp(DriverRDB.xactCommit);
628: drvr.xactOp(DriverRDB.xactAutoOn);
629: }
630: batchedPreparedStatements = null;
631:
632: // WARNING: caught exceptions should drop through to return.
633: // if not, be sure to reset autocommit before exiting.
634:
635: } catch (BatchUpdateException b) {
636: System.err.println("SQLException: " + b.getMessage());
637: System.err.println("SQLState: " + b.getSQLState());
638: System.err.println("Message: " + b.getMessage());
639: System.err.println("Vendor: " + b.getErrorCode());
640: System.err.print("Update counts: ");
641: int[] updateCounts = b.getUpdateCounts();
642: for (int i = 0; i < updateCounts.length; i++) {
643: System.err.print(updateCounts[i] + " ");
644: }
645: if (autoState)
646: drvr.xactOp(DriverRDB.xactAutoOn);
647: } catch (SQLException ex) {
648: System.err.println("SQLException: " + ex.getMessage());
649: System.err.println("SQLState: " + ex.getSQLState());
650: System.err.println("Message: " + ex.getMessage());
651: System.err.println("Vendor: " + ex.getErrorCode());
652: if (autoState)
653: drvr.xactOp(DriverRDB.xactAutoOn);
654: } finally {
655: if (batchedPreparedStatements != null) {
656: Enumeration en = batchedPreparedStatements.keys();
657: while (en.hasMoreElements()) {
658: String op = (String) en.nextElement();
659: PreparedStatement p = (PreparedStatement) batchedPreparedStatements
660: .get(op);
661: batchedPreparedStatements.remove(op);
662: m_sql.returnPreparedSQLStatement(p);
663: }
664: }
665: }
666: ArrayList c = new ArrayList(triples);
667: triples.removeAll(c);
668: }
669:
670: /**
671: * Attempt to remove a list of triples from the specialized graph.
672: *
673: * As each triple is successfully deleted it is removed from the List. If
674: * complete is true then the entire List was added and the List will be
675: * empty upon return. if complete is false, then at least one triple remains
676: * in the List.
677: *
678: * If a triple can't be stored for any reason other than incompatability
679: * (for example, a lack of disk space) then the implemenation should throw a
680: * runtime exception.
681: *
682: * @param triples
683: * List of triples to be added. This is modified by the call.
684: * @param my_GID
685: * ID of the graph.
686: */
687: public void deleteTripleList(List triples, IDBID my_GID) {
688: // for relational dbs, there are two styles for bulk operations.
689: // JDBC 2.0 supports batched updates.
690: // MySQL also supports a multiple-row update.
691: // For now, we support only jdbc 2.0 batched updates
692:
693: /** Set of PreparedStatements that need executeBatch() * */
694: Hashtable batchedPreparedStatements = null;
695: Triple t;
696: String cmd;
697: boolean autoState = false;
698: DriverRDB drvr = (DriverRDB) m_driver;
699: Iterator it = triples.iterator();
700:
701: if (SKIP_DUPLICATE_CHECK == false) {
702: // if ( false ) {
703:
704: while (it.hasNext()) {
705: t = (Triple) it.next();
706: deleteTriple(t, my_GID, false, null);
707: }
708: } else
709: try {
710: autoState = drvr.xactOp(DriverRDB.xactAutoOff);
711: batchedPreparedStatements = new Hashtable();
712: while (it.hasNext()) {
713: t = (Triple) it.next();
714: deleteTriple(t, my_GID, true,
715: batchedPreparedStatements);
716: }
717:
718: Enumeration en = batchedPreparedStatements.keys();
719: while (en.hasMoreElements()) {
720: String op = (String) en.nextElement();
721: PreparedStatement p = (PreparedStatement) batchedPreparedStatements
722: .get(op);
723: p.executeBatch();
724: batchedPreparedStatements.remove(op);
725: m_sql.returnPreparedSQLStatement(p);
726: }
727: if (autoState) {
728: drvr.xactOp(DriverRDB.xactCommit);
729: drvr.xactOp(DriverRDB.xactAutoOn);
730: }
731: batchedPreparedStatements = null;
732:
733: // WARNING: caught exceptions should drop through to return.
734: // if not, be sure to reset autocommit before exiting.
735:
736: } catch (BatchUpdateException b) {
737: System.err.println("SQLException: " + b.getMessage());
738: System.err.println("SQLState: " + b.getSQLState());
739: System.err.println("Message: " + b.getMessage());
740: System.err.println("Vendor: " + b.getErrorCode());
741: System.err.print("Update counts: ");
742: int[] updateCounts = b.getUpdateCounts();
743: for (int i = 0; i < updateCounts.length; i++) {
744: System.err.print(updateCounts[i] + " ");
745: }
746: if (autoState)
747: drvr.xactOp(DriverRDB.xactAutoOn);
748: } catch (SQLException ex) {
749: System.err.println("SQLException: " + ex.getMessage());
750: System.err.println("SQLState: " + ex.getSQLState());
751: System.err.println("Message: " + ex.getMessage());
752: System.err.println("Vendor: " + ex.getErrorCode());
753: if (autoState)
754: drvr.xactOp(DriverRDB.xactAutoOn);
755: } finally {
756: if (batchedPreparedStatements != null) {
757: Enumeration en = batchedPreparedStatements.keys();
758: while (en.hasMoreElements()) {
759: String op = (String) en.nextElement();
760: PreparedStatement p = (PreparedStatement) batchedPreparedStatements
761: .get(op);
762: batchedPreparedStatements.remove(op);
763: m_sql.returnPreparedSQLStatement(p);
764: }
765: }
766: }
767: ArrayList c = new ArrayList(triples);
768: triples.removeAll(c);
769: }
770:
771: /**
772: * Compute the number of unique triples added to the Specialized Graph.
773: *
774: * @return int count.
775: */
776: public int tripleCount(IDBID graphId) {
777: int gid = ((DBIDInt) graphId).getIntID();
778: return (rowCount(gid));
779: }
780:
781: /**
782: * Tests if a triple is contained in the specialized graph.
783: * @param t is the triple to be tested
784: * @param graphID is the id of the graph.
785: * @return boolean result to indicte if the tripple was contained
786: */
787: public boolean statementTableContains(IDBID graphID, Triple t) {
788: ExtendedIterator it = find(t, graphID);
789: boolean res = it.hasNext();
790: it.close();
791: return res;
792: }
793:
794: /* (non-Javadoc)
795: * @see com.hp.hpl.jena.db.impl.IPSet#find(com.hp.hpl.jena.graph.TripleMatch, com.hp.hpl.jena.db.impl.IDBID)
796: */
797: public ExtendedIterator find(TripleMatch t, IDBID graphID) {
798: String astName = getTblName();
799: Node subj_node = t.getMatchSubject();
800: Node pred_node = t.getMatchPredicate();
801: Node obj_node = t.getMatchObject();
802: Node_Literal objLit;
803: // String gid = graphID.getID().toString();
804: int gid = ((DBIDInt) graphID).getIntID();
805: boolean notFound = false;
806: int hack = 0;
807:
808: ResultSetTripleIterator result = new ResultSetTripleIterator(
809: this , graphID);
810:
811: PreparedStatement ps = null;
812:
813: String subj = null;
814: String pred = null;
815: String obj = null;
816: String op = "selectStatement";
817: String qual = "";
818: int args = 1;
819: if (hack != 0) {
820: subj_node = pred_node = obj_node = null;
821: }
822: if (subj_node != null) {
823: subj = m_driver.nodeToRDBString(subj_node, false);
824: if (subj == null)
825: notFound = true;
826: else
827: qual += "S";
828: }
829: if (pred_node != null) {
830: pred = m_driver.nodeToRDBString(pred_node, false);
831: if (pred == null)
832: notFound = true;
833: else
834: qual += "P";
835: }
836: if (obj_node != null) {
837: obj = m_driver.nodeToRDBString(obj_node, false);
838: if (obj == null)
839: notFound = true;
840: else
841: qual += "O";
842: }
843: if (notFound == false)
844: try {
845: op += qual;
846: /*
847: ps = m_sql.getPreparedSQLStatement(op, getTblName());
848: if ( qual.equals("") ) {
849: ps = m_sql.getPreparedSQLStatement(op+"Limit", getTblName(),Integer.toString(gid));
850:
851: // Statement stmt = m_driver.getConnection().getConnection().createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
852: // java.sql.ResultSet.CONCUR_READ_ONLY);
853: // stmt.setFetchSize(10);
854: // String qry = "SELECT S.Subj, S.Prop, S.Obj FROM " + getTblName() + " S WHERE S.GraphID = "
855: // + gid;
856: // ResultSet res = stmt.executeQuery(qry);
857: result = new ResultSetLimitTripleIter(this, graphID);
858: } else {
859: //*/
860: ps = m_sql.getPreparedSQLStatement(op, getTblName());
861: if (obj != null)
862: ps.setString(args++, obj);
863: if (subj != null)
864: ps.setString(args++, subj);
865: if (pred != null)
866: ps.setString(args++, pred);
867:
868: ps.setInt(args++, gid);
869: //*/ }
870: m_sql.executeSQL(ps, op, result);
871:
872: //m_sql.returnPreparedSQLStatement(ps,op);
873: } catch (Exception e) {
874: notFound = true;
875: logger.debug("find encountered exception: args=" + args
876: + " err: ", e);
877: throw new JenaException(
878: "Exception during database access", e); // Rethrow in case there is a recovery option
879: }
880:
881: if (notFound)
882: result.close();
883: return (new TripleMatchIterator(t.asTriple(), result));
884: }
885:
886: /* (non-Javadoc)
887: * @see com.hp.hpl.jena.graphRDB.IPSet#removeStatementsFromDB()
888: */
889: public void removeStatementsFromDB(IDBID graphID) {
890: // TODO optimise in the case where
891: String gid = graphID.getID().toString();
892:
893: try {
894: PreparedStatement ps = m_sql.getPreparedSQLStatement(
895: "removeRowsFromTable", getTblName());
896: ps.clearParameters();
897:
898: ps.setString(1, gid);
899: ps.executeUpdate();
900: m_sql.returnPreparedSQLStatement(ps);
901: } catch (SQLException e) {
902: logger.error("Problem removing statements from table: ", e);
903: throw new JenaException("Exception during database access",
904: e); // Rethrow in case there is a recovery option
905: }
906: }
907: }
908:
909: /*
910: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
911: * All rights reserved.
912: *
913: * Redistribution and use in source and binary forms, with or without
914: * modification, are permitted provided that the following conditions
915: * are met:
916: * 1. Redistributions of source code must retain the above copyright
917: * notice, this list of conditions and the following disclaimer.
918: * 2. Redistributions in binary form must reproduce the above copyright
919: * notice, this list of conditions and the following disclaimer in the
920: * documentation and/or other materials provided with the distribution.
921: * 3. The name of the author may not be used to endorse or promote products
922: * derived from this software without specific prior written permission.
923:
924: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
925: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
926: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
927: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
928: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
929: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
930: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
931: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
932: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
933: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
934: */
|