~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/function/set_user_var.cc

  • Committer: tdavies
  • Date: 2010-10-31 07:38:13 UTC
  • mto: (1897.2.4 merge)
  • mto: This revision was merged to the branch mainline in revision 1899.
  • Revision ID: tdavies@molly-20101031073813-mmu12nqc0bwezxny
struct order_st changed and renamed to c++ class named:Order

Show diffs side-by-side

added added

removed removed

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