home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / sql / item_timefunc.cpp < prev    next >
C/C++ Source or Header  |  2000-09-12  |  27KB  |  1,120 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  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 as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  7.    
  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.
  12.    
  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16.  
  17.  
  18. /* This file defines all time functions */
  19.  
  20. #ifdef __GNUC__
  21. #pragma implementation                // gcc: Class implementation
  22. #endif
  23.  
  24. #include "mysql_priv.h"
  25. #include <m_ctype.h>
  26. #include <time.h>
  27.  
  28. /*
  29. ** Todo: Move month and days to language files
  30. */
  31.  
  32. static String month_names[] = { "January", "February", "March", "April",
  33.                    "May", "June", "July", "August",
  34.                    "September", "October", "November", "December" };
  35. static String day_names[] = { "Monday", "Tuesday", "Wednesday",
  36.                  "Thursday", "Friday", "Saturday" ,"Sunday" };
  37.  
  38. /*
  39. ** Get a array of positive numbers from a string object.
  40. ** Each number is separated by 1 non digit character
  41. ** Return error if there is too many numbers.
  42. ** If there is too few numbers, assume that the numbers are left out
  43. ** from the high end. This allows one to give:
  44. ** DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds.
  45. */
  46.  
  47. bool get_interval_info(const char *str,uint length,uint count,
  48.                long *values)
  49. {
  50.   const char *end=str+length;
  51.   uint i;
  52.   while (str != end && !isdigit(*str))
  53.     str++;
  54.  
  55.   for (i=0 ; i < count ; i++)
  56.   {
  57.     long value;
  58.     for (value=0; str != end && isdigit(*str) ; str++)
  59.       value=value*10L + (long) (*str - '0');
  60.     values[i]= value;
  61.     while (str != end && !isdigit(*str))
  62.       str++;
  63.     if (str == end && i != count-1)
  64.     {
  65.       i++;
  66.       /* Change values[0...i-1] -> values[0...count-1] */
  67.       bmove_upp((char*) (values+count), (char*) (values+i),
  68.         sizeof(long)*i);
  69.       bzero((char*) values, sizeof(long)*(count-i));
  70.       break;
  71.     }
  72.   }
  73.   return (str != end);
  74. }
  75.  
  76. longlong Item_func_period_add::val_int()
  77. {
  78.   ulong period=(ulong) args[0]->val_int();
  79.   int months=(int) args[1]->val_int();
  80.  
  81.   if ((null_value=args[0]->null_value || args[1]->null_value) ||
  82.       period == 0L)
  83.     return 0; /* purecov: inspected */
  84.   return (longlong)
  85.     convert_month_to_period((uint) ((int) convert_period_to_month(period)+
  86.                     months));
  87. }
  88.  
  89.  
  90. longlong Item_func_period_diff::val_int()
  91. {
  92.   ulong period1=(ulong) args[0]->val_int();
  93.   ulong period2=(ulong) args[1]->val_int();
  94.  
  95.   if ((null_value=args[0]->null_value || args[1]->null_value))
  96.     return 0; /* purecov: inspected */
  97.   return (longlong) ((long) convert_period_to_month(period1)-
  98.              (long) convert_period_to_month(period2));
  99. }
  100.  
  101.  
  102.  
  103. longlong Item_func_to_days::val_int()
  104. {
  105.   TIME ltime;
  106.   if (get_arg0_date(<ime,0))
  107.     return 0;
  108.   return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day);
  109. }
  110.  
  111. longlong Item_func_dayofyear::val_int()
  112. {
  113.   TIME ltime;
  114.   if (get_arg0_date(<ime,0))
  115.     return 0;
  116.   return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day) -
  117.     calc_daynr(ltime.year,1,1) + 1;
  118. }
  119.  
  120. longlong Item_func_dayofmonth::val_int()
  121. {
  122.   TIME ltime;
  123.   (void) get_arg0_date(<ime,1);
  124.   return (longlong) ltime.day;
  125. }
  126.  
  127. longlong Item_func_month::val_int()
  128. {
  129.   TIME ltime;
  130.   (void) get_arg0_date(<ime,1);
  131.   return (longlong) ltime.month;
  132. }
  133.  
  134. String* Item_func_monthname::val_str(String* str)
  135. {
  136.   uint month=(uint) Item_func_month::val_int();
  137.   if (!month)                    // This is also true for NULL
  138.     return (String*) 0;
  139.   return &month_names[month-1];
  140. }
  141.  
  142. // Returns the quarter of the year
  143.  
  144. longlong Item_func_quarter::val_int()
  145. {
  146.   TIME ltime;
  147.   (void) get_arg0_date(<ime,1);
  148.   return (longlong) ((ltime.month+2)/3);
  149. }
  150.  
  151. longlong Item_func_hour::val_int()
  152. {
  153.   TIME ltime;
  154.   (void) get_arg0_time(<ime);
  155.   return ltime.hour;
  156. }
  157.  
  158. longlong Item_func_minute::val_int()
  159. {
  160.   TIME ltime;
  161.   (void) get_arg0_time(<ime);
  162.   return ltime.minute;
  163. }
  164. // Returns the second in time_exp in the range of 0 - 59
  165.  
  166. longlong Item_func_second::val_int()
  167. {
  168.   TIME ltime;
  169.   (void) get_arg0_time(<ime);
  170.   return ltime.second;
  171. }
  172.  
  173.  
  174. // Returns the week of year in the range of 0 - 53
  175.  
  176. longlong Item_func_week::val_int()
  177. {
  178.   uint year;
  179.   TIME ltime;
  180.   if (get_arg0_date(<ime,0))
  181.     return 0;
  182.   return (longlong) calc_week(<ime, 0, args[1]->val_int() == 0, &year);
  183. }
  184.  
  185.  
  186. longlong Item_func_yearweek::val_int()
  187. {
  188.   uint year,week;
  189.   TIME ltime;
  190.   if (get_arg0_date(<ime,0))
  191.     return 0;
  192.   week=calc_week(<ime, 1, args[1]->val_int() == 0, &year);
  193.   return week+year*100;
  194. }
  195.  
  196.  
  197. /* weekday() has a automatic to_days() on item */
  198.  
  199. longlong Item_func_weekday::val_int()
  200. {
  201.   ulong tmp_value=(ulong) args[0]->val_int();
  202.   if ((null_value=(args[0]->null_value || !tmp_value)))
  203.     return 0; /* purecov: inspected */
  204.  
  205.   return (longlong) calc_weekday(tmp_value,odbc_type)+test(odbc_type);
  206. }
  207.  
  208. String* Item_func_dayname::val_str(String* str)
  209. {
  210.   uint weekday=(uint) val_int();        // Always Item_func_daynr()
  211.   if (null_value)
  212.     return (String*) 0;
  213.   return &day_names[weekday];
  214. }
  215.  
  216.  
  217. longlong Item_func_year::val_int()
  218. {
  219.   TIME ltime;
  220.   (void) get_arg0_date(<ime,1);
  221.   return (longlong) ltime.year;
  222. }
  223.  
  224.  
  225. longlong Item_func_unix_timestamp::val_int()
  226. {
  227.   if (arg_count == 0)
  228.     return (longlong) current_thd->query_start();
  229.   if (args[0]->type() == FIELD_ITEM)
  230.   {                        // Optimize timestamp field
  231.     Field *field=((Item_field*) args[0])->field;
  232.     if (field->type() == FIELD_TYPE_TIMESTAMP)
  233.       return ((Field_timestamp*) field)->get_timestamp();
  234.   }
  235.   String *str=args[0]->val_str(&value);
  236.   if ((null_value=args[0]->null_value))
  237.   {
  238.     return 0; /* purecov: inspected */
  239.   }
  240.   return (longlong) str_to_timestamp(str->ptr(),str->length());
  241. }
  242.  
  243.  
  244. longlong Item_func_time_to_sec::val_int()
  245. {
  246.   TIME ltime;
  247.   (void) get_arg0_time(<ime);
  248.   return ltime.hour*3600L+ltime.minute*60+ltime.second;
  249. }
  250.  
  251.  
  252. /*
  253. ** Convert a string to a interval value
  254. ** To make code easy, allow interval objects without separators.
  255. */
  256.  
  257. static bool get_interval_value(Item *args,interval_type int_type,
  258.                    String *str_value, INTERVAL *t)
  259. {
  260.   long array[4],value;
  261.   const char *str;
  262.   uint32 length;
  263.   LINT_INIT(value);  LINT_INIT(str); LINT_INIT(length);
  264.  
  265.   bzero((char*) t,sizeof(*t));
  266.   if ((int) int_type <= INTERVAL_SECOND)
  267.   {
  268.     value=(long) args->val_int();
  269.     if (args->null_value)
  270.       return 1;
  271.     if (value < 0)
  272.     {
  273.       t->neg=1;
  274.       value= -value;
  275.     }
  276.   }
  277.   else
  278.   {
  279.     String *res;
  280.     if (!(res=args->val_str(str_value)))
  281.       return (1);
  282.  
  283.     /* record negative intervalls in t->neg */
  284.     str=res->ptr();
  285.     const char *end=str+res->length();
  286.     while (str != end && isspace(*str))
  287.       str++;
  288.     if (str != end && *str == '-')
  289.     {
  290.       t->neg=1;
  291.       str++;
  292.     }
  293.     length=(uint32) (end-str);        // Set up pointers to new str
  294.   }
  295.  
  296.   switch (int_type) {
  297.   case INTERVAL_YEAR:
  298.     t->year=value;
  299.     break;
  300.   case INTERVAL_MONTH:
  301.     t->month=value;
  302.     break;
  303.   case INTERVAL_DAY:
  304.     t->day=value;
  305.     break;
  306.   case INTERVAL_HOUR:
  307.     t->hour=value;
  308.     break;
  309.   case INTERVAL_MINUTE:
  310.     t->minute=value;
  311.     break;
  312.   case INTERVAL_SECOND:
  313.     t->second=value;
  314.     break;
  315.   case INTERVAL_YEAR_MONTH:            // Allow YEAR-MONTH YYYYYMM
  316.     if (get_interval_info(str,length,2,array))
  317.       return (1);
  318.     t->year=array[0];
  319.     t->month=array[1];
  320.     break;
  321.   case INTERVAL_DAY_HOUR:
  322.     if (get_interval_info(str,length,2,array))
  323.       return (1);
  324.     t->day=array[0];
  325.     t->hour=array[1];
  326.     break;
  327.   case INTERVAL_DAY_MINUTE:
  328.     if (get_interval_info(str,length,3,array))
  329.       return (1);
  330.     t->day=array[0];
  331.     t->hour=array[1];
  332.     t->minute=array[2];
  333.     break;
  334.   case INTERVAL_DAY_SECOND:
  335.     if (get_interval_info(str,length,4,array))
  336.       return (1);
  337.     t->day=array[0];
  338.     t->hour=array[1];
  339.     t->minute=array[2];
  340.     t->second=array[3];
  341.     break;
  342.   case INTERVAL_HOUR_MINUTE:
  343.     if (get_interval_info(str,length,2,array))
  344.       return (1);
  345.     t->hour=array[0];
  346.     t->minute=array[1];
  347.     break;
  348.   case INTERVAL_HOUR_SECOND:
  349.     if (get_interval_info(str,length,3,array))
  350.       return (1);
  351.     t->hour=array[0];
  352.     t->minute=array[1];
  353.     t->second=array[2];
  354.     break;
  355.   case INTERVAL_MINUTE_SECOND:
  356.     if (get_interval_info(str,length,2,array))
  357.       return (1);
  358.     t->minute=array[0];
  359.     t->second=array[1];
  360.     break;
  361.   }
  362.   return 0;
  363. }
  364.  
  365.  
  366. String *Item_date::val_str(String *str)
  367. {
  368.   ulong value=(ulong) val_int();
  369.   if (null_value)
  370.     return (String*) 0;
  371.   if (!value)                    // zero daynr
  372.   {
  373.     str->copy("0000-00-00");
  374.     return str;
  375.   }
  376.   if (str->alloc(11))
  377.     return &empty_string;            /* purecov: inspected */
  378.   sprintf((char*) str->ptr(),"%04d-%02d-%02d",
  379.       (int) (value/10000L) % 10000,
  380.       (int) (value/100)%100,
  381.       (int) (value%100));
  382.   str->length(10);
  383.   return str;
  384. }
  385.  
  386.  
  387. bool Item_date::save_in_field(Field *field)
  388. {
  389.   TIME ltime;
  390.   timestamp_type t_type=TIMESTAMP_FULL;
  391.   if (get_date(<ime,1))
  392.   {
  393.     if (null_value)
  394.       return set_field_to_null(field);
  395.     t_type=TIMESTAMP_NONE;            // Error
  396.   }
  397.   field->set_notnull();
  398.   field->store_time(<ime,t_type);
  399.   return 0;
  400. }
  401.  
  402.  
  403. longlong Item_func_from_days::val_int()
  404. {
  405.   longlong value=args[0]->val_int();
  406.   if ((null_value=args[0]->null_value))
  407.     return 0; /* purecov: inspected */
  408.  
  409.   uint year,month,day;
  410.   get_date_from_daynr((long) value,&year,&month,&day);
  411.   return (longlong) (year*10000L+month*100+day);
  412. }
  413.  
  414.  
  415. void Item_func_curdate::fix_length_and_dec()
  416. {
  417.   struct tm tm_tmp,*start;
  418.   time_t query_start=current_thd->query_start();
  419.   decimals=0; max_length=10;
  420.   localtime_r(&query_start,&tm_tmp);
  421.   start=&tm_tmp;
  422.   value=(longlong) ((ulong) ((uint) start->tm_year+1900)*10000L+
  423.             ((uint) start->tm_mon+1)*100+
  424.             (uint) start->tm_mday);
  425.   /* For getdate */
  426.   ltime.year=    start->tm_year+1900;
  427.   ltime.month=    start->tm_mon+1;
  428.   ltime.day=    start->tm_mday;
  429.   ltime.hour=    0;
  430.   ltime.minute=    0;
  431.   ltime.second=    0;
  432.   ltime.second_part=0;
  433.   ltime.neg=0;
  434.   ltime.time_type=TIMESTAMP_DATE;
  435. }
  436.  
  437. bool Item_func_curdate::get_date(TIME *res,
  438.                  bool fuzzy_date __attribute__((unused)))
  439. {
  440.   *res=ltime;
  441.   return 0;
  442. }
  443.  
  444. void Item_func_curtime::fix_length_and_dec()
  445. {
  446.   struct tm tm_tmp,*start;
  447.   time_t query_start=current_thd->query_start();
  448.   decimals=0; max_length=8;
  449.   localtime_r(&query_start,&tm_tmp);
  450.   start=&tm_tmp;
  451.   value=(longlong) ((ulong) ((uint) start->tm_hour)*10000L+
  452.             (ulong) (((uint) start->tm_min)*100L+
  453.                  (uint) start->tm_sec));
  454.   sprintf(buff,"%02d:%02d:%02d",
  455.       (int) start->tm_hour,
  456.       (int) start->tm_min,
  457.       (int) start->tm_sec);
  458.   buff_length=(uint) strlen(buff);
  459. }
  460.  
  461. void Item_func_now::fix_length_and_dec()
  462. {
  463.   struct tm tm_tmp,*start;
  464.   time_t query_start=current_thd->query_start();
  465.   decimals=0; max_length=19;
  466.   localtime_r(&query_start,&tm_tmp);
  467.   start=&tm_tmp;
  468.   value=((longlong) ((ulong) ((uint) start->tm_year+1900)*10000L+
  469.              (((uint) start->tm_mon+1)*100+
  470.               (uint) start->tm_mday))*(longlong) 1000000L+
  471.      (longlong) ((ulong) ((uint) start->tm_hour)*10000L+
  472.              (ulong) (((uint) start->tm_min)*100L+
  473.                 (uint) start->tm_sec)));
  474.   sprintf(buff,"%04d-%02d-%02d %02d:%02d:%02d",
  475.       ((int) (start->tm_year+1900)) % 10000,
  476.       (int) start->tm_mon+1,
  477.       (int) start->tm_mday,
  478.       (int) start->tm_hour,
  479.       (int) start->tm_min,
  480.       (int) start->tm_sec);
  481.   buff_length=(uint) strlen(buff);
  482.   /* For getdate */
  483.   ltime.year=    start->tm_year+1900;
  484.   ltime.month=    start->tm_mon+1;
  485.   ltime.day=    start->tm_mday;
  486.   ltime.hour=    start->tm_hour;
  487.   ltime.minute=    start->tm_min;
  488.   ltime.second=    start->tm_sec;
  489.   ltime.second_part=0;
  490.   ltime.neg=0;
  491.   ltime.time_type=TIMESTAMP_FULL;
  492. }
  493.  
  494. bool Item_func_now::get_date(TIME *res,
  495.                  bool fuzzy_date __attribute__((unused)))
  496. {
  497.   *res=ltime;
  498.   return 0;
  499. }
  500.  
  501.  
  502. bool Item_func_now::save_in_field(Field *to)
  503. {
  504.   to->set_notnull();
  505.   to->store_time(<ime,TIMESTAMP_FULL);
  506.   return 0;
  507. }
  508.  
  509.  
  510. String *Item_func_sec_to_time::val_str(String *str)
  511. {
  512.   char buff[23];
  513.   const char *sign="";
  514.   longlong seconds=(longlong) args[0]->val_int();
  515.   if ((null_value=args[0]->null_value))
  516.     return (String*) 0;
  517.   if (seconds < 0)
  518.   {
  519.     seconds= -seconds;
  520.     sign= "-";
  521.   }
  522.   uint sec= (uint) (seconds % 3600);
  523.   sprintf(buff,"%s%02lu:%02u:%02u",sign,(long) (seconds/3600),
  524.       sec/60, sec % 60);
  525.   str->copy(buff,(uint) strlen(buff));
  526.   return str;
  527. }
  528.  
  529.  
  530. longlong Item_func_sec_to_time::val_int()
  531. {
  532.   longlong seconds=args[0]->val_int();
  533.   longlong sign=1;
  534.   if ((null_value=args[0]->null_value))
  535.     return 0;
  536.   if (seconds < 0)
  537.   {
  538.     seconds= -seconds;
  539.     sign= -1;
  540.   }
  541.   return sign*((seconds / 3600)*10000+((seconds/60) % 60)*100+ (seconds % 60));
  542. }
  543.  
  544.  
  545. void Item_func_date_format::fix_length_and_dec()
  546. {
  547.   decimals=0;
  548.   if (args[1]->type() == STRING_ITEM)
  549.   {                        // Optimize the normal case
  550.     fixed_length=1;
  551.     max_length=format_length(((Item_string*) args[1])->const_string());
  552.   }
  553.   else
  554.   {
  555.     fixed_length=0;
  556.     max_length=args[1]->max_length*10;
  557.     set_if_smaller(max_length,MAX_BLOB_WIDTH);
  558.   }
  559.   maybe_null=1;                    // If wrong date
  560. }
  561.  
  562.  
  563. uint Item_func_date_format::format_length(const String *format)
  564. {
  565.   uint size=0;
  566.   const char *ptr=format->ptr();
  567.   const char *end=ptr+format->length();
  568.  
  569.   for (; ptr != end ; ptr++)
  570.   {
  571.     if (*ptr != '%' || ptr == end-1)
  572.       size++;
  573.     else
  574.     {
  575.       switch(*++ptr) {
  576.       case 'M': /* month, textual */
  577.       case 'W': /* day (of the week), textual */
  578.     size += 9;
  579.     break;
  580.       case 'D': /* day (of the month), numeric plus english suffix */
  581.       case 'Y': /* year, numeric, 4 digits */
  582.       case 'x': /* Year, used with 'v' */
  583.       case 'X': /* Year, used with 'v, where week starts with Monday' */
  584.     size += 4;
  585.     break;
  586.       case 'a': /* locale's abbreviated weekday name (Sun..Sat) */
  587.       case 'b': /* locale's abbreviated month name (Jan.Dec) */
  588.       case 'j': /* day of year (001..366) */
  589.     size += 3;
  590.     break;
  591.       case 'U': /* week (00..52) */
  592.       case 'u': /* week (00..52), where week starts with Monday */
  593.       case 'V': /* week 1..53 used with 'x' */
  594.       case 'v': /* week 1..53 used with 'x', where week starts with Monday */
  595.       case 'H': /* hour (00..23) */
  596.       case 'y': /* year, numeric, 2 digits */
  597.       case 'm': /* month, numeric */
  598.       case 'd': /* day (of the month), numeric */
  599.       case 'h': /* hour (01..12) */
  600.       case 'I': /* --||-- */
  601.       case 'i': /* minutes, numeric */
  602.       case 'k': /* hour ( 0..23) */
  603.       case 'l': /* hour ( 1..12) */
  604.       case 'p': /* locale's AM or PM */
  605.       case 'S': /* second (00..61) */
  606.       case 's': /* seconds, numeric */
  607.       case 'c': /* month (0..12) */
  608.       case 'e': /* day (0..31) */
  609.     size += 2;
  610.     break;
  611.       case 'r': /* time, 12-hour (hh:mm:ss [AP]M) */
  612.     size += 11;
  613.     break;
  614.       case 'T': /* time, 24-hour (hh:mm:ss) */
  615.     size += 8;
  616.     break;
  617.       case 'w': /* day (of the week), numeric */
  618.       case '%':
  619.       default:
  620.     size++;
  621.     break;
  622.       }
  623.     }
  624.   }
  625.   return size;
  626. }
  627.  
  628.  
  629. String *Item_func_date_format::val_str(String *str)
  630. {
  631.   String *format;
  632.   TIME l_time;
  633.   char intbuff[15];
  634.   uint size,weekday;
  635.  
  636.   if (!date_or_time)
  637.   {
  638.     if (get_arg0_date(&l_time,1))
  639.       return 0;
  640.   }
  641.   else
  642.   {
  643.     String *res;
  644.     if (!(res=args[0]->val_str(str)))
  645.     {
  646.       null_value=1;
  647.       return 0;
  648.     }
  649.     if (str_to_time(res->ptr(),res->length(),&l_time))
  650.     {
  651.       null_value=1;
  652.       return 0;
  653.     }
  654.     l_time.year=l_time.month=l_time.day=0;
  655.     null_value=0;
  656.   }
  657.  
  658.   if (!(format = args[1]->val_str(str)) || !format->length())
  659.   {
  660.     null_value=1;
  661.     return 0;
  662.   }
  663.  
  664.   if (fixed_length)
  665.     size=max_length;
  666.   else
  667.     size=format_length(format);
  668.   if (format == str)
  669.     str=&str_value;                // Save result here
  670.   if (str->alloc(size))
  671.   {
  672.     null_value=1;
  673.     return 0;
  674.   }
  675.   str->length(0);
  676.  
  677.   /* Create the result string */
  678.   const char *ptr=format->ptr();
  679.   const char *end=ptr+format->length();
  680.   for ( ; ptr != end ; ptr++)
  681.   {
  682.     if (*ptr != '%' || ptr+1 == end)
  683.       str->append(*ptr);
  684.     else
  685.     {
  686.       switch (*++ptr) {
  687.       case 'M':
  688.     if(!l_time.month)
  689.     {
  690.       null_value=1;
  691.       return 0;
  692.     }
  693.     str->append(month_names[l_time.month-1]);
  694.     break;
  695.       case 'b':
  696.     if(!l_time.month)
  697.     {
  698.       null_value=1;
  699.       return 0;
  700.     }
  701.     str->append(month_names[l_time.month-1].ptr(),3);
  702.     break;
  703.       case 'W':
  704.     if(date_or_time)
  705.     {
  706.       null_value=1;
  707.       return 0;
  708.     }
  709.     weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),0);
  710.     str->append(day_names[weekday]);
  711.     break;
  712.       case 'a':
  713.     if(date_or_time)
  714.     {
  715.       null_value=1;
  716.       return 0;
  717.     }
  718.     weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),0);
  719.     str->append(day_names[weekday].ptr(),3);
  720.     break;
  721.       case 'D':
  722.     if(date_or_time)
  723.     {
  724.       null_value=1;
  725.       return 0;
  726.     }
  727.     sprintf(intbuff,"%d",l_time.day);
  728.     str->append(intbuff);
  729.     if (l_time.day >= 10 &&  l_time.day <= 19)
  730.       str->append("th");
  731.     else
  732.     {
  733.       switch (l_time.day %10)
  734.       {
  735.       case 1:
  736.         str->append("st");
  737.         break;
  738.       case 2:
  739.         str->append("nd");
  740.         break;
  741.       case 3:
  742.         str->append("rd");
  743.         break;
  744.       default:
  745.         str->append("th");
  746.         break;
  747.       }
  748.     }
  749.     break;
  750.       case 'Y':
  751.     sprintf(intbuff,"%04d",l_time.year);
  752.     str->append(intbuff);
  753.     break;
  754.       case 'y':
  755.     sprintf(intbuff,"%02d",l_time.year%100);
  756.     str->append(intbuff);
  757.     break;
  758.       case 'm':
  759.     sprintf(intbuff,"%02d",l_time.month);
  760.     str->append(intbuff);
  761.     break;
  762.       case 'c':
  763.     sprintf(intbuff,"%d",l_time.month);
  764.     str->append(intbuff);
  765.     break;
  766.       case 'd':
  767.     sprintf(intbuff,"%02d",l_time.day);
  768.     str->append(intbuff);
  769.     break;
  770.       case 'e':
  771.     sprintf(intbuff,"%d",l_time.day);
  772.     str->append(intbuff);
  773.     break;
  774.       case 'H':
  775.     sprintf(intbuff,"%02d",l_time.hour);
  776.     str->append(intbuff);
  777.     break;
  778.       case 'h':
  779.       case 'I':
  780.     sprintf(intbuff,"%02d", (l_time.hour+11)%12+1);
  781.     str->append(intbuff);
  782.     break;
  783.       case 'i':                    /* minutes */
  784.     sprintf(intbuff,"%02d",l_time.minute);
  785.     str->append(intbuff);
  786.     break;
  787.       case 'j':
  788.     if(date_or_time)
  789.     {
  790.       null_value=1;
  791.       return 0;
  792.     }
  793.     sprintf(intbuff,"%03d",
  794.         (int) (calc_daynr(l_time.year,l_time.month,l_time.day) -
  795.                calc_daynr(l_time.year,1,1)) + 1);
  796.     str->append(intbuff);
  797.     break;
  798.       case 'k':
  799.     sprintf(intbuff,"%d",l_time.hour);
  800.     str->append(intbuff);
  801.     break;
  802.       case 'l':
  803.     sprintf(intbuff,"%d", (l_time.hour+11)%12+1);
  804.     str->append(intbuff);
  805.     break;
  806.       case 'p':
  807.     str->append(l_time.hour < 12 ? "AM" : "PM");
  808.     break;
  809.       case 'r':
  810.     sprintf(intbuff,(l_time.hour < 12) ? "%02d:%02d:%02d AM" :
  811.         "%02d:%02d:%02d PM",(l_time.hour+11)%12+1,l_time.minute,
  812.         l_time.second);
  813.     str->append(intbuff);
  814.     break;
  815.       case 'S':
  816.       case 's':
  817.     sprintf(intbuff,"%02d",l_time.second);
  818.     str->append(intbuff);
  819.     break;
  820.       case 'T':
  821.     sprintf(intbuff,"%02d:%02d:%02d",l_time.hour,l_time.minute,l_time.second);
  822.     str->append(intbuff);
  823.     break;
  824.       case 'U':
  825.       case 'u':
  826.       {
  827.     uint year;
  828.     sprintf(intbuff,"%02d",calc_week(&l_time, 0, (*ptr) == 'U', &year));
  829.     str->append(intbuff);
  830.       }
  831.       break;
  832.       case 'v':
  833.       case 'V':
  834.       {
  835.     uint year;
  836.     sprintf(intbuff,"%02d",calc_week(&l_time, 1, (*ptr) == 'V', &year));
  837.     str->append(intbuff);
  838.       }
  839.       break;
  840.       case 'x':
  841.       case 'X':
  842.       {
  843.     uint year;
  844.     (void) calc_week(&l_time, 1, (*ptr) == 'X', &year);
  845.     sprintf(intbuff,"%04d",year);
  846.     str->append(intbuff);
  847.       }
  848.       break;
  849.       case 'w':
  850.     weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),1);
  851.     sprintf(intbuff,"%01d",weekday);
  852.     str->append(intbuff);
  853.     break;
  854.       default:
  855.     str->append(*ptr);
  856.     break;
  857.       }
  858.     }
  859.   }
  860.   return str;
  861. }
  862.  
  863.  
  864. String *Item_func_from_unixtime::val_str(String *str)
  865. {
  866.   struct tm tm_tmp,*start;
  867.   time_t tmp=(time_t) args[0]->val_int();
  868.   if ((null_value=args[0]->null_value))
  869.     return 0;
  870.   localtime_r(&tmp,&tm_tmp);
  871.   start=&tm_tmp;
  872.   if (str->alloc(20))
  873.     return str;                    /* purecov: inspected */
  874.   sprintf((char*) str->ptr(),"%04d-%02d-%02d %02d:%02d:%02d",
  875.       (int) start->tm_year+1900,
  876.       (int) start->tm_mon+1,
  877.       (int) start->tm_mday,
  878.       (int) start->tm_hour,
  879.       (int) start->tm_min,
  880.       (int) start->tm_sec);
  881.   str->length(19);
  882.   return str;
  883. }
  884.  
  885.  
  886. longlong Item_func_from_unixtime::val_int()
  887. {
  888.   time_t tmp=(time_t) (ulong) args[0]->val_int();
  889.   if ((null_value=args[0]->null_value))
  890.     return 0;
  891.   struct tm tm_tmp,*start;
  892.   localtime_r(&tmp,&tm_tmp);
  893.   start= &tm_tmp;
  894.   return ((longlong) ((ulong) ((uint) start->tm_year+1900)*10000L+
  895.               (((uint) start->tm_mon+1)*100+
  896.                (uint) start->tm_mday))*LL(1000000)+
  897.       (longlong) ((ulong) ((uint) start->tm_hour)*10000L+
  898.               (ulong) (((uint) start->tm_min)*100L+
  899.                    (uint) start->tm_sec)));
  900. }
  901.  
  902. bool Item_func_from_unixtime::get_date(TIME *ltime,
  903.                        bool fuzzy_date __attribute__((unused)))
  904. {
  905.   time_t tmp=(time_t) (ulong) args[0]->val_int();
  906.   if ((null_value=args[0]->null_value))
  907.     return 1;
  908.   struct tm tm_tmp,*start;
  909.   localtime_r(&tmp,&tm_tmp);
  910.   start= &tm_tmp;
  911.   ltime->year=    start->tm_year+1900;
  912.   ltime->month=    start->tm_mon+1;
  913.   ltime->day=    start->tm_mday;
  914.   ltime->hour=    start->tm_hour;
  915.   ltime->minute=start->tm_min;
  916.   ltime->second=start->tm_sec;
  917.   ltime->second_part=0;
  918.   ltime->neg=0;
  919.   return 0;
  920. }
  921.  
  922.   /* Here arg[1] is a Item_interval object */
  923.  
  924. bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
  925. {
  926.   long period,sign;
  927.   INTERVAL interval;
  928.  
  929.   if (args[0]->get_date(ltime,0) ||
  930.       get_interval_value(args[1],int_type,&value,&interval))
  931.     goto null_date;
  932.   sign= (interval.neg ? -1 : 1);
  933.   if (date_sub_interval)
  934.     sign = -sign;
  935.  
  936.   null_value=0;
  937.   switch (int_type) {
  938.   case INTERVAL_SECOND:
  939.   case INTERVAL_MINUTE:
  940.   case INTERVAL_HOUR:
  941.   case INTERVAL_MINUTE_SECOND:
  942.   case INTERVAL_HOUR_SECOND:
  943.   case INTERVAL_HOUR_MINUTE:
  944.   case INTERVAL_DAY_SECOND:
  945.   case INTERVAL_DAY_MINUTE:
  946.   case INTERVAL_DAY_HOUR:
  947.     long sec,days,daynr;
  948.     ltime->time_type=TIMESTAMP_FULL;        // Return full date
  949.  
  950.     sec=((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+
  951.      ltime->second +
  952.      sign*(interval.day*3600*24L +
  953.            interval.hour*3600+interval.minute*60+interval.second));
  954.     days=sec/(3600*24L); sec=sec-days*3600*24L;
  955.     if (sec < 0)
  956.     {
  957.       days--;
  958.       sec+=3600*24L;
  959.     }
  960.     ltime->second=sec % 60;
  961.     ltime->minute=sec/60 % 60;
  962.     ltime->hour=sec/3600;
  963.     daynr= calc_daynr(ltime->year,ltime->month,1) + days;
  964.     get_date_from_daynr(daynr,<ime->year,<ime->month,<ime->day);
  965.     if (daynr < 0 || daynr >= 3652424) // Day number from year 0 to 9999-12-31
  966.       goto null_date;
  967.     break;
  968.   case INTERVAL_DAY:
  969.     period= calc_daynr(ltime->year,ltime->month,ltime->day) +
  970.       sign*interval.day;
  971.     if (period < 0 || period >= 3652424) // Daynumber from year 0 to 9999-12-31
  972.       goto null_date;
  973.     get_date_from_daynr((long) period,<ime->year,<ime->month,<ime->day);
  974.     break;
  975.   case INTERVAL_YEAR:
  976.     ltime->year += sign*interval.year;
  977.     if ((int) ltime->year < 0 || ltime->year >= 10000L)
  978.       goto null_date;
  979.     if (ltime->month == 2 && ltime->day == 29 &&
  980.     calc_days_in_year(ltime->year) != 366)
  981.       ltime->day=28;                // Was leap-year
  982.     break;
  983.   case INTERVAL_YEAR_MONTH:
  984.   case INTERVAL_MONTH:
  985.     period= (ltime->year*12 + sign*interval.year*12 +
  986.          ltime->month-1 + sign*interval.month);
  987.     if (period < 0 || period >= 120000L)
  988.       goto null_date;
  989.     ltime->year= (uint) (period / 12);
  990.     ltime->month= (uint) (period % 12L)+1;
  991.     /* Adjust day if the new month doesn't have enough days */
  992.     if (ltime->day > days_in_month[ltime->month-1])
  993.     {
  994.       ltime->day = days_in_month[ltime->month-1];
  995.       if (ltime->month == 2 && calc_days_in_year(ltime->year) == 366)
  996.     ltime->day++;                // Leap-year
  997.     }
  998.     break;
  999.   default:
  1000.     goto null_date;
  1001.   }
  1002.   return 0;                    // Ok
  1003.  
  1004.  null_date:
  1005.   return (null_value=1);
  1006. }
  1007.  
  1008.  
  1009. String *Item_date_add_interval::val_str(String *str)
  1010. {
  1011.   TIME ltime;
  1012.  
  1013.   if (Item_date_add_interval::get_date(<ime,0))
  1014.     return 0;
  1015.   if (ltime.time_type == TIMESTAMP_DATE)
  1016.   {
  1017.     if (str->alloc(11))
  1018.       goto null_date;
  1019.     sprintf((char*) str->ptr(),"%04d-%02d-%02d",
  1020.         ltime.year,ltime.month,ltime.day);
  1021.     str->length(10);
  1022.   }
  1023.   else
  1024.   {
  1025.     if (str->alloc(20))
  1026.       goto null_date;
  1027.     sprintf((char*) str->ptr(),"%04d-%02d-%02d %02d:%02d:%02d",
  1028.         ltime.year,ltime.month,ltime.day,
  1029.         ltime.hour,ltime.minute,ltime.second);
  1030.     str->length(19);
  1031.   }
  1032.   return str;
  1033.  
  1034.  null_date:
  1035.   null_value=1;
  1036.   return 0;
  1037. }
  1038.  
  1039. longlong Item_date_add_interval::val_int()
  1040. {
  1041.   TIME ltime;
  1042.   if (Item_date_add_interval::get_date(<ime,0))
  1043.     return (longlong) 0;
  1044.   return ((longlong) (((ulong) ltime.year)*10000L+
  1045.               (((uint) ltime.month)*100+
  1046.                (uint) ltime.day))*(longlong) 1000000L+
  1047.       (longlong) ((ulong) ((uint) ltime.hour)*10000L+
  1048.               (ulong) (((uint)ltime.minute)*100L+
  1049.                    (uint) ltime.second)));
  1050. }
  1051.  
  1052. void Item_extract::fix_length_and_dec()
  1053. {
  1054.   value.alloc(32);                // alloc buffer
  1055.  
  1056.   maybe_null=1;                    // If wrong date
  1057.   switch (int_type) {
  1058.   case INTERVAL_YEAR:        max_length=4; date_value=1; break;
  1059.   case INTERVAL_YEAR_MONTH:    max_length=6; date_value=1; break;
  1060.   case INTERVAL_MONTH:        max_length=2; date_value=1; break;
  1061.   case INTERVAL_DAY:        max_length=2; date_value=1; break;
  1062.   case INTERVAL_DAY_HOUR:    max_length=9; date_value=0; break;
  1063.   case INTERVAL_DAY_MINUTE:    max_length=11; date_value=0; break;
  1064.   case INTERVAL_DAY_SECOND:    max_length=13; date_value=0; break;
  1065.   case INTERVAL_HOUR:        max_length=2; date_value=0; break;
  1066.   case INTERVAL_HOUR_MINUTE:    max_length=4; date_value=0; break;
  1067.   case INTERVAL_HOUR_SECOND:    max_length=6; date_value=0; break;
  1068.   case INTERVAL_MINUTE:        max_length=2; date_value=0; break;
  1069.   case INTERVAL_MINUTE_SECOND:    max_length=4; date_value=0; break;
  1070.   case INTERVAL_SECOND:        max_length=2; date_value=0; break;
  1071.   }
  1072. }
  1073.  
  1074.  
  1075. longlong Item_extract::val_int()
  1076. {
  1077.   TIME ltime;
  1078.   long neg;
  1079.   if (date_value)
  1080.   {
  1081.     if (get_arg0_date(<ime,1))
  1082.       return 0;
  1083.     neg=1;
  1084.   }
  1085.   else
  1086.   {
  1087.     String *res= args[0]->val_str(&value);
  1088.     if (!res || str_to_time(res->ptr(),res->length(),<ime))
  1089.     {
  1090.       null_value=1;
  1091.       return 0;
  1092.     }
  1093.     neg= ltime.neg ? -1 : 1;
  1094.     null_value=0;
  1095.   }
  1096.  
  1097.   switch (int_type) {
  1098.   case INTERVAL_YEAR:        return ltime.year;
  1099.   case INTERVAL_YEAR_MONTH:    return ltime.year*100L+ltime.month;
  1100.   case INTERVAL_MONTH:        return ltime.month;
  1101.   case INTERVAL_DAY:        return ltime.day;
  1102.   case INTERVAL_DAY_HOUR:    return (long) (ltime.day*100L+ltime.hour)*neg;
  1103.   case INTERVAL_DAY_MINUTE:    return (long) (ltime.day*10000L+
  1104.                            ltime.hour*100L+
  1105.                            ltime.minute)*neg;
  1106.   case INTERVAL_DAY_SECOND:     return ((longlong) ltime.day*1000000L+
  1107.                      (longlong) (ltime.hour*10000L+
  1108.                              ltime.minute*100+
  1109.                              ltime.second))*neg;
  1110.   case INTERVAL_HOUR:        return (long) ltime.hour*neg;
  1111.   case INTERVAL_HOUR_MINUTE:    return (long) (ltime.hour*100+ltime.minute)*neg;
  1112.   case INTERVAL_HOUR_SECOND:    return (long) (ltime.hour*10000+ltime.minute*100+
  1113.                            ltime.second)*neg;
  1114.   case INTERVAL_MINUTE:        return (long) ltime.minute*neg;
  1115.   case INTERVAL_MINUTE_SECOND:    return (long) (ltime.minute*100+ltime.second)*neg;
  1116.   case INTERVAL_SECOND:        return (long) ltime.second*neg;
  1117.   }
  1118.   return 0;                    // Impossible
  1119. }
  1120.