Merge chilla.local:/home/mydev/mysql-5.1--main

into  chilla.local:/home/mydev/mysql-5.1-amerge


sql/sql_insert.cc:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_trigger.cc:
  Auto merged
This commit is contained in:
unknown 2006-07-08 10:54:54 +02:00
commit 619d8b2c65
32 changed files with 393 additions and 175 deletions

View File

@ -22,6 +22,7 @@ extern const char *not_error_sqlstate;
extern "C" {
#endif
extern CHARSET_INFO *default_client_charset_info;
MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
my_bool default_value, uint server_capabilities);
void free_rows(MYSQL_DATA *cur);

View File

@ -37,6 +37,8 @@ extern "C"
int check_user(THD *thd, enum enum_server_command command,
const char *passwd, uint passwd_len, const char *db,
bool check_count);
void thd_init_client_charset(THD *thd, uint cs_number);
C_MODE_START
#include <mysql.h>
@ -604,11 +606,14 @@ err:
return NULL;
}
#ifdef NO_EMBEDDED_ACCESS_CHECKS
int check_embedded_connection(MYSQL *mysql)
{
int result;
THD *thd= (THD*)mysql->thd;
thd_init_client_charset(thd, mysql->charset->number);
thd->update_charset();
Security_context *sctx= thd->security_ctx;
sctx->host_or_ip= sctx->host= (char*) my_localhost;
strmake(sctx->priv_host, (char*) my_localhost, MAX_HOSTNAME-1);
@ -627,6 +632,8 @@ int check_embedded_connection(MYSQL *mysql)
char scramble_buff[SCRAMBLE_LENGTH];
int passwd_len;
thd_init_client_charset(thd, mysql->charset->number);
thd->update_charset();
if (mysql->options.client_ip)
{
sctx->host= my_strdup(mysql->options.client_ip, MYF(0));

View File

@ -90,49 +90,7 @@ static void end_server(MYSQL *mysql)
}
static int mysql_init_charset(MYSQL *mysql)
{
char charset_name_buff[16], *charset_name;
if ((charset_name=mysql->options.charset_name))
{
const char *save=charsets_dir;
if (mysql->options.charset_dir)
charsets_dir=mysql->options.charset_dir;
mysql->charset=get_charset_by_name(mysql->options.charset_name,
MYF(MY_WME));
charsets_dir=save;
}
else if (mysql->server_language)
{
charset_name=charset_name_buff;
sprintf(charset_name,"%d",mysql->server_language); /* In case of errors */
mysql->charset=get_charset((uint8) mysql->server_language, MYF(MY_WME));
}
else
mysql->charset=default_charset_info;
if (!mysql->charset)
{
mysql->net.last_errno=CR_CANT_READ_CHARSET;
strmov(mysql->net.sqlstate, "HY0000");
if (mysql->options.charset_dir)
sprintf(mysql->net.last_error,ER(mysql->net.last_errno),
charset_name ? charset_name : "unknown",
mysql->options.charset_dir);
else
{
char cs_dir_name[FN_REFLEN];
get_charsets_dir(cs_dir_name);
sprintf(mysql->net.last_error,ER(mysql->net.last_errno),
charset_name ? charset_name : "unknown",
cs_dir_name);
}
return mysql->net.last_errno;
}
return 0;
}
int mysql_init_character_set(MYSQL *mysql);
MYSQL * STDCALL
mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
@ -222,10 +180,10 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
init_embedded_mysql(mysql, client_flag, db_name);
if (check_embedded_connection(mysql))
if (mysql_init_character_set(mysql))
goto error;
if (mysql_init_charset(mysql))
if (check_embedded_connection(mysql))
goto error;
mysql->server_status= SERVER_STATUS_AUTOCOMMIT;

View File

@ -13812,6 +13812,8 @@ select * from t1 where i between 2 and 4 and v in ('def','3r4f','lmn');
i v
4 3r4f
alter table t1 data directory="$MYSQLTEST_VARDIR/tmp";
Warnings:
Warning 0 DATA DIRECTORY option ignored
select * from t1;
i v
1 def

View File

@ -81,6 +81,12 @@ makedate(1997,1)
select makedate(1997,0);
makedate(1997,0)
NULL
select makedate(9999,365);
makedate(9999,365)
9999-12-31
select makedate(9999,366);
makedate(9999,366)
NULL
select addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002");
addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002")
1998-01-02 01:01:01.000001

View File

@ -361,6 +361,12 @@ extract(SECOND FROM "1999-01-02 10:11:12")
select extract(MONTH FROM "2001-02-00");
extract(MONTH FROM "2001-02-00")
2
SELECT DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE);
DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE)
9999-12-31 00:00:00
SELECT DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE);
DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE)
9999-12-31 00:00:00
SELECT EXTRACT(QUARTER FROM '2004-01-15') AS quarter;
quarter
1

