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