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