View File

@ -816,3 +816,43 @@ check table t1 extended;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
CREATE TABLE t1 (
c1 geometry NOT NULL default '',
SPATIAL KEY i1 (c1(32))
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO t1 (c1) VALUES (
PolygonFromText('POLYGON((-18.6086111000 -66.9327777000,
-18.6055555000 -66.8158332999,
-18.7186111000 -66.8102777000,
-18.7211111000 -66.9269443999,
-18.6086111000 -66.9327777000))'));
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE t1;
CREATE TABLE t1 (
c1 geometry NOT NULL default '',
SPATIAL KEY i1 (c1(32))
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO t1 (c1) VALUES (
PolygonFromText('POLYGON((-18.6086111000 -66.9327777000,
-18.6055555000 -66.8158332999,
-18.7186111000 -66.8102777000,
-18.7211111000 -66.9269443999,
-18.6086111000 -66.9327777000))'));
INSERT INTO t1 (c1) VALUES (
PolygonFromText('POLYGON((-65.7402776999 -96.6686111000,
-65.7372222000 -96.5516666000,
-65.8502777000 -96.5461111000,
-65.8527777000 -96.6627777000,
-65.7402776999 -96.6686111000))'));
INSERT INTO t1 (c1) VALUES (
PolygonFromText('POLYGON((-18.6086111000 -66.9327777000,
-18.6055555000 -66.8158332999,
-18.7186111000 -66.8102777000,
-18.7211111000 -66.9269443999,
-18.6086111000 -66.9327777000))'));
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE t1;

View File

@ -694,3 +694,13 @@ alter table t1 add primary key pti(pt);
ERROR 42000: BLOB/TEXT column 'pt' used in key specification without a key length
alter table t1 add primary key pti(pt(20));
drop table t1;
create table t1 (g GEOMETRY);
select * from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t1 t1 g g 255 4294967295 0 Y 144 0 63
g
select asbinary(g) from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def asbinary(g) 252 8192 0 Y 128 0 63
asbinary(g)
drop table t1;

View File

@ -74,18 +74,24 @@ t9 CREATE TABLE `t9` (
) ENGINE=MyISAM AUTO_INCREMENT=16725 DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' INDEX DIRECTORY='MYSQLTEST_VARDIR/run/'
drop database mysqltest;
create table t1 (a int not null) engine=myisam;
Warnings:
Warning 0 DATA DIRECTORY option ignored
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
alter table t1 add b int;
Warnings:
Warning 0 DATA DIRECTORY option ignored
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Warnings:
Warning 0 INDEX DIRECTORY option ignored
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (

View File

@ -43,6 +43,8 @@ select weekofyear("1997-11-30 23:59:59.000001");
select makedate(1997,1);
select makedate(1997,0);
select makedate(9999,365);
select makedate(9999,366);
#Time functions

View File

@ -143,6 +143,10 @@ select extract(SECOND FROM "1999-01-02 10:11:12");
select extract(MONTH FROM "2001-02-00");
#
# MySQL Bugs: #12356: DATE_SUB or DATE_ADD incorrectly returns null
#
SELECT DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE);
SELECT DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE);
# test EXTRACT QUARTER (Bug #18100)
#

View File

@ -187,4 +187,48 @@ check table t1 extended;
drop table t1;
#
# Bug#17877 - Corrupted spatial index
#
CREATE TABLE t1 (
c1 geometry NOT NULL default '',
SPATIAL KEY i1 (c1(32))
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO t1 (c1) VALUES (
PolygonFromText('POLYGON((-18.6086111000 -66.9327777000,
-18.6055555000 -66.8158332999,
-18.7186111000 -66.8102777000,
-18.7211111000 -66.9269443999,
-18.6086111000 -66.9327777000))'));
# This showed a missing key.
CHECK TABLE t1 EXTENDED;
DROP TABLE t1;
#
CREATE TABLE t1 (
c1 geometry NOT NULL default '',
SPATIAL KEY i1 (c1(32))
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO t1 (c1) VALUES (
PolygonFromText('POLYGON((-18.6086111000 -66.9327777000,
-18.6055555000 -66.8158332999,
-18.7186111000 -66.8102777000,
-18.7211111000 -66.9269443999,
-18.6086111000 -66.9327777000))'));
INSERT INTO t1 (c1) VALUES (
PolygonFromText('POLYGON((-65.7402776999 -96.6686111000,
-65.7372222000 -96.5516666000,
-65.8502777000 -96.5461111000,
-65.8527777000 -96.6627777000,
-65.7402776999 -96.6686111000))'));
# This is the same as the first insert to get a non-unique key.
INSERT INTO t1 (c1) VALUES (
PolygonFromText('POLYGON((-18.6086111000 -66.9327777000,
-18.6055555000 -66.8158332999,
-18.7186111000 -66.8102777000,
-18.7211111000 -66.9269443999,
-18.6086111000 -66.9327777000))'));
# This showed (and still shows) OK.
CHECK TABLE t1 EXTENDED;
DROP TABLE t1;
# End of 4.1 tests

View File

@ -409,3 +409,10 @@ create table t1(pt GEOMETRY);
alter table t1 add primary key pti(pt);
alter table t1 add primary key pti(pt(20));
drop table t1;
--enable_metadata
create table t1 (g GEOMETRY);
select * from t1;
select asbinary(g) from t1;
--disable_metadata
drop table t1;

View File

@ -125,6 +125,8 @@ static void mysql_close_free(MYSQL *mysql);
static int wait_for_data(my_socket fd, uint timeout);
#endif
CHARSET_INFO *default_client_charset_info = &my_charset_latin1;
/****************************************************************************
A modified version of connect(). my_connect() allows you to specify
@ -1426,7 +1428,7 @@ mysql_init(MYSQL *mysql)
bzero((char*) (mysql), sizeof(*(mysql)));
mysql->options.connect_timeout= CONNECT_TIMEOUT;
mysql->last_used_con= mysql->next_slave= mysql->master = mysql;
mysql->charset=default_charset_info;
mysql->charset=default_client_charset_info;
strmov(mysql->net.sqlstate, not_error_sqlstate);
/*
By default, we are a replication pivot. The caller must reset it
@ -1655,6 +1657,50 @@ static MYSQL_METHODS client_methods=
#endif
};
C_MODE_START
int mysql_init_character_set(MYSQL *mysql)
{
NET *net= &mysql->net;
/* Set character set */
if (!mysql->options.charset_name &&
!(mysql->options.charset_name=
my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
return 1;
{
const char *save= charsets_dir;
if (mysql->options.charset_dir)
charsets_dir=mysql->options.charset_dir;
mysql->charset=get_charset_by_csname(mysql->options.charset_name,
MY_CS_PRIMARY, MYF(MY_WME));
charsets_dir= save;
}
if (!mysql->charset)
{
net->last_errno=CR_CANT_READ_CHARSET;
strmov(net->sqlstate, unknown_sqlstate);
if (mysql->options.charset_dir)
my_snprintf(net->last_error, sizeof(net->last_error)-1,
ER(net->last_errno),
mysql->options.charset_name,
mysql->options.charset_dir);
else
{
char cs_dir_name[FN_REFLEN];
get_charsets_dir(cs_dir_name);
my_snprintf(net->last_error, sizeof(net->last_error)-1,
ER(net->last_errno),
mysql->options.charset_name,
cs_dir_name);
}
return 1;
}
return 0;
}
C_MODE_END
MYSQL *
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
@ -1992,42 +2038,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
goto error;
}
/* Set character set */
if (!mysql->options.charset_name &&
!(mysql->options.charset_name=
my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
if (mysql_init_character_set(mysql))
goto error;
{
const char *save= charsets_dir;
if (mysql->options.charset_dir)
charsets_dir=mysql->options.charset_dir;
mysql->charset=get_charset_by_csname(mysql->options.charset_name,
MY_CS_PRIMARY, MYF(MY_WME));
charsets_dir= save;
}
if (!mysql->charset)
{
net->last_errno=CR_CANT_READ_CHARSET;
strmov(net->sqlstate, unknown_sqlstate);
if (mysql->options.charset_dir)
my_snprintf(net->last_error, sizeof(net->last_error)-1,
ER(net->last_errno),
mysql->options.charset_name,
mysql->options.charset_dir);
else
{
char cs_dir_name[FN_REFLEN];
get_charsets_dir(cs_dir_name);
my_snprintf(net->last_error, sizeof(net->last_error)-1,
ER(net->last_errno),
mysql->options.charset_name,
cs_dir_name);
}
goto error;
}
/* Save connection information */
if (!my_multi_malloc(MYF(0),

View File

@ -1536,7 +1536,8 @@ bool Field::optimize_range(uint idx, uint part)
}
Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table)
Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table,
bool keep_type __attribute__((unused)))
{
Field *tmp;
if (!(tmp= (Field*) memdup_root(root,(char*) this,size_of())))
@ -1561,7 +1562,7 @@ Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table,
uint new_null_bit)
{
Field *tmp;
if ((tmp= new_field(root, new_table)))
if ((tmp= new_field(root, new_table, table == new_table)))
{
tmp->ptr= new_ptr;
tmp->null_ptr= new_null_ptr;
@ -6371,11 +6372,12 @@ uint Field_string::max_packed_col_length(uint max_length)
}
Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table)
Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table,
bool keep_type)
{
Field *field;
if (type() != MYSQL_TYPE_VAR_STRING || table == new_table)
return Field::new_field(root, new_table);
if (type() != MYSQL_TYPE_VAR_STRING || keep_type)
return Field::new_field(root, new_table, keep_type);
/*
Old VARCHAR field which should be modified to a VARCHAR on copy
@ -6384,17 +6386,7 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table)
*/
if ((field= new Field_varstring(field_length, maybe_null(), field_name,
new_table->s, charset())))
{
field->init(new_table);
/*
delayed_insert::get_local_table() needs a ptr copied from old table.
This is what other new_field() methods do too. The above method of
Field_varstring sets ptr to NULL.
*/
field->ptr= ptr;
field->null_ptr= null_ptr;
field->null_bit= null_bit;
}
return field;
}
@ -6896,9 +6888,11 @@ int Field_varstring::cmp_binary(const char *a_ptr, const char *b_ptr,
}
Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table)
Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table,
bool keep_type)
{
Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table);
Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table,
keep_type);
if (res)
res->length_bytes= length_bytes;
return res;

