From: Jim Winstead Date: December 12 2005 7:57pm Subject: bk commit into 5.1 tree (jimw:1.1958) List-Archive: http://lists.mysql.com/commits/85 Message-Id: <20051212195715.2B447A8D05@rama.trainedmonkey.com> Below is the list of changes that have just been committed into a local 5.1 repository of jimw. When jimw does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.1958 05/12/12 11:57:07 jimw@stripped +22 -0 Merge mysql.com:/home/jimw/my/mysql-5.0-clean into mysql.com:/home/jimw/my/mysql-5.1-clean sql/sql_base.cc 1.286 05/12/12 11:57:02 jimw@stripped +1 -1 Resolve conflict sql/sql_yacc.yy 1.430 05/12/12 11:55:14 jimw@stripped +0 -0 Auto merged sql/sql_update.cc 1.179 05/12/12 11:55:14 jimw@stripped +0 -0 Auto merged sql/sql_select.cc 1.375 05/12/12 11:55:13 jimw@stripped +0 -0 Auto merged sql/sql_prepare.cc 1.157 05/12/12 11:55:13 jimw@stripped +0 -0 Auto merged sql/sql_parse.cc 1.497 05/12/12 11:55:13 jimw@stripped +0 -0 Auto merged sql/sql_lex.h 1.210 05/12/12 11:55:13 jimw@stripped +0 -0 Auto merged sql/sql_lex.cc 1.169 05/12/12 11:55:13 jimw@stripped +0 -0 Auto merged sql/sql_insert.cc 1.178 05/12/12 11:55:13 jimw@stripped +0 -0 Auto merged sql/sql_delete.cc 1.160 05/12/12 11:55:13 jimw@stripped +0 -0 Auto merged sql/sql_db.cc 1.122 05/12/12 11:55:13 jimw@stripped +0 -0 Auto merged sql/sql_class.h 1.277 05/12/12 11:55:13 jimw@stripped +0 -0 Auto merged sql/sql_class.cc 1.224 05/12/12 11:55:12 jimw@stripped +0 -0 Auto merged sql/mysql_priv.h 1.354 05/12/12 11:55:12 jimw@stripped +0 -0 Auto merged sql/item_sum.cc 1.171 05/12/12 11:55:12 jimw@stripped +0 -0 Auto merged sql/item_subselect.cc 1.121 05/12/12 11:55:12 jimw@stripped +0 -0 Auto merged sql/item_strfunc.cc 1.262 05/12/12 11:55:12 jimw@stripped +0 -0 Auto merged sql/item_func.cc 1.271 05/12/12 11:55:12 jimw@stripped +0 -0 Auto merged sql/item_cmpfunc.cc 1.188 05/12/12 11:55:12 jimw@stripped +0 -0 Auto merged sql/item.h 1.184 05/12/12 11:55:12 jimw@stripped +0 -0 Auto merged sql/item.cc 1.161 05/12/12 11:55:12 jimw@stripped +0 -0 Auto merged mysql-test/r/sp.result 1.176 05/12/12 11:55:12 jimw@stripped +0 -0 Auto merged # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: jimw # Host: rama.(none) # Root: /home/jimw/my/mysql-5.1-clean/RESYNC --- 1.160/sql/item.cc 2005-12-09 03:39:39 -08:00 +++ 1.161/sql/item.cc 2005-12-12 11:55:12 -08:00 @@ -1084,6 +1084,7 @@ ref_pointer_array Pointer to array of reference fields fields All fields in select ref Pointer to item + skip_registered <=> function be must skipped for registered SUM items NOTES This is from split_sum_func2() for items that should be split @@ -1096,8 +1097,13 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, - List &fields, Item **ref) + List &fields, Item **ref, + bool skip_registered) { + /* An item of type Item_sum is registered <=> ref_by != 0 */ + if (type() == SUM_FUNC_ITEM && skip_registered && + ((Item_sum *) this)->ref_by) + return; if (type() != SUM_FUNC_ITEM && with_sum_func) { /* Will split complicated items and ignore simple ones */ @@ -3232,14 +3238,8 @@ { for each outer query Q_k beginning from the inner-most one { - if - Q_k is not a group query AND - - Q_k is not inside an aggregate function - OR - - Q_(k-1) is not in a HAVING or SELECT clause of Q_k - { - search for a column or derived column named col_ref_i - [in table T_j] in the FROM clause of Q_k; - } + search for a column or derived column named col_ref_i + [in table T_j] in the FROM clause of Q_k; if such a column is not found Search for a column or derived column named col_ref_i @@ -3318,18 +3318,11 @@ place= prev_subselect_item->parsing_place; /* - Check table fields only if the subquery is used somewhere out of - HAVING, or the outer SELECT does not use grouping (i.e. tables are - accessible). - In case of a view, find_field_in_tables() writes the pointer to the found view field into '*reference', in other words, it substitutes this Item_field with the found expression. */ - if ((place != IN_HAVING || - (!select->with_sum_func && - select->group_list.elements == 0)) && - (from_field= find_field_in_tables(thd, this, + if ((from_field= find_field_in_tables(thd, this, outer_context-> first_name_resolution_table, outer_context-> @@ -3345,6 +3338,21 @@ { prev_subselect_item->used_tables_cache|= from_field->table->map; prev_subselect_item->const_item_cache= 0; + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level == + thd->lex->current_select->nest_level) + { + Item::Type type= (*reference)->type(); + set_if_bigger(thd->lex->in_sum_func->max_arg_level, + select->nest_level); + set_field(from_field); + fixed= 1; + mark_as_dependent(thd, last_checked_context->select_lex, + context->select_lex, this, + ((type == REF_ITEM || type == FIELD_ITEM) ? + (Item_ident*) (*reference) : 0)); + return FALSE; + } } else { @@ -3496,6 +3504,11 @@ return FALSE; set_field(from_field); + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level == + thd->lex->current_select->nest_level) + set_if_bigger(thd->lex->in_sum_func->max_arg_level, + thd->lex->current_select->nest_level); } else if (thd->set_query_id) { @@ -4688,9 +4701,8 @@ aggregate function. */ if (((*ref)->with_sum_func && name && - (depended_from || - !(current_sel->linkage != GLOBAL_OPTIONS_TYPE && - current_sel->having_fix_field))) || + !(current_sel->linkage != GLOBAL_OPTIONS_TYPE && + current_sel->having_fix_field)) || !(*ref)->fixed) { my_error(ER_ILLEGAL_REFERENCE, MYF(0), @@ -5184,10 +5196,17 @@ Item_ref *ref= (Item_ref *)arg; if (ref->ref[0]->type() != FIELD_ITEM) { + my_error(ER_BAD_FIELD_ERROR, MYF(0), "", "VALUES() function"); return TRUE; } arg= ref->ref[0]; } + /* + According to our SQL grammar, VALUES() function can reference + only to a column. + */ + DBUG_ASSERT(arg->type() == FIELD_ITEM); + Item_field *field_arg= (Item_field *)arg; if (field_arg->field->table->insert_values) --- 1.183/sql/item.h 2005-12-10 23:30:51 -08:00 +++ 1.184/sql/item.h 2005-12-12 11:55:12 -08:00 @@ -729,7 +729,7 @@ // used in row subselects to get value of elements virtual void bring_value() {} - Field *tmp_table_field_from_field_type(TABLE *table); + Field *tmp_table_field_from_field_type(TABLE *table, bool fixed_length); virtual Item_field *filed_for_view_update() { return 0; } virtual Item *neg_transformer(THD *thd) { return NULL; } --- 1.187/sql/item_cmpfunc.cc 2005-12-02 20:42:27 -08:00 +++ 1.188/sql/item_cmpfunc.cc 2005-12-12 11:55:12 -08:00 @@ -1232,7 +1232,7 @@ Field *Item_func_ifnull::tmp_table_field(TABLE *table) { - return tmp_table_field_from_field_type(table); + return tmp_table_field_from_field_type(table, 0); } double --- 1.270/sql/item_func.cc 2005-12-10 23:30:51 -08:00 +++ 1.271/sql/item_func.cc 2005-12-12 11:55:12 -08:00 @@ -362,41 +362,43 @@ } -Field *Item_func::tmp_table_field(TABLE *t_arg) +Field *Item_func::tmp_table_field(TABLE *table) { - Field *res; - LINT_INIT(res); + Field *field; + LINT_INIT(field); switch (result_type()) { case INT_RESULT: if (max_length > 11) - res= new Field_longlong(max_length, maybe_null, name, t_arg, - unsigned_flag); + field= new Field_longlong(max_length, maybe_null, name, unsigned_flag); else - res= new Field_long(max_length, maybe_null, name, t_arg, - unsigned_flag); + field= new Field_long(max_length, maybe_null, name, unsigned_flag); break; case REAL_RESULT: - res= new Field_double(max_length, maybe_null, name, t_arg, decimals); + field= new Field_double(max_length, maybe_null, name, decimals); break; case STRING_RESULT: - res= make_string_field(t_arg); + return make_string_field(table); break; case DECIMAL_RESULT: - res= new Field_new_decimal(my_decimal_precision_to_length(decimal_precision(), - decimals, - unsigned_flag), - maybe_null, name, t_arg, decimals, unsigned_flag); + field= new Field_new_decimal(my_decimal_precision_to_length(decimal_precision(), + decimals, + unsigned_flag), + maybe_null, name, decimals, unsigned_flag); break; case ROW_RESULT: default: // This case should never be chosen DBUG_ASSERT(0); + field= 0; break; } - return res; + if (field) + field->init(table); + return field; } + my_decimal *Item_func::val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed); @@ -4637,7 +4639,8 @@ { maybe_null= 1; m_name->init_qname(current_thd); - dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)); + dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE)); + dummy_table->s= (TABLE_SHARE*) (dummy_table+1); } @@ -4648,9 +4651,11 @@ { maybe_null= 1; m_name->init_qname(current_thd); - dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)); + dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE)); + dummy_table->s= (TABLE_SHARE*) (dummy_table+1); } + void Item_func_sp::cleanup() { @@ -4705,16 +4710,15 @@ DBUG_RETURN(0); } } - if (!dummy_table->s) + if (!dummy_table->alias) { char *empty_name= (char *) ""; - TABLE_SHARE *share; - dummy_table->s= share= &dummy_table->share_not_to_be_used; - dummy_table->alias = empty_name; - dummy_table->maybe_null = maybe_null; + dummy_table->alias= empty_name; + dummy_table->maybe_null= maybe_null; dummy_table->in_use= current_thd; - share->table_cache_key = empty_name; - share->table_name = empty_name; + dummy_table->s->table_cache_key.str = empty_name; + dummy_table->s->table_name.str= empty_name; + dummy_table->s->db.str= empty_name; } field= m_sp->create_result_field(max_length, name, dummy_table); DBUG_RETURN(field); --- 1.170/sql/item_sum.cc 2005-12-02 20:42:27 -08:00 +++ 1.171/sql/item_sum.cc 2005-12-12 11:55:12 -08:00 @@ -371,26 +371,33 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table, uint convert_blob_length) { + Field *field; switch (result_type()) { case REAL_RESULT: - return new Field_double(max_length,maybe_null,name,table,decimals); + field= new Field_double(max_length, maybe_null, name, decimals); + break; case INT_RESULT: - return new Field_longlong(max_length,maybe_null,name,table,unsigned_flag); + field= new Field_longlong(max_length, maybe_null, name, unsigned_flag); + break; case STRING_RESULT: - if (max_length > 255 && convert_blob_length) - return new Field_varstring(convert_blob_length, maybe_null, - name, table, - collation.collation); - return make_string_field(table); + if (max_length <= 255 || !convert_blob_length) + return make_string_field(table); + field= new Field_varstring(convert_blob_length, maybe_null, + name, table->s, collation.collation); + break; case DECIMAL_RESULT: - return new Field_new_decimal(max_length, maybe_null, name, table, + field= new Field_new_decimal(max_length, maybe_null, name, decimals, unsigned_flag); + break; case ROW_RESULT: default: // This case should never be choosen DBUG_ASSERT(0); return 0; } + if (field) + field->init(table); + return field; } @@ -538,9 +545,10 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table, uint convert_blob_length) { + Field *field; if (args[0]->type() == Item::FIELD_ITEM) { - Field *field= ((Item_field*) args[0])->field; + field= ((Item_field*) args[0])->field; if ((field= create_tmp_field_from_field(current_thd, field, name, table, NULL, convert_blob_length))) @@ -554,16 +562,21 @@ */ switch (args[0]->field_type()) { case MYSQL_TYPE_DATE: - return new Field_date(maybe_null, name, table, collation.collation); + field= new Field_date(maybe_null, name, collation.collation); + break; case MYSQL_TYPE_TIME: - return new Field_time(maybe_null, name, table, collation.collation); + field= new Field_time(maybe_null, name, collation.collation); + break; case MYSQL_TYPE_TIMESTAMP: case MYSQL_TYPE_DATETIME: - return new Field_datetime(maybe_null, name, table, collation.collation); - default: + field= new Field_datetime(maybe_null, name, collation.collation); break; + default: + return Item_sum::create_tmp_field(group, table, convert_blob_length); } - return Item_sum::create_tmp_field(group, table, convert_blob_length); + if (field) + field->init(table); + return field; } @@ -1065,6 +1078,7 @@ Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table, uint convert_blob_len) { + Field *field; if (group) { /* @@ -1072,14 +1086,18 @@ The easyest way is to do this is to store both value in a string and unpack on access. */ - return new Field_string(((hybrid_type == DECIMAL_RESULT) ? + field= new Field_string(((hybrid_type == DECIMAL_RESULT) ? dec_bin_size : sizeof(double)) + sizeof(longlong), - 0, name, table, &my_charset_bin); + 0, name, &my_charset_bin); } - if (hybrid_type == DECIMAL_RESULT) - return new Field_new_decimal(max_length, maybe_null, name, table, + else if (hybrid_type == DECIMAL_RESULT) + field= new Field_new_decimal(max_length, maybe_null, name, decimals, unsigned_flag); - return new Field_double(max_length, maybe_null, name, table, decimals); + else + field= new Field_double(max_length, maybe_null, name, decimals); + if (field) + field->init(table); + return field; } @@ -1244,6 +1262,7 @@ Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table, uint convert_blob_len) { + Field *field; if (group) { /* @@ -1251,15 +1270,19 @@ The easyest way is to do this is to store both value in a string and unpack on access. */ - return new Field_string(((hybrid_type == DECIMAL_RESULT) ? + field= new Field_string(((hybrid_type == DECIMAL_RESULT) ? dec_bin_size0 + dec_bin_size1 : sizeof(double)*2) + sizeof(longlong), - 0, name, table, &my_charset_bin); + 0, name, &my_charset_bin); } - if (hybrid_type == DECIMAL_RESULT) - return new Field_new_decimal(max_length, maybe_null, name, table, + else if (hybrid_type == DECIMAL_RESULT) + field= new Field_new_decimal(max_length, maybe_null, name, decimals, unsigned_flag); - return new Field_double(max_length, maybe_null,name,table,decimals); + else + field= new Field_double(max_length, maybe_null, name, decimals); + if (field) + field->init(table); + return field; } --- 1.353/sql/mysql_priv.h 2005-12-09 03:39:39 -08:00 +++ 1.354/sql/mysql_priv.h 2005-12-12 11:55:12 -08:00 @@ -48,6 +48,7 @@ typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */ #endif typedef ulong key_part_map; /* Used for finding key parts */ +typedef ulong nesting_map; /* Used for flags of nesting constructs */ /* Used to identify NESTED_JOIN structures within a join (applicable only to structures that have not been simplified away and embed more the one --- 1.285/sql/sql_base.cc 2005-12-12 03:59:05 -08:00 +++ 1.286/sql/sql_base.cc 2005-12-12 11:57:02 -08:00 @@ -4942,11 +4942,13 @@ { reg2 Item *item; ulong save_set_query_id= thd->set_query_id; + nesting_map save_allow_sum_func= thd->lex->allow_sum_func; List_iterator it(fields); DBUG_ENTER("setup_fields"); thd->set_query_id=set_query_id; - thd->allow_sum_func= allow_sum_func; + if (allow_sum_func) + thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; thd->where= THD::DEFAULT_WHERE; /* @@ -4969,6 +4971,7 @@ if (!item->fixed && item->fix_fields(thd, it.ref()) || (item= *(it.ref()))->check_cols(1)) { + thd->lex->allow_sum_func= save_allow_sum_func; thd->set_query_id= save_set_query_id; DBUG_RETURN(TRUE); /* purecov: inspected */ } @@ -4979,6 +4982,7 @@ item->split_sum_func(thd, ref_pointer_array, *sum_func_list); thd->used_tables|= item->used_tables(); } + thd->lex->allow_sum_func= save_allow_sum_func; thd->set_query_id= save_set_query_id; DBUG_RETURN(test(thd->net.report_error)); } --- 1.223/sql/sql_class.cc 2005-12-10 23:30:52 -08:00 +++ 1.224/sql/sql_class.cc 2005-12-12 11:55:12 -08:00 @@ -288,7 +288,7 @@ variables.date_format); variables.datetime_format= date_time_format_copy((THD*) 0, variables.datetime_format); -#ifdef HAVE_NDBCLUSTER_DB +#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE variables.ndb_use_transactions= 1; #endif pthread_mutex_unlock(&LOCK_global_system_variables); @@ -665,7 +665,8 @@ DBUG_ASSERT((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && table->file->has_transactions()); - add_changed_table(table->s->table_cache_key, table->s->key_length); + add_changed_table(table->s->table_cache_key.str, + table->s->table_cache_key.length); DBUG_VOID_RETURN; } @@ -909,7 +910,7 @@ return 0; } -#ifdef HAVE_INNOBASE_DB +#ifdef WITH_INNOBASE_STORAGE_ENGINE /* We may be passing the control from mysqld to the client: release the InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved @@ -945,7 +946,7 @@ bool select_send::send_eof() { -#ifdef HAVE_INNOBASE_DB +#ifdef WITH_INNOBASE_STORAGE_ENGINE /* We may be passing the control from mysqld to the client: release the InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved by thd */ @@ -1060,7 +1061,8 @@ if (!dirname_length(exchange->file_name)) { - strxnmov(path, FN_REFLEN, mysql_real_data_home, thd->db ? thd->db : "", NullS); + strxnmov(path, FN_REFLEN-1, mysql_real_data_home, thd->db ? thd->db : "", + NullS); (void) fn_format(path, exchange->file_name, path, "", option); } else --- 1.276/sql/sql_class.h 2005-12-12 03:30:12 -08:00 +++ 1.277/sql/sql_class.h 2005-12-12 11:55:13 -08:00 @@ -791,19 +791,6 @@ and update_row */ ulong set_query_id; - /* - This variable is used in post-parse stage to declare that sum-functions, - or functions which have sense only if GROUP BY is present, are allowed. - For example in queries - SELECT MIN(i) FROM foo - SELECT GROUP_CONCAT(a, b, MIN(i)) FROM ... GROUP BY ... - MIN(i) have no sense. - Though it's grammar-related issue, it's hard to catch it out during the - parse stage because GROUP BY clause goes in the end of query. This - variable is mainly used in setup_fields/fix_fields. - See item_sum.cc for details. - */ - bool allow_sum_func; LEX_STRING name; /* name for named prepared statements */ LEX *lex; // parse tree descriptor --- 1.121/sql/sql_db.cc 2005-11-23 12:44:56 -08:00 +++ 1.122/sql/sql_db.cc 2005-12-12 11:55:13 -08:00 @@ -1162,10 +1162,12 @@ DBUG_RETURN(1); } end: - x_free(thd->db); + if (!(thd->slave_thread)) + x_free(thd->db); if (dbname && dbname[0] == 0) { - x_free(dbname); + if (!(thd->slave_thread)) + x_free(dbname); thd->db= NULL; thd->db_length= 0; } --- 1.159/sql/sql_delete.cc 2005-11-23 12:44:56 -08:00 +++ 1.160/sql/sql_delete.cc 2005-12-12 11:55:13 -08:00 @@ -301,6 +301,7 @@ if (!transactional_table) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } + free_underlaid_joins(thd, select_lex); if (transactional_table) { if (ha_autocommit_or_rollback(thd,error >= 0)) @@ -312,7 +313,6 @@ mysql_unlock_tables(thd, thd->lock); thd->lock=0; } - free_underlaid_joins(thd, select_lex); if (error < 0) { thd->row_count_func= deleted; @@ -341,7 +341,7 @@ SELECT_LEX *select_lex= &thd->lex->select_lex; DBUG_ENTER("mysql_prepare_delete"); - thd->allow_sum_func= 0; + thd->lex->allow_sum_func= 0; if (setup_tables(thd, &thd->lex->select_lex.context, &thd->lex->select_lex.top_join_list, table_list, conds, &select_lex->leaf_tables, --- 1.177/sql/sql_insert.cc 2005-12-06 22:28:11 -08:00 +++ 1.178/sql/sql_insert.cc 2005-12-12 11:55:13 -08:00 @@ -270,7 +270,7 @@ */ bool log_on= (thd->options & OPTION_BIN_LOG) || (!(thd->security_ctx->master_access & SUPER_ACL)); - bool transactional_table; + bool transactional_table, joins_freed= FALSE; uint value_count; ulong counter = 1; ulonglong id; @@ -526,6 +526,9 @@ thd->row_count++; } + free_underlaid_joins(thd, &thd->lex->select_lex); + joins_freed= TRUE; + /* Now all rows are inserted. Time to update logs and sends response to user @@ -624,7 +627,6 @@ thd->row_count_func= info.copied+info.deleted+info.updated; ::send_ok(thd, (ulong) thd->row_count_func, id, buff); } - free_underlaid_joins(thd, &thd->lex->select_lex); thd->abort_on_warning= 0; DBUG_RETURN(FALSE); @@ -633,7 +635,8 @@ if (lock_type == TL_WRITE_DELAYED) end_delayed_insert(thd); #endif - free_underlaid_joins(thd, &thd->lex->select_lex); + if (!joins_freed) + free_underlaid_joins(thd, &thd->lex->select_lex); thd->abort_on_warning= 0; DBUG_RETURN(TRUE); } --- 1.168/sql/sql_lex.cc 2005-12-06 22:28:11 -08:00 +++ 1.169/sql/sql_lex.cc 2005-12-12 11:55:13 -08:00 @@ -184,6 +184,9 @@ lex->sroutines_list.empty(); lex->sroutines_list_own_last= lex->sroutines_list.next; lex->sroutines_list_own_elements= 0; + lex->nest_level=0 ; + lex->allow_sum_func= 0; + lex->in_sum_func= NULL; DBUG_VOID_RETURN; } @@ -1147,6 +1150,7 @@ first_cond_optimization= 1; parsing_place= NO_MATTER; exclude_from_table_unique_test= no_wrap_view_item= FALSE; + nest_level= 0; link_next= 0; } @@ -1166,6 +1170,7 @@ interval_list.empty(); use_index.empty(); ftfunc_list_alloc.empty(); + inner_sum_func_list= 0; ftfunc_list= &ftfunc_list_alloc; linkage= UNSPECIFIED_TYPE; order_list.elements= 0; --- 1.209/sql/sql_lex.h 2005-12-06 22:28:12 -08:00 +++ 1.210/sql/sql_lex.h 2005-12-12 11:55:13 -08:00 @@ -531,6 +531,8 @@ ulong table_join_options; uint in_sum_expr; uint select_number; /* number of select (used for EXPLAIN) */ + int nest_level; /* nesting level of select */ + Item_sum *inner_sum_func_list; /* list of sum func in nested selects */ uint with_wild; /* item list contain '*' */ bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */ /* TRUE when having fix field called in processing of this SELECT */ @@ -794,12 +796,23 @@ SQL_LIST proc_list, auxilliary_table_list, save_list; create_field *last_field; + Item_sum *in_sum_func; udf_func udf; HA_CHECK_OPT check_opt; // check/repair options HA_CREATE_INFO create_info; LEX_MASTER_INFO mi; // used by CHANGE MASTER USER_RESOURCES mqh; ulong type; + /* + This variable is used in post-parse stage to declare that sum-functions, + or functions which have sense only if GROUP BY is present, are allowed. + For example in a query + SELECT ... FROM ...WHERE MIN(i) == 1 GROUP BY ... HAVING MIN(i) > 2 + MIN(i) in the WHERE clause is not allowed in the opposite to MIN(i) + in the HAVING clause. Due to possible nesting of select construct + the variable can contain 0 or 1 for each nest level. + */ + nesting_map allow_sum_func; enum_sql_command sql_command, orig_sql_command; thr_lock_type lock_option; enum SSL_type ssl_type; /* defined in violite.h */ @@ -818,6 +831,7 @@ uint grant, grant_tot_col, which_columns; uint fk_delete_opt, fk_update_opt, fk_match_option; uint slave_thd_opt, start_transaction_opt; + int nest_level; /* In LEX representing update which were transformed to multi-update stores total number of tables. For LEX representing multi-delete --- 1.496/sql/sql_parse.cc 2005-12-12 03:59:06 -08:00 +++ 1.497/sql/sql_parse.cc 2005-12-12 11:55:13 -08:00 @@ -5428,6 +5428,8 @@ select_lex->parent_lex= lex; /* Used in init_query. */ select_lex->init_query(); select_lex->init_select(); + lex->nest_level++; + select_lex->nest_level= lex->nest_level; /* Don't evaluate this subquery during statement prepare even if it's a constant one. The flag is switched off in the end of --- 1.374/sql/sql_select.cc 2005-12-12 02:29:42 -08:00 +++ 1.375/sql/sql_select.cc 2005-12-12 11:55:13 -08:00 @@ -274,21 +274,20 @@ ORDER *order, ORDER *group, bool *hidden_group_fields) { - bool save_allow_sum_func; int res; + nesting_map save_allow_sum_func=thd->lex->allow_sum_func ; DBUG_ENTER("setup_without_group"); - save_allow_sum_func= thd->allow_sum_func; - thd->allow_sum_func= 0; + thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level); res= setup_conds(thd, tables, leaves, conds); - thd->allow_sum_func= save_allow_sum_func; + thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields, order); - thd->allow_sum_func= 0; + thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level); res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields, group, hidden_group_fields); - thd->allow_sum_func= save_allow_sum_func; + thd->lex->allow_sum_func= save_allow_sum_func; DBUG_RETURN(res); } @@ -355,8 +354,9 @@ if (having) { + nesting_map save_allow_sum_func= thd->lex->allow_sum_func; thd->where="having clause"; - thd->allow_sum_func=1; + thd->lex->allow_sum_func|= 1 << select_lex_arg->nest_level; select_lex->having_fix_field= 1; bool having_fix_rc= (!having->fixed && (having->fix_fields(thd, &having) || @@ -366,6 +366,18 @@ DBUG_RETURN(-1); /* purecov: inspected */ if (having->with_sum_func) having->split_sum_func(thd, ref_pointer_array, all_fields); + thd->lex->allow_sum_func= save_allow_sum_func; + } + if (select_lex->inner_sum_func_list) + { + Item_sum *end=select_lex->inner_sum_func_list; + Item_sum *item_sum= end; + do + { + item_sum= item_sum->next; + item_sum->split_sum_func2(thd, ref_pointer_array, + all_fields, item_sum->ref_by, FALSE); + } while (item_sum != end); } if (!thd->lex->view_prepare_mode) @@ -5231,7 +5243,9 @@ join->const_table_map|=RAND_TABLE_BIT; { // Check const tables COND *const_cond= - make_cond_for_table(cond,join->const_table_map,(table_map) 0); + make_cond_for_table(cond, + join->const_table_map, + (table_map) 0); DBUG_EXECUTE("where",print_where(const_cond,"constants");); for (JOIN_TAB *tab= join->join_tab+join->const_tables; tab < join->join_tab+join->tables ; tab++) --- 1.178/sql/sql_update.cc 2005-12-02 11:07:08 -08:00 +++ 1.179/sql/sql_update.cc 2005-12-12 11:55:14 -08:00 @@ -632,6 +632,7 @@ if (!transactional_table) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } + free_underlaid_joins(thd, select_lex); if (transactional_table) { if (ha_autocommit_or_rollback(thd, error >= 0)) @@ -644,7 +645,6 @@ thd->lock=0; } - free_underlaid_joins(thd, select_lex); if (error < 0) { char buff[STRING_BUFFER_USUAL_SIZE]; @@ -706,7 +706,7 @@ bzero((char*) &tables,sizeof(tables)); // For ORDER BY tables.table= table; tables.alias= table_list->alias; - thd->allow_sum_func= 0; + thd->lex->allow_sum_func= 0; if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list, table_list, conds, &select_lex->leaf_tables, --- 1.429/sql/sql_yacc.yy 2005-12-09 03:39:41 -08:00 +++ 1.430/sql/sql_yacc.yy 2005-12-12 11:55:14 -08:00 @@ -5061,7 +5061,7 @@ } $$= new Item_default_value(Lex->current_context(), $3); } - | VALUES '(' simple_ident ')' + | VALUES '(' simple_ident_nospvar ')' { $$= new Item_insert_value(Lex->current_context(), $3); } | FUNC_ARG0 '(' ')' { @@ -9549,6 +9549,7 @@ LEX *lex=Lex; lex->pop_context(); lex->current_select = lex->current_select->return_after_parsing(); + lex->nest_level--; }; definer: --- 1.120/sql/item_subselect.cc 2005-11-23 12:47:27 -08:00 +++ 1.121/sql/item_subselect.cc 2005-12-12 11:55:12 -08:00 @@ -806,6 +806,7 @@ !(select_lex->next_select())) { Item_sum_hybrid *item; + nesting_map save_allow_sum_func; if (func->l_op()) { /* @@ -831,6 +832,8 @@ it.replace(item); } + save_allow_sum_func= thd->lex->allow_sum_func; + thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; /* Item_sum_(max|min) can't substitute other item => we can use 0 as reference, also Item_sum_(max|min) can't be fixed after creation, so @@ -838,6 +841,7 @@ */ if (item->fix_fields(thd, 0)) DBUG_RETURN(RES_ERROR); + thd->lex->allow_sum_func= save_allow_sum_func; /* we added aggregate function => we have to change statistic */ count_field_types(&join->tmp_table_param, join->all_fields, 0); --- 1.175/mysql-test/r/sp.result 2005-12-12 03:30:11 -08:00 +++ 1.176/mysql-test/r/sp.result 2005-12-12 11:55:12 -08:00 @@ -4110,23 +4110,23 @@ x 4711 drop procedure bug14376| -drop procedure if exists p1| -drop table if exists t1| -create table t1 (a varchar(255))| -insert into t1 (a) values ("a - table column")| -create procedure p1(a varchar(255)) +drop procedure if exists bug5967| +drop table if exists t3| +create table t3 (a varchar(255))| +insert into t3 (a) values ("a - table column")| +create procedure bug5967(a varchar(255)) begin declare i varchar(255); -declare c cursor for select a from t1; +declare c cursor for select a from t3; select a; -select a from t1 into i; +select a from t3 into i; select i as 'Parameter takes precedence over table column'; open c; fetch c into i; close c; select i as 'Parameter takes precedence over table column in cursors'; begin declare a varchar(255) default 'a - local variable'; -declare c1 cursor for select a from t1; +declare c1 cursor for select a from t3; select a as 'A local variable takes precedence over parameter'; open c1; fetch c1 into i; @@ -4134,9 +4134,9 @@ select i as 'A local variable takes precedence over parameter in cursors'; begin declare a varchar(255) default 'a - local variable in a nested compound statement'; -declare c2 cursor for select a from t1; +declare c2 cursor for select a from t3; select a as 'A local variable in a nested compound statement takes precedence over a local variable in the outer statement'; -select a from t1 into i; +select a from t3 into i; select i as 'A local variable in a nested compound statement takes precedence over table column'; open c2; fetch c2 into i; @@ -4145,7 +4145,7 @@ end; end; end| -call p1("a - stored procedure parameter")| +call bug5967("a - stored procedure parameter")| a a - stored procedure parameter Parameter takes precedence over table column @@ -4162,7 +4162,7 @@ a - local variable in a nested compound statement A local variable in a nested compound statement takes precedence over table column in cursors a - local variable in a nested compound statement -drop procedure p1| +drop procedure bug5967| drop procedure if exists bug13012| create procedure bug13012() BEGIN @@ -4190,17 +4190,17 @@ Table Op Msg_type Msg_text test.t1 repair status OK test.t2 repair status OK -test.t3 repair error Table 'test.t3' doesn't exist +test.t3 repair status OK test.v1 repair error 'test.v1' is not BASE TABLE Table Op Msg_type Msg_text test.t1 optimize status OK test.t2 optimize status OK -test.t3 optimize error Table 'test.t3' doesn't exist +test.t3 optimize status OK test.v1 optimize error 'test.v1' is not BASE TABLE Table Op Msg_type Msg_text test.t1 analyze status Table is already up to date test.t2 analyze status Table is already up to date -test.t3 analyze error Table 'test.t3' doesn't exist +test.t3 analyze status Table is already up to date test.v1 analyze error 'test.v1' is not BASE TABLE Warnings: Error 1146 Table 'test.t3' doesn't exist @@ -4213,17 +4213,17 @@ Table Op Msg_type Msg_text test.t1 repair status OK test.t2 repair status OK -test.t3 repair error Table 'test.t3' doesn't exist +test.t3 repair status OK test.v1 repair error 'test.v1' is not BASE TABLE Table Op Msg_type Msg_text test.t1 optimize status OK test.t2 optimize status OK -test.t3 optimize error Table 'test.t3' doesn't exist +test.t3 optimize status OK test.v1 optimize error 'test.v1' is not BASE TABLE Table Op Msg_type Msg_text test.t1 analyze status Table is already up to date test.t2 analyze status Table is already up to date -test.t3 analyze error Table 'test.t3' doesn't exist +test.t3 analyze status Table is already up to date test.v1 analyze error 'test.v1' is not BASE TABLE Warnings: Error 1146 Table 'test.t3' doesn't exist @@ -4236,17 +4236,17 @@ Table Op Msg_type Msg_text test.t1 repair status OK test.t2 repair status OK -test.t3 repair error Table 'test.t3' doesn't exist +test.t3 repair status OK test.v1 repair error 'test.v1' is not BASE TABLE Table Op Msg_type Msg_text test.t1 optimize status OK test.t2 optimize status OK -test.t3 optimize error Table 'test.t3' doesn't exist +test.t3 optimize status OK test.v1 optimize error 'test.v1' is not BASE TABLE Table Op Msg_type Msg_text test.t1 analyze status Table is already up to date test.t2 analyze status Table is already up to date -test.t3 analyze error Table 'test.t3' doesn't exist +test.t3 analyze status Table is already up to date test.v1 analyze error 'test.v1' is not BASE TABLE Warnings: Error 1146 Table 'test.t3' doesn't exist @@ -4258,8 +4258,17 @@ drop procedure bug13012| drop view v1; select * from t1| -a -a - table column +id data +aa 0 +aa 1 +aa 2 +aa 3 +aa 4 +aa 5 +aa 6 +aa 7 +aa 8 +aa 9 drop schema if exists mysqltest1| Warnings: Note 1008 Can't drop database 'mysqltest1'; database doesn't exist @@ -4299,4 +4308,31 @@ drop schema if exists mysqltest2| drop schema if exists mysqltest3| use test| +drop table if exists t3| +drop procedure if exists bug15441| +create table t3 (id int not null primary key, county varchar(25))| +insert into t3 (id, county) values (1, 'York')| +create procedure bug15441(c varchar(25)) +begin +update t3 set id=2, county=values(c); +end| +call bug15441('county')| +ERROR 42S22: Unknown column 'c' in 'field list' +drop procedure bug15441| +create procedure bug15441(county varchar(25)) +begin +declare c varchar(25) default "hello"; +insert into t3 (id, county) values (1, county) +on duplicate key update county= values(county); +select * from t3; +update t3 set id=2, county=values(id); +select * from t3; +end| +call bug15441('Yale')| +id county +1 Yale +id county +2 NULL +drop table t3| +drop procedure bug15441| drop table t1,t2; --- 1.156/sql/sql_prepare.cc 2005-11-23 04:04:13 -08:00 +++ 1.157/sql/sql_prepare.cc 2005-12-12 11:55:13 -08:00 @@ -2131,7 +2131,8 @@ lex->result->cleanup(); lex->result->set_thd(thd); } - thd->allow_sum_func= 0; + lex->allow_sum_func= 0; + lex->in_sum_func= NULL; DBUG_VOID_RETURN; }