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.evaluation;
007:
008: import java.util.ArrayList;
009: import java.util.List;
010:
011: /**
012: * Facilitates the building of a JOIN or FROM clause in SQL.
013: *
014: * @author James Leigh
015: *
016: */
017: public class SqlJoinBuilder {
018: private boolean left;
019: private SqlQueryBuilder subquery;
020: private String table;
021: private String alias;
022: private QueryBuilderFactory factory;
023: private List<SqlJoinBuilder> joins = new ArrayList<SqlJoinBuilder>();
024: private SqlExprBuilder on;
025: private List<SqlJoinBuilder> leftJoins = new ArrayList<SqlJoinBuilder>();
026:
027: public SqlJoinBuilder(String table, String alias,
028: QueryBuilderFactory factory) {
029: super ();
030: this .table = table;
031: this .alias = alias;
032: this .factory = factory;
033: on = factory.createSqlExprBuilder();
034: }
035:
036: public boolean isLeft() {
037: return left;
038: }
039:
040: public void setLeft(boolean left) {
041: this .left = left;
042: }
043:
044: public String getTable() {
045: if (subquery == null)
046: return table;
047: return "( " + subquery.toString() + " )";
048: }
049:
050: public String getAlias() {
051: return alias;
052: }
053:
054: public List<SqlJoinBuilder> getLeftJoins() {
055: return leftJoins;
056: }
057:
058: public SqlJoinBuilder on(String column, String expression) {
059: on.and().column(alias, column).eq().append(expression);
060: return this ;
061: }
062:
063: public SqlJoinBuilder findJoin(String alias) {
064: if (alias.equals(this .alias))
065: return this ;
066: SqlJoinBuilder result;
067: for (SqlJoinBuilder join : joins) {
068: result = join.findJoin(alias);
069: if (result != null)
070: return result;
071: }
072: for (SqlJoinBuilder join : leftJoins) {
073: result = join.findJoin(alias);
074: if (result != null)
075: return result;
076: }
077: return null;
078: }
079:
080: public SqlJoinBuilder join(String table, String alias) {
081: SqlJoinBuilder join = findJoin(alias);
082: if (join != null)
083: return join;
084: join = factory.createSqlJoinBuilder(table, alias);
085: joins.add(join);
086: return join;
087: }
088:
089: public SqlJoinBuilder leftjoin(String table, String alias) {
090: SqlJoinBuilder join = findJoin(alias);
091: if (join != null)
092: return join;
093: join = factory.createSqlJoinBuilder(table, alias);
094: join.setLeft(true);
095: leftJoins.add(join);
096: return join;
097: }
098:
099: public SqlJoinBuilder join(String alias) {
100: SqlJoinBuilder join = findJoin(alias);
101: if (join != null)
102: return join;
103: join = factory.createSqlJoinBuilder(null, alias);
104: joins.add(join);
105: return join;
106: }
107:
108: public SqlJoinBuilder leftjoin(String alias) {
109: SqlJoinBuilder join = findJoin(alias);
110: if (join != null)
111: return join;
112: join = factory.createSqlJoinBuilder(null, alias);
113: join.setLeft(true);
114: leftJoins.add(join);
115: return join;
116: }
117:
118: public SqlQueryBuilder subquery() {
119: assert table == null : table;
120: assert subquery == null : subquery;
121: return subquery = factory.createSqlQueryBuilder();
122: }
123:
124: public SqlExprBuilder on() {
125: return on;
126: }
127:
128: @Override
129: public String toString() {
130: StringBuilder sb = new StringBuilder();
131: if (isLeft()) {
132: sb.append("LEFT ");
133: }
134: sb.append("JOIN ").append(getJoinClause());
135: sb.append(" ON (").append(on()).append(")");
136: return sb.toString();
137: }
138:
139: public CharSequence getFromClause() {
140: if (joins.isEmpty() && leftJoins.isEmpty())
141: return getTable() + " " + alias;
142: StringBuilder from = new StringBuilder();
143: from.append(getTable()).append(" ").append(alias);
144: for (SqlJoinBuilder join : joins) {
145: appendJoin(from, join);
146: }
147: for (SqlJoinBuilder left : getLeftJoins()) {
148: from.append("\n LEFT JOIN ").append(left.getJoinClause());
149: from.append(" ON (").append(left.on()).append(")");
150: }
151: return from;
152: }
153:
154: protected CharSequence getJoinClause() {
155: if (joins.isEmpty() && leftJoins.isEmpty())
156: return getTable() + " " + alias;
157: StringBuilder from = new StringBuilder();
158: from.append("(");
159: from.append(getFromClause());
160: from.append(")");
161: return from;
162: }
163:
164: protected void appendJoin(StringBuilder from, SqlJoinBuilder join) {
165: if (join.isLeft()) {
166: from.append("\n LEFT JOIN ").append(join.getJoinClause());
167: } else if (join.on().isEmpty()) {
168: from.append(getSqlCrossJoin()).append(join.getJoinClause());
169: } else {
170: from.append("\n INNER JOIN ").append(join.getJoinClause());
171: }
172: if (!join.on().isEmpty()) {
173: from.append(" ON (").append(join.on()).append(")");
174: } else if (join.isLeft()) {
175: from.append(" ON (").append(alias).append(".ctx = ")
176: .append(alias).append(".ctx)");
177: }
178: }
179:
180: protected String getSqlCrossJoin() {
181: return "\n CROSS JOIN ";
182: }
183:
184: public List<Object> findParameters(List<Object> parameters) {
185: if (subquery != null) {
186: subquery.findParameters(parameters);
187: }
188: for (SqlJoinBuilder join : joins) {
189: join.findParameters(parameters);
190: }
191: for (SqlJoinBuilder join : leftJoins) {
192: join.findParameters(parameters);
193: }
194: parameters.addAll(on.getParameters());
195: return parameters;
196: }
197: }
|