mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
55c5016f92
Small bug fixes myisammrg/myrg_rfirst.c: Change mode to -rw-rw-r-- myisammrg/myrg_rlast.c: Change mode to -rw-rw-r-- myisammrg/myrg_rnext.c: Change mode to -rw-rw-r-- myisammrg/myrg_rprev.c: Change mode to -rw-rw-r-- Docs/manual.texi: Update of RENAME configure.in: Portability fix include/global.h: Fix for ODBC and Intel Ia64 include/mysqld_error.h: RENAME TABLE myisam/myisamchk.c: Faster --fast myisammrg/myrg_queue.c: Bug fix myisammrg/myrg_rkey.c: Portability fix sql-bench/test-insert.sh: Fix for duplicate key test sql/ChangeLog: Changelog sql/Makefile.am: RENAME TABLE sql/item_sum.cc: Fix for COUNT(DISTINCT) sql/lock.cc: RENAME TABLE sql/share/czech/errmsg.sys: RENAME TABLE sql/share/czech/errmsg.txt: RENAME TABLE sql/share/danish/errmsg.sys: RENAME TABLE sql/share/danish/errmsg.txt: RENAME TABLE sql/share/dutch/errmsg.sys: RENAME TABLE sql/share/dutch/errmsg.txt: RENAME TABLE sql/share/english/errmsg.sys: RENAME TABLE sql/share/english/errmsg.txt: RENAME TABLE sql/share/estonia/errmsg.sys: RENAME TABLE sql/share/estonia/errmsg.txt: RENAME TABLE sql/share/french/errmsg.sys: RENAME TABLE sql/share/french/errmsg.txt: RENAME TABLE sql/share/german/errmsg.sys: RENAME TABLE sql/share/german/errmsg.txt: RENAME TABLE sql/share/greek/errmsg.sys: RENAME TABLE sql/share/greek/errmsg.txt: RENAME TABLE sql/share/hungarian/errmsg.sys: RENAME TABLE sql/share/hungarian/errmsg.txt: RENAME TABLE sql/share/italian/errmsg.sys: RENAME TABLE sql/share/italian/errmsg.txt: RENAME TABLE sql/share/japanese/errmsg.sys: RENAME TABLE sql/share/japanese/errmsg.txt: RENAME TABLE sql/share/korean/errmsg.sys: RENAME TABLE sql/share/korean/errmsg.txt: RENAME TABLE sql/share/norwegian-ny/errmsg.txt: RENAME TABLE sql/share/norwegian/errmsg.txt: RENAME TABLE sql/share/polish/errmsg.sys: RENAME TABLE sql/share/polish/errmsg.txt: RENAME TABLE sql/share/portuguese/errmsg.sys: RENAME TABLE sql/share/portuguese/errmsg.txt: RENAME TABLE sql/share/romania/errmsg.sys: RENAME TABLE sql/share/romania/errmsg.txt: RENAME TABLE sql/share/romanian/errmsg.txt: ***MISSING WEAVE*** sql/share/russian/errmsg.sys: RENAME TABLE sql/share/russian/errmsg.txt: RENAME TABLE sql/share/slovak/errmsg.sys: RENAME TABLE sql/share/slovak/errmsg.txt: RENAME TABLE sql/share/spanish/errmsg.sys: RENAME TABLE sql/share/spanish/errmsg.txt: RENAME TABLE sql/share/swedish/errmsg.OLD: RENAME TABLE sql/share/swedish/errmsg.sys: RENAME TABLE sql/share/swedish/errmsg.txt: RENAME TABLE sql/slave.cc: Faster alloc sql/sql_base.cc: RENAME TABLE sql/sql_class.cc: Faster alloc sql/sql_class.h: Faster alloc sql/sql_insert.cc: Fix bug in INSERT ... SELECT to BDB table sql/sql_lex.h: RENAME TABLE sql/sql_select.cc: Faster alloc sql/sql_show.cc: Faster alloc sql/sql_table.cc: RENAME TABLE sql/sql_yacc.yy: RENAME TABLE sql/thr_malloc.cc: Faster alloc sql/unireg.h: RENAME TABLE strings/ctype-sjis.c: Portability fix
945 lines
18 KiB
C++
945 lines
18 KiB
C++
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
|
|
/* Sum functions (COUNT, MIN...) */
|
|
|
|
#ifdef __GNUC__
|
|
#pragma implementation // gcc: Class implementation
|
|
#endif
|
|
|
|
#include "mysql_priv.h"
|
|
|
|
|
|
Item_sum::Item_sum(List<Item> &list)
|
|
{
|
|
arg_count=list.elements;
|
|
if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
|
|
{
|
|
uint i=0;
|
|
List_iterator<Item> li(list);
|
|
Item *item;
|
|
|
|
while ((item=li++))
|
|
{
|
|
args[i++]= item;
|
|
}
|
|
}
|
|
with_sum_func=1;
|
|
list.empty(); // Fields are used
|
|
}
|
|
|
|
|
|
void Item_sum::make_field(Send_field *tmp_field)
|
|
{
|
|
if (args[0]->type() == Item::FIELD_ITEM && keep_field_type())
|
|
((Item_field*) args[0])->field->make_field(tmp_field);
|
|
else
|
|
{
|
|
tmp_field->flags=0;
|
|
if (!maybe_null)
|
|
tmp_field->flags|= NOT_NULL_FLAG;
|
|
tmp_field->length=max_length;
|
|
tmp_field->decimals=decimals;
|
|
tmp_field->type=(result_type() == INT_RESULT ? FIELD_TYPE_LONG :
|
|
result_type() == REAL_RESULT ? FIELD_TYPE_DOUBLE :
|
|
FIELD_TYPE_VAR_STRING);
|
|
}
|
|
tmp_field->table_name=(char*)"";
|
|
tmp_field->col_name=name;
|
|
}
|
|
|
|
void Item_sum::print(String *str)
|
|
{
|
|
str->append(func_name());
|
|
str->append('(');
|
|
for (uint i=0 ; i < arg_count ; i++)
|
|
{
|
|
if (i)
|
|
str->append(',');
|
|
args[i]->print(str);
|
|
}
|
|
str->append(')');
|
|
}
|
|
|
|
void Item_sum::fix_num_length_and_dec()
|
|
{
|
|
decimals=0;
|
|
for (uint i=0 ; i < arg_count ; i++)
|
|
set_if_bigger(decimals,args[i]->decimals);
|
|
max_length=float_length(decimals);
|
|
}
|
|
|
|
|
|
String *
|
|
Item_sum_num::val_str(String *str)
|
|
{
|
|
double nr=val();
|
|
if (null_value)
|
|
return 0;
|
|
str->set(nr,decimals);
|
|
return str;
|
|
}
|
|
|
|
|
|
String *
|
|
Item_sum_int::val_str(String *str)
|
|
{
|
|
longlong nr=val_int();
|
|
if (null_value)
|
|
return 0;
|
|
char buff[21];
|
|
uint length= (uint) (longlong10_to_str(nr,buff,-10)-buff);
|
|
str->copy(buff,length);
|
|
return str;
|
|
}
|
|
|
|
|
|
bool
|
|
Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
|
|
{
|
|
if (!thd->allow_sum_func)
|
|
{
|
|
my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
|
|
return 1;
|
|
}
|
|
thd->allow_sum_func=0; // No included group funcs
|
|
decimals=0;
|
|
maybe_null=0;
|
|
for (uint i=0 ; i < arg_count ; i++)
|
|
{
|
|
if (args[i]->fix_fields(thd,tables))
|
|
return 1;
|
|
if (decimals < args[i]->decimals)
|
|
decimals=args[i]->decimals;
|
|
maybe_null |= args[i]->maybe_null;
|
|
}
|
|
result_field=0;
|
|
max_length=float_length(decimals);
|
|
null_value=1;
|
|
fix_length_and_dec();
|
|
thd->allow_sum_func=1; // Allow group functions
|
|
return 0;
|
|
}
|
|
|
|
|
|
bool
|
|
Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
|
|
{
|
|
Item *item=args[0];
|
|
if (!thd->allow_sum_func)
|
|
{
|
|
my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
|
|
return 1;
|
|
}
|
|
thd->allow_sum_func=0; // No included group funcs
|
|
if (item->fix_fields(thd,tables))
|
|
return 1;
|
|
hybrid_type=item->result_type();
|
|
if (hybrid_type == INT_RESULT)
|
|
max_length=21;
|
|
else if (hybrid_type == REAL_RESULT)
|
|
max_length=float_length(decimals);
|
|
else
|
|
max_length=item->max_length;
|
|
decimals=item->decimals;
|
|
maybe_null=item->maybe_null;
|
|
binary=item->binary;
|
|
result_field=0;
|
|
null_value=1;
|
|
fix_length_and_dec();
|
|
thd->allow_sum_func=1; // Allow group functions
|
|
return 0;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
** reset and add of sum_func
|
|
***********************************************************************/
|
|
|
|
void Item_sum_sum::reset()
|
|
{
|
|
null_value=0; sum=0.0; Item_sum_sum::add();
|
|
}
|
|
|
|
bool Item_sum_sum::add()
|
|
{
|
|
sum+=args[0]->val();
|
|
return 0;
|
|
}
|
|
|
|
double Item_sum_sum::val()
|
|
{
|
|
return sum;
|
|
}
|
|
|
|
|
|
void Item_sum_count::reset()
|
|
{
|
|
count=0; add();
|
|
}
|
|
|
|
bool Item_sum_count::add()
|
|
{
|
|
if (!args[0]->maybe_null)
|
|
count++;
|
|
else
|
|
{
|
|
(void) args[0]->val_int();
|
|
if (!args[0]->null_value)
|
|
count++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
longlong Item_sum_count::val_int()
|
|
{
|
|
return (longlong) count;
|
|
}
|
|
|
|
/*
|
|
** Avgerage
|
|
*/
|
|
|
|
void Item_sum_avg::reset()
|
|
{
|
|
sum=0.0; count=0; Item_sum_avg::add();
|
|
}
|
|
|
|
bool Item_sum_avg::add()
|
|
{
|
|
double nr=args[0]->val();
|
|
if (!args[0]->null_value)
|
|
{
|
|
sum+=nr;
|
|
count++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
double Item_sum_avg::val()
|
|
{
|
|
if (!count)
|
|
{
|
|
null_value=1;
|
|
return 0.0;
|
|
}
|
|
null_value=0;
|
|
return sum/ulonglong2double(count);
|
|
}
|
|
|
|
|
|
/*
|
|
** Standard deviation
|
|
*/
|
|
|
|
void Item_sum_std::reset()
|
|
{
|
|
sum=sum_sqr=0.0; count=0; (void) Item_sum_std::add();
|
|
}
|
|
|
|
bool Item_sum_std::add()
|
|
{
|
|
double nr=args[0]->val();
|
|
if (!args[0]->null_value)
|
|
{
|
|
sum+=nr;
|
|
sum_sqr+=nr*nr;
|
|
count++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
double Item_sum_std::val()
|
|
{
|
|
if (!count)
|
|
{
|
|
null_value=1;
|
|
return 0.0;
|
|
}
|
|
null_value=0;
|
|
/* Avoid problems when the precision isn't good enough */
|
|
double tmp=ulonglong2double(count);
|
|
double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
|
|
return tmp2 <= 0.0 ? 0.0 : sqrt(tmp2);
|
|
}
|
|
|
|
|
|
void Item_sum_std::reset_field()
|
|
{
|
|
double nr=args[0]->val();
|
|
char *res=result_field->ptr;
|
|
|
|
if (args[0]->null_value)
|
|
bzero(res,sizeof(double)*2+sizeof(longlong));
|
|
else
|
|
{
|
|
float8store(res,nr);
|
|
nr*=nr;
|
|
float8store(res+sizeof(double),nr);
|
|
longlong tmp=1;
|
|
int8store(res+sizeof(double)*2,tmp);
|
|
}
|
|
}
|
|
|
|
void Item_sum_std::update_field(int offset)
|
|
{
|
|
double nr,old_nr,old_sqr;
|
|
longlong field_count;
|
|
char *res=result_field->ptr;
|
|
|
|
float8get(old_nr,res+offset);
|
|
float8get(old_sqr,res+offset+sizeof(double));
|
|
field_count=sint8korr(res+offset+sizeof(double)*2);
|
|
|
|
nr=args[0]->val();
|
|
if (!args[0]->null_value)
|
|
{
|
|
old_nr+=nr;
|
|
old_sqr+=nr*nr;
|
|
field_count++;
|
|
}
|
|
float8store(res,old_nr);
|
|
float8store(res+sizeof(double),old_sqr);
|
|
int8store(res+sizeof(double)*2,field_count);
|
|
}
|
|
|
|
/* min & max */
|
|
|
|
double Item_sum_hybrid::val()
|
|
{
|
|
if (null_value)
|
|
return 0.0;
|
|
if (hybrid_type == STRING_RESULT)
|
|
{
|
|
String *res; res=val_str(&str_value);
|
|
return res ? atof(res->c_ptr()) : 0.0;
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
|
|
String *
|
|
Item_sum_hybrid::val_str(String *str)
|
|
{
|
|
if (null_value)
|
|
return 0;
|
|
if (hybrid_type == STRING_RESULT)
|
|
return &value;
|
|
str->set(sum,decimals);
|
|
return str;
|
|
}
|
|
|
|
|
|
bool Item_sum_min::add()
|
|
{
|
|
if (hybrid_type != STRING_RESULT)
|
|
{
|
|
double nr=args[0]->val();
|
|
if (!args[0]->null_value && (null_value || nr < sum))
|
|
{
|
|
sum=nr;
|
|
null_value=0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
String *result=args[0]->val_str(&tmp_value);
|
|
if (!args[0]->null_value &&
|
|
(null_value ||
|
|
(binary ? stringcmp(&value,result) : sortcmp(&value,result)) > 0))
|
|
{
|
|
value.copy(*result);
|
|
null_value=0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
bool Item_sum_max::add()
|
|
{
|
|
if (hybrid_type != STRING_RESULT)
|
|
{
|
|
double nr=args[0]->val();
|
|
if (!args[0]->null_value && (null_value || nr > sum))
|
|
{
|
|
sum=nr;
|
|
null_value=0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
String *result=args[0]->val_str(&tmp_value);
|
|
if (!args[0]->null_value &&
|
|
(null_value ||
|
|
(binary ? stringcmp(&value,result) : sortcmp(&value,result)) < 0))
|
|
{
|
|
value.copy(*result);
|
|
null_value=0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* bit_or and bit_and */
|
|
|
|
longlong Item_sum_bit::val_int()
|
|
{
|
|
return (longlong) bits;
|
|
}
|
|
|
|
void Item_sum_bit::reset()
|
|
{
|
|
bits=reset_bits; add();
|
|
}
|
|
|
|
bool Item_sum_or::add()
|
|
{
|
|
ulonglong value= (ulonglong) args[0]->val_int();
|
|
if (!args[0]->null_value)
|
|
bits|=value;
|
|
return 0;
|
|
}
|
|
|
|
bool Item_sum_and::add()
|
|
{
|
|
ulonglong value= (ulonglong) args[0]->val_int();
|
|
if (!args[0]->null_value)
|
|
bits&=value;
|
|
return 0;
|
|
}
|
|
|
|
/************************************************************************
|
|
** reset result of a Item_sum with is saved in a tmp_table
|
|
*************************************************************************/
|
|
|
|
void Item_sum_num::reset_field()
|
|
{
|
|
double nr=args[0]->val();
|
|
char *res=result_field->ptr;
|
|
|
|
if (maybe_null)
|
|
{
|
|
if (args[0]->null_value)
|
|
{
|
|
nr=0.0;
|
|
result_field->set_null();
|
|
}
|
|
else
|
|
result_field->set_notnull();
|
|
}
|
|
float8store(res,nr);
|
|
}
|
|
|
|
|
|
void Item_sum_hybrid::reset_field()
|
|
{
|
|
if (hybrid_type == STRING_RESULT)
|
|
{
|
|
char buff[MAX_FIELD_WIDTH];
|
|
String tmp(buff,sizeof(buff)),*res;
|
|
|
|
res=args[0]->val_str(&tmp);
|
|
if (args[0]->null_value)
|
|
{
|
|
result_field->set_null();
|
|
result_field->reset();
|
|
}
|
|
else
|
|
{
|
|
result_field->set_notnull();
|
|
result_field->store(res->ptr(),res->length());
|
|
}
|
|
}
|
|
else if (hybrid_type == INT_RESULT)
|
|
{
|
|
longlong nr=args[0]->val_int();
|
|
|
|
if (maybe_null)
|
|
{
|
|
if (args[0]->null_value)
|
|
{
|
|
nr=0;
|
|
result_field->set_null();
|
|
}
|
|
else
|
|
result_field->set_notnull();
|
|
}
|
|
result_field->store(nr);
|
|
}
|
|
else // REAL_RESULT
|
|
{
|
|
double nr=args[0]->val();
|
|
|
|
if (maybe_null)
|
|
{
|
|
if (args[0]->null_value)
|
|
{
|
|
nr=0.0;
|
|
result_field->set_null();
|
|
}
|
|
else
|
|
result_field->set_notnull();
|
|
}
|
|
result_field->store(nr);
|
|
}
|
|
}
|
|
|
|
|
|
void Item_sum_sum::reset_field()
|
|
{
|
|
double nr=args[0]->val(); // Nulls also return 0
|
|
float8store(result_field->ptr,nr);
|
|
null_value=0;
|
|
result_field->set_notnull();
|
|
}
|
|
|
|
|
|
void Item_sum_count::reset_field()
|
|
{
|
|
char *res=result_field->ptr;
|
|
longlong nr=0;
|
|
|
|
if (!args[0]->maybe_null)
|
|
nr=1;
|
|
else
|
|
{
|
|
(void) args[0]->val_int();
|
|
if (!args[0]->null_value)
|
|
nr=1;
|
|
}
|
|
int8store(res,nr);
|
|
}
|
|
|
|
|
|
void Item_sum_avg::reset_field()
|
|
{
|
|
double nr=args[0]->val();
|
|
char *res=result_field->ptr;
|
|
|
|
if (args[0]->null_value)
|
|
bzero(res,sizeof(double)+sizeof(longlong));
|
|
else
|
|
{
|
|
float8store(res,nr);
|
|
res+=sizeof(double);
|
|
longlong tmp=1;
|
|
int8store(res,tmp);
|
|
}
|
|
}
|
|
|
|
void Item_sum_bit::reset_field()
|
|
{
|
|
char *res=result_field->ptr;
|
|
ulonglong nr=(ulonglong) args[0]->val_int();
|
|
int8store(res,nr);
|
|
}
|
|
|
|
/*
|
|
** calc next value and merge it with field_value
|
|
*/
|
|
|
|
void Item_sum_sum::update_field(int offset)
|
|
{
|
|
double old_nr,nr;
|
|
char *res=result_field->ptr;
|
|
|
|
float8get(old_nr,res+offset);
|
|
nr=args[0]->val();
|
|
if (!args[0]->null_value)
|
|
old_nr+=nr;
|
|
float8store(res,old_nr);
|
|
}
|
|
|
|
|
|
void Item_sum_count::update_field(int offset)
|
|
{
|
|
longlong nr;
|
|
char *res=result_field->ptr;
|
|
|
|
nr=sint8korr(res+offset);
|
|
if (!args[0]->maybe_null)
|
|
nr++;
|
|
else
|
|
{
|
|
(void) args[0]->val_int();
|
|
if (!args[0]->null_value)
|
|
nr++;
|
|
}
|
|
int8store(res,nr);
|
|
}
|
|
|
|
|
|
void Item_sum_avg::update_field(int offset)
|
|
{
|
|
double nr,old_nr;
|
|
longlong field_count;
|
|
char *res=result_field->ptr;
|
|
|
|
float8get(old_nr,res+offset);
|
|
field_count=sint8korr(res+offset+sizeof(double));
|
|
|
|
nr=args[0]->val();
|
|
if (!args[0]->null_value)
|
|
{
|
|
old_nr+=nr;
|
|
field_count++;
|
|
}
|
|
float8store(res,old_nr);
|
|
res+=sizeof(double);
|
|
int8store(res,field_count);
|
|
}
|
|
|
|
void Item_sum_hybrid::update_field(int offset)
|
|
{
|
|
if (hybrid_type == STRING_RESULT)
|
|
min_max_update_str_field(offset);
|
|
else if (hybrid_type == INT_RESULT)
|
|
min_max_update_int_field(offset);
|
|
else
|
|
min_max_update_real_field(offset);
|
|
}
|
|
|
|
|
|
void
|
|
Item_sum_hybrid::min_max_update_str_field(int offset)
|
|
{
|
|
String *res_str=args[0]->val_str(&value);
|
|
|
|
if (args[0]->null_value)
|
|
result_field->copy_from_tmp(offset); // Use old value
|
|
else
|
|
{
|
|
res_str->strip_sp();
|
|
result_field->ptr+=offset; // Get old max/min
|
|
result_field->val_str(&tmp_value,&tmp_value);
|
|
result_field->ptr-=offset;
|
|
|
|
if (result_field->is_null() ||
|
|
(cmp_sign * (binary ? stringcmp(res_str,&tmp_value) :
|
|
sortcmp(res_str,&tmp_value)) < 0))
|
|
result_field->store(res_str->ptr(),res_str->length());
|
|
else
|
|
{ // Use old value
|
|
char *res=result_field->ptr;
|
|
memcpy(res,res+offset,result_field->pack_length());
|
|
}
|
|
result_field->set_notnull();
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
Item_sum_hybrid::min_max_update_real_field(int offset)
|
|
{
|
|
double nr,old_nr;
|
|
|
|
result_field->ptr+=offset;
|
|
old_nr=result_field->val_real();
|
|
nr=args[0]->val();
|
|
if (!args[0]->null_value)
|
|
{
|
|
if (result_field->is_null(offset) ||
|
|
(cmp_sign > 0 ? old_nr > nr : old_nr < nr))
|
|
old_nr=nr;
|
|
result_field->set_notnull();
|
|
}
|
|
else if (result_field->is_null(offset))
|
|
result_field->set_null();
|
|
result_field->ptr-=offset;
|
|
result_field->store(old_nr);
|
|
}
|
|
|
|
|
|
void
|
|
Item_sum_hybrid::min_max_update_int_field(int offset)
|
|
{
|
|
longlong nr,old_nr;
|
|
|
|
result_field->ptr+=offset;
|
|
old_nr=result_field->val_int();
|
|
nr=args[0]->val_int();
|
|
if (!args[0]->null_value)
|
|
{
|
|
if (result_field->is_null(offset) ||
|
|
(cmp_sign > 0 ? old_nr > nr : old_nr < nr))
|
|
old_nr=nr;
|
|
result_field->set_notnull();
|
|
}
|
|
else if (result_field->is_null(offset))
|
|
result_field->set_null();
|
|
result_field->ptr-=offset;
|
|
result_field->store(old_nr);
|
|
}
|
|
|
|
|
|
void Item_sum_or::update_field(int offset)
|
|
{
|
|
ulonglong nr;
|
|
char *res=result_field->ptr;
|
|
|
|
nr=uint8korr(res+offset);
|
|
nr|= (ulonglong) args[0]->val_int();
|
|
int8store(res,nr);
|
|
}
|
|
|
|
|
|
void Item_sum_and::update_field(int offset)
|
|
{
|
|
ulonglong nr;
|
|
char *res=result_field->ptr;
|
|
|
|
nr=uint8korr(res+offset);
|
|
nr&= (ulonglong) args[0]->val_int();
|
|
int8store(res,nr);
|
|
}
|
|
|
|
|
|
Item_avg_field::Item_avg_field(Item_sum_avg *item)
|
|
{
|
|
name=item->name;
|
|
decimals=item->decimals;
|
|
max_length=item->max_length;
|
|
field=item->result_field;
|
|
maybe_null=1;
|
|
}
|
|
|
|
double Item_avg_field::val()
|
|
{
|
|
double nr;
|
|
longlong count;
|
|
float8get(nr,field->ptr);
|
|
char *res=(field->ptr+sizeof(double));
|
|
count=sint8korr(res);
|
|
|
|
if (!count)
|
|
{
|
|
null_value=1;
|
|
return 0.0;
|
|
}
|
|
null_value=0;
|
|
return nr/(double) count;
|
|
}
|
|
|
|
String *Item_avg_field::val_str(String *str)
|
|
{
|
|
double nr=Item_avg_field::val();
|
|
if (null_value)
|
|
return 0;
|
|
str->set(nr,decimals);
|
|
return str;
|
|
}
|
|
|
|
Item_std_field::Item_std_field(Item_sum_std *item)
|
|
{
|
|
name=item->name;
|
|
decimals=item->decimals;
|
|
max_length=item->max_length;
|
|
field=item->result_field;
|
|
maybe_null=1;
|
|
}
|
|
|
|
double Item_std_field::val()
|
|
{
|
|
double sum,sum_sqr;
|
|
longlong count;
|
|
float8get(sum,field->ptr);
|
|
float8get(sum_sqr,(field->ptr+sizeof(double)));
|
|
count=sint8korr(field->ptr+sizeof(double)*2);
|
|
|
|
if (!count)
|
|
{
|
|
null_value=1;
|
|
return 0.0;
|
|
}
|
|
null_value=0;
|
|
double tmp= (double) count;
|
|
double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
|
|
return tmp2 <= 0.0 ? 0.0 : sqrt(tmp2);
|
|
}
|
|
|
|
String *Item_std_field::val_str(String *str)
|
|
{
|
|
double nr=val();
|
|
if (null_value)
|
|
return 0;
|
|
str->set(nr,decimals);
|
|
return str;
|
|
}
|
|
|
|
/****************************************************************************
|
|
** COUNT(DISTINCT ...)
|
|
****************************************************************************/
|
|
|
|
#include "sql_select.h"
|
|
|
|
Item_sum_count_distinct::~Item_sum_count_distinct()
|
|
{
|
|
if (table)
|
|
free_tmp_table(current_thd, table);
|
|
delete tmp_table_param;
|
|
}
|
|
|
|
|
|
bool Item_sum_count_distinct::fix_fields(THD *thd,TABLE_LIST *tables)
|
|
{
|
|
if (Item_sum_num::fix_fields(thd,tables) ||
|
|
!(tmp_table_param= new TMP_TABLE_PARAM))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
bool Item_sum_count_distinct::setup(THD *thd)
|
|
{
|
|
List<Item> list;
|
|
/* Create a table with an unique key over all parameters */
|
|
for (uint i=0; i < arg_count ; i++)
|
|
if (list.push_back(args[i]))
|
|
return 1;
|
|
count_field_types(tmp_table_param,list);
|
|
if (table)
|
|
{
|
|
free_tmp_table(thd, table);
|
|
tmp_table_param->cleanup();
|
|
}
|
|
if (!(table=create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
|
|
0, 0, current_lex->options | thd->options)))
|
|
return 1;
|
|
table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows
|
|
return 0;
|
|
}
|
|
|
|
|
|
void Item_sum_count_distinct::reset()
|
|
{
|
|
table->file->extra(HA_EXTRA_NO_CACHE);
|
|
table->file->delete_all_rows();
|
|
table->file->extra(HA_EXTRA_WRITE_CACHE);
|
|
(void) add();
|
|
}
|
|
|
|
bool Item_sum_count_distinct::add()
|
|
{
|
|
int error;
|
|
copy_fields(tmp_table_param);
|
|
copy_funcs(tmp_table_param->funcs);
|
|
|
|
for (Field **field=table->field ; *field ; field++)
|
|
if ((*field)->is_real_null(0))
|
|
return 0; // Don't count NULL
|
|
|
|
if ((error=table->file->write_row(table->record[0])))
|
|
{
|
|
if (error != HA_ERR_FOUND_DUPP_KEY &&
|
|
error != HA_ERR_FOUND_DUPP_UNIQUE)
|
|
{
|
|
if (create_myisam_from_heap(table, tmp_table_param, error,1))
|
|
return 1; // Not a table_is_full error
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
longlong Item_sum_count_distinct::val_int()
|
|
{
|
|
if (!table) // Empty query
|
|
return LL(0);
|
|
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
|
return table->file->records;
|
|
}
|
|
|
|
/****************************************************************************
|
|
** Functions to handle dynamic loadable aggregates
|
|
** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su>
|
|
** Adapted for UDAs by: Andreas F. Bobak <bobak@relog.ch>.
|
|
** Rewritten by: Monty.
|
|
****************************************************************************/
|
|
|
|
#ifdef HAVE_DLOPEN
|
|
|
|
void Item_udf_sum::reset()
|
|
{
|
|
DBUG_ENTER("Item_udf_sum::reset");
|
|
udf.reset(&null_value);
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
bool Item_udf_sum::add()
|
|
{
|
|
DBUG_ENTER("Item_udf_sum::reset");
|
|
udf.add(&null_value);
|
|
DBUG_RETURN(0);
|
|
}
|
|
|
|
double Item_sum_udf_float::val()
|
|
{
|
|
DBUG_ENTER("Item_sum_udf_float::val");
|
|
DBUG_PRINT("info",("result_type: %d arg_count: %d",
|
|
args[0]->result_type(), arg_count));
|
|
DBUG_RETURN(udf.val(&null_value));
|
|
}
|
|
|
|
String *Item_sum_udf_float::val_str(String *str)
|
|
{
|
|
double nr=val();
|
|
if (null_value)
|
|
return 0; /* purecov: inspected */
|
|
else
|
|
str->set(nr,decimals);
|
|
return str;
|
|
}
|
|
|
|
|
|
longlong Item_sum_udf_int::val_int()
|
|
{
|
|
DBUG_ENTER("Item_sum_udf_int::val_int");
|
|
DBUG_PRINT("info",("result_type: %d arg_count: %d",
|
|
args[0]->result_type(), arg_count));
|
|
DBUG_RETURN(udf.val_int(&null_value));
|
|
}
|
|
|
|
String *Item_sum_udf_int::val_str(String *str)
|
|
{
|
|
longlong nr=val_int();
|
|
if (null_value)
|
|
return 0;
|
|
else
|
|
str->set(nr);
|
|
return str;
|
|
}
|
|
|
|
/* Default max_length is max argument length */
|
|
|
|
void Item_sum_udf_str::fix_length_and_dec()
|
|
{
|
|
DBUG_ENTER("Item_sum_udf_str::fix_length_and_dec");
|
|
max_length=0;
|
|
for (uint i = 0; i < arg_count; i++)
|
|
set_if_bigger(max_length,args[i]->max_length);
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
String *Item_sum_udf_str::val_str(String *str)
|
|
{
|
|
DBUG_ENTER("Item_sum_udf_str::str");
|
|
String *res=udf.val_str(str,&str_value);
|
|
null_value = !res;
|
|
DBUG_RETURN(res);
|
|
}
|
|
|
|
#endif /* HAVE_DLOPEN */
|