~drizzle-trunk/drizzle/development

492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2008 Sun Microsystems
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19
20
#include <drizzled/server_includes.h>
21
#include CSTDINT_H
670.1.20 by Monty Taylor
Renamed functions to function... everything else is singular.
22
#include <drizzled/function/set_user_var.h>
23
#include <drizzled/function/update_hash.h>
584.5.1 by Monty Taylor
Removed field includes from field.h.
24
#include <drizzled/field/num.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
25
#include <drizzled/session.h>
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
26
27
/*
28
  When a user variable is updated (in a SET command or a query like
29
  SELECT @a:= ).
30
*/
31
32
bool Item_func_set_user_var::fix_fields(Session *session, Item **ref)
33
{
34
  assert(fixed == 0);
35
  /* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
36
  if (Item_func::fix_fields(session, ref) ||
995 by Brian Aker
Refactor get_variable to session
37
      !(entry= session->getVariable(name, true)))
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
38
    return true;
39
  /*
40
     Remember the last query which updated it, this way a query can later know
41
     if this variable is a constant item in the query (it is if update_query_id
42
     is different from query_id).
43
  */
44
  entry->update_query_id= session->query_id;
45
  /*
46
    As it is wrong and confusing to associate any
47
    character set with NULL, @a should be latin2
48
    after this query sequence:
49
50
      SET @a=_latin2'string';
51
      SET @a=NULL;
52
53
    I.e. the second query should not change the charset
54
    to the current default value, but should keep the
55
    original value assigned during the first query.
56
    In order to do it, we don't copy charset
57
    from the argument if the argument is NULL
58
    and the variable has previously been initialized.
59
  */
60
  null_item= (args[0]->type() == NULL_ITEM);
61
  if (!entry->collation.collation || !null_item)
62
    entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
63
  collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
64
  cached_result_type= args[0]->result_type();
65
  return false;
66
}
67
68
void
69
Item_func_set_user_var::fix_length_and_dec()
70
{
71
  maybe_null=args[0]->maybe_null;
72
  max_length=args[0]->max_length;
73
  decimals=args[0]->decimals;
74
  collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
75
}
76
77
/*
78
  Mark field in read_map
79
80
  NOTES
81
    This is used by filesort to register used fields in a a temporary
82
    column read set or to register used fields in a view
83
*/
84
85
bool Item_func_set_user_var::register_field_in_read_map(unsigned char *arg)
86
{
87
  if (result_field)
88
  {
89
    Table *table= (Table *) arg;
90
    if (result_field->table == table || !table)
1005.2.8 by Monty Taylor
Used API.
91
      result_field->table->setReadSet(result_field->field_index);
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
92
  }
93
  return 0;
94
}
95
96
97
bool
98
Item_func_set_user_var::update_hash(void *ptr, uint32_t length,
99
                                    Item_result res_type,
100
                                    const CHARSET_INFO * const cs, Derivation dv,
101
                                    bool unsigned_arg)
