~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item/timefunc.cc

  • Committer: Brian Aker
  • Date: 2008-11-25 02:31:14 UTC
  • Revision ID: brian@tangent.org-20081125023114-2f7sx8fye2jytgyw
Removed dead event structure pieces from replication.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#include <drizzled/sql_locale.h>
36
36
#include <drizzled/session.h>
37
37
 
38
 
/** Day number for Dec 31st, 9999. */
39
 
#define MAX_DAY_NUMBER 3652424L
40
 
 
41
 
/**
42
 
  @todo
43
 
  OPTIMIZATION
44
 
  - Replace the switch with a function that should be called for each
45
 
  date type.
46
 
  - Remove sprintf and opencode the conversion, like we do in
47
 
  Field_datetime.
48
 
 
49
 
  The reason for this functions existence is that as we don't have a
50
 
  way to know if a datetime/time value has microseconds in them
51
 
  we are now only adding microseconds to the output if the
52
 
  value has microseconds.
53
 
 
54
 
  We can't use a standard make_date_time() for this as we don't know
55
 
  if someone will use %f in the format specifier in which case we would get
56
 
  the microseconds twice.
57
 
*/
58
 
 
59
 
static bool make_datetime(date_time_format_types format, DRIZZLE_TIME *ltime,
60
 
                          String *str)
61
 
{
62
 
  char *buff;
63
 
  const CHARSET_INFO * const cs= &my_charset_bin;
64
 
  uint32_t length= MAX_DATE_STRING_REP_LENGTH;
65
 
 
66
 
  if (str->alloc(length))
67
 
    return 1;
68
 
  buff= (char*) str->ptr();
69
 
 
70
 
  switch (format) {
71
 
  case TIME_ONLY:
72
 
    length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d",
73
 
                               ltime->neg ? "-" : "",
74
 
                               ltime->hour, ltime->minute, ltime->second);
75
 
    break;
76
 
  case TIME_MICROSECOND:
77
 
    length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d.%06ld",
78
 
                               ltime->neg ? "-" : "",
79
 
                               ltime->hour, ltime->minute, ltime->second,
80
 
                               ltime->second_part);
81
 
    break;
82
 
  case DATE_ONLY:
83
 
    length= cs->cset->snprintf(cs, buff, length, "%04d-%02d-%02d",
84
 
                               ltime->year, ltime->month, ltime->day);
85
 
    break;
86
 
  case DATE_TIME:
87
 
    length= cs->cset->snprintf(cs, buff, length,
88
 
                               "%04d-%02d-%02d %02d:%02d:%02d",
89
 
                               ltime->year, ltime->month, ltime->day,
90
 
                               ltime->hour, ltime->minute, ltime->second);
91
 
    break;
92
 
  case DATE_TIME_MICROSECOND:
93
 
    length= cs->cset->snprintf(cs, buff, length,
94
 
                               "%04d-%02d-%02d %02d:%02d:%02d.%06ld",
95
 
                               ltime->year, ltime->month, ltime->day,
96
 
                               ltime->hour, ltime->minute, ltime->second,
97
 
                               ltime->second_part);
98
 
    break;
99
 
  }
100
 
 
101
 
  str->length(length);
102
 
  str->set_charset(cs);
103
 
  return 0;
104
 
}
105
 
 
106
 
 
107
 
/*
108
 
  Wrapper over make_datetime() with validation of the input DRIZZLE_TIME value
109
 
 
110
 
  NOTE
111
 
    see make_datetime() for more information
112
 
 
113
 
  RETURN
114
 
    1    if there was an error during converion
115
 
    0    otherwise
116
 
*/
117
 
 
118
 
static bool make_datetime_with_warn(date_time_format_types format, DRIZZLE_TIME *ltime,
119
 
                                    String *str)
120
 
{
121
 
  int warning= 0;
122
 
 
123
 
  if (make_datetime(format, ltime, str))
124
 
    return 1;
125
 
  if (check_time_range(ltime, &warning))
126
 
    return 1;
127
 
  if (!warning)
128
 
    return 0;
129
 
 
130
 
  make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
131
 
                               str->ptr(), str->length(),
132
 
                               DRIZZLE_TIMESTAMP_TIME, NULL);
133
 
  return make_datetime(format, ltime, str);
134
 
}
135
 
 
136
 
 
137
 
/*
138
 
  Wrapper over make_time() with validation of the input DRIZZLE_TIME value
139
 
 
140
 
  NOTE
141
 
    see make_time() for more info
142
 
 
143
 
  RETURN
144
 
    1    if there was an error during conversion
145
 
    0    otherwise
146
 
*/
147
 
 
148
 
static bool make_time_with_warn(const DATE_TIME_FORMAT *format,
149
 
                                DRIZZLE_TIME *l_time, String *str)
150
 
{
151
 
  int warning= 0;
152
 
  make_time(format, l_time, str);
153
 
  if (check_time_range(l_time, &warning))
154
 
    return 1;
155
 
  if (warning)
156
 
  {
157
 
    make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
158
 
                                 str->ptr(), str->length(),
159
 
                                 DRIZZLE_TIMESTAMP_TIME, NULL);
160
 
    make_time(format, l_time, str);
161
 
  }
162
 
 
163
 
  return 0;
164
 
}
165
 
 
166
 
 
167
 
