/* 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 */ /* classes to use when handling where clause */ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "procedure.h" #include typedef struct keyuse_t { TABLE *table; Item *val; /* or value if no field */ table_map used_tables; uint key, keypart, optimize; key_part_map keypart_map; ha_rows ref_table_rows; /* If true, the comparison this value was created from will not be satisfied if val has NULL 'value'. */ bool null_rejecting; } KEYUSE; class store_key; typedef struct st_table_ref { bool key_err; uint key_parts; // num of ... uint key_length; // length of key_buff int key; // key no byte *key_buff; // value to look for with key byte *key_buff2; // key_buff+key_length store_key **key_copy; // Item **items; // val()'s for each keypart /* (null_rejecting & (1< all_fields; // to store all fields that used in query //Above list changed to use temporary table List tmp_all_fields1, tmp_all_fields2, tmp_all_fields3; //Part, shared with list above, emulate following list List tmp_fields_list1, tmp_fields_list2, tmp_fields_list3; List &fields_list; // hold field list passed to mysql_select List procedure_fields_list; int error; ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select COND *conds; // ---"--- Item *conds_history; // store WHERE for explain TABLE_LIST *tables_list; //hold 'tables' parameter of mysql_selec SQL_SELECT *select; //created in optimisation phase Item **ref_pointer_array; //used pointer reference for this select // Copy of above to be used with different lists Item **items0, **items1, **items2, **items3, **current_ref_pointer_array; uint ref_pointer_array_size; // size of above in bytes const char *zero_result_cause; // not 0 if exec must return zero result bool union_part; // this subselect is part of union bool optimized; // flag to avoid double optimization in EXPLAIN JOIN(THD *thd_arg, List &fields_arg, ulong select_options_arg, select_result *result_arg) :fields_list(fields_arg) { init(thd_arg, fields_arg, select_options_arg, result_arg); } JOIN(JOIN &join) :Sql_alloc(), fields_list(join.fields_list) { init(join.thd, join.fields_list, join.select_options, join.result); } void init(THD *thd_arg, List &fields_arg, ulong select_options_arg, select_result *result_arg) { join_tab= join_tab_save= 0; table= 0; tables= 0; const_tables= 0; sort_and_group= 0; first_record= 0; do_send_rows= 1; send_records= 0; found_records= 0; examined_rows= 0; exec_tmp_table1= 0; exec_tmp_table2= 0; thd= thd_arg; sum_funcs= sum_funcs2= 0; procedure= 0; having= tmp_having= having_history= 0; select_options= select_options_arg; result= result_arg; lock= thd_arg->lock; select_lex= 0; //for safety tmp_join= 0; select_distinct= test(select_options & SELECT_DISTINCT); no_order= 0; simple_order= 0; simple_group= 0; skip_sort_order= 0; need_tmp= 0; hidden_group_fields= 0; /*safety*/ buffer_result= test(select_options & OPTION_BUFFER_RESULT) && !test(select_options & OPTION_FOUND_ROWS); all_fields= fields_arg; fields_list= fields_arg; error= 0; select= 0; ref_pointer_array= items0= items1= items2= items3= 0; ref_pointer_array_size= 0; zero_result_cause= 0; optimized= 0; fields_list= fields_arg; bzero((char*) &keyuse,sizeof(keyuse)); tmp_table_param.init(); tmp_table_param.end_write_records= HA_POS_ERROR; rollup.state= ROLLUP::STATE_NONE; } int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num, COND *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, SELECT_LEX *select, SELECT_LEX_UNIT *unit); int optimize(); int reinit(); void exec(); int cleanup(); void restore_tmp(); bool alloc_func_list(); bool make_sum_func_list(List &all_fields, List &send_fields, bool before_group_by); inline void set_items_ref_array(Item **ptr) { memcpy((char*) ref_pointer_array, (char*) ptr, ref_pointer_array_size); current_ref_pointer_array= ptr; } inline void init_items_ref_array() { items0= ref_pointer_array + all_fields.elements; memcpy(items0, ref_pointer_array, ref_pointer_array_size); current_ref_pointer_array= items0; } bool rollup_init(); bool rollup_make_fields(List &all_fields, List &fields, Item_sum ***func); int rollup_send_data(uint idx); int rollup_write_data(uint idx, TABLE *table); bool test_in_subselect(Item **where); void join_free(bool full); void clear(); bool save_join_tab(); bool send_row_on_empty_set() { return (do_send_rows && tmp_table_param.sum_func_count != 0 && !group_list); } int change_result(select_result *result); }; typedef struct st_select_check { uint const_ref,reg_ref; } SELECT_CHECK; extern const char *join_type_str[]; void TEST_join(JOIN *join); /* Extern functions in sql_select.cc */ bool store_val_in_field(Field *field, Item *val, enum_check_fields check_flag); TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, ORDER *group, bool distinct, bool save_sum_fields, ulong select_options, ha_rows rows_limit, char* alias); void free_tmp_table(THD *thd, TABLE *entry); void count_field_types(TMP_TABLE_PARAM *param, List &fields, bool reset_with_sum_func); bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, Item **ref_pointer_array, List &new_list1, List &new_list2, uint elements, List &fields); void copy_fields(TMP_TABLE_PARAM *param); void copy_funcs(Item **func_ptr); bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, int error, bool ignore_last_dupp_error); /* functions from opt_sum.cc */ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds); /* class to copying an field/item to a key struct */ class store_key :public Sql_alloc { protected: Field *to_field; // Store data here char *null_ptr; char err; public: enum store_key_result { STORE_KEY_OK, STORE_KEY_FATAL, STORE_KEY_CONV }; store_key(THD *thd, Field *field_arg, char *ptr, char *null, uint length) :null_ptr(null),err(0) { if (field_arg->type() == FIELD_TYPE_BLOB) to_field=new Field_varstring(ptr, length, (uchar*) null, 1, Field::NONE, field_arg->field_name, field_arg->table, field_arg->charset()); else { to_field=field_arg->new_field(thd->mem_root,field_arg->table); if (to_field) to_field->move_field(ptr, (uchar*) null, 1); } } virtual ~store_key() {} /* Not actually needed */ virtual enum store_key_result copy()=0; virtual const char *name() const=0; }; class store_key_field: public store_key { Copy_field copy_field; const char *field_name; public: store_key_field(THD *thd, Field *to_field_arg, char *ptr, char *null_ptr_arg, uint length, Field *from_field, const char *name_arg) :store_key(thd, to_field_arg,ptr, null_ptr_arg ? null_ptr_arg : from_field->maybe_null() ? &err : NullS,length), field_name(name_arg) { if (to_field) { copy_field.set(to_field,from_field,0); } } enum store_key_result copy() { copy_field.do_copy(©_field); return err != 0 ? STORE_KEY_FATAL : STORE_KEY_OK; } const char *name() const { return field_name; } }; class store_key_item :public store_key { protected: Item *item; public: store_key_item(THD *thd, Field *to_field_arg, char *ptr, char *null_ptr_arg, uint length, Item *item_arg) :store_key(thd, to_field_arg,ptr, null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ? &err : NullS, length), item(item_arg) {} enum store_key_result copy() { int res= item->save_in_field(to_field, 1); return (err != 0 || res > 2 ? STORE_KEY_FATAL : (store_key_result) res); } const char *name() const { return "func"; } }; class store_key_const_item :public store_key_item { bool inited; public: store_key_const_item(THD *thd, Field *to_field_arg, char *ptr, char *null_ptr_arg, uint length, Item *item_arg) :store_key_item(thd, to_field_arg,ptr, null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ? &err : NullS, length, item_arg), inited(0) { } enum store_key_result copy() { int res; if (!inited) { inited=1; if ((res= item->save_in_field(to_field, 1))) { if (!err) err= res; } } return (err > 2 ? STORE_KEY_FATAL : (store_key_result) err); } const char *name() const { return "const"; } }; bool cp_buffer_from_ref(THD *thd, TABLE_REF *ref); bool error_if_full_join(JOIN *join); int report_error(TABLE *table, int error); int safe_index_read(JOIN_TAB *tab); COND *remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value);