Drizzled Public API Documentation

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