102
{
103
  /*
104
    If we set a variable explicitely to NULL then keep the old
105
    result type of the variable
106
  */
107
  if ((null_value= args[0]->null_value) && null_item)
108
    res_type= entry->type;                      // Don't change type of item
109
  if (::update_hash(entry, (null_value= args[0]->null_value),
110
                    ptr, length, res_type, cs, dv, unsigned_arg))
111
  {
112
    null_value= 1;
113
    return 1;
114
  }
115
  return 0;
116
}
117
118
/**
119
  This functions is invoked on SET \@variable or
120
  \@variable:= expression.
121
122
  Evaluate (and check expression), store results.
123
124
  @note
125
    For now it always return OK. All problem with value evaluating
126
    will be caught by session->is_error() check in sql_set_variables().
127
128
  @retval
129
    false OK.
130
*/
131
132
bool
133
Item_func_set_user_var::check(bool use_result_field)
134
{
135
  if (use_result_field && !result_field)
136
    use_result_field= false;
137
138
  switch (cached_result_type) {
139
  case REAL_RESULT:
140
  {
141
    save_result.vreal= use_result_field ? result_field->val_real() :
142
                        args[0]->val_real();
143
    break;
144
  }
145
  case INT_RESULT:
146
  {
147
    save_result.vint= use_result_field ? result_field->val_int() :
148
                       args[0]->val_int();
149
    unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
150
                    args[0]->unsigned_flag;
151
    break;
152
  }
153
  case STRING_RESULT:
154
  {
155
    save_result.vstr= use_result_field ? result_field->val_str(&value) :
156
                       args[0]->val_str(&value);
157
    break;
158
  }
159
  case DECIMAL_RESULT:
160
  {
161
    save_result.vdec= use_result_field ?
162
                       result_field->val_decimal(&decimal_buff) :
163
                       args[0]->val_decimal(&decimal_buff);
164
    break;
165
  }
166
  case ROW_RESULT:
167
  default:
168
    // This case should never be chosen
169
    assert(0);
170
    break;
171
  }
172
  return(false);
173
}
174
175
/**
176
  This functions is invoked on
177
  SET \@variable or \@variable:= expression.
178
179
  @note
180
    We have to store the expression as such in the variable, independent of
181
    the value method used by the user
182
183
  @retval
184
    0   OK
185
  @retval
186
    1   EOM Error
187
188
*/
189
190
bool
191
Item_func_set_user_var::update()
192
{
193
  bool res= false;
194
195
  switch (cached_result_type) {
196
  case REAL_RESULT:
197
  {
198
    res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
199
                     REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
200
    break;
201
  }
202
  case INT_RESULT:
203
  {
204
    res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
205
                     INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT,
206
                     unsigned_flag);
207
    break;
208
  }
209
  case STRING_RESULT:
210
  {
211
    if (!save_result.vstr)                                      // Null value
212
      res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
213
                       DERIVATION_IMPLICIT, 0);
214
    else
215
      res= update_hash((void*) save_result.vstr->ptr(),
216
                       save_result.vstr->length(), STRING_RESULT,
217
                       save_result.vstr->charset(),
218
                       DERIVATION_IMPLICIT, 0);
219
    break;
220
  }
221
  case DECIMAL_RESULT:
222
  {
223
    if (!save_result.vdec)                                      // Null value
224
      res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
225
                       DERIVATION_IMPLICIT, 0);
226
    else
227
      res= update_hash((void*) save_result.vdec,
228
                       sizeof(my_decimal), DECIMAL_RESULT,
229
                       &my_charset_bin, DERIVATION_IMPLICIT, 0);
230
    break;
231
  }
232
  case ROW_RESULT:
233
  default:
234
    // This case should never be chosen
235
    assert(0);
236
    break;
237
  }
238
  return(res);
239
}
240
241
double Item_func_set_user_var::val_real()
242
{
243
  assert(fixed == 1);
244
  check(0);
245
  update();                                     // Store expression
246
  return entry->val_real(&null_value);
247
}
248
249
int64_t Item_func_set_user_var::val_int()
250
{
251
  assert(fixed == 1);
252
  check(0);
253
  update();                                     // Store expression
254
  return entry->val_int(&null_value);
255
}
256
257
String *Item_func_set_user_var::val_str(String *str)
258
{
259
  assert(fixed == 1);
260
  check(0);
261
  update();                                     // Store expression
262
  return entry->val_str(&null_value, str, decimals);
263
}
264
265
266
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
267
{
268
  assert(fixed == 1);
269
  check(0);
270
  update();                                     // Store expression
271
  return entry->val_decimal(&null_value, val);
272
}
273
274
double Item_func_set_user_var::val_result()
275
{
276
  assert(fixed == 1);
277
  check(true);
278
  update();                                     // Store expression
279
  return entry->val_real(&null_value);
280
}
281
282
int64_t Item_func_set_user_var::val_int_result()
283
{
284
  assert(fixed == 1);
285
  check(true);
286
  update();                                     // Store expression
287
  return entry->val_int(&null_value);
288
}
289
290
String *Item_func_set_user_var::str_result(String *str)
291
{
292
  assert(fixed == 1);
293
  check(true);
294
  update();                                     // Store expression
295
  return entry->val_str(&null_value, str, decimals);
296
}
297
298
299
my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
300
{
301
  assert(fixed == 1);
302
  check(true);
303
  update();                                     // Store expression
304
  return entry->val_decimal(&null_value, val);
305
}
306
307
void Item_func_set_user_var::print(String *str, enum_query_type query_type)
308
{
309
  str->append(STRING_WITH_LEN("(@"));
310
  str->append(name.str, name.length);
311
  str->append(STRING_WITH_LEN(":="));
312
  args[0]->print(str, query_type);
313
  str->append(')');
314
}
315
316
317
void Item_func_set_user_var::print_as_stmt(String *str,
318
                                           enum_query_type query_type)