/*
168
 
  Convert seconds to DRIZZLE_TIME value with overflow checking
169
 
 
170
 
  SYNOPSIS:
171
 
    sec_to_time()
172
 
    seconds          number of seconds
173
 
    unsigned_flag    1, if 'seconds' is unsigned, 0, otherwise
174
 
    ltime            output DRIZZLE_TIME value
175
 
 
176
 
  DESCRIPTION
177
 
    If the 'seconds' argument is inside DRIZZLE_TIME data range, convert it to a
178
 
    corresponding value.
179
 
    Otherwise, truncate the resulting value to the nearest endpoint, and
180
 
    produce a warning message.
181
 
 
182
 
  RETURN
183
 
    1                if the value was truncated during conversion
184
 
    0                otherwise
185
 
*/
186
 
  
187
 
static bool sec_to_time(int64_t seconds, bool unsigned_flag, DRIZZLE_TIME *ltime)
188
 
{
189
 
  uint32_t sec;
190
 
 
191
 
  memset(ltime, 0, sizeof(*ltime));
192
 
  
193
 
  if (seconds < 0)
194
 
  {
195
 
    ltime->neg= 1;
196
 
    if (seconds < -3020399)
197
 
      goto overflow;
198
 
    seconds= -seconds;
199
 
  }
200
 
  else if (seconds > 3020399)
201
 
    goto overflow;
202
 
  
203
 
  sec= (uint) ((uint64_t) seconds % 3600);
204
 
  ltime->hour= (uint) (seconds/3600);
205
 
  ltime->minute= sec/60;
206
 
  ltime->second= sec % 60;
207
 
 
208
 
  return 0;
209
 
 
210
 
overflow:
211
 
  ltime->hour= TIME_MAX_HOUR;
212
 
  ltime->minute= TIME_MAX_MINUTE;
213
 
  ltime->second= TIME_MAX_SECOND;
214
 
 
215
 
  char buf[22];
216
 
  int len= (int)(int64_t10_to_str(seconds, buf, unsigned_flag ? 10 : -10)
217
 
                 - buf);
218
 
  make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
219
 
                               buf, len, DRIZZLE_TIMESTAMP_TIME,
220
 
                               NULL);
221
 
  
222
 
  return 1;
223
 
}
224
 
 
225
 
 
226
38
/*
227
39
  Date formats corresponding to compound %r and %T conversion specifiers
228
40
 
1051
863
}
1052
864
 
1053
865
 
1054
 
String *Item_func_sec_to_time::val_str(String *str)
1055
 
{
1056
 
  assert(fixed == 1);
1057
 
  DRIZZLE_TIME ltime;
1058
 
  int64_t arg_val= args[0]->val_int(); 
1059
 
 
1060
 
  if ((null_value=args[0]->null_value) ||
1061
 
      str->alloc(MAX_DATE_STRING_REP_LENGTH))
1062
 
  {
1063
 
    null_value= 1;
1064
 
    return (String*) 0;
1065
 
  }
1066
 
 
1067
 
  sec_to_time(arg_val, args[0]->unsigned_flag, &ltime);
1068
 
  
1069
 
  make_time((DATE_TIME_FORMAT *) 0, &ltime, str);
1070
 
  return str;
1071
 
}
1072
 
 
1073
 
 
1074
 
int64_t Item_func_sec_to_time::val_int()
1075
 
{
1076
 
  assert(fixed == 1);
1077
 
  DRIZZLE_TIME ltime;
1078
 
  int64_t arg_val= args[0]->val_int(); 
1079
 
  
1080
 
  if ((null_value=args[0]->null_value))
1081
 
    return 0;
1082
 
 
1083
 
  sec_to_time(arg_val, args[0]->unsigned_flag, &ltime);
1084
 
 
1085
 
  return (ltime.neg ? -1 : 1) *
1086
 
    ((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
1087
 
}
1088
 
 
1089
 
 
1090
 
void Item_func_date_format::fix_length_and_dec()
1091
 
{
1092
 
  Session* session= current_session;
1093
 
  /*
1094
 
    Must use this_item() in case it's a local SP variable
1095
 
    (for ->max_length and ->str_value)
1096
 
  */
1097
 
  Item *arg1= args[1]->this_item();
1098
 
 
1099
 
  decimals=0;
1100
 
  const CHARSET_INFO * const cs= session->variables.collation_connection;
1101
 
  uint32_t repertoire= arg1->collation.repertoire;
1102
 
  if (!session->variables.lc_time_names->is_ascii)
1103
 
    repertoire|= MY_REPERTOIRE_EXTENDED;
1104
 
  collation.set(cs, arg1->collation.derivation, repertoire);
1105
 
  if (arg1->type() == STRING_ITEM)
1106
 
  {                                             // Optimize the normal case
1107
 
    fixed_length=1;
1108
 
    max_length= format_length(&arg1->str_value) *
1109
 
                collation.collation->mbmaxlen;
1110
 
  }
1111
 
  else
1112
 
  {
1113
 
    fixed_length=0;
1114
 
    max_length=cmin(arg1->max_length,(uint32_t) MAX_BLOB_WIDTH) * 10 *
1115
 
                   collation.collation->mbmaxlen;
1116
 
    set_if_smaller(max_length,MAX_BLOB_WIDTH);
1117
 
  }
1118
 
  maybe_null=1;                                 // If wrong date
1119
 
}
1120
 
 
1121
 
 
1122
 
bool Item_func_date_format::eq(const Item *item, bool binary_cmp) const
1123
 