View File

@ -219,7 +219,8 @@ public:
*/
virtual bool can_be_compared_as_longlong() const { return FALSE; }
virtual void free() {}
virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table);
virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table,
bool keep_type);
virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
@ -1044,7 +1045,7 @@ public:
enum_field_types real_type() const { return FIELD_TYPE_STRING; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
Field *new_field(MEM_ROOT *root, struct st_table *new_table);
Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
};
@ -1117,7 +1118,7 @@ public:
enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
Field *new_field(MEM_ROOT *root, struct st_table *new_table);
Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit);

View File

@ -32,6 +32,7 @@ public:
Item_geometry_func(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {}
Item_geometry_func(List<Item> &list) :Item_str_func(list) {}
void fix_length_and_dec();
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
};
class Item_func_geometry_from_text: public Item_geometry_func
@ -67,6 +68,7 @@ public:
Item_func_as_wkb(Item *a): Item_geometry_func(a) {}
const char *func_name() const { return "aswkb"; }
String *val_str(String *);
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
};
class Item_func_geometry_type: public Item_str_func

View File

@ -27,6 +27,7 @@
/* TODO: Move month and days to language files */
/* Day number for Dec 31st, 9999 */
#define MAX_DAY_NUMBER 3652424L
static const char *month_names[]=
@ -408,7 +409,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
if (yearday > 0)
{
uint days= calc_daynr(l_time->year,1,1) + yearday - 1;
if (days <= 0 || days >= MAX_DAY_NUMBER)
if (days <= 0 || days > MAX_DAY_NUMBER)
goto err;
get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
}
@ -454,7 +455,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
(weekday - 1);
}
if (days <= 0 || days >= MAX_DAY_NUMBER)
if (days <= 0 || days > MAX_DAY_NUMBER)
goto err;
get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
}
@ -1962,7 +1963,6 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date)
if (date_sub_interval)
interval.neg = !interval.neg;
if (ltime->year < YY_MAGIC_BELOW)
return (null_value=1);
@ -2450,7 +2450,7 @@ String *Item_func_makedate::val_str(String *str)
days= calc_daynr(yearnr,1,1) + daynr - 1;
/* Day number from year 0 to 9999-12-31 */
if (days >= 0 && days < MAX_DAY_NUMBER)
if (days >= 0 && days <= MAX_DAY_NUMBER)
{
null_value=0;
get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);

