diff options
author | unknown <brian@avenger.(none)> | 2004-12-06 09:10:30 -0800 |
---|---|---|
committer | unknown <brian@avenger.(none)> | 2004-12-06 09:10:30 -0800 |
commit | e0dad0555d0721529b6b46fc75c99c20607a0c13 (patch) | |
tree | 2e1b4da222d683c1d04efbc2fd6a0acf35f1ae14 /sql | |
parent | 9740a87671a209340dc1d0a7f1ab05f23e4f9de5 (diff) | |
parent | 19a95482195a158425c66ac629d07da53e4fc1b6 (diff) | |
download | mariadb-git-e0dad0555d0721529b6b46fc75c99c20607a0c13.tar.gz |
Merge
sql/handler.h:
Auto merged
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 39 | ||||
-rw-r--r-- | sql/field.h | 1 | ||||
-rw-r--r-- | sql/handler.cc | 4 | ||||
-rw-r--r-- | sql/item.cc | 2 | ||||
-rw-r--r-- | sql/item.h | 6 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 12 | ||||
-rw-r--r-- | sql/item_func.cc | 2 | ||||
-rw-r--r-- | sql/lock.cc | 65 | ||||
-rw-r--r-- | sql/log.cc | 15 | ||||
-rw-r--r-- | sql/log_event.cc | 22 | ||||
-rw-r--r-- | sql/log_event.h | 20 | ||||
-rw-r--r-- | sql/mysql_priv.h | 3 | ||||
-rw-r--r-- | sql/mysqld.cc | 4 | ||||
-rw-r--r-- | sql/set_var.cc | 9 | ||||
-rw-r--r-- | sql/slave.cc | 2 | ||||
-rw-r--r-- | sql/slave.h | 2 | ||||
-rw-r--r-- | sql/sql_acl.cc | 7 | ||||
-rw-r--r-- | sql/sql_base.cc | 4 | ||||
-rw-r--r-- | sql/sql_class.h | 12 | ||||
-rw-r--r-- | sql/sql_db.cc | 44 | ||||
-rw-r--r-- | sql/sql_delete.cc | 6 | ||||
-rw-r--r-- | sql/sql_derived.cc | 6 | ||||
-rw-r--r-- | sql/sql_insert.cc | 85 | ||||
-rw-r--r-- | sql/sql_lex.cc | 3 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 128 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 13 | ||||
-rw-r--r-- | sql/sql_rename.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 57 | ||||
-rw-r--r-- | sql/sql_show.cc | 9 | ||||
-rw-r--r-- | sql/sql_table.cc | 159 | ||||
-rw-r--r-- | sql/sql_update.cc | 10 | ||||
-rw-r--r-- | sql/sql_view.cc | 5 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 20 |
34 files changed, 504 insertions, 276 deletions
diff --git a/sql/field.cc b/sql/field.cc index 5e76c590aac..73caddf1d0b 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5869,25 +5869,24 @@ bool Field_num::eq_def(Field *field) void create_field::create_length_to_internal_length(void) { - switch (sql_type) - { - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_STRING: - length*= charset->mbmaxlen; - pack_length= calc_pack_length(sql_type == FIELD_TYPE_VAR_STRING ? - FIELD_TYPE_STRING : sql_type, length); - break; - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_SET: - length*= charset->mbmaxlen; - break; - default: - /* do nothing */ - break; + switch (sql_type) { + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_STRING: + length*= charset->mbmaxlen; + pack_length= calc_pack_length(sql_type == FIELD_TYPE_VAR_STRING ? + FIELD_TYPE_STRING : sql_type, length); + break; + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: + length*= charset->mbmaxlen; + break; + default: + /* do nothing */ + break; } } @@ -6112,6 +6111,8 @@ create_field::create_field(Field *old_field,Field *orig_field) } length=(length+charset->mbmaxlen-1)/charset->mbmaxlen; // QQ: Probably not needed break; + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: case FIELD_TYPE_STRING: case FIELD_TYPE_VAR_STRING: length=(length+charset->mbmaxlen-1)/charset->mbmaxlen; diff --git a/sql/field.h b/sql/field.h index d1c2fa3b6fd..b4e8e61e3fb 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1196,6 +1196,7 @@ public: uint decimals,flags,pack_length; Field::utype unireg_check; TYPELIB *interval; // Which interval to use + List<String> interval_list; CHARSET_INFO *charset; Field::geometry_type geom_type; Field *field; // For alter table diff --git a/sql/handler.cc b/sql/handler.cc index b474e6290f2..edb4d5b488b 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -736,7 +736,7 @@ int ha_rollback_to_savepoint(THD *thd, char *savepoint_name) if (unlikely((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && my_b_tell(&thd->transaction.trans_log))) { - Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE); + Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); if (mysql_bin_log.write(&qinfo)) error= 1; } @@ -774,7 +774,7 @@ int ha_savepoint(THD *thd, char *savepoint_name) innobase_savepoint(thd,savepoint_name, my_b_tell(&thd->transaction.trans_log)); #endif - Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE); + Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); if (mysql_bin_log.write(&qinfo)) error= 1; } diff --git a/sql/item.cc b/sql/item.cc index 001fbef9505..03bbbe2ad49 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -187,6 +187,7 @@ Item_ident::Item_ident(THD *thd, Item_ident *item) void Item_ident::cleanup() { DBUG_ENTER("Item_ident::cleanup"); +#ifdef CANT_BE_USED_AS_MEMORY_IS_FREED DBUG_PRINT("enter", ("b:%s(%s), t:%s(%s), f:%s(%s)", db_name ? db_name : "(null)", orig_db_name ? orig_db_name : "(null)", @@ -194,6 +195,7 @@ void Item_ident::cleanup() orig_table_name ? orig_table_name : "(null)", field_name ? field_name : "(null)", orig_field_name ? orig_field_name : "(null)")); +#endif Item::cleanup(); db_name= orig_db_name; table_name= orig_table_name; diff --git a/sql/item.h b/sql/item.h index 2c2978e841c..973039f9127 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1375,7 +1375,7 @@ class Item_cache_int: public Item_cache { longlong value; public: - Item_cache_int(): Item_cache() {} + Item_cache_int(): Item_cache(), value(0) {} void store(Item *item); double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; } @@ -1393,7 +1393,7 @@ class Item_cache_real: public Item_cache { double value; public: - Item_cache_real(): Item_cache() {} + Item_cache_real(): Item_cache(), value(0) {} void store(Item *item); double val_real() { DBUG_ASSERT(fixed == 1); return value; } @@ -1415,7 +1415,7 @@ class Item_cache_str: public Item_cache char buffer[80]; String *value, value_buff; public: - Item_cache_str(): Item_cache() { } + Item_cache_str(): Item_cache(), value(0) { } void store(Item *item); double val_real(); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 389a614e3d5..7611b70c6a4 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2430,10 +2430,10 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) } int error; if ((error= regcomp(&preg,res->c_ptr(), - ((cmp_collation.collation->state & MY_CS_BINSORT) || - (cmp_collation.collation->state & MY_CS_CSSORT)) ? + ((cmp_collation.collation->state & + (MY_CS_BINSORT | MY_CS_CSSORT)) ? REG_EXTENDED | REG_NOSUB : - REG_EXTENDED | REG_NOSUB | REG_ICASE, + REG_EXTENDED | REG_NOSUB | REG_ICASE), cmp_collation.collation))) { (void) regerror(error,&preg,buff,sizeof(buff)); @@ -2482,10 +2482,10 @@ longlong Item_func_regex::val_int() regex_compiled=0; } if (regcomp(&preg,res2->c_ptr(), - ((cmp_collation.collation->state & MY_CS_BINSORT) || - (cmp_collation.collation->state & MY_CS_CSSORT)) ? + ((cmp_collation.collation->state & + (MY_CS_BINSORT | MY_CS_CSSORT)) ? REG_EXTENDED | REG_NOSUB : - REG_EXTENDED | REG_NOSUB | REG_ICASE, + REG_EXTENDED | REG_NOSUB | REG_ICASE), cmp_collation.collation)) { null_value=1; diff --git a/sql/item_func.cc b/sql/item_func.cc index eb3db156056..8fefb355efe 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2098,7 +2098,7 @@ void item_user_lock_release(User_level_lock *ull) tmp.copy(command, strlen(command), tmp.charset()); tmp.append(ull->key,ull->key_length); tmp.append("\")", 2); - Query_log_event qev(current_thd, tmp.ptr(), tmp.length(),1); + Query_log_event qev(current_thd, tmp.ptr(), tmp.length(),1, FALSE); qev.error_code=0; // this query is always safe to run on slave mysql_bin_log.write(&qev); } diff --git a/sql/lock.cc b/sql/lock.cc index 3367c6a2900..8a3619b57dd 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -707,15 +707,70 @@ static void print_lock_error(int error) /**************************************************************************** Handling of global read locks + Taking the global read lock is TWO steps (2nd step is optional; without + it, COMMIT of existing transactions will be allowed): + lock_global_read_lock() THEN make_global_read_lock_block_commit(). + The global locks are handled through the global variables: global_read_lock + count of threads which have the global read lock (i.e. have completed at + least the first step above) global_read_lock_blocks_commit - waiting_for_read_lock + count of threads which have the global read lock and block + commits (i.e. have completed the second step above) + waiting_for_read_lock + count of threads which want to take a global read lock but cannot protect_against_global_read_lock + count of threads which have set protection against global read lock. + + How blocking of threads by global read lock is achieved: that's + advisory. Any piece of code which should be blocked by global read lock must + be designed like this: + - call to wait_if_global_read_lock(). When this returns 0, no global read + lock is owned; if argument abort_on_refresh was 0, none can be obtained. + - job + - if abort_on_refresh was 0, call to start_waiting_global_read_lock() to + allow other threads to get the global read lock. I.e. removal of the + protection. + (Note: it's a bit like an implementation of rwlock). + + [ I am sorry to mention some SQL syntaxes below I know I shouldn't but found + no better descriptive way ] + + Why does FLUSH TABLES WITH READ LOCK need to block COMMIT: because it's used + to read a non-moving SHOW MASTER STATUS, and a COMMIT writes to the binary + log. + + Why getting the global read lock is two steps and not one. Because FLUSH + TABLES WITH READ LOCK needs to insert one other step between the two: + flushing tables. So the order is + 1) lock_global_read_lock() (prevents any new table write locks, i.e. stalls + all new updates) + 2) close_cached_tables() (the FLUSH TABLES), which will wait for tables + currently opened and being updated to close (so it's possible that there is + a moment where all new updates of server are stalled *and* FLUSH TABLES WITH + READ LOCK is, too). + 3) make_global_read_lock_block_commit(). + If we have merged 1) and 3) into 1), we would have had this deadlock: + imagine thread 1 and 2, in non-autocommit mode, thread 3, and an InnoDB + table t. + thd1: SELECT * FROM t FOR UPDATE; + thd2: UPDATE t SET a=1; # blocked by row-level locks of thd1 + thd3: FLUSH TABLES WITH READ LOCK; # blocked in close_cached_tables() by the + table instance of thd2 + thd1: COMMIT; # blocked by thd3. + thd1 blocks thd2 which blocks thd3 which blocks thd1: deadlock. + + Note that we need to support that one thread does + FLUSH TABLES WITH READ LOCK; and then COMMIT; + (that's what innobackup does, for some good reason). + So in this exceptional case the COMMIT should not be blocked by the FLUSH + TABLES WITH READ LOCK. + + TODO in MySQL 5.x: make_global_read_lock_block_commit() should be + killable. Normally CPU does not spend a long time in this function (COMMITs + are quite fast), but it would still be nice. - Taking the global read lock is TWO steps (2nd step is optional; without - it, COMMIT of existing transactions will be allowed): - lock_global_read_lock() THEN make_global_read_lock_block_commit(). ****************************************************************************/ volatile uint global_read_lock=0; @@ -831,6 +886,8 @@ void start_waiting_global_read_lock(THD *thd) { bool tmp; DBUG_ENTER("start_waiting_global_read_lock"); + if (unlikely(thd->global_read_lock)) + DBUG_VOID_RETURN; (void) pthread_mutex_lock(&LOCK_open); tmp= (!--protect_against_global_read_lock && waiting_for_read_lock); (void) pthread_mutex_unlock(&LOCK_open); diff --git a/sql/log.cc b/sql/log.cc index 75a1743febc..c659a3ede2e 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -383,8 +383,7 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, master (it has binlog version of the master, event types of the master), so this is suitable to parse the next relay log's event. It has been produced by - Format_description_log_event::Format_description_log_event(char* - buf,). + Format_description_log_event::Format_description_log_event(char* buf,). Why don't we want to write the description_event_for_queue if this event is for format<4 (3.23 or 4.x): this is because in that case, the description_event_for_queue describes the data received from the @@ -1326,7 +1325,7 @@ bool MYSQL_LOG::write(Log_event* event_info) (local_db && !db_ok(local_db, binlog_do_db, binlog_ignore_db))) { VOID(pthread_mutex_unlock(&LOCK_log)); - DBUG_PRINT("error",("!db_ok")); + DBUG_PRINT("error",("!db_ok('%s')", local_db)); DBUG_RETURN(0); } #endif /* HAVE_REPLICATION */ @@ -1369,7 +1368,7 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u", (uint) thd->variables.collation_connection->number, (uint) thd->variables.collation_database->number, (uint) thd->variables.collation_server->number); - Query_log_event e(thd, buf, written, 0); + Query_log_event e(thd, buf, written, 0, FALSE); if (e.write(file)) goto err; } @@ -1384,7 +1383,7 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u", char *buf_end= strxmov(buf, "SET ONE_SHOT TIME_ZONE='", thd->variables.time_zone->get_name()->ptr(), "'", NullS); - Query_log_event e(thd, buf, buf_end - buf, 0); + Query_log_event e(thd, buf, buf_end - buf, 0, FALSE); if (e.write(file)) goto err; } @@ -1430,7 +1429,7 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u", char buf[256], *p; p= strmov(strmov(buf, "SET CHARACTER SET "), thd->variables.convert_set->name); - Query_log_event e(thd, buf, (ulong) (p - buf), 0); + Query_log_event e(thd, buf, (ulong) (p - buf), 0, FALSE); if (e.write(file)) goto err; } @@ -1611,7 +1610,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback) we will add the "COMMIT mark and write the buffer to the binlog. */ { - Query_log_event qinfo(thd, "BEGIN", 5, TRUE); + Query_log_event qinfo(thd, "BEGIN", 5, TRUE, FALSE); /* Imagine this is rollback due to net timeout, after all statements of the transaction succeeded. Then we want a zero-error code in BEGIN. @@ -1651,7 +1650,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback) Query_log_event qinfo(thd, commit_or_rollback ? "COMMIT" : "ROLLBACK", commit_or_rollback ? 6 : 8, - TRUE); + TRUE, FALSE); qinfo.error_code= 0; if (qinfo.write(&log_file) || flush_io_cache(&log_file) || sync_binlog(&log_file)) diff --git a/sql/log_event.cc b/sql/log_event.cc index 77769f0e7e8..760436592b9 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -921,7 +921,8 @@ void Query_log_event::pack_info(Protocol *protocol) if (!(buf= my_malloc(9 + db_len + q_len, MYF(MY_WME)))) return; pos= buf; - if (db && db_len) + if (!(flags & LOG_EVENT_SUPPRESS_USE_F) + && db && db_len) { pos= strmov(buf, "use `"); memcpy(pos, db, db_len); @@ -1077,9 +1078,12 @@ bool Query_log_event::write(IO_CACHE* file) #ifndef MYSQL_CLIENT Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, - ulong query_length, bool using_trans) - :Log_event(thd_arg, !thd_arg->tmp_table_used ? - 0 : LOG_EVENT_THREAD_SPECIFIC_F, using_trans), + ulong query_length, bool using_trans, + bool suppress_use) + :Log_event(thd_arg, + ((thd_arg->tmp_table_used ? LOG_EVENT_THREAD_SPECIFIC_F : 0) + | (suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0)), + using_trans), data_buf(0), query(query_arg), catalog(thd_arg->catalog), db(thd_arg->db), q_len((uint32) query_length), error_code((thd_arg->killed != THD::NOT_KILLED) ? @@ -1259,14 +1263,14 @@ void Query_log_event::print(FILE* file, bool short_form, (ulong) thread_id, (ulong) exec_time, error_code); } - if (db) + if (!(flags & LOG_EVENT_SUPPRESS_USE_F) && db) { - if ((different_db = memcmp(last_event_info->db, db, db_len + 1))) + if (different_db= memcmp(last_event_info->db, db, db_len + 1)) memcpy(last_event_info->db, db, db_len + 1); + if (db[0] && different_db) + fprintf(file, "use %s;\n", db); } - - if (db && db[0] && different_db) - fprintf(file, "use %s;\n", db); + end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10); *end++=';'; *end++='\n'; diff --git a/sql/log_event.h b/sql/log_event.h index 7f958749a98..390a8c8070d 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -329,6 +329,19 @@ struct sql_ex_info #define OPTIONS_WRITTEN_TO_BIN_LOG (OPTION_AUTO_IS_NULL | \ OPTION_NO_FOREIGN_KEY_CHECKS | OPTION_RELAXED_UNIQUE_CHECKS) +/* + Suppress the generation of 'USE' statements before the actual + statement. This flag should be set for any events that does not need + the current database set to function correctly. Most notable cases + are 'CREATE DATABASE' and 'DROP DATABASE'. + + This flags should only be used in exceptional circumstances, since + it introduce a significant change in behaviour regarding the + replication logic together with the flags --binlog-do-db and + --replicated-do-db. + */ +#define LOG_EVENT_SUPPRESS_USE_F 0x8 + enum Log_event_type { /* @@ -446,8 +459,9 @@ public: /* Some 16 flags. Only one is really used now; look above for - LOG_EVENT_TIME_F, LOG_EVENT_FORCED_ROTATE_F, LOG_EVENT_THREAD_SPECIFIC_F - for notes. + LOG_EVENT_TIME_F, LOG_EVENT_FORCED_ROTATE_F, + LOG_EVENT_THREAD_SPECIFIC_F, and LOG_EVENT_SUPPRESS_USE_F for + notes. */ uint16 flags; @@ -650,7 +664,7 @@ public: #ifndef MYSQL_CLIENT Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, - bool using_trans); + bool using_trans, bool suppress_use); const char* get_db() { return db; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 09bec0a9323..91d15dc1125 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -788,7 +788,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum enum_field_types type, uint type_modifier, Item *default_value, Item *on_update_value, LEX_STRING *comment, - char *change, TYPELIB *interval,CHARSET_INFO *cs, + char *change, List<String> *interval_list, + CHARSET_INFO *cs, uint uint_geom_type); void store_position_for_column(const char *name); bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc=0); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 27248ebaec2..42ae6982eb0 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2128,7 +2128,7 @@ extern "C" void *signal_hand(void *arg __attribute__((unused))) { reload_acl_and_cache((THD*) 0, (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST | - REFRESH_STATUS | REFRESH_GRANT | + REFRESH_GRANT | REFRESH_THREADS | REFRESH_HOSTS), (TABLE_LIST*) 0, NULL); // Flush logs mysql_print_status((THD*) 0); // Send debug some info @@ -4910,7 +4910,7 @@ log and this option does nothing anymore.", "Data file autoextend increment in megabytes", (gptr*) &srv_auto_extend_increment, (gptr*) &srv_auto_extend_increment, - 0, GET_LONG, REQUIRED_ARG, 8L, 1L, ~0L, 0, 1L, 0}, + 0, GET_LONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0}, {"innodb_buffer_pool_awe_mem_mb", OPT_INNODB_BUFFER_POOL_AWE_MEM_MB, "If Windows AWE is used, the size of InnoDB buffer pool allocated from the AWE memory.", (gptr*) &innobase_buffer_pool_awe_mem_mb, (gptr*) &innobase_buffer_pool_awe_mem_mb, 0, diff --git a/sql/set_var.cc b/sql/set_var.cc index 532547c2618..234ec6617c3 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2773,24 +2773,23 @@ sys_var *find_sys_var(const char *str, uint length) int sql_set_variables(THD *thd, List<set_var_base> *var_list) { - int error= 0; + int error; List_iterator_fast<set_var_base> it(*var_list); DBUG_ENTER("sql_set_variables"); set_var_base *var; while ((var=it++)) { - if ((error=var->check(thd))) + if ((error= var->check(thd))) goto err; } - if (!thd->net.report_error) + if (!(error= test(thd->net.report_error))) { it.rewind(); while ((var= it++)) error|= var->update(thd); // Returns 0, -1 or 1 } - else - error= 1; + err: free_underlaid_joins(thd, &thd->lex->select_lex); DBUG_RETURN(error); diff --git a/sql/slave.cc b/sql/slave.cc index e67def552bd..1e38d92ebc5 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -877,7 +877,7 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len) 1 should be logged/replicated */ -int tables_ok(THD* thd, TABLE_LIST* tables) +bool tables_ok(THD* thd, TABLE_LIST* tables) { bool some_tables_updating= 0; DBUG_ENTER("tables_ok"); diff --git a/sql/slave.h b/sql/slave.h index 1abe166c944..69d3dc38e78 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -494,7 +494,7 @@ bool show_master_info(THD* thd, MASTER_INFO* mi); bool show_binlog_info(THD* thd); /* See if the query uses any tables that should not be replicated */ -int tables_ok(THD* thd, TABLE_LIST* tables); +bool tables_ok(THD* thd, TABLE_LIST* tables); /* Check to see if the database is ok to operate on with respect to the diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 0c6b061aa0c..4d4923d16b8 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -446,7 +446,8 @@ void acl_free(bool end) SYNOPSIS acl_reload() - thd Thread handle + thd Thread handle. Note that this may be NULL if we refresh + because we got a signal */ void acl_reload(THD *thd) @@ -1313,7 +1314,7 @@ bool change_password(THD *thd, const char *host, const char *user, acl_user->host.hostname ? acl_user->host.hostname : "", new_password)); thd->clear_error(); - Query_log_event qinfo(thd, buff, query_length, 0); + Query_log_event qinfo(thd, buff, query_length, 0, FALSE); mysql_bin_log.write(&qinfo); DBUG_RETURN(0); } @@ -2153,7 +2154,7 @@ static int replace_column_table(GRANT_TABLE *g_t, { table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read(table->record[0], (byte*) table->field[0]->ptr, - table->key_info[0].key_length, + key_length, HA_READ_KEY_EXACT)) goto end; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 97e2a2cf0d0..3ead7163171 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -535,7 +535,7 @@ void close_temporary_tables(THD *thd) { /* The -1 is to remove last ',' */ thd->clear_error(); - Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0); + Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0, FALSE); /* Imagine the thread had created a temp table, then was doing a SELECT, and the SELECT was killed. Then it's not clever to mark the statement above as @@ -1587,7 +1587,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, { end = strxmov(strmov(query, "DELETE FROM `"), db,"`.`",name,"`", NullS); - Query_log_event qinfo(thd, query, (ulong)(end-query), 0); + Query_log_event qinfo(thd, query, (ulong)(end-query), 0, FALSE); mysql_bin_log.write(&qinfo); my_free(query, MYF(0)); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 083f90fc93e..6cec2c2c787 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1230,6 +1230,12 @@ public: void set_status_var_init(); }; +#define tmp_disable_binlog(A) \ + ulong save_options= (A)->options; \ + (A)->options&= ~OPTION_BIN_LOG; + +#define reenable_binlog(A) (A)->options= save_options; + /* Flags for the THD::system_thread (bitmap) variable */ #define SYSTEM_THREAD_DELAYED_INSERT 1 #define SYSTEM_THREAD_SLAVE_IO 2 @@ -1371,6 +1377,7 @@ class select_insert :public select_result_interceptor { ~select_insert(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); bool send_data(List<Item> &items); + virtual void store_values(List<Item> &values); void send_error(uint errcode,const char *err); bool send_eof(); /* not implemented: select_insert is never re-used in prepared statements */ @@ -1397,7 +1404,8 @@ public: lock(0) {} int prepare(List<Item> &list, SELECT_LEX_UNIT *u); - bool send_data(List<Item> &values); + void store_values(List<Item> &values); + void send_error(uint errcode,const char *err); bool send_eof(); void abort(); }; @@ -1447,7 +1455,7 @@ public: if (copy_field) /* Fix for Intel compiler */ { delete [] copy_field; - copy_field=0; + save_copy_field= copy_field= 0; } } }; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index ad4887146d8..3e606029bec 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -468,7 +468,29 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, } if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, query, query_length, 0); + Query_log_event qinfo(thd, query, query_length, 0, + /* suppress_use */ TRUE); + + /* + Write should use the database being created as the "current + database" and not the threads current database, which is the + default. If we do not change the "current database" to the + database being created, the CREATE statement will not be + replicated when using --binlog-do-db to select databases to be + replicated. + + An example (--binlog-do-db=sisyfos): + + CREATE DATABASE bob; # Not replicated + USE bob; # 'bob' is the current database + CREATE DATABASE sisyfos; # Not replicated since 'bob' is + # current database. + USE sisyfos; # Will give error on slave since + # database does not exist. + */ + qinfo.db = db; + qinfo.db_len = strlen(db); + mysql_bin_log.write(&qinfo); } send_ok(thd, result); @@ -517,7 +539,15 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, + /* suppress_use */ TRUE); + + // Write should use the database being created as the "current + // database" and not the threads current database, which is the + // default. + qinfo.db = db; + qinfo.db_len = strlen(db); + thd->clear_error(); mysql_bin_log.write(&qinfo); } @@ -623,7 +653,15 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) } if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, query, query_length, 0); + Query_log_event qinfo(thd, query, query_length, 0, + /* suppress_use */ TRUE); + + // Write should use the database being created as the "current + // database" and not the threads current database, which is the + // default. + qinfo.db = db; + qinfo.db_len = strlen(db); + thd->clear_error(); mysql_bin_log.write(&qinfo); } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 51cf085cfb5..f4c5b0f8b59 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -249,7 +249,7 @@ cleanup: if (error <= 0) thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - log_delayed); + log_delayed, FALSE); if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; } @@ -670,7 +670,7 @@ bool multi_delete::send_eof() if (error <= 0) thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - log_delayed); + log_delayed, FALSE); if (mysql_bin_log.write(&qinfo) && !normal_tables) local_error=1; // Log write failed: roll back the SQL statement } @@ -779,7 +779,7 @@ end: { thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - thd->tmp_table); + thd->tmp_table, FALSE); mysql_bin_log.write(&qinfo); } send_ok(thd); // This should return record count diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 10ef6a081b6..69511018880 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -77,7 +77,7 @@ mysql_handle_derived(LEX *lex, int (*processor)(THD*, LEX*, TABLE_LIST*)) Create temporary table structure (but do not fill it) SYNOPSIS - mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) + mysql_derived_prepare() thd Thread handle lex LEX for this thread orig_table_list TABLE_LIST for the upper SELECT @@ -103,6 +103,7 @@ int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) { SELECT_LEX_UNIT *unit= orig_table_list->derived; int res= 0; + DBUG_ENTER("mysql_derived_prepare"); if (unit) { SELECT_LEX *first_select= unit->first_select(); @@ -110,7 +111,6 @@ int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) select_union *derived_result; bool is_union= first_select->next_select() && first_select->next_select()->linkage == UNION_TYPE; - DBUG_ENTER("mysql_derived"); if (!(derived_result= new select_union(0))) DBUG_RETURN(1); // out of memory @@ -173,7 +173,7 @@ exit: } else if (orig_table_list->ancestor) orig_table_list->set_ancestor(); - return (res); + DBUG_RETURN(res); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 673d7425c36..0814c7a747e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -116,7 +116,8 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields, Item *item; TABLE_LIST *tbl= 0; table_map map= 0; - while (item= it++) + + while ((item= it++)) map|= item->used_tables(); if (table_list->check_single_table(&tbl, map) || tbl == 0) { @@ -455,7 +456,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (error <= 0) thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - log_delayed); + log_delayed, FALSE); if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; } @@ -1614,7 +1615,7 @@ bool delayed_insert::handle_inserts(void) } if (row->query && row->log_query && using_bin_log) { - Query_log_event qinfo(&thd, row->query, row->query_length,0); + Query_log_event qinfo(&thd, row->query, row->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } if (table->blob_fields) @@ -1795,7 +1796,6 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) restore_record(table,default_values); // Get empty record table->next_number_field=table->found_next_number_field; - thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields thd->cuted_fields=0; if (info.handle_duplicates == DUP_IGNORE || info.handle_duplicates == DUP_REPLACE) @@ -1834,35 +1834,48 @@ select_insert::~select_insert() bool select_insert::send_data(List<Item> &values) { DBUG_ENTER("select_insert::send_data"); + bool error=0; if (unit->offset_limit_cnt) { // using limit offset,count unit->offset_limit_cnt--; DBUG_RETURN(0); } - if (fields->elements) - fill_record(thd, *fields, values, 1); - else - fill_record(thd, table->field, values, 1); - switch (table_list->view_check_option(thd, - thd->lex->duplicates == DUP_IGNORE)) - { - case VIEW_CHECK_SKIP: - DBUG_RETURN(0); - case VIEW_CHECK_ERROR: + + thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields + store_values(values); + thd->count_cuted_fields= CHECK_FIELD_IGNORE; + if (thd->net.report_error) DBUG_RETURN(1); + if (table_list) // Not CREATE ... SELECT + { + switch (table_list->view_check_option(thd, + thd->lex->duplicates == + DUP_IGNORE)) { + case VIEW_CHECK_SKIP: + DBUG_RETURN(0); + case VIEW_CHECK_ERROR: + DBUG_RETURN(1); + } } - if (thd->net.report_error || write_record(thd, table, &info)) - DBUG_RETURN(1); - if (table->next_number_field) // Clear for next record + if (!(error= write_record(thd, table,&info)) && table->next_number_field) { + /* Clear for next record */ table->next_number_field->reset(); if (! last_insert_id && thd->insert_id_used) last_insert_id=thd->insert_id(); } - DBUG_RETURN(0); + DBUG_RETURN(error); } +void select_insert::store_values(List<Item> &values) +{ + if (fields->elements) + fill_record(thd, *fields, values, 1); + else + fill_record(thd, table->field, values, 1); +} + void select_insert::send_error(uint errcode,const char *err) { DBUG_ENTER("select_insert::send_error"); @@ -1892,7 +1905,7 @@ void select_insert::send_error(uint errcode,const char *err) if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, - table->file->has_transactions()); + table->file->has_transactions(), FALSE); mysql_bin_log.write(&qinfo); } if (!table->tmp_table) @@ -1935,7 +1948,7 @@ bool select_insert::send_eof() if (!error) thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - table->file->has_transactions()); + table->file->has_transactions(), FALSE); mysql_bin_log.write(&qinfo); } if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error) @@ -1988,8 +2001,6 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) table->next_number_field=table->found_next_number_field; restore_record(table,default_values); // Get empty record - /* Count warnings. This is reset in ~select_insert() */ - thd->count_cuted_fields= CHECK_FIELD_WARN; thd->cuted_fields=0; if (info.handle_duplicates == DUP_IGNORE || info.handle_duplicates == DUP_REPLACE) @@ -2004,23 +2015,21 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) } -bool select_create::send_data(List<Item> &values) +void select_create::store_values(List<Item> &values) { - if (unit->offset_limit_cnt) - { // using limit offset,count - unit->offset_limit_cnt--; - return 0; - } fill_record(thd, field, values, 1); - if (thd->net.report_error || write_record(thd, table, &info)) - return 1; - if (table->next_number_field) // Clear for next record - { - table->next_number_field->reset(); - if (! last_insert_id && thd->insert_id_used) - last_insert_id=thd->insert_id(); - } - return 0; +} + + +void select_create::send_error(uint errcode,const char *err) +{ + /* + Disable binlog, because we "roll back" partial inserts in ::abort + by removing the table, even for non-transactional tables. + */ + tmp_disable_binlog(thd); + select_insert::send_error(errcode, err); + reenable_binlog(thd); } @@ -2068,7 +2077,7 @@ void select_create::abort() enum db_type table_type=table->db_type; if (!table->tmp_table) { - ulong version= table->version; + ulong version= table->version; hash_delete(&open_cache,(byte*) table); if (!create_info->table_existed) quick_rm_table(table_type, create_table->db, create_table->real_name); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index ce37318ca01..12e4d912f15 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -144,8 +144,9 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->select_lex.init_order(); lex->select_lex.group_list.empty(); lex->describe= 0; - lex->derived_tables= FALSE; + lex->subqueries= FALSE; lex->view_prepare_mode= FALSE; + lex->derived_tables= 0; lex->lock_option= TL_READ; lex->found_colon= 0; lex->safe_to_cache_query= 1; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index e99e6138b6d..1c0e3e2e02e 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -687,7 +687,6 @@ typedef struct st_lex List<Item_param> param_list; List<LEX_STRING> view_list; // view list (list of field names in view) SQL_LIST proc_list, auxilliary_table_list, save_list; - TYPELIB *interval; create_field *last_field; char *savepoint_name; // Transaction savepoint id udf_func udf; @@ -721,6 +720,7 @@ typedef struct st_lex /* special JOIN::prepare mode: changing of query is prohibited */ bool view_prepare_mode; bool safe_to_cache_query; + bool subqueries; bool variables_used; ALTER_INFO alter_info; /* Prepared statements SQL syntax:*/ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e27cd20e15e..168632f7578 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -615,7 +615,7 @@ end: } -static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0) +static void reset_mqh(LEX_USER *lu, bool get_them= 0) { #ifndef NO_EMBEDDED_ACCESS_CHECKS (void) pthread_mutex_lock(&LOCK_user_conn); @@ -2830,7 +2830,7 @@ create_error: if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } } @@ -2860,7 +2860,7 @@ create_error: if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } } @@ -2883,7 +2883,7 @@ create_error: if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } } @@ -3396,7 +3396,7 @@ create_error: { if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } send_ok(thd); @@ -3411,7 +3411,7 @@ create_error: { if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } send_ok(thd); @@ -3426,7 +3426,7 @@ create_error: { if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } send_ok(thd); @@ -3441,7 +3441,7 @@ create_error: { if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } send_ok(thd); @@ -3484,7 +3484,7 @@ create_error: mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } } @@ -3504,7 +3504,7 @@ create_error: if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } if (mqh_used && lex->sql_command == SQLCOM_GRANT) @@ -3512,7 +3512,7 @@ create_error: List_iterator <LEX_USER> str_list(lex->users_list); LEX_USER *user; while ((user=str_list++)) - reset_mqh(thd,user); + reset_mqh(user); } } } @@ -3544,7 +3544,7 @@ create_error: { if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } } @@ -4529,6 +4529,7 @@ mysql_new_select(LEX *lex, bool move_down) select_lex->parent_lex= lex; if (move_down) { + lex->subqueries= TRUE; /* first select_lex of subselect or derived table */ SELECT_LEX_UNIT *unit; if (!(unit= new(lex->thd->mem_root) SELECT_LEX_UNIT())) @@ -4717,31 +4718,6 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length) -/* - Calculate interval lengths. - Strip trailing spaces from all strings. - After this function call: - - ENUM uses max_length - - SET uses tot_length. -*/ -void calculate_interval_lengths(THD *thd, TYPELIB *interval, - uint32 *max_length, uint32 *tot_length) -{ - const char **pos; - uint *len; - CHARSET_INFO *cs= thd->variables.character_set_client; - *max_length= *tot_length= 0; - for (pos= interval->type_names, len= interval->type_lengths; - *pos ; pos++, len++) - { - *len= (uint) strip_sp((char*) *pos); - uint length= cs->cset->numchars(cs, *pos, *pos + *len); - *tot_length+= length; - set_if_bigger(*max_length, (uint32)length); - } -} - - /***************************************************************************** ** Store field definition for create ** Return 0 if ok @@ -4752,7 +4728,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, uint type_modifier, Item *default_value, Item *on_update_value, LEX_STRING *comment, - char *change, TYPELIB *interval, CHARSET_INFO *cs, + char *change, + List<String> *interval_list, CHARSET_INFO *cs, uint uint_geom_type) { register create_field *new_field; @@ -5059,62 +5036,39 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, break; case FIELD_TYPE_SET: { - if (interval->count > sizeof(longlong)*8) + if (interval_list->elements > sizeof(longlong)*8) { my_error(ER_TOO_BIG_SET, MYF(0), field_name); /* purecov: inspected */ - DBUG_RETURN(1); /* purecov: inspected */ + DBUG_RETURN(1); /* purecov: inspected */ } - new_field->pack_length=(interval->count+7)/8; + new_field->pack_length= (interval_list->elements + 7) / 8; if (new_field->pack_length > 4) - new_field->pack_length=8; - new_field->interval=interval; - uint32 dummy_max_length; - calculate_interval_lengths(thd, interval, - &dummy_max_length, &new_field->length); - new_field->length+= (interval->count - 1); - set_if_smaller(new_field->length,MAX_FIELD_WIDTH-1); - if (default_value) - { - char *not_used; - uint not_used2; - bool not_used3; - - thd->cuted_fields=0; - String str,*res; - res=default_value->val_str(&str); - (void) find_set(interval, res->ptr(), res->length(), - &my_charset_bin, - ¬_used, ¬_used2, ¬_used3); - if (thd->cuted_fields) - { - my_error(ER_INVALID_DEFAULT, MYF(0), field_name); - DBUG_RETURN(1); - } - } + new_field->pack_length=8; + + List_iterator<String> it(*interval_list); + String *tmp; + while ((tmp= it++)) + new_field->interval_list.push_back(tmp); + /* + Set fake length to 1 to pass the below conditions. + Real length will be set in mysql_prepare_table() + when we know the character set of the column + */ + new_field->length= 1; } break; case FIELD_TYPE_ENUM: { - new_field->interval=interval; - new_field->pack_length=interval->count < 256 ? 1 : 2; // Should be safe + // Should be safe + new_field->pack_length= interval_list->elements < 256 ? 1 : 2; - uint32 dummy_tot_length; - calculate_interval_lengths(thd, interval, - &new_field->length, &dummy_tot_length); - set_if_smaller(new_field->length,MAX_FIELD_WIDTH-1); - if (default_value) - { - String str,*res; - res=default_value->val_str(&str); - res->strip_sp(); - if (!find_type(interval, res->ptr(), res->length(), 0)) - { - my_error(ER_INVALID_DEFAULT, MYF(0), field_name); - DBUG_RETURN(1); - } - } - break; + List_iterator<String> it(*interval_list); + String *tmp; + while ((tmp= it++)) + new_field->interval_list.push_back(tmp); + new_field->length= 1; // See comment for FIELD_TYPE_SET above. } + break; } if ((new_field->length > MAX_FIELD_CHARLENGTH && type != FIELD_TYPE_SET && @@ -5683,7 +5637,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, acl_reload(thd); grant_reload(thd); if (mqh_used) - reset_mqh(thd,(LEX_USER *) NULL,TRUE); + reset_mqh((LEX_USER *) NULL,TRUE); } #endif if (options & REFRESH_LOG) @@ -5759,7 +5713,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, } if (options & REFRESH_HOSTS) hostname_cache_refresh(); - if (options & REFRESH_STATUS) + if (thd && (options & REFRESH_STATUS)) refresh_status(); if (options & REFRESH_THREADS) flush_thread_cache(); @@ -5789,7 +5743,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, } #endif if (options & REFRESH_USER_RESOURCES) - reset_mqh(thd,(LEX_USER *) NULL); + reset_mqh((LEX_USER *) NULL); if (write_to_binlog) *write_to_binlog= tmp_write_to_binlog; return result; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index d4851393a89..6d59d465445 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -427,8 +427,17 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len) #else/*!EMBEDDED_LIBRARY*/ void set_param_time(Item_param *param, uchar **pos, ulong len) { - MYSQL_TIME *to= (MYSQL_TIME*)*pos; - param->set_time(to, MYSQL_TIMESTAMP_TIME, + MYSQL_TIME tm= *((MYSQL_TIME*)*pos); + tm.hour+= tm.day * 24; + tm.day= tm.year= tm.month= 0; + if (tm.hour > 838) + { + /* TODO: add warning 'Data truncated' here */ + tm.hour= 838; + tm.minute= 59; + tm.second= 59; + } + param->set_time(&tm, MYSQL_TIMESTAMP_TIME, MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN); } diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 9f29a975441..1640fc1a634 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -84,7 +84,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } send_ok(thd); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0a7cd0f7338..1049c074ce1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1050,7 +1050,7 @@ JOIN::optimize() } } - if (select_lex->master_unit()->uncacheable) + if (thd->lex->subqueries) { if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN)))) DBUG_RETURN(-1); @@ -1249,7 +1249,7 @@ JOIN::exec() /* Copy data to the temporary table */ thd->proc_info= "Copying to tmp table"; - + DBUG_PRINT("info", ("%s", thd->proc_info)); if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0))) { error= tmp_error; @@ -1377,6 +1377,7 @@ JOIN::exec() } thd->proc_info="Copying to group table"; + DBUG_PRINT("info", ("%s", thd->proc_info)); tmp_error= -1; if (curr_join != this) { @@ -1615,6 +1616,7 @@ JOIN::exec() else { thd->proc_info="Sending data"; + DBUG_PRINT("info", ("%s", thd->proc_info)); error= do_select(curr_join, curr_fields_list, NULL, procedure); thd->limit_found_rows= curr_join->send_records; thd->examined_row_count= curr_join->examined_rows; @@ -1910,6 +1912,8 @@ void Cursor::close() { THD *thd= join->thd; + DBUG_ENTER("Cursor::close"); + join->join_free(0); if (unit) { @@ -1940,6 +1944,7 @@ Cursor::close() } join= 0; unit= 0; + DBUG_VOID_RETURN; } @@ -4718,11 +4723,12 @@ get_best_combination(JOIN *join) KEYUSE *keyuse; uint table_count; THD *thd=join->thd; + DBUG_ENTER("get_best_combination"); table_count=join->tables; if (!(join->join_tab=join_tab= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*table_count))) - return TRUE; + DBUG_RETURN(TRUE); join->full_join=0; @@ -4736,6 +4742,7 @@ get_best_combination(JOIN *join) form->reginfo.join_tab=j; if (!*j->on_expr_ref) form->reginfo.not_exists_optimize=0; // Only with LEFT JOIN + DBUG_PRINT("info",("type: %d", j->type)); if (j->type == JT_CONST) continue; // Handled in make_join_stat.. @@ -4751,13 +4758,13 @@ get_best_combination(JOIN *join) join->full_join=1; } else if (create_ref_for_key(join, j, keyuse, used_tables)) - return TRUE; // Something went wrong + DBUG_RETURN(TRUE); // Something went wrong } for (i=0 ; i < table_count ; i++) join->map2table[join->join_tab[i].table->tablenr]=join->join_tab+i; update_depend_map(join); - return 0; + DBUG_RETURN(0); } @@ -4770,6 +4777,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, uint keyparts,length,key; TABLE *table; KEY *keyinfo; + DBUG_ENTER("create_ref_for_key"); /* Use best key from find_best */ table=j->table; @@ -4819,7 +4827,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, (keyparts+1)))) || !(j->ref.items= (Item**) thd->alloc(sizeof(Item*)*keyparts))) { - return TRUE; + DBUG_RETURN(TRUE); } j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length); j->ref.key_err=1; @@ -4832,7 +4840,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, { j->ref.items[0]=((Item_func*)(keyuse->val))->key_item(); if (keyuse->used_tables) - return TRUE; // not supported yet. SerG + DBUG_RETURN(TRUE); // not supported yet. SerG j->type=JT_FT; } @@ -4856,7 +4864,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, maybe_null ? (char*) key_buff : 0, keyinfo->key_part[i].length, keyuse->val); if (thd->is_fatal_error) - return TRUE; + DBUG_RETURN(TRUE); tmp.copy(); } else @@ -4876,7 +4884,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, } /* not ftkey */ *ref_key=0; // end_marker if (j->type == JT_FT) - return 0; + DBUG_RETURN(0); if (j->type == JT_CONST) j->table->const_table= 1; else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY | @@ -4900,7 +4908,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, } else j->type=JT_EQ_REF; - return 0; + DBUG_RETURN(0); } @@ -4963,10 +4971,11 @@ make_simple_join(JOIN *join,TABLE *tmp_table) { TABLE **tableptr; JOIN_TAB *join_tab; + DBUG_ENTER("make_simple_join"); if (!(tableptr=(TABLE**) join->thd->alloc(sizeof(TABLE*))) || !(join_tab=(JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB)))) - return TRUE; + DBUG_RETURN(TRUE); join->join_tab=join_tab; join->table=tableptr; tableptr[0]=tmp_table; join->tables=1; @@ -4996,10 +5005,11 @@ make_simple_join(JOIN *join,TABLE *tmp_table) join_tab->not_used_in_distinct=0; join_tab->read_first_record= join_init_read_record; join_tab->join=join; + join_tab->ref.key_parts= 0; bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record)); tmp_table->status=0; tmp_table->null_row=0; - return FALSE; + DBUG_RETURN(FALSE); } @@ -5702,7 +5712,9 @@ JOIN::join_free(bool full) JOIN_TAB *tab,*end; DBUG_ENTER("JOIN::join_free"); - full= full || !select_lex->uncacheable; + full= full || (!select_lex->uncacheable && + !thd->lex->subqueries && + !thd->lex->describe); // do not cleanup too early on EXPLAIN if (table) { @@ -5731,6 +5743,7 @@ JOIN::join_free(bool full) for (tab= join_tab, end= tab+tables; tab != end; tab++) tab->cleanup(); table= 0; + tables= 0; } else { @@ -8119,6 +8132,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, keyinfo->key_length=0; keyinfo->rec_per_key=0; keyinfo->algorithm= HA_KEY_ALG_UNDEF; + keyinfo->name= (char*) "group_key"; for (; group ; group=group->next,key_part_info++) { Field *field=(*group->item)->get_tmp_table_field(); @@ -8189,7 +8203,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, keyinfo->key_part=key_part_info; keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL; keyinfo->key_length=(uint16) reclength; - keyinfo->name=(char*) "tmp"; + keyinfo->name= (char*) "distinct_key"; keyinfo->algorithm= HA_KEY_ALG_UNDEF; if (null_pack_length) { @@ -11970,6 +11984,8 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array, { List_iterator_fast<Item> it(all_fields); Item *item_field,*item; + DBUG_ENTER("change_to_use_tmp_fields"); + res_selected_fields.empty(); res_all_fields.empty(); @@ -11993,8 +12009,8 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array, else item_field= (Item*) new Item_field(field); if (!item_field) - return TRUE; // Fatal error - item_field->name= item->name; /*lint -e613 */ + DBUG_RETURN(TRUE); // Fatal error + item_field->name= item->name; #ifndef DBUG_OFF if (_db_on_ && !item_field->name) { @@ -12018,7 +12034,7 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array, for (i= 0; i < border; i++) itr++; itr.sublist(res_selected_fields, elements); - return FALSE; + DBUG_RETURN(FALSE); } @@ -12089,10 +12105,11 @@ change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array, static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr) { Item_sum *func; + DBUG_ENTER("setup_sum_funcs"); while ((func= *(func_ptr++))) if (func->setup(thd)) - return TRUE; - return FALSE; + DBUG_RETURN(TRUE); + DBUG_RETURN(FALSE); } @@ -12614,10 +12631,10 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, item_list.push_back(new Item_string(join_type_str[tab->type], strlen(join_type_str[tab->type]), cs)); - uint j; /* Build "possible_keys" value and add it to item_list */ if (!tab->keys.is_clear_all()) { + uint j; for (j=0 ; j < table->keys ; j++) { if (tab->keys.is_set(j)) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index d443ec96a01..f30eeb2d206 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -847,6 +847,15 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) { uchar chr= (uchar) *name; length= my_mbcharlen(system_charset_info, chr); + /* + my_mbcharlen can retur 0 on a wrong multibyte + sequence. It is possible when upgrading from 4.0, + and identifier contains some accented characters. + The manual says it does not work. So we'll just + change length to 1 not to hang in the endless loop. + */ + if (!length) + length= 1; if (length == 1 && chr == (uchar) quote_char) packet->append("e_char, 1, system_charset_info); packet->append(name, length, packet->charset()); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index a7c08f356a2..c0ddfdb2f07 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -29,12 +29,6 @@ #include <io.h> #endif -#define tmp_disable_binlog(A) \ - ulong save_options= (A)->options; \ - (A)->options&= ~OPTION_BIN_LOG; - -#define reenable_binlog(A) (A)->options= save_options; - const char *primary_key_name="PRIMARY"; static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end); @@ -281,7 +275,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, if (!error) thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - tmp_table_deleted && !some_tables_deleted); + tmp_table_deleted && !some_tables_deleted, + FALSE); mysql_bin_log.write(&qinfo); } } @@ -390,6 +385,41 @@ void check_duplicates_in_interval(const char *set_or_name, } } + +/* + Check TYPELIB (set or enum) max and total lengths + + SYNOPSIS + calculate_interval_lengths() + cs charset+collation pair of the interval + typelib list of values for the column + max_length length of the longest item + tot_length sum of the item lengths + + DESCRIPTION + After this function call: + - ENUM uses max_length + - SET uses tot_length. + + RETURN VALUES + void +*/ +void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval, + uint32 *max_length, uint32 *tot_length) +{ + const char **pos; + uint *len; + *max_length= *tot_length= 0; + for (pos= interval->type_names, len= interval->type_lengths; + *pos ; pos++, len++) + { + uint length= cs->cset->numchars(cs, *pos, *pos + *len); + *tot_length+= length; + set_if_bigger(*max_length, (uint32)length); + } +} + + /* Preparation for table creation @@ -453,6 +483,91 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, DBUG_RETURN(-1); } + if ((sql_field->sql_type == FIELD_TYPE_SET || + sql_field->sql_type == FIELD_TYPE_ENUM) && !sql_field->interval) + { + uint32 dummy; + CHARSET_INFO *cs= sql_field->charset; + TYPELIB *interval; + + /* + Create typelib from interval_list, and if necessary + convert strings from client character set to the + column character set. + */ + + interval= sql_field->interval= typelib(sql_field->interval_list); + List_iterator<String> it(sql_field->interval_list); + String conv, *tmp; + for (uint i= 0; (tmp= it++); i++) + { + if (String::needs_conversion(tmp->length(), tmp->charset(), cs, &dummy)) + { + uint cnv_errs; + conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs); + char *buf= (char*) sql_alloc(conv.length()+1); + memcpy(buf, conv.ptr(), conv.length()); + buf[conv.length()]= '\0'; + interval->type_names[i]= buf; + interval->type_lengths[i]= conv.length(); + } + + // Strip trailing spaces. + uint lengthsp= cs->cset->lengthsp(cs, interval->type_names[i], + interval->type_lengths[i]); + interval->type_lengths[i]= lengthsp; + ((uchar *)interval->type_names[i])[lengthsp]= '\0'; + } + sql_field->interval_list.empty(); // Don't need interval_list anymore + + + /* + Convert the default value from client character + set into the column character set if necessary. + */ + if (sql_field->def) + { + sql_field->def= + sql_field->def->safe_charset_converter(cs); + } + + if (sql_field->sql_type == FIELD_TYPE_SET) + { + if (sql_field->def) + { + char *not_used; + uint not_used2; + bool not_found= 0; + String str, *def= sql_field->def->val_str(&str); + def->length(cs->cset->lengthsp(cs, def->ptr(), def->length())); + (void) find_set(interval, def->ptr(), def->length(), + cs, ¬_used, ¬_used2, ¬_found); + if (not_found) + { + my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); + DBUG_RETURN(-1); + } + } + calculate_interval_lengths(cs, interval, &dummy, &sql_field->length); + sql_field->length+= (interval->count - 1); + } + else /* FIELD_TYPE_ENUM */ + { + if (sql_field->def) + { + String str, *def= sql_field->def->val_str(&str); + def->length(cs->cset->lengthsp(cs, def->ptr(), def->length())); + if (!find_type2(interval, def->ptr(), def->length(), cs)) + { + my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); + DBUG_RETURN(-1); + } + } + calculate_interval_lengths(cs, interval, &sql_field->length, &dummy); + } + set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1); + } + sql_field->create_length_to_internal_length(); /* Don't pack keys in old tables if the user has requested this */ @@ -816,8 +931,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, DBUG_RETURN(-1); } } - else - if (key_info->algorithm == HA_KEY_ALG_RTREE) + else if (key_info->algorithm == HA_KEY_ALG_RTREE) { #ifdef HAVE_RTREE_KEYS if ((key_info->key_parts & 1) == 1) @@ -839,6 +953,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, CHARSET_INFO *ft_key_charset=0; // for FULLTEXT for (uint column_nr=0 ; (column=cols++) ; column_nr++) { + key_part_spec *dup_column; + it.rewind(); field=0; while ((sql_field=it++) && @@ -851,9 +967,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name); DBUG_RETURN(-1); } - for (uint dup_nr= 0; dup_nr < column_nr; dup_nr++) + while ((dup_column= cols2++) != column) { - key_part_spec *dup_column= cols2++; if (!my_strcasecmp(system_charset_info, column->field_name, dup_column->field_name)) { @@ -864,12 +979,6 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, } } cols2.rewind(); - /* for fulltext keys keyseg length is 1 for blobs (it's ignored in - ft code anyway, and 0 (set to column width later) for char's. - it has to be correct col width for char's, as char data are not - prefixed with length (unlike blobs, where ft code takes data length - from a data prefix, ignoring column->length). - */ if (key->type == Key::FULLTEXT) { if ((sql_field->sql_type != FIELD_TYPE_STRING && @@ -1296,10 +1405,12 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name, thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, test(create_info->options & - HA_LEX_CREATE_TMP_TABLE)); + HA_LEX_CREATE_TMP_TABLE), + FALSE); mysql_bin_log.write(&qinfo); } error= FALSE; + end: VOID(pthread_mutex_unlock(&LOCK_open)); start_waiting_global_read_lock(thd); @@ -1559,6 +1670,7 @@ void close_cached_table(THD *thd, TABLE *table) /* When lock on LOCK_open is freed other threads can continue */ pthread_cond_broadcast(&COND_refresh); + DBUG_VOID_RETURN; } static int send_check_errmsg(THD *thd, TABLE_LIST* table, @@ -2274,7 +2386,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, test(create_info->options & - HA_LEX_CREATE_TMP_TABLE)); + HA_LEX_CREATE_TMP_TABLE), + FALSE); mysql_bin_log.write(&qinfo); } res= FALSE; @@ -2384,7 +2497,7 @@ mysql_discard_or_import_tablespace(THD *thd, goto err; if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } err: @@ -2773,7 +2886,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } if (do_send_ok) @@ -3189,7 +3302,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } goto end_temporary; @@ -3323,7 +3436,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); } VOID(pthread_cond_broadcast(&COND_refresh)); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 4a2790f7d78..9613e39d403 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -482,7 +482,7 @@ int mysql_update(THD *thd, if (error <= 0) thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - log_delayed); + log_delayed, FALSE); if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; // Rollback update } @@ -776,12 +776,10 @@ bool mysql_multi_update_prepare(THD *thd) */ List_iterator_fast<Item> it(*fields); Item *item; - while (item= it++) - { + while ((item= it++)) item->cleanup(); - } - /* We have to cleunup translation tables of views. */ + /* We have to cleanup translation tables of views. */ for (TABLE_LIST *tbl= table_list; tbl; tbl= tbl->next_global) tbl->cleanup_items(); @@ -1417,7 +1415,7 @@ bool multi_update::send_eof() if (local_error <= 0) thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - log_delayed); + log_delayed, FALSE); if (mysql_bin_log.write(&qinfo) && trans_safe) local_error= 1; // Rollback update } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index ec63bb92c54..993a4d1987b 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -312,7 +312,7 @@ bool mysql_create_view(THD *thd, send_ok(thd); lex->link_first_table_back(view, link_to_local); - return 0; + DBUG_RETURN(0); err: thd->proc_info= "end"; @@ -793,7 +793,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) /* re-nest tables of VIEW */ { List_iterator_fast<TABLE_LIST> ti(nested_join->join_list); - while(tbl= ti++) + while ((tbl= ti++)) { tbl->join_list= &nested_join->join_list; tbl->embedding= table; @@ -832,6 +832,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) view_select->linkage= DERIVED_TABLE_TYPE; table->updatable= 0; table->effective_with_check= VIEW_CHECK_NONE; + old_lex->subqueries= TRUE; /* SELECT tree link */ lex->unit.include_down(table->select_lex); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 74a96701bdc..8ea7cdb34fa 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2728,7 +2728,7 @@ field_spec: field_ident { LEX *lex=Lex; - lex->length=lex->dec=0; lex->type=0; lex->interval=0; + lex->length=lex->dec=0; lex->type=0; lex->default_value= lex->on_update_value= 0; lex->comment=0; lex->charset=NULL; @@ -2741,7 +2741,7 @@ field_spec: lex->length,lex->dec,lex->type, lex->default_value, lex->on_update_value, lex->comment, - lex->change,lex->interval,lex->charset, + lex->change,&lex->interval_list,lex->charset, lex->uint_geom_type)) YYABORT; }; @@ -2838,17 +2838,9 @@ type: | FIXED_SYM float_options field_options { $$=FIELD_TYPE_DECIMAL;} | ENUM {Lex->interval_list.empty();} '(' string_list ')' opt_binary - { - LEX *lex=Lex; - lex->interval=typelib(lex->interval_list); - $$=FIELD_TYPE_ENUM; - } + { $$=FIELD_TYPE_ENUM; } | SET { Lex->interval_list.empty();} '(' string_list ')' opt_binary - { - LEX *lex=Lex; - lex->interval=typelib(lex->interval_list); - $$=FIELD_TYPE_SET; - } + { $$=FIELD_TYPE_SET; } | LONG_SYM opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; } | SERIAL_SYM { @@ -3328,7 +3320,7 @@ alter_list_item: | MODIFY_SYM opt_column field_ident { LEX *lex=Lex; - lex->length=lex->dec=0; lex->type=0; lex->interval=0; + lex->length=lex->dec=0; lex->type=0; lex->default_value= lex->on_update_value= 0; lex->comment=0; lex->charset= NULL; @@ -3342,7 +3334,7 @@ alter_list_item: lex->length,lex->dec,lex->type, lex->default_value, lex->on_update_value, lex->comment, - $3.str, lex->interval, lex->charset, + $3.str, &lex->interval_list, lex->charset, lex->uint_geom_type)) YYABORT; } |