1
2 /*
3 Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation. The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License, version 2.0, for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #include "my_config.h"
27
28 #include "Operation.h"
29 #include "TabSeparatedValues.h"
30
31
32 /*
33 Class Operation originated as a header-only class and formed a bridge
34 between the "high-level" application code in ndb_worker.cc and the
35 low-level details of using the NDB API.
36
37 This proved difficult to debug. On many platforms, gdb's support for
38 inlined functions from header-only classes is poor.
39
40 A few methods are always compiled here.
41 */
42
43
Operation(QueryPlan * p,int o,char * kbuf)44 Operation::Operation(QueryPlan *p, int o, char *kbuf) : key_buffer(kbuf),
45 plan(p),
46 op(o)
47 {
48 set_default_record();
49 }
50
Operation(workitem * i,Uint32 mask)51 Operation::Operation(workitem *i, Uint32 mask) : key_buffer(i->ndb_key_buffer),
52 plan(i->plan),
53 op(i->base.verb)
54 {
55 set_default_record();
56 if(mask) {
57 row_mask[0] = mask & 0x000000FF;
58 row_mask[1] = mask & 0x0000FF00;
59 row_mask[2] = mask & 0x00FF0000;
60 row_mask[3] = mask & 0xFF000000;
61 }
62 }
63
Operation(QueryPlan * p,char * buf)64 Operation::Operation(QueryPlan *p, char * buf) : buffer(buf),
65 plan(p),
66 op(OP_READ)
67 {
68 set_default_record();
69 }
70
71
set_default_record()72 void Operation::set_default_record() {
73 row_mask[3] = row_mask[2] = row_mask[1] = row_mask[0] = 0;
74 key_mask[3] = key_mask[2] = key_mask[1] = key_mask[0] = 0;
75 read_mask_ptr = 0;
76
77 if(op == OP_READ) record = plan->val_record;
78 else if(op == OP_FLUSH) record = plan->key_record; // scanning delete
79 else record = plan->row_record;
80 }
81
82
83 /* Methods for reading columns from the response */
84
85
getStringValueNoCopy(int idx,char ** dstptr,size_t * lenptr) const86 bool Operation::getStringValueNoCopy(int idx, char **dstptr,
87 size_t *lenptr) const {
88 if(record->isNull(idx, buffer)) {
89 *dstptr = 0;
90 *lenptr = 0;
91 return true;
92 }
93 return record->decodeNoCopy(idx, dstptr, lenptr, buffer);
94 }
95
96
copyValue(int idx,char * dest) const97 size_t Operation::copyValue(int idx, char *dest) const {
98 if(record->isNull(idx, buffer)) {
99 *dest = 0;
100 return 0;
101 }
102 return record->decodeCopy(idx, dest, buffer);
103 }
104
105
106 /* NdbTransaction method wrappers */
107
startTransaction(Ndb * db) const108 NdbTransaction * Operation::startTransaction(Ndb *db) const {
109 char hash_buffer[512];
110 return db->startTransaction(plan->key_record->ndb_record, key_buffer,
111 hash_buffer, 512);
112 }
113
scanIndex(NdbTransaction * tx,NdbIndexScanOperation::IndexBound * bound)114 NdbIndexScanOperation * Operation::scanIndex(NdbTransaction *tx,
115 NdbIndexScanOperation::IndexBound *bound) {
116 /* MUST BE ORDERED ASC; used by configuration to read key_prefixes */
117 NdbScanOperation::ScanOptions opts;
118 opts.optionsPresent = NdbScanOperation::ScanOptions::SO_SCANFLAGS;
119 opts.scan_flags = NdbScanOperation::SF_OrderBy;
120
121 return tx->scanIndex(plan->key_record->ndb_record, // scan key
122 plan->row_record->ndb_record, // row record
123 NdbOperation::LM_Read, // lock mode
124 (const unsigned char*) 0, // result mask
125 bound, // bound
126 & opts,
127 sizeof(opts));
128 }
129
130
setKey(int nparts,const char * dbkey,size_t key_len)131 bool Operation::setKey(int nparts, const char *dbkey, size_t key_len ) {
132 bool r = true;
133
134 clearKeyNullBits();
135 if(nparts > 1) {
136 TabSeparatedValues tsv(dbkey, nparts, key_len);
137 int idx = 0;
138 do {
139 if(tsv.getLength()) {
140 DEBUG_PRINT("Set key part %d [%.*s]", idx, tsv.getLength(), tsv.getPointer());
141 if(! setKeyPart(COL_STORE_KEY+idx, tsv.getPointer(), tsv.getLength()))
142 return false;
143 }
144 else {
145 DEBUG_PRINT("Set key part NULL: %d ", idx);
146 setKeyPartNull(COL_STORE_KEY+idx);
147 }
148 idx++;
149 } while (tsv.advance());
150 }
151 else {
152 r = setKeyPart(COL_STORE_KEY, dbkey, key_len);
153 }
154 return r;
155 }
156
157
setFieldsInRow(int offset,const char * desc,int nparts,const char * val,size_t len)158 bool Operation::setFieldsInRow(int offset, const char * desc,
159 int nparts, const char *val, size_t len ) {
160 bool r = true;
161
162 if(nparts > 1) {
163 TabSeparatedValues tsv(val, nparts, len);
164 int idx = 0;
165 do {
166 if(tsv.getLength()) {
167 DEBUG_PRINT("Set %s part %d [%.*s]", desc, idx, tsv.getLength(), tsv.getPointer());
168 if(! setColumn(offset+idx, tsv.getPointer(), tsv.getLength()))
169 return false;
170 }
171 else {
172 DEBUG_PRINT("Set %s part NULL: %d ", desc, idx);
173 setColumnNull(offset+idx);
174 }
175 idx++;
176 } while (tsv.advance());
177 }
178 else {
179 r = setColumn(offset, val, len);
180 }
181 return r;
182 }
183
184
185