319
{
320
  str->append(STRING_WITH_LEN("set @"));
321
  str->append(name.str, name.length);
322
  str->append(STRING_WITH_LEN(":="));
323
  args[0]->print(str, query_type);
324
  str->append(')');
325
}
326
327
bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
328
{
329
  if (result_field)
330
  {
331
    check(1);
332
    update();
333
    return protocol->store(result_field);
334
  }
335
  return Item::send(protocol, str_arg);
336
}
337
338
void Item_func_set_user_var::make_field(Send_field *tmp_field)
339
{
340
  if (result_field)
341
  {
342
    result_field->make_field(tmp_field);
343
    assert(tmp_field->table_name != 0);
344
    if (Item::name)
345
      tmp_field->col_name=Item::name;               // Use user supplied name
346
  }
347
  else
348
    Item::make_field(tmp_field);
349
}
350
351
/*
352
  Save the value of a user variable into a field
353
354
  SYNOPSIS
355
    save_in_field()
356
      field           target field to save the value to
357
      no_conversion   flag indicating whether conversions are allowed
358
359
  DESCRIPTION
360
    Save the function value into a field and update the user variable
361
    accordingly. If a result field is defined and the target field doesn't
362
    coincide with it then the value from the result field will be used as
363
    the new value of the user variable.
364
365
    The reason to have this method rather than simply using the result
366
    field in the val_xxx() methods is that the value from the result field
367
    not always can be used when the result field is defined.
368
    Let's consider the following cases:
369
    1) when filling a tmp table the result field is defined but the value of it
370
    is undefined because it has to be produced yet. Thus we can't use it.
371
    2) on execution of an INSERT ... SELECT statement the save_in_field()
372
    function will be called to fill the data in the new record. If the SELECT
373
    part uses a tmp table then the result field is defined and should be
374
    used in order to get the correct result.
375
376
    The difference between the SET_USER_VAR function and regular functions
377
    like CONCAT is that the Item_func objects for the regular functions are
378
    replaced by Item_field objects after the values of these functions have
379
    been stored in a tmp table. Yet an object of the Item_field class cannot
380
    be used to update a user variable.
381
    Due to this we have to handle the result field in a special way here and
382
    in the Item_func_set_user_var::send() function.
383
384
  RETURN VALUES
385
    false       Ok
386
    true        Error
387
*/
388
389
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
390
                                          bool can_use_result_field)
391
{
392
  bool use_result_field= (!can_use_result_field ? 0 :
393
                          (result_field && result_field != field));
394
  int error;
395
396
  /* Update the value of the user variable */
397
  check(use_result_field);
398
  update();
399
400
  if (result_type() == STRING_RESULT ||
401
      (result_type() == REAL_RESULT && field->result_type() == STRING_RESULT))
402
  {
403
    String *result;
404
    const CHARSET_INFO * const cs= collation.collation;
405
    char buff[MAX_FIELD_WIDTH];         // Alloc buffer for small columns
406
    str_value.set_quick(buff, sizeof(buff), cs);
407
    result= entry->val_str(&null_value, &str_value, decimals);
408
409
    if (null_value)
410
    {
411
      str_value.set_quick(0, 0, cs);
412
      return set_field_to_null_with_conversions(field, no_conversions);
413
    }
414
415
    /* NOTE: If null_value == false, "result" must be not NULL.  */
416
417
    field->set_notnull();
418
    error=field->store(result->ptr(),result->length(),cs);
419
    str_value.set_quick(0, 0, cs);
420
  }
421
  else if (result_type() == REAL_RESULT)
422
  {
423
    double nr= entry->val_real(&null_value);
424
    if (null_value)
425
      return set_field_to_null(field);
426
    field->set_notnull();
427
    error=field->store(nr);
428
  }
429
  else if (result_type() == DECIMAL_RESULT)
430
  {
431
    my_decimal decimal_value;
432
    my_decimal *val= entry->val_decimal(&null_value, &decimal_value);
433
    if (null_value)
434
      return set_field_to_null(field);
435
    field->set_notnull();
436
    error=field->store_decimal(val);
437
  }
438
  else
439
  {
440
    int64_t nr= entry->val_int(&null_value);
441
    if (null_value)
442
      return set_field_to_null_with_conversions(field, no_conversions);
443
    field->set_notnull();
444
    error=field->store(nr, unsigned_flag);
445
  }
446
  return error;
447
}
448
449