{
1124
 
  Item_func_date_format *item_func;
1125
 
 
1126
 
  if (item->type() != FUNC_ITEM)
1127
 
    return 0;
1128
 
  if (func_name() != ((Item_func*) item)->func_name())
1129
 
    return 0;
1130
 
  if (this == item)
1131
 
    return 1;
1132
 
  item_func= (Item_func_date_format*) item;
1133
 
  if (!args[0]->eq(item_func->args[0], binary_cmp))
1134
 
    return 0;
1135
 
  /*
1136
 
    We must compare format string case sensitive.
1137
 
    This needed because format modifiers with different case,
1138
 
    for example %m and %M, have different meaning.
1139
 
  */
1140
 
  if (!args[1]->eq(item_func->args[1], 1))
1141
 
    return 0;
1142
 
  return 1;
1143
 
}
1144
 
 
1145
 
 
1146
 
 
1147
 
uint32_t Item_func_date_format::format_length(const String *format)
1148
 
{
1149
 
  uint32_t size=0;
1150
 
  const char *ptr=format->ptr();
1151
 
  const char *end=ptr+format->length();
1152
 
 
1153
 
  for (; ptr != end ; ptr++)
1154
 
  {
1155
 
    if (*ptr != '%' || ptr == end-1)
1156
 
      size++;
1157
 
    else
1158
 
    {
1159
 
      switch(*++ptr) {
1160
 
      case 'M': /* month, textual */
1161
 
      case 'W': /* day (of the week), textual */
1162
 
        size += 64; /* large for UTF8 locale data */
1163
 
        break;
1164
 
      case 'D': /* day (of the month), numeric plus english suffix */
1165
 
      case 'Y': /* year, numeric, 4 digits */
1166
 
      case 'x': /* Year, used with 'v' */
1167
 
      case 'X': /* Year, used with 'v, where week starts with Monday' */
1168
 
        size += 4;
1169
 
        break;
1170
 
      case 'a': /* locale's abbreviated weekday name (Sun..Sat) */
1171
 
      case 'b': /* locale's abbreviated month name (Jan.Dec) */
1172
 
        size += 32; /* large for UTF8 locale data */
1173
 
        break;
1174
 
      case 'j': /* day of year (001..366) */
1175
 
        size += 3;
1176
 
        break;
1177
 
      case 'U': /* week (00..52) */
1178
 
      case 'u': /* week (00..52), where week starts with Monday */
1179
 
      case 'V': /* week 1..53 used with 'x' */
1180
 
      case 'v': /* week 1..53 used with 'x', where week starts with Monday */
1181
 
      case 'y': /* year, numeric, 2 digits */
1182
 
      case 'm': /* month, numeric */
1183
 
      case 'd': /* day (of the month), numeric */
1184
 
      case 'h': /* hour (01..12) */
1185
 
      case 'I': /* --||-- */
1186
 
      case 'i': /* minutes, numeric */
1187
 
      case 'l': /* hour ( 1..12) */
1188
 
      case 'p': /* locale's AM or PM */
1189
 
      case 'S': /* second (00..61) */
1190
 
      case 's': /* seconds, numeric */
1191
 
      case 'c': /* month (0..12) */
1192
 
      case 'e': /* day (0..31) */
1193
 
        size += 2;
1194
 
        break;
1195
 
      case 'k': /* hour ( 0..23) */
1196
 
      case 'H': /* hour (00..23; value > 23 OK, padding always 2-digit) */
1197
 
        size += 7; /* docs allow > 23, range depends on sizeof(unsigned int) */
1198
 
        break;
1199
 
      case 'r': /* time, 12-hour (hh:mm:ss [AP]M) */
1200
 
        size += 11;
1201
 
        break;
1202
 
      case 'T': /* time, 24-hour (hh:mm:ss) */
1203
 
        size += 8;
1204
 
        break;
1205
 
      case 'f': /* microseconds */
1206
 
        size += 6;
1207
 
        break;
1208
 
      case 'w': /* day (of the week), numeric */
1209
 
      case '%':
1210
 
      default:
1211
 
        size++;
1212
 
        break;
1213
 
      }
1214
 
    }
1215
 
  }
1216
 
  return size;
1217
 
}
1218
 
 
1219
 
 
1220
 
String *Item_func_date_format::val_str(String *str)
1221
 
