diff options
60 files changed, 720 insertions, 162 deletions
diff --git a/client/mysql.cc b/client/mysql.cc index 8589bdb05ed..12c86e02dc4 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -653,7 +653,7 @@ static struct my_option my_long_options[] = "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"socket", 'S', "Socket file to use for connection. (This will override --port unless --protocol=TCP is specified.)", + {"socket", 'S', "Socket file to use for connection.", (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #include "sslopt-longopts.h" @@ -939,14 +939,7 @@ static int get_options(int argc, char **argv) opt_reconnect= 0; connect_flag= 0; /* Not in interactive mode */ } - - if (opt_mysql_port && (!opt_protocol) && (!opt_mysql_unix_port)) - { - /* Not checking return type since we are using a constant value */ - /* straight from the initialization of sql_protocol_typelib. */ - opt_protocol= find_type("TCP", &sql_protocol_typelib, 0); - } - + if (strcmp(default_charset, charset_info->csname) && !(charset_info= get_charset_by_csname(default_charset, MY_CS_PRIMARY, MYF(MY_WME)))) diff --git a/extra/yassl/include/openssl/rsa.h b/extra/yassl/include/openssl/rsa.h index 1ab9d13b89f..fe64e655bdc 100644 --- a/extra/yassl/include/openssl/rsa.h +++ b/extra/yassl/include/openssl/rsa.h @@ -1,7 +1,7 @@ /* rsa.h for openSSL */ -#ifndef ysSSL_rsa_h__ +#ifndef yaSSL_rsa_h__ #define yaSSL_rsa_h__ enum { RSA_F4 = 1 }; diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index 1c8291c2f13..8a87196b7ed 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -23,7 +23,7 @@ * */ -#ifndef ysSSL_openssl_h__ +#ifndef yaSSL_openssl_h__ #define yaSSL_openssl_h__ #include <stdio.h> /* ERR_print fp */ diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp index 60a78a3970e..e75294ad073 100644 --- a/extra/yassl/include/yassl_int.hpp +++ b/extra/yassl/include/yassl_int.hpp @@ -123,8 +123,6 @@ public: friend sslFactory& GetSSL_Factory(); // singleton creator private: - static sslFactory instance_; - sslFactory(const sslFactory&); // hide copy sslFactory& operator=(const sslFactory&); // and assign }; @@ -216,8 +214,6 @@ public: friend Sessions& GetSessions(); // singleton creator private: - static Sessions instance_; - Sessions(const Sessions&); // hide copy Sessions& operator=(const Sessions&); // and assign }; diff --git a/extra/yassl/include/yassl_types.hpp b/extra/yassl/include/yassl_types.hpp index ec9e6fb7ceb..66cc6aa3c68 100644 --- a/extra/yassl/include/yassl_types.hpp +++ b/extra/yassl/include/yassl_types.hpp @@ -34,6 +34,11 @@ namespace yaSSL { + +// Delete static singleton memory holders +void CleanUp(); + + // library allocation struct new_t {}; // yaSSL New type extern new_t ys; // pass in parameter diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index d7df438b8df..16c9bde2003 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -648,8 +648,6 @@ void build_certHashes(SSL& ssl, Hashes& hashes) } -mySTL::auto_ptr<input_buffer> null_buffer(ysDelete); - // do process input requests mySTL::auto_ptr<input_buffer> DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered) @@ -659,7 +657,8 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered) if (!ready) { // Nothing to receive after blocking wait => error ssl.SetError(receive_error); - return buffered= null_buffer; + buffered.reset(0); + return buffered; } // add buffered data if its there @@ -667,10 +666,10 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered) input_buffer buffer(buffSz + ready); if (buffSz) { buffer.assign(buffered.get()->get_buffer(), buffSz); - buffered = null_buffer; + buffered.reset(0); } - // add new (ys) data + // add new data uint read = ssl.getSocket().receive(buffer.get_buffer() + buffSz, ready); buffer.add_size(read); uint offset = 0; @@ -703,11 +702,15 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered) mySTL::auto_ptr<Message> msg(mf.CreateObject(hdr.type_), ysDelete); if (!msg.get()) { ssl.SetError(factory_error); - return buffered = null_buffer; + buffered.reset(0); + return buffered; } buffer >> *msg; msg->Process(buffer, ssl); - if (ssl.GetError()) return buffered = null_buffer; + if (ssl.GetError()) { + buffered.reset(0); + return buffered; + } } offset += hdr.length_ + RECORD_HEADER; } diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp index 5ee57e76aed..c55ca39bec2 100644 --- a/extra/yassl/src/template_instnt.cpp +++ b/extra/yassl/src/template_instnt.cpp @@ -87,6 +87,8 @@ template void ysDelete<BulkCipher>(BulkCipher*); template void ysDelete<Digest>(Digest*); template void ysDelete<X509>(X509*); template void ysDelete<Message>(Message*); +template void ysDelete<sslFactory>(sslFactory*); +template void ysDelete<Sessions>(Sessions*); template void ysArrayDelete<unsigned char>(unsigned char*); template void ysArrayDelete<char>(char*); } diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp index 740618ce701..87d990b3506 100644 --- a/extra/yassl/src/yassl_int.cpp +++ b/extra/yassl/src/yassl_int.cpp @@ -1361,19 +1361,31 @@ SSL_SESSION::~SSL_SESSION() } -Sessions Sessions::instance_; // simple singleton +static Sessions* sessionsInstance = 0; Sessions& GetSessions() { - return Sessions::instance_; + if (!sessionsInstance) + sessionsInstance = new (ys) Sessions; + return *sessionsInstance; } -sslFactory sslFactory::instance_; // simple singleton +static sslFactory* sslFactoryInstance = 0; sslFactory& GetSSL_Factory() -{ - return sslFactory::instance_; +{ + if (!sslFactoryInstance) + sslFactoryInstance = new (ys) sslFactory; + return *sslFactoryInstance; +} + + +void CleanUp() +{ + TaoCrypt::CleanUp(); + ysDelete(sslFactoryInstance); + ysDelete(sessionsInstance); } diff --git a/extra/yassl/taocrypt/include/integer.hpp b/extra/yassl/taocrypt/include/integer.hpp index 76034c3ae8f..d3bd731e2bd 100644 --- a/extra/yassl/taocrypt/include/integer.hpp +++ b/extra/yassl/taocrypt/include/integer.hpp @@ -275,8 +275,6 @@ private: AlignedWordBlock reg_; Sign sign_; - static const Integer zero_; - static const Integer one_; }; inline bool operator==(const Integer& a, const Integer& b) diff --git a/extra/yassl/taocrypt/include/misc.hpp b/extra/yassl/taocrypt/include/misc.hpp index f705cc99970..26383d4c96b 100644 --- a/extra/yassl/taocrypt/include/misc.hpp +++ b/extra/yassl/taocrypt/include/misc.hpp @@ -34,6 +34,11 @@ namespace TaoCrypt { + +// Delete static singleton holders +void CleanUp(); + + // library allocation struct new_t {}; // TaoCrypt New type extern new_t tc; // pass in parameter diff --git a/extra/yassl/taocrypt/include/runtime.hpp b/extra/yassl/taocrypt/include/runtime.hpp index 254e67a7f64..d9d7877bd93 100644 --- a/extra/yassl/taocrypt/include/runtime.hpp +++ b/extra/yassl/taocrypt/include/runtime.hpp @@ -25,11 +25,27 @@ -#if !defined(yaSSL_NEW_HPP) && defined(__GNUC__) -#if !(defined(__ICC) || defined(__INTEL_COMPILER)) - +#ifndef yaSSL_NEW_HPP #define yaSSL_NEW_HPP + +#ifdef __sun + +#include <assert.h> + +// Handler for pure virtual functions +namespace __Crun { + static void pure_error(void) + { + assert("Pure virtual method called." == "Aborted"); + } +} // namespace __Crun + +#endif // __sun + + +#if defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if __GNUC__ > 2 extern "C" { @@ -47,6 +63,6 @@ static int __cxa_pure_virtual() } // extern "C" #endif // __GNUC__ > 2 -#endif // ! _ICC -#endif // yaSSL_NEW_HPP && __GNUC__ +#endif // compiler check +#endif // yaSSL_NEW_HPP diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp index 45bbcfa662a..8f4ce051a43 100644 --- a/extra/yassl/taocrypt/src/algebra.cpp +++ b/extra/yassl/taocrypt/src/algebra.cpp @@ -76,7 +76,9 @@ const Integer& AbstractEuclideanDomain::Mod(const Element &a, const Integer& AbstractEuclideanDomain::Gcd(const Element &a, const Element &b) const { - Element g[3]={b, a}; + mySTL::vector<Element> g(3); + g[0]= b; + g[1]= a; unsigned int i0=0, i1=1, i2=2; while (!Equal(g[i1], this->Identity())) diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index 71324b04b92..4ade5491530 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -2709,19 +2709,32 @@ unsigned int Integer::Encode(byte* output, unsigned int outputLen, } -const Integer Integer::zero_; +static Integer* zero = 0; const Integer &Integer::Zero() { - return zero_; + if (!zero) + zero = new (tc) Integer; + return *zero; } -const Integer Integer::one_(1,2); +static Integer* one = 0; const Integer &Integer::One() { - return one_; + if (!one) + one = new (tc) Integer(1,2); + return *one; +} + + +// Clean up static singleton holders, not a leak, but helpful to have gone +// when checking for leaks +void CleanUp() +{ + tcDelete(one); + tcDelete(zero); } diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp index 9a3c12badfc..59814d03209 100644 --- a/extra/yassl/taocrypt/src/template_instnt.cpp +++ b/extra/yassl/taocrypt/src/template_instnt.cpp @@ -41,6 +41,7 @@ template class RSA_Decryptor<RSA_BlockType2>; template class RSA_Encryptor<RSA_BlockType1>; template class RSA_Encryptor<RSA_BlockType2>; template void tcDelete<HASH>(HASH*); +template void tcDelete<Integer>(Integer*); template void tcArrayDelete<byte>(byte*); template AllocatorWithCleanup<byte>::pointer StdReallocate<byte, AllocatorWithCleanup<byte> >(AllocatorWithCleanup<byte>&, byte*, AllocatorWithCleanup<byte>::size_type, AllocatorWithCleanup<byte>::size_type, bool); template void tcArrayDelete<word>(word*); diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 653addd9ede..bad8886d0be 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -1249,15 +1249,13 @@ dict_table_remove_from_cache( /* Remove table from LRU list of tables */ UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table); - mutex_free(&(table->autoinc_mutex)); - size = mem_heap_get_size(table->heap); ut_ad(dict_sys->size >= size); dict_sys->size -= size; - mem_heap_free(table->heap); + dict_mem_table_free(table); } /************************************************************************** @@ -1378,6 +1376,38 @@ dict_col_reposition_in_cache( HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col); } +/******************************************************************** +If the given column name is reserved for InnoDB system columns, return +TRUE. */ + +ibool +dict_col_name_is_reserved( +/*======================*/ + /* out: TRUE if name is reserved */ + const char* name) /* in: column name */ +{ + /* This check reminds that if a new system column is added to + the program, it should be dealt with here. */ +#if DATA_N_SYS_COLS != 4 +#error "DATA_N_SYS_COLS != 4" +#endif + + static const char* reserved_names[] = { + "DB_ROW_ID", "DB_TRX_ID", "DB_ROLL_PTR", "DB_MIX_ID" + }; + + ulint i; + + for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) { + if (strcmp(name, reserved_names[i]) == 0) { + + return(TRUE); + } + } + + return(FALSE); +} + /************************************************************************** Adds an index to the dictionary cache. */ @@ -1551,7 +1581,7 @@ dict_index_remove_from_cache( dict_sys->size -= size; - mem_heap_free(index->heap); + dict_mem_index_free(index); } /*********************************************************************** diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index 6415cc56b61..bd93a719f6c 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -767,7 +767,7 @@ dict_load_table( if (!btr_pcur_is_on_user_rec(&pcur, &mtr) || rec_get_deleted_flag(rec, sys_tables->comp)) { /* Not found */ - + err_exit: btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); @@ -779,11 +779,8 @@ dict_load_table( /* Check if the table name in record is the searched one */ if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) { - btr_pcur_close(&pcur); - mtr_commit(&mtr); - mem_heap_free(heap); - - return(NULL); + + goto err_exit; } ut_a(0 == ut_strcmp("SPACE", @@ -844,6 +841,14 @@ dict_load_table( field = rec_get_nth_field_old(rec, 5, &len); table->type = mach_read_from_4(field); + if (UNIV_UNLIKELY(table->type != DICT_TABLE_ORDINARY)) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: table %s: unknown table type %lu\n", + name, (ulong) table->type); + goto err_exit; + } + if (table->type == DICT_TABLE_CLUSTER_MEMBER) { ut_error; #if 0 /* clustered tables have not been implemented yet */ diff --git a/innobase/dict/dict0mem.c b/innobase/dict/dict0mem.c index eec35310039..98ef44a4969 100644 --- a/innobase/dict/dict0mem.c +++ b/innobase/dict/dict0mem.c @@ -97,6 +97,21 @@ dict_mem_table_create( return(table); } +/******************************************************************** +Free a table memory object. */ + +void +dict_mem_table_free( +/*================*/ + dict_table_t* table) /* in: table */ +{ + ut_ad(table); + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + + mutex_free(&(table->autoinc_mutex)); + mem_heap_free(table->heap); +} + /************************************************************************** Creates a cluster memory object. */ @@ -290,5 +305,8 @@ dict_mem_index_free( /*================*/ dict_index_t* index) /* in: index */ { + ut_ad(index); + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + mem_heap_free(index->heap); } diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c index d7fa48b6e66..e4694ed52ae 100644 --- a/innobase/ibuf/ibuf0ibuf.c +++ b/innobase/ibuf/ibuf0ibuf.c @@ -1160,9 +1160,9 @@ ibuf_dummy_index_free( dict_index_t* index) /* in: dummy index */ { dict_table_t* table = index->table; - mem_heap_free(index->heap); - mutex_free(&(table->autoinc_mutex)); - mem_heap_free(table->heap); + + dict_mem_index_free(index); + dict_mem_table_free(table); } /************************************************************************* diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h index 4396611e529..642037494b5 100644 --- a/innobase/include/dict0dict.h +++ b/innobase/include/dict0dict.h @@ -98,6 +98,15 @@ ulint dict_col_get_clust_pos( /*===================*/ dict_col_t* col); +/******************************************************************** +If the given column name is reserved for InnoDB system columns, return +TRUE. */ + +ibool +dict_col_name_is_reserved( +/*======================*/ + /* out: TRUE if name is reserved */ + const char* name); /* in: column name */ /************************************************************************ Initializes the autoinc counter. It is not an error to initialize an already initialized counter. */ diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h index 7eec86d0bcb..3c10e82342b 100644 --- a/innobase/include/dict0mem.h +++ b/innobase/include/dict0mem.h @@ -56,6 +56,13 @@ dict_mem_table_create( a member of a cluster */ ulint n_cols, /* in: number of columns */ ibool comp); /* in: TRUE=compact page format */ +/******************************************************************** +Free a table memory object. */ + +void +dict_mem_table_free( +/*================*/ + dict_table_t* table); /* in: table */ /************************************************************************** Creates a cluster memory object. */ diff --git a/innobase/include/univ.i b/innobase/include/univ.i index 04b254a8221..bc3bd031f0c 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -261,6 +261,9 @@ it is read or written. */ /* Tell the compiler that cond is unlikely to hold */ #define UNIV_UNLIKELY(cond) UNIV_EXPECT(cond, FALSE) +/* Compile-time constant of the given array's size. */ +#define UT_ARR_SIZE(a) (sizeof(a) / sizeof((a)[0])) + #include <stdio.h> #include "ut0dbg.h" #include "ut0ut.h" diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c index 42e854398ba..7c56fe35d48 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -890,9 +890,9 @@ recv_parse_or_apply_log_rec_body( ut_ad(!page || ptr); if (index) { dict_table_t* table = index->table; - mem_heap_free(index->heap); - mutex_free(&(table->autoinc_mutex)); - mem_heap_free(table->heap); + + dict_mem_index_free(index); + dict_mem_table_free(table); } return(ptr); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 937056c300e..89b82882d93 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1673,7 +1673,9 @@ row_mysql_recover_tmp_table( if (!ptr) { /* table name does not begin with "/rsql" */ + dict_mem_table_free(table); trx_commit_for_mysql(trx); + return(DB_ERROR); } else { @@ -1785,6 +1787,7 @@ row_create_table_for_mysql( const char* table_name; ulint table_name_len; ulint err; + ulint i; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); #ifdef UNIV_SYNC_DEBUG @@ -1802,6 +1805,7 @@ row_create_table_for_mysql( "InnoDB: with raw, and innodb_force_... is removed.\n", stderr); + dict_mem_table_free(table); trx_commit_for_mysql(trx); return(DB_ERROR); @@ -1816,11 +1820,25 @@ row_create_table_for_mysql( "InnoDB: MySQL system tables must be of the MyISAM type!\n", table->name); + dict_mem_table_free(table); trx_commit_for_mysql(trx); return(DB_ERROR); } + /* Check that no reserved column names are used. */ + for (i = 0; i < dict_table_get_n_user_cols(table); i++) { + dict_col_t* col = dict_table_get_nth_col(table, i); + + if (dict_col_name_is_reserved(col->name)) { + + dict_mem_table_free(table); + trx_commit_for_mysql(trx); + + return(DB_ERROR); + } + } + trx_start_if_not_started(trx); if (row_mysql_is_recovered_tmp_table(table->name)) { diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index a045441e046..ea0e11a69d9 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1457,7 +1457,8 @@ sub ndbcluster_start ($) { # FIXME, we want to _append_ output to file $file_ndb_testrun_log instead of /dev/null if ( mtr_run("$glob_mysql_test_dir/ndb/ndbcluster", ["--port=$opt_ndbcluster_port", - "--data-dir=$opt_vardir"], + "--data-dir=$opt_vardir", + "--character-sets-dir=$path_charsetsdir"], "", "/dev/null", "", "") ) { mtr_error("Error ndbcluster_start"); diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index d7e976f9d49..c41344548f5 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -631,7 +631,9 @@ fi [ -d $MYSQL_TEST_DIR/var/tmp ] || mkdir $MYSQL_TEST_DIR/var/tmp [ -d $MYSQL_TEST_DIR/var/run ] || mkdir $MYSQL_TEST_DIR/var/run [ -d $MYSQL_TEST_DIR/var/log ] || mkdir $MYSQL_TEST_DIR/var/log -if ! test -L $MYSQL_TEST_DIR/var/std_data_ln ; then + +# Use 'test', not '[' as the shell builtin might not have '-L +if test ! -L "$MYSQL_TEST_DIR/var/std_data_ln" ; then ln -s $MYSQL_TEST_DIR/std_data/ $MYSQL_TEST_DIR/var/std_data_ln fi @@ -1241,7 +1243,7 @@ start_ndbcluster() else NDBCLUSTER_EXTRA_OPTS="--small" fi - ./ndb/ndbcluster $NDBCLUSTER_OPTS $NDBCLUSTER_EXTRA_OPTS --initial || NDB_STATUS_OK=0 + ./ndb/ndbcluster $NDBCLUSTER_OPTS --character-sets-dir=$CHARSETSDIR $NDBCLUSTER_EXTRA_OPTS --initial || NDB_STATUS_OK=0 if [ x$NDB_STATUS_OK != x1 ] ; then if [ x$FORCE != x1 ] ; then exit 1 diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh index c09c013552e..ad01f6574cf 100644 --- a/mysql-test/ndb/ndbcluster.sh +++ b/mysql-test/ndb/ndbcluster.sh @@ -60,6 +60,7 @@ ndb_imem=24M NDB_MGM_EXTRA_OPTS= NDB_MGMD_EXTRA_OPTS= NDBD_EXTRA_OPTS= +CHARSETSDIR= while test $# -gt 0; do case "$1" in @@ -106,6 +107,9 @@ while test $# -gt 0; do --ndbd-extra-opts=*) NDBD_EXTRA_OPTS=`echo "$1" | sed -e "s;--ndbd-extra-opts=;;"` ;; + --character-sets-dir=*) + CHARSETSDIR=`echo "$1" | sed -e "s;--character-sets-dir=;;"` + ;; -- ) shift; break ;; --* ) $ECHO "Unrecognized option: $1"; exit 1 ;; * ) break ;; @@ -135,7 +139,7 @@ fi exec_mgmtclient="$exec_mgmtclient --no-defaults $NDB_MGM_EXTRA_OPTS" exec_mgmtsrvr="$exec_mgmtsrvr --no-defaults $NDB_MGMD_EXTRA_OPTS" -exec_ndb="$exec_ndb --no-defaults $NDBD_EXTRA_OPTS" +exec_ndb="$exec_ndb --no-defaults $NDBD_EXTRA_OPTS --character-sets-dir=$CHARSETSDIR" exec_waiter="$exec_waiter --no-defaults" ndb_host="localhost" diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 7889f8953f4..d8a539da3fe 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -611,6 +611,16 @@ count(distinct (f1+1)) 1 3 drop table t1; +create table t1 (f1 int unsigned, f2 varchar(255)); +insert into t1 values (1,repeat('a',255)),(2,repeat('b',255)); +select f2,group_concat(f1) from t1 group by f2; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 t1 f2 f2 253 255 255 Y 0 0 8 +def group_concat(f1) 253 400 1 Y 128 0 63 +f2 group_concat(f1) +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1 +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 2 +drop table t1; set names latin1; create table t1 (a char, b char); insert into t1 values ('a', 'a'), ('a', 'b'), ('b', 'a'), ('b', 'b'); diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 911d6eea033..aed79e7f8fa 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1030,3 +1030,13 @@ c res y,abc abc y,abc abc drop table t1; +select cast(rtrim(' 20.06 ') as decimal(19,2)); +cast(rtrim(' 20.06 ') as decimal(19,2)) +20.06 +select cast(ltrim(' 20.06 ') as decimal(19,2)); +cast(ltrim(' 20.06 ') as decimal(19,2)) +20.06 +select cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2)); +cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2)) +20.06 +End of 5.0 tests diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 75e41e7a94f..d32cd405ce8 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -3241,6 +3241,8 @@ where t2.a between t1.a - interval 2 day and t1.a + interval 2 day; a a 2005-10-01 2005-10-01 drop table t1, t2; +CREATE TABLE t1 (DB_ROW_ID int) engine=innodb; +ERROR HY000: Can't create table './test/t1.frm' (errno: -1) CREATE TABLE t1 ( a BIGINT(20) NOT NULL, PRIMARY KEY (a) diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result index de9a2b2c003..99f5277f817 100644 --- a/mysql-test/r/key_cache.result +++ b/mysql-test/r/key_cache.result @@ -289,6 +289,48 @@ check table t1; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; +CREATE TABLE t1(a int NOT NULL AUTO_INCREMENT PRIMARY KEY); +SET GLOBAL key_cache_block_size=1536; +INSERT INTO t1 VALUES (1); +SELECT @@key_cache_block_size; +@@key_cache_block_size +1536 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +CREATE TABLE t1(a int NOT NULL AUTO_INCREMENT PRIMARY KEY, b int); +CREATE TABLE t2(a int NOT NULL AUTO_INCREMENT PRIMARY KEY, b int); +SET GLOBAL key_cache_block_size=1536; +INSERT INTO t1 VALUES (1,0); +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +SELECT COUNT(*) FROM t1; +COUNT(*) +4181 +SELECT @@key_cache_block_size; +@@key_cache_block_size +1536 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1,t2; set @@global.key_buffer_size=0; Warnings: Warning 1438 Cannot drop default keycache diff --git a/mysql-test/r/ndb_bitfield.result b/mysql-test/r/ndb_bitfield.result index 9a941862854..389e19f2893 100644 --- a/mysql-test/r/ndb_bitfield.result +++ b/mysql-test/r/ndb_bitfield.result @@ -201,13 +201,13 @@ create table t1 ( pk1 bit(9) not null primary key, b int ) engine=ndbcluster; -ERROR HY000: Can't create table './test/t1.frm' (errno: 739) +ERROR HY000: Can't create table './test/t1.frm' (errno: 906) create table t1 ( pk1 int not null primary key, b bit(9), key(b) ) engine=ndbcluster; -ERROR HY000: Can't create table './test/t1.frm' (errno: 743) +ERROR HY000: Can't create table './test/t1.frm' (errno: 906) create table t1 ( pk1 int primary key, b bit(32) not null diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 6864c35dbfc..a36935a583d 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -820,3 +820,35 @@ a 2 2 DROP TABLE t1; +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (1,30), (2,20), (1,10), (2,30), (1,20), (2,10); +(SELECT b,a FROM t1 ORDER BY a,b) ORDER BY b,a; +b a +10 1 +10 2 +20 1 +20 2 +30 1 +30 2 +(SELECT b FROM t1 ORDER BY b DESC) ORDER BY b ASC; +b +10 +10 +20 +20 +30 +30 +(SELECT b,a FROM t1 ORDER BY b,a) ORDER BY a,b; +b a +10 1 +20 1 +30 1 +10 2 +20 2 +30 2 +(SELECT b,a FROM t1 ORDER by b,a LIMIT 3) ORDER by a,b; +b a +10 1 +20 1 +10 2 +DROP TABLE t1; diff --git a/mysql-test/r/rpl_deadlock.result b/mysql-test/r/rpl_deadlock.result index c25cb1e6a53..541e12b806f 100644 --- a/mysql-test/r/rpl_deadlock.result +++ b/mysql-test/r/rpl_deadlock.result @@ -44,8 +44,39 @@ select * from t2; a 22 show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 18911 # # master-bin.000001 Yes Yes 0 0 18911 # None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_MYPORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 18911 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 18911 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # stop slave; change master to master_log_pos=532; begin; @@ -62,8 +93,39 @@ select * from t2; a 22 show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 18911 # # master-bin.000001 Yes Yes 0 0 18911 # None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_MYPORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 18911 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running # +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 18911 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # set global max_relay_log_size=0; stop slave; change master to master_log_pos=532; @@ -82,6 +144,37 @@ select * from t2; a 22 show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 18911 # # master-bin.000001 # Yes 0 0 18911 # None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_MYPORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 18911 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running # +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 18911 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # drop table t1,t2,t3,t4; diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index aa28c9d5f52..fbfdfa3b5d0 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -397,6 +397,17 @@ insert into t1 values(1),(2),(3); select f1, group_concat(f1+1) from t1 group by f1 with rollup; select count(distinct (f1+1)) from t1 group by f1 with rollup; drop table t1; + +# +# Bug#14169 type of group_concat() result changed to blob if tmp_table was used +# +create table t1 (f1 int unsigned, f2 varchar(255)); +insert into t1 values (1,repeat('a',255)),(2,repeat('b',255)); +--enable_metadata +select f2,group_concat(f1) from t1 group by f2; +--disable_metadata +drop table t1; + # End of 4.1 tests # diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index ef20d766bce..85cedee0f4a 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -684,4 +684,11 @@ insert into t1 values ('y,abc'),('y,abc'); select c, substring_index(lcase(c), @q:=',', -1) as res from t1; drop table t1; -# End of 5.0 tests +# +# Bug #17043: Casting trimmed string to decimal loses precision +# +select cast(rtrim(' 20.06 ') as decimal(19,2)); +select cast(ltrim(' 20.06 ') as decimal(19,2)); +select cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2)); + +--echo End of 5.0 tests diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index fe5da58d4e7..fea4890286c 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -2133,13 +2133,17 @@ disconnect b; # create table t1(a date) engine=innodb; -create table t2(a date, key(a)) engine=innodb; +create table t2(a date, key(a)) engine=innodb; insert into t1 values('2005-10-01'); insert into t2 values('2005-10-01'); select * from t1, t2 where t2.a between t1.a - interval 2 day and t1.a + interval 2 day; drop table t1, t2; +# bug 18934, "InnoDB crashes when table uses column names like DB_ROW_ID" +--error 1005 +CREATE TABLE t1 (DB_ROW_ID int) engine=innodb; + # # Bug #17152: Wrong result with BINARY comparison on aliased column # diff --git a/mysql-test/t/innodb_unsafe_binlog-master.opt b/mysql-test/t/innodb_unsafe_binlog-master.opt index 503c8457b2c..5c0136b5db3 100644 --- a/mysql-test/t/innodb_unsafe_binlog-master.opt +++ b/mysql-test/t/innodb_unsafe_binlog-master.opt @@ -1 +1 @@ ---innodb_locks_unsafe_for_binlog=true +--loose-innodb_locks_unsafe_for_binlog=true diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test index df584021af1..4001e0df4af 100644 --- a/mysql-test/t/key_cache.test +++ b/mysql-test/t/key_cache.test @@ -149,6 +149,7 @@ show status like 'key_blocks_used'; --replace_result 1812 KEY_BLOCKS_UNUSED 1793 KEY_BLOCKS_UNUSED 1674 KEY_BLOCKS_UNUSED 1818 KEY_BLOCKS_UNUSED 1824 KEY_BLOCKS_UNUSED show status like 'key_blocks_unused'; + # Cleanup # We don't reset keycache2 as we want to ensure that mysqld will reset it set global keycache2.key_buffer_size=0; @@ -157,7 +158,7 @@ set global keycache2.key_buffer_size=0; set global keycache3.key_buffer_size=100; set global keycache3.key_buffer_size=0; -# Test case for buf 6447 +# Test case for bug 6447 create table t1 (mytext text, FULLTEXT (mytext)); insert t1 values ('aaabbb'); @@ -169,6 +170,44 @@ check table t1; drop table t1; # +# Bug #19079: corrupted index when key_cache_block_size is not multiple of +# myisam_block_size + +CREATE TABLE t1(a int NOT NULL AUTO_INCREMENT PRIMARY KEY); +SET GLOBAL key_cache_block_size=1536; +INSERT INTO t1 VALUES (1); +SELECT @@key_cache_block_size; +CHECK TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(a int NOT NULL AUTO_INCREMENT PRIMARY KEY, b int); +CREATE TABLE t2(a int NOT NULL AUTO_INCREMENT PRIMARY KEY, b int); +SET GLOBAL key_cache_block_size=1536; +INSERT INTO t1 VALUES (1,0); +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +INSERT INTO t2(b) SELECT b FROM t1; +INSERT INTO t1(b) SELECT b FROM t2; +SELECT COUNT(*) FROM t1; +SELECT @@key_cache_block_size; +CHECK TABLE t1; +DROP TABLE t1,t2; + +# # Bug#10473 - Can't set 'key_buffer_size' system variable to ZERO # (One cannot drop the default key cache.) # diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index b1807579b20..98e542dac95 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -563,4 +563,18 @@ SELECT a FROM t1 ORDER BY a; (SELECT a FROM t1) ORDER BY a; DROP TABLE t1; +# +# Bug #18767: global ORDER BY applied to a SELECT with ORDER BY either was +# ignored or 'concatened' to the latter. + +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (1,30), (2,20), (1,10), (2,30), (1,20), (2,10); + +(SELECT b,a FROM t1 ORDER BY a,b) ORDER BY b,a; +(SELECT b FROM t1 ORDER BY b DESC) ORDER BY b ASC; +(SELECT b,a FROM t1 ORDER BY b,a) ORDER BY a,b; +(SELECT b,a FROM t1 ORDER by b,a LIMIT 3) ORDER by a,b; + +DROP TABLE t1; + # End of 4.1 tests diff --git a/mysql-test/t/rpl_deadlock.test b/mysql-test/t/rpl_deadlock.test index c74ed989ece..684cb54611c 100644 --- a/mysql-test/t/rpl_deadlock.test +++ b/mysql-test/t/rpl_deadlock.test @@ -67,7 +67,9 @@ select * from t2; # check that no error is reported --replace_column 1 # 8 # 9 # 23 # 33 # --replace_result $MASTER_MYPORT MASTER_MYPORT +--vertical_results show slave status; +--horizontal_results # 2) Test lock wait timeout @@ -82,9 +84,11 @@ sync_with_master; select * from t1; # check that slave succeeded finally select * from t2; # check that no error is reported ---replace_column 1 # 8 # 9 # 23 # 33 # +--replace_column 1 # 8 # 9 # 11 # 23 # 33 # --replace_result $MASTER_MYPORT MASTER_MYPORT +--vertical_results show slave status; +--horizontal_results # Now we repeat 2), but with BEGIN in the same relay log as # COMMIT (to see if seeking into hot log is ok). @@ -104,7 +108,9 @@ select * from t1; select * from t2; --replace_column 1 # 8 # 9 # 11 # 23 # 33 # --replace_result $MASTER_MYPORT MASTER_MYPORT +--vertical_results show slave status; +--horizontal_results connection master; drop table t1,t2,t3,t4; diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 3b5e277b56d..11e27bb19ad 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -1805,6 +1805,7 @@ byte *key_cache_read(KEY_CACHE *keycache, uint status; int page_st; + offset= (uint) (filepos & (keycache->key_cache_block_size-1)); /* Read data in key_cache_block_size increments */ do { @@ -1814,7 +1815,6 @@ byte *key_cache_read(KEY_CACHE *keycache, keycache_pthread_mutex_unlock(&keycache->cache_lock); goto no_key_cache; } - offset= (uint) (filepos & (keycache->key_cache_block_size-1)); filepos-= offset; read_length= length; set_if_smaller(read_length, keycache->key_cache_block_size-offset); @@ -1890,6 +1890,7 @@ byte *key_cache_read(KEY_CACHE *keycache, #endif buff+= read_length; filepos+= read_length+offset; + offset= 0; } while ((length-= read_length)); DBUG_RETURN(start); @@ -1941,17 +1942,17 @@ int key_cache_insert(KEY_CACHE *keycache, uint read_length; int page_st; int error; + uint offset; + offset= (uint) (filepos & (keycache->key_cache_block_size-1)); do { - uint offset; keycache_pthread_mutex_lock(&keycache->cache_lock); if (!keycache->can_be_used) { keycache_pthread_mutex_unlock(&keycache->cache_lock); DBUG_RETURN(0); } - offset= (uint) (filepos & (keycache->key_cache_block_size-1)); /* Read data into key cache from buff in key_cache_block_size incr. */ filepos-= offset; read_length= length; @@ -2009,6 +2010,7 @@ int key_cache_insert(KEY_CACHE *keycache, buff+= read_length; filepos+= read_length+offset; + offset= 0; } while ((length-= read_length)); } @@ -2075,17 +2077,17 @@ int key_cache_write(KEY_CACHE *keycache, /* Key cache is used */ uint read_length; int page_st; + uint offset; + offset= (uint) (filepos & (keycache->key_cache_block_size-1)); do { - uint offset; keycache_pthread_mutex_lock(&keycache->cache_lock); if (!keycache->can_be_used) { keycache_pthread_mutex_unlock(&keycache->cache_lock); goto no_key_cache; } - offset= (uint) (filepos & (keycache->key_cache_block_size-1)); /* Write data in key_cache_block_size increments */ filepos-= offset; read_length= length; diff --git a/ndb/include/kernel/signaldata/TupFrag.hpp b/ndb/include/kernel/signaldata/TupFrag.hpp index 8acb3d28bd6..5fb9d7bcf42 100644 --- a/ndb/include/kernel/signaldata/TupFrag.hpp +++ b/ndb/include/kernel/signaldata/TupFrag.hpp @@ -146,7 +146,8 @@ public: enum ErrorCode { NoError = 0, InvalidCharset = 743, - TooManyBitsUsed = 831 + TooManyBitsUsed = 831, + UnsupportedType = 906 }; private: Uint32 userPtr; diff --git a/ndb/include/util/NdbSqlUtil.hpp b/ndb/include/util/NdbSqlUtil.hpp index 3e98dcd1805..36a75136c45 100644 --- a/ndb/include/util/NdbSqlUtil.hpp +++ b/ndb/include/util/NdbSqlUtil.hpp @@ -117,9 +117,9 @@ public: /** * Check character set. */ - static bool usable_in_pk(Uint32 typeId, const void* info); - static bool usable_in_hash_index(Uint32 typeId, const void* info); - static bool usable_in_ordered_index(Uint32 typeId, const void* info); + static uint check_column_for_pk(Uint32 typeId, const void* info); + static uint check_column_for_hash_index(Uint32 typeId, const void* info); + static uint check_column_for_ordered_index(Uint32 typeId, const void* info); /** * Get number of length bytes and length from variable length string. diff --git a/ndb/include/util/ndb_opts.h b/ndb/include/util/ndb_opts.h index 787c32f06fd..08ab4a2e9df 100644 --- a/ndb/include/util/ndb_opts.h +++ b/ndb/include/util/ndb_opts.h @@ -84,7 +84,10 @@ const char *opt_debug= 0; 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },\ { "core-file", OPT_WANT_CORE, "Write core on errors.",\ (gptr*) &opt_core, (gptr*) &opt_core, 0,\ - GET_BOOL, NO_ARG, OPT_WANT_CORE_DEFAULT, 0, 0, 0, 0, 0} + GET_BOOL, NO_ARG, OPT_WANT_CORE_DEFAULT, 0, 0, 0, 0, 0},\ + {"character-sets-dir", OPT_CHARSETS_DIR,\ + "Directory where character sets are.", (gptr*) &charsets_dir,\ + (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}\ #ifndef DBUG_OFF #define NDB_STD_OPTS(prog_name) \ @@ -111,6 +114,7 @@ enum ndb_std_options { OPT_WANT_CORE, OPT_NDB_MGMD, OPT_NDB_NODEID, + OPT_CHARSETS_DIR, NDB_STD_OPTIONS_LAST /* should always be last in this enum */ }; diff --git a/ndb/src/common/util/NdbSqlUtil.cpp b/ndb/src/common/util/NdbSqlUtil.cpp index 09e150dbacf..f2506eda6d4 100644 --- a/ndb/src/common/util/NdbSqlUtil.cpp +++ b/ndb/src/common/util/NdbSqlUtil.cpp @@ -872,8 +872,8 @@ NdbSqlUtil::likeLongvarbinary(const void* info, const void* p1, unsigned n1, con // check charset -bool -NdbSqlUtil::usable_in_pk(Uint32 typeId, const void* info) +uint +NdbSqlUtil::check_column_for_pk(Uint32 typeId, const void* info) { const Type& type = getType(typeId); switch (type.m_typeId) { @@ -882,12 +882,14 @@ NdbSqlUtil::usable_in_pk(Uint32 typeId, const void* info) case Type::Longvarchar: { const CHARSET_INFO *cs = (const CHARSET_INFO*)info; - return - cs != 0 && - cs->cset != 0 && - cs->coll != 0 && - cs->coll->strnxfrm != 0 && - cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY; + if(cs != 0 && + cs->cset != 0 && + cs->coll != 0 && + cs->coll->strnxfrm != 0 && + cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY) + return 0; + else + return 743; } break; case Type::Undefined: @@ -896,19 +898,19 @@ NdbSqlUtil::usable_in_pk(Uint32 typeId, const void* info) case Type::Bit: break; default: - return true; + return 0; } - return false; + return 906; } -bool -NdbSqlUtil::usable_in_hash_index(Uint32 typeId, const void* info) +uint +NdbSqlUtil::check_column_for_hash_index(Uint32 typeId, const void* info) { - return usable_in_pk(typeId, info); + return check_column_for_pk(typeId, info); } -bool -NdbSqlUtil::usable_in_ordered_index(Uint32 typeId, const void* info) +uint +NdbSqlUtil::check_column_for_ordered_index(Uint32 typeId, const void* info) { const Type& type = getType(typeId); if (type.m_cmp == NULL) @@ -919,13 +921,15 @@ NdbSqlUtil::usable_in_ordered_index(Uint32 typeId, const void* info) case Type::Longvarchar: { const CHARSET_INFO *cs = (const CHARSET_INFO*)info; - return - cs != 0 && - cs->cset != 0 && - cs->coll != 0 && - cs->coll->strnxfrm != 0 && - cs->coll->strnncollsp != 0 && - cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY; + if (cs != 0 && + cs->cset != 0 && + cs->coll != 0 && + cs->coll->strnxfrm != 0 && + cs->coll->strnncollsp != 0 && + cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY) + return 0; + else + return 743; } break; case Type::Undefined: @@ -934,9 +938,9 @@ NdbSqlUtil::usable_in_ordered_index(Uint32 typeId, const void* info) case Type::Bit: // can be fixed break; default: - return true; + return 0; } - return false; + return 906; } // utilities diff --git a/ndb/src/kernel/SimBlockList.cpp b/ndb/src/kernel/SimBlockList.cpp index 6029fc7e225..271d515dc92 100644 --- a/ndb/src/kernel/SimBlockList.cpp +++ b/ndb/src/kernel/SimBlockList.cpp @@ -111,8 +111,12 @@ SimBlockList::unload(){ if(theList != 0){ for(int i = 0; i<noOfBlocks; i++){ if(theList[i] != 0){ +#ifdef VM_TRACE theList[i]->~SimulatedBlock(); free(theList[i]); +#else + delete(theList[i]); +#endif theList[i] = 0; } } diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp index 93c4a583624..c85c8384081 100644 --- a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp +++ b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp @@ -217,11 +217,12 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal) break; } if (descAttr.m_charset != 0) { + uint err; CHARSET_INFO *cs = all_charsets[descAttr.m_charset]; ndbrequire(cs != 0); - if (! NdbSqlUtil::usable_in_ordered_index(descAttr.m_typeId, cs)) { + if ((err = NdbSqlUtil::check_column_for_ordered_index(descAttr.m_typeId, cs))) { jam(); - errorCode = TuxAddAttrRef::InvalidCharset; + errorCode = (TuxAddAttrRef::ErrorCode) err; break; } } diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp index 564501526a8..08251348b2b 100644 --- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp +++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp @@ -25,7 +25,10 @@ void Ndbcntr::initData() { - + c_start.reset(); + cmasterNodeId = 0; + cnoStartNodes = 0; + cnoWaitrep = 0; // Records with constant sizes ndbBlocksRec = new NdbBlocksRec[ZSIZE_NDB_BLOCKS_REC]; }//Ndbcntr::initData() diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index f7a28eb989c..6cb8e1f9a24 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -1573,7 +1573,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, bool alter) { DBUG_ENTER("NdbDictInterface::createOrAlterTable"); - unsigned i; + unsigned i, err; if((unsigned)impl.getNoOfPrimaryKeys() > NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY){ m_error.code= 4317; DBUG_RETURN(-1); @@ -1683,8 +1683,10 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, DBUG_RETURN(-1); } // primary key type check - if (col->m_pk && ! NdbSqlUtil::usable_in_pk(col->m_type, col->m_cs)) { - m_error.code= (col->m_cs != 0 ? 743 : 739); + if (col->m_pk && + (err = NdbSqlUtil::check_column_for_pk(col->m_type, col->m_cs))) + { + m_error.code= err; DBUG_RETURN(-1); } // distribution key not supported for Char attribute @@ -2157,7 +2159,7 @@ NdbDictInterface::createIndex(Ndb & ndb, { //validate(); //aggregate(); - unsigned i; + unsigned i, err; UtilBufferWriter w(m_buffer); const size_t len = strlen(impl.m_externalName.c_str()) + 1; if(len > MAX_TAB_NAME_SIZE) { @@ -2208,10 +2210,12 @@ NdbDictInterface::createIndex(Ndb & ndb, // index key type check if (it == DictTabInfo::UniqueHashIndex && - ! NdbSqlUtil::usable_in_hash_index(col->m_type, col->m_cs) || + (err = NdbSqlUtil::check_column_for_hash_index(col->m_type, col->m_cs)) + || it == DictTabInfo::OrderedIndex && - ! NdbSqlUtil::usable_in_ordered_index(col->m_type, col->m_cs)) { - m_error.code = 743; + (err = NdbSqlUtil::check_column_for_ordered_index(col->m_type, col->m_cs))) + { + m_error.code = err; return -1; } attributeList.id[i] = col->m_attrId; diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index 9f8a2916d2f..869704c7bb3 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -1086,6 +1086,11 @@ int NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo, int type, const void* aValue, Uint32 len) { + if (!tAttrInfo) + { + setErrorCodeAbort(4318); // Invalid attribute + return -1; + } if (theOperationType == OpenRangeScanRequest && (0 <= type && type <= 4) && len <= 8000) { diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index a3e47154bc3..60183ac9b5a 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -80,6 +80,20 @@ String *Item_str_func::check_well_formed_result(String *str) } +my_decimal *Item_str_func::val_decimal(my_decimal *decimal_value) +{ + DBUG_ASSERT(fixed == 1); + char buff[64]; + String *res, tmp(buff,sizeof(buff), &my_charset_bin); + res= val_str(&tmp); + if (!res) + return 0; + (void)str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(), + res->length(), res->charset(), decimal_value); + return decimal_value; +} + + double Item_str_func::val_real() { DBUG_ASSERT(fixed == 1); diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 6a95a9e5d1f..7d7b62df0dc 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -33,6 +33,7 @@ public: Item_str_func(List<Item> &list) :Item_func(list) {decimals=NOT_FIXED_DEC; } longlong val_int(); double val_real(); + my_decimal *val_decimal(my_decimal *); enum Item_result result_type () const { return STRING_RESULT; } void left_right_max_length(); String *check_well_formed_result(String *str); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 8826144266e..962454e237e 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -377,12 +377,12 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table, case INT_RESULT: return new Field_longlong(max_length,maybe_null,name,table,unsigned_flag); case STRING_RESULT: - if (max_length > 255 && convert_blob_length) + if (max_length/collation.collation->mbmaxlen > 255 && convert_blob_length) return new Field_varstring(convert_blob_length, maybe_null, name, table, collation.collation); return make_string_field(table); - case DECIMAL_RESULT: +case DECIMAL_RESULT: return new Field_new_decimal(max_length, maybe_null, name, table, decimals, unsigned_flag); case ROW_RESULT: diff --git a/sql/item_sum.h b/sql/item_sum.h index 328f8dd8400..f4ff257aa4e 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -1121,7 +1121,7 @@ public: virtual Item_result result_type () const { return STRING_RESULT; } enum_field_types field_type() const { - if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB) + if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB ) return FIELD_TYPE_BLOB; else return MYSQL_TYPE_VARCHAR; diff --git a/sql/lock.cc b/sql/lock.cc index a584b063a0b..8ea13b2117c 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -78,6 +78,7 @@ extern HASH open_cache; static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count, uint flags, TABLE **write_locked); +static void reset_lock_data(MYSQL_LOCK *sql_lock); static int lock_external(THD *thd, TABLE **table,uint count); static int unlock_external(THD *thd, TABLE **table,uint count); static void print_lock_error(int error, const char *); @@ -135,12 +136,16 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, */ if (wait_if_global_read_lock(thd, 1, 1)) { + /* Clear the lock type of all lock data to avoid reusage. */ + reset_lock_data(sql_lock); my_free((gptr) sql_lock,MYF(0)); sql_lock=0; break; - } + } if (thd->version != refresh_version) { + /* Clear the lock type of all lock data to avoid reusage. */ + reset_lock_data(sql_lock); my_free((gptr) sql_lock,MYF(0)); goto retry; } @@ -149,6 +154,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, thd->proc_info="System lock"; if (lock_external(thd, tables, count)) { + /* Clear the lock type of all lock data to avoid reusage. */ + reset_lock_data(sql_lock); my_free((gptr) sql_lock,MYF(0)); sql_lock=0; break; @@ -699,7 +706,10 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, *write_lock_used=table; if (table->db_stat & HA_READ_ONLY) { - my_error(ER_OPEN_AS_READONLY, MYF(0), table->alias); + my_error(ER_OPEN_AS_READONLY,MYF(0),table->alias); + /* Clear the lock type of the lock data that are stored already. */ + sql_lock->lock_count= locks - sql_lock->locks; + reset_lock_data(sql_lock); my_free((gptr) sql_lock,MYF(0)); DBUG_RETURN(0); } @@ -724,6 +734,48 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, } +/* + Reset lock type in lock data. + + SYNOPSIS + reset_lock_data() + sql_lock The MySQL lock. + + DESCRIPTION + + After a locking error we want to quit the locking of the table(s). + The test case in the bug report for Bug #18544 has the following + cases: 1. Locking error in lock_external() due to InnoDB timeout. + 2. Locking error in get_lock_data() due to missing write permission. + 3. Locking error in wait_if_global_read_lock() due to lock conflict. + + In all these cases we have already set the lock type into the lock + data of the open table(s). If the table(s) are in the open table + cache, they could be reused with the non-zero lock type set. This + could lead to ignoring a different lock type with the next lock. + + Clear the lock type of all lock data. This ensures that the next + lock request will set its lock type properly. + + RETURN + void +*/ + +static void reset_lock_data(MYSQL_LOCK *sql_lock) +{ + THR_LOCK_DATA **ldata; + THR_LOCK_DATA **ldata_end; + + for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count; + ldata < ldata_end; + ldata++) + { + /* Reset lock type. */ + (*ldata)->type= TL_UNLOCK; + } +} + + /***************************************************************************** Lock table based on the name. This is used when we need total access to a closed, not open table diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 8512c075f69..34e7ee969b6 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -454,6 +454,7 @@ public: void print(String *str); + bool add_fake_select_lex(THD *thd); void init_prepare_fake_select_lex(THD *thd); inline bool is_prepared() { return prepared; } bool change_result(select_subselect *result, select_subselect *old_result); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 38eadb5a738..c58628cd856 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5544,48 +5544,17 @@ mysql_new_select(LEX *lex, bool move_down) } else { - Name_resolution_context *outer_context; if (lex->current_select->order_list.first && !lex->current_select->braces) { my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY"); DBUG_RETURN(1); } select_lex->include_neighbour(lex->current_select); - /* - we are not sure that we have one level of SELECTs above, so we take - outer_context address from first select of unit - */ - outer_context= - select_lex->master_unit()->first_select()->context.outer_context; - SELECT_LEX_UNIT *unit= select_lex->master_unit(); - SELECT_LEX *fake= unit->fake_select_lex; - if (!fake) - { - /* - as far as we included SELECT_LEX for UNION unit should have - fake SELECT_LEX for UNION processing - */ - if (!(fake= unit->fake_select_lex= new (thd->mem_root) SELECT_LEX())) - DBUG_RETURN(1); - fake->include_standalone(unit, - (SELECT_LEX_NODE**)&unit->fake_select_lex); - fake->select_number= INT_MAX; - fake->parent_lex= lex; /* Used in init_query. */ - fake->make_empty_select(); - fake->linkage= GLOBAL_OPTIONS_TYPE; - fake->select_limit= 0; - - fake->context.outer_context= outer_context; - /* allow item list resolving in fake select for ORDER BY */ - fake->context.resolve_in_select_list= TRUE; - fake->context.select_lex= fake; - /* - Remove the name resolution context of the fake select from the - context stack. - */ - lex->pop_context(); - } - select_lex->context.outer_context= outer_context; + SELECT_LEX_UNIT *unit= select_lex->master_unit(); + if (!unit->fake_select_lex && unit->add_fake_select_lex(lex->thd)) + DBUG_RETURN(1); + select_lex->context.outer_context= + unit->first_select()->context.outer_context; } select_lex->master_unit()->global_parameters= select_lex; @@ -6358,6 +6327,68 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type) /* + Create a fake SELECT_LEX for a unit + + SYNOPSIS: + add_fake_select_lex() + thd thread handle + + DESCRIPTION + The method create a fake SELECT_LEX object for a unit. + This object is created for any union construct containing a union + operation and also for any single select union construct of the form + (SELECT ... ORDER BY order_list [LIMIT n]) ORDER BY ... + or of the form + (SELECT ... ORDER BY LIMIT n) ORDER BY ... + + NOTES + The object is used to retrieve rows from the temporary table + where the result on the union is obtained. + + RETURN VALUES + 1 on failure to create the object + 0 on success +*/ + +bool st_select_lex_unit::add_fake_select_lex(THD *thd) +{ + SELECT_LEX *first_sl= first_select(); + DBUG_ENTER("add_fake_select_lex"); + DBUG_ASSERT(!fake_select_lex); + + if (!(fake_select_lex= new (thd->mem_root) SELECT_LEX())) + DBUG_RETURN(1); + fake_select_lex->include_standalone(this, + (SELECT_LEX_NODE**)&fake_select_lex); + fake_select_lex->select_number= INT_MAX; + fake_select_lex->parent_lex= thd->lex; /* Used in init_query. */ + fake_select_lex->make_empty_select(); + fake_select_lex->linkage= GLOBAL_OPTIONS_TYPE; + fake_select_lex->select_limit= 0; + + fake_select_lex->context.outer_context=first_sl->context.outer_context; + /* allow item list resolving in fake select for ORDER BY */ + fake_select_lex->context.resolve_in_select_list= TRUE; + fake_select_lex->context.select_lex= fake_select_lex; + + if (!first_sl->next_select()) + { + /* + This works only for + (SELECT ... ORDER BY list [LIMIT n]) ORDER BY order_list [LIMIT m], + (SELECT ... LIMIT n) ORDER BY order_list [LIMIT m] + just before the parser starts processing order_list + */ + global_parameters= fake_select_lex; + fake_select_lex->no_table_names_allowed= 1; + thd->lex->current_select= fake_select_lex; + } + thd->lex->pop_context(); + DBUG_RETURN(0); +} + + +/* Push a new name resolution context for a JOIN ... ON clause to the context stack of a query block. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0211539e784..47c5281b258 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -224,7 +224,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, register SELECT_LEX *select_lex = &lex->select_lex; DBUG_ENTER("handle_select"); - if (select_lex->next_select()) + if (select_lex->next_select() || select_lex->master_unit()->fake_select_lex) res= mysql_union(thd, lex, result, &lex->unit, setup_tables_done_option); else { diff --git a/sql/sql_union.cc b/sql/sql_union.cc index dee88af7d83..c5af81ae55a 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -202,7 +202,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, thd_arg->lex->current_select= sl= first_sl; found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS; - is_union= test(first_sl->next_select()); + is_union= first_sl->next_select() || fake_select_lex; /* Global option */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c3d9cb5913b..6473163a6ec 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5609,14 +5609,32 @@ order_clause: ORDER_SYM BY { LEX *lex=Lex; - if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE && - lex->current_select->olap != - UNSPECIFIED_OLAP_TYPE) + SELECT_LEX *sel= lex->current_select; + SELECT_LEX_UNIT *unit= sel-> master_unit(); + if (sel->linkage != GLOBAL_OPTIONS_TYPE && + sel->olap != UNSPECIFIED_OLAP_TYPE) { my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY"); YYABORT; } + if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex) + { + /* + A query of the of the form (SELECT ...) ORDER BY order_list is + executed in the same way as the query + SELECT ... ORDER BY order_list + unless the SELECT construct contains ORDER BY or LIMIT clauses. + Otherwise we create a fake SELECT_LEX if it has not been created + yet. + */ + SELECT_LEX *first_sl= unit->first_select(); + if (!first_sl->next_select() && + (first_sl->order_list.elements || + first_sl->select_limit) && + unit->add_fake_select_lex(lex->thd)) + YYABORT; + } } order_list; order_list: |