1 /*
2 Copyright (c) 2003, 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
26 #include <ndb_global.h>
27 #include <NdbOut.hpp>
28 #include <NdbRecAttr.hpp>
29 #include <NdbBlob.hpp>
30 #include "NdbDictionaryImpl.hpp"
31 #include <NdbTCP.h>
32
NdbRecAttr(Ndb *)33 NdbRecAttr::NdbRecAttr(Ndb*)
34 {
35 theStorageX = 0;
36 init();
37 }
38
~NdbRecAttr()39 NdbRecAttr::~NdbRecAttr()
40 {
41 release();
42 }
43
44 int
setup(const class NdbDictionary::Column * col,char * aValue)45 NdbRecAttr::setup(const class NdbDictionary::Column* col, char* aValue)
46 {
47 return setup(&(col->m_impl), aValue);
48 }
49
50 int
setup(const NdbColumnImpl * anAttrInfo,char * aValue)51 NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue)
52 {
53 Uint32 tAttrSize = anAttrInfo->m_attrSize;
54 Uint32 tArraySize = anAttrInfo->m_arraySize;
55 Uint32 tAttrByteSize = tAttrSize * tArraySize;
56
57 m_column = anAttrInfo;
58
59 theAttrId = anAttrInfo->m_attrId;
60 m_size_in_bytes = tAttrByteSize;
61
62 return setup(tAttrByteSize, aValue);
63 }
64
65 int
setup(Uint32 byteSize,char * aValue)66 NdbRecAttr::setup(Uint32 byteSize, char* aValue)
67 {
68 theValue = aValue;
69 m_getVarValue = NULL; // set in getVarValue() only
70
71 if (theStorageX)
72 delete[] theStorageX;
73 theStorageX = NULL; // "safety first"
74
75 // check alignment to signal data
76 // a future version could check alignment per data type as well
77
78 if (aValue != NULL && (UintPtr(aValue)&3) == 0 && (byteSize&3) == 0) {
79 theRef = aValue;
80 return 0;
81 }
82
83 if (byteSize <= 32) {
84 theStorage[0] = 0;
85 theStorage[1] = 0;
86 theStorage[2] = 0;
87 theStorage[3] = 0;
88 theRef = theStorage;
89 return 0;
90 }
91 Uint32 tSize = (byteSize + 7) >> 3;
92 Uint64* tRef = new Uint64[tSize];
93 if (tRef != NULL) {
94 for (Uint32 i = 0; i < tSize; i++) {
95 tRef[i] = 0;
96 }
97 theStorageX = tRef;
98 theRef = tRef;
99 return 0;
100 }
101 errno= ENOMEM;
102 return -1;
103 }
104
105
106 void
copyout()107 NdbRecAttr::copyout()
108 {
109 char* tRef = (char*)theRef;
110 char* tValue = theValue;
111 if (tRef != tValue && tRef != NULL && tValue != NULL) {
112 Uint32 n = m_size_in_bytes;
113 while (n-- > 0) {
114 *tValue++ = *tRef++;
115 }
116 }
117 }
118
119 NdbRecAttr *
clone() const120 NdbRecAttr::clone() const {
121 NdbRecAttr * ret = new NdbRecAttr(0);
122 if (ret == NULL)
123 {
124 errno = ENOMEM;
125 return NULL;
126 }
127 ret->theAttrId = theAttrId;
128 ret->m_size_in_bytes = m_size_in_bytes;
129 ret->m_column = m_column;
130
131 Uint32 n = m_size_in_bytes;
132 if(n <= 32){
133 ret->theRef = (char*)&ret->theStorage[0];
134 ret->theStorageX = 0;
135 ret->theValue = 0;
136 } else {
137 ret->theStorageX = new Uint64[((n + 7) >> 3)];
138 if (ret->theStorageX == NULL)
139 {
140 delete ret;
141 errno = ENOMEM;
142 return NULL;
143 }
144 ret->theRef = (char*)ret->theStorageX;
145 ret->theValue = 0;
146 }
147 memcpy(ret->theRef, theRef, n);
148 return ret;
149 }
150
151 bool
receive_data(const Uint32 * data32,Uint32 sz)152 NdbRecAttr::receive_data(const Uint32 * data32, Uint32 sz)
153 {
154 const unsigned char* data = (const unsigned char*)data32;
155 if(sz)
156 {
157 if (unlikely(m_getVarValue != NULL)) {
158 // ONLY for blob V2 implementation
159 assert(m_column->getType() == NdbDictionary::Column::Longvarchar ||
160 m_column->getType() == NdbDictionary::Column::Longvarbinary);
161 assert(sz >= 2);
162 Uint32 len = data[0] + (data[1] << 8);
163 assert(len == sz - 2);
164 assert(len < (1 << 16));
165 *m_getVarValue = len;
166 data += 2;
167 sz -= 2;
168 }
169 if(!copyoutRequired())
170 memcpy(theRef, data, sz);
171 else
172 memcpy(theValue, data, sz);
173 m_size_in_bytes= sz;
174 return true;
175 }
176 else
177 {
178 return setNULL();
179 }
180 return false;
181 }
182
183 static const NdbRecordPrintFormat default_print_format;
184
185 NdbOut&
ndbrecattr_print_formatted(NdbOut & out,const NdbRecAttr & r,const NdbRecordPrintFormat & f)186 ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r,
187 const NdbRecordPrintFormat &f)
188 {
189 return NdbDictionary::printFormattedValue(out,
190 f,
191 r.getColumn(),
192 r.isNULL()==0 ? r.aRef() : 0);
193 }
194
operator <<(NdbOut & out,const NdbRecAttr & r)195 NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
196 {
197 return ndbrecattr_print_formatted(out, r, default_print_format);
198 }
199
200 Int64
int64_value() const201 NdbRecAttr::int64_value() const
202 {
203 Int64 val;
204 memcpy(&val,theRef,8);
205 return val;
206 }
207
208 Uint64
u_64_value() const209 NdbRecAttr::u_64_value() const
210 {
211 Uint64 val;
212 memcpy(&val,theRef,8);
213 return val;
214 }
215
216 float
float_value() const217 NdbRecAttr::float_value() const
218 {
219 float val;
220 memcpy(&val,theRef,sizeof(val));
221 return val;
222 }
223
224 double
double_value() const225 NdbRecAttr::double_value() const
226 {
227 double val;
228 memcpy(&val,theRef,sizeof(val));
229 return val;
230 }
231
232 Int32
medium_value() const233 NdbRecAttr::medium_value() const
234 {
235 return sint3korr((unsigned char *)theRef);
236 }
237
238 Uint32
u_medium_value() const239 NdbRecAttr::u_medium_value() const
240 {
241 return uint3korr((unsigned char*)theRef);
242 }
243