~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
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
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
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
20
#include "config.h"
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
21
670.1.20 by Monty Taylor
Renamed functions to function... everything else is singular.
22
#include <drizzled/function/set_user_var.h>
584.5.1 by Monty Taylor
Removed field includes from field.h.
23
#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.
24
#include <drizzled/session.h>
971.6.1 by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way.
25
#include <drizzled/plugin/client.h>
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
26
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
27
namespace drizzled
28
{
971.3.65 by Eric Day
Namespace cleanup for Protocol and Listen.
29
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
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) ||
995 by Brian Aker
Refactor get_variable to session
40
      !(entry= session->getVariable(name, true)))
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
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
  */
1273.1.1 by Jay Pipes
* Changes Session::warn_id to Session::warn_query_id
47
  entry->update_query_id= session->getQueryId();
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
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;
1660.1.3 by Brian Aker
Encapsulate Table in field
93
    if (result_field->getTable() == table || !table)
1999.4.2 by Brian Aker
Encapsulate the field's position.
94
      result_field->getTable()->setReadSet(result_field->position());
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
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
1089.1.5 by Brian Aker
Cleanup of user_var
112
  if (entry->update_hash((null_value= args[0]->null_value),
113
                         ptr, length, res_type, cs, dv, unsigned_arg))
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
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:
2008 by Brian Aker
Formatting + remove default from switch/case.
143
    {
144
      save_result.vreal= use_result_field ? result_field->val_real() :
145
        args[0]->val_real();
146
      break;
147
    }
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
148
  case INT_RESULT:
2008 by Brian Aker
Formatting + remove default from switch/case.
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
    }
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
156
  case STRING_RESULT:
2008 by Brian Aker
Formatting + remove default from switch/case.
157
    {
158
      save_result.vstr= use_result_field ? result_field->val_str_internal(&value) :
159
        args[0]->val_str(&value);
160
      break;
161
    }
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
162
  case DECIMAL_RESULT:
2008 by Brian Aker
Formatting + remove default from switch/case.
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
    }
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
169
  case ROW_RESULT:
170
    // This case should never be chosen
171
    assert(0);
172
    break;
173
  }
2008 by Brian Aker
Formatting + remove default from switch/case.
174
175
  return false;
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
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:
2008 by Brian Aker
Formatting + remove default from switch/case.
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
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
206
  case INT_RESULT:
2008 by Brian Aker
Formatting + remove default from switch/case.
207
    {
208
      res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
209
                       INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT,
210
                       unsigned_flag);
211
      break;
212
    }
213
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
214
  case STRING_RESULT:
2008 by Brian Aker
Formatting + remove default from switch/case.
215
    {
216
      if (!save_result.vstr)                                      // Null value
217
        res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
218
                         DERIVATION_IMPLICIT, 0);
219
      else
220
        res= update_hash((void*) save_result.vstr->ptr(),
221
                         save_result.vstr->length(), STRING_RESULT,
222
                         save_result.vstr->charset(),
223
                         DERIVATION_IMPLICIT, 0);
224
      break;
225
    }
226
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
227
  case DECIMAL_RESULT:
2008 by Brian Aker
Formatting + remove default from switch/case.
228
    {
229
      if (!save_result.vdec)                                      // Null value
230
        res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
231
                         DERIVATION_IMPLICIT, 0);
232
      else
233
        res= update_hash((void*) save_result.vdec,
234
                         sizeof(my_decimal), DECIMAL_RESULT,
235
                         &my_charset_bin, DERIVATION_IMPLICIT, 0);
236
      break;
237
    }
238
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
239
  case ROW_RESULT:
240
    // This case should never be chosen
241
    assert(0);
242
    break;
243
  }
2008 by Brian Aker
Formatting + remove default from switch/case.
244
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
245
  return(res);
