/*
* (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Florent Guillaume
*/
package org.nuxeo.ecm.core.storage.sql.jdbc.db;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import org.nuxeo.ecm.core.storage.sql.jdbc.dialect.Dialect;
/**
* A SQL JOIN.
*/
public class Join implements Serializable, Comparable<Join> {
private static final long serialVersionUID = 1L;
public static final int INNER = 1;
public static final int LEFT = 2;
public static final int RIGHT = 3;
public static final int IMPLICIT = 4;
/** INNER / LEFT / RIGHT / IMPLICIT */
public final int kind;
/** Table name. */
public final String table;
/** Table alias, or {@code null}. */
public final String tableAlias;
/**
* Parameter if table name is an expression that contains a "?", or {@code null}.
*/
public final String tableParam;
/** Left part of equijoin. */
public Column column1;
/** Right part of equijoin. */
public Column column2;
/** Left part of equijoin. */
public String on1;
/** Right part of equijoin. */
public String on2;
/** Additional WHERE clauses. */
public final List<String> whereClauses = new LinkedList<String>();
/** Additional WHERE clauses parameters. */
public final List<Serializable> whereParams = new LinkedList<Serializable>();
private Join(int kind, String table, String tableAlias, String tableParam) {
this.kind = kind;
this.table = table;
this.tableAlias = tableAlias;
this.tableParam = tableParam;
}
public Join(int kind, String table, String tableAlias, String tableParam, Column column1, Column column2) {
this(kind, table, tableAlias, tableParam);
this.column1 = column1;
this.column2 = column2;
}
public Join(int kind, String table, String tableAlias, String tableParam, String on1, String on2) {
this(kind, table, tableAlias, tableParam);
this.on1 = on1;
this.on2 = on2;
}
public void addWhereClause(String whereClause, Serializable whereParam) {
whereClauses.add(whereClause);
whereParams.add(whereParam);
}
// make sure IMPLICIT joins are last
@Override
public int compareTo(Join other) {
if (kind == IMPLICIT && other.kind == IMPLICIT) {
return 0;
}
if (kind == IMPLICIT) {
return 1;
}
if (other.kind == IMPLICIT) {
return -1;
}
return 0;
}
public String getTable(Dialect dialect) {
if (tableAlias == null) {
return table;
} else {
return table + " " + dialect.openQuote() + tableAlias + dialect.closeQuote();
}
}
public String getClause(Dialect dialect) {
if (on1 == null && on2 == null) {
on1 = column1.getFullQuotedName();
on2 = column2.getFullQuotedName();
boolean isid1 = column1.getType().isId();
boolean isid2 = column2.getType().isId();
if (dialect != null && isid1 != isid2) {
// temporary fix cast uuid to varchar because relation table
// has varchar source and target field
if (isid1) {
on1 = dialect.castIdToVarchar(on1);
} else {
on2 = dialect.castIdToVarchar(on2);
}
}
}
return on1 + " = " + on2;
}
/**
* Does not return the WHERE clause.
* <p>
* {@inheritDoc}
*/
public String toSql(Dialect dialect) {
switch (kind) {
case INNER:
return String.format(" JOIN %s ON %s", getTable(dialect), getClause(dialect));
case LEFT:
return String.format(" LEFT JOIN %s ON %s", getTable(dialect), getClause(dialect));
case RIGHT:
return String.format(" RIGHT JOIN %s ON %s", getTable(dialect), getClause(dialect));
case IMPLICIT:
return String.format(", %s", getTable(dialect));
default:
throw new AssertionError();
}
}
@Override
public String toString() {
String k;
switch (kind) {
case INNER:
k = "INNER";
break;
case LEFT:
k = "LEFT";
break;
case RIGHT:
k = "RIGHT";
break;
case IMPLICIT:
k = "IMPLICIT";
break;
default:
throw new AssertionError();
}
StringBuilder buf = new StringBuilder();
buf.append("<");
buf.append(k);
buf.append(" JOIN ");
buf.append(table);
if (tableAlias != null) {
buf.append(" ");
buf.append(tableAlias);
}
buf.append(" ON ");
buf.append(getClause(null));
if (!whereClauses.isEmpty()) {
buf.append(" WHERE ");
buf.append(whereClauses);
buf.append(" % ");
buf.append(whereParams);
}
buf.append(">");
return buf.toString();
}
}