001/* 002 * Copyright 2010 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.externaldata.data.sql; 017 018import java.sql.ResultSet; 019import java.sql.ResultSetMetaData; 020import java.sql.SQLException; 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.Iterator; 024import java.util.List; 025 026import org.ametys.core.datasource.ConnectionHelper; 027import org.ametys.plugins.externaldata.data.DataInclusionException; 028import org.ametys.plugins.externaldata.data.QueryResult; 029import org.ametys.plugins.externaldata.data.QueryResultRow; 030import org.ametys.plugins.externaldata.data.Query.ResultType; 031 032/** 033 * SQL query result. 034 */ 035public class LazySqlQueryResult implements QueryResult, Iterator<QueryResultRow> 036{ 037 038 /** The result type. */ 039 protected ResultType _resultType; 040 041 /** The wrapped ResultSet */ 042 protected ResultSet _resultSet; 043 044 /** The column names. */ 045 private Collection<String> _columnNames; 046 047 /** 048 * Constructs a query result around a {@link ResultSet}. 049 * @param resultSet the result set 050 */ 051 public LazySqlQueryResult(ResultSet resultSet) 052 { 053 _resultSet = resultSet; 054 try 055 { 056 _columnNames = _extractColumnNames(_resultSet); 057 } 058 catch (SQLException e) 059 { 060 throw new RuntimeException(e); 061 } 062 } 063 064 @Override 065 public ResultType getType() 066 { 067 return _resultType; 068 } 069 070 @Override 071 public int getSize() 072 { 073 try 074 { 075 return _resultSet.getFetchSize(); 076 } 077 catch (SQLException e) 078 { 079 return -1; 080 } 081 } 082 083 /** 084 * Set the result type. 085 * @param resultType the result type. 086 */ 087 public void setType(ResultType resultType) 088 { 089 this._resultType = resultType; 090 } 091 092 @Override 093 public Collection<String> getColumnNames() throws DataInclusionException 094 { 095 try 096 { 097 if (_columnNames == null) 098 { 099 _columnNames = _extractColumnNames(_resultSet); 100 } 101 return _columnNames; 102 } 103 catch (SQLException e) 104 { 105 throw new DataInclusionException("Unable to retrieve the column names.", e); 106 } 107 } 108 109 @Override 110 public Iterator<QueryResultRow> iterator() 111 { 112 return this; 113 } 114 115 @Override 116 public boolean hasNext() 117 { 118 try 119 { 120 return _resultSet.next(); 121 } 122 catch (SQLException e) 123 { 124 // TODO Throw a RuntimeException. 125 throw new RuntimeException(e); 126 } 127 } 128 129 @Override 130 public QueryResultRow next() 131 { 132 try 133 { 134 SqlQueryResultRow row = new SqlQueryResultRow(); 135 136 for (String colName : getColumnNames()) 137 { 138 String value = _resultSet.getString(colName); 139 row.put(colName, value); 140 } 141 142 return row; 143 } 144 catch (DataInclusionException e) 145 { 146 throw new RuntimeException(e); 147 } 148 catch (SQLException e) 149 { 150 throw new RuntimeException(e); 151 } 152 } 153 154 @Override 155 public void remove() 156 { 157 throw new UnsupportedOperationException("Remove operation not supported."); 158 } 159 160 @Override 161 public void close() 162 { 163 ConnectionHelper.cleanup(_resultSet); 164 } 165 166 /** 167 * Extract the column names of a JDBC result set. 168 * @param resultSet the JDBC result set. 169 * @return the column names as a Collection. 170 * @throws SQLException if an exception occurs when manipulating the result set 171 */ 172 protected Collection<String> _extractColumnNames(ResultSet resultSet) throws SQLException 173 { 174 ResultSetMetaData rsMeta = resultSet.getMetaData(); 175 int count = rsMeta.getColumnCount(); 176 177 List<String> columns = new ArrayList<>(count); 178 179 for (int i = 1; i <= count; i++) 180 { 181 columns.add(rsMeta.getColumnLabel(i)); 182 } 183 184 return columns; 185 } 186 187}