{
1222
 
  String *format;
1223
 
  DRIZZLE_TIME l_time;
1224
 
  uint32_t size;
1225
 
  assert(fixed == 1);
1226
 
 
1227
 
  if (!is_time_format)
1228
 
  {
1229
 
    if (get_arg0_date(&l_time, TIME_FUZZY_DATE))
1230
 
      return 0;
1231
 
  }
1232
 
  else
1233
 
  {
1234
 
    String *res;
1235
 
    if (!(res=args[0]->val_str(str)) ||
1236
 
        (str_to_time_with_warn(res->ptr(), res->length(), &l_time)))
1237
 
      goto null_date;
1238
 
 
1239
 
    l_time.year=l_time.month=l_time.day=0;
1240
 
    null_value=0;
1241
 
  }
1242
 
 
1243
 
  if (!(format = args[1]->val_str(str)) || !format->length())
1244
 
    goto null_date;
1245
 
 
1246
 
  if (fixed_length)
1247
 
    size=max_length;
1248
 
  else
1249
 
    size=format_length(format);
1250
 
 
1251
 
  if (size < MAX_DATE_STRING_REP_LENGTH)
1252
 
    size= MAX_DATE_STRING_REP_LENGTH;
1253
 
 
1254
 
  if (format == str)
1255
 
    str= &value;                                // Save result here
1256
 
  if (str->alloc(size))
1257
 
    goto null_date;
1258
 
 
1259
 
  DATE_TIME_FORMAT date_time_format;
1260
 
  date_time_format.format.str=    (char*) format->ptr();
1261
 
  date_time_format.format.length= format->length(); 
1262
 
 
1263
 
  /* Create the result string */
1264
 
  str->set_charset(collation.collation);
1265
 
  if (!make_date_time(&date_time_format, &l_time,
1266
 
                      is_time_format ? DRIZZLE_TIMESTAMP_TIME :
1267
 
                                       DRIZZLE_TIMESTAMP_DATE,
1268
 
                      str))
1269
 
    return str;
1270
 
 
1271
 
null_date:
1272
 
  null_value=1;
1273
 
  return 0;
1274
 
}
1275
 
 
1276
 
 
1277
 
void Item_func_from_unixtime::fix_length_and_dec()
1278
 
1279
 
  session= current_session;
1280
 
  collation.set(&my_charset_bin);
1281
 
  decimals= DATETIME_DEC;
1282
 
  max_length=MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
1283
 
  maybe_null= 1;
1284
 
  session->time_zone_used= 1;
1285
 
}
1286
 
 
1287
 
 
1288
 
String *Item_func_from_unixtime::val_str(String *str)
1289
 
{
1290
 
  DRIZZLE_TIME time_tmp;
1291
 
 
1292
 
  assert(fixed == 1);
1293
 
 
1294
 
  if (get_date(&time_tmp, 0))
1295
 
    return 0;
1296
 
 
1297
 
  if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
1298
 
  {
1299
 
    null_value= 1;
1300
 
    return 0;
1301
 
  }
1302
 
 
1303
 
  make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str);
1304
 
 
1305
 
  return str;
1306
 
}
1307
 
 
1308
 
 
1309
 
int64_t Item_func_from_unixtime::val_int()
1310
 
{
1311
 
  DRIZZLE_TIME time_tmp;
1312
 
 
1313
 
  assert(fixed == 1);
1314
 
 
1315
 
  if (get_date(&time_tmp, 0))
1316
 
    return 0;
1317
 
 
1318
 
  return (int64_t) TIME_to_uint64_t_datetime(&time_tmp);
1319
 
}
1320
 
 
1321
 
bool Item_func_from_unixtime::get_date(DRIZZLE_TIME *ltime,
1322
 
                                       uint32_t fuzzy_date __attribute__((unused)))
1323
 
{
1324
 
  uint64_t tmp= (uint64_t)(args[0]->val_int());
1325
 
  /*
1326
 
    "tmp > TIMESTAMP_MAX_VALUE" check also covers case of negative
1327
 
    from_unixtime() argument since tmp is unsigned.
1328
 
  */
1329
 
  if ((null_value= (args[0]->null_value || tmp > TIMESTAMP_MAX_VALUE)))
1330
 
    return 1;
1331
 
 
1332
 
  session->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)tmp);
1333
 
 
1334
 
  return 0;
1335
 
}
1336
 
 
1337
 
 
1338
866
void Item_date_add_interval::fix_length_and_dec()
1339
867
{
1340
868
  enum_field_types arg0_field_type;
1865
1393
}
1866
1394
 
1867
1395
/**
1868
 
  MAKEDATE(a,b) is a date function that creates a date value 
1869
 
  from a year and day value.
1870
 
 
1871
 
  NOTES:
1872
 
    As arguments are integers, we can't know if the year is a 2 digit or 4 digit year.
1873
 
    In this case we treat all years < 100 as 2 digit years. Ie, this is not safe
1874
 
    for dates between 0000-01-01 and 0099-12-31
1875
 
*/
1876
 
 
1877
 
String *Item_func_makedate::val_str(String *str)
1878
 
{
1879
 
  assert(fixed == 1);
1880
 
  DRIZZLE_TIME l_time;
1881
 
  long daynr=  (long) args[1]->val_int();
1882
 
  long year= (long) args[0]->val_int();
1883
 
  long days;
1884
 
 
1885
 
  if (args[0]->null_value || args[1]->null_value ||
1886
 
      year < 0 || daynr <= 0)
1887
 
    goto err;
1888
 
 
1889
 
  if (year < 100)
1890
 
    year= year_2000_handling(year);
1891
 
 
1892
 
  days= calc_daynr(year,1,1) + daynr - 1;
1893
 
  /* Day number from year 0 to 9999-12-31 */
1894
 
  if (days >= 0 && days <= MAX_DAY_NUMBER)
1895
 
  {
1896
 
    null_value=0;
1897
 
    get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
1898
 
    if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
1899
 
      goto err;
1900
 
    make_date((DATE_TIME_FORMAT *) 0, &l_time, str);
1901
 
    return str;
1902
 
  }
1903
 
 
1904
 
err:
1905
 
  null_value=1;
1906
 
  return 0;
1907
 
}
1908
 
 
1909
 
 
1910
 
