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 bool
00102 Item_func_set_user_var::update_hash(void *ptr, uint32_t length,
00103                                     Item_result res_type,
00104                                     const CHARSET_INFO * 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   if (entry->update_hash((null_value= args[0]->null_value),
00114                          ptr, length, res_type, cs, dv, unsigned_arg))
00115   {
00116     null_value= 1;
00117     return 1;
00118   }
00119   return 0;
00120 }
00121 
00136 bool
00137 Item_func_set_user_var::check(bool use_result_field)
00138 {
00139   if (use_result_field && !result_field)
00140     use_result_field= false;
00141 
00142   switch (cached_result_type) {
00143   case REAL_RESULT:
00144     {
00145       save_result.vreal= use_result_field ? result_field->val_real() :
00146         args[0]->val_real();
00147       break;
00148     }
00149   case INT_RESULT:
00150     {
00151       save_result.vint= use_result_field ? result_field->val_int() :
00152         args[0]->val_int();
00153       unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
00154         args[0]->unsigned_flag;
00155       break;
00156     }
00157   case STRING_RESULT:
00158     {
00159       save_result.vstr= use_result_field ? result_field->val_str_internal(&value) :
00160         args[0]->val_str(&value);
00161       break;
00162     }
00163   case DECIMAL_RESULT:
00164     {
00165       save_result.vdec= use_result_field ?
00166         result_field->val_decimal(&decimal_buff) :
00167         args[0]->val_decimal(&decimal_buff);
00168       break;
00169     }
00170   case ROW_RESULT:
00171     // This case should never be chosen
00172     assert(0);
00173     break;
00174   }
00175 
00176   return false;
00177 }
00178 
00194 bool
00195 Item_func_set_user_var::update()
00196 {
00197   bool res= false;
00198 
00199   switch (cached_result_type) {
00200   case REAL_RESULT:
00201     {
00202       res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
00203                        REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
00204       break;
00205     }
00206 
00207   case INT_RESULT:
00208     {
00209       res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
00210                        INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT,
00211                        unsigned_flag);
00212       break;
00213     }
00214 
00215   case STRING_RESULT:
00216     {
00217       if (!save_result.vstr)                                      // Null value
00218         res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
00219                          DERIVATION_IMPLICIT, 0);
00220       else
00221         res= update_hash((void*) save_result.vstr->ptr(),
00222                          save_result.vstr->length(), STRING_RESULT,
00223                          save_result.vstr->charset(),
00224                          DERIVATION_IMPLICIT, 0);
00225       break;
00226     }
00227 
00228   case DECIMAL_RESULT:
00229     {
00230       if (!save_result.vdec)                                      // Null value
00231         res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
00232                          DERIVATION_IMPLICIT, 0);
00233       else
00234         res= update_hash((void*) save_result.vdec,
00235                          sizeof(type::Decimal), DECIMAL_RESULT,
00236                          &my_charset_bin, DERIVATION_IMPLICIT, 0);
00237       break;
00238     }
00239 
00240   case ROW_RESULT:
00241     // This case should never be chosen
00242     assert(0);
00243     break;
00244   }
00245 
00246   return(res);
00247 }
00248 
00249 double Item_func_set_user_var::val_real()
00250 {
00251   assert(fixed == 1);
00252   check(0);
00253   update();                                     // Store expression
00254   return entry->val_real(&null_value);
00255 }
00256 
00257 int64_t Item_func_set_user_var::val_int()
00258 {
00259   assert(fixed == 1);
00260   check(0);
00261   update();                                     // Store expression
00262   return entry->val_int(&null_value);
00263 }
00264 
00265 String *Item_func_set_user_var::val_str(String *str)
00266 {
00267   assert(fixed == 1);
00268   check(0);
00269   update();                                     // Store expression
00270   return entry->val_str(&null_value, str, decimals);
00271 }
00272 
00273 
00274 type::Decimal *Item_func_set_user_var::val_decimal(type::Decimal *val)
00275 {
00276   assert(fixed == 1);
00277   check(0);
00278   update();                                     // Store expression
00279   return entry->val_decimal(&null_value, val);
00280 }
00281 
00282 double Item_func_set_user_var::val_result()
00283 {
00284   assert(fixed == 1);
00285   check(true);
00286   update();                                     // Store expression
00287   return entry->val_real(&null_value);
00288 }
00289 
00290 int64_t Item_func_set_user_var::val_int_result()
00291 {
00292   assert(fixed == 1);
00293   check(true);
00294   update();                                     // Store expression
00295   return entry->val_int(&null_value);
00296 }
00297 
00298 String *Item_func_set_user_var::str_result(String *str)
00299 {
00300   assert(fixed == 1);
00301   check(true);
00302   update();                                     // Store expression
00303   return entry->val_str(&null_value, str, decimals);
00304 }
00305 
00306 
00307 type::Decimal *Item_func_set_user_var::val_decimal_result(type::Decimal *val)
00308 {
00309   assert(fixed == 1);
00310   check(true);
00311   update();                                     // Store expression
00312   return entry->val_decimal(&null_value, val);
00313 }
00314 
00315 void Item_func_set_user_var::print(String *str)
00316 {
00317   str->append(STRING_WITH_LEN("(@"));
00318   str->append(name.str, name.length);
00319   str->append(STRING_WITH_LEN(":="));
00320   args[0]->print(str);
00321   str->append(')');
00322 }
00323 
00324 bool Item_func_set_user_var::send(plugin::Client *client, String *str_arg)
00325 {
00326   if (result_field)
00327   {
00328     check(1);
00329     update();
00330     return client->store(result_field);
00331   }
00332   return Item::send(client, str_arg);
00333 }
00334 
00335 void Item_func_set_user_var::make_field(SendField *tmp_field)
00336 {
00337   if (result_field)
00338   {
00339     result_field->make_field(tmp_field);
00340     assert(tmp_field->table_name != 0);
00341     if (Item::name)
00342       tmp_field->col_name=Item::name;               // Use user supplied name
00343   }
00344   else
00345   {
00346     Item::make_field(tmp_field);
00347   }
00348 }
00349 
00350 /*
00351   Save the value of a user variable into a field
00352 
00353   SYNOPSIS
00354     save_in_field()
00355       field           target field to save the value to
00356       no_conversion   flag indicating whether conversions are allowed
00357 
00358   DESCRIPTION
00359     Save the function value into a field and update the user variable
00360     accordingly. If a result field is defined and the target field doesn't
00361     coincide with it then the value from the result field will be used as
00362     the new value of the user variable.
00363 
00364     The reason to have this method rather than simply using the result
00365     field in the val_xxx() methods is that the value from the result field
00366     not always can be used when the result field is defined.
00367     Let's consider the following cases:
00368     1) when filling a tmp table the result field is defined but the value of it
00369     is undefined because it has to be produced yet. Thus we can't use it.
00370     2) on execution of an INSERT ... SELECT statement the save_in_field()
00371     function will be called to fill the data in the new record. If the SELECT
00372     part uses a tmp table then the result field is defined and should be
00373     used in order to get the correct result.
00374 
00375     The difference between the SET_USER_VAR function and regular functions
00376     like CONCAT is that the Item_func objects for the regular functions are
00377     replaced by Item_field objects after the values of these functions have
00378     been stored in a tmp table. Yet an object of the Item_field class cannot
00379     be used to update a user variable.
00380     Due to this we have to handle the result field in a special way here and
00381     in the Item_func_set_user_var::send() function.
00382 
00383   RETURN VALUES
00384     false       Ok
00385     true        Error
00386 */
00387 
00388 int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
00389                                           bool can_use_result_field)
00390 {
00391   bool use_result_field= (!can_use_result_field ? 0 :
00392                           (result_field && result_field != field));
00393   int error;
00394 
00395   /* Update the value of the user variable */
00396   check(use_result_field);
00397   update();
00398 
00399   if (result_type() == STRING_RESULT ||
00400       (result_type() == REAL_RESULT && field->result_type() == STRING_RESULT))
00401   {
00402     String *result;
00403     const CHARSET_INFO * const cs= collation.collation;
00404     char buff[MAX_FIELD_WIDTH];         // Alloc buffer for small columns
00405     str_value.set_quick(buff, sizeof(buff), cs);
00406     result= entry->val_str(&null_value, &str_value, decimals);
00407 
00408     if (null_value)
00409     {
00410       str_value.set_quick(0, 0, cs);
00411       return set_field_to_null_with_conversions(field, no_conversions);
00412     }
00413 
00414     /* NOTE: If null_value == false, "result" must be not NULL.  */
00415 
00416     field->set_notnull();
00417     error=field->store(result->ptr(),result->length(),cs);
00418     str_value.set_quick(0, 0, cs);
00419   }
00420   else if (result_type() == REAL_RESULT)
00421   {
00422     double nr= entry->val_real(&null_value);
00423     if (null_value)
00424       return set_field_to_null(field);
00425     field->set_notnull();
00426     error=field->store(nr);
00427   }
00428   else if (result_type() == DECIMAL_RESULT)
00429   {
00430     type::Decimal decimal_value;
00431     type::Decimal *val= entry->val_decimal(&null_value, &decimal_value);
00432     if (null_value)
00433       return set_field_to_null(field);
00434     field->set_notnull();
00435     error=field->store_decimal(val);
00436   }
00437   else
00438   {
00439     int64_t nr= entry->val_int(&null_value);
00440     if (null_value)
00441       return set_field_to_null_with_conversions(field, no_conversions);
00442     field->set_notnull();
00443     error=field->store(nr, unsigned_flag);
00444   }
00445   return error;
00446 }
00447 
00448 
00449 } /* namespace drizzled */