001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2004-2005 TONBELLER AG 008// Copyright (C) 2005-2013 Pentaho and others 009// All Rights Reserved. 010*/ 011package mondrian.rolap; 012 013import mondrian.calc.TupleList; 014import mondrian.calc.impl.DelegatingTupleList; 015import mondrian.calc.impl.UnaryTupleList; 016import mondrian.olap.*; 017import mondrian.olap.fun.FunUtil; 018import mondrian.rolap.sql.TupleConstraint; 019import mondrian.server.Locus; 020import mondrian.server.monitor.SqlStatementEvent; 021import mondrian.util.Pair; 022import mondrian.util.TraversalList; 023 024import java.sql.SQLException; 025import java.util.*; 026 027import javax.sql.DataSource; 028 029/** 030 * Reads the members of a single level (level.members) or of multiple levels 031 * (crossjoin). 032 * 033 * @deprecated Deprecated for Mondrian 4.0. 034 * @author luis f. canals 035 * @since Dec, 2007 036 */ 037@Deprecated 038public class HighCardSqlTupleReader extends SqlTupleReader { 039 private ResultLoader resultLoader; 040 private boolean moreRows; 041 042 int maxRows = 0; 043 044 public HighCardSqlTupleReader(final TupleConstraint constraint) { 045 super(constraint); 046 } 047 048 public void addLevelMembers( 049 final RolapLevel level, 050 final MemberBuilder memberBuilder, 051 final List<RolapMember> srcMembers) 052 { 053 targets.add(new Target( 054 level, memberBuilder, srcMembers, constraint, this)); 055 } 056 057 protected void prepareTuples( 058 final DataSource dataSource, 059 final TupleList partialResult, 060 final List<List<RolapMember>> newPartialResult) 061 { 062 String message = "Populating member cache with members for " + targets; 063 SqlStatement stmt = null; 064 boolean execQuery = (partialResult == null); 065 boolean success = false; 066 try { 067 if (execQuery) { 068 // we're only reading tuples from the targets that are 069 // non-enum targets 070 List<TargetBase> partialTargets = new ArrayList<TargetBase>(); 071 for (TargetBase target : targets) { 072 if (target.getSrcMembers() == null) { 073 partialTargets.add(target); 074 } 075 } 076 final Pair<String, List<SqlStatement.Type>> pair = 077 makeLevelMembersSql(dataSource); 078 String sql = pair.left; 079 List<SqlStatement.Type> types = pair.right; 080 stmt = RolapUtil.executeQuery( 081 dataSource, sql, types, maxRows, 0, 082 new SqlStatement.StatementLocus( 083 Locus.peek().execution, 084 "HighCardSqlTupleReader.readTuples " + partialTargets, 085 message, 086 SqlStatementEvent.Purpose.TUPLES, 0), 087 -1, -1, null); 088 } 089 090 for (TargetBase target : targets) { 091 target.open(); 092 } 093 094 // determine how many enum targets we have 095 int enumTargetCount = getEnumTargetCount(); 096 097 int currPartialResultIdx = 0; 098 if (execQuery) { 099 this.moreRows = stmt.getResultSet().next(); 100 if (this.moreRows) { 101 ++stmt.rowCount; 102 } 103 } else { 104 this.moreRows = currPartialResultIdx < partialResult.size(); 105 } 106 107 this.resultLoader = 108 new ResultLoader( 109 enumTargetCount, 110 targets, stmt, execQuery, partialResult, 111 newPartialResult); 112 113 // Read first and second elements if exists (or marks 114 // source as having "no more rows") 115 readNextTuple(); 116 readNextTuple(); 117 success = true; 118 } catch (SQLException sqle) { 119 if (stmt != null) { 120 throw stmt.handle(sqle); 121 } else { 122 throw Util.newError(sqle, message); 123 } 124 } finally { 125 if (!moreRows || !success) { 126 if (stmt != null) { 127 stmt.close(); 128 } 129 } 130 } 131 } 132 133 public TupleList readMembers( 134 final DataSource dataSource, 135 final TupleList partialResult, 136 final List<List<RolapMember>> newPartialResult) 137 { 138 prepareTuples(dataSource, partialResult, newPartialResult); 139 140 assert targets.size() == 1; 141 142 return new UnaryTupleList( 143 targets.get(0).close()); 144 } 145 146 public TupleList readTuples( 147 final DataSource jdbcConnection, 148 final TupleList partialResult, 149 final List<List<RolapMember>> newPartialResult) 150 { 151 prepareTuples(jdbcConnection, partialResult, newPartialResult); 152 153 // List of tuples 154 final int n = targets.size(); 155 @SuppressWarnings({"unchecked"}) 156 final List<Member>[] lists = new List[n]; 157 for (int i = 0; i < n; i++) { 158 lists[i] = targets.get(i).close(); 159 } 160 161 final List<List<Member>> list = 162 new TraversalList<Member>(lists, Member.class); 163 TupleList tupleList = new DelegatingTupleList(n, list); 164 165 // need to hierarchize the columns from the enumerated targets 166 // since we didn't necessarily add them in the order in which 167 // they originally appeared in the cross product 168 int enumTargetCount = getEnumTargetCount(); 169 if (enumTargetCount > 0) { 170 tupleList = FunUtil.hierarchizeTupleList(tupleList, false); 171 } 172 return tupleList; 173 } 174 175 /** 176 * Reads next tuple, notifying all internal targets. 177 * 178 * @return whether there are any more rows 179 */ 180 public boolean readNextTuple() { 181 if (!this.moreRows) { 182 return false; 183 } 184 try { 185 this.moreRows = this.resultLoader.loadResult(); 186 } catch (SQLException sqle) { 187 this.moreRows = false; 188 throw this.resultLoader.handle(sqle); 189 } 190 if (!this.moreRows) { 191 this.resultLoader.close(); 192 } 193 return this.moreRows; 194 } 195 196 public void setMaxRows(int maxRows) { 197 this.maxRows = maxRows; 198 } 199 200 public int getMaxRows() { 201 return maxRows; 202 } 203 204 Collection<RolapCube> getBaseCubeCollection(final Query query) { 205 return query.getBaseCubes(); 206 } 207} 208// End HighCardSqlTupleReader.java