Merge jbruehe@bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/M50/mysql-5.0
This commit is contained in:
commit
19b0b3c62b
@ -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))))
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* rsa.h for openSSL */
|
||||
|
||||
|
||||
#ifndef ysSSL_rsa_h__
|
||||
#ifndef yaSSL_rsa_h__
|
||||
#define yaSSL_rsa_h__
|
||||
|
||||
enum { RSA_F4 = 1 };
|
||||
|
@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ysSSL_openssl_h__
|
||||
#ifndef yaSSL_openssl_h__
|
||||
#define yaSSL_openssl_h__
|
||||
|
||||
#include <stdio.h> /* ERR_print fp */
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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*);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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()))
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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*);
|
||||
|
@ -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");
|
||||
|
@ -1243,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
|
||||
|
@ -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"
|
||||
|
@ -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');
|
||||
|
@ -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;
|
||||
|
@ -398,6 +398,16 @@ 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
|
||||
|
||||
#
|
||||
|
@ -1 +1 @@
|
||||
--innodb_locks_unsafe_for_binlog=true
|
||||
--loose-innodb_locks_unsafe_for_binlog=true
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
103
sql/sql_parse.cc
103
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;
|
||||
@ -6357,6 +6326,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.
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -5697,14 +5697,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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user