/*
1911
 
  MAKEDATE(a,b) is a date function that creates a date value 
1912
 
  from a year and day value.
1913
 
 
1914
 
  NOTES:
1915
 
    As arguments are integers, we can't know if the year is a 2 digit or 4 digit year.
1916
 
    In this case we treat all years < 100 as 2 digit years. Ie, this is not safe
1917
 
    for dates between 0000-01-01 and 0099-12-31
1918
 
*/
1919
 
 
1920
 
int64_t Item_func_makedate::val_int()
1921
 
{
1922
 
  assert(fixed == 1);
1923
 
  DRIZZLE_TIME l_time;
1924
 
  long daynr=  (long) args[1]->val_int();
1925
 
  long year= (long) args[0]->val_int();
1926
 
  long days;
1927
 
 
1928
 
  if (args[0]->null_value || args[1]->null_value ||
1929
 
      year < 0 || daynr <= 0)
1930
 
    goto err;
1931
 
 
1932
 
  if (year < 100)
1933
 
    year= year_2000_handling(year);
1934
 
 
1935
 
  days= calc_daynr(year,1,1) + daynr - 1;
1936
 
  /* Day number from year 0 to 9999-12-31 */
1937
 
  if (days >= 0 && days < MAX_DAY_NUMBER)
1938
 
  {
1939
 
    null_value=0;
1940
 
    get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
1941
 
    return (int64_t) (l_time.year * 10000L + l_time.month * 100 + l_time.day);
1942
 
  }
1943
 
 
1944
 
err:
1945
 
  null_value= 1;
1946
 
  return 0;
1947
 
}
1948
 
 
1949
 
 
1950
 
void Item_func_add_time::fix_length_and_dec()
1951
 
{
1952
 
  enum_field_types arg0_field_type;
1953
 
  decimals=0;
1954
 
  max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
1955
 
  maybe_null= 1;
1956
 
 
1957
 
  /*
1958
 
    The field type for the result of an Item_func_add_time function is defined
1959
 
    as follows:
1960
 
 
1961
 
    - If first arg is a DRIZZLE_TYPE_DATETIME or DRIZZLE_TYPE_TIMESTAMP 
1962
 
      result is DRIZZLE_TYPE_DATETIME
1963
 
    - If first arg is a DRIZZLE_TYPE_TIME result is DRIZZLE_TYPE_TIME
1964
 
    - Otherwise the result is DRIZZLE_TYPE_VARCHAR
1965
 
  */
1966
 
 
1967
 
  cached_field_type= DRIZZLE_TYPE_VARCHAR;
1968
 
  arg0_field_type= args[0]->field_type();
1969
 
  if (arg0_field_type == DRIZZLE_TYPE_DATE ||
1970
 
      arg0_field_type == DRIZZLE_TYPE_DATETIME ||
1971
 
      arg0_field_type == DRIZZLE_TYPE_TIMESTAMP)
1972
 
    cached_field_type= DRIZZLE_TYPE_DATETIME;
1973
 
  else if (arg0_field_type == DRIZZLE_TYPE_TIME)
1974
 
    cached_field_type= DRIZZLE_TYPE_TIME;
1975
 
}
1976
 
 
1977
 
/**
1978
 
  ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a
1979
 
  time/datetime value 
1980
 
 
1981
 
  t: time_or_datetime_expression
1982
 
  a: time_expression
1983
 
  
1984
 
  Result: Time value or datetime value
1985
 
*/
1986
 
 
1987
 
String *Item_func_add_time::val_str(String *str)
1988
 
{
1989
 
  assert(fixed == 1);
1990
 
  DRIZZLE_TIME l_time1, l_time2, l_time3;
1991
 
  bool is_time= 0;
1992
 
  long days, microseconds;
1993
 
  int64_t seconds;
1994
 
  int l_sign= sign;
1995
 
 
1996
 
  null_value=0;
1997
 
  if (is_date)                        // TIMESTAMP function
1998
 
  {
1999
 
    if (get_arg0_date(&l_time1, TIME_FUZZY_DATE) || 
2000
 
        args[1]->get_time(&l_time2) ||
2001
 
        l_time1.time_type == DRIZZLE_TIMESTAMP_TIME || 
2002
 
        l_time2.time_type != DRIZZLE_TIMESTAMP_TIME)
2003
 
      goto null_date;
2004
 
  }
2005
 
  else                                // ADDTIME function
2006
 
  {
2007
 
    if (args[0]->get_time(&l_time1) || 
2008
 
        args[1]->get_time(&l_time2) ||
2009
 
        l_time2.time_type == DRIZZLE_TIMESTAMP_DATETIME)
2010
 
      goto null_date;
2011
 
    is_time= (l_time1.time_type == DRIZZLE_TIMESTAMP_TIME);
2012
 
  }
2013
 
  if (l_time1.neg != l_time2.neg)
2014
 
    l_sign= -l_sign;
2015
 
  
2016
 
  memset(&l_time3, 0, sizeof(l_time3));
2017
 
  
2018
 
  l_time3.neg= calc_time_diff(&l_time1, &l_time2, -l_sign,
2019
 
                              &seconds, &microseconds);
2020
 
 
2021
 
  /*
2022
 
    If first argument was negative and diff between arguments
2023
 
    is non-zero we need to swap sign to get proper result.
2024
 
  */
2025
 
  if (l_time1.neg && (seconds || microseconds))
2026
 
    l_time3.neg= 1-l_time3.neg;         // Swap sign of result
2027
 
 
2028
 
  if (!is_time && l_time3.neg)
2029
 
    goto null_date;
2030
 
 
2031
 
  days= (long)(seconds/86400L);
2032
 
 
2033
 
  calc_time_from_sec(&l_time3, (long)(seconds%86400L), microseconds);
2034
 
 
2035
 
  if (!is_time)
2036
 
  {
2037
 
    get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
2038
 
    if (l_time3.day &&
2039
 
        !make_datetime(l_time1.second_part || l_time2.second_part ?
2040
 
                       DATE_TIME_MICROSECOND : DATE_TIME,
2041
 
                       &l_time3, str))
2042
 
      return str;
2043
 
    goto null_date;
2044
 
  }
2045
 
  
2046
 
  l_time3.hour+= days*24;
2047
 
  if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
2048
 
                               TIME_MICROSECOND : TIME_ONLY,
2049
 
                               &l_time3, str))
