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