1 /* 2 Copyright (c) 2012, 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.tie; 26 27 import java.math.BigDecimal; 28 import java.math.BigInteger; 29 30 import java.nio.ByteBuffer; 31 import java.util.ArrayList; 32 import java.util.List; 33 34 import com.mysql.clusterj.ClusterJFatalInternalException; 35 36 import com.mysql.clusterj.core.store.Blob; 37 import com.mysql.clusterj.core.store.Column; 38 import com.mysql.clusterj.core.store.Db; 39 import com.mysql.clusterj.core.store.Operation; 40 import com.mysql.clusterj.core.store.ResultData; 41 import com.mysql.clusterj.core.store.Table; 42 43 import com.mysql.clusterj.core.util.I18NHelper; 44 import com.mysql.clusterj.core.util.Logger; 45 import com.mysql.clusterj.core.util.LoggerFactoryService; 46 47 import com.mysql.clusterj.tie.DbImpl.BufferManager; 48 49 import com.mysql.ndbjtie.ndbapi.NdbBlob; 50 import com.mysql.ndbjtie.ndbapi.NdbOperationConst; 51 import com.mysql.ndbjtie.ndbapi.NdbDictionary.Dictionary; 52 53 /** 54 * Implementation of store operation that uses NdbRecord. 55 * Operations of the "equal" variety delegate to the key NdbRecordImpl. 56 * Operations of the "set" and "get" varieties delegate to the value NdbRecordImpl. 57 */ 58 public class NdbRecordOperationImpl implements Operation { 59 60 /** My message translator */ 61 static final I18NHelper local = I18NHelper 62 .getInstance(NdbRecordOperationImpl.class); 63 64 /** My logger */ 65 static final Logger logger = LoggerFactoryService.getFactory() 66 .getInstance(NdbRecordOperationImpl.class); 67 68 /** The ClusterTransaction that this operation belongs to */ 69 protected ClusterTransactionImpl clusterTransaction = null; 70 71 /** The NdbOperation wrapped by this object */ 72 protected NdbOperationConst ndbOperation = null; 73 74 /** The NdbRecord for keys */ 75 protected NdbRecordImpl ndbRecordKeys = null; 76 77 /** The NdbRecord for values */ 78 protected NdbRecordImpl ndbRecordValues = null; 79 80 /** The ByteBuffer pool for handling blob operations */ 81 protected VariableByteBufferPoolImpl byteBufferPool; 82 83 /** The mask for this operation, which contains a bit set for each column referenced. 84 * For insert, this contains a bit for each column to be inserted. 85 * For update, this contains a bit for each column to be updated. 86 * For read/scan operations, this contains a bit for each column to be read. 87 */ 88 byte[] mask; 89 90 /** The ByteBuffer containing keys */ 91 ByteBuffer keyBuffer = null; 92 93 /** The ByteBuffer containing values */ 94 ByteBuffer valueBuffer = null; 95 96 /** Blobs for this NdbRecord */ 97 protected NdbRecordBlobImpl[] blobs = null; 98 99 /** Blobs that have been accessed for this operation */ 100 protected List<NdbRecordBlobImpl> activeBlobs = new ArrayList<NdbRecordBlobImpl>(); 101 102 /** The size of the key buffer for this operation */ 103 protected int keyBufferSize; 104 105 /** The size of the value buffer for this operation */ 106 protected int valueBufferSize; 107 108 /** The buffer manager for string encode and decode */ 109 protected BufferManager bufferManager; 110 111 /** The table name */ 112 protected String tableName; 113 114 /** The store table */ 115 protected Table storeTable; 116 117 /** The store columns. */ 118 protected Column[] storeColumns; 119 120 /** The number of columns */ 121 int numberOfColumns; 122 123 /** The db for this operation */ 124 protected DbImpl db; 125 126 /** If autoincrement is defined for any column */ 127 protected boolean autoIncrement = false; 128 129 /** The autoincrement column id or zero if none */ 130 protected int autoIncrementColumnId = 0; 131 132 /** Constructor used for smart value handler for new instances, 133 * and the cluster transaction is not yet known. There is only one 134 * NdbRecord and one buffer, so all operations result in using 135 * the same buffer. 136 * 137 * @param clusterConnection the cluster connection 138 * @param db the Db 139 * @param storeTable the store table 140 */ NdbRecordOperationImpl(ClusterConnectionImpl clusterConnection, Db db, Table storeTable)141 public NdbRecordOperationImpl(ClusterConnectionImpl clusterConnection, Db db, Table storeTable) { 142 byteBufferPool = clusterConnection.getByteBufferPool(); 143 this.db = (DbImpl)db; 144 this.storeTable = storeTable; 145 Column autoIncrementColumn = storeTable.getAutoIncrementColumn(); 146 if (autoIncrementColumn != null) { 147 this.autoIncrement = true; 148 this.autoIncrementColumnId = autoIncrementColumn.getColumnId(); 149 } 150 logger.detail("autoIncrement for " + storeTable.getName() + " is: " + autoIncrement); 151 this.tableName = storeTable.getName(); 152 this.ndbRecordValues = clusterConnection.getCachedNdbRecordImpl(storeTable); 153 this.ndbRecordKeys = ndbRecordValues; 154 this.valueBufferSize = ndbRecordValues.getBufferSize(); 155 this.keyBufferSize = ndbRecordKeys.getBufferSize(); 156 this.valueBuffer = ndbRecordValues.newBuffer(); 157 this.keyBuffer = valueBuffer; 158 this.storeColumns = ndbRecordValues.storeColumns; 159 this.numberOfColumns = storeColumns.length; 160 this.blobs = new NdbRecordBlobImpl[this.numberOfColumns]; 161 this.bufferManager = ((DbImpl)db).getBufferManager(); 162 resetMask(); 163 } 164 165 /** Constructor used when the transaction is known. 166 * 167 * @param clusterTransaction the cluster transaction 168 */ NdbRecordOperationImpl(ClusterTransactionImpl clusterTransaction, Table storeTable)169 public NdbRecordOperationImpl(ClusterTransactionImpl clusterTransaction, Table storeTable) { 170 this.byteBufferPool = clusterTransaction.getClusterConnection().getByteBufferPool(); 171 this.clusterTransaction = clusterTransaction; 172 this.db = clusterTransaction.db; 173 this.bufferManager = clusterTransaction.getBufferManager(); 174 this.storeTable = storeTable; 175 Column autoIncrementColumn = storeTable.getAutoIncrementColumn(); 176 if (autoIncrementColumn != null) { 177 this.autoIncrement = true; 178 this.autoIncrementColumnId = autoIncrementColumn.getColumnId(); 179 } 180 logger.detail("autoIncrement for " + storeTable.getName() + " is: " + autoIncrement); 181 this.tableName = storeTable.getName(); 182 this.ndbRecordValues = clusterTransaction.getCachedNdbRecordImpl(storeTable); 183 this.valueBufferSize = ndbRecordValues.getBufferSize(); 184 this.valueBuffer = ndbRecordValues.newBuffer(); 185 this.storeColumns = ndbRecordValues.storeColumns; 186 this.numberOfColumns = ndbRecordValues.getNumberOfColumns(); 187 this.blobs = new NdbRecordBlobImpl[this.numberOfColumns]; 188 resetMask(); 189 } 190 191 /** Constructor used to copy an existing NdbRecordOperationImpl for use with a SmartValueHandler. 192 * The value buffer is copied and cannot be used by the existing NdbRecordOperationImpl. 193 * 194 * @param ndbRecordOperationImpl2 the existing NdbRecordOperationImpl with value buffer 195 */ NdbRecordOperationImpl(NdbRecordOperationImpl ndbRecordOperationImpl2)196 public NdbRecordOperationImpl(NdbRecordOperationImpl ndbRecordOperationImpl2) { 197 this.byteBufferPool = ndbRecordOperationImpl2.byteBufferPool; 198 this.ndbRecordValues = ndbRecordOperationImpl2.ndbRecordValues; 199 this.valueBufferSize = ndbRecordOperationImpl2.valueBufferSize; 200 this.ndbRecordKeys = ndbRecordValues; 201 this.keyBufferSize = ndbRecordKeys.bufferSize; 202 this.valueBuffer = ndbRecordOperationImpl2.valueBuffer; 203 this.keyBuffer = this.valueBuffer; 204 this.bufferManager = ndbRecordOperationImpl2.bufferManager; 205 this.tableName = ndbRecordOperationImpl2.tableName; 206 this.storeColumns = ndbRecordOperationImpl2.ndbRecordValues.storeColumns; 207 this.numberOfColumns = this.storeColumns.length; 208 this.blobs = new NdbRecordBlobImpl[this.numberOfColumns]; 209 // copy the blob data from the original but leave out the NdbBlob part 210 // which is bound to the NdbOperation and is not suitable 211 for (int i = 0; i < ndbRecordOperationImpl2.blobs.length; ++i) { 212 if (ndbRecordOperationImpl2.blobs[i] != null) { 213 this.blobs[i] = new NdbRecordBlobImpl(this, ndbRecordOperationImpl2.blobs[i]); 214 } 215 } 216 resetMask(); 217 } 218 219 /** Release any resources associated with this object. 220 * This method is called by the owner of this object. 221 */ release()222 public void release() { 223 if (logger.isDetailEnabled()) logger.detail("NdbRecordOperationImpl.release"); 224 if (keyBuffer != null && keyBuffer != valueBuffer) { 225 ndbRecordKeys.returnBuffer(keyBuffer); 226 this.keyBuffer = null; 227 } 228 if (valueBuffer != null) { 229 ndbRecordValues.returnBuffer(valueBuffer); 230 this.valueBuffer = null; 231 } 232 this.ndbRecordValues = null; 233 this.ndbRecordKeys = null; 234 this.bufferManager = null; 235 if (this.blobs != null) { 236 for (int i = 0; i < this.blobs.length; ++i) { 237 if (this.blobs[i] != null) { 238 this.blobs[i].release(); 239 this.blobs[i] = null; 240 } 241 } 242 this.blobs = null; 243 } 244 } 245 insert(ClusterTransactionImpl clusterTransactionImpl)246 public NdbOperationConst insert(ClusterTransactionImpl clusterTransactionImpl) { 247 // (only) if the autoincrement column has not been set by the user, get the autoincrement value 248 if (autoIncrement && !isModified(autoIncrementColumnId)) { 249 long value = db.getAutoincrementValue(storeTable); 250 if (logger.isDebugEnabled()) { 251 logger.debug("insert for " + storeTable.getName() + " autoincrement value: " + value); 252 } 253 ndbRecordValues.setAutoIncrementValue(valueBuffer, value); 254 columnSet(autoIncrementColumnId); 255 } 256 // position the buffer at the beginning for ndbjtie 257 valueBuffer.limit(valueBufferSize); 258 valueBuffer.position(0); 259 ndbOperation = clusterTransactionImpl.insertTuple(ndbRecordValues.getNdbRecord(), valueBuffer, mask, null); 260 clusterTransactionImpl.addOperationToCheck(this); 261 // for each blob column set, get the blob handle and write the values 262 for (NdbRecordBlobImpl blob: activeBlobs) { 263 // activate the blob by getting the NdbBlob 264 blob.setNdbBlob(); 265 // set values into the blob 266 blob.setValue(); 267 } 268 return ndbOperation; 269 } 270 delete(ClusterTransactionImpl clusterTransactionImpl)271 public NdbOperationConst delete(ClusterTransactionImpl clusterTransactionImpl) { 272 // position the buffer at the beginning for ndbjtie 273 keyBuffer.limit(keyBufferSize); 274 keyBuffer.position(0); 275 ndbOperation = clusterTransactionImpl.deleteTuple(ndbRecordKeys.getNdbRecord(), keyBuffer, mask, null); 276 return ndbOperation; 277 } 278 update(ClusterTransactionImpl clusterTransactionImpl)279 public void update(ClusterTransactionImpl clusterTransactionImpl) { 280 // position the buffer at the beginning for ndbjtie 281 valueBuffer.limit(valueBufferSize); 282 valueBuffer.position(0); 283 ndbOperation = clusterTransactionImpl.updateTuple(ndbRecordValues.getNdbRecord(), valueBuffer, mask, null); 284 clusterTransactionImpl.addOperationToCheck(this); 285 // calculate the active blobs 286 activeBlobs.clear(); 287 for (NdbRecordBlobImpl blob: blobs) { 288 if (blob != null && isColumnSet(blob.getColumnId())) { 289 activeBlobs.add(blob); 290 blob.setNdbBlob(); 291 blob.setValue(); 292 } 293 } 294 if (!activeBlobs.isEmpty()) { 295 // if any blobs, execute the transaction to enable the blob values to be updated 296 clusterTransactionImpl.executeNoCommit(); 297 } 298 return; 299 } 300 write(ClusterTransactionImpl clusterTransactionImpl)301 public void write(ClusterTransactionImpl clusterTransactionImpl) { 302 // position the buffer at the beginning for ndbjtie 303 valueBuffer.limit(valueBufferSize); 304 valueBuffer.position(0); 305 ndbOperation = clusterTransactionImpl.writeTuple(ndbRecordValues.getNdbRecord(), valueBuffer, mask, null); 306 clusterTransactionImpl.addOperationToCheck(this); 307 // for each blob column set, get the blob handle and write the values 308 for (NdbRecordBlobImpl blob: activeBlobs) { 309 // activate the blob by getting the NdbBlob 310 blob.setNdbBlob(); 311 // set values into the blob 312 blob.setValue(); 313 } 314 return; 315 } 316 load(ClusterTransactionImpl clusterTransactionImpl)317 public void load(ClusterTransactionImpl clusterTransactionImpl) { 318 // position the buffer at the beginning for ndbjtie 319 valueBuffer.limit(valueBufferSize); 320 valueBuffer.position(0); 321 ndbOperation = clusterTransactionImpl.readTuple(ndbRecordKeys.getNdbRecord(), keyBuffer, ndbRecordValues.getNdbRecord(), valueBuffer, mask, null); 322 // for each blob column set, get the blob handle 323 for (NdbRecordBlobImpl blob: activeBlobs) { 324 // activate the blob by getting the NdbBlob 325 blob.setNdbBlob(); 326 } 327 } 328 resetMask()329 protected void resetMask() { 330 this.mask = new byte[1 + (numberOfColumns/8)]; 331 } 332 allocateValueBuffer()333 public void allocateValueBuffer() { 334 this.valueBuffer = ndbRecordValues.newBuffer(); 335 } 336 activateBlobs()337 protected void activateBlobs() { 338 for (NdbRecordBlobImpl blob: activeBlobs) { 339 blob.setNdbBlob(); 340 } 341 } 342 equalBigInteger(Column storeColumn, BigInteger value)343 public void equalBigInteger(Column storeColumn, BigInteger value) { 344 int columnId = ndbRecordKeys.setBigInteger(keyBuffer, storeColumn, value); 345 columnSet(columnId); 346 } 347 equalBoolean(Column storeColumn, boolean booleanValue)348 public void equalBoolean(Column storeColumn, boolean booleanValue) { 349 byte value = (booleanValue?(byte)0x01:(byte)0x00); 350 equalByte(storeColumn, value); 351 } 352 equalByte(Column storeColumn, byte value)353 public void equalByte(Column storeColumn, byte value) { 354 int columnId = ndbRecordKeys.setByte(keyBuffer, storeColumn, value); 355 columnSet(columnId); 356 } 357 equalBytes(Column storeColumn, byte[] value)358 public void equalBytes(Column storeColumn, byte[] value) { 359 int columnId = ndbRecordKeys.setBytes(keyBuffer, storeColumn, value); 360 columnSet(columnId); 361 } 362 equalDecimal(Column storeColumn, BigDecimal value)363 public void equalDecimal(Column storeColumn, BigDecimal value) { 364 int columnId = ndbRecordKeys.setDecimal(keyBuffer, storeColumn, value); 365 columnSet(columnId); 366 } 367 equalDouble(Column storeColumn, double value)368 public void equalDouble(Column storeColumn, double value) { 369 int columnId = ndbRecordKeys.setDouble(keyBuffer, storeColumn, value); 370 columnSet(columnId); 371 } 372 equalFloat(Column storeColumn, float value)373 public void equalFloat(Column storeColumn, float value) { 374 int columnId = ndbRecordKeys.setFloat(keyBuffer, storeColumn, value); 375 columnSet(columnId); 376 } 377 equalInt(Column storeColumn, int value)378 public void equalInt(Column storeColumn, int value) { 379 int columnId = ndbRecordKeys.setInt(keyBuffer, storeColumn, value); 380 columnSet(columnId); 381 } 382 equalLong(Column storeColumn, long value)383 public void equalLong(Column storeColumn, long value) { 384 int columnId = ndbRecordKeys.setLong(keyBuffer, storeColumn, value); 385 columnSet(columnId); 386 } 387 equalShort(Column storeColumn, short value)388 public void equalShort(Column storeColumn, short value) { 389 int columnId = ndbRecordKeys.setShort(keyBuffer, storeColumn, value); 390 columnSet(columnId); 391 } 392 equalString(Column storeColumn, String value)393 public void equalString(Column storeColumn, String value) { 394 int columnId = ndbRecordKeys.setString(keyBuffer, bufferManager, storeColumn, value); 395 columnSet(columnId); 396 } 397 getBlob(Column storeColumn)398 public void getBlob(Column storeColumn) { 399 getBlobHandle(storeColumn); 400 } 401 402 /** 403 * Get the blob handle for this column. The same column will return the same blob handle 404 * regardless of how many times it is called. 405 * @param storeColumn the store column 406 * @return the blob handle 407 */ getBlobHandle(Column storeColumn)408 public Blob getBlobHandle(Column storeColumn) { 409 if (logger.isDetailEnabled()) { 410 logger.detail("column: " + storeColumn.getName()); 411 } 412 int columnId = storeColumn.getColumnId(); 413 NdbRecordBlobImpl result = blobs[columnId]; 414 if (result == null) { 415 if (logger.isDetailEnabled()) { 416 logger.detail("column: " + storeColumn.getName() + " was null; activating."); 417 } 418 columnSet(columnId); 419 result = new NdbRecordBlobImpl(this, storeColumn, byteBufferPool); 420 blobs[columnId] = result; 421 activeBlobs.add(result); 422 } 423 return result; 424 } 425 426 /** Specify the columns to be used for the operation. 427 */ getValue(Column storeColumn)428 public void getValue(Column storeColumn) { 429 int columnId = storeColumn.getColumnId(); 430 columnSet(columnId); 431 } 432 postExecuteCallback(Runnable callback)433 public void postExecuteCallback(Runnable callback) { 434 clusterTransaction.postExecuteCallback(callback); 435 } 436 437 /** Construct a new ResultData using the saved column data and then execute the operation. 438 */ resultData()439 public ResultData resultData() { 440 return resultData(true); 441 } 442 443 /** Construct a new ResultData and if requested, execute the operation. 444 */ resultData(boolean execute)445 public ResultData resultData(boolean execute) { 446 NdbRecordResultDataImpl result = 447 new NdbRecordResultDataImpl(this); 448 if (execute) { 449 clusterTransaction.executeNoCommit(false, true); 450 } 451 return result; 452 } 453 setBigInteger(Column storeColumn, BigInteger value)454 public void setBigInteger(Column storeColumn, BigInteger value) { 455 if (value == null) { 456 setNull(storeColumn); 457 } else { 458 int columnId = ndbRecordValues.setBigInteger(valueBuffer, storeColumn, value); 459 columnSet(columnId); 460 } 461 } 462 setBigInteger(int columnId, BigInteger value)463 public void setBigInteger(int columnId, BigInteger value) { 464 setBigInteger(storeColumns[columnId], value); 465 } 466 setBoolean(Column storeColumn, Boolean booleanValue)467 public void setBoolean(Column storeColumn, Boolean booleanValue) { 468 byte value = (booleanValue?(byte)0x01:(byte)0x00); 469 setByte(storeColumn, value); 470 } 471 setBoolean(int columnId, boolean value)472 public void setBoolean(int columnId, boolean value) { 473 setBoolean(storeColumns[columnId], value); 474 } 475 setByte(Column storeColumn, byte value)476 public void setByte(Column storeColumn, byte value) { 477 int columnId = ndbRecordValues.setByte(valueBuffer, storeColumn, value); 478 columnSet(columnId); 479 } 480 setByte(int columnId, byte value)481 public void setByte(int columnId, byte value) { 482 setByte(storeColumns[columnId], value); 483 } 484 setBytes(Column storeColumn, byte[] value)485 public void setBytes(Column storeColumn, byte[] value) { 486 if (logger.isDetailEnabled()) { 487 logger.detail("NdbRecordOperationImpl.setBytes for: " + storeColumn.getName() + " value: " + 488 Utility.dumpBytes(value)); 489 } 490 if (value == null) { 491 setNull(storeColumn); 492 } else { 493 int columnId = ndbRecordValues.setBytes(valueBuffer, storeColumn, value); 494 columnSet(columnId); 495 } 496 } 497 setBytes(int columnId, byte[] value)498 public void setBytes(int columnId, byte[] value) { 499 setBytes(storeColumns[columnId], value); 500 } 501 setDecimal(Column storeColumn, BigDecimal value)502 public void setDecimal(Column storeColumn, BigDecimal value) { 503 if (value == null) { 504 setNull(storeColumn); 505 } else { 506 int columnId = ndbRecordValues.setDecimal(valueBuffer, storeColumn, value); 507 columnSet(columnId); 508 } 509 } 510 setDecimal(int columnId, BigDecimal value)511 public void setDecimal(int columnId, BigDecimal value) { 512 setDecimal(storeColumns[columnId], value); 513 } 514 setDouble(Column storeColumn, Double value)515 public void setDouble(Column storeColumn, Double value) { 516 int columnId = ndbRecordValues.setDouble(valueBuffer, storeColumn, value); 517 columnSet(columnId); 518 } 519 setDouble(int columnId, double value)520 public void setDouble(int columnId, double value) { 521 setDouble(storeColumns[columnId], value); 522 } 523 setFloat(Column storeColumn, Float value)524 public void setFloat(Column storeColumn, Float value) { 525 int columnId = ndbRecordValues.setFloat(valueBuffer, storeColumn, value); 526 columnSet(columnId); 527 } 528 setFloat(int columnId, float value)529 public void setFloat(int columnId, float value) { 530 setFloat(storeColumns[columnId], value); 531 } 532 setInt(Column storeColumn, Integer value)533 public void setInt(Column storeColumn, Integer value) { 534 int columnId = ndbRecordValues.setInt(valueBuffer, storeColumn, value); 535 columnSet(columnId); 536 } 537 setInt(int columnId, int value)538 public void setInt(int columnId, int value) { 539 setInt(storeColumns[columnId], value); 540 } 541 setLong(Column storeColumn, long value)542 public void setLong(Column storeColumn, long value) { 543 int columnId = ndbRecordValues.setLong(valueBuffer, storeColumn, value); 544 columnSet(columnId); 545 } 546 setLong(int columnId, long value)547 public void setLong(int columnId, long value) { 548 setLong(storeColumns[columnId], value); 549 } 550 setNull(Column storeColumn)551 public void setNull(Column storeColumn) { 552 int columnId = ndbRecordValues.setNull(valueBuffer, storeColumn); 553 columnSet(columnId); 554 } 555 setNull(int columnId)556 public void setNull(int columnId) { 557 setNull(storeColumns[columnId]); 558 } 559 setShort(Column storeColumn, Short value)560 public void setShort(Column storeColumn, Short value) { 561 int columnId = ndbRecordValues.setShort(valueBuffer, storeColumn, value); 562 columnSet(columnId); 563 } 564 setShort(int columnId, short value)565 public void setShort(int columnId, short value) { 566 setShort(storeColumns[columnId], value); 567 } 568 setObjectBoolean(int columnId, Boolean value)569 public void setObjectBoolean(int columnId, Boolean value) { 570 Column storeColumn = storeColumns[columnId]; 571 if (value == null) { 572 setNull(storeColumn); 573 } else { 574 setBoolean(storeColumn, value); 575 } 576 } 577 setObjectByte(int columnId, Byte value)578 public void setObjectByte(int columnId, Byte value) { 579 Column storeColumn = storeColumns[columnId]; 580 if (value == null) { 581 setNull(storeColumn); 582 } else { 583 setByte(storeColumn, value); 584 } 585 } 586 setObjectDouble(int columnId, Double value)587 public void setObjectDouble(int columnId, Double value) { 588 Column storeColumn = storeColumns[columnId]; 589 if (value == null) { 590 setNull(storeColumn); 591 } else { 592 setDouble(storeColumn, value); 593 } 594 } 595 setObjectFloat(int columnId, Float value)596 public void setObjectFloat(int columnId, Float value) { 597 Column storeColumn = storeColumns[columnId]; 598 if (value == null) { 599 setNull(storeColumn); 600 } else { 601 setFloat(storeColumn, value); 602 } 603 } 604 setObjectInt(int columnId, Integer value)605 public void setObjectInt(int columnId, Integer value) { 606 Column storeColumn = storeColumns[columnId]; 607 if (value == null) { 608 setNull(storeColumn); 609 } else { 610 setInt(storeColumn, value); 611 } 612 } 613 setObjectLong(int columnId, Long value)614 public void setObjectLong(int columnId, Long value) { 615 Column storeColumn = storeColumns[columnId]; 616 if (value == null) { 617 setNull(storeColumn); 618 } else { 619 setLong(storeColumn, value); 620 } 621 } 622 setObjectShort(int columnId, Short value)623 public void setObjectShort(int columnId, Short value) { 624 Column storeColumn = storeColumns[columnId]; 625 if (value == null) { 626 setNull(storeColumn); 627 } else { 628 setShort(storeColumn, value); 629 } 630 } 631 setString(Column storeColumn, String value)632 public void setString(Column storeColumn, String value) { 633 if (value == null) { 634 setNull(storeColumn); 635 } else { 636 int columnId = ndbRecordValues.setString(valueBuffer, bufferManager, storeColumn, value); 637 columnSet(columnId); 638 } 639 } 640 setString(int columnId, String value)641 public void setString(int columnId, String value) { 642 setString(storeColumns[columnId], value); 643 } 644 errorCode()645 public int errorCode() { 646 return ndbOperation.getNdbError().code(); 647 } 648 handleError(int returnCode, NdbOperationConst ndbOperation2)649 protected static void handleError(int returnCode, NdbOperationConst ndbOperation2) { 650 if (returnCode == 0) { 651 return; 652 } else { 653 Utility.throwError(returnCode, ndbOperation2.getNdbError()); 654 } 655 } 656 handleError(Object object, NdbOperationConst ndbOperation)657 protected static void handleError(Object object, NdbOperationConst ndbOperation) { 658 if (object != null) { 659 return; 660 } else { 661 Utility.throwError(null, ndbOperation.getNdbError()); 662 } 663 } 664 handleError(Object object, Dictionary ndbDictionary)665 protected static void handleError(Object object, Dictionary ndbDictionary) { 666 if (object != null) { 667 return; 668 } else { 669 Utility.throwError(null, ndbDictionary.getNdbError()); 670 } 671 } 672 getNdbBlob(Column storeColumn)673 public NdbBlob getNdbBlob(Column storeColumn) { 674 if (ndbOperation == null) { 675 throw new ClusterJFatalInternalException("NdbRecordOperationImpl.getNdbBlob with no ndbOperation."); 676 } else { 677 NdbBlob result = ndbOperation.getBlobHandle(storeColumn.getColumnId()); 678 handleError(result, ndbOperation); 679 return result; 680 } 681 } 682 683 /** Activate blob/text columns just read 684 * 685 */ activateBlobColumns()686 public void activateBlobColumns() { 687 for (Column storeColumn: storeColumns) { 688 if (storeColumn.isLob()) { 689 getBlobHandle(storeColumn); 690 } 691 } 692 } 693 694 /** 695 * Set this column into the mask for NdbRecord operation. 696 * @param columnId the column id 697 */ columnSet(int columnId)698 protected void columnSet(int columnId) { 699 int byteOffset = columnId / 8; 700 int bitInByte = columnId - (byteOffset * 8); 701 mask[byteOffset] |= NdbRecordImpl.BIT_IN_BYTE_MASK[bitInByte]; 702 } 703 isColumnSet(int columnId)704 protected boolean isColumnSet(int columnId) { 705 int byteOffset = columnId / 8; 706 int bitInByte = columnId - (byteOffset * 8); 707 byte testMask = NdbRecordImpl.BIT_IN_BYTE_MASK[bitInByte]; 708 return (mask[byteOffset] & testMask) == testMask; 709 } 710 getValueNdbRecord()711 public NdbRecordImpl getValueNdbRecord() { 712 return ndbRecordValues; 713 } 714 getBoolean(int columnId)715 public boolean getBoolean(int columnId) { 716 return ndbRecordValues.getBoolean(valueBuffer, columnId); 717 } 718 getBoolean(Column storeColumn)719 public boolean getBoolean(Column storeColumn) { 720 return ndbRecordValues.getBoolean(valueBuffer, storeColumn.getColumnId()); 721 } 722 getBooleans(int column)723 public boolean[] getBooleans(int column) { 724 throw new ClusterJFatalInternalException(local.message("ERR_Method_Not_Implemented", 725 "NdbRecordResultDataImpl.getBooleans(int)")); 726 } 727 getBooleans(Column storeColumn)728 public boolean[] getBooleans(Column storeColumn) { 729 throw new ClusterJFatalInternalException(local.message("ERR_Method_Not_Implemented", 730 "NdbRecordResultDataImpl.getBooleans(Column)")); 731 } 732 getByte(int columnId)733 public byte getByte(int columnId) { 734 return ndbRecordValues.getByte(valueBuffer, columnId); 735 } 736 getByte(Column storeColumn)737 public byte getByte(Column storeColumn) { 738 return ndbRecordValues.getByte(valueBuffer, storeColumn.getColumnId()); 739 } 740 getShort(int columnId)741 public short getShort(int columnId) { 742 return ndbRecordValues.getShort(valueBuffer, columnId); 743 } 744 getShort(Column storeColumn)745 public short getShort(Column storeColumn) { 746 return ndbRecordValues.getShort(valueBuffer, storeColumn.getColumnId()); 747 } 748 getInt(int columnId)749 public int getInt(int columnId) { 750 return ndbRecordValues.getInt(valueBuffer, columnId); 751 } 752 getInt(Column storeColumn)753 public int getInt(Column storeColumn) { 754 return getInt(storeColumn.getColumnId()); 755 } 756 getLong(int columnId)757 public long getLong(int columnId) { 758 return ndbRecordValues.getLong(valueBuffer, columnId); 759 } 760 getFloat(int columnId)761 public float getFloat(int columnId) { 762 return ndbRecordValues.getFloat(valueBuffer, columnId); 763 } 764 getFloat(Column storeColumn)765 public float getFloat(Column storeColumn) { 766 return getFloat(storeColumn.getColumnId()); 767 } 768 getDouble(int columnId)769 public double getDouble(int columnId) { 770 return ndbRecordValues.getDouble(valueBuffer, columnId); 771 } 772 getDouble(Column storeColumn)773 public double getDouble(Column storeColumn) { 774 return getDouble(storeColumn.getColumnId()); 775 } 776 getString(int columnId)777 public String getString(int columnId) { 778 return ndbRecordValues.getString(valueBuffer, columnId, bufferManager); 779 } 780 getString(Column storeColumn)781 public String getString(Column storeColumn) { 782 return ndbRecordValues.getString(valueBuffer, storeColumn.getColumnId(), bufferManager); 783 } 784 getBytes(int column)785 public byte[] getBytes(int column) { 786 return ndbRecordValues.getBytes(valueBuffer, column); 787 } 788 getBytes(Column storeColumn)789 public byte[] getBytes(Column storeColumn) { 790 return ndbRecordValues.getBytes(valueBuffer, storeColumn); 791 } 792 getObject(int column)793 public Object getObject(int column) { 794 throw new ClusterJFatalInternalException(local.message("ERR_Method_Not_Implemented", 795 "NdbRecordResultDataImpl.getObject(int)")); 796 } 797 getObject(Column storeColumn)798 public Object getObject(Column storeColumn) { 799 throw new ClusterJFatalInternalException(local.message("ERR_Method_Not_Implemented", 800 "NdbRecordResultDataImpl.getObject(Column)")); 801 } 802 wasNull(Column storeColumn)803 public boolean wasNull(Column storeColumn) { 804 throw new ClusterJFatalInternalException(local.message("ERR_Method_Not_Implemented", 805 "NdbRecordResultDataImpl.wasNull(Column)")); 806 } 807 getObjectBoolean(int column)808 public Boolean getObjectBoolean(int column) { 809 return ndbRecordValues.getObjectBoolean(valueBuffer, column); 810 } 811 getObjectBoolean(Column storeColumn)812 public Boolean getObjectBoolean(Column storeColumn) { 813 return ndbRecordValues.getObjectBoolean(valueBuffer, storeColumn.getColumnId()); 814 } 815 getObjectByte(int columnId)816 public Byte getObjectByte(int columnId) { 817 return ndbRecordValues.getObjectByte(valueBuffer, columnId); 818 } 819 getObjectByte(Column storeColumn)820 public Byte getObjectByte(Column storeColumn) { 821 return ndbRecordValues.getObjectByte(valueBuffer, storeColumn.getColumnId()); 822 } 823 getObjectFloat(int column)824 public Float getObjectFloat(int column) { 825 return ndbRecordValues.getObjectFloat(valueBuffer, column); 826 } 827 getObjectFloat(Column storeColumn)828 public Float getObjectFloat(Column storeColumn) { 829 return ndbRecordValues.getObjectFloat(valueBuffer, storeColumn.getColumnId()); 830 } 831 getObjectDouble(int column)832 public Double getObjectDouble(int column) { 833 return ndbRecordValues.getObjectDouble(valueBuffer, column); 834 } 835 getObjectDouble(Column storeColumn)836 public Double getObjectDouble(Column storeColumn) { 837 return ndbRecordValues.getObjectDouble(valueBuffer, storeColumn.getColumnId()); 838 } 839 getObjectInteger(int columnId)840 public Integer getObjectInteger(int columnId) { 841 return ndbRecordValues.getObjectInteger(valueBuffer, columnId); 842 } 843 getObjectInteger(Column storeColumn)844 public Integer getObjectInteger(Column storeColumn) { 845 return ndbRecordValues.getObjectInteger(valueBuffer, storeColumn.getColumnId()); 846 } 847 getObjectLong(int column)848 public Long getObjectLong(int column) { 849 return ndbRecordValues.getObjectLong(valueBuffer, column); 850 } 851 getObjectLong(Column storeColumn)852 public Long getObjectLong(Column storeColumn) { 853 return ndbRecordValues.getObjectLong(valueBuffer, storeColumn.getColumnId()); 854 } 855 getObjectShort(int columnId)856 public Short getObjectShort(int columnId) { 857 return ndbRecordValues.getObjectShort(valueBuffer, columnId); 858 } 859 getObjectShort(Column storeColumn)860 public Short getObjectShort(Column storeColumn) { 861 return ndbRecordValues.getObjectShort(valueBuffer, storeColumn.getColumnId()); 862 } 863 getBigInteger(int column)864 public BigInteger getBigInteger(int column) { 865 return ndbRecordValues.getBigInteger(valueBuffer, column); 866 } 867 getBigInteger(Column storeColumn)868 public BigInteger getBigInteger(Column storeColumn) { 869 return ndbRecordValues.getBigInteger(valueBuffer, storeColumn); 870 } 871 getDecimal(int column)872 public BigDecimal getDecimal(int column) { 873 return ndbRecordValues.getDecimal(valueBuffer, column); 874 } 875 getDecimal(Column storeColumn)876 public BigDecimal getDecimal(Column storeColumn) { 877 return ndbRecordValues.getDecimal(valueBuffer, storeColumn); 878 } 879 beginDefinition()880 public void beginDefinition() { 881 // by default, nothing to do 882 } 883 endDefinition()884 public void endDefinition() { 885 // by default, nothing to do 886 } 887 freeResourcesAfterExecute()888 public void freeResourcesAfterExecute() { 889 // by default, nothing to do 890 } 891 dumpValues()892 public String dumpValues() { 893 return ndbRecordValues.dumpValues(valueBuffer, mask); 894 } 895 dumpKeys()896 public String dumpKeys() { 897 return ndbRecordKeys.dumpValues(keyBuffer, null); 898 } 899 isModified(int columnId)900 public boolean isModified(int columnId) { 901 return ndbRecordValues.isPresent(mask, columnId); 902 } 903 isNull(int columnId)904 public boolean isNull(int columnId) { 905 return ndbRecordValues.isNull(valueBuffer, columnId); 906 } 907 markModified(int columnId)908 public void markModified(int columnId) { 909 ndbRecordValues.markPresent(mask, columnId); 910 } 911 resetModified()912 public void resetModified() { 913 this.mask = new byte[1 + (numberOfColumns/8)]; 914 } 915 getBlobHandle(int columnId)916 public NdbRecordBlobImpl getBlobHandle(int columnId) { 917 return (NdbRecordBlobImpl) getBlobHandle(storeColumns[columnId]); 918 } 919 getErrorCode()920 public int getErrorCode() { 921 return ndbOperation.getNdbError().code(); 922 } 923 getClassification()924 public int getClassification() { 925 return ndbOperation.getNdbError().classification(); 926 } 927 getMysqlCode()928 public int getMysqlCode() { 929 return ndbOperation.getNdbError().mysql_code(); 930 } 931 getStatus()932 public int getStatus() { 933 return ndbOperation.getNdbError().status(); 934 } 935 936 @Override toString()937 public String toString() { 938 return " NdbRecordOperationImpl for table " + tableName; 939 } 940 941 /** After executing the operation, fetch the blob values into each blob's data holder. 942 * 943 */ loadBlobValues()944 public void loadBlobValues() { 945 for (NdbRecordBlobImpl ndbRecordBlobImpl: activeBlobs) { 946 ndbRecordBlobImpl.readData(); 947 } 948 } 949 950 /** Transform this NdbRecordOperationImpl into one that can be used to back a SmartValueHandler. 951 * For instances that are used in primary key or unique key operations, the same instance is used. 952 * Scans are handled by a subclass that overrides this method. 953 * 954 * @return this NdbRecordOperationImpl 955 */ transformNdbRecordOperationImpl()956 public NdbRecordOperationImpl transformNdbRecordOperationImpl() { 957 this.keyBuffer = valueBuffer; 958 resetModified(); 959 return this; 960 } 961 962 /** Check the NdbRecord buffer guard */ checkGuard(String where)963 protected void checkGuard(String where) { 964 if (ndbRecordValues != null) { 965 ndbRecordValues.checkGuard(this.valueBuffer, where); 966 } 967 } 968 969 } 970