Commit ae6c5d0d authored by Michael Widenius's avatar Michael Widenius

Fix for LP#571200 MySQL Bug#32426: FederatedX corrupt ORDER BY with TEXT

Patch taken from lp:~capttofu/maria/bug_571200 (originally for MariaDB 5.3, but adapted for 5.1)

parent 6bbb0b57
...@@ -213,7 +213,7 @@ id name ...@@ -213,7 +213,7 @@ id name
alter server s1 options (database 'db_bogus'); alter server s1 options (database 'db_bogus');
flush tables; flush tables;
select * from federated.t1; select * from federated.t1;
ERROR 42000: Got error: 1044 : Access denied for user 'test_fed'@'localhost' to database 'db_bogus' ERROR 42000: Received error: 1044 : Access denied for user 'test_fed'@'localhost' to database 'db_bogus'
drop server if exists 's1'; drop server if exists 's1';
ERROR 42000: Access denied; you need the SUPER privilege for this operation ERROR 42000: Access denied; you need the SUPER privilege for this operation
create server 's1' foreign data wrapper 'mysql' options create server 's1' foreign data wrapper 'mysql' options
......
/* /*
Copyright (c) 2007, Antony T Curtis Copyright (c) 2007, Antony T Curtis
All rights reserved. All rights reserved.
...@@ -51,6 +51,12 @@ typedef struct federatedx_savepoint ...@@ -51,6 +51,12 @@ typedef struct federatedx_savepoint
uint flags; uint flags;
} SAVEPT; } SAVEPT;
struct mysql_position
{
MYSQL_RES* result;
MYSQL_ROW_OFFSET offset;
};
class federatedx_io_mysql :public federatedx_io class federatedx_io_mysql :public federatedx_io
{ {
...@@ -76,16 +82,16 @@ class federatedx_io_mysql :public federatedx_io ...@@ -76,16 +82,16 @@ class federatedx_io_mysql :public federatedx_io
virtual int error_code(); virtual int error_code();
virtual const char *error_str(); virtual const char *error_str();
void reset(); void reset();
int commit(); int commit();
int rollback(); int rollback();
int savepoint_set(ulong sp); int savepoint_set(ulong sp);
ulong savepoint_release(ulong sp); ulong savepoint_release(ulong sp);
ulong savepoint_rollback(ulong sp); ulong savepoint_rollback(ulong sp);
void savepoint_restrict(ulong sp); void savepoint_restrict(ulong sp);
ulong last_savepoint() const; ulong last_savepoint() const;
ulong actual_savepoint() const; ulong actual_savepoint() const;
bool is_autocommit() const; bool is_autocommit() const;
...@@ -94,7 +100,7 @@ class federatedx_io_mysql :public federatedx_io ...@@ -94,7 +100,7 @@ class federatedx_io_mysql :public federatedx_io
uint table_name_length, uint flag); uint table_name_length, uint flag);
/* resultset operations */ /* resultset operations */
virtual void free_result(FEDERATEDX_IO_RESULT *io_result); virtual void free_result(FEDERATEDX_IO_RESULT *io_result);
virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result); virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result);
virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result); virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result);
...@@ -104,6 +110,12 @@ class federatedx_io_mysql :public federatedx_io ...@@ -104,6 +110,12 @@ class federatedx_io_mysql :public federatedx_io
unsigned int column); unsigned int column);
virtual bool is_column_null(const FEDERATEDX_IO_ROW *row, virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
unsigned int column) const; unsigned int column) const;
virtual size_t get_ref_length() const;
virtual void mark_position(FEDERATEDX_IO_RESULT *io_result,
void *ref);
virtual int seek_position(FEDERATEDX_IO_RESULT **io_result,
const void *ref);
}; };
...@@ -466,14 +478,13 @@ const char *federatedx_io_mysql::error_str() ...@@ -466,14 +478,13 @@ const char *federatedx_io_mysql::error_str()
return mysql_error(&mysql); return mysql_error(&mysql);
} }
FEDERATEDX_IO_RESULT *federatedx_io_mysql::store_result() FEDERATEDX_IO_RESULT *federatedx_io_mysql::store_result()
{ {
FEDERATEDX_IO_RESULT *result; FEDERATEDX_IO_RESULT *result;
DBUG_ENTER("federatedx_io_mysql::store_result"); DBUG_ENTER("federatedx_io_mysql::store_result");
result= (FEDERATEDX_IO_RESULT *) mysql_store_result(&mysql); result= (FEDERATEDX_IO_RESULT *) mysql_store_result(&mysql);
DBUG_RETURN(result); DBUG_RETURN(result);
} }
...@@ -590,3 +601,45 @@ bool federatedx_io_mysql::table_metadata(ha_statistics *stats, ...@@ -590,3 +601,45 @@ bool federatedx_io_mysql::table_metadata(ha_statistics *stats,
free_result(result); free_result(result);
return 1; return 1;
} }
size_t federatedx_io_mysql::get_ref_length() const
{
return sizeof(mysql_position);
}
void federatedx_io_mysql::mark_position(FEDERATEDX_IO_RESULT *io_result,
void *ref)
{
MYSQL_ROWS *tmp= 0;
mysql_position& pos= *reinterpret_cast<mysql_position*>(ref);
pos.result= (MYSQL_RES *) io_result;
if (pos.result && pos.result->data)
{
for (tmp= pos.result->data->data;
tmp && (tmp->next != pos.result->data_cursor);
tmp= tmp->next)
{}
}
pos.offset= tmp;
}
int federatedx_io_mysql::seek_position(FEDERATEDX_IO_RESULT **io_result,
const void *ref)
{
const mysql_position& pos= *reinterpret_cast<const mysql_position*>(ref);
if (!pos.result || !pos.offset)
return HA_ERR_END_OF_FILE;
pos.result->current_row= 0;
pos.result->data_cursor= pos.offset;
*io_result= (FEDERATEDX_IO_RESULT*) pos.result;
return 0;
}
...@@ -96,6 +96,11 @@ class federatedx_io_null :public federatedx_io ...@@ -96,6 +96,11 @@ class federatedx_io_null :public federatedx_io
unsigned int column); unsigned int column);
virtual bool is_column_null(const FEDERATEDX_IO_ROW *row, virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
unsigned int column) const; unsigned int column) const;
virtual size_t get_ref_length() const;
virtual void mark_position(FEDERATEDX_IO_RESULT *io_result,
void *ref);
virtual int seek_position(FEDERATEDX_IO_RESULT **io_result,
const void *ref);
}; };
...@@ -275,3 +280,20 @@ bool federatedx_io_null::table_metadata(ha_statistics *stats, ...@@ -275,3 +280,20 @@ bool federatedx_io_null::table_metadata(ha_statistics *stats,
return 0; return 0;
} }
size_t federatedx_io_null::get_ref_length() const
{
return sizeof(int);
}
void federatedx_io_null::mark_position(FEDERATEDX_IO_RESULT *io_result,
void *ref)
{
}
int federatedx_io_null::seek_position(FEDERATEDX_IO_RESULT **io_result,
const void *ref)
{
return 0;
}
This diff is collapsed.
/* /*
Copyright (c) 2008, Patrick Galbraith Copyright (c) 2008, Patrick Galbraith
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
...@@ -43,7 +43,7 @@ class federatedx_io; ...@@ -43,7 +43,7 @@ class federatedx_io;
typedef struct st_fedrated_server { typedef struct st_fedrated_server {
MEM_ROOT mem_root; MEM_ROOT mem_root;
uint use_count, io_count; uint use_count, io_count;
uchar *key; uchar *key;
uint key_length; uint key_length;
...@@ -74,10 +74,10 @@ typedef struct st_fedrated_server { ...@@ -74,10 +74,10 @@ typedef struct st_fedrated_server {
#include <mysql.h> #include <mysql.h>
/* /*
handler::print_error has a case statement for error numbers. handler::print_error has a case statement for error numbers.
This value is (10000) is far out of range and will envoke the This value is (10000) is far out of range and will envoke the
default: case. default: case.
(Current error range is 120-159 from include/my_base.h) (Current error range is 120-159 from include/my_base.h)
*/ */
#define HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM 10000 #define HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM 10000
...@@ -158,7 +158,7 @@ class federatedx_io ...@@ -158,7 +158,7 @@ class federatedx_io
const char * get_database() const { return server->database; } const char * get_database() const { return server->database; }
ushort get_port() const { return server->port; } ushort get_port() const { return server->port; }
const char * get_socket() const { return server->socket; } const char * get_socket() const { return server->socket; }
static bool handles_scheme(const char *scheme); static bool handles_scheme(const char *scheme);
static federatedx_io *construct(MEM_ROOT *server_root, static federatedx_io *construct(MEM_ROOT *server_root,
FEDERATEDX_SERVER *server); FEDERATEDX_SERVER *server);
...@@ -167,7 +167,7 @@ class federatedx_io ...@@ -167,7 +167,7 @@ class federatedx_io
{ return alloc_root(mem_root, size); } { return alloc_root(mem_root, size); }
static void operator delete(void *ptr, size_t size) static void operator delete(void *ptr, size_t size)
{ TRASH(ptr, size); } { TRASH(ptr, size); }
virtual int query(const char *buffer, uint length)=0; virtual int query(const char *buffer, uint length)=0;
virtual FEDERATEDX_IO_RESULT *store_result()=0; virtual FEDERATEDX_IO_RESULT *store_result()=0;
...@@ -178,25 +178,25 @@ class federatedx_io ...@@ -178,25 +178,25 @@ class federatedx_io
virtual int error_code()=0; virtual int error_code()=0;
virtual const char *error_str()=0; virtual const char *error_str()=0;
virtual void reset()=0; virtual void reset()=0;
virtual int commit()=0; virtual int commit()=0;
virtual int rollback()=0; virtual int rollback()=0;
virtual int savepoint_set(ulong sp)=0; virtual int savepoint_set(ulong sp)=0;
virtual ulong savepoint_release(ulong sp)=0; virtual ulong savepoint_release(ulong sp)=0;
virtual ulong savepoint_rollback(ulong sp)=0; virtual ulong savepoint_rollback(ulong sp)=0;
virtual void savepoint_restrict(ulong sp)=0; virtual void savepoint_restrict(ulong sp)=0;
virtual ulong last_savepoint() const=0; virtual ulong last_savepoint() const=0;
virtual ulong actual_savepoint() const=0; virtual ulong actual_savepoint() const=0;
virtual bool is_autocommit() const=0; virtual bool is_autocommit() const=0;
virtual bool table_metadata(ha_statistics *stats, const char *table_name, virtual bool table_metadata(ha_statistics *stats, const char *table_name,
uint table_name_length, uint flag) = 0; uint table_name_length, uint flag) = 0;
/* resultset operations */ /* resultset operations */
virtual void free_result(FEDERATEDX_IO_RESULT *io_result)=0; virtual void free_result(FEDERATEDX_IO_RESULT *io_result)=0;
virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result)=0; virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result)=0;
virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result)=0; virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result)=0;
...@@ -206,6 +206,13 @@ class federatedx_io ...@@ -206,6 +206,13 @@ class federatedx_io
unsigned int column)=0; unsigned int column)=0;
virtual bool is_column_null(const FEDERATEDX_IO_ROW *row, virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
unsigned int column) const=0; unsigned int column) const=0;
virtual size_t get_ref_length() const=0;
virtual void mark_position(FEDERATEDX_IO_RESULT *io_result,
void *ref)=0;
virtual int seek_position(FEDERATEDX_IO_RESULT **io_result,
const void *ref)=0;
}; };
...@@ -215,12 +222,12 @@ class federatedx_txn ...@@ -215,12 +222,12 @@ class federatedx_txn
ulong savepoint_level; ulong savepoint_level;
ulong savepoint_stmt; ulong savepoint_stmt;
ulong savepoint_next; ulong savepoint_next;
void release_scan(); void release_scan();
public: public:
federatedx_txn(); federatedx_txn();
~federatedx_txn(); ~federatedx_txn();
bool has_connections() const { return txn_list != NULL; } bool has_connections() const { return txn_list != NULL; }
bool in_transaction() const { return savepoint_next != 0; } bool in_transaction() const { return savepoint_next != 0; }
int acquire(FEDERATEDX_SHARE *share, bool readonly, federatedx_io **io); int acquire(FEDERATEDX_SHARE *share, bool readonly, federatedx_io **io);
...@@ -254,8 +261,12 @@ class ha_federatedx: public handler ...@@ -254,8 +261,12 @@ class ha_federatedx: public handler
federatedx_txn *txn; federatedx_txn *txn;
federatedx_io *io; federatedx_io *io;
FEDERATEDX_IO_RESULT *stored_result; FEDERATEDX_IO_RESULT *stored_result;
/**
Array of all stored results we get during a query execution.
*/
DYNAMIC_ARRAY results;
bool position_called;
uint fetch_num; // stores the fetch num uint fetch_num; // stores the fetch num
FEDERATEDX_IO_OFFSET current_position; // Current position used by ::position()
int remote_error_number; int remote_error_number;
char remote_error_buf[FEDERATEDX_QUERY_BUFFER_SIZE]; char remote_error_buf[FEDERATEDX_QUERY_BUFFER_SIZE];
bool ignore_duplicates, replace_duplicates; bool ignore_duplicates, replace_duplicates;
...@@ -269,7 +280,7 @@ class ha_federatedx: public handler ...@@ -269,7 +280,7 @@ class ha_federatedx: public handler
*/ */
uint convert_row_to_internal_format(uchar *buf, FEDERATEDX_IO_ROW *row, uint convert_row_to_internal_format(uchar *buf, FEDERATEDX_IO_ROW *row,
FEDERATEDX_IO_RESULT *result); FEDERATEDX_IO_RESULT *result);
bool create_where_from_key(String *to, KEY *key_info, bool create_where_from_key(String *to, KEY *key_info,
const key_range *start_key, const key_range *start_key,
const key_range *end_key, const key_range *end_key,
bool records_in_range, bool eq_range); bool records_in_range, bool eq_range);
...@@ -348,18 +359,18 @@ class ha_federatedx: public handler ...@@ -348,18 +359,18 @@ class ha_federatedx: public handler
Talk to Kostja about this - how to get the Talk to Kostja about this - how to get the
number of rows * ... number of rows * ...
disk scan time on other side (block size, size of the row) + network time ... disk scan time on other side (block size, size of the row) + network time ...
The reason for "records * 1000" is that such a large number forces The reason for "records * 1000" is that such a large number forces
this to use indexes " this to use indexes "
*/ */
double scan_time() double scan_time()
{ {
DBUG_PRINT("info", ("records %lu", (ulong) stats.records)); DBUG_PRINT("info", ("records %lu", (ulong) stats.records));
return (double)(stats.records*1000); return (double)(stats.records*1000);
} }
/* /*
The next method will never be called if you do not implement indexes. The next method will never be called if you do not implement indexes.
*/ */
double read_time(uint index, uint ranges, ha_rows rows) double read_time(uint index, uint ranges, ha_rows rows)
{ {
/* /*
Per Brian, this number is bugus, but this method must be implemented, Per Brian, this number is bugus, but this method must be implemented,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment