1 /*
2    Copyright (c) 2007, 2014, 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 #ifndef NdbRecord_H
26 #define NdbRecord_H
27 
28 class NdbRecord {
29 public:
30   /* Flag bits for the entire NdbRecord. */
31   enum RecFlags
32   {
33     /*
34       This flag tells whether this NdbRecord is a PK record for the table,
35       ie. that it describes _exactly_ the primary key attributes, no more and
36       no less.
37     */
38     RecIsKeyRecord= 0x1,
39 
40     /*
41       This flag tells whether this NdbRecord includes _at least_ all PK columns
42       (and possibly other columns). This is a requirement for many key-based
43       operations.
44     */
45     RecHasAllKeys= 0x2,
46 
47     /* This NdbRecord is for an ordered index, not a table. */
48     RecIsIndex= 0x4,
49 
50     /* This NdbRecord has at least one blob. */
51     RecHasBlob= 0x8,
52 
53     /*
54       The table has at least one blob (though the NdbRecord may not include
55       it). This is needed so that deleteTuple() can know to delete all blob
56       parts.
57     */
58     RecTableHasBlob= 0x10,
59 
60     /* This NdbRecord is a default NdbRecord */
61     RecIsDefaultRec= 0x20
62 
63     /* The table has user defined partitioning */
64     ,RecHasUserDefinedPartitioning = 0x40
65   };
66 
67   /* Flag bits for individual columns in the NdbRecord. */
68   enum ColFlags
69   {
70     /*
71       This flag tells whether the column is part of the primary key, used
72       for insert.
73     */
74     IsKey=   0x1,
75     /* This flag is true if column is disk based. */
76     IsDisk= 0x2,
77     /* True if column can be NULL and has a NULL bit. */
78     IsNullable= 0x04,
79     /*
80       Flags for determining the actual length of data (which for varsize
81       columns is different from the maximum size.
82       The flags are mutually exclusive.
83     */
84     IsVar1ByteLen= 0x08,
85     IsVar2ByteLen= 0x10,
86     /* Flag for column that is a part of the distribution key. */
87     IsDistributionKey= 0x20,
88     /* Flag for blob columns. */
89     IsBlob= 0x40,
90     /*
91        Flag for special handling of short varchar for index keys, which is
92        used by mysqld to avoid converting index key rows.
93     */
94     IsMysqldShrinkVarchar= 0x80,
95     /* Bitfield stored in the internal mysqld format. */
96     IsMysqldBitfield= 0x100,
97     /*
98       Bit field maps only null bits.
99       No overflow bits.
100       Used only with IsMysqldBitfield.
101     */
102     BitFieldMapsNullBitOnly= 0x200
103   };
104 
105   struct Attr
106   {
107     Uint32 attrId;
108 
109     /* Character set information, for ordered index merge sort. */
110     CHARSET_INFO *charset_info;
111     /* Function used to compare attributes during merge sort. */
112     NdbSqlUtil::Cmp *compare_function;
113 
114     void *unused; /* Make it 64 bytes large */
115 
116     Uint32 column_no;
117     /*
118       The index_attrId member is the attribute id in the index table object,
119       which is used to specify ordered index bounds in KEYINFO signal.
120       Note that this is different from the normal attribute id in the main
121       table, unless the ordered index is on columns (0..N).
122     */
123     Uint32 index_attrId;
124     /*
125       Maximum size of the attribute. This is duplicated here to avoid having
126       to dig into Table object for every attribute fetch/store.
127     */
128     Uint32 maxSize;
129     /* Number of bits in a bitfield. */
130     Uint32 bitCount;
131 
132     /* NULL bit location (only for nullable columns, ie. flags&IsNullable). */
133     Uint32 nullbit_byte_offset;
134     Uint32 nullbit_bit_in_byte;
135 
136     /* Offset of data from the start of a row. */
137     Uint32 offset;
138 
139     /* Flags, or-ed from enum ColFlags. */
140     Uint32 flags;
141 
142     /*
143       Alignment information for the attribute, duplicated from column info
144     */
145     Uint32 orgAttrSize;
146 
get_var_lengthNdbRecord::Attr147     bool get_var_length(const char *row, Uint32& len) const
148     {
149       if (flags & IsVar1ByteLen)
150         len= 1 + *((Uint8*)(row+offset));
151       else if (flags & IsVar2ByteLen)
152         len= 2 + uint2korr(row+offset);
153       else
154         len= maxSize;
155       return len <= maxSize;
156     }
is_nullNdbRecord::Attr157     bool is_null(const char *row) const
158     {
159       return (flags & IsNullable) &&
160              (row[nullbit_byte_offset] & (1 << nullbit_bit_in_byte));
161     }
162 
163     /* 255 bytes of data and 1 byte of length */
164     STATIC_CONST( SHRINK_VARCHAR_BUFFSIZE= 256 );
165     /*
166       Mysqld uses a slightly different format for storing varchar in
167       index keys; the length is always two bytes little endian, even
168       for max size < 256.
169       This converts to the usual format expected by NDB kernel.
170     */
shrink_varcharNdbRecord::Attr171     bool shrink_varchar(const char *row, Uint32& out_len, char *buf) const
172     {
173       const char *p= row + offset;
174       Uint32 len= uint2korr(p);
175       if (len >= SHRINK_VARCHAR_BUFFSIZE || len >= maxSize)
176       {
177         out_len = 0;
178         return false;
179       }
180       buf[0]= (unsigned char)len;
181       memcpy(buf+1, p+2, len);
182       out_len= len + 1;
183       return true;
184     }
185     /*
186       Accessing mysqld format bitfields.
187       For internal use in myqsld.
188       In mysqld, fractional bytes of each bit field are stored inside the
189       null bytes area.
190     */
191     void get_mysqld_bitfield(const char *src_row, char *dst_buffer) const;
192     void put_mysqld_bitfield(char *dst_row, const char *src_buffer) const;
193   };
194 
195   /*
196     ToDo: For now we need to hang on to the Table *, since lots of the
197     existing code (class NdbOperation*, class NdbScanFilter) depends
198     on having access to it.
199     Long-term, we want to eliminate it (instead relying only on copying
200     tableId, fragmentCount etc. into the NdbRecord.
201   */
202   const NdbTableImpl *table;
203 
204   Uint32 tableId;
205   Uint32 tableVersion;
206   /* Copy of table->m_keyLenInWords. */
207   Uint32 m_keyLenInWords;
208   /**
209    * Number of distribution keys (usually == number of primary keys).
210    *
211    * For an index NdbRecord, this is zero if the index does not include all
212    * of the distribution keys in the table.
213    */
214   Uint32 m_no_of_distribution_keys;
215   /*
216     Array of index (into columns[]) of primary key columns, in order.
217     Physical storage for these is after columns[] array.
218     This array is only fully initialised if flags&RecHasAllKeys.
219   */
220   const Uint32 *key_indexes;
221   /* Length of key_indexes array. */
222   Uint32 key_index_length;
223 
224   /* Length of distkey_indexes array. */
225   Uint32 distkey_index_length;
226   /*
227     Array of index (into columns[]) of distribution keys, in attrId order.
228     This is used to build the distribution key, which is the concatenation
229     of key values in attrId order.
230 
231     If the index does not include all of the base table's distribution keys,
232     this array is empty (zero length).
233   */
234   const Uint32 *distkey_indexes;
235 
236   /*
237     m_min_distkey_prefix_length is the minimum lenght of an index prefix
238     needed to include all distribution keys. In other words, it is one more
239     that the index of the last distribution key in the index order.
240 
241     This member only makes sense for an index NdbRecord.
242   */
243   Uint32 m_min_distkey_prefix_length;
244 
245   /* Size of array pointed to by m_attrId_indexes. */
246   Uint32 m_attrId_indexes_length;
247   /* The real size of the array at the end of this struct. */
248   Uint32 noOfColumns;
249   /* Flags, or-ed from enum RecFlags. */
250   Uint32 flags;
251   /**
252    * Array mapping an attribute Id into the corresponding index into the
253    * columns[] array, useful for looking up a column by attribute id.
254    *
255    * If the column is not included in the NdbRecord, the value is -1.
256    */
257   const int *m_attrId_indexes;
258 
259   /* Size of row (really end of right-most defined attribute in row). */
260   Uint32 m_row_size;
261 
262   struct Attr columns[1];
263 
264   /* Copy a user-supplied mask to internal mask. */
265   void copyMask(Uint32 *dst, const unsigned char *src) const;
266 
267   /* Clear internal mask. */
clearMask(Uint32 * dst) const268   void clearMask(Uint32 *dst) const
269   {
270     BitmaskImpl::clear((NDB_MAX_ATTRIBUTES_IN_TABLE+31)>>5, dst);
271   }
272 };
273 
274 #endif
275