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