diff --git a/configure.in b/configure.in index 39151205533..2df5155ecbb 100644 --- a/configure.in +++ b/configure.in @@ -15,8 +15,8 @@ SHARED_LIB_VERSION=14:0:0 # ndb version NDB_VERSION_MAJOR=3 NDB_VERSION_MINOR=5 -NDB_VERSION_BUILD=1 -NDB_VERSION_STATUS=beta +NDB_VERSION_BUILD=2 +NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? # Remember that regexps needs to quote [ and ] since this is run through m4 diff --git a/include/my_pthread.h b/include/my_pthread.h index 602a4439575..cd0cf49a891 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -234,7 +234,6 @@ extern int my_sigwait(const sigset_t *set,int *sig); #include #undef sigwait #endif -#undef _REENTRANT /* Fix if _REENTRANT is in pthread.h */ #include #ifndef _REENTRANT #define _REENTRANT diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index e91be39a0cd..e6d478070b0 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -365,6 +365,15 @@ lock_deadlock_recursive( ulint* cost); /* in/out: number of calculation steps thus far: if this exceeds LOCK_MAX_N_STEPS_... we return TRUE */ +/************************************************************************* +Gets the nth bit of a record lock. */ +UNIV_INLINE +ibool +lock_rec_get_nth_bit( +/*=================*/ + /* out: TRUE if bit set */ + lock_t* lock, /* in: record lock */ + ulint i); /* in: index of the bit */ #define lock_mutex_enter_kernel() mutex_enter(&kernel_mutex) #define lock_mutex_exit_kernel() mutex_exit(&kernel_mutex) diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result index a823049634f..6a7cecdd460 100644 --- a/mysql-test/r/type_timestamp.result +++ b/mysql-test/r/type_timestamp.result @@ -369,7 +369,7 @@ create table t1 (a timestamp null, b timestamp null); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` timestamp NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `a` timestamp NULL default NULL, `b` timestamp NULL default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 insert into t1 values (NULL, NULL); @@ -378,7 +378,22 @@ insert into t1 values (); select * from t1; a b NULL NULL -2001-09-09 04:46:57 NULL +NULL NULL +drop table t1; +create table t1 (a timestamp null default current_timestamp on update current_timestamp, b timestamp null); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` timestamp NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `b` timestamp NULL default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +insert into t1 values (NULL, NULL); +SET TIMESTAMP=1000000018; +insert into t1 values (); +select * from t1; +a b +NULL NULL +2001-09-09 04:46:58 NULL drop table t1; create table t1 (a timestamp null default null, b timestamp null default '2003-01-01 00:00:00'); show create table t1; diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test index 7c1258785b0..3f0b41d7221 100644 --- a/mysql-test/t/type_timestamp.test +++ b/mysql-test/t/type_timestamp.test @@ -236,9 +236,10 @@ drop table t1; # # Test for TIMESTAMP columns which are able to store NULLs -# (Auto-set property should work for them and NULL values -# should be OK as default values) # + +# Unlike for default TIMESTAMP fields we don't interpret first field +# in this table as TIMESTAMP with DEFAULT NOW() ON UPDATE NOW() properties. create table t1 (a timestamp null, b timestamp null); show create table t1; insert into t1 values (NULL, NULL); @@ -247,6 +248,16 @@ insert into t1 values (); select * from t1; drop table t1; +# But explicit auto-set properties still should be OK. +create table t1 (a timestamp null default current_timestamp on update current_timestamp, b timestamp null); +show create table t1; +insert into t1 values (NULL, NULL); +SET TIMESTAMP=1000000018; +insert into t1 values (); +select * from t1; +drop table t1; + +# It is also OK to specify NULL as default explicitly for such fields. create table t1 (a timestamp null default null, b timestamp null default '2003-01-01 00:00:00'); show create table t1; insert into t1 values (NULL, NULL); diff --git a/ndb/src/common/util/version.c b/ndb/src/common/util/version.c index 937ca1d32dd..b8408c7f201 100644 --- a/ndb/src/common/util/version.c +++ b/ndb/src/common/util/version.c @@ -37,13 +37,19 @@ Uint32 makeVersion(Uint32 major, Uint32 minor, Uint32 build) { char * getVersionString(Uint32 version, char * status) { char buff[100]; - snprintf(buff, sizeof(buff), - "Version %d.%d.%d (%s)", - getMajor(version), - getMinor(version), - getBuild(version), - status); - + if (status && status[0] != 0) + snprintf(buff, sizeof(buff), + "Version %d.%d.%d (%s)", + getMajor(version), + getMinor(version), + getBuild(version), + status); + else + snprintf(buff, sizeof(buff), + "Version %d.%d.%d", + getMajor(version), + getMinor(version), + getBuild(version)); return strdup(buff); } @@ -63,6 +69,7 @@ struct NdbUpGradeCompatible { #ifndef TEST_VERSION struct NdbUpGradeCompatible ndbCompatibleTable_full[] = { + { MAKE_VERSION(3,5,2), MAKE_VERSION(3,5,1), UG_Exact }, { 0, 0, UG_Null } }; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 685dd50e128..788f8a881b3 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1203,7 +1203,8 @@ inline int ha_ndbcluster::next_result(byte *buf) { if (execute_commit(this,trans) != 0) DBUG_RETURN(ndb_err(trans)); - DBUG_ASSERT(trans->restart() == 0); + int res= trans->restart(); + DBUG_ASSERT(res == 0); } ops_pending= 0; } @@ -1663,7 +1664,8 @@ int ha_ndbcluster::write_row(byte *record) no_uncommitted_rows_execute_failure(); DBUG_RETURN(ndb_err(trans)); } - DBUG_ASSERT(trans->restart() == 0); + int res= trans->restart(); + DBUG_ASSERT(res == 0); } } if ((has_auto_increment) && (skip_auto_increment)) @@ -2294,7 +2296,8 @@ int ha_ndbcluster::rnd_init(bool scan) { if (!scan) DBUG_RETURN(1); - DBUG_ASSERT(cursor->restart() == 0); + int res= cursor->restart(); + DBUG_ASSERT(res == 0); } index_init(table->primary_key); DBUG_RETURN(0); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 3dbf4eae55b..bb2bb6319a9 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -638,6 +638,8 @@ String *Item_in_subselect::val_str(String *str) } +/* Rewrite a single-column IN/ALL/ANY subselect. */ + Item_subselect::trans_res Item_in_subselect::single_value_transformer(JOIN *join, Comp_creator *func) @@ -656,12 +658,27 @@ Item_in_subselect::single_value_transformer(JOIN *join, if (arena->is_stmt_prepare()) thd->set_n_backup_item_arena(arena, &backup); + /* + Check that the right part of the subselect contains no more than one + column. E.g. in SELECT 1 IN (SELECT * ..) the right part is (SELECT * ...) + */ if (select_lex->item_list.elements > 1) { my_error(ER_OPERAND_COLUMNS, MYF(0), 1); goto err; } + /* + If this is an ALL/ANY single-value subselect, try to rewrite it with + a MIN/MAX subselect. We can do that if a possible NULL result of the + subselect can be ignored. + E.g. SELECT * FROM t1 WHERE b > ANY (SELECT a FROM t2) can be rewritten + with SELECT * FROM t1 WHERE b > (SELECT MAX(a) FROM t2). + We can't check that this optimization is safe if it's not a top-level + item of the WHERE clause (e.g. because the WHERE clause can contain IS + NULL/IS NOT NULL functions). If so, we rewrite ALL/ANY with NOT EXISTS + later in this method. + */ if ((abort_on_null || (upper_not && upper_not->top_level())) && !select_lex->master_unit()->uncacheable && !func->eqne_op()) { @@ -764,7 +781,13 @@ Item_in_subselect::single_value_transformer(JOIN *join, Item *item; item= (Item*) select_lex->item_list.head(); - + /* + Add the left part of a subselect to a WHERE or HAVING clause of + the right part, e.g. SELECT 1 IN (SELECT a FROM t1) => + SELECT Item_in_optimizer(1, SELECT a FROM t1 WHERE a=1) + HAVING is used only if the right part contains a SUM function, a GROUP + BY or a HAVING clause. + */ if (join->having || select_lex->with_sum_func || select_lex->group_list.elements) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e8441c05609..34cad1b062d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4142,12 +4142,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, } else if (default_value->type() == Item::NULL_ITEM) { - /* - TIMESTAMP type should be able to distingush non-specified default - value and default value NULL later. - */ - if (type != FIELD_TYPE_TIMESTAMP) - default_value= 0; + default_value= 0; if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == NOT_NULL_FLAG) { @@ -4357,19 +4352,27 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, else new_field->unireg_check= (on_update_value?Field::TIMESTAMP_UN_FIELD: Field::NONE); - - if (default_value->type() == Item::NULL_ITEM) - new_field->def= 0; } else { - /* - We are setting TIMESTAMP_OLD_FIELD here only temporary, we will - replace this value by TIMESTAMP_DNUN_FIELD or NONE later when + /* + If we have default TIMESTAMP NOT NULL column without explicit DEFAULT + or ON UPDATE values then for the sake of compatiblity we should treat + this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't + have another TIMESTAMP column with auto-set option before this one) + or DEFAULT 0 (in other cases). + So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will + replace this value by TIMESTAMP_DNUN_FIELD or NONE later when information about all TIMESTAMP fields in table will be availiable. + + If we have TIMESTAMP NULL column without explicit DEFAULT value + we treat it as having DEFAULT NULL attribute. */ - new_field->unireg_check= on_update_value?Field::TIMESTAMP_UN_FIELD: - Field::TIMESTAMP_OLD_FIELD; + new_field->unireg_check= on_update_value ? + Field::TIMESTAMP_UN_FIELD : + (new_field->flags & NOT_NULL_FLAG ? + Field::TIMESTAMP_OLD_FIELD: + Field::NONE); } break; case FIELD_TYPE_DATE: // Old date type