246
}
247
248
double Item_func_set_user_var::val_real()
249
{
250
  assert(fixed == 1);
251
  check(0);
252
  update();                                     // Store expression
253
  return entry->val_real(&null_value);
254
}
255
256
int64_t Item_func_set_user_var::val_int()
257
{
258
  assert(fixed == 1);
259
  check(0);
260
  update();                                     // Store expression
261
  return entry->val_int(&null_value);
262
}
263
264
String *Item_func_set_user_var::val_str(String *str)
265
{
266
  assert(fixed == 1);
267
  check(0);
268
  update();                                     // Store expression
269
  return entry->val_str(&null_value, str, decimals);
270
}
271
272
273
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
274
{
275
  assert(fixed == 1);
276
  check(0);
277
  update();                                     // Store expression
278
  return entry->val_decimal(&null_value, val);
279
}
280
281
double Item_func_set_user_var::val_result()
282
{
283
  assert(fixed == 1);
284
  check(true);
285
  update();                                     // Store expression
286
  return entry->val_real(&null_value);
287
}
288
289
int64_t Item_func_set_user_var::val_int_result()
290
{
291
  assert(fixed == 1);
292
  check(true);
293
  update();                                     // Store expression
294
  return entry->val_int(&null_value);
295
}
296
297
String *Item_func_set_user_var::str_result(String *str)
298
{
299
  assert(fixed == 1);
300
  check(true);
301
  update();                                     // Store expression
302
  return entry->val_str(&null_value, str, decimals);
303
}
304
305
306
my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
307
{
308
  assert(fixed == 1);
309
  check(true);
310
  update();                                     // Store expression
311
  return entry->val_decimal(&null_value, val);
312
}
313
314
void Item_func_set_user_var::print(String *str, enum_query_type query_type)
315
{
316
  str->append(STRING_WITH_LEN("(@"));
317
  str->append(name.str, name.length);
318
  str->append(STRING_WITH_LEN(":="));
319
  args[0]->print(str, query_type);
320
  str->append(')');
321
}
322
971.6.1 by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way.
323
bool Item_func_set_user_var::send(plugin::Client *client, String *str_arg)
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
324
{
325
  if (result_field)
326
  {
327
    check(1);
328
    update();
971.6.1 by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way.
329
    return client->store(result_field);
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
330
  }
971.6.1 by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way.
331
  return Item::send(client, str_arg);
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
332
}
333
1052.2.4 by Nathan Williams
No actual code changes. Changed Send_field to SendField to be consistent with coding standards.
334
void Item_func_set_user_var::make_field(SendField *tmp_field)
492.3.35 by Lee
more changes to move functions from item_func.cc/h to the functions directory
335
{
336
  if (result_field)
337
  {
338
    result_field->make_field(tmp_field);
339
    assert(tmp_field->table_name != 0);
340
    if (Item::name)
341
      tmp_field->col_name=Item::name;               // Use user supplied name
342
  }
343
  else
344
    Item::make_field(tmp_field);
345
}
346
347
/*
348
  Save the value of a user variable into a field
349
350
  SYNOPSIS
351
    save_in_field()
352
      field           target field to save the value to
353
      no_conversion   flag indicating whether conversions are allowed
354
355
  DESCRIPTION
356
    Save the function value into a field and update the user variable
357
    accordingly. If a result field is defined and the target field doesn't
358
    coincide with it then the value from the result field will be used as
359
    the new value of the user variable.
360
361
    The reason to have this method rather than simply using the result
362
    field in the val_xxx() methods is that the value from the result field
363
    not always can be used when the result field is defined.
364
    Let's consider the following cases:
365
    1) when filling a tmp table the result field is defined but the value of it
366
    is undefined because it has to be produced yet. Thus we can't use it.
367
    2) on execution of an INSERT ... SELECT statement the save_in_field()
368
    function will be called to fill the data in the new record. If the SELECT
369
    part uses a tmp table then the result field is defined and should be
370
    used in order to get the correct result.
371
372
    The difference between the SET_USER_VAR function and regular functions
373
    like CONCAT is that the Item_func objects for the regular functions are
374
    replaced by Item_field objects after the values of these functions have
375
    been stored in a tmp table. Yet an object of the Item_field class cannot
376
    be used to update a user variable.
377
    Due to this we have to handle the result field in a special way here and
378
    in the Item_func_set_user_var::send() function.
379
380
  RETURN VALUES
381
    false       Ok
382
    true        Error
383
*/
384
385
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
386
                                          bool can_use_result_field)
387
{
388
  bool use_result_field= (!can_use_result_field ? 0 :
389
                          (result_field && result_field != field));
390
  int error;
391
392
  /* Update the value of the user variable */
393
  check(use_result_field);
394
  update();
395
396
  if (result_type() == STRING_RESULT ||
397
      (result_type() == REAL_RESULT && field->result_type() == STRING_RESULT))
398
  {
399
    String *result;
400
    const CHARSET_INFO * const cs= collation.collation;
401
    char buff[MAX_FIELD_WIDTH];         // Alloc buffer for small columns
402
    str_value.set_quick(buff, sizeof(buff), cs);
403
    result= entry->val_str(&null_value, &str_value, decimals);
404
405
    if (null_value)
406
    {
407
      str_value.set_quick(0, 0, cs);
408
      return set_field_to_null_with_conversions(field, no_conversions);
409
    }
410
411
    /* NOTE: If null_value == false, "result" must be not NULL.  */
412
413
    field->set_notnull();
414
    error=field->store(result->ptr(),result->length(),cs);
415
    str_value.set_quick(0, 0, cs);
416
  }
417
  else if (result_type() == REAL_RESULT)
418
  {
419
    double nr= entry->val_real(&null_value);
420
    if (null_value)
421
      return set_field_to_null(field);
422
    field->set_notnull();
423
    error=field->store(nr);
424
  }
425
  else if (result_type() == DECIMAL_RESULT)
426
  {
427
    my_decimal decimal_value;
428
    my_decimal *val= entry->val_decimal(&null_value, &decimal_value);
429
    if (null_value)
430
      return set_field_to_null(field);
431
    field->set_notnull();
432
    error=field->store_decimal(val);
433
  }
434
  else
435
  {
436
    int64_t nr= entry->val_int(&null_value);
437
    if (null_value)
438
      return set_field_to_null_with_conversions(field, no_conversions);
439
    field->set_notnull();
440
    error=field->store(nr, unsigned_flag);
441
  }
442
  return error;
443
}
444
445
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
446
} /* namespace drizzled */