View File

@ -1015,7 +1015,7 @@ bool select_send::send_data(List<Item> &items)
Protocol *protocol= thd->protocol;
char buff[MAX_FIELD_WIDTH];
String buffer(buff, sizeof(buff), &my_charset_bin);
DBUG_ENTER("send_data");
DBUG_ENTER("select_send::send_data");
protocol->prepare_for_resend();
Item *item;
@ -1228,7 +1228,7 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
bool select_export::send_data(List<Item> &items)
{
DBUG_ENTER("send_data");
DBUG_ENTER("select_export::send_data");
char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
bool space_inited=0;
String tmp(buff,sizeof(buff),&my_charset_bin),*res;
@ -1385,7 +1385,7 @@ bool select_dump::send_data(List<Item> &items)
String tmp(buff,sizeof(buff),&my_charset_bin),*res;
tmp.length(0);
Item *item;
DBUG_ENTER("send_data");
DBUG_ENTER("select_dump::send_data");
if (unit->offset_limit_cnt)
{ // using limit offset,count

View File

@ -17,6 +17,44 @@
/* Insert of records */
/*
INSERT DELAYED
Insert delayed is distinguished from a normal insert by lock_type ==
TL_WRITE_DELAYED instead of TL_WRITE. It first tries to open a
"delayed" table (delayed_get_table()), but falls back to
open_and_lock_tables() on error and proceeds as normal insert then.
Opening a "delayed" table means to find a delayed insert thread that
has the table open already. If this fails, a new thread is created and
waited for to open and lock the table.
If accessing the thread succeeded, in
delayed_insert::get_local_table() the table of the thread is copied
for local use. A copy is required because the normal insert logic
works on a target table, but the other threads table object must not
be used. The insert logic uses the record buffer to create a record.
And the delayed insert thread uses the record buffer to pass the
record to the table handler. So there must be different objects. Also
the copied table is not included in the lock, so that the statement
can proceed even if the real table cannot be accessed at this moment.
Copying a table object is not a trivial operation. Besides the TABLE
object there are the field pointer array, the field objects and the
record buffer. After copying the field objects, their pointers into
the record must be "moved" to point to the new record buffer.
After this setup the normal insert logic is used. Only that for
delayed inserts write_delayed() is called instead of write_record().
It inserts the rows into a queue and signals the delayed insert thread
instead of writing directly to the table.
The delayed insert thread awakes from the signal. It locks the table,
inserts the rows from the queue, unlocks the table, and waits for the
next signal. It does normally live until a FLUSH TABLES or SHUTDOWN.
*/
#include "mysql_priv.h"
#include "sp_head.h"
#include "sql_trigger.h"
@ -1515,6 +1553,7 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
TABLE *copy;
TABLE_SHARE *share= table->s;
byte *bitmap;
DBUG_ENTER("delayed_insert::get_local_table");
/* First request insert thread to get a lock */
status=1;
@ -1538,6 +1577,13 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
}
}
/*
Allocate memory for the TABLE object, the field pointers array, and
one record buffer of reclength size. Normally a table has three
record buffers of rec_buff_length size, which includes alignment
bytes. Since the table copy is used for creating one record only,
the other record buffers and alignment are unnecessary.
*/
client_thd->proc_info="allocating local table";
copy= (TABLE*) client_thd->alloc(sizeof(*copy)+
(share->fields+1)*sizeof(Field**)+
@ -1545,23 +1591,28 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
share->column_bitmap_size*2);
if (!copy)
goto error;
/* Copy the TABLE object. */
*copy= *table;
/* We don't need to change the file handler here */
field= copy->field= (Field**) (copy+1);
bitmap= (byte*) (field+share->fields+1);
copy->record[0]= (bitmap+ share->column_bitmap_size*2);
memcpy((char*) copy->record[0],(char*) table->record[0],share->reclength);
/* Make a copy of all fields */
adjust_ptrs=PTR_BYTE_DIFF(copy->record[0],table->record[0]);
found_next_number_field=table->found_next_number_field;
for (org_field=table->field ; *org_field ; org_field++,field++)
/* Assign the pointers for the field pointers array and the record. */
field= copy->field= (Field**) (copy + 1);
bitmap= (byte*) (field + share->fields + 1);
copy->record[0]= (bitmap + share->column_bitmap_size * 2);
memcpy((char*) copy->record[0], (char*) table->record[0], share->reclength);
/*
Make a copy of all fields.
The copied fields need to point into the copied record. This is done
by copying the field objects with their old pointer values and then
"move" the pointers by the distance between the original and copied
records. That way we preserve the relative positions in the records.
*/
adjust_ptrs= PTR_BYTE_DIFF(copy->record[0], table->record[0]);
found_next_number_field= table->found_next_number_field;
for (org_field= table->field; *org_field; org_field++, field++)
{
if (!(*field= (*org_field)->new_field(client_thd->mem_root,copy)))
return 0;
if (!(*field= (*org_field)->new_field(client_thd->mem_root, copy, 1)))
DBUG_RETURN(0);
(*field)->orig_table= copy; // Remove connection
(*field)->move_field_offset(adjust_ptrs); // Point at copy->record[0]
if (*org_field == found_next_number_field)
@ -1594,14 +1645,14 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
copy->read_set= &copy->def_read_set;
copy->write_set= &copy->def_write_set;
return copy;
DBUG_RETURN(copy);
/* Got fatal error */
error:
tables_in_use--;
status=1;
pthread_cond_signal(&cond); // Inform thread about abort
return 0;
DBUG_RETURN(0);
}

