mirror of
https://github.com/MariaDB/server.git
synced 2026-05-15 19:37:16 +02:00
Merge bk-internal.mysql.com:/home/bk/mysql-5.1-engines
into chilla.local:/home/mydev/mysql-5.1-axmrg sql/mysql_priv.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_servers.h: Auto merged storage/federated/ha_federated.cc: Auto merged storage/heap/ha_heap.cc: Auto merged storage/myisam/ha_myisam.cc: Auto merged sql/sql_servers.cc: Manual merge
This commit is contained in:
commit
74519b9835
16 changed files with 1026 additions and 358 deletions
|
|
@ -43,23 +43,55 @@
|
|||
The create table will simply create the .frm file, and within the
|
||||
"CREATE TABLE" SQL, there SHALL be any of the following :
|
||||
|
||||
comment=scheme://username:password@hostname:port/database/tablename
|
||||
comment=scheme://username@hostname/database/tablename
|
||||
comment=scheme://username:password@hostname/database/tablename
|
||||
comment=scheme://username:password@hostname/database/tablename
|
||||
connection=scheme://username:password@hostname:port/database/tablename
|
||||
connection=scheme://username@hostname/database/tablename
|
||||
connection=scheme://username:password@hostname/database/tablename
|
||||
connection=scheme://username:password@hostname/database/tablename
|
||||
|
||||
- OR -
|
||||
|
||||
As of 5.1 (See worklog #3031), federated now allows you to use a non-url
|
||||
format, taking advantage of mysql.servers:
|
||||
|
||||
connection="connection_one"
|
||||
connection="connection_one/table_foo"
|
||||
|
||||
An example would be:
|
||||
|
||||
comment=mysql://username:password@hostname:port/database/tablename
|
||||
connection=mysql://username:password@hostname:port/database/tablename
|
||||
|
||||
***IMPORTANT***
|
||||
or, if we had:
|
||||
|
||||
This is a first release, conceptual release
|
||||
Only 'mysql://' is supported at this release.
|
||||
create server 'server_one' foreign data wrapper 'mysql' options
|
||||
(HOST '127.0.0.1',
|
||||
DATABASE 'db1',
|
||||
USER 'root',
|
||||
PASSWORD '',
|
||||
PORT 3306,
|
||||
SOCKET '',
|
||||
OWNER 'root');
|
||||
|
||||
CREATE TABLE federated.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(64) NOT NULL default ''
|
||||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='server_one';
|
||||
|
||||
This comment connection string is necessary for the handler to be
|
||||
able to connect to the foreign server.
|
||||
So, this will have been the equivalent of
|
||||
|
||||
CONNECTION="mysql://root@127.0.0.1:3306/db1/t1"
|
||||
|
||||
Then, we can also change the server to point to a new schema:
|
||||
|
||||
ALTER SERVER 'server_one' options(DATABASE 'db2');
|
||||
|
||||
All subsequent calls will now be against db2.t1! Guess what? You don't
|
||||
have to perform an alter table!
|
||||
|
||||
This connecton="connection string" is necessary for the handler to be
|
||||
able to connect to the foreign server, either by URL, or by server
|
||||
name.
|
||||
|
||||
|
||||
The basic flow is this:
|
||||
|
|
@ -166,7 +198,7 @@
|
|||
KEY other_key (other))
|
||||
ENGINE="FEDERATED"
|
||||
DEFAULT CHARSET=latin1
|
||||
COMMENT='root@127.0.0.1:9306/federated/test_federated';
|
||||
CONNECTION='mysql://root@127.0.0.1:9306/federated/test_federated';
|
||||
|
||||
Notice the "COMMENT" and "ENGINE" field? This is where you
|
||||
respectively set the engine type, "FEDERATED" and foreign
|
||||
|
|
@ -263,7 +295,7 @@
|
|||
To run these tests, go into ./mysql-test (based in the directory you
|
||||
built the server in)
|
||||
|
||||
./mysql-test-run federatedd
|
||||
./mysql-test-run federated
|
||||
|
||||
To run the test, or if you want to run the test and have debug info:
|
||||
|
||||
|
|
@ -311,7 +343,7 @@
|
|||
-------------
|
||||
|
||||
These were the files that were modified or created for this
|
||||
Federated handler to work:
|
||||
Federated handler to work, in 5.0:
|
||||
|
||||
./configure.in
|
||||
./sql/Makefile.am
|
||||
|
|
@ -329,6 +361,13 @@
|
|||
./sql/ha_federated.cc
|
||||
./sql/ha_federated.h
|
||||
|
||||
In 5.1
|
||||
|
||||
my:~/mysql-build/mysql-5.1-bkbits patg$ ls storage/federated/
|
||||
CMakeLists.txt Makefile.in ha_federated.h plug.in
|
||||
Makefile SCCS libfederated.a
|
||||
Makefile.am ha_federated.cc libfederated_a-ha_federated.o
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -546,42 +585,39 @@ static int parse_url_error(FEDERATED_SHARE *share, TABLE *table, int error_num)
|
|||
int buf_len;
|
||||
DBUG_ENTER("ha_federated parse_url_error");
|
||||
|
||||
if (share->connection_string)
|
||||
{
|
||||
DBUG_PRINT("info",
|
||||
("error: parse_url. Returning error code %d \
|
||||
freeing share->connection_string %lx",
|
||||
error_num, (long unsigned int) share->connection_string));
|
||||
my_free((gptr) share->connection_string, MYF(0));
|
||||
share->connection_string= 0;
|
||||
}
|
||||
buf_len= min(table->s->connect_string.length,
|
||||
FEDERATED_QUERY_BUFFER_SIZE-1);
|
||||
strmake(buf, table->s->connect_string.str, buf_len);
|
||||
my_error(error_num, MYF(0), buf);
|
||||
DBUG_RETURN(error_num);
|
||||
}
|
||||
|
||||
/*
|
||||
retrieve server object which contains server meta-data
|
||||
from the system table given a server's name, set share
|
||||
connection parameter members
|
||||
*/
|
||||
int get_connection(FEDERATED_SHARE *share)
|
||||
int get_connection(MEM_ROOT *mem_root, FEDERATED_SHARE *share)
|
||||
{
|
||||
int error_num= ER_FOREIGN_SERVER_DOESNT_EXIST;
|
||||
char error_buffer[FEDERATED_QUERY_BUFFER_SIZE];
|
||||
FOREIGN_SERVER *server;
|
||||
FOREIGN_SERVER *server, server_buffer;
|
||||
DBUG_ENTER("ha_federated::get_connection");
|
||||
|
||||
/*
|
||||
get_server_by_name() clones the server if exists and allocates
|
||||
copies of strings in the supplied mem_root
|
||||
*/
|
||||
if (!(server=
|
||||
get_server_by_name(share->connection_string)))
|
||||
get_server_by_name(mem_root, share->connection_string, &server_buffer)))
|
||||
{
|
||||
DBUG_PRINT("info", ("get_server_by_name returned > 0 error condition!"));
|
||||
/* need to come up with error handling */
|
||||
error_num=1;
|
||||
goto error;
|
||||
}
|
||||
DBUG_PRINT("info", ("get_server_by_name returned server at %lx", (long unsigned int) server));
|
||||
DBUG_PRINT("info", ("get_server_by_name returned server at %lx",
|
||||
(long unsigned int) server));
|
||||
|
||||
/*
|
||||
Most of these should never be empty strings, error handling will
|
||||
|
|
@ -590,29 +626,22 @@ int get_connection(FEDERATED_SHARE *share)
|
|||
except there are errors in the trace file of the share being overrun
|
||||
at the address of the share.
|
||||
*/
|
||||
if (server->server_name)
|
||||
share->server_name= server->server_name;
|
||||
share->server_name_length= server->server_name_length ?
|
||||
server->server_name_length : 0;
|
||||
if (server->username)
|
||||
share->username= server->username;
|
||||
if (server->password)
|
||||
share->password= server->password;
|
||||
if (server->db)
|
||||
share->database= server->db;
|
||||
|
||||
share->port= server->port ? (ushort) server->port : MYSQL_PORT;
|
||||
|
||||
if (server->host)
|
||||
share->hostname= server->host;
|
||||
if (server->socket)
|
||||
share->socket= server->socket;
|
||||
else if (strcmp(share->hostname, my_localhost) == 0)
|
||||
share->socket= my_strdup(MYSQL_UNIX_ADDR, MYF(0));
|
||||
if (server->scheme)
|
||||
share->scheme= server->scheme;
|
||||
else
|
||||
share->scheme= NULL;
|
||||
share->server_name_length= server->server_name_length;
|
||||
share->server_name= server->server_name;
|
||||
share->username= server->username;
|
||||
share->password= server->password;
|
||||
share->database= server->db;
|
||||
#ifndef I_AM_PARANOID
|
||||
share->port= server->port > 0 && server->port < 65536 ?
|
||||
#else
|
||||
share->port= server->port > 1023 && server->port < 65536 ?
|
||||
#endif
|
||||
(ushort) server->port : MYSQL_PORT;
|
||||
share->hostname= server->host;
|
||||
if (!(share->socket= server->socket) &&
|
||||
!strcmp(share->hostname, my_localhost))
|
||||
share->socket= (char *) MYSQL_UNIX_ADDR;
|
||||
share->scheme= server->scheme;
|
||||
|
||||
DBUG_PRINT("info", ("share->username %s", share->username));
|
||||
DBUG_PRINT("info", ("share->password %s", share->password));
|
||||
|
|
@ -635,6 +664,7 @@ error:
|
|||
|
||||
SYNOPSIS
|
||||
parse_url()
|
||||
mem_root MEM_ROOT pointer for memory allocation
|
||||
share pointer to FEDERATED share
|
||||
table pointer to current TABLE class
|
||||
table_create_flag determines what error to throw
|
||||
|
|
@ -684,7 +714,7 @@ error:
|
|||
|
||||
*/
|
||||
|
||||
static int parse_url(FEDERATED_SHARE *share, TABLE *table,
|
||||
static int parse_url(MEM_ROOT *mem_root, FEDERATED_SHARE *share, TABLE *table,
|
||||
uint table_create_flag)
|
||||
{
|
||||
uint error_num= (table_create_flag ?
|
||||
|
|
@ -698,20 +728,19 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
|
|||
DBUG_PRINT("info", ("Length: %d", table->s->connect_string.length));
|
||||
DBUG_PRINT("info", ("String: '%.*s'", table->s->connect_string.length,
|
||||
table->s->connect_string.str));
|
||||
share->connection_string= my_strndup(table->s->connect_string.str,
|
||||
table->s->connect_string.length,
|
||||
MYF(0));
|
||||
share->connection_string= strmake_root(mem_root, table->s->connect_string.str,
|
||||
table->s->connect_string.length);
|
||||
|
||||
// Add a null for later termination of table name
|
||||
share->connection_string[table->s->connect_string.length]= 0;
|
||||
DBUG_PRINT("info",("parse_url alloced share->connection_string %lx",
|
||||
(long unsigned int) share->connection_string));
|
||||
|
||||
DBUG_PRINT("info",("share->connection_string %s",share->connection_string));
|
||||
/* No delimiters, must be a straight connection name */
|
||||
if ( (!strchr(share->connection_string, '/')) &&
|
||||
(!strchr(share->connection_string, '@')) &&
|
||||
(!strchr(share->connection_string, ';')))
|
||||
/*
|
||||
No :// or @ in connection string. Must be a straight connection name of
|
||||
either "servername" or "servername/tablename"
|
||||
*/
|
||||
if ( (!strstr(share->connection_string, "://") &&
|
||||
(!strchr(share->connection_string, '@'))))
|
||||
{
|
||||
|
||||
DBUG_PRINT("info",
|
||||
|
|
@ -720,17 +749,51 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
|
|||
share->connection_string,
|
||||
(long unsigned int) share->connection_string));
|
||||
|
||||
/* ok, so we do a little parsing, but not completely! */
|
||||
share->parsed= FALSE;
|
||||
if ((error_num= get_connection(share)))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
connection specifies everything but, resort to
|
||||
expecting remote and foreign table names to match
|
||||
If there is a single '/' in the connection string, this means the user is
|
||||
specifying a table name
|
||||
*/
|
||||
share->table_name= table->s->table_name.str;
|
||||
share->table_name_length= table->s->table_name.length;
|
||||
share->table_name[share->table_name_length]= '\0';
|
||||
|
||||
if ((share->table_name= strchr(share->connection_string, '/')))
|
||||
{
|
||||
share->connection_string[share->table_name - share->connection_string]= '\0';
|
||||
share->table_name++;
|
||||
share->table_name_length= strlen(share->table_name);
|
||||
|
||||
DBUG_PRINT("info",
|
||||
("internal format, parsed table_name share->connection_string \
|
||||
%s share->table_name %s",
|
||||
share->connection_string, share->table_name));
|
||||
|
||||
/*
|
||||
there better not be any more '/'s !
|
||||
*/
|
||||
if (strchr(share->table_name, '/'))
|
||||
goto error;
|
||||
|
||||
}
|
||||
/*
|
||||
otherwise, straight server name, use tablename of federated table
|
||||
as remote table name
|
||||
*/
|
||||
else
|
||||
{
|
||||
/*
|
||||
connection specifies everything but, resort to
|
||||
expecting remote and foreign table names to match
|
||||
*/
|
||||
share->table_name= strmake_root(mem_root, table->s->table_name.str,
|
||||
(share->table_name_length= table->s->table_name.length));
|
||||
DBUG_PRINT("info",
|
||||
("internal format, default table_name share->connection_string \
|
||||
%s share->table_name %s",
|
||||
share->connection_string, share->table_name));
|
||||
}
|
||||
|
||||
if ((error_num= get_connection(mem_root, share)))
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -816,7 +879,7 @@ Then password is a null string, so set to NULL
|
|||
if (!share->port)
|
||||
{
|
||||
if (strcmp(share->hostname, my_localhost) == 0)
|
||||
share->socket= my_strdup(MYSQL_UNIX_ADDR, MYF(0));
|
||||
share->socket= (char *) MYSQL_UNIX_ADDR;
|
||||
else
|
||||
share->port= MYSQL_PORT;
|
||||
}
|
||||
|
|
@ -1420,22 +1483,26 @@ err:
|
|||
|
||||
static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
|
||||
{
|
||||
char *select_query;
|
||||
char query_buffer[FEDERATED_QUERY_BUFFER_SIZE];
|
||||
Field **field;
|
||||
String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
|
||||
FEDERATED_SHARE *share= NULL, tmp_share;
|
||||
MEM_ROOT mem_root;
|
||||
DBUG_ENTER("ha_federated.cc::get_share");
|
||||
|
||||
/*
|
||||
In order to use this string, we must first zero it's length,
|
||||
or it will contain garbage
|
||||
*/
|
||||
query.length(0);
|
||||
|
||||
init_alloc_root(&mem_root, 256, 0);
|
||||
|
||||
pthread_mutex_lock(&federated_mutex);
|
||||
|
||||
tmp_share.share_key= table_name;
|
||||
tmp_share.share_key_length= strlen(table_name);
|
||||
if (parse_url(&tmp_share, table, 0))
|
||||
if (parse_url(&mem_root, &tmp_share, table, 0))
|
||||
goto error;
|
||||
|
||||
/* TODO: change tmp_share.scheme to LEX_STRING object */
|
||||
|
|
@ -1456,24 +1523,17 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
|
|||
query.length(query.length() - sizeof_trailing_comma);
|
||||
|
||||
query.append(STRING_WITH_LEN(" FROM `"));
|
||||
query.append(tmp_share.table_name, tmp_share.table_name_length);
|
||||
query.append(STRING_WITH_LEN("`"));
|
||||
DBUG_PRINT("info", ("calling alloc_root"));
|
||||
|
||||
if (!(share= (FEDERATED_SHARE *)
|
||||
my_multi_malloc(MYF(MY_WME),
|
||||
&share, sizeof(*share),
|
||||
&select_query,
|
||||
query.length()+table->s->connect_string.length+1,
|
||||
NullS)))
|
||||
if (!(share= (FEDERATED_SHARE *) memdup_root(&mem_root, (char*)&tmp_share, sizeof(*share))) ||
|
||||
!(share->select_query= (char*) strmake_root(&mem_root, query.ptr(), query.length())))
|
||||
goto error;
|
||||
|
||||
memcpy(share, &tmp_share, sizeof(tmp_share));
|
||||
|
||||
share->table_name_length= strlen(share->table_name);
|
||||
/* TODO: share->table_name to LEX_STRING object */
|
||||
query.append(share->table_name, share->table_name_length);
|
||||
query.append(STRING_WITH_LEN("`"));
|
||||
share->select_query= select_query;
|
||||
strmov(share->select_query, query.ptr());
|
||||
share->use_count= 0;
|
||||
share->mem_root= mem_root;
|
||||
|
||||
DBUG_PRINT("info",
|
||||
("share->select_query %s", share->select_query));
|
||||
|
||||
|
|
@ -1482,17 +1542,18 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
|
|||
thr_lock_init(&share->lock);
|
||||
pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST);
|
||||
}
|
||||
else
|
||||
free_root(&mem_root, MYF(0)); /* prevents memory leak */
|
||||
|
||||
share->use_count++;
|
||||
pthread_mutex_unlock(&federated_mutex);
|
||||
|
||||
return share;
|
||||
DBUG_RETURN(share);
|
||||
|
||||
error:
|
||||
pthread_mutex_unlock(&federated_mutex);
|
||||
my_free((gptr) tmp_share.connection_string, MYF(MY_ALLOW_ZERO_PTR));
|
||||
tmp_share.connection_string= 0;
|
||||
my_free((gptr) share, MYF(MY_ALLOW_ZERO_PTR));
|
||||
return NULL;
|
||||
free_root(&mem_root, MYF(0));
|
||||
DBUG_RETURN(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1504,23 +1565,16 @@ error:
|
|||
|
||||
static int free_share(FEDERATED_SHARE *share)
|
||||
{
|
||||
MEM_ROOT mem_root= share->mem_root;
|
||||
DBUG_ENTER("free_share");
|
||||
|
||||
pthread_mutex_lock(&federated_mutex);
|
||||
if (!--share->use_count)
|
||||
{
|
||||
hash_delete(&federated_open_tables, (byte*) share);
|
||||
if (share->parsed)
|
||||
my_free((gptr) share->socket, MYF(MY_ALLOW_ZERO_PTR));
|
||||
/*if (share->connection_string)
|
||||
{
|
||||
*/
|
||||
my_free((gptr) share->connection_string, MYF(MY_ALLOW_ZERO_PTR));
|
||||
share->connection_string= 0;
|
||||
/*}*/
|
||||
thr_lock_delete(&share->lock);
|
||||
VOID(pthread_mutex_destroy(&share->mutex));
|
||||
my_free((gptr) share, MYF(0));
|
||||
free_root(&mem_root, MYF(0));
|
||||
}
|
||||
pthread_mutex_unlock(&federated_mutex);
|
||||
|
||||
|
|
@ -1589,6 +1643,8 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked)
|
|||
mysql_options(mysql,MYSQL_SET_CHARSET_NAME,
|
||||
this->table->s->table_charset->csname);
|
||||
|
||||
DBUG_PRINT("info", ("calling mysql_real_connect hostname %s user %s",
|
||||
share->hostname, share->username));
|
||||
if (!mysql || !mysql_real_connect(mysql,
|
||||
share->hostname,
|
||||
share->username,
|
||||
|
|
@ -2831,15 +2887,13 @@ int ha_federated::create(const char *name, TABLE *table_arg,
|
|||
HA_CREATE_INFO *create_info)
|
||||
{
|
||||
int retval;
|
||||
THD *thd= current_thd;
|
||||
FEDERATED_SHARE tmp_share; // Only a temporary share, to test the url
|
||||
DBUG_ENTER("ha_federated::create");
|
||||
|
||||
if (!(retval= parse_url(&tmp_share, table_arg, 1)))
|
||||
if (!(retval= parse_url(thd->mem_root, &tmp_share, table_arg, 1)))
|
||||
retval= check_foreign_data_source(&tmp_share, 1);
|
||||
|
||||
/* free this because strdup created it in parse_url */
|
||||
my_free((gptr) tmp_share.connection_string, MYF(MY_ALLOW_ZERO_PTR));
|
||||
tmp_share.connection_string= 0;
|
||||
DBUG_RETURN(retval);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@
|
|||
The example implements the minimum of what you will probably need.
|
||||
*/
|
||||
typedef struct st_federated_share {
|
||||
MEM_ROOT mem_root;
|
||||
|
||||
bool parsed;
|
||||
/* this key is unique db/tablename */
|
||||
const char *share_key;
|
||||
|
|
@ -67,6 +69,7 @@ typedef struct st_federated_share {
|
|||
char *sport;
|
||||
int share_key_length;
|
||||
ushort port;
|
||||
|
||||
uint table_name_length, server_name_length, connect_string_length, use_count;
|
||||
pthread_mutex_t mutex;
|
||||
THR_LOCK lock;
|
||||
|
|
|
|||
|
|
@ -628,7 +628,10 @@ int ha_heap::create(const char *name, TABLE *table_arg,
|
|||
seg->length= (uint) key_part->length;
|
||||
seg->flag= key_part->key_part_flag;
|
||||
|
||||
seg->charset= field->charset();
|
||||
if (field->flags & (ENUM_FLAG | SET_FLAG))
|
||||
seg->charset= &my_charset_bin;
|
||||
else
|
||||
seg->charset= field->charset();
|
||||
if (field->null_ptr)
|
||||
{
|
||||
seg->null_bit= field->null_bit;
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *record,
|
|||
heap_rb_param custom_arg;
|
||||
uint old_allocated;
|
||||
|
||||
info->last_pos= NULL; /* For heap_rnext/heap_rprev */
|
||||
custom_arg.keyseg= keyinfo->seg;
|
||||
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
|
||||
if (keyinfo->flag & HA_NOSAME)
|
||||
|
|
|
|||
|
|
@ -635,6 +635,9 @@ bool ha_myisam::check_if_locking_is_allowed(uint sql_command,
|
|||
|
||||
int ha_myisam::open(const char *name, int mode, uint test_if_locked)
|
||||
{
|
||||
MI_KEYDEF *keyinfo;
|
||||
MI_COLUMNDEF *recinfo= 0;
|
||||
uint recs;
|
||||
uint i;
|
||||
|
||||
/*
|
||||
|
|
@ -657,6 +660,26 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
|
|||
|
||||
if (!(file=mi_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
|
||||
return (my_errno ? my_errno : -1);
|
||||
if (!table->s->tmp_table) /* No need to perform a check for tmp table */
|
||||
{
|
||||
if ((my_errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
|
||||
{
|
||||
/* purecov: begin inspected */
|
||||
DBUG_PRINT("error", ("Failed to convert TABLE object to MyISAM "
|
||||
"key and column definition"));
|
||||
goto err;
|
||||
/* purecov: end */
|
||||
}
|
||||
if (check_definition(keyinfo, recinfo, table->s->keys, recs,
|
||||
file->s->keyinfo, file->s->rec,
|
||||
file->s->base.keys, file->s->base.fields, true))
|
||||
{
|
||||
/* purecov: begin inspected */
|
||||
my_errno= HA_ERR_CRASHED;
|
||||
goto err;
|
||||
/* purecov: end */
|
||||
}
|
||||
}
|
||||
|
||||
if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
|
||||
VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
|
||||
|
|
@ -677,7 +700,18 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
|
|||
(struct st_mysql_ftparser *)parser->plugin->info;
|
||||
table->key_info[i].block_size= file->s->keyinfo[i].block_length;
|
||||
}
|
||||
return (0);
|
||||
my_errno= 0;
|
||||
goto end;
|
||||
err:
|
||||
this->close();
|
||||
end:
|
||||
/*
|
||||
Both recinfo and keydef are allocated by my_multi_malloc(), thus only
|
||||
recinfo must be freed.
|
||||
*/
|
||||
if (recinfo)
|
||||
my_free((gptr) recinfo, MYF(0));
|
||||
return my_errno;
|
||||
}
|
||||
|
||||
int ha_myisam::close(void)
|
||||
|
|
@ -1023,6 +1057,22 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool do_optimize)
|
|||
ha_rows rows= file->state->records;
|
||||
DBUG_ENTER("ha_myisam::repair");
|
||||
|
||||
/*
|
||||
Normally this method is entered with a properly opened table. If the
|
||||
repair fails, it can be repeated with more elaborate options. Under
|
||||
special circumstances it can happen that a repair fails so that it
|
||||
closed the data file and cannot re-open it. In this case file->dfile
|
||||
is set to -1. We must not try another repair without an open data
|
||||
file. (Bug #25289)
|
||||
*/
|
||||
if (file->dfile == -1)
|
||||
{
|
||||
sql_print_information("Retrying repair of: '%s' failed. "
|
||||
"Please try REPAIR EXTENDED or myisamchk",
|
||||
table->s->path.str);
|
||||
DBUG_RETURN(HA_ADMIN_FAILED);
|
||||
}
|
||||
|
||||
param.db_name= table->s->db.str;
|
||||
param.table_name= table->alias;
|
||||
param.tmpfile_createflag = O_RDWR | O_TRUNC;
|
||||
|
|
|
|||
|
|
@ -573,6 +573,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
|
|||
|
||||
pthread_mutex_lock(&THR_LOCK_myisam);
|
||||
|
||||
/*
|
||||
NOTE: For test_if_reopen() we need a real path name. Hence we need
|
||||
MY_RETURN_REAL_PATH for every fn_format(filename, ...).
|
||||
*/
|
||||
if (ci->index_file_name)
|
||||
{
|
||||
char *iext= strrchr(ci->index_file_name, '.');
|
||||
|
|
@ -584,13 +588,14 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
|
|||
if ((path= strrchr(ci->index_file_name, FN_LIBCHAR)))
|
||||
*path= '\0';
|
||||
fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
|
||||
MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
|
||||
MY_REPLACE_DIR | MY_UNPACK_FILENAME |
|
||||
MY_RETURN_REAL_PATH | MY_APPEND_EXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
|
||||
MY_UNPACK_FILENAME | (have_iext ? MY_REPLACE_EXT :
|
||||
MY_APPEND_EXT));
|
||||
MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
|
||||
(have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
|
||||
}
|
||||
fn_format(linkname, name, "", MI_NAME_IEXT,
|
||||
MY_UNPACK_FILENAME|MY_APPEND_EXT);
|
||||
|
|
@ -603,10 +608,11 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
|
|||
}
|
||||
else
|
||||
{
|
||||
char *iext= strrchr(name, '.');
|
||||
int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
|
||||
fn_format(filename, name, "", MI_NAME_IEXT,
|
||||
(MY_UNPACK_FILENAME |
|
||||
(flags & HA_DONT_TOUCH_DATA) ? MY_RETURN_REAL_PATH : 0) |
|
||||
MY_APPEND_EXT);
|
||||
MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
|
||||
(have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
|
||||
linkname_ptr=0;
|
||||
/* Replace the current file */
|
||||
create_flag=MY_DELETE_OLD;
|
||||
|
|
@ -618,6 +624,9 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
|
|||
A TRUNCATE command checks for the table in the cache only and could
|
||||
be fooled to believe, the table is not open.
|
||||
Pull the emergency brake in this situation. (Bug #8306)
|
||||
|
||||
NOTE: The filename is compared against unique_file_name of every
|
||||
open table. Hence we need a real path here.
|
||||
*/
|
||||
if (test_if_reopen(filename))
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue