1 /* 2 * Copyright (c) 2011, 2021, Oracle and/or its affiliates. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License, version 2.0, 6 * as published by the Free Software Foundation. 7 * 8 * This program is also distributed with certain software (including 9 * but not limited to OpenSSL) that is licensed under separate terms, 10 * as designated in a particular file or component or in included license 11 * documentation. The authors of MySQL hereby grant you an additional 12 * permission to link the program and your derivative works with the 13 * separately licensed software that they have included with MySQL. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License, version 2.0, for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 */ 24 25 package com.mysql.clusterj.jdbc; 26 27 import java.math.BigDecimal; 28 import java.sql.Date; 29 import java.sql.SQLException; 30 import java.sql.Time; 31 import java.sql.Timestamp; 32 import java.util.Calendar; 33 import java.util.HashMap; 34 import java.util.Map; 35 36 import com.mysql.clusterj.core.spi.SessionSPI; 37 import com.mysql.clusterj.core.store.ResultData; 38 import com.mysql.clusterj.core.util.I18NHelper; 39 import com.mysql.clusterj.core.util.Logger; 40 import com.mysql.clusterj.core.util.LoggerFactoryService; 41 42 /** This class is part of the statement interceptor contract with the MySQL JDBC connection. 43 * When a statement is intercepted and executed, an instance of this class is returned if there 44 * is a real result to be iterated. A sibling class, ResultSetInternalMethodsUpdateCount, is 45 * returned if only an insert/delete/update count is returned. 46 * This class in turn delegates to the clusterj ResultData to retrieve data from the cluster. 47 */ 48 public class ResultSetInternalMethodsImpl extends AbstractResultSetInternalMethods { 49 50 /** My message translator */ 51 static final I18NHelper local = I18NHelper.getInstance(ResultSetInternalMethodsImpl.class); 52 53 /** My logger */ 54 static final Logger logger = LoggerFactoryService.getFactory().getInstance(ResultSetInternalMethodsImpl.class); 55 56 private ResultData resultData; 57 58 private SessionSPI session; 59 60 private int[] columnIndexToFieldNumberMap; 61 62 private Map<String, Integer> columnNameToFieldNumberMap = new HashMap<String, Integer>(); 63 64 private boolean autotransaction = true; 65 ResultSetInternalMethodsImpl(ResultData resultData, int[] columnIndexToFieldNumberMap, Map<String, Integer> columnNameToFieldNumberMap, SessionSPI session)66 public ResultSetInternalMethodsImpl(ResultData resultData, int[] columnIndexToFieldNumberMap, 67 Map<String, Integer> columnNameToFieldNumberMap, SessionSPI session) { 68 this.columnIndexToFieldNumberMap = columnIndexToFieldNumberMap; 69 this.columnNameToFieldNumberMap = columnNameToFieldNumberMap; 70 this.resultData = resultData; 71 this.session = session; 72 } 73 74 @Override reallyResult()75 public boolean reallyResult() { 76 return true; 77 } 78 79 @Override next()80 public boolean next() { 81 boolean hasNext = resultData.next(); 82 // startAutoTransaction was called in SQLExecutor.Select.execute and 83 // endAutoTransaction must be called exactly once after all results have been read 84 if (autotransaction & !hasNext) { 85 session.endAutoTransaction(); 86 autotransaction = false; 87 } 88 if (logger.isDetailEnabled()) logger.detail("ResultSetInternalMethods.next returned: " + hasNext); 89 return hasNext; 90 } 91 92 @Override getUpdateID()93 public long getUpdateID() { 94 return 0; 95 } 96 97 @Override getBoolean(int columnIndex)98 public boolean getBoolean(int columnIndex) throws SQLException { 99 boolean result = resultData.getBoolean(columnIndexToFieldNumberMap[columnIndex]); 100 return result; 101 } 102 103 @Override getBoolean(String columnName)104 public boolean getBoolean(String columnName) throws SQLException { 105 boolean result = resultData.getBoolean(getFieldNumberForColumnName(columnName)); 106 return result; 107 } 108 109 @Override getByte(int columnIndex)110 public byte getByte(int columnIndex) throws SQLException { 111 byte result = resultData.getByte(columnIndexToFieldNumberMap[columnIndex]); 112 return result; 113 } 114 115 @Override getByte(String columnName)116 public byte getByte(String columnName) throws SQLException { 117 byte result = resultData.getByte(getFieldNumberForColumnName(columnName)); 118 return result; 119 } 120 121 @Override getBytes(int columnIndex)122 public byte[] getBytes(int columnIndex) throws SQLException { 123 byte[] result = resultData.getBytes(columnIndexToFieldNumberMap[columnIndex]); 124 return result; 125 } 126 127 @Override getBytes(String columnName)128 public byte[] getBytes(String columnName) throws SQLException { 129 byte[] result = resultData.getBytes(getFieldNumberForColumnName(columnName)); 130 return result; 131 } 132 133 @Override getDate(int columnIndex)134 public Date getDate(int columnIndex) throws SQLException { 135 throw new SQLException(local.message("ERR_Should_Not_Occur")); 136 } 137 138 @Override getDate(String columnName)139 public Date getDate(String columnName) throws SQLException { 140 throw new SQLException(local.message("ERR_Should_Not_Occur")); 141 } 142 143 @Override getDate(int columnIndex, Calendar cal)144 public Date getDate(int columnIndex, Calendar cal) throws SQLException { 145 throw new SQLException(local.message("ERR_Should_Not_Occur")); 146 } 147 148 @Override getDate(String columnName, Calendar cal)149 public Date getDate(String columnName, Calendar cal) throws SQLException { 150 throw new SQLException(local.message("ERR_Should_Not_Occur")); 151 } 152 153 @Override getDouble(int columnIndex)154 public double getDouble(int columnIndex) throws SQLException { 155 double result = resultData.getDouble(columnIndexToFieldNumberMap[columnIndex]); 156 return result; 157 } 158 159 @Override getDouble(String columnName)160 public double getDouble(String columnName) throws SQLException { 161 double result = resultData.getDouble(getFieldNumberForColumnName(columnName)); 162 return result; 163 } 164 165 @Override getFloat(int columnIndex)166 public float getFloat(int columnIndex) throws SQLException { 167 float result = resultData.getFloat(columnIndexToFieldNumberMap[columnIndex]); 168 return result; 169 } 170 171 @Override getFloat(String columnName)172 public float getFloat(String columnName) throws SQLException { 173 float result = resultData.getFloat(getFieldNumberForColumnName(columnName)); 174 return result; 175 } 176 177 @Override getLong(int columnIndex)178 public long getLong(int columnIndex) throws SQLException { 179 long result = resultData.getLong(columnIndexToFieldNumberMap[columnIndex]); 180 return result; 181 } 182 183 @Override getLong(String columnName)184 public long getLong(String columnName) throws SQLException { 185 long result = resultData.getLong(getFieldNumberForColumnName(columnName)); 186 return result; 187 } 188 189 @Override getInt(int columnIndex)190 public int getInt(int columnIndex) throws SQLException { 191 int result = resultData.getInt(columnIndexToFieldNumberMap[columnIndex]); 192 return result; 193 } 194 195 @Override getInt(String columnName)196 public int getInt(String columnName) throws SQLException { 197 int result = resultData.getInt(getFieldNumberForColumnName(columnName)); 198 return result; 199 } 200 201 @Override getShort(int columnIndex)202 public short getShort(int columnIndex) throws SQLException { 203 short result = resultData.getShort(columnIndexToFieldNumberMap[columnIndex]); 204 return result; 205 } 206 207 @Override getShort(String columnName)208 public short getShort(String columnName) throws SQLException { 209 short result = resultData.getShort(getFieldNumberForColumnName(columnName)); 210 return result; 211 } 212 213 @Override getString(int columnIndex)214 public String getString(int columnIndex) throws SQLException { 215 String result = resultData.getString(columnIndexToFieldNumberMap[columnIndex]); 216 return result; 217 } 218 219 @Override getString(String columnName)220 public String getString(String columnName) throws SQLException { 221 String result = resultData.getString(getFieldNumberForColumnName(columnName)); 222 return result; 223 } 224 225 @Override getTime(int columnIndex)226 public Time getTime(int columnIndex) throws SQLException { 227 throw new SQLException(local.message("ERR_Should_Not_Occur")); 228 } 229 230 @Override getTime(String columnName)231 public Time getTime(String columnName) throws SQLException { 232 throw new SQLException(local.message("ERR_Should_Not_Occur")); 233 } 234 235 @Override getTime(int columnIndex, Calendar cal)236 public Time getTime(int columnIndex, Calendar cal) throws SQLException { 237 throw new SQLException(local.message("ERR_Should_Not_Occur")); 238 } 239 240 @Override getTime(String columnName, Calendar cal)241 public Time getTime(String columnName, Calendar cal) throws SQLException { 242 throw new SQLException(local.message("ERR_Should_Not_Occur")); 243 } 244 245 @Override getTimestamp(int columnIndex)246 public Timestamp getTimestamp(int columnIndex) throws SQLException { 247 throw new SQLException(local.message("ERR_Should_Not_Occur")); 248 } 249 250 @Override getTimestamp(String columnName)251 public Timestamp getTimestamp(String columnName) throws SQLException { 252 throw new SQLException(local.message("ERR_Should_Not_Occur")); 253 } 254 255 @Override getTimestamp(int columnIndex, Calendar cal)256 public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { 257 throw new SQLException(local.message("ERR_Should_Not_Occur")); 258 } 259 260 @Override getTimestamp(String columnName, Calendar cal)261 public Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException { 262 throw new SQLException(local.message("ERR_Should_Not_Occur")); 263 } 264 265 @Override getBigDecimal(int columnIndex)266 public BigDecimal getBigDecimal(int columnIndex) throws SQLException { 267 BigDecimal result = resultData.getDecimal(columnIndexToFieldNumberMap[columnIndex]); 268 return result; 269 } 270 271 @Override getBigDecimal(String columnName)272 public BigDecimal getBigDecimal(String columnName) throws SQLException { 273 BigDecimal result = resultData.getDecimal(getFieldNumberForColumnName(columnName)); 274 return result; 275 } 276 277 @Override realClose(boolean arg0)278 public void realClose(boolean arg0) throws SQLException { 279 // if next() was never called to end the autotransaction, do so now 280 if (autotransaction) { 281 session.endAutoTransaction(); 282 autotransaction = false; 283 } 284 } 285 getFieldNumberForColumnName(String columnName)286 private int getFieldNumberForColumnName(String columnName) throws SQLException { 287 Integer fieldNumber = columnNameToFieldNumberMap.get(columnName); 288 if (fieldNumber != null) { 289 return fieldNumber.intValue(); 290 } 291 throw new SQLException(local.message("ERR_Column_Name_Not_In_Result", columnName)); 292 } 293 294 } 295