2050
 
    return str;
2051
 
 
2052
 
null_date:
2053
 
  null_value=1;
2054
 
  return 0;
2055
 
}
2056
 
 
2057
 
 
2058
 
void Item_func_add_time::print(String *str, enum_query_type query_type)
2059
 
{
2060
 
  if (is_date)
2061
 
  {
2062
 
    assert(sign > 0);
2063
 
    str->append(STRING_WITH_LEN("timestamp("));
2064
 
  }
2065
 
  else
2066
 
  {
2067
 
    if (sign > 0)
2068
 
      str->append(STRING_WITH_LEN("addtime("));
2069
 
    else
2070
 
      str->append(STRING_WITH_LEN("subtime("));
2071
 
  }
2072
 
  args[0]->print(str, query_type);
2073
 
  str->append(',');
2074
 
  args[1]->print(str, query_type);
2075
 
  str->append(')');
2076
 
}
2077
 
 
2078
 
 
2079
 
/**
2080
 
  TIMEDIFF(t,s) is a time function that calculates the 
2081
 
  time value between a start and end time.
2082
 
 
2083
 
  t and s: time_or_datetime_expression
2084
 
  Result: Time value
2085
 
*/
2086
 
 
2087
 
String *Item_func_timediff::val_str(String *str)
2088
 
{
2089
 
  assert(fixed == 1);
2090
 
  int64_t seconds;
2091
 
  long microseconds;
2092
 
  int l_sign= 1;
2093
 
  DRIZZLE_TIME l_time1 ,l_time2, l_time3;
2094
 
 
2095
 
  null_value= 0;  
2096
 
  if (args[0]->get_time(&l_time1) ||
2097
 
      args[1]->get_time(&l_time2) ||
2098
 
      l_time1.time_type != l_time2.time_type)
2099
 
    goto null_date;
2100
 
 
2101
 
  if (l_time1.neg != l_time2.neg)
2102
 
    l_sign= -l_sign;
2103
 
 
2104
 
  memset(&l_time3, 0, sizeof(l_time3));
2105
 
  
2106
 
  l_time3.neg= calc_time_diff(&l_time1, &l_time2, l_sign,
2107
 
                              &seconds, &microseconds);
2108
 
 
2109
 
  /*
2110
 
    For DRIZZLE_TIMESTAMP_TIME only:
2111
 
      If first argument was negative and diff between arguments
2112
 
      is non-zero we need to swap sign to get proper result.
2113
 
  */
2114
 
  if (l_time1.neg && (seconds || microseconds))
2115
 
    l_time3.neg= 1-l_time3.neg;         // Swap sign of result
2116
 
 
2117
 
  calc_time_from_sec(&l_time3, (long) seconds, microseconds);
2118
 
 
2119
 
  if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
2120
 
                               TIME_MICROSECOND : TIME_ONLY,
2121
 
                               &l_time3, str))
2122
 
    return str;
2123
 
 
2124
 
null_date:
2125
 
  null_value=1;
2126
 
  return 0;
2127
 
}
2128
 
 
2129
 
/**
2130
 
  MAKETIME(h,m,s) is a time function that calculates a time value 
2131
 
  from the total number of hours, minutes, and seconds.
2132
 
  Result: Time value
2133
 
*/
2134
 
 
2135
 
String *Item_func_maketime::val_str(String *str)
2136
 
{
2137
 
  assert(fixed == 1);
2138
 
  DRIZZLE_TIME ltime;
2139
 
  bool overflow= 0;
2140
 
 
2141
 
  int64_t hour=   args[0]->val_int();
2142
 
  int64_t minute= args[1]->val_int();
2143
 
  int64_t second= args[2]->val_int();
2144
 
 
2145
 
  if ((null_value=(args[0]->null_value || 
2146
 
                   args[1]->null_value ||
2147
 
                   args[2]->null_value ||
2148
 
                   minute < 0 || minute > 59 ||
2149
 
                   second < 0 || second > 59 ||
2150
 
                   str->alloc(MAX_DATE_STRING_REP_LENGTH))))
2151
 
    return 0;
2152
 
 
2153
 
  memset(&ltime, 0, sizeof(ltime));
2154
 
  ltime.neg= 0;
2155
 
 
2156
 
  /* Check for integer overflows */
2157
 
  if (hour < 0)
2158
 
    ltime.neg= 1;
2159
 
 
2160
 
  if (-hour > UINT_MAX || hour > UINT_MAX)
2161
 
    overflow= 1;
2162
 
 
2163
 
  if (!overflow)
2164
 
  {
2165
 
    ltime.hour=   (uint) ((hour < 0 ? -hour : hour));
2166
 
    ltime.minute= (uint) minute;
2167
 
    ltime.second= (uint) second;
2168
 
  }
2169
 
  else
2170
 
  {
2171
 
    ltime.hour= TIME_MAX_HOUR;
2172
 
    ltime.minute= TIME_MAX_MINUTE;
2173
 
    ltime.second= TIME_MAX_SECOND;
2174
 
    char buf[28];
2175
 
    char *ptr= int64_t10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10);
2176
 
    int len = (int)(ptr - buf) +
2177
 
      sprintf(ptr, ":%02u:%02u", (uint)minute, (uint)second);
2178
 
    make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
2179
 
                                 buf, len, DRIZZLE_TIMESTAMP_TIME,
2180
 
                                 NULL);
