~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2005-2006 MySQL 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; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
16
#include <drizzled/server_includes.h>
1 by brian
clean slate
17
#include <time.h>
549 by Monty Taylor
Took gettext.h out of header files.
18
#include <drizzled/error.h>
1 by brian
clean slate
19
20
21
/**
22
  report result of decimal operation.
23
24
  @param result  decimal library return code (E_DEC_* see include/decimal.h)
25
26
  @todo
27
    Fix error messages
28
29
  @return
30
    result
31
*/
32
33
int decimal_operation_results(int result)
34
{
35
  switch (result) {
36
  case E_DEC_OK:
37
    break;
38
  case E_DEC_TRUNCATED:
520.1.22 by Brian Aker
Second pass of thd cleanup
39
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
40
			ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED),
1 by brian
clean slate
41
			"", (long)-1);
42
    break;
43
  case E_DEC_OVERFLOW:
520.1.22 by Brian Aker
Second pass of thd cleanup
44
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1 by brian
clean slate
45
                        ER_TRUNCATED_WRONG_VALUE,
46
                        ER(ER_TRUNCATED_WRONG_VALUE),
47
			"DECIMAL", "");
48
    break;
49
  case E_DEC_DIV_ZERO:
520.1.22 by Brian Aker
Second pass of thd cleanup
50
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1 by brian
clean slate
51
			ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO));
52
    break;
53
  case E_DEC_BAD_NUM:
520.1.22 by Brian Aker
Second pass of thd cleanup
54
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1 by brian
clean slate
55
			ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
56
			ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
57
			"decimal", "", "", (long)-1);
58
    break;
59
  case E_DEC_OOM:
60
    my_error(ER_OUT_OF_RESOURCES, MYF(0));
61
    break;
62
  default:
51.1.33 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
63
    assert(0);
1 by brian
clean slate
64
  }
65
  return result;
66
}
67
68
69
/**
70
  @brief Converting decimal to string
71
72
  @details Convert given my_decimal to String; allocate buffer as needed.
73
74
  @param[in]   mask        what problems to warn on (mask of E_DEC_* values)
75
  @param[in]   d           the decimal to print
76
  @param[in]   fixed_prec  overall number of digits if ZEROFILL, 0 otherwise
77
  @param[in]   fixed_dec   number of decimal places (if fixed_prec != 0)
78
  @param[in]   filler      what char to pad with (ZEROFILL et al.)
79
  @param[out]  *str        where to store the resulting string
80
81
  @return error coce
82
    @retval E_DEC_OK
83
    @retval E_DEC_TRUNCATED
84
    @retval E_DEC_OVERFLOW
85
    @retval E_DEC_OOM
86
*/
87
482 by Brian Aker
Remove uint.
88
int my_decimal2string(uint32_t mask, const my_decimal *d,
89
                      uint32_t fixed_prec, uint32_t fixed_dec,
1 by brian
clean slate
90
                      char filler, String *str)
91
{
92
  /*
93
    Calculate the size of the string: For DECIMAL(a,b), fixed_prec==a
94
    holds true iff the type is also ZEROFILL, which in turn implies
95
    UNSIGNED. Hence the buffer for a ZEROFILLed value is the length
96
    the user requested, plus one for a possible decimal point, plus
97
    one if the user only wanted decimal places, but we force a leading
98
    zero on them. Because the type is implicitly UNSIGNED, we do not
99
    need to reserve a character for the sign. For all other cases,
100
    fixed_prec will be 0, and my_decimal_string_length() will be called
101
    instead to calculate the required size of the buffer.
102
  */
103
  int length= (fixed_prec
104
               ? (fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1)
105
               : my_decimal_string_length(d));
106
  int result;
107
  if (str->alloc(length))
108
    return check_result(mask, E_DEC_OOM);
109
  result= decimal2string((decimal_t*) d, (char*) str->ptr(),
110
                         &length, (int)fixed_prec, fixed_dec,
111
                         filler);
112
  str->length(length);
113
  return check_result(mask, result);
114
}
115
116
117
/*
118
  Convert from decimal to binary representation
119
120
  SYNOPSIS
121
    my_decimal2binary()
122
    mask        error processing mask
123
    d           number for conversion
124
    bin         pointer to buffer where to write result
125
    prec        overall number of decimal digits
126
    scale       number of decimal digits after decimal point
127
128
  NOTE
129
    Before conversion we round number if it need but produce truncation
130
    error in this case
131
132
  RETURN
133
    E_DEC_OK
134
    E_DEC_TRUNCATED
135
    E_DEC_OVERFLOW
136
*/
137
482 by Brian Aker
Remove uint.
138
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
1 by brian
clean slate
139
		      int scale)
