Drizzled Public API Documentation

set_user_var.cc
00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include <drizzled/function/set_user_var.h>
00023 #include <drizzled/field/num.h>
00024 #include <drizzled/session.h>
00025 #include <drizzled/plugin/client.h>
00026 #include <drizzled/user_var_entry.h>
00027 #include <drizzled/table.h>
00028 
00029 namespace drizzled {
00030 
00031 /*
00032   When a user variable is updated (in a SET command or a query like
00033   SELECT @a:= ).
00034 */
00035 
00036 bool Item_func_set_user_var::fix_fields(Session *session, Item **ref)
00037 {
00038   assert(fixed == 0);
00039   /* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
00040   if (Item_func::fix_fields(session, ref) ||
00041       !(entry= session->getVariable(name, true)))
00042     return true;
00043   /*
00044      Remember the last query which updated it, this way a query can later know
00045      if this variable is a constant item in the query (it is if update_query_id
00046      is different from query_id).
00047   */
00048   entry->update_query_id= session->getQueryId();
00049   /*
00050     As it is wrong and confusing to associate any
00051     character set with NULL, @a should be latin2
00052     after this query sequence:
00053 
00054       SET @a=_latin2'string';
00055       SET @a=NULL;
00056 
00057     I.e. the second query should not change the charset
00058     to the current default value, but should keep the
00059     original value assigned during the first query.
00060     In order to do it, we don't copy charset
00061     from the argument if the argument is NULL
00062     and the variable has previously been initialized.
00063   */
00064   null_item= (args[0]->type() == NULL_ITEM);
00065   if (!entry->collation.collation || !null_item)
00066     entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
00067   collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
00068   cached_result_type= args[0]->result_type();
00069   return false;
00070 }
00071 
00072 void
00073 Item_func_set_user_var::fix_length_and_dec()
00074 {
00075   maybe_null=args[0]->maybe_null;
00076   max_length=args[0]->max_length;
00077   decimals=args[0]->decimals;
00078   collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
00079 }
00080 
00081 /*
00082   Mark field in read_map
00083 
00084   NOTES
00085     This is used by filesort to register used fields in a a temporary
00086     column read set or to register used fields in a view
00087 */
00088 
00089 bool Item_func_set_user_var::register_field_in_read_map(unsigned char *arg)
00090 {
00091   if (result_field)
00092   {
00093     Table *table= (Table *) arg;
00094     if (result_field->getTable() == table || !table)
00095       result_field->getTable()->setReadSet(result_field->position());
00096   }
00097   return 0;
00098 }
00099 
00100 
00101 void
00102 Item_func_set_user_var::update_hash(data_ref data,
00103                                     Item_result res_type,
00104                                     const charset_info_st * const cs, Derivation dv,
00105                                     bool unsigned_arg)
00106 {
00107   /*
00108     If we set a variable explicitely to NULL then keep the old
00109     result type of the variable
00110   */
00111   if ((null_value= args[0]->null_value) && null_item)
00112     res_type= entry->type;                      // Don't change type of item
00113   entry->update_hash((null_value= args[0]->null_value), data, res_type, cs, dv, unsigned_arg);
00114 }
00115 
00130 bool
00131 Item_func_set_user_var::check(bool use_result_field)
00132 {
00133   if (use_result_field && !result_field)
00134     use_result_field= false;
00135 
00136   switch (cached_result_type) {
00137   case REAL_RESULT:
00138     {
00139       save_result.vreal= use_result_field ? result_field->val_real() :
00140         args[0]->val_real();
00141       break;
00142     }
00143   case INT_RESULT:
00144     {
00145       save_result.vint= use_result_field ? result_field->val_int() :
00146         args[0]->val_int();
00147 
00148       unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
00149         args[0]->unsigned_flag;
00150 
00151       break;
00152     }
00153   case STRING_RESULT:
00154     {
00155       save_result.vstr= use_result_field ? result_field->val_str_internal(&value) :
00156         args[0]->val_str(&value);
00157       break;
00158     }
00159   case DECIMAL_RESULT:
00160     {
00161       save_result.vdec= use_result_field ?
00162         result_field->val_decimal(&decimal_buff) :
00163         args[0]->val_decimal(&decimal_buff);
00164       break;
00165     }
00166   case ROW_RESULT:
00167     // This case should never be chosen
00168     assert(0);
00169     break;
00170   }
00171 
00172   return false;
00173 }
00174 
00190 void
00191 Item_func_set_user_var::update()
00192 {
00193   switch (cached_result_type) {
00194   case REAL_RESULT:
00195     {
00196       update_hash(data_ref(&save_result.vreal, sizeof(save_result.vreal)), REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
00197       break;
00198     }
00199 
00200   case INT_RESULT:
00201     {
00202       update_hash(data_ref(&save_result.vint, sizeof(save_result.vint)), INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, unsigned_flag);
00203       break;
00204     }
00205 
00206   case STRING_RESULT:
00207     {
00208       if (!save_result.vstr)                                      // Null value
00209         update_hash(data_ref(), STRING_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
00210       else
00211         update_hash(*save_result.vstr, STRING_RESULT, save_result.vstr->charset(), DERIVATION_IMPLICIT, 0);
00212       break;
00213     }
00214 
00215   case DECIMAL_RESULT:
00216     {
00217       if (!save_result.vdec)                                      // Null value
00218         update_hash(data_ref(), DECIMAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
00219       else
00220         update_hash(data_ref(save_result.vdec, sizeof(type::Decimal)), DECIMAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
00221       break;
00222     }
00223 
00224   case ROW_RESULT:
00225     // This case should never be chosen
00226     assert(false);
00227     break;
00228   }
00229 }
00230 
00231 double Item_func_set_user_var::val_real()
00232 {
00233   assert(fixed == 1);
00234   check(0);
00235   update();                                     // Store expression
00236   return entry->val_real(&null_value);
00237 }
00238 
00239 int64_t Item_func_set_user_var::val_int()
00240 {
00241   assert(fixed == 1);
00242   check(0);
00243   update();                                     // Store expression
00244   return entry->val_int(&null_value);
00245 }
00246 
00247 String *Item_func_set_user_var::val_str(String *str)
00248 {
00249   assert(fixed == 1);
00250   check(0);
00251   update();                                     // Store expression
00252   return entry->val_str(&null_value, str, decimals);
00253 }
00254 
00255 
00256 type::Decimal *Item_func_set_user_var::val_decimal(type::Decimal *val)
00257 {
00258   assert(fixed == 1);
00259   check(0);
00260   update();                                     // Store expression
00261   return entry->val_decimal(&null_value, val);
00262 }
00263 
00264 double Item_func_set_user_var::val_result()
00265 {
00266   assert(fixed == 1);
00267   check(true);
00268   update();                                     // Store expression
00269   return entry->val_real(&null_value);
00270 }
00271 
00272 int64_t Item_func_set_user_var::val_int_result()
00273 {
00274   assert(fixed == 1);
00275   check(true);
00276   update();                                     // Store expression
00277   return entry->val_int(&null_value);
00278 }
00279 
00280 String *Item_func_set_user_var::str_result(String *str)
00281 {
00282   assert(fixed == 1);
00283   check(true);
00284   update();                                     // Store expression
00285   return entry->val_str(&null_value, str, decimals);
00286 }
00287 
00288 
00289 type::Decimal *Item_func_set_user_var::val_decimal_result(type::Decimal *val)
00290 {
00291   assert(fixed == 1);
00292   check(true);
00293   update();                                     // Store expression
00294   return entry->val_decimal(&null_value, val);
00295 }
00296 
00297 void Item_func_set_user_var::print(String *str)
00298 {
00299   str->append(STRING_WITH_LEN("(@"));
00300   str->append(name);
00301   str->append(STRING_WITH_LEN(":="));
00302   args[0]->print(str);
00303   str->append(')');
00304 }
00305 
00306 void Item_func_set_user_var::send(plugin::Client *client, String *str_arg)
00307 {
00308   if (result_field)
00309   {
00310     check(1);
00311     update();
00312     client->store(result_field);
00313     return;
00314   }
00315   Item::send(client, str_arg);
00316 }
00317 
00318 void Item_func_set_user_var::make_field(SendField *tmp_field)
00319 {
00320   if (result_field)
00321   {
00322     result_field->make_field(tmp_field);
00323     assert(tmp_field->table_name != 0);
00324     if (Item::name)
00325       tmp_field->col_name=Item::name;               // Use user supplied name
00326   }
00327   else
00328   {
00329     Item::make_field(tmp_field);
00330   }
00331 }
00332 
00333 /*
00334   Save the value of a user variable into a field
00335 
00336   SYNOPSIS
00337     save_in_field()
00338       field           target field to save the value to
00339       no_conversion   flag indicating whether conversions are allowed
00340 
00341   DESCRIPTION
00342     Save the function value into a field and update the user variable
00343     accordingly. If a result field is defined and the target field doesn't
00344     coincide with it then the value from the result field will be used as
00345     the new value of the user variable.
00346 
00347     The reason to have this method rather than simply using the result
00348     field in the val_xxx() methods is that the value from the result field
00349     not always can be used when the result field is defined.
00350     Let's consider the following cases:
00351     1) when filling a tmp table the result field is defined but the value of it
00352     is undefined because it has to be produced yet. Thus we can't use it.
00353     2) on execution of an INSERT ... SELECT statement the save_in_field()
00354     function will be called to fill the data in the new record. If the SELECT
00355     part uses a tmp table then the result field is defined and should be
00356     used in order to get the correct result.
00357 
00358     The difference between the SET_USER_VAR function and regular functions
00359     like CONCAT is that the Item_func objects for the regular functions are
00360     replaced by Item_field objects after the values of these functions have
00361     been stored in a tmp table. Yet an object of the Item_field class cannot
00362     be used to update a user variable.
00363     Due to this we have to handle the result field in a special way here and
00364     in the Item_func_set_user_var::send() function.
00365 
00366   RETURN VALUES
00367     false       Ok
00368     true        Error
00369 */
00370 
00371 int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
00372                                           bool can_use_result_field)
00373 {
00374   bool use_result_field= (!can_use_result_field ? 0 :
00375                           (result_field && result_field != field));
00376   int error;
00377 
00378   /* Update the value of the user variable */
00379   check(use_result_field);
00380   update();
00381 
00382   if (result_type() == STRING_RESULT ||
00383       (result_type() == REAL_RESULT && field->result_type() == STRING_RESULT))
00384   {
00385     String *result;
00386     const charset_info_st * const cs= collation.collation;
00387     char buff[MAX_FIELD_WIDTH];         // Alloc buffer for small columns
00388     str_value.set_quick(buff, sizeof(buff), cs);
00389     result= entry->val_str(&null_value, &str_value, decimals);
00390 
00391     if (null_value)
00392     {
00393       str_value.set_quick(0, 0, cs);
00394       return set_field_to_null_with_conversions(field, no_conversions);
00395     }
00396 
00397     /* NOTE: If null_value == false, "result" must be not NULL.  */
00398 
00399     field->set_notnull();
00400     error=field->store(result->ptr(),result->length(),cs);
00401     str_value.set_quick(0, 0, cs);
00402   }
00403   else if (result_type() == REAL_RESULT)
00404   {
00405     double nr= entry->val_real(&null_value);
00406     if (null_value)
00407       return set_field_to_null(field);
00408     field->set_notnull();
00409     error=field->store(nr);
00410   }
00411   else if (result_type() == DECIMAL_RESULT)
00412   {
00413     type::Decimal decimal_value;
00414     type::Decimal *val= entry->val_decimal(&null_value, &decimal_value);
00415     if (null_value)
00416       return set_field_to_null(field);
00417     field->set_notnull();
00418     error=field->store_decimal(val);
00419   }
00420   else
00421   {
00422     int64_t nr= entry->val_int(&null_value);
00423     if (null_value)
00424       return set_field_to_null_with_conversions(field, no_conversions);
00425     field->set_notnull();
00426     error=field->store(nr, unsigned_flag);
00427   }
00428   return error;
00429 }
00430 
00431 
00432 } /* namespace drizzled */