001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 2008.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.sail.rdbms.optimizers;
007:
008: import org.openrdf.query.BindingSet;
009: import org.openrdf.query.Dataset;
010: import org.openrdf.query.algebra.TupleExpr;
011: import org.openrdf.query.algebra.evaluation.QueryOptimizer;
012: import org.openrdf.sail.rdbms.algebra.BNodeColumn;
013: import org.openrdf.sail.rdbms.algebra.ColumnVar;
014: import org.openrdf.sail.rdbms.algebra.DatatypeColumn;
015: import org.openrdf.sail.rdbms.algebra.DateTimeColumn;
016: import org.openrdf.sail.rdbms.algebra.HashColumn;
017: import org.openrdf.sail.rdbms.algebra.IdColumn;
018: import org.openrdf.sail.rdbms.algebra.JoinItem;
019: import org.openrdf.sail.rdbms.algebra.LabelColumn;
020: import org.openrdf.sail.rdbms.algebra.LanguageColumn;
021: import org.openrdf.sail.rdbms.algebra.LongLabelColumn;
022: import org.openrdf.sail.rdbms.algebra.LongURIColumn;
023: import org.openrdf.sail.rdbms.algebra.NumericColumn;
024: import org.openrdf.sail.rdbms.algebra.RefIdColumn;
025: import org.openrdf.sail.rdbms.algebra.SelectQuery;
026: import org.openrdf.sail.rdbms.algebra.SqlEq;
027: import org.openrdf.sail.rdbms.algebra.URIColumn;
028: import org.openrdf.sail.rdbms.algebra.base.FromItem;
029: import org.openrdf.sail.rdbms.algebra.base.RdbmsQueryModelVisitorBase;
030: import org.openrdf.sail.rdbms.schema.BNodeTable;
031: import org.openrdf.sail.rdbms.schema.HashTable;
032: import org.openrdf.sail.rdbms.schema.LiteralTable;
033: import org.openrdf.sail.rdbms.schema.URITable;
034:
035: /**
036: * Adds LEFT JOINs to the query for value tables.
037: *
038: * @author James Leigh
039: *
040: */
041: public class ValueJoinOptimizer extends
042: RdbmsQueryModelVisitorBase<RuntimeException> implements
043: QueryOptimizer {
044: private URITable uris;
045: private BNodeTable bnodes;
046: private LiteralTable literals;
047: private HashTable hashes;
048: private FromItem join;
049: private FromItem parent;
050: private SelectQuery query;
051:
052: public void setUriTable(URITable uris) {
053: this .uris = uris;
054: }
055:
056: public void setBnodeTable(BNodeTable bnodes) {
057: this .bnodes = bnodes;
058: }
059:
060: public void setLiteralTable(LiteralTable literals) {
061: this .literals = literals;
062: }
063:
064: public void setHashTable(HashTable hashes) {
065: this .hashes = hashes;
066: }
067:
068: public void optimize(TupleExpr tupleExpr, Dataset dataset,
069: BindingSet bindings) {
070: join = null;
071: tupleExpr.visit(this );
072: }
073:
074: @Override
075: public void meetFromItem(FromItem node) throws RuntimeException {
076: FromItem top = parent;
077: parent = join;
078: join = node;
079: super .meetFromItem(node);
080: join = parent;
081: parent = top;
082: }
083:
084: @Override
085: public void meet(SelectQuery node) throws RuntimeException {
086: query = node;
087: parent = node.getFrom();
088: join = node.getFrom();
089: super .meet(node);
090: join = null;
091: parent = null;
092: query = null;
093: }
094:
095: @Override
096: public void meet(HashColumn node) throws RuntimeException {
097: if (hashes == null || hashes.getName() == null) {
098: super .meet(node);
099: } else {
100: ColumnVar var = node.getRdbmsVar();
101: String alias = "h" + getDBName(var);
102: String tableName = hashes.getName();
103: join(var, alias, tableName, false);
104: }
105: }
106:
107: @Override
108: public void meet(BNodeColumn node) throws RuntimeException {
109: ColumnVar var = node.getRdbmsVar();
110: String alias = "b" + getDBName(var);
111: String tableName = bnodes.getName();
112: join(var, alias, tableName);
113: }
114:
115: @Override
116: public void meet(DatatypeColumn node) throws RuntimeException {
117: ColumnVar var = node.getRdbmsVar();
118: String alias = "d" + getDBName(var);
119: String tableName = literals.getDatatypeTable().getName();
120: join(var, alias, tableName);
121: }
122:
123: @Override
124: public void meet(DateTimeColumn node) throws RuntimeException {
125: ColumnVar var = node.getRdbmsVar();
126: String alias = "t" + getDBName(var);
127: String tableName = literals.getDateTimeTable().getName();
128: join(var, alias, tableName);
129: }
130:
131: @Override
132: public void meet(LabelColumn node) throws RuntimeException {
133: ColumnVar var = node.getRdbmsVar();
134: String alias = "l" + getDBName(var);
135: String tableName = literals.getLabelTable().getName();
136: join(var, alias, tableName);
137: }
138:
139: @Override
140: public void meet(LongLabelColumn node) throws RuntimeException {
141: ColumnVar var = node.getRdbmsVar();
142: String alias = "ll" + getDBName(var);
143: String tableName = literals.getLongLabelTable().getName();
144: join(var, alias, tableName);
145: }
146:
147: @Override
148: public void meet(LanguageColumn node) throws RuntimeException {
149: ColumnVar var = node.getRdbmsVar();
150: String alias = "g" + getDBName(var);
151: String tableName = literals.getLanguageTable().getName();
152: join(var, alias, tableName);
153: }
154:
155: @Override
156: public void meet(NumericColumn node) throws RuntimeException {
157: ColumnVar var = node.getRdbmsVar();
158: String alias = "n" + getDBName(var);
159: String tableName = literals.getNumericTable().getName();
160: join(var, alias, tableName);
161: }
162:
163: @Override
164: public void meet(LongURIColumn node) throws RuntimeException {
165: ColumnVar var = node.getRdbmsVar();
166: String alias = "lu" + getDBName(var);
167: String tableName = uris.getLongTableName();
168: join(var, alias, tableName);
169: }
170:
171: @Override
172: public void meet(URIColumn node) throws RuntimeException {
173: ColumnVar var = node.getRdbmsVar();
174: String alias = "u" + getDBName(var);
175: String tableName = uris.getShortTableName();
176: join(var, alias, tableName);
177: }
178:
179: private CharSequence getDBName(ColumnVar var) {
180: String name = var.getName();
181: if (name.indexOf('-') >= 0)
182: return name.replace('-', '_');
183: return "_" + name; // might be a keyword otherwise
184: }
185:
186: private void join(ColumnVar var, String alias, String tableName) {
187: join(var, alias, tableName, true);
188: }
189:
190: private void join(ColumnVar var, String alias, String tableName,
191: boolean left) {
192: if (query.getFromItem(alias) == null) {
193: FromItem valueJoin = valueJoin(alias, tableName, var, left);
194: if (join == parent
195: || join.getFromItem(var.getAlias()) != null) {
196: join.addJoin(valueJoin);
197: } else {
198: parent.addJoinBefore(valueJoin, join);
199: }
200: }
201: }
202:
203: private FromItem valueJoin(String alias, String tableName,
204: ColumnVar using, boolean left) {
205: JoinItem j = new JoinItem(alias, tableName);
206: j.setLeft(left);
207: j.addFilter(new SqlEq(new IdColumn(alias), new RefIdColumn(
208: using)));
209: return j;
210: }
211: }
|