1 /* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 #include "sql/create_field.h"
24
25 #include "sql/derror.h"
26 #include "sql/field.h"
27 #include "sql/item.h"
28 #include "sql/my_decimal.h"
29 #include "sql/sql_class.h"
30 #include "sql_string.h"
31 #include "template_utils.h"
32
33 #include <cmath>
34
35 // Definition of static constexpr data members in Create_field.
36 constexpr size_t Create_field::TINYBLOB_MAX_SIZE_IN_BYTES;
37 constexpr size_t Create_field::BLOB_MAX_SIZE_IN_BYTES;
38 constexpr size_t Create_field::MEDIUMBLOB_MAX_SIZE_IN_BYTES;
39 constexpr size_t Create_field::LONGBLOB_MAX_SIZE_IN_BYTES;
40
41 /**
42 Constructs a column definition from an object representing an actual
43 column. This is a reverse-engineering procedure that creates a column
44 definition object as produced by the parser (Create_field) from a resolved
45 column object (Field).
46
47 @param old_field The column object from which the column definition is
48 constructed.
49 @param orig_field Used for copying default values. This parameter may be
50 NULL, but if present it is used for copying default
51 values.
52
53 Default values are copied into an Item_string unless:
54 - The default value is a function.
55 - There is no default value.
56 - old_field is a BLOB column.
57 - old_field has its data pointer improperly initialized.
58 */
Create_field(Field * old_field,Field * orig_field)59 Create_field::Create_field(Field *old_field, Field *orig_field)
60 : hidden(old_field->hidden()),
61 field_name(old_field->field_name),
62 change(nullptr),
63 comment(old_field->comment),
64 sql_type(old_field->real_type()),
65 decimals(old_field->decimals()),
66 flags(old_field->all_flags()),
67 auto_flags(old_field->auto_flags),
68 charset(old_field->charset()), // May be NULL ptr
69 is_explicit_collation(false),
70 geom_type(Field::GEOM_GEOMETRY),
71 field(old_field),
72 is_nullable(old_field->is_nullable()),
73 is_zerofill(false), // Init to avoid UBSAN warnings
74 is_unsigned(false), // Init to avoid UBSAN warnings
75 treat_bit_as_char(
76 false), // Init to avoid valgrind warnings in opt. build
77 pack_length_override(0),
78 gcol_info(old_field->gcol_info),
79 stored_in_db(old_field->stored_in_db),
80 m_default_val_expr(old_field->m_default_val_expr),
81 is_array(old_field->is_array()),
82 m_engine_attribute(old_field->m_engine_attribute),
83 m_secondary_engine_attribute(old_field->m_secondary_engine_attribute),
84 m_max_display_width_in_codepoints(old_field->char_length()) {
85 switch (sql_type) {
86 case MYSQL_TYPE_TINY_BLOB:
87 case MYSQL_TYPE_MEDIUM_BLOB:
88 case MYSQL_TYPE_LONG_BLOB:
89 case MYSQL_TYPE_BLOB:
90 sql_type = blob_type_from_pack_length(old_field->pack_length() -
91 portable_sizeof_char_ptr);
92 break;
93 case MYSQL_TYPE_STRING:
94 /* Change CHAR -> VARCHAR if dynamic record length */
95 if (old_field->type() == MYSQL_TYPE_VAR_STRING)
96 sql_type = MYSQL_TYPE_VARCHAR;
97 break;
98 case MYSQL_TYPE_GEOMETRY: {
99 const Field_geom *field_geom = down_cast<const Field_geom *>(old_field);
100 geom_type = field_geom->geom_type;
101 m_srid = field_geom->get_srid();
102 break;
103 }
104 case MYSQL_TYPE_YEAR:
105 m_max_display_width_in_codepoints = 4; // set default value
106 break;
107 default:
108 break;
109 }
110
111 if (flags & (ENUM_FLAG | SET_FLAG))
112 interval = down_cast<Field_enum *>(old_field)->typelib;
113 else
114 interval = nullptr;
115 constant_default = nullptr;
116
117 /*
118 Copy the default (constant/function) from the column object orig_field, if
119 supplied. We do this if all these conditions are met:
120
121 - The column allows a default.
122
123 - The column type is not a BLOB type.
124
125 - The original column (old_field) was properly initialized with a record
126 buffer pointer.
127 */
128 if (!(flags & (NO_DEFAULT_VALUE_FLAG | BLOB_FLAG)) &&
129 old_field->field_ptr() != nullptr && orig_field != nullptr) {
130 bool default_now = false;
131 if (real_type_with_now_as_default(sql_type)) {
132 // The SQL type of the new field allows a function default:
133 default_now = orig_field->has_insert_default_datetime_value_expression();
134 auto_flags = default_now ? Field::DEFAULT_NOW : Field::NONE;
135 if (orig_field->has_update_default_datetime_value_expression())
136 auto_flags |= Field::ON_UPDATE_NOW;
137 if (orig_field->has_insert_default_general_value_expression())
138 auto_flags |= Field::GENERATED_FROM_EXPRESSION;
139 }
140 if (!default_now) // Give a constant default
141 {
142 /* Get the value from default_values */
143 ptrdiff_t diff = orig_field->table->default_values_offset();
144 orig_field->move_field_offset(diff); // Points now at default_values
145 if (!orig_field->is_real_null()) {
146 StringBuffer<MAX_FIELD_WIDTH> tmp(charset);
147 String *res = orig_field->val_str(&tmp);
148 char *pos = sql_strmake(res->ptr(), res->length());
149 constant_default = new Item_string(pos, res->length(), charset);
150 }
151 orig_field->move_field_offset(-diff); // Back to record[0]
152 }
153 }
154 }
155
156 /**
157 Initialize a column definition object. Column definition objects can be used
158 to construct Field objects.
159
160 @param thd Session/Thread handle.
161 @param fld_name Column name.
162 @param fld_type Column type.
163 @param display_width_in_codepoints The column display width, counted in
164 number of code points.
165 @param fld_decimals Number of digits to the right of the decimal
166 point (if any.)
167 @param fld_type_modifier Additional type information.
168 @param fld_default_value Column default constant or datetime expression
169 (if any.)
170 @param fld_on_update_value The expression in the ON UPDATE clause.
171 @param fld_comment Column comment.
172 @param fld_change Column change.
173 @param fld_interval_list Interval list (if any.)
174 @param fld_charset Column charset.
175 @param has_explicit_collation Column has an explicit COLLATE attribute.
176 @param fld_geom_type Column geometry type (if any.)
177 @param fld_gcol_info Generated column data
178 @param fld_default_val_expr The expression for generating default values
179 @param srid The SRID specification. This might be null
180 (has_value() may return false).
181 @param hidden Whether this column should be hidden or not.
182 @param is_array_arg Whether the field is a typed array
183
184 @retval
185 false on success.
186 @retval
187 true on error.
188 */
189
init(THD * thd,const char * fld_name,enum_field_types fld_type,const char * display_width_in_codepoints,const char * fld_decimals,uint fld_type_modifier,Item * fld_default_value,Item * fld_on_update_value,const LEX_CSTRING * fld_comment,const char * fld_change,List<String> * fld_interval_list,const CHARSET_INFO * fld_charset,bool has_explicit_collation,uint fld_geom_type,Value_generator * fld_gcol_info,Value_generator * fld_default_val_expr,Nullable<gis::srid_t> srid,dd::Column::enum_hidden_type hidden,bool is_array_arg)190 bool Create_field::init(
191 THD *thd, const char *fld_name, enum_field_types fld_type,
192 const char *display_width_in_codepoints, const char *fld_decimals,
193 uint fld_type_modifier, Item *fld_default_value, Item *fld_on_update_value,
194 const LEX_CSTRING *fld_comment, const char *fld_change,
195 List<String> *fld_interval_list, const CHARSET_INFO *fld_charset,
196 bool has_explicit_collation, uint fld_geom_type,
197 Value_generator *fld_gcol_info, Value_generator *fld_default_val_expr,
198 Nullable<gis::srid_t> srid, dd::Column::enum_hidden_type hidden,
199 bool is_array_arg) {
200 uint sign_len, allowed_type_modifier = 0;
201 ulong max_field_charlength = MAX_FIELD_CHARLENGTH;
202
203 DBUG_TRACE;
204
205 DBUG_ASSERT(!(has_explicit_collation && fld_charset == nullptr));
206
207 field = nullptr;
208 field_name = fld_name;
209 flags = fld_type_modifier;
210 is_explicit_collation = (fld_charset != nullptr);
211
212 if (!has_explicit_collation && fld_charset == &my_charset_utf8mb4_0900_ai_ci)
213 charset = thd->variables.default_collation_for_utf8mb4;
214 else
215 charset = fld_charset;
216
217 auto_flags = Field::NONE;
218 is_nullable = !(fld_type_modifier & NOT_NULL_FLAG);
219 this->hidden = hidden;
220 is_array = is_array_arg;
221
222 if (fld_default_value != nullptr &&
223 fld_default_value->type() == Item::FUNC_ITEM) {
224 // We have a function default for insertions.
225 constant_default = nullptr;
226 auto_flags |= Field::DEFAULT_NOW;
227 } else {
228 // No function default for insertions. Either NULL or a constant.
229 constant_default = fld_default_value;
230 }
231
232 // ON UPDATE CURRENT_TIMESTAMP
233 if (fld_on_update_value != nullptr &&
234 fld_on_update_value->type() == Item::FUNC_ITEM)
235 auto_flags |= Field::ON_UPDATE_NOW;
236
237 // Automatic increment.
238 if (fld_type_modifier & AUTO_INCREMENT_FLAG) auto_flags |= Field::NEXT_NUMBER;
239
240 decimals = fld_decimals ? (uint)atoi(fld_decimals) : 0;
241 if (is_temporal_real_type(fld_type)) {
242 flags |= BINARY_FLAG;
243 charset = &my_charset_numeric;
244 if (decimals > DATETIME_MAX_DECIMALS) {
245 my_error(ER_TOO_BIG_PRECISION, MYF(0), decimals, fld_name,
246 DATETIME_MAX_DECIMALS);
247 return true;
248 }
249 } else if (decimals >= DECIMAL_NOT_SPECIFIED) {
250 my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
251 static_cast<ulong>(DECIMAL_NOT_SPECIFIED - 1));
252 return true;
253 }
254
255 sql_type = fld_type;
256 change = fld_change;
257 interval = nullptr;
258 geom_type = static_cast<Field::geometry_type>(fld_geom_type);
259 interval_list.empty();
260
261 comment = *fld_comment;
262 gcol_info = fld_gcol_info;
263 stored_in_db = true;
264 m_srid = srid;
265
266 if (fld_default_val_expr) {
267 constant_default = nullptr;
268 auto_flags |= Field::GENERATED_FROM_EXPRESSION;
269 m_default_val_expr = fld_default_val_expr;
270 }
271
272 // Initialize data for a virtual field or default value expression
273 if (gcol_info || m_default_val_expr) {
274 if (gcol_info) {
275 DBUG_ASSERT(gcol_info->expr_item);
276 stored_in_db = gcol_info->get_field_stored();
277
278 /*
279 Make a field created for the real type.
280 Note that "real" and generated fields differ from each other
281 only by Field::gcol_info, which is always 0 for normal columns.
282 gcol_info is updated for fields later in procedure open_binary_frm.
283 */
284 sql_type = fld_type = gcol_info->get_real_type();
285 if (pre_validate_value_generator_expr(gcol_info->expr_item, field_name,
286 VGS_GENERATED_COLUMN))
287 return true;
288 } else {
289 if (pre_validate_value_generator_expr(m_default_val_expr->expr_item,
290 field_name, VGS_DEFAULT_EXPRESSION))
291 return true;
292 }
293 }
294
295 /*
296 Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value
297 or an expression to generate the default value and
298 it is NOT NULL and not an AUTO_INCREMENT field.
299 */
300 if (!fld_default_value && !fld_default_val_expr &&
301 (fld_type_modifier & NOT_NULL_FLAG) &&
302 !(fld_type_modifier & AUTO_INCREMENT_FLAG)) {
303 /*
304 TIMESTAMP columns get implicit DEFAULT value when
305 explicit_defaults_for_timestamp is not set.
306 */
307 if (thd->variables.explicit_defaults_for_timestamp ||
308 !is_timestamp_type(fld_type)) {
309 flags |= NO_DEFAULT_VALUE_FLAG;
310 }
311 }
312
313 if (display_width_in_codepoints != nullptr) {
314 errno = 0;
315 const ulonglong ull_length =
316 my_strtoull(display_width_in_codepoints, nullptr, 10);
317 if ((errno != 0) || (ull_length > MAX_FIELD_BLOBLENGTH)) {
318 my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), fld_name, MAX_FIELD_BLOBLENGTH);
319 return true;
320 }
321 m_max_display_width_in_codepoints = static_cast<size_t>(ull_length);
322 m_explicit_display_width = true;
323
324 if (m_max_display_width_in_codepoints == 0)
325 display_width_in_codepoints = nullptr; /* purecov: inspected */
326 }
327
328 sign_len = fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
329
330 switch (fld_type) {
331 case MYSQL_TYPE_TINY:
332 if (!display_width_in_codepoints)
333 m_max_display_width_in_codepoints = MAX_TINYINT_WIDTH + sign_len;
334 allowed_type_modifier = AUTO_INCREMENT_FLAG;
335 break;
336 case MYSQL_TYPE_SHORT:
337 if (!display_width_in_codepoints)
338 m_max_display_width_in_codepoints = MAX_SMALLINT_WIDTH + sign_len;
339 allowed_type_modifier = AUTO_INCREMENT_FLAG;
340 break;
341 case MYSQL_TYPE_INT24:
342 if (!display_width_in_codepoints)
343 m_max_display_width_in_codepoints = MAX_MEDIUMINT_WIDTH + sign_len;
344 allowed_type_modifier = AUTO_INCREMENT_FLAG;
345 break;
346 case MYSQL_TYPE_LONG:
347 if (!display_width_in_codepoints)
348 m_max_display_width_in_codepoints = MAX_INT_WIDTH + sign_len;
349 allowed_type_modifier = AUTO_INCREMENT_FLAG;
350 break;
351 case MYSQL_TYPE_LONGLONG:
352 if (!display_width_in_codepoints)
353 m_max_display_width_in_codepoints = MAX_BIGINT_WIDTH;
354 allowed_type_modifier = AUTO_INCREMENT_FLAG;
355 break;
356 case MYSQL_TYPE_NULL:
357 break;
358 case MYSQL_TYPE_NEWDECIMAL: {
359 ulong precision = static_cast<ulong>(m_max_display_width_in_codepoints);
360 my_decimal_trim(&precision, &decimals);
361 m_max_display_width_in_codepoints = precision;
362 }
363 if (m_max_display_width_in_codepoints > DECIMAL_MAX_PRECISION) {
364 my_error(ER_TOO_BIG_PRECISION, MYF(0),
365 static_cast<int>(m_max_display_width_in_codepoints), fld_name,
366 static_cast<ulong>(DECIMAL_MAX_PRECISION));
367 return true;
368 }
369 if (m_max_display_width_in_codepoints < decimals) {
370 my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
371 return true;
372 }
373 m_max_display_width_in_codepoints = my_decimal_precision_to_length(
374 m_max_display_width_in_codepoints, decimals,
375 fld_type_modifier & UNSIGNED_FLAG);
376 break;
377 case MYSQL_TYPE_VARCHAR:
378 // Note that VARCHAR fields with a long length may be converted to blob
379 // types in prepare_blob_field()
380 max_field_charlength = MAX_FIELD_VARCHARLENGTH;
381 break;
382 case MYSQL_TYPE_STRING:
383 break;
384 case MYSQL_TYPE_BLOB:
385 case MYSQL_TYPE_TINY_BLOB:
386 case MYSQL_TYPE_LONG_BLOB:
387 case MYSQL_TYPE_MEDIUM_BLOB:
388 case MYSQL_TYPE_JSON:
389 if (fld_default_value) {
390 /* Allow empty as default value. */
391 String str, *res;
392 res = fld_default_value->val_str(&str);
393 /*
394 A default other than '' is always an error, and any non-NULL
395 specified default is an error in strict mode.
396 */
397 if (res->length() || thd->is_strict_mode()) {
398 my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0),
399 fld_name); /* purecov: inspected */
400 return true;
401 } else {
402 /*
403 Otherwise a default of '' is just a warning.
404 */
405 push_warning_printf(thd, Sql_condition::SL_WARNING,
406 ER_BLOB_CANT_HAVE_DEFAULT,
407 ER_THD(thd, ER_BLOB_CANT_HAVE_DEFAULT), fld_name);
408 }
409 constant_default = nullptr;
410 }
411
412 flags |= BLOB_FLAG;
413 break;
414 case MYSQL_TYPE_GEOMETRY:
415 if (fld_default_value) {
416 my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), fld_name);
417 return true;
418 }
419 flags |= BLOB_FLAG;
420 break;
421 case MYSQL_TYPE_YEAR:
422 if (!display_width_in_codepoints ||
423 m_max_display_width_in_codepoints != 4)
424 m_max_display_width_in_codepoints = 4; /* Default length */
425 flags |= ZEROFILL_FLAG | UNSIGNED_FLAG;
426 break;
427 case MYSQL_TYPE_FLOAT:
428 /* change FLOAT(precision) to FLOAT or DOUBLE */
429 allowed_type_modifier = AUTO_INCREMENT_FLAG;
430 if (display_width_in_codepoints && !fld_decimals) {
431 size_t tmp_length = m_max_display_width_in_codepoints;
432 if (tmp_length > PRECISION_FOR_DOUBLE) {
433 my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
434 return true;
435 } else if (tmp_length > PRECISION_FOR_FLOAT) {
436 sql_type = MYSQL_TYPE_DOUBLE;
437 m_max_display_width_in_codepoints = MAX_DOUBLE_STR_LENGTH;
438 } else
439 m_max_display_width_in_codepoints = MAX_FLOAT_STR_LENGTH;
440 decimals = DECIMAL_NOT_SPECIFIED;
441 break;
442 }
443 if (!display_width_in_codepoints && !fld_decimals) {
444 m_max_display_width_in_codepoints = MAX_FLOAT_STR_LENGTH;
445 decimals = DECIMAL_NOT_SPECIFIED;
446 }
447 if (m_max_display_width_in_codepoints < decimals &&
448 decimals != DECIMAL_NOT_SPECIFIED) {
449 my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
450 return true;
451 }
452 break;
453 case MYSQL_TYPE_DOUBLE:
454 allowed_type_modifier = AUTO_INCREMENT_FLAG;
455 if (!display_width_in_codepoints && !fld_decimals) {
456 m_max_display_width_in_codepoints = DBL_DIG + 7;
457 decimals = DECIMAL_NOT_SPECIFIED;
458 }
459 if (m_max_display_width_in_codepoints < decimals &&
460 decimals != DECIMAL_NOT_SPECIFIED) {
461 my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
462 return true;
463 }
464 break;
465 case MYSQL_TYPE_TIMESTAMP:
466 /* Add flags for TIMESTAMP for 4.0 MYD and 4.0 InnoDB compatibility */
467 flags |= ZEROFILL_FLAG | UNSIGNED_FLAG;
468 /* Fall through */
469 case MYSQL_TYPE_TIMESTAMP2:
470 if (display_width_in_codepoints == nullptr) {
471 m_max_display_width_in_codepoints =
472 MAX_DATETIME_WIDTH + (decimals ? (1 + decimals) : 0);
473 } else if (m_max_display_width_in_codepoints != MAX_DATETIME_WIDTH) {
474 /*
475 We support only even TIMESTAMP lengths less or equal than 14
476 and 19 as length of 4.1 compatible representation. Silently
477 shrink it to MAX_DATETIME_COMPRESSED_WIDTH.
478 */
479 DBUG_ASSERT(MAX_DATETIME_COMPRESSED_WIDTH < UINT_MAX);
480 if (m_max_display_width_in_codepoints !=
481 UINT_MAX) /* avoid overflow; is safe because of min() */
482 m_max_display_width_in_codepoints =
483 ((m_max_display_width_in_codepoints + 1) / 2) * 2;
484 m_max_display_width_in_codepoints = std::min<size_t>(
485 m_max_display_width_in_codepoints, MAX_DATETIME_COMPRESSED_WIDTH);
486 }
487
488 /*
489 Since we silently rewrite down to MAX_DATETIME_COMPRESSED_WIDTH bytes,
490 the parser should not raise errors unless bizzarely large.
491 */
492 max_field_charlength = UINT_MAX;
493
494 break;
495 case MYSQL_TYPE_DATE:
496 /* Old date type. */
497 sql_type = MYSQL_TYPE_NEWDATE;
498 /* fall through */
499 case MYSQL_TYPE_NEWDATE:
500 m_max_display_width_in_codepoints = MAX_DATE_WIDTH;
501 break;
502 case MYSQL_TYPE_TIME:
503 case MYSQL_TYPE_TIME2:
504 m_max_display_width_in_codepoints =
505 MAX_TIME_WIDTH + (decimals ? (1 + decimals) : 0);
506 break;
507 case MYSQL_TYPE_DATETIME:
508 case MYSQL_TYPE_DATETIME2:
509 m_max_display_width_in_codepoints =
510 MAX_DATETIME_WIDTH + (decimals ? (1 + decimals) : 0);
511 break;
512 case MYSQL_TYPE_SET:
513 case MYSQL_TYPE_ENUM: {
514 for (String &it : *fld_interval_list) {
515 interval_list.push_back(&it);
516 }
517 break;
518 }
519 case MYSQL_TYPE_VAR_STRING:
520 DBUG_ASSERT(0); /* Impossible. */
521 break;
522 case MYSQL_TYPE_BIT: {
523 if (!display_width_in_codepoints) {
524 my_error(ER_INVALID_FIELD_SIZE, MYF(0), fld_name);
525 return true;
526 }
527 if (m_max_display_width_in_codepoints > MAX_BIT_FIELD_LENGTH) {
528 my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), fld_name,
529 static_cast<ulong>(MAX_BIT_FIELD_LENGTH));
530 return true;
531 }
532 break;
533 }
534 case MYSQL_TYPE_DECIMAL:
535 default:
536 DBUG_ASSERT(0); /* Was obsolete */
537 }
538
539 if (!(flags & BLOB_FLAG) &&
540 ((m_max_display_width_in_codepoints > max_field_charlength &&
541 fld_type != MYSQL_TYPE_SET && fld_type != MYSQL_TYPE_ENUM &&
542 (fld_type != MYSQL_TYPE_VARCHAR || fld_default_value)) ||
543 ((m_max_display_width_in_codepoints == 0 && m_explicit_display_width) &&
544 fld_type != MYSQL_TYPE_STRING && fld_type != MYSQL_TYPE_VARCHAR &&
545 fld_type != MYSQL_TYPE_GEOMETRY))) {
546 my_error((fld_type == MYSQL_TYPE_VAR_STRING ||
547 fld_type == MYSQL_TYPE_VARCHAR || fld_type == MYSQL_TYPE_STRING)
548 ? ER_TOO_BIG_FIELDLENGTH
549 : ER_TOO_BIG_DISPLAYWIDTH,
550 MYF(0), fld_name, max_field_charlength); /* purecov: inspected */
551 return true;
552 }
553 fld_type_modifier &= AUTO_INCREMENT_FLAG;
554 if ((~allowed_type_modifier) & fld_type_modifier) {
555 my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
556 return true;
557 }
558
559 /*
560 After all checks were carried out we should be able guarantee that column
561 can't have AUTO_INCREMENT and DEFAULT/ON UPDATE CURRENT_TIMESTAMP at the
562 same time.
563 */
564 DBUG_ASSERT(!((auto_flags & (Field::DEFAULT_NOW | Field::ON_UPDATE_NOW |
565 Field::GENERATED_FROM_EXPRESSION)) != 0 &&
566 (auto_flags & Field::NEXT_NUMBER) != 0));
567
568 return false; /* success */
569 }
570
571 /**
572 Init for a tmp table field. To be extended if need be.
573 */
init_for_tmp_table(enum_field_types sql_type_arg,uint32 length_arg,uint32 decimals_arg,bool is_nullable_arg,bool is_unsigned_arg,uint pack_length_override_arg,const char * fld_name)574 void Create_field::init_for_tmp_table(enum_field_types sql_type_arg,
575 uint32 length_arg, uint32 decimals_arg,
576 bool is_nullable_arg,
577 bool is_unsigned_arg,
578 uint pack_length_override_arg,
579 const char *fld_name) {
580 DBUG_TRACE;
581
582 field_name = fld_name;
583 sql_type = sql_type_arg;
584 m_max_display_width_in_codepoints = length_arg;
585 auto_flags = Field::NONE;
586 interval = nullptr;
587 charset = &my_charset_bin;
588 geom_type = Field::GEOM_GEOMETRY;
589
590 DBUG_PRINT("enter", ("sql_type: %d, length: %u", sql_type_arg, length_arg));
591
592 /* Init members needed for correct execution of make_field(). */
593 #ifndef DBUG_OFF
594 const uint32 FIELDFLAG_MAX_DEC = 31;
595 #endif
596
597 switch (sql_type_arg) {
598 case MYSQL_TYPE_BIT:
599 treat_bit_as_char = true;
600 break;
601 case MYSQL_TYPE_DATE:
602 // Old type
603 sql_type = MYSQL_TYPE_NEWDATE;
604 break;
605
606 case MYSQL_TYPE_NEWDECIMAL:
607 DBUG_ASSERT(decimals_arg <= DECIMAL_MAX_SCALE);
608 case MYSQL_TYPE_DECIMAL:
609 case MYSQL_TYPE_FLOAT:
610 case MYSQL_TYPE_DOUBLE:
611 DBUG_ASSERT(decimals_arg <= FIELDFLAG_MAX_DEC);
612 decimals = decimals_arg;
613 break;
614
615 default:
616 break;
617 }
618
619 is_nullable = is_nullable_arg;
620
621 is_zerofill = false;
622 is_unsigned = is_unsigned_arg;
623
624 pack_length_override = pack_length_override_arg;
625
626 gcol_info = nullptr;
627 stored_in_db = true;
628 m_default_val_expr = nullptr;
629 }
630
max_display_width_in_codepoints() const631 size_t Create_field::max_display_width_in_codepoints() const {
632 if (sql_type == MYSQL_TYPE_ENUM || sql_type == MYSQL_TYPE_SET) {
633 DBUG_ASSERT(interval != nullptr);
634 DBUG_ASSERT(charset != nullptr);
635
636 size_t max_display_width_in_codepoints = 0;
637 for (size_t i = 0; i < interval->count; i++) {
638 const char *start = interval->type_names[i];
639 const char *end = interval->type_names[i] + interval->type_lengths[i];
640 const size_t num_characters =
641 charset->cset->numchars(charset, start, end);
642
643 if (sql_type == MYSQL_TYPE_ENUM) {
644 // ENUM uses the longest value.
645 max_display_width_in_codepoints =
646 std::max(max_display_width_in_codepoints, num_characters);
647 } else if (sql_type == MYSQL_TYPE_SET) {
648 // SET uses the total length of all values, plus a comma between each
649 // value.
650 max_display_width_in_codepoints += num_characters;
651 if (i > 0) {
652 max_display_width_in_codepoints++;
653 }
654 }
655 }
656
657 return std::min(max_display_width_in_codepoints,
658 static_cast<size_t>(MAX_FIELD_WIDTH - 1));
659 } else if (sql_type == MYSQL_TYPE_TINY_BLOB) {
660 return TINYBLOB_MAX_SIZE_IN_BYTES / charset->mbmaxlen;
661 } else if (sql_type == MYSQL_TYPE_BLOB && !explicit_display_width()) {
662 // For BLOB and TEXT, the user can give a display width explicitly in CREATE
663 // TABLE (BLOB(25), TEXT(25)) where the expected behavior is that the server
664 // will find the smallest possible BLOB/TEXT type that will fit the given
665 // display width. If the user has given an explicit display width, return
666 // that instead of the max BLOB size.
667 return BLOB_MAX_SIZE_IN_BYTES / charset->mbmaxlen;
668 } else if (sql_type == MYSQL_TYPE_MEDIUM_BLOB) {
669 return MEDIUMBLOB_MAX_SIZE_IN_BYTES / charset->mbmaxlen;
670 } else if (sql_type == MYSQL_TYPE_LONG_BLOB || sql_type == MYSQL_TYPE_JSON ||
671 sql_type == MYSQL_TYPE_GEOMETRY) {
672 return LONGBLOB_MAX_SIZE_IN_BYTES / charset->mbmaxlen;
673 } else {
674 return m_max_display_width_in_codepoints;
675 }
676 }
677
max_display_width_in_bytes() const678 size_t Create_field::max_display_width_in_bytes() const {
679 // It might seem unnecessary to have special case for the various BLOB types
680 // instead of just using the "else" clause for these types as well. However,
681 // that might give us rounding errors for multi-byte character sets. One
682 // example is JSON which has the character set utf8mb4_bin.
683 // max_display_width_in_codepoints() will return 1073741823 (truncated from
684 // 1073741823.75), and multiplying that by four again will give 4294967292
685 // which is the wrong result.
686 DBUG_ASSERT(charset != nullptr);
687 if (is_numeric_type(sql_type) || is_temporal_real_type(sql_type) ||
688 sql_type == MYSQL_TYPE_YEAR || sql_type == MYSQL_TYPE_BIT) {
689 // Numeric types, temporal types, YEAR or BIT are never multi-byte.
690 return max_display_width_in_codepoints();
691 } else if (sql_type == MYSQL_TYPE_TINY_BLOB) {
692 return TINYBLOB_MAX_SIZE_IN_BYTES;
693 } else if (sql_type == MYSQL_TYPE_BLOB && !explicit_display_width()) {
694 // For BLOB and TEXT, the user can give a display width (BLOB(25), TEXT(25))
695 // where the expected behavior is that the server will find the smallest
696 // possible BLOB/TEXT type that will fit the given display width. If the
697 // user has given an explicit display width, return that instead of the
698 // max BLOB size.
699 return BLOB_MAX_SIZE_IN_BYTES;
700 } else if (sql_type == MYSQL_TYPE_MEDIUM_BLOB) {
701 return MEDIUMBLOB_MAX_SIZE_IN_BYTES;
702 } else if (sql_type == MYSQL_TYPE_LONG_BLOB || sql_type == MYSQL_TYPE_JSON ||
703 sql_type == MYSQL_TYPE_GEOMETRY) {
704 return LONGBLOB_MAX_SIZE_IN_BYTES;
705 } else {
706 // If the user has given a display width to the TEXT type where the display
707 // width is 2^32-1, the below computation will exceed
708 // LONGBLOB_MAX_SIZE_IN_BYTES if the character set is multi-byte. So we must
709 // ensure that we never return a value greater than
710 // LONGBLOB_MAX_SIZE_IN_BYTES.
711 std::int64_t display_width = max_display_width_in_codepoints() *
712 static_cast<std::int64_t>(charset->mbmaxlen);
713 return static_cast<size_t>(std::min(
714 display_width, static_cast<std::int64_t>(LONGBLOB_MAX_SIZE_IN_BYTES)));
715 }
716 }
717
pack_length(bool dont_override) const718 size_t Create_field::pack_length(bool dont_override) const {
719 if (!dont_override && pack_length_override != 0) return pack_length_override;
720
721 switch (sql_type) {
722 case MYSQL_TYPE_SET: {
723 return get_set_pack_length(interval == nullptr ? interval_list.elements
724 : interval->count);
725 }
726 case MYSQL_TYPE_ENUM: {
727 return get_enum_pack_length(interval == nullptr ? interval_list.elements
728 : interval->count);
729 }
730 case MYSQL_TYPE_NEWDECIMAL: {
731 DBUG_ASSERT(decimals <= DECIMAL_MAX_SCALE);
732 uint precision = my_decimal_length_to_precision(
733 max_display_width_in_bytes(), decimals, (flags & UNSIGNED_FLAG));
734 precision = std::min(precision, static_cast<uint>(DECIMAL_MAX_PRECISION));
735 return my_decimal_get_binary_size(precision, decimals);
736 }
737 case MYSQL_TYPE_BIT: {
738 if (treat_bit_as_char) {
739 return (max_display_width_in_bytes() + 7) / 8;
740 } else {
741 return max_display_width_in_bytes() / 8;
742 }
743 }
744 default: {
745 return calc_pack_length(sql_type, max_display_width_in_bytes());
746 }
747 }
748 }
749
key_length() const750 size_t Create_field::key_length() const {
751 switch (sql_type) {
752 case MYSQL_TYPE_TINY_BLOB:
753 case MYSQL_TYPE_MEDIUM_BLOB:
754 case MYSQL_TYPE_LONG_BLOB:
755 case MYSQL_TYPE_BLOB:
756 case MYSQL_TYPE_GEOMETRY:
757 case MYSQL_TYPE_JSON:
758 case MYSQL_TYPE_VAR_STRING:
759 case MYSQL_TYPE_STRING:
760 case MYSQL_TYPE_VARCHAR: {
761 return std::min(max_display_width_in_bytes(),
762 static_cast<size_t>(MAX_FIELD_BLOBLENGTH));
763 }
764 case MYSQL_TYPE_ENUM:
765 case MYSQL_TYPE_SET: {
766 return pack_length();
767 }
768 case MYSQL_TYPE_BIT: {
769 if (treat_bit_as_char) {
770 return pack_length();
771 }
772 return pack_length() + (max_display_width_in_bytes() & 7 ? 1 : 0);
773 }
774 default: {
775 return pack_length(is_array);
776 }
777 }
778 }
779
is_field_for_functional_index(const Create_field * create_field)780 bool is_field_for_functional_index(const Create_field *create_field) {
781 return create_field->hidden == dd::Column::enum_hidden_type::HT_HIDDEN_SQL;
782 }
783