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