View File

@ -818,6 +818,37 @@ static void reset_mqh(LEX_USER *lu, bool get_them= 0)
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}
void thd_init_client_charset(THD *thd, uint cs_number)
{
/*
Use server character set and collation if
- opt_character_set_client_handshake is not set
- client has not specified a character set
- client character set is the same as the servers
- client character set doesn't exists in server
*/
if (!opt_character_set_client_handshake ||
!(thd->variables.character_set_client= get_charset(cs_number, MYF(0))) ||
!my_strcasecmp(&my_charset_latin1,
global_system_variables.character_set_client->name,
thd->variables.character_set_client->name))
{
thd->variables.character_set_client=
global_system_variables.character_set_client;
thd->variables.collation_connection=
global_system_variables.collation_connection;
thd->variables.character_set_results=
global_system_variables.character_set_results;
}
else
{
thd->variables.character_set_results=
thd->variables.collation_connection=
thd->variables.character_set_client;
}
}
/*
Perform handshake, authorize client and update thd ACL variables.
SYNOPSIS
@ -953,33 +984,7 @@ static int check_connection(THD *thd)
thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
thd->max_client_packet_length= uint4korr(net->read_pos+4);
DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
/*
Use server character set and collation if
- opt_character_set_client_handshake is not set
- client has not specified a character set
- client character set is the same as the servers
- client character set doesn't exists in server
*/
if (!opt_character_set_client_handshake ||
!(thd->variables.character_set_client=
get_charset((uint) net->read_pos[8], MYF(0))) ||
!my_strcasecmp(&my_charset_latin1,
global_system_variables.character_set_client->name,
thd->variables.character_set_client->name))
{
thd->variables.character_set_client=
global_system_variables.character_set_client;
thd->variables.collation_connection=
global_system_variables.collation_connection;
thd->variables.character_set_results=
global_system_variables.character_set_results;
}
else
{
thd->variables.character_set_results=
thd->variables.collation_connection=
thd->variables.character_set_client;
}
thd_init_client_charset(thd, (uint) net->read_pos[8]);
thd->update_charset();
end= (char*) net->read_pos+32;
}
@ -3112,6 +3117,12 @@ end_with_restore_list:
}
}
/* Don't yet allow changing of symlinks with ALTER TABLE */
if (lex->create_info.data_file_name)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
"DATA DIRECTORY option ignored");
if (lex->create_info.index_file_name)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
"INDEX DIRECTORY option ignored");
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
/* ALTER TABLE ends previous transaction */
if (end_active_trans(thd))

