| /* |
| * 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; |
| |
| import java.sql.Connection; |
| import java.sql.PreparedStatement; |
| import java.sql.ResultSet; |
| import java.sql.SQLException; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.openjpa.jdbc.kernel.exps.ExpContext; |
| import org.apache.openjpa.jdbc.kernel.exps.QueryExpressionsState; |
| import org.apache.openjpa.jdbc.meta.ClassMapping; |
| import org.apache.openjpa.jdbc.sql.DBDictionary; |
| import org.apache.openjpa.jdbc.sql.Result; |
| import org.apache.openjpa.jdbc.sql.ResultSetResult; |
| import org.apache.openjpa.jdbc.sql.SQLBuffer; |
| import org.apache.openjpa.jdbc.sql.SQLExceptions; |
| import org.apache.openjpa.jdbc.sql.SelectImpl; |
| import org.apache.openjpa.kernel.ExpressionStoreQuery.AbstractExpressionExecutor; |
| import org.apache.openjpa.kernel.StoreQuery; |
| import org.apache.openjpa.kernel.exps.QueryExpressions; |
| import org.apache.openjpa.lib.rop.RangeResultObjectProvider; |
| import org.apache.openjpa.lib.rop.ResultObjectProvider; |
| import org.apache.openjpa.meta.ClassMetaData; |
| import org.apache.openjpa.util.InternalException; |
| |
| /** |
| * A executor for Prepared SQL Query. |
| * |
| * @author Pinaki Poddar |
| * |
| */ |
| public class PreparedSQLStoreQuery extends SQLStoreQuery { |
| private static final long serialVersionUID = 1L; |
| private PreparedQueryImpl _cached; |
| public PreparedSQLStoreQuery(JDBCStore store) { |
| super(store); |
| } |
| |
| @Override |
| public Executor newDataStoreExecutor(ClassMetaData meta, |
| boolean subclasses) { |
| return new PreparedSQLExecutor(this, meta); |
| } |
| |
| @Override |
| public boolean setQuery(Object query) { |
| if (!(query instanceof PreparedQueryImpl)) { |
| throw new InternalException(query.getClass() + " not recognized"); |
| } |
| _cached = (PreparedQueryImpl)query; |
| return true; |
| } |
| |
| PreparedQueryImpl getPreparedQuery() { |
| return _cached; |
| } |
| |
| /** |
| * Executor of a prepared query uses the QueryExpressions of the original query |
| * available via the PreparedQuery. |
| * |
| */ |
| public static class PreparedSQLExecutor extends AbstractExpressionExecutor { |
| private final ClassMetaData _meta; |
| private final PreparedSQLStoreQuery _query; |
| |
| public PreparedSQLExecutor(PreparedSQLStoreQuery q, ClassMetaData candidate) { |
| _meta = candidate; |
| _query = q; |
| } |
| |
| @Override |
| public QueryExpressions[] getQueryExpressions() { |
| return _query.getPreparedQuery().getQueryExpressions(); |
| } |
| |
| @Override |
| public Class[] getProjectionTypes(StoreQuery q) { |
| return _query.getPreparedQuery().getProjectionTypes(); |
| } |
| |
| @Override |
| public ResultObjectProvider executeQuery(StoreQuery q, Object[] params, Range range) { |
| PreparedSQLStoreQuery psq = (PreparedSQLStoreQuery) q; |
| PreparedQueryImpl pq = psq.getPreparedQuery(); |
| JDBCStore store = psq.getStore(); |
| DBDictionary dict = store.getDBDictionary(); |
| |
| SQLBuffer buf = new SQLBuffer(dict).append(pq.getTargetQuery()); |
| Connection conn = store.getConnection(); |
| JDBCFetchConfiguration fetch = (JDBCFetchConfiguration)q.getContext().getFetchConfiguration(); |
| |
| ResultObjectProvider rop; |
| PreparedStatement stmnt = null; |
| try { |
| stmnt = !range.lrs ? buf.prepareStatement(conn) : buf.prepareStatement(conn, fetch, -1, -1); |
| |
| int index = 0; |
| for (int i = 0; i < params.length; i++) { |
| dict.setUnknown(stmnt, ++index, params[i], null); |
| } |
| dict.setTimeouts(stmnt, fetch, false); |
| |
| ResultSet rs = stmnt.executeQuery(); |
| |
| SelectImpl cachedSelect = pq.getSelect(); |
| Result res = cachedSelect.getEagerResult(conn, stmnt, rs, store, fetch, false, null); |
| |
| if (getQueryExpressions()[0].projections.length > 0) { |
| ExpContext ctx = new ExpContext(store, params, fetch); |
| QueryExpressionsState state = (QueryExpressionsState)getQueryExpressions()[0].state; |
| rop = new PreparedProjectionResultObjectProvider(cachedSelect, getQueryExpressions(), |
| new QueryExpressionsState[]{state}, ctx, res); |
| } else if (q.getContext().getCandidateType() != null) { |
| rop = new PreparedResultObjectProvider(cachedSelect, |
| (ClassMapping) _meta, store, fetch, res); |
| } else { |
| rop = new SQLProjectionResultObjectProvider(store, fetch, |
| (ResultSetResult)res, q.getContext().getResultType()); |
| } |
| } catch (SQLException se) { |
| if (stmnt != null) |
| try { stmnt.close(); } catch (SQLException se2) {} |
| try { conn.close(); } catch (SQLException se2) {} |
| throw SQLExceptions.getStore(se, dict); |
| } |
| |
| if (range.start != 0 || range.end != Long.MAX_VALUE) |
| rop = new RangeResultObjectProvider(rop, range.start,range.end); |
| return rop; |
| } |
| |
| /** |
| * Convert given userParams to an array whose ordering matches as |
| * per expected during executeXXX() methods. |
| * The given userParams is already re-parameterized, so this method have |
| * to merely copy the given Map values. |
| * |
| * @see PreparedQueryImpl#reparametrize(Map, org.apache.openjpa.kernel.Broker) |
| */ |
| @Override |
| public synchronized Object[] toParameterArray(StoreQuery q, Map userParams) { |
| Object[] array = new Object[userParams.size()]; |
| |
| Set<Map.Entry<Object,Object>> userSet = userParams.entrySet(); |
| for (Map.Entry<Object,Object> userEntry : userSet) { |
| int idx = (Integer) userEntry.getKey(); |
| array[idx] = userEntry.getValue(); |
| } |
| return array; |
| } |
| } |
| } |