001: /*
002: * (c) Copyright 2002, 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.util.List;
009:
010: import com.hp.hpl.jena.graph.*;
011: import com.hp.hpl.jena.graph.query.*;
012: import com.hp.hpl.jena.shared.JenaException;
013: import com.hp.hpl.jena.vocabulary.RDF;
014:
015: import java.util.*;
016:
017: import org.apache.commons.logging.*;
018:
019: /**
020: @author kers
021: <br>
022: PatternStageCompiler serves two purposes: it contains the standard algorithm
023: for compiling patterns-as-triples to patterns-as-Pattern(s), and it has the
024: standard implementation of PatternCompiler in terms of ordinary Elements.
025: */
026: public final class DBQueryStageCompiler {
027: protected static Log logger = LogFactory
028: .getLog(DBQueryStageCompiler.class);
029:
030: public DBQueryStageCompiler() {
031: }
032:
033: /**
034: to compile an array of triples, compile each triple and form the corresponding
035: array of Patterns. *preserve the order*.
036: */
037: public static DBQuery compile(DBQueryStageCompiler compiler,
038: DBQueryHandler qh, SpecializedGraph sg, List varList,
039: List dbPat, ExpressionSet constraints) {
040: DBQuery query = new DBQuery(sg, varList, qh.queryOnlyStmt,
041: qh.queryOnlyReif, qh.queryFullReif);
042: if (qh.getQueryOnlyReified() && !qh.getQueryFullReified())
043: throw new JenaException(
044: "Fastpath currently requires QueryFullReified to be true if QueryOnlyReified is also true");
045: if (!query.isEmpty) {
046: for (int i = 0; i < dbPat.size(); i += 1)
047: compilePattern(compiler, query, (DBPattern) dbPat
048: .get(i));
049: compileConstraints(compiler, query, constraints);
050: compileQuery(compiler, query);
051: }
052: if (logger.isDebugEnabled())
053: logger.debug("generated SQL: " + query.stmt);
054: return query;
055: }
056:
057: /**
058: compile a triple pattern.
059: */
060:
061: private static void compilePattern(DBQueryStageCompiler compiler,
062: DBQuery query, DBPattern dbpat) {
063: Element subj = dbpat.S;
064: Element obj = dbpat.O;
065: Element pred = dbpat.P;
066: String qual = "";
067: int alias = query.aliasCnt;
068:
069: if (query.isReifier) {
070: boolean newAlias = true;
071: if (!(pred instanceof Fixed))
072: throw new JenaException("Reifier predicate not bound");
073: Node p = ((Fixed) pred).asNodeMatch((Domain) null);
074: char reifProp = getReificationChar(p);
075: if (!subj.equals(Element.ANY)) {
076: // optionally do join optimization for reification.
077: // if the subject is joined with another pattern and
078: // that subject is already bound, skip the join.
079: if (query.qryFullReif
080: && (subj instanceof Free)
081: && query.getBinding(((Free) subj).getListing())
082: .isBoundToCol()) {
083: alias = (query.getBinding(((Free) subj)
084: .getListing())).alias;
085: newAlias = false;
086: } else
087: qual = query.sqlAnd.gen(getQual(query, alias, 'N',
088: subj));
089: }
090: qual += query.sqlAnd.gen(getQual(query, alias, reifProp,
091: obj));
092: qual += query.sqlAnd.gen(query.driver.genSQLQualGraphId(
093: alias, query.graphId));
094: if (newAlias)
095: query.newAlias();
096:
097: } else {
098: // query over triple table
099: qual = query.sqlAnd.gen(getQual(query, alias, 'S', subj));
100: qual += query.sqlAnd.gen(getQual(query, alias, 'P', pred));
101: qual += query.sqlAnd.gen(getQual(query, alias, 'O', obj));
102: qual += query.sqlAnd.gen(query.driver.genSQLQualGraphId(
103: alias, query.graphId));
104: query.newAlias();
105: }
106: query.stmt += qual;
107: }
108:
109: /**
110: Answer the character S, P, O, or T which describes this predicate node.
111: Throw an exception if it's not one of rdf: subject/predicate/object/type.
112: @param p the predicate node to be tested
113: @return the (manky) character code
114: */
115: private static char getReificationChar(Node p) {
116: if (p.equals(RDF.Nodes.subject))
117: return 'S';
118: else if (p.equals(RDF.Nodes.predicate))
119: return 'P';
120: else if (p.equals(RDF.Nodes.object))
121: return 'O';
122: else if (p.equals(RDF.Nodes.type))
123: return 'T';
124: else
125: throw new JenaException("Unexpected reifier predicate: "
126: + p);
127: }
128:
129: private static String getQual(DBQuery query, int alias, char pred,
130: Element spo) {
131: String qual = "";
132: if (spo instanceof Fixed) {
133: Node obj = ((Fixed) spo).asNodeMatch((Domain) null);
134: if (query.isReifier)
135: qual = query.driver.genSQLReifQualConst(alias, pred,
136: obj);
137: else
138: qual = query.driver.genSQLQualConst(alias, pred, obj);
139: } else if (spo instanceof Free) {
140: Free v = (Free) spo;
141: VarDesc bind = query.getBinding(v.getListing());
142: // only bind to argument value for first use of variable.
143: // subsequent references should join to first binding.
144: if (v.isArg() && !bind.isBoundToCol) {
145: query.argCnt++;
146: query.argType += pred;
147: query.argIndex.add(new Integer(v.getMapping()));
148: qual = query.driver.genSQLQualParam(alias, pred);
149: bind.bindToCol(alias, pred);
150: } else {
151: if (bind.isBoundToCol()) {
152: qual = query.driver.genSQLJoin(bind.alias,
153: bind.column, alias, pred);
154: } else {
155: // nothing to compare. just binding the var to the column
156: bind.bindToCol(alias, pred);
157: qual = "";
158: }
159: }
160: } else if (spo != Element.ANY)
161: throw new JenaException("Invalid Element in qualifier");
162: return qual;
163: }
164:
165: /**
166: compile the constraints.
167: */
168: private static void compileConstraints(
169: DBQueryStageCompiler compiler, DBQuery query,
170: ExpressionSet constraints) {
171: Iterator it = constraints.iterator();
172: while (it.hasNext()) {
173: Expression e = (Expression) it.next();
174: VarDesc bind = query.findBinding(e.getArg(0).getName());
175: if (bind == null)
176: throw new JenaException(
177: "Unbound variable in constraint");
178: String strMat = ((Expression.Fixed) e.getArg(1)).toString();
179: query.stmt += query.sqlAnd.gen(query.driver
180: .genSQLStringMatch(bind.alias, bind.column, e
181: .getFun(), strMat));
182: }
183: }
184:
185: /**
186: compile the final form of the query statement.
187: */
188: private static void compileQuery(DBQueryStageCompiler compiler,
189: DBQuery query) {
190: // create result list
191: int resCnt = query.vars.length - query.argCnt;
192: query.resList = new int[resCnt];
193: query.stmt = query.driver.genSQLSelectStmt(query.driver
194: .genSQLResList(query.resList, query.vars), query.driver
195: .genSQLFromList(query.aliasCnt, query.table),
196: query.stmt);
197: }
198:
199: }
200:
201: /*
202: * (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
203: * All rights reserved.
204: *
205: * Redistribution and use in source and binary forms, with or without
206: * modification, are permitted provided that the following conditions
207: * are met:
208: * 1. Redistributions of source code must retain the above copyright
209: * notice, this list of conditions and the following disclaimer.
210: * 2. Redistributions in binary form must reproduce the above copyright
211: * notice, this list of conditions and the following disclaimer in the
212: * documentation and/or other materials provided with the distribution.
213: * 3. The name of the author may not be used to endorse or promote products
214: * derived from this software without specific prior written permission.
215: *
216: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
217: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
218: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
219: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
220: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
221: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
222: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
223: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
224: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
225: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
226: */
|