View File

@ -8058,7 +8058,8 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field,
org_field->field_name, table->s,
org_field->charset());
else
new_field= org_field->new_field(thd->mem_root, table);
new_field= org_field->new_field(thd->mem_root, table,
table == org_field->table);
if (new_field)
{
new_field->init(table);
@ -13166,7 +13167,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
saved value
*/
Field *field= item->field;
item->result_field=field->new_field(thd->mem_root,field->table);
item->result_field=field->new_field(thd->mem_root,field->table, 1);
char *tmp=(char*) sql_alloc(field->pack_length()+1);
if (!tmp)
goto err;

View File

@ -733,7 +733,8 @@ bool Table_triggers_list::prepare_record1_accessors(TABLE *table)
QQ: it is supposed that it is ok to use this function for field
cloning...
*/
if (!(*old_fld= (*fld)->new_field(&table->mem_root, table)))
if (!(*old_fld= (*fld)->new_field(&table->mem_root, table,
table == (*fld)->table)))
return 1;
(*old_fld)->move_field_offset((my_ptrdiff_t)(table->record[1] -
table->record[0]));

View File

@ -1456,7 +1456,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
Create a new field for the key part that matches the index
*/
field= key_part->field=field->new_field(&outparam->mem_root,
outparam);
outparam, 0);
field->field_length= key_part->length;
}
}

