1 /*
2 Copyright (c) 2013, 2018, 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 <string.h>
26
27 #include <node.h>
28 #include <node_buffer.h>
29
30 #include "adapter_global.h"
31 #include "KeyOperation.h"
32 #include "BatchImpl.h"
33 #include "NdbWrappers.h"
34 #include "js_wrapper_macros.h"
35 #include "NdbRecordObject.h"
36 #include "TransactionImpl.h"
37 #include "BlobHandler.h"
38
39 enum {
40 HELPER_ROW_BUFFER = 0,
41 HELPER_KEY_BUFFER,
42 HELPER_ROW_RECORD,
43 HELPER_KEY_RECORD,
44 HELPER_LOCK_MODE,
45 HELPER_COLUMN_MASK,
46 HELPER_VALUE_OBJECT,
47 HELPER_OPCODE,
48 HELPER_IS_VO,
49 HELPER_BLOBS,
50 HELPER_IS_VALID
51 };
52
53 void DBOperationHelper_VO(Handle<Object>, KeyOperation &);
54 void DBOperationHelper_NonVO(Handle<Object>, KeyOperation &);
55
56 void setKeysInOp(Handle<Object> spec, KeyOperation & op);
57
58
59 /* DBOperationHelper takes an array of HelperSpecs.
60 arg0: Length of Array
61 arg1: Array of HelperSpecs
62 arg2: TransactionImpl *
63 arg3: Old BatchImpl wrapper (for recycling)
64
65 Returns: BatchImpl
66 */
DBOperationHelper(const Arguments & args)67 void DBOperationHelper(const Arguments &args) {
68 EscapableHandleScope scope(args.GetIsolate());
69
70 int length = args[0]->Int32Value();
71 const Local<Object> array = args[1]->ToObject();
72 TransactionImpl *txc = unwrapPointer<TransactionImpl *>(args[2]->ToObject());
73 Handle<Value> oldWrapper = args[3];
74
75 BatchImpl * pendingOps = new BatchImpl(txc, length);
76
77 for(int i = 0 ; i < length ; i++) {
78 Handle<Object> spec = array->Get(i)->ToObject();
79
80 int opcode = spec->Get(HELPER_OPCODE)->Int32Value();
81 bool is_vo = spec->Get(HELPER_IS_VO)->ToBoolean()->Value();
82 bool op_ok = spec->Get(HELPER_IS_VALID)->ToBoolean()->Value();
83
84 KeyOperation * op = pendingOps->getKeyOperation(i);
85
86 if(op_ok) {
87 op->opcode = opcode;
88 if(is_vo) DBOperationHelper_VO(spec, *op);
89 else DBOperationHelper_NonVO(spec, *op);
90 }
91 }
92
93 if(oldWrapper->IsObject()) {
94 args.GetReturnValue().Set(BatchImpl_Recycle(oldWrapper->ToObject(), pendingOps));
95 } else {
96 args.GetReturnValue().Set(BatchImpl_Wrapper(pendingOps));
97 }
98 }
99
100
setKeysInOp(Handle<Object> spec,KeyOperation & op)101 void setKeysInOp(Handle<Object> spec, KeyOperation & op) {
102 Local<Value> v;
103 Local<Object> o;
104
105 v = spec->Get(HELPER_KEY_BUFFER);
106 if(! v->IsNull()) {
107 o = v->ToObject();
108 op.key_buffer = node::Buffer::Data(o);
109 }
110
111 v = spec->Get(HELPER_KEY_RECORD);
112 if(! v->IsNull()) {
113 o = v->ToObject();
114 op.key_record = unwrapPointer<const Record *>(o);
115 }
116 }
117
118
DBOperationHelper_NonVO(Handle<Object> spec,KeyOperation & op)119 void DBOperationHelper_NonVO(Handle<Object> spec, KeyOperation & op) {
120 Local<Value> v;
121 Local<Object> o;
122
123 setKeysInOp(spec, op);
124
125 v = spec->Get(HELPER_ROW_BUFFER);
126 if(! v->IsNull()) {
127 o = v->ToObject();
128 op.row_buffer = node::Buffer::Data(o);
129 }
130
131 v = spec->Get(HELPER_ROW_RECORD);
132 if(! v->IsNull()) {
133 o = v->ToObject();
134 const Record * record = unwrapPointer<const Record *>(o);
135 op.row_record = record;
136
137 v = spec->Get(HELPER_BLOBS);
138 if(v->IsObject()) {
139 if(op.opcode == 1) {
140 op.nblobs = op.createBlobReadHandles(record);
141 } else {
142 op.nblobs = op.createBlobWriteHandles(v->ToObject(), record);
143 }
144 }
145 }
146
147 v = spec->Get(HELPER_LOCK_MODE);
148 if(! v->IsNull()) {
149 int intLockMode = v->Int32Value();
150 op.lmode = static_cast<NdbOperation::LockMode>(intLockMode);
151 }
152
153 v = spec->Get(HELPER_COLUMN_MASK);
154 if(! v->IsNull()) {
155 v8::Array *maskArray = v8::Array::Cast(*v);
156 for(unsigned int m = 0 ; m < maskArray->Length() ; m++) {
157 Local<Value> colId = maskArray->Get(m);
158 op.useColumn(colId->Int32Value());
159 }
160 }
161
162 DEBUG_PRINT("Non-VO %s -- mask: %u lobs: %d", op.getOperationName(),
163 op.u.maskvalue, op.nblobs);
164 }
165
166
DBOperationHelper_VO(Handle<Object> spec,KeyOperation & op)167 void DBOperationHelper_VO(Handle<Object> spec, KeyOperation & op) {
168 DEBUG_MARKER(UDEB_DETAIL);
169 Local<Value> v;
170 Local<Object> o;
171 Local<Object> valueObj;
172
173 v = spec->Get(HELPER_VALUE_OBJECT);
174 valueObj = v->ToObject();
175 NdbRecordObject * nro = unwrapPointer<NdbRecordObject *>(valueObj);
176
177 /* Set the key record and key buffer from the helper spec */
178 setKeysInOp(spec, op);
179
180 /* Set the row record, row buffer, and mask from the VO */
181 op.row_record = nro->getRecord();
182 op.row_buffer = nro->getBuffer();
183
184 /* A persist operation must write all columns.
185 A save operation must write all columns only if the PK has changed.
186 Other operations only write columns that have changed since being read.
187 */
188 if(op.opcode == 2)
189 op.setRowMask(op.row_record->getAllColumnMask());
190 else if(op.opcode == 8 && (nro->getMaskValue() & op.row_record->getPkColumnMask()))
191 op.setRowMask(op.row_record->getAllColumnMask());
192 else
193 op.setRowMask(nro->getMaskValue());
194
195 op.nblobs = nro->createBlobWriteHandles(op);
196
197 DEBUG_PRINT(" VO %s -- mask: %u lobs: %d", op.getOperationName(),
198 op.u.maskvalue, op.nblobs);
199 nro->resetMask();
200 }
201
202
DBOperationHelper_initOnLoad(Handle<Object> target)203 void DBOperationHelper_initOnLoad(Handle<Object> target) {
204 DEBUG_MARKER(UDEB_DETAIL);
205 DEFINE_JS_FUNCTION(target, "DBOperationHelper", DBOperationHelper);
206 Local<Object> OpHelper = Object::New(Isolate::GetCurrent());
207 Local<Object> LockModes = Object::New(Isolate::GetCurrent());
208
209 target->Set(NEW_SYMBOL("OpHelper"), OpHelper);
210 DEFINE_JS_INT(OpHelper, "row_buffer", HELPER_ROW_BUFFER);
211 DEFINE_JS_INT(OpHelper, "key_buffer", HELPER_KEY_BUFFER);
212 DEFINE_JS_INT(OpHelper, "row_record", HELPER_ROW_RECORD);
213 DEFINE_JS_INT(OpHelper, "key_record", HELPER_KEY_RECORD);
214 DEFINE_JS_INT(OpHelper, "lock_mode", HELPER_LOCK_MODE);
215 DEFINE_JS_INT(OpHelper, "column_mask", HELPER_COLUMN_MASK);
216 DEFINE_JS_INT(OpHelper, "value_obj", HELPER_VALUE_OBJECT);
217 DEFINE_JS_INT(OpHelper, "opcode", HELPER_OPCODE);
218 DEFINE_JS_INT(OpHelper, "is_value_obj", HELPER_IS_VO);
219 DEFINE_JS_INT(OpHelper, "blobs", HELPER_BLOBS);
220 DEFINE_JS_INT(OpHelper, "is_valid", HELPER_IS_VALID);
221
222 target->Set(NEW_SYMBOL("LockModes"), LockModes);
223 DEFINE_JS_INT(LockModes, "EXCLUSIVE", NdbOperation::LM_Exclusive);
224 DEFINE_JS_INT(LockModes, "SHARED", NdbOperation::LM_Read);
225 DEFINE_JS_INT(LockModes, "COMMITTED", NdbOperation::LM_CommittedRead);
226 }
227
228