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.algebra;
007:
008: import java.util.ArrayList;
009: import java.util.HashMap;
010: import java.util.List;
011: import java.util.Map;
012:
013: import org.openrdf.query.algebra.QueryModelNode;
014: import org.openrdf.query.algebra.QueryModelVisitor;
015: import org.openrdf.sail.rdbms.algebra.base.FromItem;
016: import org.openrdf.sail.rdbms.algebra.base.RdbmsQueryModelVisitorBase;
017: import org.openrdf.sail.rdbms.schema.ValueTypes;
018:
019: /**
020: * An SQL UNION expression between two {@link FromItem}s.
021: *
022: * @author James Leigh
023: *
024: */
025: public class UnionItem extends FromItem {
026: private List<FromItem> union = new ArrayList<FromItem>();
027:
028: public UnionItem(String alias) {
029: super (alias);
030: }
031:
032: @Override
033: public FromItem getFromItem(String alias) {
034: for (FromItem from : union) {
035: FromItem item = from.getFromItem(alias);
036: if (item != null)
037: return item;
038: }
039: return super .getFromItem(alias);
040: }
041:
042: public List<String> getSelectVarNames() {
043: List<ColumnVar> vars = new ArrayList<ColumnVar>();
044: for (FromItem from : union) {
045: from.appendVars(vars);
046: }
047: List<String> selectVars = new ArrayList<String>();
048: for (ColumnVar var : vars) {
049: if (var.isHidden())
050: continue;
051: if (!selectVars.contains(var.getName())) {
052: selectVars.add(var.getName());
053: }
054: }
055: return selectVars;
056: }
057:
058: public List<ColumnVar> getSelectColumns() {
059: List<ColumnVar> vars = new ArrayList<ColumnVar>();
060: for (FromItem from : union) {
061: from.appendVars(vars);
062: }
063: List<ColumnVar> columns = new ArrayList<ColumnVar>();
064: Map<String, ColumnVar> selectVars = new HashMap<String, ColumnVar>();
065: for (ColumnVar var : vars) {
066: if (var.isHidden())
067: continue;
068: if (selectVars.containsKey(var.getName())) {
069: ValueTypes types = selectVars.get(var.getName())
070: .getTypes();
071: types = types.clone().merge(var.getTypes());
072: selectVars.get(var.getName()).setTypes(types);
073: } else {
074: String name = var.getAlias() + var.getColumn();
075: ColumnVar as = var.as(getAlias(), name);
076: columns.add(as);
077: selectVars.put(var.getName(), as);
078: }
079: }
080: return columns;
081: }
082:
083: @Override
084: public List<ColumnVar> appendVars(List<ColumnVar> columns) {
085: columns.addAll(getSelectColumns());
086: return super .appendVars(columns);
087: }
088:
089: @Override
090: public ColumnVar getVar(String name) {
091: for (ColumnVar var : appendVars(new ArrayList<ColumnVar>())) {
092: if (var.getName().equals(name)) {
093: return var;
094: }
095: }
096: return null;
097: }
098:
099: @Override
100: public ColumnVar getVarForChildren(String name) {
101: for (FromItem join : union) {
102: ColumnVar var = join.getVar(name);
103: if (var != null)
104: return var;
105: }
106: return super .getVarForChildren(name);
107: }
108:
109: public void addUnion(FromItem from) {
110: union.add(from);
111: from.setParentNode(this );
112: }
113:
114: public List<FromItem> getUnion() {
115: return union;
116: }
117:
118: @Override
119: public UnionItem clone() {
120: UnionItem clone = (UnionItem) super .clone();
121: clone.union = new ArrayList<FromItem>();
122: for (FromItem from : union) {
123: clone.addUnion(from.clone());
124: }
125: return clone;
126: }
127:
128: @Override
129: public <X extends Exception> void visit(
130: RdbmsQueryModelVisitorBase<X> visitor) throws X {
131: visitor.meet(this );
132: }
133:
134: @Override
135: public void replaceChildNode(QueryModelNode current,
136: QueryModelNode replacement) {
137: for (int i = 0, n = union.size(); i < n; i++) {
138: if (current == union.get(i)) {
139: union.set(i, (FromItem) replacement);
140: return;
141: }
142: }
143: super .replaceChildNode(current, replacement);
144: }
145:
146: @Override
147: public <X extends Exception> void visitChildren(
148: QueryModelVisitor<X> visitor) throws X {
149: super .visitChildren(visitor);
150: for (FromItem join : new ArrayList<FromItem>(union)) {
151: join.visit(visitor);
152: }
153: }
154:
155: }
|