2 Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 /* Analyse database */
21 /* TODO: - Check if any character fields can be of any date type
22 ** (date, datetime, year, time, timestamp, newdate)
23 ** - Check if any number field should be a timestamp
24 ** - type set is out of optimization yet
27 #ifdef USE_PRAGMA_IMPLEMENTATION
28 #pragma implementation // gcc: Class implementation
33 #include "mysql_priv.h"
34 #include "procedure.h"
35 #include "sql_analyse.h"
38 #define MAX_TREEMEM 8192
39 #define MAX_TREE_ELEMENTS 256
41 int sortcmp2(void* cmp_arg
__attribute__((unused
)),
42 const String
*a
,const String
*b
)
44 return sortcmp(a
,b
,a
->charset());
47 int compare_double2(void* cmp_arg
__attribute__((unused
)),
48 const double *s
, const double *t
)
50 return compare_double(s
,t
);
53 int compare_longlong2(void* cmp_arg
__attribute__((unused
)),
54 const longlong
*s
, const longlong
*t
)
56 return compare_longlong(s
,t
);
59 int compare_ulonglong2(void* cmp_arg
__attribute__((unused
)),
60 const ulonglong
*s
, const ulonglong
*t
)
62 return compare_ulonglong(s
,t
);
65 int compare_decimal2(int* len
, const char *s
, const char *t
)
67 return memcmp(s
, t
, *len
);
72 proc_analyse_init(THD
*thd
, ORDER
*param
, select_result
*result
,
73 List
<Item
> &field_list
)
75 char *proc_name
= (*param
->item
)->name
;
76 analyse
*pc
= new analyse(result
);
78 DBUG_ENTER("proc_analyse_init");
83 if (!(param
= param
->next
))
85 pc
->max_tree_elements
= MAX_TREE_ELEMENTS
;
86 pc
->max_treemem
= MAX_TREEMEM
;
91 if (!(*param
->item
)->fixed
&& (*param
->item
)->fix_fields(thd
, param
->item
))
93 DBUG_PRINT("info", ("fix_fields() for the first parameter failed"));
96 if ((*param
->item
)->type() != Item::INT_ITEM
||
97 (*param
->item
)->val_real() < 0)
99 my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE
, MYF(0), proc_name
);
102 pc
->max_tree_elements
= (uint
) (*param
->item
)->val_int();
104 if (param
->next
) // no third parameter possible
106 my_error(ER_WRONG_PARAMCOUNT_TO_PROCEDURE
, MYF(0), proc_name
);
110 if (!(*param
->item
)->fixed
&& (*param
->item
)->fix_fields(thd
, param
->item
))
112 DBUG_PRINT("info", ("fix_fields() for the second parameter failed"));
115 if ((*param
->item
)->type() != Item::INT_ITEM
||
116 (*param
->item
)->val_real() < 0)
118 my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE
, MYF(0), proc_name
);
121 pc
->max_treemem
= (uint
) (*param
->item
)->val_int();
123 else if ((*param
->item
)->type() != Item::INT_ITEM
||
124 (*param
->item
)->val_real() < 0)
126 my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE
, MYF(0), proc_name
);
129 // if only one parameter was given, it will be the value of max_tree_elements
132 pc
->max_tree_elements
= (uint
) (*param
->item
)->val_int();
133 pc
->max_treemem
= MAX_TREEMEM
;
137 (field_info
**)sql_alloc(sizeof(field_info
*)*field_list
.elements
)))
139 pc
->f_end
= pc
->f_info
+ field_list
.elements
;
140 pc
->fields
= field_list
;
143 List_iterator_fast
<Item
> it(pc
->fields
);
147 while ((item
= it
++))
149 field_info
*new_field
;
150 switch (item
->result_type()) {
152 // Check if fieldtype is ulonglong
153 if (item
->type() == Item::FIELD_ITEM
&&
154 ((Item_field
*) item
)->field
->type() == MYSQL_TYPE_LONGLONG
&&
155 ((Field_longlong
*) ((Item_field
*) item
)->field
)->unsigned_flag
)
156 new_field
= new field_ulonglong(item
, pc
);
158 new_field
= new field_longlong(item
, pc
);
161 new_field
= new field_real(item
, pc
);
164 new_field
= new field_decimal(item
, pc
);
167 new_field
= new field_str(item
, pc
);
172 *f_info
++= new_field
;
183 Return 1 if number, else return 0
184 store info about found number in info
185 NOTE:It is expected, that elements of 'info' are all zero!
188 bool test_if_number(NUM_INFO
*info
, const char *str
, uint str_len
)
190 const char *begin
, *end
= str
+ str_len
;
191 DBUG_ENTER("test_if_number");
194 MySQL removes any endspaces of a string, so we must take care only of
195 spaces in front of a string
197 for (; str
!= end
&& my_isspace(system_charset_info
, *str
); str
++) ;
204 if (++str
== end
|| *str
== '0') // converting -0 to a number
205 DBUG_RETURN(0); // might lose information
210 for (; str
!= end
&& my_isdigit(system_charset_info
,*str
); str
++)
212 if (!info
->integers
&& *str
== '0' && (str
+ 1) != end
&&
213 my_isdigit(system_charset_info
,*(str
+ 1)))
214 info
->zerofill
= 1; // could be a postnumber for example
217 if (str
== end
&& info
->integers
)
219 char *endpos
= (char*) end
;
221 info
->ullval
= (ulonglong
) my_strtoll10(begin
, &endpos
, &error
);
222 if (info
->integers
== 1)
223 DBUG_RETURN(0); // single number can't be zerofill
224 info
->maybe_zerofill
= 1;
225 DBUG_RETURN(1); // a zerofill number, or an integer
227 if (*str
== '.' || *str
== 'e' || *str
== 'E')
229 if (info
->zerofill
) // can't be zerofill anymore
231 if ((str
+ 1) == end
) // number was something like '123[.eE]'
233 char *endpos
= (char*) str
;
235 info
->ullval
= (ulonglong
) my_strtoll10(begin
, &endpos
, &error
);
238 if (*str
== 'e' || *str
== 'E') // number may be something like '1e+50'
241 if (*str
!= '-' && *str
!= '+')
243 for (str
++; str
!= end
&& my_isdigit(system_charset_info
,*str
); str
++) ;
246 info
->is_float
= 1; // we can't use variable decimals here
251 for (str
++; *(end
- 1) == '0'; end
--) ; // jump over zeros at the end
252 if (str
== end
) // number was something like '123.000'
254 char *endpos
= (char*) str
;
256 info
->ullval
= (ulonglong
) my_strtoll10(begin
, &endpos
, &error
);
259 for (; str
!= end
&& my_isdigit(system_charset_info
,*str
); str
++)
263 info
->dval
= my_atof(begin
);
272 Stores the biggest and the smallest value from current 'info'
274 If info contains an ulonglong number, which is bigger than
275 biggest positive number able to be stored in a longlong variable
276 and is marked as negative, function will return 0, else 1.
279 bool get_ev_num_info(EV_NUM_INFO
*ev_info
, NUM_INFO
*info
, const char *num
)
283 if (((longlong
) info
->ullval
) < 0)
284 return 0; // Impossible to store as a negative number
285 ev_info
->llval
= -(longlong
) max((ulonglong
) -ev_info
->llval
,
287 ev_info
->min_dval
= (double) -max(-ev_info
->min_dval
, info
->dval
);
289 else // ulonglong is as big as bigint in MySQL
291 if ((check_ulonglong(num
, info
->integers
) == DECIMAL_NUM
))
293 ev_info
->ullval
= (ulonglong
) max(ev_info
->ullval
, info
->ullval
);
294 ev_info
->max_dval
= (double) max(ev_info
->max_dval
, info
->dval
);
300 void free_string(String
*s
)
306 void field_str::add()
308 char buff
[MAX_FIELD_WIDTH
], *ptr
;
309 String
s(buff
, sizeof(buff
),&my_charset_bin
), *res
;
312 if (!(res
= item
->val_str(&s
)))
318 if (!(length
= res
->length()))
322 ptr
= (char*) res
->ptr();
323 if (*(ptr
+ (length
- 1)) == ' ')
327 if (can_be_still_num
)
329 bzero((char*) &num_info
, sizeof(num_info
));
330 if (!test_if_number(&num_info
, res
->ptr(), (uint
) length
))
331 can_be_still_num
= 0;
334 bzero((char*) &ev_num_info
, sizeof(ev_num_info
));
335 was_zero_fill
= num_info
.zerofill
;
337 else if (num_info
.zerofill
!= was_zero_fill
&& !was_maybe_zerofill
)
338 can_be_still_num
= 0; // one more check needed, when length is counted
339 if (can_be_still_num
)
340 can_be_still_num
= get_ev_num_info(&ev_num_info
, &num_info
, res
->ptr());
341 was_maybe_zerofill
= num_info
.maybe_zerofill
;
344 /* Update min and max arguments */
350 min_length
= max_length
= length
; sum
=length
;
355 if (length
< min_length
)
357 if (length
> max_length
)
360 if (sortcmp(res
, &min_arg
,item
->collation
.collation
) < 0)
362 if (sortcmp(res
, &max_arg
,item
->collation
.collation
) > 0)
370 if (!tree_search(&tree
, (void*) &s
, tree
.custom_arg
)) // If not in tree
372 s
.copy(); // slow, when SAFE_MALLOC is in use
373 if (!tree_insert(&tree
, (void*) &s
, 0, tree
.custom_arg
))
375 room_in_tree
= 0; // Remove tree, out of RAM ?
380 bzero((char*) &s
, sizeof(s
)); // Let tree handle free of this
381 if ((treemem
+= length
) > pc
->max_treemem
)
383 room_in_tree
= 0; // Remove tree, too big tree
390 if ((num_info
.zerofill
&& (max_length
!= min_length
)) ||
391 (was_zero_fill
&& (max_length
!= min_length
)))
392 can_be_still_num
= 0; // zerofilled numbers must be of same length
396 void field_real::add()
398 char buff
[MAX_FIELD_WIDTH
], *ptr
, *end
;
399 double num
= item
->val_real();
400 uint length
, zero_count
, decs
;
401 TREE_ELEMENT
*element
;
403 if (item
->null_value
)
411 if ((decs
= decimals()) == NOT_FIXED_DEC
)
413 length
= sprintf(buff
, "%g", num
);
414 if (rint(num
) != num
)
415 max_notzero_dec_len
= 1;
420 buff
[sizeof(buff
)-1]=0; // Safety
421 snprintf(buff
, sizeof(buff
)-1, "%-.*f", (int) decs
, num
);
422 length
= (uint
) strlen(buff
);
424 length
= sprintf(buff
, "%-.*f", (int) decs
, num
);
427 // We never need to check further than this
428 end
= buff
+ length
- 1 - decs
+ max_notzero_dec_len
;
431 for (ptr
= buff
+ length
- 1; ptr
> end
&& *ptr
== '0'; ptr
--)
434 if ((decs
- zero_count
> max_notzero_dec_len
))
435 max_notzero_dec_len
= decs
- zero_count
;
440 if (!(element
= tree_insert(&tree
, (void*) &num
, 0, tree
.custom_arg
)))
442 room_in_tree
= 0; // Remove tree, out of RAM ?
446 if element->count == 1, this element can be found only once from tree
447 if element->count == 2, or more, this element is already in tree
449 else if (element
->count
== 1 && (tree_elements
++) >= pc
->max_tree_elements
)
451 room_in_tree
= 0; // Remove tree, too many elements
459 min_arg
= max_arg
= sum
= num
;
461 min_length
= max_length
= length
;
466 sum_sqr
+= num
* num
;
467 if (length
< min_length
)
469 if (length
> max_length
)
471 if (compare_double(&num
, &min_arg
) < 0)
473 if (compare_double(&num
, &max_arg
) > 0)
479 void field_decimal::add()
481 /*TODO - remove rounding stuff after decimal_div returns proper frac */
482 my_decimal dec_buf
, *dec
= item
->val_decimal(&dec_buf
);
485 TREE_ELEMENT
*element
;
487 if (item
->null_value
)
493 my_decimal_round(E_DEC_FATAL_ERROR
, dec
, item
->decimals
, FALSE
,&rounded
);
496 length
= my_decimal_string_length(dec
);
498 if (decimal_is_zero(dec
))
503 uchar buf
[DECIMAL_MAX_FIELD_SIZE
];
504 my_decimal2binary(E_DEC_FATAL_ERROR
, dec
, buf
,
505 item
->max_length
, item
->decimals
);
506 if (!(element
= tree_insert(&tree
, (void*)buf
, 0, tree
.custom_arg
)))
508 room_in_tree
= 0; // Remove tree, out of RAM ?
512 if element->count == 1, this element can be found only once from tree
513 if element->count == 2, or more, this element is already in tree
515 else if (element
->count
== 1 && (tree_elements
++) >= pc
->max_tree_elements
)
517 room_in_tree
= 0; // Remove tree, too many elements
525 min_arg
= max_arg
= sum
[0] = *dec
;
526 my_decimal_mul(E_DEC_FATAL_ERROR
, sum_sqr
, dec
, dec
);
528 min_length
= max_length
= length
;
530 else if (!decimal_is_zero(dec
))
532 int next_cur_sum
= cur_sum
^ 1;
535 my_decimal_add(E_DEC_FATAL_ERROR
, sum
+next_cur_sum
, sum
+cur_sum
, dec
);
536 my_decimal_mul(E_DEC_FATAL_ERROR
, &sqr_buf
, dec
, dec
);
537 my_decimal_add(E_DEC_FATAL_ERROR
,
538 sum_sqr
+next_cur_sum
, sum_sqr
+cur_sum
, &sqr_buf
);
539 cur_sum
= next_cur_sum
;
540 if (length
< min_length
)
542 if (length
> max_length
)
544 if (my_decimal_cmp(dec
, &min_arg
) < 0)
548 if (my_decimal_cmp(dec
, &max_arg
) > 0)
556 void field_longlong::add()
558 char buff
[MAX_FIELD_WIDTH
];
559 longlong num
= item
->val_int();
560 uint length
= (uint
) (longlong10_to_str(num
, buff
, -10) - buff
);
561 TREE_ELEMENT
*element
;
563 if (item
->null_value
)
573 if (!(element
= tree_insert(&tree
, (void*) &num
, 0, tree
.custom_arg
)))
575 room_in_tree
= 0; // Remove tree, out of RAM ?
579 if element->count == 1, this element can be found only once from tree
580 if element->count == 2, or more, this element is already in tree
582 else if (element
->count
== 1 && (tree_elements
++) >= pc
->max_tree_elements
)
584 room_in_tree
= 0; // Remove tree, too many elements
592 min_arg
= max_arg
= sum
= num
;
594 min_length
= max_length
= length
;
599 sum_sqr
+= num
* num
;
600 if (length
< min_length
)
602 if (length
> max_length
)
604 if (compare_longlong(&num
, &min_arg
) < 0)
606 if (compare_longlong(&num
, &max_arg
) > 0)
609 } // field_longlong::add
612 void field_ulonglong::add()
614 char buff
[MAX_FIELD_WIDTH
];
615 longlong num
= item
->val_int();
616 uint length
= (uint
) (longlong10_to_str(num
, buff
, 10) - buff
);
617 TREE_ELEMENT
*element
;
619 if (item
->null_value
)
629 if (!(element
= tree_insert(&tree
, (void*) &num
, 0, tree
.custom_arg
)))
631 room_in_tree
= 0; // Remove tree, out of RAM ?
635 if element->count == 1, this element can be found only once from tree
636 if element->count == 2, or more, this element is already in tree
638 else if (element
->count
== 1 && (tree_elements
++) >= pc
->max_tree_elements
)
640 room_in_tree
= 0; // Remove tree, too many elements
648 min_arg
= max_arg
= sum
= num
;
650 min_length
= max_length
= length
;
655 sum_sqr
+= num
* num
;
656 if (length
< min_length
)
658 if (length
> max_length
)
660 if (compare_ulonglong((ulonglong
*) &num
, &min_arg
) < 0)
662 if (compare_ulonglong((ulonglong
*) &num
, &max_arg
) > 0)
665 } // field_ulonglong::add
668 int analyse::send_row(List
<Item
> & /* field_list */)
670 field_info
**f
= f_info
;
674 for (;f
!= f_end
; f
++)
679 } // analyse::send_row
682 int analyse::end_of_records()
684 field_info
**f
= f_info
;
685 char buff
[MAX_FIELD_WIDTH
];
686 String
*res
, s_min(buff
, sizeof(buff
),&my_charset_bin
),
687 s_max(buff
, sizeof(buff
),&my_charset_bin
),
688 ans(buff
, sizeof(buff
),&my_charset_bin
);
690 for (; f
!= f_end
; f
++)
692 func_items
[0]->set((*f
)->item
->full_name());
695 func_items
[1]->null_value
= 1;
696 func_items
[2]->null_value
= 1;
700 func_items
[1]->null_value
= 0;
701 res
= (*f
)->get_min_arg(&s_min
);
702 func_items
[1]->set(res
->ptr(), res
->length(), res
->charset());
703 func_items
[2]->null_value
= 0;
704 res
= (*f
)->get_max_arg(&s_max
);
705 func_items
[2]->set(res
->ptr(), res
->length(), res
->charset());
707 func_items
[3]->set((longlong
) (*f
)->min_length
);
708 func_items
[4]->set((longlong
) (*f
)->max_length
);
709 func_items
[5]->set((longlong
) (*f
)->empty
);
710 func_items
[6]->set((longlong
) (*f
)->nulls
);
711 res
= (*f
)->avg(&s_max
, rows
);
712 func_items
[7]->set(res
->ptr(), res
->length(), res
->charset());
713 func_items
[8]->null_value
= 0;
714 res
= (*f
)->std(&s_max
, rows
);
716 func_items
[8]->null_value
= 1;
718 func_items
[8]->set(res
->ptr(), res
->length(), res
->charset());
720 count the dots, quotas, etc. in (ENUM("a","b","c"...))
721 If tree has been removed, don't suggest ENUM.
722 treemem is used to measure the size of tree for strings,
723 tree_elements is used to count the elements
724 max_treemem tells how long the string starting from ENUM("... and
725 ending to ..") shall at maximum be. If case is about numbers,
726 max_tree_elements will tell the length of the above, now
727 every number is considered as length 1
729 if (((*f
)->treemem
|| (*f
)->tree_elements
) &&
730 (*f
)->tree
.elements_in_tree
&&
731 (((*f
)->treemem
? max_treemem
: max_tree_elements
) >
732 (((*f
)->treemem
? (*f
)->treemem
: (*f
)->tree_elements
) +
733 ((*f
)->tree
.elements_in_tree
* 3 - 1 + 6))))
735 char tmp
[331]; //331, because one double prec. num. can be this long
736 String
tmp_str(tmp
, sizeof(tmp
),&my_charset_bin
);
739 tree_info
.str
= &tmp_str
;
741 tree_info
.item
= (*f
)->item
;
743 tmp_str
.set(STRING_WITH_LEN("ENUM("),&my_charset_bin
);
744 tree_walk(&(*f
)->tree
, (*f
)->collect_enum(), (char*) &tree_info
,
749 tmp_str
.append(STRING_WITH_LEN(" NOT NULL"));
750 output_str_length
= tmp_str
.length();
751 func_items
[9]->set(tmp_str
.ptr(), tmp_str
.length(), tmp_str
.charset());
752 if (result
->send_data(result_fields
))
758 if (!(*f
)->treemem
&& !(*f
)->tree_elements
)
759 ans
.append(STRING_WITH_LEN("CHAR(0)"));
760 else if ((*f
)->item
->type() == Item::FIELD_ITEM
)
762 switch (((Item_field
*) (*f
)->item
)->field
->real_type())
764 case MYSQL_TYPE_TIMESTAMP
:
765 ans
.append(STRING_WITH_LEN("TIMESTAMP"));
767 case MYSQL_TYPE_DATETIME
:
768 ans
.append(STRING_WITH_LEN("DATETIME"));
770 case MYSQL_TYPE_DATE
:
771 case MYSQL_TYPE_NEWDATE
:
772 ans
.append(STRING_WITH_LEN("DATE"));
775 ans
.append(STRING_WITH_LEN("SET"));
777 case MYSQL_TYPE_YEAR
:
778 ans
.append(STRING_WITH_LEN("YEAR"));
780 case MYSQL_TYPE_TIME
:
781 ans
.append(STRING_WITH_LEN("TIME"));
783 case MYSQL_TYPE_DECIMAL
:
784 ans
.append(STRING_WITH_LEN("DECIMAL"));
785 // if item is FIELD_ITEM, it _must_be_ Field_num in this case
786 if (((Field_num
*) ((Item_field
*) (*f
)->item
)->field
)->zerofill
)
787 ans
.append(STRING_WITH_LEN(" ZEROFILL"));
790 (*f
)->get_opt_type(&ans
, rows
);
795 ans
.append(STRING_WITH_LEN(" NOT NULL"));
796 func_items
[9]->set(ans
.ptr(), ans
.length(), ans
.charset());
797 if (result
->send_data(result_fields
))
801 } // analyse::end_of_records
804 void field_str::get_opt_type(String
*answer
, ha_rows total_rows
)
806 char buff
[MAX_FIELD_WIDTH
];
808 if (can_be_still_num
)
810 if (num_info
.is_float
)
811 sprintf(buff
, "DOUBLE"); // number was like 1e+50... TODO:
812 else if (num_info
.decimals
) // DOUBLE(%d,%d) sometime
814 if (num_info
.dval
> -FLT_MAX
&& num_info
.dval
< FLT_MAX
)
815 sprintf(buff
, "FLOAT(%d,%d)", (num_info
.integers
+ num_info
.decimals
), num_info
.decimals
);
817 sprintf(buff
, "DOUBLE(%d,%d)", (num_info
.integers
+ num_info
.decimals
), num_info
.decimals
);
819 else if (ev_num_info
.llval
>= -128 &&
820 ev_num_info
.ullval
<=
821 (ulonglong
) (ev_num_info
.llval
>= 0 ? 255 : 127))
822 sprintf(buff
, "TINYINT(%d)", num_info
.integers
);
823 else if (ev_num_info
.llval
>= INT_MIN16
&&
824 ev_num_info
.ullval
<= (ulonglong
) (ev_num_info
.llval
>= 0 ?
825 UINT_MAX16
: INT_MAX16
))
826 sprintf(buff
, "SMALLINT(%d)", num_info
.integers
);
827 else if (ev_num_info
.llval
>= INT_MIN24
&&
828 ev_num_info
.ullval
<= (ulonglong
) (ev_num_info
.llval
>= 0 ?
829 UINT_MAX24
: INT_MAX24
))
830 sprintf(buff
, "MEDIUMINT(%d)", num_info
.integers
);
831 else if (ev_num_info
.llval
>= INT_MIN32
&&
832 ev_num_info
.ullval
<= (ulonglong
) (ev_num_info
.llval
>= 0 ?
833 UINT_MAX32
: INT_MAX32
))
834 sprintf(buff
, "INT(%d)", num_info
.integers
);
836 sprintf(buff
, "BIGINT(%d)", num_info
.integers
);
837 answer
->append(buff
, (uint
) strlen(buff
));
838 if (ev_num_info
.llval
>= 0 && ev_num_info
.min_dval
>= 0)
839 answer
->append(STRING_WITH_LEN(" UNSIGNED"));
840 if (num_info
.zerofill
)
841 answer
->append(STRING_WITH_LEN(" ZEROFILL"));
843 else if (max_length
< 256)
847 if (item
->collation
.collation
== &my_charset_bin
)
848 answer
->append(STRING_WITH_LEN("TINYBLOB"));
850 answer
->append(STRING_WITH_LEN("TINYTEXT"));
852 else if ((max_length
* (total_rows
- nulls
)) < (sum
+ total_rows
))
854 sprintf(buff
, "CHAR(%d)", (int) max_length
);
855 answer
->append(buff
, (uint
) strlen(buff
));
859 sprintf(buff
, "VARCHAR(%d)", (int) max_length
);
860 answer
->append(buff
, (uint
) strlen(buff
));
863 else if (max_length
< (1L << 16))
865 if (item
->collation
.collation
== &my_charset_bin
)
866 answer
->append(STRING_WITH_LEN("BLOB"));
868 answer
->append(STRING_WITH_LEN("TEXT"));
870 else if (max_length
< (1L << 24))
872 if (item
->collation
.collation
== &my_charset_bin
)
873 answer
->append(STRING_WITH_LEN("MEDIUMBLOB"));
875 answer
->append(STRING_WITH_LEN("MEDIUMTEXT"));
879 if (item
->collation
.collation
== &my_charset_bin
)
880 answer
->append(STRING_WITH_LEN("LONGBLOB"));
882 answer
->append(STRING_WITH_LEN("LONGTEXT"));
884 } // field_str::get_opt_type
887 void field_real::get_opt_type(String
*answer
,
888 ha_rows total_rows
__attribute__((unused
)))
890 char buff
[MAX_FIELD_WIDTH
];
892 if (!max_notzero_dec_len
)
894 int len
= (int) max_length
- ((item
->decimals
== NOT_FIXED_DEC
) ?
895 0 : (item
->decimals
+ 1));
897 if (min_arg
>= -128 && max_arg
<= (min_arg
>= 0 ? 255 : 127))
898 sprintf(buff
, "TINYINT(%d)", len
);
899 else if (min_arg
>= INT_MIN16
&& max_arg
<= (min_arg
>= 0 ?
900 UINT_MAX16
: INT_MAX16
))
901 sprintf(buff
, "SMALLINT(%d)", len
);
902 else if (min_arg
>= INT_MIN24
&& max_arg
<= (min_arg
>= 0 ?
903 UINT_MAX24
: INT_MAX24
))
904 sprintf(buff
, "MEDIUMINT(%d)", len
);
905 else if (min_arg
>= INT_MIN32
&& max_arg
<= (min_arg
>= 0 ?
906 UINT_MAX32
: INT_MAX32
))
907 sprintf(buff
, "INT(%d)", len
);
909 sprintf(buff
, "BIGINT(%d)", len
);
910 answer
->append(buff
, (uint
) strlen(buff
));
912 answer
->append(STRING_WITH_LEN(" UNSIGNED"));
914 else if (item
->decimals
== NOT_FIXED_DEC
)
916 if (min_arg
>= -FLT_MAX
&& max_arg
<= FLT_MAX
)
917 answer
->append(STRING_WITH_LEN("FLOAT"));
919 answer
->append(STRING_WITH_LEN("DOUBLE"));
923 if (min_arg
>= -FLT_MAX
&& max_arg
<= FLT_MAX
)
924 sprintf(buff
, "FLOAT(%d,%d)", (int) max_length
- (item
->decimals
+ 1) + max_notzero_dec_len
,
925 max_notzero_dec_len
);
927 sprintf(buff
, "DOUBLE(%d,%d)", (int) max_length
- (item
->decimals
+ 1) + max_notzero_dec_len
,
928 max_notzero_dec_len
);
929 answer
->append(buff
, (uint
) strlen(buff
));
931 // if item is FIELD_ITEM, it _must_be_ Field_num in this class
932 if (item
->type() == Item::FIELD_ITEM
&&
933 // a single number shouldn't be zerofill
934 (max_length
- (item
->decimals
+ 1)) != 1 &&
935 ((Field_num
*) ((Item_field
*) item
)->field
)->zerofill
)
936 answer
->append(STRING_WITH_LEN(" ZEROFILL"));
937 } // field_real::get_opt_type
940 void field_longlong::get_opt_type(String
*answer
,
941 ha_rows total_rows
__attribute__((unused
)))
943 char buff
[MAX_FIELD_WIDTH
];
945 if (min_arg
>= -128 && max_arg
<= (min_arg
>= 0 ? 255 : 127))
946 sprintf(buff
, "TINYINT(%d)", (int) max_length
);
947 else if (min_arg
>= INT_MIN16
&& max_arg
<= (min_arg
>= 0 ?
948 UINT_MAX16
: INT_MAX16
))
949 sprintf(buff
, "SMALLINT(%d)", (int) max_length
);
950 else if (min_arg
>= INT_MIN24
&& max_arg
<= (min_arg
>= 0 ?
951 UINT_MAX24
: INT_MAX24
))
952 sprintf(buff
, "MEDIUMINT(%d)", (int) max_length
);
953 else if (min_arg
>= INT_MIN32
&& max_arg
<= (min_arg
>= 0 ?
954 UINT_MAX32
: INT_MAX32
))
955 sprintf(buff
, "INT(%d)", (int) max_length
);
957 sprintf(buff
, "BIGINT(%d)", (int) max_length
);
958 answer
->append(buff
, (uint
) strlen(buff
));
960 answer
->append(STRING_WITH_LEN(" UNSIGNED"));
962 // if item is FIELD_ITEM, it _must_be_ Field_num in this class
963 if ((item
->type() == Item::FIELD_ITEM
) &&
964 // a single number shouldn't be zerofill
966 ((Field_num
*) ((Item_field
*) item
)->field
)->zerofill
)
967 answer
->append(STRING_WITH_LEN(" ZEROFILL"));
968 } // field_longlong::get_opt_type
971 void field_ulonglong::get_opt_type(String
*answer
,
972 ha_rows total_rows
__attribute__((unused
)))
974 char buff
[MAX_FIELD_WIDTH
];
977 sprintf(buff
, "TINYINT(%d) UNSIGNED", (int) max_length
);
978 else if (max_arg
<= ((2 * INT_MAX16
) + 1))
979 sprintf(buff
, "SMALLINT(%d) UNSIGNED", (int) max_length
);
980 else if (max_arg
<= ((2 * INT_MAX24
) + 1))
981 sprintf(buff
, "MEDIUMINT(%d) UNSIGNED", (int) max_length
);
982 else if (max_arg
< (((ulonglong
) 1) << 32))
983 sprintf(buff
, "INT(%d) UNSIGNED", (int) max_length
);
985 sprintf(buff
, "BIGINT(%d) UNSIGNED", (int) max_length
);
986 // if item is FIELD_ITEM, it _must_be_ Field_num in this class
987 answer
->append(buff
, (uint
) strlen(buff
));
988 if (item
->type() == Item::FIELD_ITEM
&&
989 // a single number shouldn't be zerofill
991 ((Field_num
*) ((Item_field
*) item
)->field
)->zerofill
)
992 answer
->append(STRING_WITH_LEN(" ZEROFILL"));
993 } //field_ulonglong::get_opt_type
996 void field_decimal::get_opt_type(String
*answer
,
997 ha_rows total_rows
__attribute__((unused
)))
1000 char buff
[MAX_FIELD_WIDTH
];
1003 my_decimal_set_zero(&zero
);
1004 my_bool is_unsigned
= (my_decimal_cmp(&zero
, &min_arg
) >= 0);
1006 length
= my_snprintf(buff
, sizeof(buff
), "DECIMAL(%d, %d)",
1007 (int) (max_length
- (item
->decimals
? 1 : 0)),
1010 length
= (uint
) (strmov(buff
+length
, " UNSIGNED")- buff
);
1011 answer
->append(buff
, length
);
1015 String
*field_decimal::get_min_arg(String
*str
)
1017 my_decimal2string(E_DEC_FATAL_ERROR
, &min_arg
, 0, 0, '0', str
);
1022 String
*field_decimal::get_max_arg(String
*str
)
1024 my_decimal2string(E_DEC_FATAL_ERROR
, &max_arg
, 0, 0, '0', str
);
1029 String
*field_decimal::avg(String
*s
, ha_rows rows
)
1031 if (!(rows
- nulls
))
1033 s
->set_real((double) 0.0, 1,my_thd_charset
);
1036 my_decimal num
, avg_val
, rounded_avg
;
1037 int prec_increment
= current_thd
->variables
.div_precincrement
;
1039 int2my_decimal(E_DEC_FATAL_ERROR
, rows
- nulls
, FALSE
, &num
);
1040 my_decimal_div(E_DEC_FATAL_ERROR
, &avg_val
, sum
+cur_sum
, &num
, prec_increment
);
1041 /* TODO remove this after decimal_div returns proper frac */
1042 my_decimal_round(E_DEC_FATAL_ERROR
, &avg_val
,
1043 min(sum
[cur_sum
].frac
+ prec_increment
, DECIMAL_MAX_SCALE
),
1044 FALSE
,&rounded_avg
);
1045 my_decimal2string(E_DEC_FATAL_ERROR
, &rounded_avg
, 0, 0, '0', s
);
1050 String
*field_decimal::std(String
*s
, ha_rows rows
)
1052 if (!(rows
- nulls
))
1054 s
->set_real((double) 0.0, 1,my_thd_charset
);
1057 my_decimal num
, tmp
, sum2
, sum2d
;
1059 int prec_increment
= current_thd
->variables
.div_precincrement
;
1061 int2my_decimal(E_DEC_FATAL_ERROR
, rows
- nulls
, FALSE
, &num
);
1062 my_decimal_mul(E_DEC_FATAL_ERROR
, &sum2
, sum
+cur_sum
, sum
+cur_sum
);
1063 my_decimal_div(E_DEC_FATAL_ERROR
, &tmp
, &sum2
, &num
, prec_increment
);
1064 my_decimal_sub(E_DEC_FATAL_ERROR
, &sum2
, sum_sqr
+cur_sum
, &tmp
);
1065 my_decimal_div(E_DEC_FATAL_ERROR
, &tmp
, &sum2
, &num
, prec_increment
);
1066 my_decimal2double(E_DEC_FATAL_ERROR
, &tmp
, &std_sqr
);
1067 s
->set_real(((double) std_sqr
<= 0.0 ? 0.0 : sqrt(std_sqr
)),
1068 min(item
->decimals
+ prec_increment
, NOT_FIXED_DEC
), my_thd_charset
);
1074 int collect_string(String
*element
,
1075 element_count count
__attribute__((unused
)),
1079 info
->str
->append(',');
1082 info
->str
->append('\'');
1083 if (append_escaped(info
->str
, element
))
1085 info
->str
->append('\'');
1090 int collect_real(double *element
, element_count count
__attribute__((unused
)),
1093 char buff
[MAX_FIELD_WIDTH
];
1094 String
s(buff
, sizeof(buff
),current_thd
->charset());
1097 info
->str
->append(',');
1100 info
->str
->append('\'');
1101 s
.set_real(*element
, info
->item
->decimals
, current_thd
->charset());
1102 info
->str
->append(s
);
1103 info
->str
->append('\'');
1108 int collect_decimal(uchar
*element
, element_count count
,
1111 char buff
[DECIMAL_MAX_STR_LENGTH
];
1112 String
s(buff
, sizeof(buff
),&my_charset_bin
);
1115 info
->str
->append(',');
1119 binary2my_decimal(E_DEC_FATAL_ERROR
, element
, &dec
,
1120 info
->item
->max_length
, info
->item
->decimals
);
1122 info
->str
->append('\'');
1123 my_decimal2string(E_DEC_FATAL_ERROR
, &dec
, 0, 0, '0', &s
);
1124 info
->str
->append(s
);
1125 info
->str
->append('\'');
1130 int collect_longlong(longlong
*element
,
1131 element_count count
__attribute__((unused
)),
1134 char buff
[MAX_FIELD_WIDTH
];
1135 String
s(buff
, sizeof(buff
),&my_charset_bin
);
1138 info
->str
->append(',');
1141 info
->str
->append('\'');
1142 s
.set(*element
, current_thd
->charset());
1143 info
->str
->append(s
);
1144 info
->str
->append('\'');
1146 } // collect_longlong
1149 int collect_ulonglong(ulonglong
*element
,
1150 element_count count
__attribute__((unused
)),
1153 char buff
[MAX_FIELD_WIDTH
];
1154 String
s(buff
, sizeof(buff
),&my_charset_bin
);
1157 info
->str
->append(',');
1160 info
->str
->append('\'');
1161 s
.set(*element
, current_thd
->charset());
1162 info
->str
->append(s
);
1163 info
->str
->append('\'');
1165 } // collect_ulonglong
1168 bool analyse::change_columns(List
<Item
> &field_list
)
1172 func_items
[0] = new Item_proc_string("Field_name", 255);
1173 func_items
[1] = new Item_proc_string("Min_value", 255);
1174 func_items
[1]->maybe_null
= 1;
1175 func_items
[2] = new Item_proc_string("Max_value", 255);
1176 func_items
[2]->maybe_null
= 1;
1177 func_items
[3] = new Item_proc_int("Min_length");
1178 func_items
[4] = new Item_proc_int("Max_length");
1179 func_items
[5] = new Item_proc_int("Empties_or_zeros");
1180 func_items
[6] = new Item_proc_int("Nulls");
1181 func_items
[7] = new Item_proc_string("Avg_value_or_avg_length", 255);
1182 func_items
[8] = new Item_proc_string("Std", 255);
1183 func_items
[8]->maybe_null
= 1;
1184 func_items
[9] = new Item_proc_string("Optimal_fieldtype",
1185 max(64, output_str_length
));
1187 for (uint i
= 0; i
< array_elements(func_items
); i
++)
1188 field_list
.push_back(func_items
[i
]);
1189 result_fields
= field_list
;
1191 } // analyse::change_columns
1193 int compare_double(const double *s
, const double *t
)
1195 return ((*s
< *t
) ? -1 : *s
> *t
? 1 : 0);
1196 } /* compare_double */
1198 int compare_longlong(const longlong
*s
, const longlong
*t
)
1200 return ((*s
< *t
) ? -1 : *s
> *t
? 1 : 0);
1201 } /* compare_longlong */
1203 int compare_ulonglong(const ulonglong
*s
, const ulonglong
*t
)
1205 return ((*s
< *t
) ? -1 : *s
> *t
? 1 : 0);
1206 } /* compare_ulonglong */
1209 uint
check_ulonglong(const char *str
, uint length
)
1211 const char *long_str
= "2147483647", *ulonglong_str
= "18446744073709551615";
1212 const uint long_len
= 10, ulonglong_len
= 20;
1214 while (*str
== '0' && length
)
1218 if (length
< long_len
)
1221 uint smaller
, bigger
;
1224 if (length
== long_len
)
1230 else if (length
> ulonglong_len
)
1234 cmp
= ulonglong_str
;
1236 bigger
= DECIMAL_NUM
;
1238 while (*cmp
&& *cmp
++ == *str
++) ;
1239 return ((uchar
) str
[-1] <= (uchar
) cmp
[-1]) ? smaller
: bigger
;
1240 } /* check_ulonlong */
1244 Quote special characters in a string.
1247 append_escaped(to_str, from_str)
1248 to_str (in) A pointer to a String.
1249 from_str (to) A pointer to an allocated string
1252 append_escaped() takes a String type variable, where it appends
1253 escaped the second argument. Only characters that require escaping
1261 bool append_escaped(String
*to_str
, String
*from_str
)
1263 char *from
, *end
, c
;
1265 if (to_str
->realloc(to_str
->length() + from_str
->length()))
1268 from
= (char*) from_str
->ptr();
1269 end
= from
+ from_str
->length();
1270 for (; from
< end
; from
++)
1284 goto normal_character
;
1286 if (to_str
->append('\\'))
1290 if (to_str
->append(c
))