View File

@ -749,6 +749,7 @@ void make_truncated_value_warning(THD *thd, const char *str_val,
ER_TRUNCATED_WRONG_VALUE, warn_buff);
}
/* Daynumber from year 0 to 9999-12-31 */
#define MAX_DAY_NUMBER 3652424L
bool date_add_interval(TIME *ltime, interval_type int_type, INTERVAL interval)
@ -804,7 +805,7 @@ bool date_add_interval(TIME *ltime, interval_type int_type, INTERVAL interval)
ltime->hour= (uint) (sec/3600);
daynr= calc_daynr(ltime->year,ltime->month,1) + days;
/* Day number from year 0 to 9999-12-31 */
if ((ulonglong) daynr >= MAX_DAY_NUMBER)
if ((ulonglong) daynr > MAX_DAY_NUMBER)
goto invalid_date;
get_date_from_daynr((long) daynr, &ltime->year, &ltime->month,
&ltime->day);
@ -815,7 +816,7 @@ bool date_add_interval(TIME *ltime, interval_type int_type, INTERVAL interval)
period= (calc_daynr(ltime->year,ltime->month,ltime->day) +
sign * (long) interval.day);
/* Daynumber from year 0 to 9999-12-31 */
if ((ulong) period >= MAX_DAY_NUMBER)
if ((ulong) period > MAX_DAY_NUMBER)
goto invalid_date;
get_date_from_daynr((long) period,&ltime->year,&ltime->month,&ltime->day);
break;

View File

