| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| package org.apache.openjpa.jdbc.kernel.exps; |
| |
| import java.sql.SQLException; |
| |
| import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration; |
| import org.apache.openjpa.jdbc.meta.ClassMapping; |
| import org.apache.openjpa.jdbc.meta.JavaSQLTypes; |
| import org.apache.openjpa.jdbc.sql.Result; |
| import org.apache.openjpa.jdbc.sql.SQLBuffer; |
| import org.apache.openjpa.jdbc.sql.Select; |
| import org.apache.openjpa.kernel.Filters; |
| import org.apache.openjpa.kernel.exps.ExpressionVisitor; |
| import org.apache.openjpa.kernel.exps.QueryExpressions; |
| import org.apache.openjpa.kernel.exps.Subquery; |
| import org.apache.openjpa.meta.ClassMetaData; |
| |
| /** |
| * A subquery. |
| * |
| * @author Abe White |
| */ |
| class SubQ |
| extends AbstractVal |
| implements Subquery { |
| |
| private final ClassMapping _candidate; |
| private final boolean _subs; |
| private final String _alias; |
| private final SelectConstructor _cons = new SelectConstructor(); |
| |
| private Class _type = null; |
| private ClassMetaData _meta = null; |
| private QueryExpressions _exps = null; |
| |
| /** |
| * Constructor. Supply candidate, whether subclasses are included in |
| * the query, and the query alias. |
| */ |
| public SubQ(ClassMapping candidate, boolean subs, String alias) { |
| _candidate = candidate; |
| _subs = subs; |
| _alias = alias; |
| } |
| |
| /** |
| * Return the subquery candidate type. |
| */ |
| public ClassMapping getCandidate() { |
| return _candidate; |
| } |
| |
| public Class getType() { |
| if (_exps != null) { |
| if (_exps.projections.length == 0) |
| return _candidate.getDescribedType(); |
| if (_exps.projections.length == 1) |
| return _exps.projections[0].getType(); |
| } |
| return _type; |
| } |
| |
| public void setImplicitType(Class type) { |
| if (_exps != null && _exps.projections.length == 1) |
| _exps.projections[0].setImplicitType(type); |
| _type = type; |
| } |
| |
| public ClassMetaData getMetaData() { |
| return _meta; |
| } |
| |
| public void setMetaData(ClassMetaData meta) { |
| _meta = meta; |
| } |
| |
| public String getCandidateAlias() { |
| return _alias; |
| } |
| |
| public void setQueryExpressions(QueryExpressions query) { |
| _exps = query; |
| } |
| |
| public ExpState initialize(Select sel, ExpContext ctx, int flags) { |
| if (_exps.projections.length == 1) |
| return ((Val) _exps.projections[0]).initialize(sel, ctx, flags); |
| return ExpState.NULL; |
| } |
| |
| public Object toDataStoreValue(Select sel, ExpContext ctx, ExpState state, |
| Object val) { |
| if (_exps.projections.length == 0) |
| return _candidate.toDataStoreValue(val, |
| _candidate.getPrimaryKeyColumns(), ctx.store); |
| if (_exps.projections.length == 1) |
| return ((Val) _exps.projections[0]).toDataStoreValue(sel, ctx, |
| state, val); |
| return val; |
| } |
| |
| public void select(Select sel, ExpContext ctx, ExpState state, |
| boolean pks) { |
| selectColumns(sel, ctx, state, pks); |
| } |
| |
| public void selectColumns(Select sel, ExpContext ctx, ExpState state, |
| boolean pks) { |
| sel.select(newSQLBuffer(sel, ctx, state), this); |
| } |
| |
| public void groupBy(Select sel, ExpContext ctx, ExpState state) { |
| sel.groupBy(newSQLBuffer(sel, ctx, state)); |
| } |
| |
| public void orderBy(Select sel, ExpContext ctx, ExpState state, |
| boolean asc) { |
| sel.orderBy(newSQLBuffer(sel, ctx, state), asc, false); |
| } |
| |
| private SQLBuffer newSQLBuffer(Select sel, ExpContext ctx, ExpState state) { |
| SQLBuffer buf = new SQLBuffer(ctx.store.getDBDictionary()); |
| appendTo(sel, ctx, state, buf, 0); |
| return buf; |
| } |
| |
| public Object load(ExpContext ctx, ExpState state, Result res) |
| throws SQLException { |
| return Filters.convert(res.getObject(this, |
| JavaSQLTypes.JDBC_DEFAULT, null), getType()); |
| } |
| |
| public void calculateValue(Select sel, ExpContext ctx, ExpState state, |
| Val other, ExpState otherState) { |
| } |
| |
| public int length(Select sel, ExpContext ctx, ExpState state) { |
| return 1; |
| } |
| |
| public void appendTo(Select sel, ExpContext ctx, ExpState state, |
| SQLBuffer sql, int index) { |
| appendTo(sel, ctx, state, sql, index, false); |
| } |
| |
| private void appendTo(Select sel, ExpContext ctx, ExpState state, |
| SQLBuffer sql, int index, boolean size) { |
| QueryExpressionsState substate = new QueryExpressionsState(); |
| Select sub = _cons.evaluate(ctx, sel, _alias, _exps, substate); |
| _cons.select(sub, ctx, _candidate, _subs, _exps, substate, |
| JDBCFetchConfiguration.EAGER_NONE); |
| |
| if (size) |
| sql.appendCount(sub, ctx.fetch); |
| else |
| sql.append(sub, ctx.fetch); |
| } |
| |
| public void appendIsEmpty(Select sel, ExpContext ctx, ExpState state, |
| SQLBuffer sql) { |
| sql.append("NOT EXISTS "); |
| appendTo(sel, ctx, state, sql, 0); |
| } |
| |
| public void appendIsNotEmpty(Select sel, ExpContext ctx, ExpState state, |
| SQLBuffer sql) { |
| sql.append("EXISTS "); |
| appendTo(sel, ctx, state, sql, 0); |
| } |
| |
| public void appendSize(Select sel, ExpContext ctx, ExpState state, |
| SQLBuffer sql) { |
| appendTo(sel, ctx, state, sql, 0, true); |
| } |
| |
| public void acceptVisit(ExpressionVisitor visitor) { |
| visitor.enter(this); |
| for (int i = 0; i < _exps.projections.length; i++) |
| _exps.projections[i].acceptVisit(visitor); |
| if (_exps.filter != null) |
| _exps.filter.acceptVisit(visitor); |
| for (int i = 0; i < _exps.grouping.length; i++) |
| _exps.grouping[i].acceptVisit(visitor); |
| if (_exps.having != null) |
| _exps.having.acceptVisit(visitor); |
| for (int i = 0; i < _exps.ordering.length; i++) |
| _exps.ordering[i].acceptVisit(visitor); |
| visitor.exit(this); |
| } |
| } |