summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BitKeeper/etc/logging_ok2
-rw-r--r--include/my_sys.h2
-rw-r--r--innobase/dict/dict0dict.c331
-rw-r--r--innobase/row/row0mysql.c26
-rw-r--r--mysql-test/r/bigint.result3
-rw-r--r--mysql-test/r/ctype_tis620.result17
-rw-r--r--mysql-test/r/innodb.result4
-rw-r--r--mysql-test/r/rpl_insert_id.result2
-rw-r--r--mysql-test/r/timezone.result6
-rw-r--r--mysql-test/r/type_timestamp.result47
-rw-r--r--mysql-test/t/bigint.test2
-rw-r--r--mysql-test/t/ctype_tis620-master.opt1
-rw-r--r--mysql-test/t/ctype_tis620.test18
-rw-r--r--mysql-test/t/innodb.test4
-rw-r--r--mysql-test/t/rpl_insert_id.test2
-rw-r--r--mysql-test/t/timezone.test7
-rw-r--r--mysql-test/t/type_timestamp.test33
-rw-r--r--mysys/my_alloc.c66
-rw-r--r--mysys/my_getopt.c8
-rw-r--r--sql/field.cc17
-rw-r--r--sql/field.h5
-rw-r--r--sql/ha_innodb.cc11
-rw-r--r--sql/mysql_priv.h5
-rw-r--r--sql/mysqld.cc36
-rw-r--r--sql/set_var.cc32
-rw-r--r--sql/sql_parse.cc12
-rw-r--r--sql/sql_show.cc14
-rw-r--r--sql/sql_table.cc10
-rw-r--r--sql/time.cc19
-rw-r--r--sql/unireg.cc2
-rw-r--r--strings/ctype-tis620.c177
-rw-r--r--support-files/mysql.server.sh8
32 files changed, 650 insertions, 279 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 5cf95b9fc2a..e6bfe0ceb36 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -43,6 +43,7 @@ jani@janikt.pp.saunalahti.fi
jani@rhols221.adsl.netsonic.fi
jani@rhols221.arenanet.fi
jani@ua126d19.elisa.omakaista.fi
+jani@ua141d10.elisa.omakaista.fi
jcole@abel.spaceapes.com
jcole@main.burghcom.com
jcole@mugatu.spaceapes.com
@@ -98,6 +99,7 @@ ranger@regul.home.lan
root@x3.internalnet
salle@geopard.(none)
salle@geopard.online.bg
+salle@vafla.home
salle@vafla.online.bg
sasha@mysql.sashanet.com
serg@build.mysql2.com
diff --git a/include/my_sys.h b/include/my_sys.h
index e1656cfc626..75e22629a19 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -740,6 +740,8 @@ extern void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
extern gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size);
extern void free_root(MEM_ROOT *root, myf MyFLAGS);
extern void set_prealloc_root(MEM_ROOT *root, char *ptr);
+extern void reset_root_defaults(MEM_ROOT *mem_root, uint block_size,
+ uint prealloc_size);
extern char *strdup_root(MEM_ROOT *root,const char *str);
extern char *strmake_root(MEM_ROOT *root,const char *str,uint len);
extern char *memdup_root(MEM_ROOT *root,const char *str,uint len);
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index dc7acfcba36..87505656d5a 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -52,7 +52,7 @@ rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve
hash table fixed size in bytes */
#define DICT_POOL_PER_VARYING 4 /* buffer pool max size per data
dictionary varying size in bytes */
-
+
/**************************************************************************
Adds a column to the data dictionary hash table. */
static
@@ -2109,6 +2109,68 @@ dict_accept(
}
/*************************************************************************
+Scans an id. For the lexical definition of an 'id', see the code below.
+Strips backquotes or double quotes from around the id. */
+static
+char*
+dict_scan_id(
+/*=========*/
+ /* out: scanned to */
+ char* ptr, /* in: scanned to */
+ char** start, /* out: start of the id; NULL if no id was
+ scannable */
+ ulint* len, /* out: length of the id */
+ ibool accept_also_dot)/* in: TRUE if also a dot can appear in a
+ non-quoted id; in a quoted id it can appear
+ always */
+{
+ char quote = '\0';
+
+ *start = NULL;
+
+ while (isspace(*ptr)) {
+ ptr++;
+ }
+
+ if (*ptr == '\0') {
+
+ return(ptr);
+ }
+
+ if (*ptr == '`' || *ptr == '"') {
+ quote = *ptr++;
+ }
+
+ *start = ptr;
+
+ if (quote) {
+ while (*ptr != quote && *ptr != '\0') {
+ ptr++;
+ }
+ } else {
+ while (!isspace(*ptr) && *ptr != '(' && *ptr != ')'
+ && (accept_also_dot || *ptr != '.')
+ && *ptr != ',' && *ptr != '\0') {
+
+ ptr++;
+ }
+ }
+
+ *len = (ulint) (ptr - *start);
+
+ if (quote) {
+ if (*ptr == quote) {
+ ptr++;
+ } else {
+ /* Syntax error */
+ *start = NULL;
+ }
+ }
+
+ return(ptr);
+}
+
+/*************************************************************************
Tries to scan a column name. */
static
char*
@@ -2124,64 +2186,29 @@ dict_scan_col(
ulint* column_name_len)/* out: column name length */
{
dict_col_t* col;
- char* old_ptr;
ulint i;
*success = FALSE;
- while (isspace(*ptr)) {
- ptr++;
- }
+ ptr = dict_scan_id(ptr, column_name, column_name_len, TRUE);
- if (*ptr == '\0') {
+ if (column_name == NULL) {
- return(ptr);
- }
-
- if (*ptr == '`' || *ptr == '"') {
- /*
- The identifier is quoted. Search for end quote.
- We can't use the general code here as the name may contain
- special characters like space.
- */
- char quote= *ptr++;
-
- old_ptr= ptr;
- /*
- The colum name should always end with 'quote' but we check for
- end zero just to be safe if this is called outside of MySQL
- */
- while (*ptr && *ptr != quote)
- ptr++;
- *column_name_len = (ulint)(ptr - old_ptr);
-
- if (*ptr) /* Skip end quote */
- ptr++;
- }
- else
- {
- old_ptr = ptr;
-
- while (!isspace(*ptr) && *ptr != ',' && *ptr != ')'
- && *ptr != '\0') {
- ptr++;
- }
- *column_name_len = (ulint)(ptr - old_ptr);
+ return(ptr); /* Syntax error */
}
-
if (table == NULL) {
*success = TRUE;
*column = NULL;
- *column_name = old_ptr;
} else {
for (i = 0; i < dict_table_get_n_cols(table); i++) {
col = dict_table_get_nth_col(table, i);
if (ut_strlen(col->name) == *column_name_len
- && 0 == ut_cmp_in_lower_case(col->name, old_ptr,
- *column_name_len)) {
+ && 0 == ut_cmp_in_lower_case(col->name,
+ *column_name,
+ *column_name_len)) {
/* Found */
*success = TRUE;
@@ -2211,147 +2238,117 @@ dict_scan_table_name(
the referenced table name; must be at least
2500 bytes */
{
- char* dot_ptr = NULL;
- char* old_ptr;
+ char* database_name = NULL;
+ ulint database_name_len = 999999999; /* init to a dummy value to
+ suppress a compiler warning */
+ char* table_name = NULL;
+ ulint table_name_len;
+ char* scanned_id;
+ ulint scanned_id_len;
ulint i;
- char quote = 0;
*success = FALSE;
*table = NULL;
+
+ ptr = dict_scan_id(ptr, &scanned_id, &scanned_id_len, FALSE);
- while (isspace(*ptr)) {
- ptr++;
+ if (scanned_id == NULL) {
+
+ return(ptr); /* Syntax error */
}
- if (*ptr == '\0') {
+ if (*ptr == '.') {
+ /* We scanned the database name; scan also the table name */
- return(ptr);
- }
+ ptr++;
- if (*ptr == '`' || *ptr == '"') {
- quote= *ptr++;
- }
+ database_name = scanned_id;
+ database_name_len = scanned_id_len;
- old_ptr = ptr;
-
- while (*ptr != quote &&
- (quote || (!isspace(*ptr) && *ptr != '(')) &&
- *ptr != '\0') {
- if (!quote && *ptr == '.') {
- dot_ptr = ptr;
- }
+ ptr = dict_scan_id(ptr, &table_name, &table_name_len, FALSE);
- ptr++;
- }
+ if (table_name == NULL) {
- if (ptr - old_ptr > 2000) {
- return(old_ptr);
- }
-
- if (dot_ptr == NULL) {
- /* Copy the database name from 'name' to the start */
- for (i = 0;; i++) {
- second_table_name[i] = name[i];
- if (name[i] == '/') {
- i++;
- break;
- }
- }
-#ifdef __WIN__
- ut_cpy_in_lower_case(second_table_name + i, old_ptr,
- ptr - old_ptr);
-#else
- if (srv_lower_case_table_names) {
- ut_cpy_in_lower_case(second_table_name + i, old_ptr,
- ptr - old_ptr);
- } else {
- ut_memcpy(second_table_name + i, old_ptr,
- ptr - old_ptr);
+ return(ptr); /* Syntax error */
}
-#endif
- second_table_name[i + (ptr - old_ptr)] = '\0';
} else {
-#ifdef __WIN__
- ut_cpy_in_lower_case(second_table_name, old_ptr,
- ptr - old_ptr);
-#else
- if (srv_lower_case_table_names) {
- ut_cpy_in_lower_case(second_table_name, old_ptr,
- ptr - old_ptr);
- } else {
- ut_memcpy(second_table_name, old_ptr, ptr - old_ptr);
+ /* To be able to read table dumps made with InnoDB-4.0.17 or
+ earlier, we must allow the dot separator between the database
+ name and the table name also to appear within a quoted
+ identifier! InnoDB used to print a constraint as:
+ ... REFERENCES `databasename.tablename` ...
+ starting from 4.0.18 it is
+ ... REFERENCES `databasename`.`tablename` ... */
+
+ for (i = 0; i < scanned_id_len; i++) {
+ if (scanned_id[i] == '.') {
+ database_name = scanned_id;
+ database_name_len = i;
+
+ scanned_id = scanned_id + i + 1;
+ scanned_id_len -= i + 1;
+ }
}
-#endif
- second_table_name[dot_ptr - old_ptr] = '/';
- second_table_name[ptr - old_ptr] = '\0';
- }
- *success = TRUE;
-
- *table = dict_table_get_low(second_table_name);
-
- if (*ptr && *ptr == quote) {
- ptr++;
+ table_name = scanned_id;
+ table_name_len = scanned_id_len;
}
- return(ptr);
-}
+ if (database_name == NULL) {
+ /* Use the database name of the foreign key table */
-/*************************************************************************
-Scans an id. For the lexical definition of an 'id', see the code below.
-Strips backquotes from around the id. */
-static
-char*
-dict_scan_id(
-/*=========*/
- /* out: scanned to */
- char* ptr, /* in: scanned to */
- char** start, /* out: start of the id; NULL if no id was
- scannable */
- ulint* len) /* out: length of the id */
-{
- char quote = 0;
-
- *start = NULL;
+ database_name = name;
+
+ i = 0;
+ while (name[i] != '/') {
+ i++;
+ }
- while (isspace(*ptr)) {
- ptr++;
+ database_name_len = i;
}
- if (*ptr == '\0') {
+ if (table_name_len + database_name_len > 2000) {
- return(ptr);
- }
-
- if (*ptr == '`' || *ptr == '"') {
- quote = *ptr++;
+ return(ptr); /* Too long name */
}
- *start = ptr;
-
- while (*ptr != quote &&
- (!quote || (!isspace(*ptr) && *ptr != ',' && *ptr != '(' &&
- *ptr != ')'))
- && *ptr != '\0') {
- ptr++;
+#ifdef __WIN__
+ ut_cpy_in_lower_case(second_table_name, database_name,
+ database_name_len);
+#else
+ if (srv_lower_case_table_names) {
+ ut_cpy_in_lower_case(second_table_name, database_name,
+ database_name_len);
+ } else {
+ ut_memcpy(second_table_name, database_name,
+ database_name_len);
}
+#endif
+ second_table_name[database_name_len] = '/';
- *len = (ulint) (ptr - *start);
-
- if (quote) {
- if (*ptr == quote) {
- ptr++;
- } else {
- /* Syntax error */
- *start = NULL;
- }
+#ifdef __WIN__
+ ut_cpy_in_lower_case(second_table_name + database_name_len + 1,
+ table_name, table_name_len);
+#else
+ if (srv_lower_case_table_names) {
+ ut_cpy_in_lower_case(second_table_name + database_name_len + 1,
+ table_name, table_name_len);
+ } else {
+ ut_memcpy(second_table_name + database_name_len + 1,
+ table_name, table_name_len);
}
+#endif
+ second_table_name[database_name_len + 1 + table_name_len] = '\0';
+
+ *success = TRUE;
+
+ *table = dict_table_get_low(second_table_name);
return(ptr);
}
/*************************************************************************
-Skips one id. */
+Skips one id. The id is allowed to contain also '.'. */
static
char*
dict_skip_word(
@@ -2366,7 +2363,7 @@ dict_skip_word(
*success = FALSE;
- ptr = dict_scan_id(ptr, &start, &len);
+ ptr = dict_scan_id(ptr, &start, &len, TRUE);
if (start) {
*success = TRUE;
@@ -3064,7 +3061,7 @@ loop:
goto syntax_error;
}
- ptr = dict_scan_id(ptr, &start, &len);
+ ptr = dict_scan_id(ptr, &start, &len, TRUE);
if (start == NULL) {
@@ -3899,6 +3896,7 @@ dict_print_info_on_foreign_key_in_create_format(
char* buf) /* in: buffer of at least 5000 bytes */
{
char* buf2 = buf;
+ ulint cpy_len;
ulint i;
buf2 += sprintf(buf2, ",\n CONSTRAINT `%s` FOREIGN KEY (",
@@ -3918,24 +3916,31 @@ dict_print_info_on_foreign_key_in_create_format(
if (dict_tables_have_same_db(foreign->foreign_table_name,
foreign->referenced_table_name)) {
- /* Do not print the database name of the referenced
- table */
+ /* Do not print the database name of the referenced table */
buf2 += sprintf(buf2, ") REFERENCES `%.500s` (",
dict_remove_db_name(
foreign->referenced_table_name));
} else {
- buf2 += sprintf(buf2, ") REFERENCES `%.500s` (",
- foreign->referenced_table_name);
- /* Change the '/' in the table name to '.' */
-
- for (i = ut_strlen(buf); i > 0; i--) {
- if (buf[i] == '/') {
+ buf2 += sprintf(buf2, ") REFERENCES `");
+
+ /* Look for the '/' in the table name */
- buf[i] = '.';
+ i = 0;
+ while (foreign->referenced_table_name[i] != '/') {
+ i++;
+ }
+
+ cpy_len = i;
- break;
- }
+ if (cpy_len > 500) {
+ cpy_len = 500;
}
+
+ memcpy(buf2, foreign->referenced_table_name, cpy_len);
+ buf2 += cpy_len;
+
+ buf2 += sprintf(buf2, "`.`%.500s` (",
+ foreign->referenced_table_name + i + 1);
}
for (i = 0; i < foreign->n_fields; i++) {
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 468404268f4..257756ff8aa 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -1804,6 +1804,7 @@ row_drop_table_for_mysql(
char* name, /* in: table name */
trx_t* trx) /* in: transaction handle */
{
+ dict_foreign_t* foreign;
dict_table_t* table;
que_thr_t* thr;
que_t* graph;
@@ -1996,6 +1997,31 @@ row_drop_table_for_mysql(
goto funct_exit;
}
+ foreign = UT_LIST_GET_FIRST(table->referenced_list);
+
+ if (foreign && trx->check_foreigns) {
+ char* buf = dict_foreign_err_buf;
+
+ /* We only allow dropping a referenced table if
+ FOREIGN_KEY_CHECKS is set to 0 */
+
+ err = DB_CANNOT_DROP_CONSTRAINT;
+
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+
+ sprintf(buf + strlen(buf),
+ " Cannot drop table %.500s\n", name);
+ sprintf(buf + strlen(buf),
+"because it is referenced by %.500s\n", foreign->foreign_table_name);
+
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+
+ mutex_exit(&dict_foreign_err_mutex);
+
+ goto funct_exit;
+ }
+
if (table->n_mysql_handles_opened > 0) {
ut_print_timestamp(stderr);
diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result
index 308adc881f2..f96da579bce 100644
--- a/mysql-test/r/bigint.result
+++ b/mysql-test/r/bigint.result
@@ -81,3 +81,6 @@ quantity
10000000000000000000
10000000000000000000
drop table t1;
+SELECT '0x8000000000000001'+0;
+'0x8000000000000001'+0
+0
diff --git a/mysql-test/r/ctype_tis620.result b/mysql-test/r/ctype_tis620.result
new file mode 100644
index 00000000000..d939fd12e60
--- /dev/null
+++ b/mysql-test/r/ctype_tis620.result
@@ -0,0 +1,17 @@
+DROP TABLE IF EXISTS t620;
+CREATE TABLE t620 (
+recid int(11) NOT NULL auto_increment,
+dyninfo text,
+PRIMARY KEY (recid)
+) TYPE=MyISAM;
+INSERT INTO t620 VALUES (1,'color=\"STB,NPG\"\r\nengine=\"J30A13\"\r\nframe=\"MRHCG1640YP4\"\r\ngrade=\"V6\"\r\nmodel=\"ACCORD\"\r\nmodelcode=\"CG164YEN\"\r\ntype=\"VT6\"\r\n');
+INSERT INTO t620 VALUES (2,'color=\"HTM,NPG,DEG,RGS\"\r\nengine=\"F23A5YP1\"\r\nframe=\"MRHCF8640YP3\"\r\ngrade=\"EXi AT\"\r\nmodel=\"ACCORD\"\r\nmodelcode=\"CF864YE\"\r\ntype=\"EXA\"\r\n');
+SELECT DISTINCT
+(IF( LOCATE( 'year=\"', dyninfo ) = 1,
+SUBSTRING( dyninfo, 6+1, LOCATE('\"\r',dyninfo) - 6 -1),
+IF( LOCATE( '\nyear=\"', dyninfo ),
+SUBSTRING( dyninfo, LOCATE( '\nyear=\"', dyninfo ) + 7,
+LOCATE( '\"\r', SUBSTRING( dyninfo, LOCATE( '\nyear=\"', dyninfo ) +7 )) - 1), '' ))) AS year
+FROM t620
+HAVING year != '' ORDER BY year;
+year
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index ca4a49fea4e..416c583a8d7 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -1004,7 +1004,7 @@ select * from t1;
id
select * from t2;
id t1_id
-drop table t1,t2;
+drop table t2,t1;
DROP TABLE IF EXISTS t1,t2;
CREATE TABLE t1(id INT NOT NULL, PRIMARY KEY (id)) TYPE=INNODB;
CREATE TABLE t2(id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id) ) TYPE=INNODB;
@@ -1245,4 +1245,4 @@ a
drop table t1;
CREATE TABLE t1 (`id 1` INT NOT NULL, PRIMARY KEY (`id 1`)) TYPE=INNODB;
CREATE TABLE t2 (id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id), FOREIGN KEY (`t1_id`) REFERENCES `t1`(`id 1`) ON DELETE CASCADE ) TYPE=INNODB;
-drop table t1,t2;
+drop table t2,t1;
diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result
index 889e7891770..d2dfbb05675 100644
--- a/mysql-test/r/rpl_insert_id.result
+++ b/mysql-test/r/rpl_insert_id.result
@@ -39,8 +39,8 @@ select * from t2;
b c
5 0
6 11
-drop table t1;
drop table t2;
+drop table t1;
create table t1(a int auto_increment, key(a));
create table t2(b int auto_increment, c int, key(b));
insert into t1 values (10);
diff --git a/mysql-test/r/timezone.result b/mysql-test/r/timezone.result
index 20706408075..15f0d4121c7 100644
--- a/mysql-test/r/timezone.result
+++ b/mysql-test/r/timezone.result
@@ -32,3 +32,9 @@ ts from_unixtime(ts)
1048989599 2003-03-30 03:59:59
1048989601 2003-03-30 04:00:01
DROP TABLE t1;
+select unix_timestamp('1970-01-01 01:00:00'),
+unix_timestamp('1970-01-01 01:00:01'),
+unix_timestamp('2038-01-01 00:59:59'),
+unix_timestamp('2038-01-01 01:00:00');
+unix_timestamp('1970-01-01 01:00:00') unix_timestamp('1970-01-01 01:00:01') unix_timestamp('2038-01-01 00:59:59') unix_timestamp('2038-01-01 01:00:00')
+0 1 2145916799 0
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index b513f958787..cd45bcf911d 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -122,5 +122,48 @@ t2 t4 t6 t8 t10 t12 t14
0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00
1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59
drop table t1;
-create table t1 (a timestamp default 1);
-Invalid default value for 'a'
+create table t1 (t1 timestamp default '2003-01-01 00:00:00',
+t2 timestamp default '2003-01-01 00:00:00');
+set TIMESTAMP=1000000000;
+insert into t1 values();
+select * from t1;
+t1 t2
+2001-09-09 04:46:40 2003-01-01 00:00:00
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `t1` timestamp(14) NOT NULL,
+ `t2` timestamp(14) NOT NULL default '2003-01-01 00:00:00'
+) TYPE=MyISAM
+show columns from t1;
+Field Type Null Key Default Extra
+t1 timestamp(14) YES NULL
+t2 timestamp(14) YES 2003-01-01 00:00:00
+show columns from t1 like 't2';
+Field Type Null Key Default Extra
+t2 timestamp(14) YES 2003-01-01 00:00:00
+create table t2 (select * from t1);
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `t1` timestamp(14) NOT NULL,
+ `t2` timestamp(14) NOT NULL default '2003-01-01 00:00:00'
+) TYPE=MyISAM
+alter table t1 add column t0 timestamp first;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `t0` timestamp(14) NOT NULL,
+ `t1` timestamp(14) NOT NULL default '2003-01-01 00:00:00',
+ `t2` timestamp(14) NOT NULL default '2003-01-01 00:00:00'
+) TYPE=MyISAM
+drop table t1,t2;
+create table t1 (ts1 timestamp, ts2 timestamp);
+set TIMESTAMP=1000000000;
+insert into t1 values ();
+insert into t1 values (DEFAULT, DEFAULT);
+select * from t1;
+ts1 ts2
+2001-09-09 04:46:40 0000-00-00 00:00:00
+2001-09-09 04:46:40 0000-00-00 00:00:00
+drop table t1;
diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test
index f21f821e45c..0092317dc5e 100644
--- a/mysql-test/t/bigint.test
+++ b/mysql-test/t/bigint.test
@@ -60,3 +60,5 @@ insert into t1 values ('10000000000000000000');
select * from t1;
drop table t1;
+SELECT '0x8000000000000001'+0;
+
diff --git a/mysql-test/t/ctype_tis620-master.opt b/mysql-test/t/ctype_tis620-master.opt
new file mode 100644
index 00000000000..69d47c06e42
--- /dev/null
+++ b/mysql-test/t/ctype_tis620-master.opt
@@ -0,0 +1 @@
+--default-character-set=tis620
diff --git a/mysql-test/t/ctype_tis620.test b/mysql-test/t/ctype_tis620.test
new file mode 100644
index 00000000000..7a0555515e1
--- /dev/null
+++ b/mysql-test/t/ctype_tis620.test
@@ -0,0 +1,18 @@
+DROP TABLE IF EXISTS t620;
+CREATE TABLE t620 (
+ recid int(11) NOT NULL auto_increment,
+ dyninfo text,
+ PRIMARY KEY (recid)
+) TYPE=MyISAM;
+
+INSERT INTO t620 VALUES (1,'color=\"STB,NPG\"\r\nengine=\"J30A13\"\r\nframe=\"MRHCG1640YP4\"\r\ngrade=\"V6\"\r\nmodel=\"ACCORD\"\r\nmodelcode=\"CG164YEN\"\r\ntype=\"VT6\"\r\n');
+INSERT INTO t620 VALUES (2,'color=\"HTM,NPG,DEG,RGS\"\r\nengine=\"F23A5YP1\"\r\nframe=\"MRHCF8640YP3\"\r\ngrade=\"EXi AT\"\r\nmodel=\"ACCORD\"\r\nmodelcode=\"CF864YE\"\r\ntype=\"EXA\"\r\n');
+
+SELECT DISTINCT
+ (IF( LOCATE( 'year=\"', dyninfo ) = 1,
+ SUBSTRING( dyninfo, 6+1, LOCATE('\"\r',dyninfo) - 6 -1),
+ IF( LOCATE( '\nyear=\"', dyninfo ),
+ SUBSTRING( dyninfo, LOCATE( '\nyear=\"', dyninfo ) + 7,
+ LOCATE( '\"\r', SUBSTRING( dyninfo, LOCATE( '\nyear=\"', dyninfo ) +7 )) - 1), '' ))) AS year
+FROM t620
+HAVING year != '' ORDER BY year;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 51fadccdc1c..ec9aa83ae16 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -692,7 +692,7 @@ insert into t2 set id=1, t1_id=1;
delete t1,t2 from t1,t2 where t1.id=t2.t1_id;
select * from t1;
select * from t2;
-drop table t1,t2;
+drop table t2,t1;
DROP TABLE IF EXISTS t1,t2;
CREATE TABLE t1(id INT NOT NULL, PRIMARY KEY (id)) TYPE=INNODB;
CREATE TABLE t2(id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id) ) TYPE=INNODB;
@@ -877,4 +877,4 @@ drop table t1;
CREATE TABLE t1 (`id 1` INT NOT NULL, PRIMARY KEY (`id 1`)) TYPE=INNODB;
CREATE TABLE t2 (id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id), FOREIGN KEY (`t1_id`) REFERENCES `t1`(`id 1`) ON DELETE CASCADE ) TYPE=INNODB;
#show create table t2;
-drop table t1,t2;
+drop table t2,t1;
diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test
index 49fefae72b8..a6da44de456 100644
--- a/mysql-test/t/rpl_insert_id.test
+++ b/mysql-test/t/rpl_insert_id.test
@@ -42,8 +42,8 @@ connection master;
# check if INSERT SELECT in auto_increment is well replicated (bug #490)
-drop table t1;
drop table t2;
+drop table t1;
create table t1(a int auto_increment, key(a));
create table t2(b int auto_increment, c int, key(b));
insert into t1 values (10);
diff --git a/mysql-test/t/timezone.test b/mysql-test/t/timezone.test
index ab732c11a34..ba65eb72fe6 100644
--- a/mysql-test/t/timezone.test
+++ b/mysql-test/t/timezone.test
@@ -38,3 +38,10 @@ INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01'));
SELECT ts,from_unixtime(ts) FROM t1;
DROP TABLE t1;
+#
+# Test for fix for Bug#2523
+#
+select unix_timestamp('1970-01-01 01:00:00'),
+ unix_timestamp('1970-01-01 01:00:01'),
+ unix_timestamp('2038-01-01 00:59:59'),
+ unix_timestamp('2038-01-01 01:00:00');
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index 17f7b7c487f..3483227376e 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -73,8 +73,35 @@ select * from t1;
drop table t1;
#
-# Bug #1885
+# Bug #1885, bug #2539.
+# Not perfect but still sensible attitude towards defaults for TIMESTAMP
+# We will ignore default value for first TIMESTAMP column.
#
+create table t1 (t1 timestamp default '2003-01-01 00:00:00',
+ t2 timestamp default '2003-01-01 00:00:00');
+set TIMESTAMP=1000000000;
+insert into t1 values();
+select * from t1;
+show create table t1;
+show columns from t1;
+show columns from t1 like 't2';
+create table t2 (select * from t1);
+show create table t2;
+
+# Ugly, but we can't do anything about this in 4.0
+alter table t1 add column t0 timestamp first;
+show create table t1;
---error 1067
-create table t1 (a timestamp default 1);
+drop table t1,t2;
+
+#
+# Test for bug 2464, DEFAULT keyword in INSERT statement should return
+# default value for column.
+#
+
+create table t1 (ts1 timestamp, ts2 timestamp);
+set TIMESTAMP=1000000000;
+insert into t1 values ();
+insert into t1 values (DEFAULT, DEFAULT);
+select * from t1;
+drop table t1;
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index 4d3b0604984..d03ec5841af 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -47,6 +47,72 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
#endif
}
+/*
+ SYNOPSIS
+ reset_root_defaults()
+ mem_root memory root to change defaults of
+ block_size new value of block size. Must be
+ greater than ~68 bytes (the exact value depends on
+ platform and compilation flags)
+ pre_alloc_size new size of preallocated block. If not zero,
+ must be equal to or greater than block size,
+ otherwise means 'no prealloc'.
+ DESCRIPTION
+ Function aligns and assigns new value to block size; then it tries to
+ reuse one of existing blocks as prealloc block, or malloc new one of
+ requested size. If no blocks can be reused, all unused blocks are freed
+ before allocation.
+ */
+
+void reset_root_defaults(MEM_ROOT *mem_root, uint block_size,
+ uint pre_alloc_size)
+{
+ mem_root->block_size= block_size-MALLOC_OVERHEAD-sizeof(USED_MEM)-8;
+#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
+ if (pre_alloc_size)
+ {
+ uint size= pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM));
+ if (!mem_root->pre_alloc || mem_root->pre_alloc->size != size)
+ {
+ USED_MEM *mem, **prev= &mem_root->free;
+ /*
+ Free unused blocks, so that consequent calls
+ to reset_root_defaults won't eat away memory.
+ */
+ while (*prev)
+ {
+ mem= *prev;
+ if (mem->size == size)
+ {
+ /* We found a suitable block, no need to do anything else */
+ mem_root->pre_alloc= mem;
+ return;
+ }
+ if (mem->left + ALIGN_SIZE(sizeof(USED_MEM)) == mem->size)
+ {
+ /* remove block from the list and free it */
+ *prev= mem->next;
+ my_free((gptr) mem, MYF(0));
+ }
+ else
+ prev= &mem->next;
+ }
+ /* Allocate new prealloc block and add it to the end of free list */
+ if ((mem= (USED_MEM *) my_malloc(size, MYF(0))))
+ {
+ mem->size= size;
+ mem->left= pre_alloc_size;
+ mem->next= *prev;
+ *prev= mem_root->pre_alloc= mem;
+ }
+ }
+ }
+ else
+#endif
+ mem_root->pre_alloc= 0;
+}
+
+
gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
{
#if defined(HAVE_purify) && defined(EXTRA_DEBUG)
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 662e33a3a5a..a8c57b4cd1d 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -298,9 +298,11 @@ int handle_options(int *argc, char ***argv,
--enable-'option-name'.
*optend was set to '0' if one used --disable-option
*/
- *((my_bool*) optp->value)= (my_bool) (!optend || *optend == '1');
- (*argc)--;
- get_one_option(optp->id, optp, argument);
+ my_bool tmp= (my_bool) (!optend || *optend == '1');
+ *((my_bool*) optp->value)= tmp;
+ (*argc)--;
+ get_one_option(optp->id, optp,
+ tmp ? (char*) "1" : disabled_my_option);
continue;
}
argument= optend;
diff --git a/sql/field.cc b/sql/field.cc
index 8bcbf8ecc56..ac3ebb4bfc7 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2583,22 +2583,18 @@ static longlong fix_datetime(longlong nr, TIME *time_res)
void Field_timestamp::store(longlong nr)
{
TIME l_time;
- time_t timestamp;
+ time_t timestamp= 0;
if ((nr= fix_datetime(nr, &l_time)))
{
long not_used;
- if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1)
- {
+ timestamp= my_gmt_sec(&l_time, &not_used);
+
+ if (!timestamp)
current_thd->cuted_fields++;
- timestamp=0;
- }
- else
- timestamp=my_gmt_sec(&l_time, &not_used);
}
- else
- timestamp=0;
+
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -5124,8 +5120,7 @@ create_field::create_field(Field *old_field,Field *orig_field)
interval=0;
def=0;
if (!old_field->is_real_null() && ! (flags & BLOB_FLAG) &&
- old_field->type() != FIELD_TYPE_TIMESTAMP && old_field->ptr &&
- orig_field)
+ old_field->ptr && orig_field)
{
char buff[MAX_FIELD_WIDTH],*pos;
String tmp(buff,sizeof(buff));
diff --git a/sql/field.h b/sql/field.h
index 413a08f08d4..6f049e3809e 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -564,7 +564,10 @@ public:
void set_time();
virtual void set_default()
{
- set_time();
+ if (table->timestamp_field == this)
+ set_time();
+ else
+ Field::set_default();
}
inline long get_timestamp()
{
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index bcd1130dcdb..68052014f57 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -276,7 +276,7 @@ convert_error_code_to_mysql(
} else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) {
- return(HA_WRONG_CREATE_OPTION);
+ return(HA_ERR_ROW_IS_REFERENCED);
} else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
@@ -3572,6 +3572,7 @@ ha_innobase::delete_table(
int error;
trx_t* parent_trx;
trx_t* trx;
+ THD *thd= current_thd;
char norm_name[1000];
DBUG_ENTER("ha_innobase::delete_table");
@@ -3597,6 +3598,14 @@ ha_innobase::delete_table(
trx->mysql_thd = current_thd;
trx->mysql_query_str = &((*current_thd).query);
+ if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
+ trx->check_foreigns = FALSE;
+ }
+
+ if (thd->options & OPTION_RELAXED_UNIQUE_CHECKS) {
+ trx->check_unique_secondary = FALSE;
+ }
+
name_len = strlen(name);
assert(name_len < 1000);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index acb7005c26c..b3c3c5648bf 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -116,6 +116,9 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
/* Time handling defaults */
#define TIMESTAMP_MAX_YEAR 2038
#define YY_PART_YEAR 70
+#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1)
+#define TIMESTAMP_MAX_VALUE 2145916799
+#define TIMESTAMP_MIN_VALUE 1
#define PRECISION_FOR_DOUBLE 53
#define PRECISION_FOR_FLOAT 24
@@ -708,7 +711,7 @@ extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
extern my_bool opt_safe_show_db, opt_local_infile;
extern my_bool opt_slave_compressed_protocol, use_temp_pool;
extern my_bool opt_readonly;
-extern my_bool opt_enable_named_pipe;
+extern my_bool opt_enable_named_pipe, opt_sync_frm;
extern MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log;
extern FILE *bootstrap_file;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index c3931eccc0c..b0ab59b49e6 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -140,7 +140,7 @@ int initgroups(const char *,unsigned int);
typedef fp_except fp_except_t;
#endif
- /* We can't handle floating point expections with threads, so disable
+ /* We can't handle floating point exceptions with threads, so disable
this on freebsd
*/
@@ -308,7 +308,7 @@ static my_bool opt_noacl=0, opt_bootstrap=0, opt_myisam_log=0;
my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
my_bool opt_log_slave_updates= 0, opt_console= 0;
-my_bool opt_readonly = 0;
+my_bool opt_readonly = 0, opt_sync_bdb_logs, opt_sync_frm;
volatile bool mqh_used = 0;
FILE *bootstrap_file=0;
@@ -1689,7 +1689,7 @@ static void start_signal_handler(void)
(void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
- pthread_attr_setstacksize(&thr_attr,32768);
+ pthread_attr_setstacksize(&thr_attr,thread_stack);
#endif
(void) pthread_mutex_lock(&LOCK_thread_count);
@@ -3158,7 +3158,7 @@ enum options_mysqld {
OPT_DELAY_KEY_WRITE_ALL, OPT_SLOW_QUERY_LOG,
OPT_DELAY_KEY_WRITE, OPT_CHARSETS_DIR,
OPT_BDB_HOME, OPT_BDB_LOG,
- OPT_BDB_TMP, OPT_BDB_NOSYNC,
+ OPT_BDB_TMP, OPT_BDB_SYNC,
OPT_BDB_LOCK, OPT_BDB_SKIP,
OPT_BDB_NO_RECOVER, OPT_BDB_SHARED,
OPT_MASTER_HOST, OPT_MASTER_USER,
@@ -3251,7 +3251,8 @@ enum options_mysqld {
OPT_DEFAULT_WEEK_FORMAT,
OPT_RANGE_ALLOC_BLOCK_SIZE,
OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE,
- OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE
+ OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE,
+ OPT_SYNC_FRM, OPT_BDB_NOSYNC
};
@@ -3277,8 +3278,14 @@ struct my_option my_long_options[] =
{"bdb-no-recover", OPT_BDB_NO_RECOVER,
"Don't try to recover Berkeley DB tables on start", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
- {"bdb-no-sync", OPT_BDB_NOSYNC, "Don't synchronously flush logs", 0, 0, 0,
- GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"bdb-no-sync", OPT_BDB_NOSYNC,
+ "Disable synchronously flushing logs. This option is deprecated, use --skip-sync-bdb-logs or sync-bdb-logs=0 instead",
+ // (gptr*) &opt_sync_bdb_logs, (gptr*) &opt_sync_bdb_logs, 0, GET_BOOL,
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"sync-bdb-logs", OPT_BDB_SYNC,
+ "Synchronously flush logs. Enabled by default",
+ (gptr*) &opt_sync_bdb_logs, (gptr*) &opt_sync_bdb_logs, 0, GET_BOOL,
+ NO_ARG, 1, 0, 0, 0, 0, 0},
{"bdb-shared-data", OPT_BDB_SHARED,
"Start Berkeley DB in multi-process mode", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
@@ -3286,6 +3293,9 @@ struct my_option my_long_options[] =
(gptr*) &berkeley_tmpdir, (gptr*) &berkeley_tmpdir, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif /* HAVE_BERKELEY_DB */
+ {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default",
+ (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0,
+ 0, 0, 0, 0},
{"skip-bdb", OPT_BDB_SKIP, "Don't use berkeley db (will save memory)",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"big-tables", OPT_BIG_TABLES,
@@ -4044,7 +4054,7 @@ this value; if zero (the default): when the size exceeds max_binlog_size. \
(gptr*) &max_system_variables.range_alloc_block_size, 0, GET_ULONG,
REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0},
{"read-only", OPT_READONLY,
- "Make all tables readonly, with the expections for replications (slave) threads and users with the SUPER privilege",
+ "Make all tables readonly, with the exception for replication (slave) threads and users with the SUPER privilege",
(gptr*) &opt_readonly,
(gptr*) &opt_readonly,
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
@@ -4729,7 +4739,15 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
#ifdef HAVE_BERKELEY_DB
case OPT_BDB_NOSYNC:
- berkeley_env_flags|=DB_TXN_NOSYNC;
+ /* Deprecated option */
+ opt_sync_bdb_logs= 0;
+ /* Fall through */
+ case OPT_BDB_SYNC:
+ if (!opt_sync_bdb_logs)
+ berkeley_env_flags|= DB_TXN_NOSYNC;
+ else
+ berkeley_env_flags&= ~DB_TXN_NOSYNC;
+ printf("berkeley_env_flags: %d, arg '%s'\n", berkeley_env_flags, argument);
break;
case OPT_BDB_NO_RECOVER:
berkeley_init_flags&= ~(DB_RECOVER);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 693d8e4c958..475beb798e6 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -88,6 +88,8 @@ static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
static void fix_max_binlog_size(THD *thd, enum_var_type type);
static void fix_max_relay_log_size(THD *thd, enum_var_type type);
static void fix_max_connections(THD *thd, enum_var_type type);
+static void fix_thd_mem_root(THD *thd, enum_var_type type);
+static void fix_trans_mem_root(THD *thd, enum_var_type type);
/*
Variable definition list
@@ -209,13 +211,17 @@ sys_var_long_ptr sys_query_cache_size("query_cache_size",
sys_var_thd_ulong sys_range_alloc_block_size("range_alloc_block_size",
&SV::range_alloc_block_size);
sys_var_thd_ulong sys_query_alloc_block_size("query_alloc_block_size",
- &SV::query_alloc_block_size);
+ &SV::query_alloc_block_size,
+ fix_thd_mem_root);
sys_var_thd_ulong sys_query_prealloc_size("query_prealloc_size",
- &SV::query_prealloc_size);
+ &SV::query_prealloc_size,
+ fix_thd_mem_root);
sys_var_thd_ulong sys_trans_alloc_block_size("transaction_alloc_block_size",
- &SV::trans_alloc_block_size);
+ &SV::trans_alloc_block_size,
+ fix_trans_mem_root);
sys_var_thd_ulong sys_trans_prealloc_size("transaction_prealloc_size",
- &SV::trans_prealloc_size);
+ &SV::trans_prealloc_size,
+ fix_trans_mem_root);
#ifdef HAVE_QUERY_CACHE
sys_var_long_ptr sys_query_cache_limit("query_cache_limit",
@@ -763,6 +769,24 @@ static void fix_max_connections(THD *thd, enum_var_type type)
}
+static void fix_thd_mem_root(THD *thd, enum_var_type type)
+{
+ if (type != OPT_GLOBAL)
+ reset_root_defaults(&thd->mem_root,
+ thd->variables.query_alloc_block_size,
+ thd->variables.query_prealloc_size);
+}
+
+
+static void fix_trans_mem_root(THD *thd, enum_var_type type)
+{
+ if (type != OPT_GLOBAL)
+ reset_root_defaults(&thd->transaction.mem_root,
+ thd->variables.trans_alloc_block_size,
+ thd->variables.trans_prealloc_size);
+}
+
+
bool sys_var_long_ptr::update(THD *thd, set_var *var)
{
ulonglong tmp= var->value->val_int();
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f97b1b8f8be..ac3ccd4fc62 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3040,12 +3040,12 @@ bool add_field_to_list(char *field_name, enum_field_types type,
if (default_value)
{
- if (type == FIELD_TYPE_TIMESTAMP)
- {
- net_printf(&thd->net, ER_INVALID_DEFAULT, field_name);
- DBUG_RETURN(1);
- }
- else if (default_value->type() == Item::NULL_ITEM)
+ /*
+ We allow specifying value for first TIMESTAMP column
+ altough it is silently ignored. This should be fixed in 4.1
+ (by proper warning or real support for default values)
+ */
+ if (default_value->type() == Item::NULL_ITEM)
{
default_value=0;
if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) ==
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index addea958ff6..f62853ce9d6 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -503,6 +503,12 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
field->sql_type(type);
net_store_data(packet,convert,type.ptr(),type.length());
+ /*
+ Altough TIMESTAMP fields can't contain NULL as its value they
+ will accept NULL if you will try to insert such value and will
+ convert it to current TIMESTAMP. So YES here means that NULL
+ is allowed for assignment but can't be returned.
+ */
pos=(byte*) ((flags & NOT_NULL_FLAG) &&
field->type() != FIELD_TYPE_TIMESTAMP ?
"" : "YES");
@@ -512,7 +518,11 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
(field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
net_store_data(packet,convert,(char*) pos);
- if (field->type() == FIELD_TYPE_TIMESTAMP ||
+ /*
+ We handle first TIMESTAMP column in special way because its
+ default value is ignored and current timestamp used instead.
+ */
+ if (table->timestamp_field == field ||
field->unireg_check == Field::NEXT_NUMBER)
null_default_value=1;
if (!null_default_value && !field->is_null())
@@ -883,7 +893,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append(type.ptr(),type.length());
has_default= (field->type() != FIELD_TYPE_BLOB &&
- field->type() != FIELD_TYPE_TIMESTAMP &&
+ table->timestamp_field != field &&
field->unireg_check != Field::NEXT_NUMBER);
if (flags & NOT_NULL_FLAG)
packet->append(" NOT NULL", 9);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 7fa973eb60f..774801c094a 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -167,7 +167,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
String wrong_tables;
db_type table_type;
int error;
- bool some_tables_deleted=0, tmp_table_deleted=0;
+ bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
DBUG_ENTER("mysql_rm_table_part2");
if (lock_table_names(thd, tables))
@@ -212,6 +212,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
error=ha_delete_table(table_type, path);
if (error == ENOENT && if_exists)
error = 0;
+ if (error == HA_ERR_ROW_IS_REFERENCED)
+ foreign_key_error=1; /* the table is referenced by a foreign key
+ constraint */
if (!error || error == ENOENT)
{
/* Delete the table definition file */
@@ -247,7 +250,10 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
error= 0;
if (wrong_tables.length())
{
- my_error(ER_BAD_TABLE_ERROR,MYF(0),wrong_tables.c_ptr());
+ if (!foreign_key_error)
+ my_error(ER_BAD_TABLE_ERROR,MYF(0),wrong_tables.c_ptr());
+ else
+ my_error(ER_ROW_IS_REFERENCED,MYF(0));
error= 1;
}
DBUG_RETURN(error);
diff --git a/sql/time.cc b/sql/time.cc
index 5dc229b1d88..0363d764100 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -63,6 +63,9 @@ long my_gmt_sec(TIME *t, long *my_timezone)
struct tm *l_time,tm_tmp;
long diff, current_timezone;
+ if (t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR)
+ return 0;
+
if (t->hour >= 24)
{ /* Fix for time-loop */
t->day+=t->hour/24;
@@ -125,8 +128,10 @@ long my_gmt_sec(TIME *t, long *my_timezone)
tmp-=t->minute*60 + t->second; // Move to previous hour
}
*my_timezone= current_timezone;
- if (tmp < 0 && t->year <= 1900+YY_PART_YEAR)
+
+ if (tmp < TIMESTAMP_MIN_VALUE || tmp > TIMESTAMP_MAX_VALUE)
tmp= 0;
+
return (long) tmp;
} /* my_gmt_sec */
@@ -444,15 +449,13 @@ time_t str_to_timestamp(const char *str,uint length)
{
TIME l_time;
long not_used;
+ time_t timestamp= 0;
- if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE)
- return(0);
- if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1)
- {
+ if (str_to_TIME(str,length,&l_time,0) != TIMESTAMP_NONE &&
+ !(timestamp= my_gmt_sec(&l_time, &not_used)))
current_thd->cuted_fields++;
- return(0);
- }
- return(my_gmt_sec(&l_time, &not_used));
+
+ return timestamp;
}
diff --git a/sql/unireg.cc b/sql/unireg.cc
index ff42bfae0f0..955e5cfda8a 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -150,7 +150,7 @@ int rea_create_table(my_string file_name,
my_free((gptr) screen_buff,MYF(0));
my_afree((gptr) keybuff);
- if (my_sync(file, MYF(MY_WME)))
+ if (opt_sync_frm && my_sync(file, MYF(MY_WME)))
goto err2;
if (my_close(file,MYF(MY_WME)) ||
ha_create_table(file_name,create_info,0))
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index 7ffc83ea005..5cd718f5944 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -15,6 +15,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
+ Copyright (C) 2003 by Sathit Jittanupat <jsat66@hotmail.com,jsat66@yahoo.com>
+ * solving bug crash with long text field string
+ * sorting with different number of space or sign char. within string
+
Copyright (C) 2001 by Korakot Chaovavanich <korakot@iname.com> and
Apisilp Trunganont <apisilp@pantip.inet.co.th>
Copyright (C) 1998, 1999 by Pruet Boonma <pruet@eng.cmu.ac.th>
@@ -49,10 +53,6 @@
#include "m_ctype.h"
#include "t_ctype.h"
-static uchar* thai2sortable(const uchar *tstr,int len);
-
-#define BUFFER_MULTIPLY 4
-#define buffsize(s) (BUFFER_MULTIPLY * (strlen(s) + 1))
#define M L_MIDDLE
#define U L_UPPER
#define L L_LOWER
@@ -453,13 +453,77 @@ uchar NEAR sort_order_tis620[]=
Arg: const source string and length of converted string
Ret: Sortable string
*/
+static void _thai2sortable(uchar *tstr)
+{
+ uchar *p ;
+ int len,tlen ;
+ uchar c,l2bias ;
+
+ tlen= len = strlen (tstr) ;
+ l2bias = 256 - 8 ;
+ for (p=tstr; tlen > 0; p++,tlen--)
+ {
+ c = *p ;
+
+ if (isthai(c))
+ {
+ int *t_ctype0 = t_ctype[c] ;
+
+ if (isconsnt(c))
+ l2bias -= 8 ;
+ if (isldvowel(c) && isconsnt(p[1]))
+ {
+ /*
+ simply swap between leading-vowel and consonant
+ */
+ *p = p[1];
+ p[1]= c ;
+ tlen-- ;
+ p++;
+ continue ;
+ }
+
+ // if found level 2 char (L2_GARAN,L2_TONE*,L2_TYKHU) move to last
+ if (t_ctype0[1]>= L2_GARAN)
+ {
+ // l2bias use to control position weight of l2char
+ // example (*=l2char) XX*X must come before X*XX
+ strcpy (p,p+1) ;
+ tstr[len-1] = l2bias + t_ctype0[1]- L2_GARAN +1 ;
+ p-- ;
+ continue ;
+ }
+ }
+ else
+ {
+ l2bias -= 8 ;
+ *p = to_lower_tis620[c];
+ }
+ /*
+ this routine skip non-printable char
+ but not necessary, leave it like raw ascii 8 bits
+ */
+ /*
+ t_ctype0 = t_ctype[p[0]];
+ if ((t_ctype0[0]|t_ctype0[1]|t_ctype0[2])==IGNORE)
+ {
+ strcpy(p,p+1);
+ p-- ;
+ }
+ */
+ }
+}
+
/*
NOTE: isn't it faster to alloc buffer in calling function?
- */
+*/
+/*
+Sathit's NOTE: we don't use this function anymore
static uchar* thai2sortable(const uchar * tstr,int len)
{
+*/
/* We use only 3 levels (neglect capitalization). */
-
+/*
const uchar* p= tstr;
uchar *outBuf;
uchar *pRight1, *pRight2, *pRight3;
@@ -526,6 +590,7 @@ static uchar* thai2sortable(const uchar * tstr,int len)
memcpy(pRight1, pLeft3, pRight3 - pLeft3);
return outBuf;
}
+*/
/* strncoll() replacement, compare 2 string, both are conveted to sortable string
Arg: 2 Strings and it compare length
@@ -533,16 +598,27 @@ static uchar* thai2sortable(const uchar * tstr,int len)
*/
int my_strnncoll_tis620(const uchar * s1, int len1, const uchar * s2, int len2)
{
- uchar *tc1, *tc2;
- int i;
- tc1= thai2sortable(s1, len1);
- tc2= thai2sortable(s2, len2);
- i= strcmp((char*)tc1, (char*)tc2);
- if (tc1 != s1)
- free(tc1);
- if (tc2 != s2)
- free(tc2);
- return i;
+ uchar buf[80] ;
+ uchar *tc1, *tc2;
+ int i;
+
+ len1= (int) strnlen((char*) s1,len1);
+ len2= (int) strnlen((char*) s2,len2);
+ if ((len1 + len2 +2) > (int) sizeof(buf))
+ tc1 = (uchar *)malloc(len1+len2) ;
+ else
+ tc1 = buf ;
+ tc2 = tc1 + len1+1 ;
+ strncpy((char *)tc1,(char *)s1,len1) ;
+ tc1[len1] = 0; // if s1's length > len1, need to put 'end of string'
+ strncpy((char *)tc2,(char *)s2,len2) ;
+ tc2[len2] = 0; // put end of string
+ _thai2sortable(tc1);
+ _thai2sortable(tc2);
+ i= strcmp((char*)tc1, (char*)tc2);
+ if (tc1 != buf )
+ free(tc1);
+ return i;
}
/* strnxfrm replacment, convert Thai string to sortable string
@@ -551,15 +627,12 @@ int my_strnncoll_tis620(const uchar * s1, int len1, const uchar * s2, int len2)
*/
int my_strnxfrm_tis620(uchar * dest, const uchar * src, int len, int srclen)
{
- uint bufSize;
- uchar *tmp;
- bufSize= (uint) buffsize((char*)src);
- tmp= thai2sortable(src,srclen);
- set_if_smaller(bufSize,(uint) len);
- memcpy((uchar *)dest, tmp, bufSize);
- if (tmp != src)
- free(tmp);
- return (int)bufSize;
+ if (len > srclen)
+ len = srclen ;
+ strncpy (dest,src,len) ;
+ dest[len] = 0; // if src's length > len, need to put 'end of string'
+ _thai2sortable(dest);
+ return strlen(dest);
}
/* strcoll replacment, compare 2 strings
@@ -568,16 +641,7 @@ int my_strnxfrm_tis620(uchar * dest, const uchar * src, int len, int srclen)
*/
int my_strcoll_tis620(const uchar * s1, const uchar * s2)
{
- uchar *tc1, *tc2;
- int i;
- tc1= thai2sortable(s1, (int) strlen((char*)s1));
- tc2= thai2sortable(s2, (int) strlen((char*)s2));
- i= strcmp((char*)tc1, (char*)tc2);
- if (tc1 != s1)
- free(tc1);
- if (tc2 != s2)
- free(tc2);
- return i;
+ return my_strnncoll_tis620(s1, strlen((char *)s1),s2,strlen((char *)s2));
}
/* strxfrm replacment, convert Thai string to sortable string
@@ -586,15 +650,7 @@ int my_strcoll_tis620(const uchar * s1, const uchar * s2)
*/
int my_strxfrm_tis620(uchar * dest, const uchar * src, int len)
{
- uint bufSize;
- uchar *tmp;
-
- bufSize= (uint)buffsize((char*) src);
- tmp= thai2sortable(src, len);
- memcpy((uchar *)dest, tmp, bufSize);
- if (tmp != src)
- free(tmp);
- return bufSize;
+ return my_strnxfrm_tis620(dest,src,len,strlen((char *)src));
}
/* Convert SQL like string to C string
@@ -658,20 +714,31 @@ void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length)
{
const uchar* fr= from;
uchar* p= ptr;
+ uint i;
if (length > field_length)
length= field_length;
- while (length--)
- if ((istone(*fr) || isdiacrt1(*fr)) &&
- (islwrvowel(fr[1]) || isuprvowel(fr[1])))
- {
- *p= fr[1];
- p[1]= *fr;
- fr+= 2;
- p+= 2;
- length--;
+ for (i=0;i<length;i++,p++,fr++)
+ {
+ *p = *fr ;
+
+/* Sathit's NOTE: it's better idea not to do any normalize
+*/
+ if (istone(*fr) || isdiacrt1(*fr))
+ {
+ if (i > 0 && (islwrvowel(fr[-1]) || isuprvowel(fr[-1])))
+ continue ;
+ if(islwrvowel(fr[1]) || isuprvowel(fr[1]))
+ {
+ *p= fr[1];
+ p[1]= *fr;
+ fr++;
+ p++;
+ i++ ;
+ }
}
- else
- *p++ = *fr++;
+
+ }
+
}
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index d55068db64e..7f4987be3a8 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -59,6 +59,12 @@ export PATH
mode=$1 # start or stop
+case `echo "testing\c"`,`echo -n testing` in
+ *c*,-n*) echo_n= echo_c= ;;
+ *c*,*) echo_n=-n echo_c= ;;
+ *) echo_n= echo_c='\c' ;;
+esac
+
parse_arguments() {
for arg do
case "$arg" in
@@ -169,7 +175,7 @@ case "$mode" in
sleep 1
while [ -s $pid_file -a "$flags" != aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ]
do
- [ -z "$flags" ] && echo "Wait for mysqld to exit\c" || echo ".\c"
+ [ -z "$flags" ] && echo $echo_n "Wait for mysqld to exit$echo_c" || echo $echo_n ".$echo_c"
flags=a$flags
sleep 1
done