@ -1158,13 +1158,14 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
#ifdef HAVE_RTREE_KEYS
(keyinfo->flag & HA_SPATIAL) ?
rtree_find_first(info, key, info->lastkey, key_length,
SEARCH_SAME) :
MBR_EQUAL | MBR_DATA) :
#endif
_mi_search(info,keyinfo,info->lastkey,key_length,
SEARCH_SAME, info->s->state.key_root[key]);
if (search_result)
{
mi_check_print_error(param,"Record at: %10s Can't find key for index: %2d",
mi_check_print_error(param,"Record at: %10s "
"Can't find key for index: %2d",
llstr(start_recpos,llbuff),key+1);
if (error++ > MAXERR || !(param->testflag & T_VERBOSE))
goto err2;

View File

@ -60,6 +60,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
my_off_t key_root[MI_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
MI_CREATE_INFO tmp_create_info;
DBUG_ENTER("mi_create");
DBUG_PRINT("enter", ("keys: %u columns: %u uniques: %u flags: %u",
keys, columns, uniques, flags));
if (!ci)
{
@ -482,6 +484,16 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
uniques * MI_UNIQUEDEF_SIZE +
(key_segs + unique_key_parts)*HA_KEYSEG_SIZE+
columns*MI_COLUMNDEF_SIZE);
DBUG_PRINT("info", ("info_length: %u", info_length));
/* There are only 16 bits for the total header length. */
if (info_length > 65535)
{
my_printf_error(0, "MyISAM table '%s' has too many columns and/or "
"indexes and/or unique constraints.",
MYF(0), name + dirname_length(name));
my_errno= HA_WRONG_CREATE_OPTION;
goto err;
}
bmove(share.state.header.file_version,(byte*) myisam_file_magic,4);
ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
@ -650,6 +662,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
errpos=3;
}
DBUG_PRINT("info", ("write state info and base info"));
if (mi_state_info_write(file, &share.state, 2) ||
mi_base_info_write(file, &share.base))
goto err;
@ -663,6 +676,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
#endif
/* Write key and keyseg definitions */
DBUG_PRINT("info", ("write key and keyseg definitions"));
for (i=0 ; i < share.base.keys - uniques; i++)
{
uint sp_segs=(keydefs[i].flag & HA_SPATIAL) ? 2*SPDIMS : 0;
@ -713,6 +727,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
}
/* Save unique definition */
DBUG_PRINT("info", ("write unique definitions"));
for (i=0 ; i < share.state.header.uniques ; i++)
{
HA_KEYSEG *keyseg_end;
@ -743,6 +758,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
goto err;
}
}
DBUG_PRINT("info", ("write field definitions"));
for (i=0 ; i < share.base.fields ; i++)
if (mi_recinfo_write(file, &recinfo[i]))
goto err;
@ -757,6 +773,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
#endif
/* Enlarge files */
DBUG_PRINT("info", ("enlarge to keystart: %lu", (ulong) share.base.keystart));
if (my_chsize(file,(ulong) share.base.keystart,0,MYF(0)))
goto err;

View File

@ -34,12 +34,24 @@ int mi_delete_table(const char *name)
#ifdef USE_RAID
{
MI_INFO *info;
/* we use 'open_for_repair' to be able to delete a crashed table */
if (!(info=mi_open(name, O_RDONLY, HA_OPEN_FOR_REPAIR)))
DBUG_RETURN(my_errno);
raid_type = info->s->base.raid_type;
raid_chunks = info->s->base.raid_chunks;
mi_close(info);
/*
When built with RAID support, we need to determine if this table
makes use of the raid feature. If yes, we need to remove all raid
chunks. This is done with my_raid_delete(). Unfortunately it is
necessary to open the table just to check this. We use
'open_for_repair' to be able to open even a crashed table. If even
this open fails, we assume no raid configuration for this table
and try to remove the normal data file only. This may however
leave the raid chunks behind.
*/
if (!(info= mi_open(name, O_RDONLY, HA_OPEN_FOR_REPAIR)))
raid_type= 0;
else
{
raid_type= info->s->base.raid_type;
raid_chunks= info->s->base.raid_chunks;
mi_close(info);
}
}
#ifdef EXTRA_DEBUG
check_table_is_closed(name,"delete");

View File

@ -1329,6 +1329,9 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf)
info->rec_cache.pos_in_file <= block_info.next_filepos &&
flush_io_cache(&info->rec_cache))
goto err;
/* A corrupted table can have wrong pointers. (Bug# 19835) */
if (block_info.next_filepos == HA_OFFSET_ERROR)
goto panic;
info->rec_cache.seek_not_done=1;
if ((b_type=_mi_get_block_info(&block_info,file,
block_info.next_filepos))

View File

@ -68,6 +68,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
if (fast_mi_readinfo(info))
goto err;
if (share->concurrent_insert)
rw_rdlock(&share->key_root_lock[inx]);
@ -90,24 +91,35 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
case HA_KEY_ALG_BTREE:
default:
if (!_mi_search(info, keyinfo, key_buff, use_key_length,
myisam_read_vec[search_flag], info->s->state.key_root[inx]))
myisam_read_vec[search_flag], info->s->state.key_root[inx]))
{
while (info->lastpos >= info->state->data_file_length)
/*
If we are searching for an exact key (including the data pointer)
and this was added by an concurrent insert,
then the result is "key not found".
*/
if ((search_flag == HA_READ_KEY_EXACT) &&
(info->lastpos >= info->state->data_file_length))
{
my_errno= HA_ERR_KEY_NOT_FOUND;
info->lastpos= HA_OFFSET_ERROR;
}
else while (info->lastpos >= info->state->data_file_length)
{
/*
Skip rows that are inserted by other threads since we got a lock
Note that this can only happen if we are not searching after an
exact key, because the keys are sorted according to position
*/
if (_mi_search_next(info, keyinfo, info->lastkey,
info->lastkey_length,
myisam_readnext_vec[search_flag],
info->s->state.key_root[inx]))
info->lastkey_length,
myisam_readnext_vec[search_flag],
info->s->state.key_root[inx]))
break;
}
}
}
if (share->concurrent_insert)
rw_unlock(&share->key_root_lock[inx]);

View File

@ -183,9 +183,11 @@ int rtree_find_first(MI_INFO *info, uint keynr, uchar *key, uint key_length,
return -1;
}
/* Save searched key */
memcpy(info->first_mbr_key, key, keyinfo->keylength -
info->s->base.rec_reflength);
/*
Save searched key, include data pointer.
The data pointer is required if the search_flag contains MBR_DATA.
*/
memcpy(info->first_mbr_key, key, keyinfo->keylength);
info->last_rkey_length = key_length;
info->rtree_recursion_depth = -1;

View File

@ -52,10 +52,14 @@
if (EQUAL_CMP(amin, amax, bmin, bmax)) \
return 1; \
} \
else /* if (nextflag & MBR_DISJOINT) */ \
else if (nextflag & MBR_DISJOINT) \
{ \
if (DISJOINT_CMP(amin, amax, bmin, bmax)) \
return 1; \
}\
else /* if unknown comparison operator */ \
{ \
DBUG_ASSERT(0); \
}
#define RT_CMP_KORR(type, korr_func, len, nextflag) \