2181
 
  }
2182
 
  
2183
 
  if (make_time_with_warn((DATE_TIME_FORMAT *) 0, &ltime, str))
2184
 
  {
2185
 
    null_value= 1;
2186
 
    return 0;
2187
 
  }
2188
 
  return str;
2189
 
}
2190
 
 
2191
 
 
2192
 
/**
2193
 
  MICROSECOND(a) is a function ( extraction) that extracts the microseconds
2194
 
  from a.
2195
 
 
2196
 
  a: Datetime or time value
2197
 
  Result: int value
2198
 
*/
2199
 
 
2200
 
int64_t Item_func_microsecond::val_int()
2201
 
{
2202
 
  assert(fixed == 1);
2203
 
  DRIZZLE_TIME ltime;
2204
 
  if (!get_arg0_time(&ltime))
2205
 
    return ltime.second_part;
2206
 
  return 0;
2207
 
}
2208
 
 
2209
 
 
2210
 
int64_t Item_func_timestamp_diff::val_int()
2211
 
{
2212
 
  DRIZZLE_TIME ltime1, ltime2;
2213
 
  int64_t seconds;
2214
 
  long microseconds;
2215
 
  long months= 0;
2216
 
  int neg= 1;
2217
 
 
2218
 
  null_value= 0;  
2219
 
  if (args[0]->get_date(&ltime1, TIME_NO_ZERO_DATE) ||
2220
 
      args[1]->get_date(&ltime2, TIME_NO_ZERO_DATE))
2221
 
    goto null_date;
2222
 
 
2223
 
  if (calc_time_diff(&ltime2,&ltime1, 1,
2224
 
                     &seconds, &microseconds))
2225
 
    neg= -1;
2226
 
 
2227
 
  if (int_type == INTERVAL_YEAR ||
2228
 
      int_type == INTERVAL_QUARTER ||
2229
 
      int_type == INTERVAL_MONTH)
2230
 
  {
2231
 
    uint32_t year_beg, year_end, month_beg, month_end, day_beg, day_end;
2232
 
    uint32_t years= 0;
2233
 
    uint32_t second_beg, second_end, microsecond_beg, microsecond_end;
2234
 
 
2235
 
    if (neg == -1)
2236
 
    {
2237
 
      year_beg= ltime2.year;
2238
 
      year_end= ltime1.year;
2239
 
      month_beg= ltime2.month;
2240
 
      month_end= ltime1.month;
2241
 
      day_beg= ltime2.day;
2242
 
      day_end= ltime1.day;
2243
 
      second_beg= ltime2.hour * 3600 + ltime2.minute * 60 + ltime2.second;
2244
 
      second_end= ltime1.hour * 3600 + ltime1.minute * 60 + ltime1.second;
2245
 
      microsecond_beg= ltime2.second_part;
2246
 
      microsecond_end= ltime1.second_part;
2247
 
    }
2248
 
    else
2249
 
    {
2250
 
      year_beg= ltime1.year;
2251
 
      year_end= ltime2.year;
2252
 
      month_beg= ltime1.month;
2253
 
      month_end= ltime2.month;
2254
 
      day_beg= ltime1.day;
2255
 
      day_end= ltime2.day;
2256
 
      second_beg= ltime1.hour * 3600 + ltime1.minute * 60 + ltime1.second;
2257
 
      second_end= ltime2.hour * 3600 + ltime2.minute * 60 + ltime2.second;
2258
 
      microsecond_beg= ltime1.second_part;
2259
 
      microsecond_end= ltime2.second_part;
2260
 
    }
2261
 
 
2262
 
    /* calc years */
2263
 
    years= year_end - year_beg;
2264
 
    if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
2265
 
      years-= 1;
2266
 
 
2267
 
    /* calc months */
2268
 
    months= 12*years;
2269
 
    if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
2270
 
      months+= 12 - (month_beg - month_end);
2271
 
    else
2272
 
      months+= (month_end - month_beg);
2273
 
 
2274
 
    if (day_end < day_beg)
2275
 
      months-= 1;
2276
 
    else if ((day_end == day_beg) &&
2277
 
             ((second_end < second_beg) ||
2278
 
              (second_end == second_beg && microsecond_end < microsecond_beg)))
2279
 
      months-= 1;
2280
 
  }
2281
 
 
2282
 
  switch (int_type) {
2283
 
  case INTERVAL_YEAR:
2284
 
    return months/12*neg;
2285
 
  case INTERVAL_QUARTER:
2286
 
    return months/3*neg;
2287
 
  case INTERVAL_MONTH:
2288
 
    return months*neg;
2289
 
  case INTERVAL_WEEK:          
2290
 
    return seconds/86400L/7L*neg;
2291
 
  case INTERVAL_DAY:            
2292
 
    return seconds/86400L*neg;
2293
 
  case INTERVAL_HOUR:           
2294
 
    return seconds/3600L*neg;
2295
 
  case INTERVAL_MINUTE:         
2296
 
    return seconds/60L*neg;
2297
 
  case INTERVAL_SECOND:         
2298
 
    return seconds*neg;
2299
 
  case INTERVAL_MICROSECOND:
2300
 
    /*
2301
 
      In MySQL difference between any two valid datetime values
2302
 
      in microseconds fits into int64_t.
2303
 
    */
2304
 
    return (seconds*1000000L+microseconds)*neg;
2305
 
  default:
2306
 
    break;
2307
 
  }
2308
 
 
2309
 
null_date:
2310
 
  null_value=1;
2311
 
  return 0;
2312
 
}
2313
 
 
2314
 
 
2315
 
