001: /**
002: * Objective Database Abstraction Layer (ODAL)
003: * Copyright (c) 2004, The ODAL Development Group
004: * All rights reserved.
005: * For definition of the ODAL Development Group please refer to LICENCE.txt file
006: *
007: * Distributable under LGPL license.
008: * See terms of license at gnu.org.
009: */package com.completex.objective.components.persistency.core.impl;
010:
011: import com.completex.objective.components.log.Log;
012: import com.completex.objective.components.persistency.AbstractParameters;
013: import com.completex.objective.components.persistency.BasicQuery;
014: import com.completex.objective.components.persistency.Call;
015: import com.completex.objective.components.persistency.CallParameter;
016: import com.completex.objective.components.persistency.CallParameters;
017: import com.completex.objective.components.persistency.LifeCycleController;
018: import com.completex.objective.components.persistency.ResultableQueryManager;
019: import com.completex.objective.components.persistency.core.ResultSetCtl;
020: import com.completex.objective.components.persistency.core.ResultSetExecutor;
021: import com.completex.objective.components.persistency.core.ResultSetIterator;
022: import com.completex.objective.components.persistency.core.impl.query.QueryContext;
023: import com.completex.objective.components.persistency.transact.Transaction;
024: import com.completex.objective.components.persistency.type.ArrayListCollectionFactory;
025: import com.completex.objective.components.persistency.type.MultipartCollection;
026:
027: import java.sql.CallableStatement;
028: import java.sql.PreparedStatement;
029: import java.sql.ResultSet;
030: import java.sql.SQLException;
031: import java.util.Collection;
032:
033: /**
034: * @author Gennady Krizhevsky
035: */
036: public class RefCursorResultSetExecutor extends
037: AbstractResultSetExecutor implements ResultSetExecutor {
038:
039: RefCursorResultSetExecutor() {
040: }
041:
042: public RefCursorResultSetExecutor(Log logger,
043: BasicDatabasePersistencyImpl persistency,
044: ResultSetCtl resultSetCtl) {
045: super (logger, persistency, resultSetCtl);
046: }
047:
048: public void execute(Transaction transaction,
049: PreparedStatement statement, ResultableQueryManager query,
050: ResultSetCtl resultSetCtl, MultipartCollection results,
051: LifeCycleController controller, boolean firstOnly,
052: QueryContext queryContext) throws SQLException {
053: CallableStatement callableStatement = (CallableStatement) statement;
054: statement.execute();
055: Call call = (Call) query;
056: ResultSet[] resultSets = extract(callableStatement, call
057: .getParameters());
058: for (int i = 0; i < resultSets.length; i++) {
059: ResultSet resultSet = resultSets[i];
060: if (i == 0 || !firstOnly) {
061: resultSetCtl.retrieve(transaction, query, resultSet, i,
062: results, controller, queryContext);
063: } else {
064: closeRs(resultSet);
065: }
066: }
067: }
068:
069: public Collection executeFetch(DatabaseTransactionImpl transaction,
070: ResultableQueryManager query, ResultSetCtl resultSetCtl,
071: LifeCycleController controller, QueryContext queryContext)
072: throws SQLException {
073: if (query.getState() == BasicQuery.STATE_CLOSED) {
074: BasicDatabasePersistencyImpl.warn(logger,
075: "Attempt to executeQueryFetch from closed query");
076: return query.getMultipleResultFactory()
077: .nullCollectionFactory().newCollection();
078: }
079: query.setRetrievedCount(0);
080: MultiResultSetWrapper resultSetWrapper = (MultiResultSetWrapper) query
081: .getResultSetWrapper();
082: PreparedStatementWrapper statementWrapper = query
083: .getStatementWrapper();
084: PreparedStatement statement = statementWrapper.getStatement();
085: ResultSet currentResultSet;
086: //
087: // Execute query if this is the 1st time we access it:
088: //
089: executeStatementIfNeeded(resultSetWrapper, statement, query);
090: MultipartCollection results = new MultipartCollection();
091: resultSetWrapper = extract(transaction, resultSetWrapper,
092: statement, (Call) query);
093: if (resultSetWrapper.isEmpty()) {
094: return ArrayListCollectionFactory.NULL_ARRAY_LIST;
095: }
096:
097: int index = resultSetWrapper.getIndex();
098: currentResultSet = resultSetWrapper.getResultSet(index);
099: resultSetCtl.retrieve(transaction, query, currentResultSet,
100: index, results, controller, queryContext);
101: if (query.getRetrievedCount() == 0) {
102: if (statement.getMoreResults()
103: && statement.getUpdateCount() == -1) {
104: resultSetWrapper.close(index);
105: index++;
106: resultSetWrapper.setIndex(index);
107: query.setRetrievedCount(-1);
108: }
109: }
110: return results.getFirst();
111: }
112:
113: private MultiResultSetWrapper extract(
114: DatabaseTransactionImpl transaction,
115: MultiResultSetWrapper resultSetWrapper,
116: PreparedStatement statement, Call call) throws SQLException {
117: if (resultSetWrapper == null) {
118: ResultSet[] resultSets;
119: resultSets = extract(((CallableStatement) statement), call
120: .getParameters());
121: resultSetWrapper = new MultiResultSetWrapper(resultSets, 0);
122: transaction.addMultiPageResultSet(resultSetWrapper);
123: call.setResultSetWrapper(resultSetWrapper);
124: }
125: return resultSetWrapper;
126: }
127:
128: /**
129: *
130: * @param statement
131: * @param parameters
132: * @return ResultSet []
133: * @throws SQLException
134: */
135: protected static ResultSet[] extract(CallableStatement statement,
136: CallParameters parameters) throws SQLException {
137: int count = 0;
138: for (int i = 0; i < parameters.size(); i++) {
139: CallParameter parameter = (CallParameter) parameters.get(i);
140: if (parameter.isRefCursor()) {
141: count++;
142: }
143: }
144:
145: int index = 0;
146: ResultSet[] resultSets = new ResultSet[count];
147: for (int i = 0; i < parameters.size(); i++) {
148: CallParameter parameter = (CallParameter) parameters.get(i);
149: if (parameter.isRefCursor()) {
150: resultSets[index++] = (ResultSet) statement
151: .getObject(i + 1);
152: }
153: }
154:
155: return resultSets;
156: }
157:
158: public ResultSetIterator resultSetIterator(
159: PreparedStatement statement, AbstractParameters parameters)
160: throws SQLException {
161: return new ResultSetIteratorImpl(
162: ((CallableStatement) statement),
163: ((CallParameters) parameters));
164: }
165:
166: static class ResultSetIteratorImpl implements ResultSetIterator {
167:
168: private ResultSet[] resultSets;
169: private int resultSetIndex = -1;
170:
171: public ResultSetIteratorImpl(CallableStatement statement,
172: CallParameters parameters) throws SQLException {
173: statement.execute();
174: resultSets = extract(statement, parameters);
175: }
176:
177: public boolean next() {
178: resultSetIndex++;
179: return indexValid();
180: }
181:
182: public ResultSet getResultSet() {
183: ResultSet resultSet = null;
184: if (indexValid()) {
185: resultSet = resultSets[resultSetIndex];
186: }
187: return resultSet;
188: }
189:
190: private boolean indexValid() {
191: return resultSets != null
192: && resultSetIndex < resultSets.length;
193: }
194:
195: public boolean hasResultSet() {
196: return indexValid() && resultSetIndex >= 0;
197: }
198:
199: public boolean isAfterLast() {
200: return !indexValid();
201: }
202:
203: public int getResultSetIndex() {
204: return resultSetIndex;
205: }
206: }
207:
208: }
|