001: /*
002: (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: [See end of file]
004: */
005:
006: package com.hp.hpl.jena.db.impl;
007:
008: import java.sql.PreparedStatement;
009: import java.sql.SQLException;
010: import java.util.List;
011:
012: import com.hp.hpl.jena.graph.*;
013: import com.hp.hpl.jena.shared.*;
014: import com.hp.hpl.jena.graph.impl.LiteralLabel;
015: import com.hp.hpl.jena.util.iterator.ExtendedIterator;
016: import com.hp.hpl.jena.util.iterator.Map1;
017: import com.hp.hpl.jena.db.RDFRDBException;
018:
019: import com.hp.hpl.jena.vocabulary.RDF;
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.29 $ on $Date: 2008/01/02 12:08:24 $
043: */
044:
045: public class PSet_ReifStore_RDB extends PSet_TripleStore_RDB {
046:
047: //=======================================================================
048: // Internal variables
049:
050: protected static Log logger = LogFactory
051: .getLog(PSet_ReifStore_RDB.class);
052:
053: //=======================================================================
054: // Constructors and accessors
055:
056: /**
057: * Constructor.
058: */
059: public PSet_ReifStore_RDB() {
060: }
061:
062: //=======================================================================
063:
064: // Database operations
065:
066: public void storeReifStmt(Node n, Triple t, IDBID my_GID) {
067: storeTripleAR(t, my_GID, n, true, false, null);
068: }
069:
070: public void deleteReifStmt(Node n, Triple t, IDBID my_GID) {
071: deleteTripleAR(t, my_GID, n, false, null);
072: }
073:
074: /* (non-Javadoc)
075: * @see com.hp.hpl.jena.db.impl.IPSet#find(com.hp.hpl.jena.graph.TripleMatch, com.hp.hpl.jena.db.impl.IDBID)
076: */
077: public ResultSetReifIterator findReifStmt(Node stmtURI,
078: boolean hasType, IDBID graphID, boolean getTriples) {
079: String astName = getTblName();
080: String gid = graphID.getID().toString();
081: ResultSetReifIterator result = new ResultSetReifIterator(this ,
082: getTriples, graphID);
083:
084: PreparedStatement ps = null;
085:
086: boolean objIsBlankOrURI = false;
087: int args = 1;
088: String stmtStr;
089: boolean findAll = (stmtURI == null) || stmtURI.equals(Node.ANY);
090: boolean notFound = false;
091:
092: if (findAll)
093: stmtStr = hasType ? "selectReifiedT" : "selectReified";
094: else
095: stmtStr = hasType ? "selectReifiedNT" : "selectReifiedN";
096: try {
097: ps = m_sql.getPreparedSQLStatement(stmtStr, getTblName());
098:
099: if (!findAll) {
100: String stmt_uri = m_driver.nodeToRDBString(stmtURI,
101: false);
102: if (stmt_uri == null)
103: notFound = true;
104: else
105: ps.setString(args++, stmt_uri);
106: }
107: if (hasType)
108: ps.setString(args++, "T");
109:
110: ps.setString(args++, gid);
111:
112: } catch (Exception e) {
113: notFound = true;
114: logger.warn("Getting prepared statement for " + stmtStr
115: + " Caught exception ", e);
116: throw new JenaException("Exception during database access",
117: e); // Rethrow in case there is a recovery option
118: }
119:
120: if (notFound)
121: result.close();
122: else {
123: try {
124: m_sql.executeSQL(ps, stmtStr, result);
125: } catch (Exception e) {
126: logger.debug("find encountered exception ", e);
127: throw new JenaException(
128: "Exception during database access", e); // Rethrow in case there is a recovery option
129: }
130: }
131: return result;
132: }
133:
134: public ResultSetReifIterator findReifTripleMatch(TripleMatch t,
135: IDBID graphID) {
136: String astName = getTblName();
137: String gid = graphID.getID().toString();
138: ResultSetReifIterator result = new ResultSetReifIterator(this ,
139: true, graphID);
140: PreparedStatement ps = null;
141:
142: String stmtStr = "*findReif ";
143: boolean gotStmt = false;
144: boolean gotPred = false;
145: boolean gotObj = false;
146: boolean objIsStmt = false;
147: char reifProp = ' ';
148: String objNode = null;
149: boolean done = false;
150: int argc = 1;
151:
152: Node stmtURI = t.getMatchSubject();
153: Node obj = t.getMatchObject();
154: Node pred = t.getMatchPredicate();
155:
156: if ((stmtURI != null) && !stmtURI.equals(Node.ANY)) {
157: gotStmt = true;
158: stmtStr += "N";
159: }
160: if ((pred != null) && !pred.equals(Node.ANY)) {
161: gotPred = true;
162: if (pred.equals(RDF.Nodes.subject))
163: reifProp = 'S';
164: else if (pred.equals(RDF.Nodes.predicate))
165: reifProp = 'P';
166: else if (pred.equals(RDF.Nodes.object))
167: reifProp = 'O';
168: else if (pred.equals(RDF.Nodes.type))
169: reifProp = 'T';
170: else
171: done = true;
172: stmtStr += ("P" + reifProp);
173: }
174: if ((obj != null) && !obj.equals(Node.ANY)) {
175: gotObj = true;
176: stmtStr += "O";
177: if (obj.equals(RDF.Nodes.Statement)) {
178: objIsStmt = true;
179: stmtStr += "C";
180: } else if (reifProp == 'T')
181: // reifier only stores patterns like (-, rdf:type, rdf:Statement)
182: done = true;
183: }
184:
185: if (done == false)
186: try {
187: ps = m_sql.getPreparedSQLStatement(stmtStr,
188: getTblName());
189: ps.setString(argc++, gid);
190: if (gotStmt) {
191: String stmtNode = m_driver.nodeToRDBString(stmtURI,
192: false);
193: if (stmtNode == null)
194: done = true;
195: else
196: ps.setString(argc++, stmtNode);
197: }
198: if (gotObj) {
199: // no arguments in case match is <-,rdf:type,rdf:Statement>
200: if (!(gotPred && objIsStmt)) {
201: objNode = m_driver.nodeToRDBString(obj, false);
202: ps.setString(argc++, objNode);
203: if (gotPred == false) {
204: // if no predicate, object value could be in subj, pred or obj column
205: ps.setString(argc++, objNode);
206: ps.setString(argc++, objNode);
207: }
208: }
209: }
210:
211: } catch (Exception e) {
212: done = true;
213: logger.warn("Getting prepared statement for " + stmtStr
214: + " Caught exception ", e);
215: throw new JenaException(
216: "Exception during database access", e); // Rethrow in case there is a recovery option
217: }
218:
219: if (done) {
220: result.close();
221: } else {
222: if (gotPred) {
223: result.close();
224: result = new ResultSetReifIterator(this , reifProp,
225: graphID);
226: } else if (gotObj) {
227: result.close();
228: result = new ResultSetReifIterator(this , obj, graphID);
229: }
230: try {
231: m_sql.executeSQL(ps, stmtStr, result);
232: } catch (Exception e) {
233: logger.debug("find encountered exception ", e);
234: throw new JenaException(
235: "Exception during database access", e); // Rethrow in case there is a recovery option
236: }
237: }
238: return result;
239: }
240:
241: /*
242: * (non-Javadoc)
243: * return all nodes which reify the triple as a statement. no
244: * need to do distinct here since we only return nodes for reified statments.
245: */
246:
247: public ExtendedIterator findReifStmtURIByTriple(Triple t,
248: IDBID my_GID) {
249: String stmtStr = null;
250: int argc = 1;
251: PreparedStatement ps = null;
252: ResultSetIterator result = new ResultSetNodeIterator();
253: boolean notFound = false;
254:
255: stmtStr = "selectReifNode";
256: stmtStr += (t == null) ? "T" : "SPOT";
257:
258: try {
259: ps = m_sql.getPreparedSQLStatement(stmtStr, getTblName());
260: ps.clearParameters();
261:
262: if (t != null) {
263: String argStr;
264: argStr = m_driver
265: .nodeToRDBString(t.getSubject(), false);
266: if (argStr == null)
267: notFound = true;
268: else
269: ps.setString(argc++, argStr);
270: argStr = m_driver.nodeToRDBString(t.getPredicate(),
271: false);
272: if (argStr == null)
273: notFound = true;
274: else
275: ps.setString(argc++, argStr);
276: argStr = m_driver.nodeToRDBString(t.getObject(), false);
277: if (argStr == null)
278: notFound = true;
279: else
280: ps.setString(argc++, argStr);
281: }
282:
283: ps.setString(argc, my_GID.getID().toString());
284: } catch (Exception e) {
285: notFound = true;
286: logger.warn("Getting prepared statement for " + stmtStr
287: + " Caught exception ", e);
288: throw new JenaException("Exception during database access",
289: e); // Rethrow in case there is a recovery option
290: }
291:
292: // find on object field
293: if (notFound)
294: result.close();
295: else {
296: try {
297: m_sql.executeSQL(ps, stmtStr, result);
298: } catch (Exception e) {
299: logger.debug("find encountered exception ", e);
300: throw new JenaException(
301: "Exception during database access", e); // Rethrow in case there is a recovery option
302: }
303: }
304: return result.mapWith(new MapResultSetToNode());
305: }
306:
307: private class MapResultSetToNode implements Map1 {
308:
309: /* (non-Javadoc)
310: * @see com.hp.hpl.jena.util.iterator.Map1#map1(java.lang.Object)
311: */
312: public Object map1(Object o) {
313: // TODO Auto-generated method stub
314: List l = (List) o;
315: // TODO we have a BUG here somewhere, hence the message.
316: String s = null;
317: Object n = l.get(0);
318: if ((n instanceof String) || (n instanceof Byte))
319: s = (String) n;
320: else
321: throw new JenaException("String required: "
322: + l.get(0).getClass() + " " + l.get(0));
323: Node r = m_driver.RDBStringToNode(s);
324: return r;
325: }
326:
327: }
328:
329: /* (non-Javadoc)
330: * return (distinct) nodes which reify something (have any fragment)
331: */
332:
333: public ExtendedIterator findReifNodes(Node stmtURI, IDBID graphID) {
334: String astName = getTblName();
335: String gid = graphID.getID().toString();
336: ResultSetIterator result = new ResultSetNodeIterator();
337: int argc = 1;
338: PreparedStatement ps = null;
339: boolean notFound = false;
340:
341: String stmtStr = stmtURI == null ? "selectReifNode"
342: : "selectReifNodeN";
343: try {
344: ps = m_sql.getPreparedSQLStatement(stmtStr, getTblName());
345:
346: if (stmtURI != null) {
347: String stmt_uri = m_driver.nodeToRDBString(stmtURI,
348: false);
349: if (stmtURI == null)
350: notFound = true;
351: else
352: ps.setString(argc++, stmt_uri);
353: }
354:
355: ps.setString(argc, gid);
356:
357: } catch (Exception e) {
358: notFound = true;
359: logger.warn("Getting prepared statement for " + stmtStr
360: + " Caught exception ", e);
361: throw new JenaException("Exception during database access",
362: e); // Rethrow in case there is a recovery option
363: }
364:
365: if (notFound)
366: result.close();
367: else
368: try {
369: result = m_sql.executeSQL(ps, stmtStr, result);
370: } catch (Exception e) {
371: logger.debug("find encountered exception ", e);
372: throw new JenaException(
373: "Exception during database access", e); // Rethrow in case there is a recovery option
374: }
375: return result;
376: }
377:
378: public void storeFrag(Node stmtURI, Triple frag,
379: ReificationStatementMask fragMask, IDBID my_GID) {
380: Node subj = fragMask.hasSubj() ? frag.getObject() : Node.NULL;
381: Node prop = fragMask.hasPred() ? frag.getObject() : Node.NULL;
382: Node obj = fragMask.hasObj() ? frag.getObject() : Node.NULL;
383: Triple t = Triple.create(subj, prop, obj);
384: storeTripleAR(t, my_GID, stmtURI, fragMask.hasType(), false,
385: null);
386: }
387:
388: public void updateOneFrag(Node stmtURI, Triple frag,
389: ReificationStatementMask fragMask, boolean nullify,
390: IDBID my_GID) {
391:
392: String stmtStr = null;
393: Node val = null;
394: int argc = 1;
395: String argStr;
396:
397: if (!fragMask.hasOneBit())
398: throw new JenaException(
399: "Reification can only update one column");
400: PreparedStatement ps = null;
401:
402: if (fragMask.hasSubj()) {
403: stmtStr = "updateReifiedS";
404: if (!nullify)
405: val = frag.getObject();
406: } else if (fragMask.hasPred()) {
407: stmtStr = "updateReifiedP";
408: if (!nullify)
409: val = frag.getObject();
410: } else if (fragMask.hasObj()) {
411: stmtStr = "updateReifiedO";
412: if (!nullify)
413: val = frag.getObject();
414: } else if (fragMask.hasType()) {
415: stmtStr = "updateReifiedT";
416: }
417:
418: try {
419: try {
420: ps = m_sql.getPreparedSQLStatement(stmtStr,
421: getTblName());
422: ps.clearParameters();
423: if (fragMask.hasSubj() || fragMask.hasPred()
424: || fragMask.hasObj()) {
425: if (nullify)
426: ps.setNull(argc++, java.sql.Types.VARCHAR);
427: else {
428: argStr = m_driver.nodeToRDBString(val, true);
429: if (argStr == null)
430: throw new RDFRDBException(
431: "Invalid update argument: "
432: + val.toString());
433: ps.setString(argc++, argStr);
434: }
435: } else {
436: // update hasType field
437: if (nullify)
438: ps.setString(argc++, " "); // not nullable
439: else
440: ps.setString(argc++, "T");
441: }
442: argStr = m_driver.nodeToRDBString(stmtURI, true);
443: if (argStr == null)
444: throw new RDFRDBException(
445: "Invalid update statement URI: "
446: + stmtURI.toString());
447: ps.setString(argc++, argStr);
448:
449: ps.setString(argc++, my_GID.getID().toString());
450: } catch (Exception e) {
451: logger.warn("Getting prepared statement for " + stmtStr
452: + " Caught exception ", e);
453: throw new JenaException(
454: "Exception during database access", e); // Rethrow in case there is a recovery option
455: }
456: try {
457: ps.executeUpdate();
458: } catch (SQLException e1) {
459: logger.error(
460: "SQLException caught during reification update"
461: + e1.getErrorCode(), e1);
462: throw new JenaException(
463: "Exception during database access", e1); // Rethrow in case there is a recovery option
464: }
465: } finally {
466: if (ps != null)
467: m_sql.returnPreparedSQLStatement(ps);
468: }
469: }
470:
471: public void nullifyFrag(Node stmtURI,
472: ReificationStatementMask fragMask, IDBID my_GID) {
473: updateOneFrag(stmtURI, null, fragMask, true, my_GID);
474: }
475:
476: public void updateFrag(Node stmtURI, Triple frag,
477: ReificationStatementMask fragMask, IDBID my_GID) {
478: updateOneFrag(stmtURI, frag, fragMask, false, my_GID);
479: }
480:
481: public ResultSetReifIterator findFrag(Node stmtURI, Triple frag,
482: ReificationStatementMask fragMask, IDBID my_GID) {
483:
484: String stmtStr = null;
485: Node val = null;
486: int argc = 1;
487: ResultSetReifIterator result = new ResultSetReifIterator(this ,
488: true, my_GID);
489: boolean notFound = false;
490: String argStr;
491:
492: Node_Literal litNode = null;
493: LiteralLabel ll = null;
494: String lval = null;
495: boolean litIsPlain = false;
496: boolean objIsURI = false;
497:
498: if (!fragMask.hasOneBit())
499: throw new JenaException(
500: "Reification can only find one column");
501: PreparedStatement ps = null;
502:
503: val = frag.getObject();
504: if (fragMask.hasSubj()) {
505: stmtStr = "selectReifiedNS";
506: } else if (fragMask.hasPred()) {
507: stmtStr = "selectReifiedNP";
508: } else if (fragMask.hasObj()) {
509: stmtStr = "selectReifiedNO";
510: } else if (fragMask.hasType()) {
511: stmtStr = "selectReifiedNT";
512: }
513:
514: try {
515: ps = m_sql.getPreparedSQLStatement(stmtStr, getTblName());
516: ps.clearParameters();
517: argStr = m_driver.nodeToRDBString(stmtURI, false);
518: if (argStr == null)
519: notFound = true;
520: else
521: ps.setString(argc++, argStr);
522: if (fragMask.hasSubj() || fragMask.hasPred()
523: || fragMask.hasObj()) {
524: argStr = m_driver.nodeToRDBString(val, false);
525: if (argStr == null)
526: notFound = true;
527: else
528: ps.setString(argc++, argStr);
529: } else {
530: // find on hasType field
531: ps.setString(argc++, "T");
532: }
533: ps.setString(argc, my_GID.getID().toString());
534:
535: } catch (Exception e) {
536: logger.warn("Getting prepared statement for " + stmtStr
537: + " Caught exception ", e);
538: throw new JenaException("Exception during database access",
539: e); // Rethrow in case there is a recovery option
540: }
541:
542: if (notFound)
543: result.close();
544: else
545: try {
546: m_sql.executeSQL(ps, stmtStr, result);
547: } catch (Exception e) {
548: logger.debug("find encountered exception ", e);
549: throw new JenaException(
550: "Exception during database access", e); // Rethrow in case there is a recovery option
551: }
552: return result;
553: }
554:
555: public void deleteFrag(Triple frag,
556: ReificationStatementMask fragMask, IDBID my_GID) {
557:
558: if (!fragMask.hasOneBit())
559: throw new JenaException("Can only delete one fragment");
560: int argc = 1;
561:
562: PreparedStatement ps = null;
563: String stmtStr = "deleteReified";
564: if (fragMask.hasSubj())
565: stmtStr += "S";
566: else if (fragMask.hasPred())
567: stmtStr += "P";
568: else if (fragMask.hasObj())
569: stmtStr += "O";
570: else if (fragMask.hasType())
571: stmtStr += "T";
572: else
573: throw new JenaException(
574: "Unspecified reification fragment in deleteFrag");
575:
576: Node val = frag.getObject();
577: String argStr = m_driver.nodeToRDBString(val, false);
578: Node stmtURI = frag.getSubject();
579: String uriStr = m_driver.nodeToRDBString(stmtURI, false);
580:
581: try {
582: try {
583: ps = m_sql.getPreparedSQLStatement(stmtStr,
584: getTblName());
585: ps.clearParameters();
586:
587: if (fragMask.hasSubj())
588: ps.setString(argc++, argStr);
589: else if (fragMask.hasPred())
590: ps.setString(argc++, argStr);
591: else if (fragMask.hasObj())
592: ps.setString(argc++, argStr);
593: ps.setString(argc++, my_GID.getID().toString());
594: ps.setString(argc, uriStr);
595:
596: } catch (Exception e) {
597: logger.warn("Getting prepared statement for " + stmtStr
598: + " Caught exception ", e);
599: throw new JenaException(
600: "Exception during database access", e); // Rethrow in case there is a recovery option
601: }
602: try {
603: ps.executeUpdate();
604: } catch (Exception e) {
605: logger.debug("deleteFrag encountered exception ", e);
606: throw new JenaException(
607: "Exception during database access", e); // Rethrow in case there is a recovery option
608: }
609: } finally {
610: if (ps != null)
611: m_sql.returnPreparedSQLStatement(ps);
612: }
613: return;
614: }
615: }
616: /*
617: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
618: * All rights reserved.
619: *
620: * Redistribution and use in source and binary forms, with or without
621: * modification, are permitted provided that the following conditions
622: * are met:
623: * 1. Redistributions of source code must retain the above copyright
624: * notice, this list of conditions and the following disclaimer.
625: * 2. Redistributions in binary form must reproduce the above copyright
626: * notice, this list of conditions and the following disclaimer in the
627: * documentation and/or other materials provided with the distribution.
628: * 3. The name of the author may not be used to endorse or promote products
629: * derived from this software without specific prior written permission.
630:
631: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
632: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
633: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
634: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
635: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
636: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
637: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
638: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
639: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
640: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
641: */
|