/* * Copyright (c) 2011, 2021, Oracle and/or its affiliates. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2.0, * as published by the Free Software Foundation. * * This program is also distributed with certain software (including * but not limited to OpenSSL) that is licensed under separate terms, * as designated in a particular file or component or in included license * documentation. The authors of MySQL hereby grant you an additional * permission to link the program and your derivative works with the * separately licensed software that they have included with MySQL. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License, version 2.0, for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package com.mysql.clusterj.jdbc; import java.math.BigDecimal; import java.sql.Date; import java.sql.SQLException; import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; import java.util.HashMap; import java.util.Map; import com.mysql.clusterj.core.spi.SessionSPI; import com.mysql.clusterj.core.store.ResultData; import com.mysql.clusterj.core.util.I18NHelper; import com.mysql.clusterj.core.util.Logger; import com.mysql.clusterj.core.util.LoggerFactoryService; /** This class is part of the statement interceptor contract with the MySQL JDBC connection. * When a statement is intercepted and executed, an instance of this class is returned if there * is a real result to be iterated. A sibling class, ResultSetInternalMethodsUpdateCount, is * returned if only an insert/delete/update count is returned. * This class in turn delegates to the clusterj ResultData to retrieve data from the cluster. */ public class ResultSetInternalMethodsImpl extends AbstractResultSetInternalMethods { /** My message translator */ static final I18NHelper local = I18NHelper.getInstance(ResultSetInternalMethodsImpl.class); /** My logger */ static final Logger logger = LoggerFactoryService.getFactory().getInstance(ResultSetInternalMethodsImpl.class); private ResultData resultData; private SessionSPI session; private int[] columnIndexToFieldNumberMap; private Map columnNameToFieldNumberMap = new HashMap(); private boolean autotransaction = true; public ResultSetInternalMethodsImpl(ResultData resultData, int[] columnIndexToFieldNumberMap, Map columnNameToFieldNumberMap, SessionSPI session) { this.columnIndexToFieldNumberMap = columnIndexToFieldNumberMap; this.columnNameToFieldNumberMap = columnNameToFieldNumberMap; this.resultData = resultData; this.session = session; } @Override public boolean reallyResult() { return true; } @Override public boolean next() { boolean hasNext = resultData.next(); // startAutoTransaction was called in SQLExecutor.Select.execute and // endAutoTransaction must be called exactly once after all results have been read if (autotransaction & !hasNext) { session.endAutoTransaction(); autotransaction = false; } if (logger.isDetailEnabled()) logger.detail("ResultSetInternalMethods.next returned: " + hasNext); return hasNext; } @Override public long getUpdateID() { return 0; } @Override public boolean getBoolean(int columnIndex) throws SQLException { boolean result = resultData.getBoolean(columnIndexToFieldNumberMap[columnIndex]); return result; } @Override public boolean getBoolean(String columnName) throws SQLException { boolean result = resultData.getBoolean(getFieldNumberForColumnName(columnName)); return result; } @Override public byte getByte(int columnIndex) throws SQLException { byte result = resultData.getByte(columnIndexToFieldNumberMap[columnIndex]); return result; } @Override public byte getByte(String columnName) throws SQLException { byte result = resultData.getByte(getFieldNumberForColumnName(columnName)); return result; } @Override public byte[] getBytes(int columnIndex) throws SQLException { byte[] result = resultData.getBytes(columnIndexToFieldNumberMap[columnIndex]); return result; } @Override public byte[] getBytes(String columnName) throws SQLException { byte[] result = resultData.getBytes(getFieldNumberForColumnName(columnName)); return result; } @Override public Date getDate(int columnIndex) throws SQLException { throw new SQLException(local.message("ERR_Should_Not_Occur")); } @Override public Date getDate(String columnName) throws SQLException { throw new SQLException(local.message("ERR_Should_Not_Occur")); } @Override public Date getDate(int columnIndex, Calendar cal) throws SQLException { throw new SQLException(local.message("ERR_Should_Not_Occur")); } @Override public Date getDate(String columnName, Calendar cal) throws SQLException { throw new SQLException(local.message("ERR_Should_Not_Occur")); } @Override public double getDouble(int columnIndex) throws SQLException { double result = resultData.getDouble(columnIndexToFieldNumberMap[columnIndex]); return result; } @Override public double getDouble(String columnName) throws SQLException { double result = resultData.getDouble(getFieldNumberForColumnName(columnName)); return result; } @Override public float getFloat(int columnIndex) throws SQLException { float result = resultData.getFloat(columnIndexToFieldNumberMap[columnIndex]); return result; } @Override public float getFloat(String columnName) throws SQLException { float result = resultData.getFloat(getFieldNumberForColumnName(columnName)); return result; } @Override public long getLong(int columnIndex) throws SQLException { long result = resultData.getLong(columnIndexToFieldNumberMap[columnIndex]); return result; } @Override public long getLong(String columnName) throws SQLException { long result = resultData.getLong(getFieldNumberForColumnName(columnName)); return result; } @Override public int getInt(int columnIndex) throws SQLException { int result = resultData.getInt(columnIndexToFieldNumberMap[columnIndex]); return result; } @Override public int getInt(String columnName) throws SQLException { int result = resultData.getInt(getFieldNumberForColumnName(columnName)); return result; } @Override public short getShort(int columnIndex) throws SQLException { short result = resultData.getShort(columnIndexToFieldNumberMap[columnIndex]); return result; } @Override public short getShort(String columnName) throws SQLException { short result = resultData.getShort(getFieldNumberForColumnName(columnName)); return result; } @Override public String getString(int columnIndex) throws SQLException { String result = resultData.getString(columnIndexToFieldNumberMap[columnIndex]); return result; } @Override public String getString(String columnName) throws SQLException { String result = resultData.getString(getFieldNumberForColumnName(columnName)); return result; } @Override public Time getTime(int columnIndex) throws SQLException { throw new SQLException(local.message("ERR_Should_Not_Occur")); } @Override public Time getTime(String columnName) throws SQLException { throw new SQLException(local.message("ERR_Should_Not_Occur")); } @Override public Time getTime(int columnIndex, Calendar cal) throws SQLException { throw new SQLException(local.message("ERR_Should_Not_Occur")); } @Override public Time getTime(String columnName, Calendar cal) throws SQLException { throw new SQLException(local.message("ERR_Should_Not_Occur")); } @Override public Timestamp getTimestamp(int columnIndex) throws SQLException { throw new SQLException(local.message("ERR_Should_Not_Occur")); } @Override public Timestamp getTimestamp(String columnName) throws SQLException { throw new SQLException(local.message("ERR_Should_Not_Occur")); } @Override public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { throw new SQLException(local.message("ERR_Should_Not_Occur")); } @Override public Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException { throw new SQLException(local.message("ERR_Should_Not_Occur")); } @Override public BigDecimal getBigDecimal(int columnIndex) throws SQLException { BigDecimal result = resultData.getDecimal(columnIndexToFieldNumberMap[columnIndex]); return result; } @Override public BigDecimal getBigDecimal(String columnName) throws SQLException { BigDecimal result = resultData.getDecimal(getFieldNumberForColumnName(columnName)); return result; } @Override public void realClose(boolean arg0) throws SQLException { // if next() was never called to end the autotransaction, do so now if (autotransaction) { session.endAutoTransaction(); autotransaction = false; } } private int getFieldNumberForColumnName(String columnName) throws SQLException { Integer fieldNumber = columnNameToFieldNumberMap.get(columnName); if (fieldNumber != null) { return fieldNumber.intValue(); } throw new SQLException(local.message("ERR_Column_Name_Not_In_Result", columnName)); } }