package squill.query; import static squill.util.StringUtil.join; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import squill.alias.Alias; import squill.db.TypedSQLException; import squill.format.Sql92Format; import squill.query.from.FromExpression; import squill.query.from.JoinElement; import squill.query.from.OrmJoin; import squill.query.orderby.OrderByElement; import squill.query.select.Column; import squill.query.select.ReadableTable; import squill.tree.QueryPartHandler; import squill.tree.TreeTraverser; import squill.util.StringUtil; public class FromPart implements QueryPart { // list of tables to select from private final List<ReadableTable> tableList = new ArrayList<ReadableTable>(); private final List<JoinElement> joinList = new ArrayList<JoinElement>(); // list of all used table aliases protected final Collection<String> tableAliases = new HashSet<String>(); private final QueryContext ctx; public FromPart(QueryContext ctx) { this.ctx = ctx; } protected void addTable(ReadableTable... tables) { this.tableList.addAll(Arrays.asList(tables)); // register all used table aliases for validating purposes for (ReadableTable table : tables) { table.setQueryContext(ctx); //registerTableAlias(table.getAlias()); } } /** * Register using of alias in order to check the uniqueness of all aliases * * @param alias Alias that is being used in query. */ // protected void registerTableAlias(String alias) { // tableAliases.add(alias); // } /** * Return comma separated list of tablenames. Select has to owerwrite this to * include JOINs */ public String getTablesWithAliasesSql() { return StringUtil.join(tableList, Sql92Format.GET_FROM_SQL, ", "); } public String getTablesSql() { return join(getTableList(), ReadableTable.GET_NAME, ", "); } public List<ReadableTable> getTableList() { return Collections.unmodifiableList(tableList); } protected void addJoin(FromExpression join) { if (join instanceof OrmJoin) join = new JoinElement((OrmJoin) join); ((JoinElement) join).setQueryContext(ctx); this.joinList.add((JoinElement) join); //registerTableAlias(((JoinElement) join).getTable().getAlias()); } public String getJoinSql() { return StringUtil.join(joinList, Sql92Format.GET_FROM_SQL, ""); } public <T> void traverse(final QueryPartHandler<T> handler, final T collectingParameter) { TreeTraverser traverser = new TreeTraverser(); traverser.traverse(this, handler, collectingParameter); for (ReadableTable table : getTableList()) { traverser.traverse(table, handler, collectingParameter); } for (JoinElement joinElement : joinList) { traverser.traverse(joinElement, handler, collectingParameter); } } public void checkOrderByOccurrence(final OrderByElement<?> orderby) { if (orderby.getSelectExpr() instanceof Column) { Column field = (Column) orderby.getSelectExpr(); if (!this.tableAliases.contains(field.getTable().getAlias())) { // Order by against object not present in from/join throw new TypedSQLException("Orderby expression '" + orderby.getDefaultSql() + "' not found inside from/join"); } } } public String getDefaultSql() { return " FROM " + getTablesWithAliasesSql() + getJoinSql(); } public List<Object> getSqlArguments() { return null; } public void addFromExpressions(FromExpression... fromExprs) { for (FromExpression fromExpr : fromExprs) { // TODO Maybe keep all in one List and sort out types during creating of SQL if (fromExpr.isJoin()) { addJoin(fromExpr); } else { addTable((ReadableTable) fromExpr); } } } public List<JoinElement> getJoinList() { return joinList; } public void setQueryContext(QueryContext ctx) { for (ReadableTable table : getTableList()) { table.setQueryContext(ctx); } for (JoinElement joinElement : joinList) { joinElement.setQueryContext(ctx); } } }