00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <drizzled/function/math/divide.h>
00023 #include <drizzled/session.h>
00024
00025 #include <algorithm>
00026
00027 using namespace std;
00028
00029 namespace drizzled
00030 {
00031
00032 double Item_func_div::real_op()
00033 {
00034 assert(fixed == 1);
00035 double value= args[0]->val_real();
00036 double val2= args[1]->val_real();
00037 if ((null_value= args[0]->null_value || args[1]->null_value))
00038 return 0.0;
00039 if (val2 == 0.0)
00040 {
00041 signal_divide_by_null();
00042 return 0.0;
00043 }
00044 return fix_result(value/val2);
00045 }
00046
00047
00048 type::Decimal *Item_func_div::decimal_op(type::Decimal *decimal_value)
00049 {
00050 type::Decimal value1, *val1;
00051 type::Decimal value2, *val2;
00052 int err;
00053
00054 val1= args[0]->val_decimal(&value1);
00055 if ((null_value= args[0]->null_value))
00056 return 0;
00057 val2= args[1]->val_decimal(&value2);
00058 if ((null_value= args[1]->null_value))
00059 return 0;
00060 if ((err= class_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
00061 val1, val2, prec_increment)) > 3)
00062 {
00063 if (err == E_DEC_DIV_ZERO)
00064 signal_divide_by_null();
00065 null_value= 1;
00066 return 0;
00067 }
00068 return decimal_value;
00069 }
00070
00071
00072 void Item_func_div::result_precision()
00073 {
00074 uint32_t precision= min(args[0]->decimal_precision() + prec_increment,
00075 (unsigned int)DECIMAL_MAX_PRECISION);
00076
00077 if (result_type() == INT_RESULT)
00078 unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
00079 else
00080 unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
00081
00082 decimals= min(args[0]->decimals + prec_increment, (unsigned int)DECIMAL_MAX_SCALE);
00083 max_length= class_decimal_precision_to_length(precision, decimals,
00084 unsigned_flag);
00085 }
00086
00087
00088 void Item_func_div::fix_length_and_dec()
00089 {
00090 prec_increment= session->variables.div_precincrement;
00091 Item_num_op::fix_length_and_dec();
00092
00093 switch(hybrid_type)
00094 {
00095 case REAL_RESULT:
00096 {
00097 decimals= max(args[0]->decimals,args[1]->decimals)+prec_increment;
00098 set_if_smaller(decimals, NOT_FIXED_DEC);
00099 max_length= args[0]->max_length - args[0]->decimals + decimals;
00100 uint32_t tmp= float_length(decimals);
00101 set_if_smaller(max_length,tmp);
00102 break;
00103 }
00104 case INT_RESULT:
00105 hybrid_type= DECIMAL_RESULT;
00106 result_precision();
00107 break;
00108 case DECIMAL_RESULT:
00109 result_precision();
00110 break;
00111 default:
00112 assert(0);
00113 }
00114 maybe_null= 1;
00115 return;
00116 }
00117
00118 }