2 Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 package com.mysql.clusterj.tie;
20 import java.math.BigDecimal;
21 import java.math.BigInteger;
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
26 import java.util.List;
28 import com.mysql.clusterj.ClusterJFatalInternalException;
30 import com.mysql.clusterj.core.store.Blob;
31 import com.mysql.clusterj.core.store.Column;
32 import com.mysql.clusterj.core.store.ResultData;
34 import com.mysql.clusterj.core.util.I18NHelper;
35 import com.mysql.clusterj.core.util.Logger;
36 import com.mysql.clusterj.core.util.LoggerFactoryService;
37 import com.mysql.clusterj.tie.DbImpl.BufferManager;
39 import com.mysql.ndbjtie.ndbapi.NdbBlob;
40 import com.mysql.ndbjtie.ndbapi.NdbErrorConst;
41 import com.mysql.ndbjtie.ndbapi.NdbOperation;
42 import com.mysql.ndbjtie.ndbapi.NdbRecAttr;
47 class ResultDataImpl implements ResultData {
49 /** My message translator */
50 static final I18NHelper local = I18NHelper
51 .getInstance(ResultDataImpl.class);
54 static final Logger logger = LoggerFactoryService.getFactory()
55 .getInstance(ResultDataImpl.class);
57 /** Flags for iterating a scan */
58 protected final int RESULT_READY = 0;
59 protected final int SCAN_FINISHED = 1;
60 protected final int CACHE_EMPTY = 2;
62 /** The NdbOperation that defines the result */
63 private NdbOperation ndbOperation = null;
65 /** The NdbRecAttrs that specify the columns to retrieve */
66 private NdbRecAttr[] ndbRecAttrs = null;
68 /** The flag indicating that there are no more results */
69 private boolean nextDone;
71 /** The ByteBuffer containing the results, possibly obtained from buffer manager */
72 private ByteBuffer byteBuffer = null;
74 /** Offsets into the ByteBuffer containing the results */
75 private int[] offsets = null;
77 /** Lengths of the fields in the ByteBuffer containing the results */
78 private int[] lengths = null;
80 /** The Columns in this result */
81 private final Column[] storeColumns;
83 /** The buffer manager */
84 private BufferManager bufferManager;
86 /** Construct the ResultDataImpl based on an NdbOperation, a list of columns
87 * to include in the result, and the pre-computed buffer layout for the result.
88 * @param ndbOperation the NdbOperation
89 * @param storeColumns the columns in the result
90 * @param maximumColumnId the largest column id
91 * @param bufferSize the size of the buffer needed
92 * @param offsets the array of offsets indexed by column id
93 * @param lengths the array of lengths indexed by column id
94 * @param bufferManager the buffer manager
95 * @param allocateNew true to allocate a new (unshared) result buffer
97 public ResultDataImpl(NdbOperation ndbOperation, List<Column> storeColumns,
98 int maximumColumnId, int bufferSize, int[] offsets, int[] lengths,
99 BufferManager bufferManager, boolean allocateNew) {
100 this.ndbOperation = ndbOperation;
101 this.bufferManager = bufferManager;
102 // save the column list
103 this.storeColumns = storeColumns.toArray(new Column[storeColumns.size()]);
104 this.offsets = offsets;
105 this.lengths = lengths;
107 byteBuffer = ByteBuffer.allocateDirect(bufferSize);
109 byteBuffer = bufferManager.getResultDataBuffer(bufferSize);
111 byteBuffer.order(ByteOrder.nativeOrder());
112 // iterate the list of store columns and allocate an NdbRecAttr (via getValue) for each
113 ndbRecAttrs = new NdbRecAttr[maximumColumnId + 1];
114 for (Column storeColumn: storeColumns) {
115 NdbRecAttr ndbRecAttr = null;
116 int columnId = storeColumn.getColumnId();
117 byteBuffer.position(offsets[columnId]);
118 if (lengths[columnId] == 0) {
119 // TODO: to help profiling
120 ndbRecAttr = ndbOperation.getValue(columnId, null);
121 // ndbRecAttr = getValue(ndbOperation, columnId, null);
123 ndbRecAttr = ndbOperation.getValue(columnId, byteBuffer);
124 // ndbRecAttr = getValue(ndbOperation, columnId, byteBuffer);
126 handleError(ndbRecAttr, ndbOperation);
127 ndbRecAttrs[columnId] = ndbRecAttr;
131 private NdbRecAttr getValue(NdbOperation ndbOperation2, int columnId,
132 ByteBuffer byteBuffer2) {
133 // TODO: to help profiling
134 return ndbOperation2.getValue(columnId, byteBuffer2);
137 public boolean next() {
138 // NdbOperation has exactly zero or one result. ScanResultDataImpl handles scans...
139 NdbErrorConst error = ndbOperation.getNdbError();
140 // if the ndbOperation reports an error there is no result
141 int errorCode = error.code();
142 if (errorCode != 0) {
153 public Blob getBlob(int column) {
154 return getBlob(storeColumns[column]);
157 public Blob getBlob(Column storeColumn) {
158 NdbBlob ndbBlob = ndbOperation.getBlobHandle(storeColumn.getColumnId());
159 handleError(ndbBlob, ndbOperation);
160 return new BlobImpl(ndbBlob);
163 public boolean getBoolean(int column) {
164 return getBoolean(storeColumns[column]);
167 public boolean getBoolean(Column storeColumn) {
168 int index = storeColumn.getColumnId();
169 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
170 return Utility.getBoolean(storeColumn, ndbRecAttr);
173 public boolean[] getBooleans(int column) {
174 return getBooleans(storeColumns[column]);
177 public boolean[] getBooleans(Column storeColumn) {
178 throw new ClusterJFatalInternalException(local.message("ERR_Not_Implemented"));
181 public byte getByte(int column) {
182 return getByte(storeColumns[column]);
185 public byte getByte(Column storeColumn) {
186 int index = storeColumn.getColumnId();
187 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
188 return Utility.getByte(storeColumn, ndbRecAttr);
191 public short getShort(int column) {
192 return getShort(storeColumns[column]);
195 public short getShort(Column storeColumn) {
196 int index = storeColumn.getColumnId();
197 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
198 return Utility.getShort(storeColumn, ndbRecAttr);
201 public int getInt(int column) {
202 return getInt(storeColumns[column]);
205 public int getInt(Column storeColumn) {
206 int index = storeColumn.getColumnId();
207 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
208 return Utility.getInt(storeColumn, ndbRecAttr);
211 public long getLong(int column) {
212 return getLong(storeColumns[column]);
215 public long getLong(Column storeColumn) {
216 int index = storeColumn.getColumnId();
217 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
218 return Utility.getLong(storeColumn, ndbRecAttr);
221 public float getFloat(int column) {
222 return getFloat(storeColumns[column]);
225 public float getFloat(Column storeColumn) {
226 int index = storeColumn.getColumnId();
227 float result = ndbRecAttrs[index].float_value();
231 public double getDouble(int column) {
232 return getDouble(storeColumns[column]);
235 public double getDouble(Column storeColumn) {
236 int index = storeColumn.getColumnId();
237 double result = ndbRecAttrs[index].double_value();
241 public String getString(int column) {
242 return getString(storeColumns[column]);
245 public String getString(Column storeColumn) {
246 int index = storeColumn.getColumnId();
247 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
248 if (ndbRecAttr.isNULL() == 1) return null;
249 int prefixLength = storeColumn.getPrefixLength();
251 int offset = offsets[index];
252 byteBuffer.limit(byteBuffer.capacity());
253 switch (prefixLength) {
255 actualLength = lengths[index];
258 actualLength = (byteBuffer.get(offset) + 256) % 256;
262 actualLength = (byteBuffer.get(offset) + 256) % 256;
263 int length2 = (byteBuffer.get(offset + 1) + 256) % 256;
264 actualLength += 256 * length2;
268 throw new ClusterJFatalInternalException(
269 local.message("ERR_Invalid_Prefix_Length", prefixLength));
272 byteBuffer.position(offset);
273 byteBuffer.limit(offset + actualLength);
275 String result = Utility.decode(byteBuffer, storeColumn.getCharsetNumber(), bufferManager);
280 public byte[] getBytes(int column) {
281 return getBytes(storeColumns[column]);
284 public byte[] getBytes(Column storeColumn) {
285 int index = storeColumn.getColumnId();
286 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
287 if (ndbRecAttr.isNULL() == 1) return null;
288 int prefixLength = storeColumn.getPrefixLength();
289 int actualLength = lengths[index];
290 int offset = offsets[index];
291 switch (prefixLength) {
295 actualLength = (byteBuffer.get(offset) + 256) % 256;
299 actualLength = (byteBuffer.get(offset) + 256) % 256;
300 int length2 = (byteBuffer.get(offset + 1) + 256) % 256;
301 actualLength += 256 * length2;
305 throw new ClusterJFatalInternalException(
306 local.message("ERR_Invalid_Prefix_Length", prefixLength));
308 byteBuffer.position(offset);
309 byte[] result = new byte[actualLength];
310 byteBuffer.get(result);
315 public Object getObject(int column) {
316 return getObject(storeColumns[column]);
319 public Object getObject(Column storeColumn) {
320 throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
323 public boolean wasNull(Column storeColumn) {
324 throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
327 public Boolean getObjectBoolean(int column) {
328 return getObjectBoolean(storeColumns[column]);
331 public Boolean getObjectBoolean(Column storeColumn) {
332 int index = storeColumn.getColumnId();
333 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
334 if (ndbRecAttr.isNULL() == 1) {
337 byte value = ndbRecAttr.int8_value();
338 Boolean result = (Boolean.valueOf((value & 0x01) == 0x01));
343 public Byte getObjectByte(int column) {
344 return getObjectByte(storeColumns[column]);
347 public Byte getObjectByte(Column storeColumn) {
348 int index = storeColumn.getColumnId();
349 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
350 return (ndbRecAttr.isNULL() == 1)?null:Utility.getByte(storeColumn, ndbRecAttr);
353 public Short getObjectShort(int column) {
354 return getObjectShort(storeColumns[column]);
357 public Short getObjectShort(Column storeColumn) {
358 int index = storeColumn.getColumnId();
359 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
360 return (ndbRecAttr.isNULL() == 1)?null:Utility.getShort(storeColumn, ndbRecAttr);
363 public Integer getObjectInteger(int column) {
364 return getObjectInteger(storeColumns[column]);
367 public Integer getObjectInteger(Column storeColumn) {
368 int index = storeColumn.getColumnId();
369 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
370 return (ndbRecAttr.isNULL() == 1)?null:Utility.getInt(storeColumn, ndbRecAttr);
373 public Long getObjectLong(int column) {
374 return getObjectLong(storeColumns[column]);
377 public Long getObjectLong(Column storeColumn) {
378 int index = storeColumn.getColumnId();
379 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
380 return (ndbRecAttr.isNULL() == 1)?null:Utility.getLong(storeColumn, ndbRecAttr);
383 public Float getObjectFloat(int column) {
384 return getObjectFloat(storeColumns[column]);
387 public Float getObjectFloat(Column storeColumn) {
388 int index = storeColumn.getColumnId();
389 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
390 return (ndbRecAttr.isNULL() == 1)?null:getFloat(storeColumn);
393 public Double getObjectDouble(int column) {
394 return getObjectDouble(storeColumns[column]);
397 public Double getObjectDouble(Column storeColumn) {
398 int index = storeColumn.getColumnId();
399 NdbRecAttr ndbRecAttr = ndbRecAttrs[index];
400 return (ndbRecAttr.isNULL() == 1)?null:getDouble(storeColumn);
403 public BigInteger getBigInteger(int column) {
404 return getBigInteger(storeColumns[column]);
407 public BigInteger getBigInteger(Column storeColumn) {
408 int index = storeColumn.getColumnId();
409 int offset = offsets[index];
410 int precision = storeColumn.getPrecision();
411 int scale = storeColumn.getScale();
412 int length = Utility.getDecimalColumnSpace(precision, scale);
413 byteBuffer.position(offset);
414 return Utility.getBigInteger(byteBuffer, length, precision, scale);
417 public BigDecimal getDecimal(int column) {
418 return getDecimal(storeColumns[column]);
421 public BigDecimal getDecimal(Column storeColumn) {
422 int index = storeColumn.getColumnId();
423 int offset = offsets[index];
424 int precision = storeColumn.getPrecision();
425 int scale = storeColumn.getScale();
426 int length = Utility.getDecimalColumnSpace(precision, scale);
427 byteBuffer.position(offset);
428 return Utility.getDecimal(byteBuffer, length, precision, scale);
431 private void handleError(Object object, NdbOperation ndbOperation) {
432 if (object == null) {
433 Utility.throwError(object, ndbOperation.getNdbError());
437 public void setNoResult() {
441 public Column[] getColumns() {