void Item_func_timestamp_diff::print(String *str, enum_query_type query_type)
2316
 
{
2317
 
  str->append(func_name());
2318
 
  str->append('(');
2319
 
 
2320
 
  switch (int_type) {
2321
 
  case INTERVAL_YEAR:
2322
 
    str->append(STRING_WITH_LEN("YEAR"));
2323
 
    break;
2324
 
  case INTERVAL_QUARTER:
2325
 
    str->append(STRING_WITH_LEN("QUARTER"));
2326
 
    break;
2327
 
  case INTERVAL_MONTH:
2328
 
    str->append(STRING_WITH_LEN("MONTH"));
2329
 
    break;
2330
 
  case INTERVAL_WEEK:          
2331
 
    str->append(STRING_WITH_LEN("WEEK"));
2332
 
    break;
2333
 
  case INTERVAL_DAY:            
2334
 
    str->append(STRING_WITH_LEN("DAY"));
2335
 
    break;
2336
 
  case INTERVAL_HOUR:
2337
 
    str->append(STRING_WITH_LEN("HOUR"));
2338
 
    break;
2339
 
  case INTERVAL_MINUTE:         
2340
 
    str->append(STRING_WITH_LEN("MINUTE"));
2341
 
    break;
2342
 
  case INTERVAL_SECOND:
2343
 
    str->append(STRING_WITH_LEN("SECOND"));
2344
 
    break;              
2345
 
  case INTERVAL_MICROSECOND:
2346
 
    str->append(STRING_WITH_LEN("SECOND_FRAC"));
2347
 
    break;
2348
 
  default:
2349
 
    break;
2350
 
  }
2351
 
 
2352
 
  for (uint32_t i=0 ; i < 2 ; i++)
2353
 
  {
2354
 
    str->append(',');
2355
 
    args[i]->print(str, query_type);
2356
 
  }
2357
 
  str->append(')');
2358
 
}
2359
 
 
2360
 
 
2361
 
String *Item_func_get_format::val_str(String *str)
2362
 
{
2363
 
  assert(fixed == 1);
2364
 
  const char *format_name;
2365
 
  KNOWN_DATE_TIME_FORMAT *format;
2366
 
  String *val= args[0]->val_str(str);
2367
 
  ulong val_len;
2368
 
 
2369
 
  if ((null_value= args[0]->null_value))
2370
 
    return 0;    
2371
 
 
2372
 
  val_len= val->length();
2373
 
  for (format= &known_date_time_formats[0];
2374
 
       (format_name= format->format_name);
2375
 
       format++)
2376
 
  {
2377
 
    uint32_t format_name_len;
2378
 
    format_name_len= strlen(format_name);
2379
 
    if (val_len == format_name_len &&
2380
 
        !my_strnncoll(&my_charset_utf8_general_ci, 
2381
 
                      (const unsigned char *) val->ptr(), val_len, 
2382
 
                      (const unsigned char *) format_name, val_len))
2383
 
    {
2384
 
      const char *format_str= get_date_time_format_str(format, type);
2385
 
      str->set(format_str, strlen(format_str), &my_charset_bin);
2386
 
      return str;
2387
 
    }
2388
 
  }
2389
 
 
2390
 
  null_value= 1;
2391
 
  return 0;
2392
 
}
2393
 
 
2394
 
 
2395
 
void Item_func_get_format::print(String *str, enum_query_type query_type)
2396
 
{
2397
 
  str->append(func_name());
2398
 
  str->append('(');
2399
 
 
2400
 
  switch (type) {
2401
 
  case DRIZZLE_TIMESTAMP_DATE:
2402
 
    str->append(STRING_WITH_LEN("DATE, "));
2403
 
    break;
2404
 
  case DRIZZLE_TIMESTAMP_DATETIME:
2405
 
    str->append(STRING_WITH_LEN("DATETIME, "));
2406
 
    break;
2407
 
  case DRIZZLE_TIMESTAMP_TIME:
2408
 
    str->append(STRING_WITH_LEN("TIME, "));
2409
 
    break;
2410
 
  default:
2411
 
    assert(0);
2412
 
  }
2413
 
  args[0]->print(str, query_type);
2414
 
  str->append(')');
2415
 
}
2416
 
 
2417
 
 
2418
 
/**
2419
1396
  Get type of datetime value (DATE/TIME/...) which will be produced
2420
1397
  according to format string.
2421
1398