1 /*
2 Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
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 #include <node_buffer.h>
26
27 #include "adapter_global.h"
28 #include "unified_debug.h"
29 #include "KeyOperation.h"
30
31 using namespace v8;
32
33 const char * opcode_strings[17] =
34 { 0, "read ", "insert", 0, "update", 0, 0, 0, "write ",
35 0, 0, 0, 0, 0, 0, 0, "delete" };
36
getOperationName()37 const char * KeyOperation::getOperationName() {
38 return opcode < 17 ? opcode_strings[opcode] : 0;
39 }
40
41 // Call the right destructor for a chain of blob handlers,
42 // where B is either BlobReadHandler or BlobWriteHandler
deleteBlobChain(BlobHandler * b)43 template <typename B> void deleteBlobChain(BlobHandler *b) {
44 do {
45 B * blobHandler = static_cast<B *>(b);
46 b = blobHandler->getNext();
47 delete blobHandler;
48 } while(b);
49 }
50
~KeyOperation()51 KeyOperation::~KeyOperation() {
52 if(isBlobReadOperation()) {
53 deleteBlobChain<BlobReadHandler>(blobHandler);
54 } else if(blobHandler) {
55 deleteBlobChain<BlobWriteHandler>(blobHandler);
56 }
57 }
58
readTuple(NdbTransaction * tx)59 const NdbOperation * KeyOperation::readTuple(NdbTransaction *tx) {
60 const NdbOperation *op;
61 op = tx->readTuple(key_record->getNdbRecord(), key_buffer,
62 row_record->getNdbRecord(), row_buffer, lmode, read_mask_ptr);
63 if(blobHandler) blobHandler->prepare(op);
64 return op;
65 }
66
deleteTuple(NdbTransaction * tx)67 const NdbOperation * KeyOperation::deleteTuple(NdbTransaction *tx) {
68 return tx->deleteTuple(key_record->getNdbRecord(), key_buffer,
69 row_record->getNdbRecord(), 0, 0, options);
70 }
71
writeTuple(NdbTransaction * tx)72 const NdbOperation * KeyOperation::writeTuple(NdbTransaction *tx) {
73 const NdbOperation *op;
74 op = tx->writeTuple(key_record->getNdbRecord(), key_buffer,
75 row_record->getNdbRecord(), row_buffer, u.row_mask);
76 if(blobHandler) blobHandler->prepare(op);
77 return op;
78 }
79
insertTuple(NdbTransaction * tx)80 const NdbOperation * KeyOperation::insertTuple(NdbTransaction *tx) {
81 const NdbOperation *op;
82 op = tx->insertTuple(row_record->getNdbRecord(), row_buffer,
83 u.row_mask, options);
84 if(blobHandler) blobHandler->prepare(op);
85 return op;
86 }
87
updateTuple(NdbTransaction * tx)88 const NdbOperation * KeyOperation::updateTuple(NdbTransaction *tx) {
89 const NdbOperation *op;
90 op = tx->updateTuple(key_record->getNdbRecord(), key_buffer,
91 row_record->getNdbRecord(), row_buffer,
92 u.row_mask, options);
93 if(blobHandler) blobHandler->prepare(op);
94 return op;
95 }
96
97
prepare(NdbTransaction * tx)98 const NdbOperation * KeyOperation::prepare(NdbTransaction *tx) {
99 switch(opcode) {
100 case 1: // OP_READ:
101 return readTuple(tx);
102 case 2: // OP_INSERT:
103 return insertTuple(tx);
104 case 4: // OP_UPDATE:
105 return updateTuple(tx);
106 case 8: // OP_WRITE:
107 return writeTuple(tx);
108 case 16: // OP_DELETE:
109 return deleteTuple(tx);
110 default:
111 return NULL;
112 }
113 }
114
setBlobHandler(BlobHandler * b)115 void KeyOperation::setBlobHandler(BlobHandler *b) {
116 b->setNext(blobHandler);
117 blobHandler = b;
118 }
119
createBlobReadHandles(const Record * rowRecord)120 int KeyOperation::createBlobReadHandles(const Record * rowRecord) {
121 DEBUG_MARKER(UDEB_DEBUG);
122 int ncreated = 0;
123 int ncol = rowRecord->getNoOfColumns();
124 for(int i = 0 ; i < ncol ; i++) {
125 const NdbDictionary::Column * col = rowRecord->getColumn(i);
126 if((col->getType() == NdbDictionary::Column::Blob) ||
127 (col->getType() == NdbDictionary::Column::Text))
128 {
129 setBlobHandler(new BlobReadHandler(i, col->getColumnNo()));
130 ncreated++;
131 }
132 }
133 return ncreated;
134 }
135
136
createBlobWriteHandles(Handle<Object> blobsArray,const Record * rowRecord)137 int KeyOperation::createBlobWriteHandles(Handle<Object> blobsArray,
138 const Record * rowRecord) {
139 DEBUG_MARKER(UDEB_DEBUG);
140 int ncreated = 0;
141 int ncol = rowRecord->getNoOfColumns();
142 for(int i = 0 ; i < ncol ; i++) {
143 if(blobsArray->Get(i)->IsObject()) {
144 Local<Object> blobValue = blobsArray->Get(i)->ToObject();
145 assert(node::Buffer::HasInstance(blobValue));
146 const NdbDictionary::Column * col = rowRecord->getColumn(i);
147 assert( (col->getType() == NdbDictionary::Column::Blob) ||
148 (col->getType() == NdbDictionary::Column::Text));
149 ncreated++;
150 setBlobHandler(new BlobWriteHandler(i, col->getColumnNo(), blobValue));
151 }
152 }
153 return ncreated;
154 }
155
156
readBlobResults(const Arguments & args)157 void KeyOperation::readBlobResults(const Arguments & args) {
158 DEBUG_MARKER(UDEB_DEBUG);
159 v8::Isolate * isolate = args.GetIsolate();
160 EscapableHandleScope scope(isolate);
161
162 args.GetReturnValue().SetUndefined();
163 if(isBlobReadOperation()) {
164 Local<Object> results = Array::New(isolate);
165 BlobReadHandler * readHandler = static_cast<BlobReadHandler *>(blobHandler);
166 while(readHandler) {
167 Local<Value> buffer = readHandler->getResultBuffer(isolate);
168 if(buffer.IsEmpty()) {
169 buffer = Null(isolate);
170 }
171 results->ToObject()->Set(readHandler->getFieldNumber(), buffer);
172 readHandler = static_cast<BlobReadHandler *>(readHandler->getNext());
173 }
174 args.GetReturnValue().Set(scope.Escape(results));
175 }
176 }
177