140
{
141
  int err1= E_DEC_OK, err2;
142
  my_decimal rounded;
143
  my_decimal2decimal(d, &rounded);
144
  rounded.frac= decimal_actual_fraction(&rounded);
145
  if (scale < rounded.frac)
146
  {
147
    err1= E_DEC_TRUNCATED;
148
    /* decimal_round can return only E_DEC_TRUNCATED */
149
    decimal_round(&rounded, &rounded, scale, HALF_UP);
150
  }
151
  err2= decimal2bin(&rounded, bin, prec, scale);
152
  if (!err2)
153
    err2= err1;
154
  return check_result(mask, err2);
155
}
156
157
158
/*
159
  Convert string for decimal when string can be in some multibyte charset
160
161
  SYNOPSIS
162
    str2my_decimal()
163
    mask            error processing mask
164
    from            string to process
165
    length          length of given string
166
    charset         charset of given string
167
    decimal_value   buffer for result storing
168
169
  RESULT
170
    E_DEC_OK
171
    E_DEC_TRUNCATED
172
    E_DEC_OVERFLOW
173
    E_DEC_BAD_NUM
174
    E_DEC_OOM
175
*/
176
482 by Brian Aker
Remove uint.
177
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
178
                   const CHARSET_INFO * charset, my_decimal *decimal_value)
1 by brian
clean slate
179
{
180
  char *end, *from_end;
181
  int err;
182
  char buff[STRING_BUFFER_USUAL_SIZE];
183
  String tmp(buff, sizeof(buff), &my_charset_bin);
184
  if (charset->mbminlen > 1)
185
  {
482 by Brian Aker
Remove uint.
186
    uint32_t dummy_errors;
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
187
    tmp.copy(from, length, charset, &my_charset_utf8_general_ci, &dummy_errors);
1 by brian
clean slate
188
    from= tmp.ptr();
189
    length=  tmp.length();
190
    charset= &my_charset_bin;
191
  }
192
  from_end= end= (char*) from+length;
193
  err= string2decimal((char *)from, (decimal_t*) decimal_value, &end);
194
  if (end != from_end && !err)
195
  {
196
    /* Give warning if there is something other than end space */
197
    for ( ; end < from_end; end++)
198
    {
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
199
      if (!my_isspace(&my_charset_utf8_general_ci, *end))
1 by brian
clean slate
200
      {
201
        err= E_DEC_TRUNCATED;
202
        break;
203
      }
204
    }
205
  }
206
  check_result_and_overflow(mask, err, decimal_value);
207
  return err;
208
}
209
210
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
211
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec)
1 by brian
clean slate
212
{
152 by Brian Aker
longlong replacement
213
  int64_t date;
1 by brian
clean slate
214
  date = (ltime->year*100L + ltime->month)*100L + ltime->day;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
215
  if (ltime->time_type > DRIZZLE_TIMESTAMP_DATE)
1 by brian
clean slate
216
    date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second;
51.1.33 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
217
  if (int2my_decimal(E_DEC_FATAL_ERROR, date, false, dec))
1 by brian
clean slate
218
    return dec;
219
  if (ltime->second_part)
220
  {
221
    dec->buf[(dec->intg-1) / 9 + 1]= ltime->second_part * 1000;
222
    dec->frac= 6;
223
  }
224
  return dec;
225
}
226
227
482 by Brian Aker
Remove uint.
228
void my_decimal_trim(uint32_t *precision, uint32_t *scale)
1 by brian
clean slate
229
{
230
  if (!(*precision) && !(*scale))
231
  {
232
    *precision= 10;
233
    *scale= 0;
234
    return;
235
  }
236
}