Commit 3412bdf0 authored by marko's avatar marko

Merge changes from MySQL AB:

innodb_mysql.test, innodb_mysql.result:
  Bug #16798: Uninitialized row buffer reads in ref-or-null optimizer
  Bug #12882: min/max inconsistent on empty table
  Test of behaviour with CREATE ... SELECT
 Moved from group_min_max.test:
  Bug #12672: primary key implicitly included in every innodb index
  Bug #6142: a problem with empty innodb table 
  Bug #9798: group by with rollup

ChangeSet@2006/06/01 21:47:15+03:00 bell@sanja.is.com.ua 
#   interface for transaction log management added to handlerton
#   iterators creation interface added to handlerton
ha_innodb.cc: Add get_log_status = create_iterator = NULL

ChangeSet@2006/06/04 18:52:22+03:00 monty@mysql.com 
#   This changeset is largely a handler cleanup changeset (WL#3281),
#   but includes fixes and cleanups that was found necessary while
#   testing the handler changes
# sql/ha_innodb.h
#   2006/06/04 18:52:09+03:00 monty@mysql.com +6 -13
#   Update to 'newer' table handler interface
#   - table_flags are now ulonglong
#   - Added reset() method
#   - Removed not needed ha_retrieve_all_cols() and ha_retrieve_all_pk()
#     columns.
#   - Made build_template() a class function to be able to easier access
#     class variables
# sql/ha_innodb.cc
#   2006/06/04 18:52:09+03:00 monty@mysql.com +37 -44
#   Update to 'newer' table handler interface
#   - Update innobase_create_handler() to new interface
#   - Removed HA_NOT_EXACT_COUNT (not needed)
#   - Renamed HA_PRIMARY_KEY_ALLOW_RANDOM_ACCESS
#     to HA_PRIMARY_KEY_REQUIRED_FOR_POSITION.
#   - Prefixed base status variables with 'stats'
#   - Use table column bitmaps instead of ha_get_bit_in_read_set()
#   - Added ::reset(), with code from ::extra(HA_EXTRA_RESET)
#   - Removed HA_EXTRA_RETRIVE_ALL_COLS and HA_EXTRA_RETRIEVE_PRIMARY_KEY as
#     the table->read_set and table->write_set bitmaps now are accurate

ChangeSet@2006/06/02 22:21:32+02:00 guilhem@mysql.com 
#   First push for WL#3146 "less locking in auto_increment". It is a
#   0-real-change patch.
#   New prototype for get_auto_increment() (but new arguments not yet used),
#   to be able to reserve a finite interval of auto_increment values from
#   cooperating engines.
#   A hint on how many values to reserve is found in
#   handler::estimation_rows_to_insert,
#   filled by ha_start_bulk_insert(), new wrapper around start_bulk_insert().
#   NOTE: this patch changes nothing, for all engines.
#   But it makes the API ready for those
#   engines which will want to do reservation.
#   More csets will come to complete WL#3146.
ha_innodb.h, ha_innodb.cc: update to new prototype of get_auto_increment

ChangeSet@2006/05/28 14:51:01+02:00 serg@sergbook.mysql.com 
#   handlerton cleanup:
#   duplicate fields removed, st_mysql_storage_engine added to support
#   run-time handlerton initialization (no compiler warnings), handler API
#   is now tied to MySQL version, handlerton->plugin mapping added
#   (slot-based), dummy default_hton removed, plugin-type-specific
#   initialization generalized, built-in plugins are now initialized too,
#   --default-storage-engine no longer needs a list of storage engines
#   in handle_options().
#   
# sql/ha_innodb.h
#   2006/05/28 14:50:53+02:00 serg@sergbook.mysql.com +1 -1
#   handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine,
#   initialize handlerton run-time to avoid compiler warnings
# 
# sql/ha_innodb.cc
#   2006/05/28 14:50:53+02:00 serg@sergbook.mysql.com +37 -52
#   handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine,
#   initialize handlerton run-time to avoid compiler warnings

ChangeSet@2006/06/01 23:59:34+02:00 serg@serg.mylan 
#   second patch for make distcheck
ha_innodb.cc: enclose in #ifdef WITH_INNOBASE_STORAGE_ENGINE / #endif
parent b93fa678
......@@ -43,6 +43,7 @@ have disables the InnoDB inlining in this file. */
#define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1))
#ifdef WITH_INNOBASE_STORAGE_ENGINE
#include "ha_innodb.h"
pthread_mutex_t innobase_share_mutex, /* to protect innobase_open_files */
......@@ -204,54 +205,16 @@ static int innobase_rollback(THD* thd, bool all);
static int innobase_rollback_to_savepoint(THD* thd, void *savepoint);
static int innobase_savepoint(THD* thd, void *savepoint);
static int innobase_release_savepoint(THD* thd, void *savepoint);
static handler *innobase_create_handler(TABLE_SHARE *table);
static handler *innobase_create_handler(TABLE_SHARE *table,
MEM_ROOT *mem_root);
static const char innobase_hton_name[]= "InnoDB";
static const char innobase_hton_comment[]=
"Supports transactions, row-level locking, and foreign keys";
handlerton innobase_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
innobase_hton_name,
SHOW_OPTION_YES,
innobase_hton_comment,
DB_TYPE_INNODB,
innobase_init,
0, /* slot */
sizeof(trx_named_savept_t), /* savepoint size. TODO: use it */
innobase_close_connection,
innobase_savepoint,
innobase_rollback_to_savepoint,
innobase_release_savepoint,
innobase_commit, /* commit */
innobase_rollback, /* rollback */
innobase_xa_prepare, /* prepare */
innobase_xa_recover, /* recover */
innobase_commit_by_xid, /* commit_by_xid */
innobase_rollback_by_xid, /* rollback_by_xid */
innobase_create_cursor_view,
innobase_set_cursor_view,
innobase_close_cursor_view,
innobase_create_handler, /* Create a new handler */
innobase_drop_database, /* Drop a database */
innobase_end, /* Panic call */
innobase_start_trx_and_assign_read_view, /* Start Consistent Snapshot */
innobase_flush_logs, /* Flush logs */
innobase_show_status, /* Show status */
NULL, /* Partition flags */
NULL, /* Alter table flags */
NULL, /* alter_tablespace */
NULL, /* Fill FILES table */
HTON_NO_FLAGS,
NULL, /* binlog_func */
NULL, /* binlog_log_query */
innobase_release_temporary_latches
};
handlerton innobase_hton;
static handler *innobase_create_handler(TABLE_SHARE *table)
static handler *innobase_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root)
{
return new ha_innobase(table);
return new (mem_root) ha_innobase(table);
}
......@@ -933,10 +896,9 @@ ha_innobase::ha_innobase(TABLE_SHARE *table_arg)
HA_NULL_IN_KEY |
HA_CAN_INDEX_BLOBS |
HA_CAN_SQL_HANDLER |
HA_NOT_EXACT_COUNT |
HA_PRIMARY_KEY_ALLOW_RANDOM_ACCESS |
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
HA_PRIMARY_KEY_IN_READ_INDEX |
HA_CAN_GEOMETRY |
HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
HA_TABLE_SCAN_ON_INDEX),
start_of_scan(0),
num_write_row(0)
......@@ -1367,10 +1329,9 @@ ha_innobase::init_table_handle_for_HANDLER(void)
/*************************************************************************
Opens an InnoDB database. */
bool
int
innobase_init(void)
/*===============*/
/* out: &innobase_hton, or NULL on error */
{
static char current_dir[3]; /* Set if using current lib */
int err;
......@@ -1379,8 +1340,33 @@ innobase_init(void)
DBUG_ENTER("innobase_init");
innobase_hton.state=have_innodb;
innobase_hton.db_type= DB_TYPE_INNODB;
innobase_hton.savepoint_offset=sizeof(trx_named_savept_t);
innobase_hton.close_connection=innobase_close_connection;
innobase_hton.savepoint_set=innobase_savepoint;
innobase_hton.savepoint_rollback=innobase_rollback_to_savepoint;
innobase_hton.savepoint_release=innobase_release_savepoint;
innobase_hton.commit=innobase_commit;
innobase_hton.rollback=innobase_rollback;
innobase_hton.prepare=innobase_xa_prepare;
innobase_hton.recover=innobase_xa_recover;
innobase_hton.commit_by_xid=innobase_commit_by_xid;
innobase_hton.rollback_by_xid=innobase_rollback_by_xid;
innobase_hton.create_cursor_read_view=innobase_create_cursor_view;
innobase_hton.set_cursor_read_view=innobase_set_cursor_view;
innobase_hton.close_cursor_read_view=innobase_close_cursor_view;
innobase_hton.create=innobase_create_handler;
innobase_hton.drop_database=innobase_drop_database;
innobase_hton.panic=innobase_end;
innobase_hton.start_consistent_snapshot=innobase_start_trx_and_assign_read_view;
innobase_hton.flush_logs=innobase_flush_logs;
innobase_hton.show_status=innobase_show_status;
innobase_hton.flags=HTON_NO_FLAGS;
innobase_hton.release_temporary_latches=innobase_release_temporary_latches;
if (have_innodb != SHOW_OPTION_YES)
goto error;
DBUG_RETURN(0); // nothing else to do
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
......@@ -2476,7 +2462,7 @@ ha_innobase::open(
}
}
block_size = 16 * 1024; /* Index block size in InnoDB: used by MySQL
stats.block_size = 16 * 1024; /* Index block size in InnoDB: used by MySQL
in query optimization */
/* Init table lock structure */
......@@ -3071,16 +3057,15 @@ ha_innobase::store_key_val_for_row(
/******************************************************************
Builds a 'template' to the prebuilt struct. The template is used in fast
retrieval of just those column values MySQL needs in its processing. */
static
void
build_template(
ha_innobase::build_template(
/*===========*/
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
THD* thd, /* in: current user thread, used
only if templ_type is
ROW_MYSQL_REC_FIELDS */
TABLE* table, /* in: MySQL table */
ulint templ_type) /* in: ROW_MYSQL_WHOLE_ROW or
uint templ_type) /* in: ROW_MYSQL_WHOLE_ROW or
ROW_MYSQL_REC_FIELDS */
{
dict_index_t* index;
......@@ -3189,8 +3174,8 @@ build_template(
goto include_field;
}
if (table->file->ha_get_bit_in_read_set(i+1) ||
table->file->ha_get_bit_in_write_set(i+1)) {
if (bitmap_is_set(table->read_set, i) ||
bitmap_is_set(table->write_set, i)) {
/* This field is needed in the query */
goto include_field;
......@@ -5566,7 +5551,7 @@ ha_innobase::info(
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
if (os_file_get_status(path,&stat_info)) {
create_time = stat_info.ctime;
stats.create_time = stat_info.ctime;
}
}
......@@ -5594,21 +5579,21 @@ ha_innobase::info(
n_rows++;
}
records = (ha_rows)n_rows;
deleted = 0;
data_file_length = ((ulonglong)
stats.records = (ha_rows)n_rows;
stats.deleted = 0;
stats.data_file_length = ((ulonglong)
ib_table->stat_clustered_index_size)
* UNIV_PAGE_SIZE;
index_file_length = ((ulonglong)
stats.index_file_length = ((ulonglong)
ib_table->stat_sum_of_other_index_sizes)
* UNIV_PAGE_SIZE;
delete_length = 0;
check_time = 0;
stats.delete_length = 0;
stats.check_time = 0;
if (records == 0) {
mean_rec_length = 0;
if (stats.records == 0) {
stats.mean_rec_length = 0;
} else {
mean_rec_length = (ulong) (data_file_length / records);
stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
}
}
......@@ -5657,9 +5642,9 @@ ha_innobase::info(
if (index->stat_n_diff_key_vals[j + 1] == 0) {
rec_per_key = records;
rec_per_key = stats.records;
} else {
rec_per_key = (ha_rows)(records /
rec_per_key = (ha_rows)(stats.records /
index->stat_n_diff_key_vals[j + 1]);
}
......@@ -5714,7 +5699,7 @@ ha_innobase::info(
}
}
auto_increment_value = auto_inc;
stats.auto_increment_value = auto_inc;
}
prebuilt->trx->op_info = (char*)"";
......@@ -6109,8 +6094,7 @@ ha_innobase::extra(
/*===============*/
/* out: 0 or error number */
enum ha_extra_function operation)
/* in: HA_EXTRA_RETRIEVE_ALL_COLS or some
other flag */
/* in: HA_EXTRA_FLUSH or some other flag */
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
......@@ -6124,13 +6108,6 @@ ha_innobase::extra(
row_mysql_prebuilt_free_blob_heap(prebuilt);
}
break;
case HA_EXTRA_RESET:
if (prebuilt->blob_heap) {
row_mysql_prebuilt_free_blob_heap(prebuilt);
}
prebuilt->keep_other_fields_on_keyread = 0;
prebuilt->read_just_key = 0;
break;
case HA_EXTRA_RESET_STATE:
prebuilt->keep_other_fields_on_keyread = 0;
prebuilt->read_just_key = 0;
......@@ -6138,16 +6115,6 @@ ha_innobase::extra(
case HA_EXTRA_NO_KEYREAD:
prebuilt->read_just_key = 0;
break;
case HA_EXTRA_RETRIEVE_ALL_COLS:
prebuilt->hint_need_to_fetch_extra_cols
= ROW_RETRIEVE_ALL_COLS;
break;
case HA_EXTRA_RETRIEVE_PRIMARY_KEY:
if (prebuilt->hint_need_to_fetch_extra_cols == 0) {
prebuilt->hint_need_to_fetch_extra_cols
= ROW_RETRIEVE_PRIMARY_KEY;
}
break;
case HA_EXTRA_KEYREAD:
prebuilt->read_just_key = 1;
break;
......@@ -6161,6 +6128,18 @@ ha_innobase::extra(
return(0);
}
int ha_innobase::reset()
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
if (prebuilt->blob_heap) {
row_mysql_prebuilt_free_blob_heap(prebuilt);
}
prebuilt->keep_other_fields_on_keyread = 0;
prebuilt->read_just_key = 0;
return 0;
}
/**********************************************************************
MySQL calls this function at the start of each SQL statement inside LOCK
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
......@@ -6619,7 +6598,7 @@ innodb_show_status(
bool result = FALSE;
if (stat_print(thd, innobase_hton.name, strlen(innobase_hton.name),
if (stat_print(thd, innobase_hton_name, strlen(innobase_hton_name),
STRING_WITH_LEN(""), str, flen)) {
result= TRUE;
}
......@@ -6646,7 +6625,7 @@ innodb_mutex_show_status(
ulint rw_lock_count_os_wait= 0;
ulint rw_lock_count_os_yield= 0;
ulonglong rw_lock_wait_time= 0;
uint hton_name_len= strlen(innobase_hton.name), buf1len, buf2len;
uint hton_name_len= strlen(innobase_hton_name), buf1len, buf2len;
DBUG_ENTER("innodb_mutex_show_status");
#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
......@@ -6673,7 +6652,7 @@ innodb_mutex_show_status(
mutex->count_os_yield,
mutex->lspent_time/1000);
if (stat_print(thd, innobase_hton.name,
if (stat_print(thd, innobase_hton_name,
hton_name_len, buf1, buf1len,
buf2, buf2len)) {
#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
......@@ -6703,7 +6682,7 @@ innodb_mutex_show_status(
rw_lock_count_os_wait, rw_lock_count_os_yield,
rw_lock_wait_time/1000);
if (stat_print(thd, innobase_hton.name, hton_name_len,
if (stat_print(thd, innobase_hton_name, hton_name_len,
STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
DBUG_RETURN(1);
}
......@@ -7120,17 +7099,21 @@ ha_innobase::innobase_read_and_init_auto_inc(
return(error);
}
/***********************************************************************
/*******************************************************************************
This function initializes the auto-inc counter if it has not been
initialized yet. This function does not change the value of the auto-inc
counter if it already has been initialized. Returns the value of the
auto-inc counter. */
auto-inc counter in *first_value, and ULONGLONG_MAX in *nb_reserved_values (as
we have a table-level lock). offset, increment, nb_desired_values are ignored.
*first_value is set to -1 if error (deadlock or lock wait timeout) */
ulonglong
ha_innobase::get_auto_increment()
/*=============================*/
/* out: auto-increment column value, -1 if error
(deadlock or lock wait timeout) */
void ha_innobase::get_auto_increment(
/*=================================*/
ulonglong offset, /* in */
ulonglong increment, /* in */
ulonglong nb_desired_values, /* in */
ulonglong *first_value, /* out */
ulonglong *nb_reserved_values) /* out */
{
longlong nr;
int error;
......@@ -7145,10 +7128,13 @@ ha_innobase::get_auto_increment()
ut_print_timestamp(stderr);
sql_print_error("Error %lu in ::get_auto_increment()",
(ulong) error);
return(~(ulonglong) 0);
*first_value= (~(ulonglong) 0);
return;
}
return((ulonglong) nr);
*first_value= (ulonglong) nr;
/* table-level autoinc lock reserves up to +inf */
*nb_reserved_values= ULONGLONG_MAX;
}
/* See comment in handler.h */
......@@ -7616,15 +7602,17 @@ bool ha_innobase::check_if_incompatible_data(
return COMPATIBLE_DATA_YES;
}
struct st_mysql_storage_engine innobase_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION, &innobase_hton};
mysql_declare_plugin(innobase)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
&innobase_hton,
&innobase_storage_engine,
innobase_hton_name,
"Innobase OY",
innobase_hton_comment,
NULL, /* Plugin Init */
"Supports transactions, row-level locking, and foreign keys",
innobase_init, /* Plugin Init */
NULL, /* Plugin Deinit */
0x0100 /* 1.0 */,
0
......@@ -7632,3 +7620,4 @@ mysql_declare_plugin(innobase)
mysql_declare_plugin_end;
#endif
......@@ -33,6 +33,8 @@ typedef struct st_innobase_share {
} INNOBASE_SHARE;
struct row_prebuilt_struct;
my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name,
uint full_name_len,
ulonglong *unused);
......@@ -89,7 +91,7 @@ class ha_innobase: public handler
const char* table_type() const { return("InnoDB");}
const char *index_type(uint key_number) { return "BTREE"; }
const char** bas_ext() const;
ulong table_flags() const { return int_table_flags; }
ulonglong table_flags() const { return int_table_flags; }
ulong index_flags(uint idx, uint part, bool all_parts) const
{
return (HA_READ_NEXT |
......@@ -109,7 +111,6 @@ class ha_innobase: public handler
uint max_supported_key_length() const { return 3500; }
uint max_supported_key_part_length() const;
const key_map *keys_to_use_for_scanning() { return &key_map_full; }
bool has_transactions() { return 1;}
int open(const char *name, int mode, uint test_if_locked);
int close(void);
......@@ -147,20 +148,10 @@ class ha_innobase: public handler
int optimize(THD* thd,HA_CHECK_OPT* check_opt);
int discard_or_import_tablespace(my_bool discard);
int extra(enum ha_extra_function operation);
int reset();
int external_lock(THD *thd, int lock_type);
int transactional_table_lock(THD *thd, int lock_type);
int start_stmt(THD *thd, thr_lock_type lock_type);
int ha_retrieve_all_cols()
{
ha_set_all_bits_in_read_set();
return extra(HA_EXTRA_RETRIEVE_ALL_COLS);
}
int ha_retrieve_all_pk()
{
ha_set_primary_key_in_read_set();
return extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
}
void position(byte *record);
ha_rows records_in_range(uint inx, key_range *min_key, key_range
*max_key);
......@@ -181,7 +172,10 @@ class ha_innobase: public handler
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
void init_table_handle_for_HANDLER();
ulonglong get_auto_increment();
virtual void get_auto_increment(ulonglong offset, ulonglong increment,
ulonglong nb_desired_values,
ulonglong *first_value,
ulonglong *nb_reserved_values);
int reset_auto_increment(ulonglong value);
virtual bool get_error_message(int error, String *buf);
......@@ -207,6 +201,8 @@ class ha_innobase: public handler
int cmp_ref(const byte *ref1, const byte *ref2);
bool check_if_incompatible_data(HA_CREATE_INFO *info,
uint table_changes);
void build_template(struct row_prebuilt_struct *prebuilt, THD *thd,
TABLE *table, uint templ_type);
};
extern SHOW_VAR innodb_status_variables[];
......@@ -249,7 +245,7 @@ extern ulong srv_thread_concurrency;
extern ulong srv_commit_concurrency;
}
bool innobase_init(void);
int innobase_init(void);
int innobase_end(ha_panic_function type);
bool innobase_flush_logs(void);
uint innobase_get_free_space(void);
......
drop table if exists t1;
drop table if exists t1,t2,t1m,t1i,t2m,t2i,t4;
create table t1 (
c_id int(11) not null default '0',
org_id int(11) default null,
unique key contacts$c_id (c_id),
key contacts$org_id (org_id)
) engine=innodb;
insert into t1 values
(2,null),(120,null),(141,null),(218,7), (128,1),
(151,2),(234,2),(236,2),(243,2),(255,2),(259,2),(232,3),(235,3),(238,3),
(246,3),(253,3),(269,3),(285,3),(291,3),(293,3),(131,4),(230,4),(231,4);
create table t2 (
slai_id int(11) not null default '0',
owner_tbl int(11) default null,
owner_id int(11) default null,
sla_id int(11) default null,
inc_web int(11) default null,
inc_email int(11) default null,
inc_chat int(11) default null,
inc_csr int(11) default null,
inc_total int(11) default null,
time_billed int(11) default null,
activedate timestamp null default null,
expiredate timestamp null default null,
state int(11) default null,
sla_set int(11) default null,
unique key t2$slai_id (slai_id),
key t2$owner_id (owner_id),
key t2$sla_id (sla_id)
) engine=innodb;
insert into t2(slai_id, owner_tbl, owner_id, sla_id) values
(1,3,1,1), (3,3,10,2), (4,3,3,6), (5,3,2,5), (6,3,8,3), (7,3,9,7),
(8,3,6,8), (9,3,4,9), (10,3,5,10), (11,3,11,11), (12,3,7,12);
flush tables;
select si.slai_id
from t1 c join t2 si on
((si.owner_tbl = 3 and si.owner_id = c.org_id) or
( si.owner_tbl = 2 and si.owner_id = c.c_id))
where
c.c_id = 218 and expiredate is null;
slai_id
12
select * from t1 where org_id is null;
c_id org_id
2 NULL
120 NULL
141 NULL
select si.slai_id
from t1 c join t2 si on
((si.owner_tbl = 3 and si.owner_id = c.org_id) or
( si.owner_tbl = 2 and si.owner_id = c.c_id))
where
c.c_id = 218 and expiredate is null;
slai_id
12
drop table t1, t2;
create table t1m (a int) engine=myisam;
create table t1i (a int) engine=innodb;
create table t2m (a int) engine=myisam;
create table t2i (a int) engine=innodb;
insert into t2m values (5);
insert into t2i values (5);
select min(a) from t1m;
min(a)
NULL
select min(7) from t1m;
min(7)
NULL
select min(7) from DUAL;
min(7)
NULL
explain select min(7) from t2m join t1m;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
select min(7) from t2m join t1m;
min(7)
NULL
select max(a) from t1m;
max(a)
NULL
select max(7) from t1m;
max(7)
NULL
select max(7) from DUAL;
max(7)
NULL
explain select max(7) from t2m join t1m;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
select max(7) from t2m join t1m;
max(7)
NULL
select 1, min(a) from t1m where a=99;
1 min(a)
1 NULL
select 1, min(a) from t1m where 1=99;
1 min(a)
1 NULL
select 1, min(1) from t1m where a=99;
1 min(1)
1 NULL
select 1, min(1) from t1m where 1=99;
1 min(1)
1 NULL
select 1, max(a) from t1m where a=99;
1 max(a)
1 NULL
select 1, max(a) from t1m where 1=99;
1 max(a)
1 NULL
select 1, max(1) from t1m where a=99;
1 max(1)
1 NULL
select 1, max(1) from t1m where 1=99;
1 max(1)
1 NULL
select min(a) from t1i;
min(a)
NULL
select min(7) from t1i;
min(7)
NULL
select min(7) from DUAL;
min(7)
NULL
explain select min(7) from t2i join t1i;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2i ALL NULL NULL NULL NULL 1
1 SIMPLE t1i ALL NULL NULL NULL NULL 1
select min(7) from t2i join t1i;
min(7)
NULL
select max(a) from t1i;
max(a)
NULL
select max(7) from t1i;
max(7)
NULL
select max(7) from DUAL;
max(7)
NULL
explain select max(7) from t2i join t1i;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2i ALL NULL NULL NULL NULL 1
1 SIMPLE t1i ALL NULL NULL NULL NULL 1
select max(7) from t2i join t1i;
max(7)
NULL
select 1, min(a) from t1i where a=99;
1 min(a)
1 NULL
select 1, min(a) from t1i where 1=99;
1 min(a)
1 NULL
select 1, min(1) from t1i where a=99;
1 min(1)
1 NULL
select 1, min(1) from t1i where 1=99;
1 min(1)
1 NULL
select 1, max(a) from t1i where a=99;
1 max(a)
1 NULL
select 1, max(a) from t1i where 1=99;
1 max(a)
1 NULL
select 1, max(1) from t1i where a=99;
1 max(1)
1 NULL
select 1, max(1) from t1i where 1=99;
1 max(1)
1 NULL
explain select count(*), min(7), max(7) from t1m, t1i;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found
1 SIMPLE t1i ALL NULL NULL NULL NULL 1
select count(*), min(7), max(7) from t1m, t1i;
count(*) min(7) max(7)
0 NULL NULL
explain select count(*), min(7), max(7) from t1m, t2i;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found
1 SIMPLE t2i ALL NULL NULL NULL NULL 1
select count(*), min(7), max(7) from t1m, t2i;
count(*) min(7) max(7)
0 NULL NULL
explain select count(*), min(7), max(7) from t2m, t1i;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2m system NULL NULL NULL NULL 1
1 SIMPLE t1i ALL NULL NULL NULL NULL 1
select count(*), min(7), max(7) from t2m, t1i;
count(*) min(7) max(7)
0 NULL NULL
drop table t1m, t1i, t2m, t2i;
create table t1 (
a1 char(64), a2 char(64), b char(16), c char(16) not null, d char(16), dummy char(64) default ' '
);
insert into t1 (a1, a2, b, c, d) values
('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4'),
('d','a','a','a411','xy1'),('d','a','a','b411','xy2'),('d','a','a','c411','xy3'),('d','a','a','d411','xy4'),
('d','a','b','e412','xy1'),('d','a','b','f412','xy2'),('d','a','b','g412','xy3'),('d','a','b','h412','xy4'),
('d','b','a','i421','xy1'),('d','b','a','j421','xy2'),('d','b','a','k421','xy3'),('d','b','a','l421','xy4'),
('d','b','b','m422','xy1'),('d','b','b','n422','xy2'),('d','b','b','o422','xy3'),('d','b','b','p422','xy4'),
('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4'),
('d','a','a','a411','xy1'),('d','a','a','b411','xy2'),('d','a','a','c411','xy3'),('d','a','a','d411','xy4'),
('d','a','b','e412','xy1'),('d','a','b','f412','xy2'),('d','a','b','g412','xy3'),('d','a','b','h412','xy4'),
('d','b','a','i421','xy1'),('d','b','a','j421','xy2'),('d','b','a','k421','xy3'),('d','b','a','l421','xy4'),
('d','b','b','m422','xy1'),('d','b','b','n422','xy2'),('d','b','b','o422','xy3'),('d','b','b','p422','xy4');
create table t4 (
pk_col int auto_increment primary key, a1 char(64), a2 char(64), b char(16), c char(16) not null, d char(16), dummy char(64) default ' '
) engine=innodb;
insert into t4 (a1, a2, b, c, d, dummy) select * from t1;
create index idx12672_0 on t4 (a1);
create index idx12672_1 on t4 (a1,a2,b,c);
create index idx12672_2 on t4 (a1,a2,b);
analyze table t1;
Table Op Msg_type Msg_text
test.t1 analyze status OK
select distinct a1 from t4 where pk_col not in (1,2,3,4);
a1
a
b
c
d
drop table t1,t4;
create table t1 (
a varchar(30), b varchar(30), primary key(a), key(b)
) engine=innodb;
select distinct a from t1;
a
drop table t1;
create table t1(a int, key(a)) engine=innodb;
insert into t1 values(1);
select a, count(a) from t1 group by a with rollup;
a count(a)
1 1
NULL 1
drop table t1;
create table t1 (f1 int, f2 char(1), primary key(f1,f2)) engine=innodb;
insert into t1 values ( 1,"e"),(2,"a"),( 3,"c"),(4,"d");
alter table t1 drop primary key, add primary key (f2, f1);
explain select distinct f1 a, f1 b from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL PRIMARY 5 NULL 4 Using index; Using temporary
explain select distinct f1, f2 from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL PRIMARY 5 NULL 3 Using index for group-by; Using temporary
drop table t1;
set storage_engine=innodb;
CREATE TABLE t1 (a int, b int);
insert into t1 values (1,1),(1,2);
CREATE TABLE t2 (primary key (a)) select * from t1;
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
drop table if exists t2;
Warnings:
Note 1051 Unknown table 't2'
CREATE TEMPORARY TABLE t2 (primary key (a)) select * from t1;
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
drop table if exists t2;
Warnings:
Note 1051 Unknown table 't2'
CREATE TABLE t2 (a int, b int, primary key (a));
BEGIN;
INSERT INTO t2 values(100,100);
CREATE TABLE IF NOT EXISTS t2 (primary key (a)) select * from t1;
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
SELECT * from t2;
a b
100 100
ROLLBACK;
SELECT * from t2;
a b
100 100
TRUNCATE table t2;
INSERT INTO t2 select * from t1;
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
SELECT * from t2;
a b
drop table t2;
CREATE TEMPORARY TABLE t2 (a int, b int, primary key (a));
BEGIN;
INSERT INTO t2 values(100,100);
CREATE TEMPORARY TABLE IF NOT EXISTS t2 (primary key (a)) select * from t1;
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
SELECT * from t2;
a b
100 100
COMMIT;
BEGIN;
INSERT INTO t2 values(101,101);
CREATE TEMPORARY TABLE IF NOT EXISTS t2 (primary key (a)) select * from t1;
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
SELECT * from t2;
a b
100 100
101 101
ROLLBACK;
SELECT * from t2;
a b
100 100
TRUNCATE table t2;
INSERT INTO t2 select * from t1;
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
SELECT * from t2;
a b
drop table t1,t2;
-- source include/have_innodb.inc
--disable_warnings
drop table if exists t1;
drop table if exists t1,t2,t1m,t1i,t2m,t2i,t4;
--enable_warnings
# BUG#16798: Uninitialized row buffer reads in ref-or-null optimizer
# (repeatable only w/innodb).
create table t1 (
c_id int(11) not null default '0',
org_id int(11) default null,
unique key contacts$c_id (c_id),
key contacts$org_id (org_id)
) engine=innodb;
insert into t1 values
(2,null),(120,null),(141,null),(218,7), (128,1),
(151,2),(234,2),(236,2),(243,2),(255,2),(259,2),(232,3),(235,3),(238,3),
(246,3),(253,3),(269,3),(285,3),(291,3),(293,3),(131,4),(230,4),(231,4);
create table t2 (
slai_id int(11) not null default '0',
owner_tbl int(11) default null,
owner_id int(11) default null,
sla_id int(11) default null,
inc_web int(11) default null,
inc_email int(11) default null,
inc_chat int(11) default null,
inc_csr int(11) default null,
inc_total int(11) default null,
time_billed int(11) default null,
activedate timestamp null default null,
expiredate timestamp null default null,
state int(11) default null,
sla_set int(11) default null,
unique key t2$slai_id (slai_id),
key t2$owner_id (owner_id),
key t2$sla_id (sla_id)
) engine=innodb;
insert into t2(slai_id, owner_tbl, owner_id, sla_id) values
(1,3,1,1), (3,3,10,2), (4,3,3,6), (5,3,2,5), (6,3,8,3), (7,3,9,7),
(8,3,6,8), (9,3,4,9), (10,3,5,10), (11,3,11,11), (12,3,7,12);
flush tables;
select si.slai_id
from t1 c join t2 si on
((si.owner_tbl = 3 and si.owner_id = c.org_id) or
( si.owner_tbl = 2 and si.owner_id = c.c_id))
where
c.c_id = 218 and expiredate is null;
select * from t1 where org_id is null;
select si.slai_id
from t1 c join t2 si on
((si.owner_tbl = 3 and si.owner_id = c.org_id) or
( si.owner_tbl = 2 and si.owner_id = c.c_id))
where
c.c_id = 218 and expiredate is null;
drop table t1, t2;
#
# Bug #12882 min/max inconsistent on empty table
#
--disable_warnings
create table t1m (a int) engine=myisam;
create table t1i (a int) engine=innodb;
create table t2m (a int) engine=myisam;
create table t2i (a int) engine=innodb;
--enable_warnings
insert into t2m values (5);
insert into t2i values (5);
# test with MyISAM
select min(a) from t1m;
select min(7) from t1m;
select min(7) from DUAL;
explain select min(7) from t2m join t1m;
select min(7) from t2m join t1m;
select max(a) from t1m;
select max(7) from t1m;
select max(7) from DUAL;
explain select max(7) from t2m join t1m;
select max(7) from t2m join t1m;
select 1, min(a) from t1m where a=99;
select 1, min(a) from t1m where 1=99;
select 1, min(1) from t1m where a=99;
select 1, min(1) from t1m where 1=99;
select 1, max(a) from t1m where a=99;
select 1, max(a) from t1m where 1=99;
select 1, max(1) from t1m where a=99;
select 1, max(1) from t1m where 1=99;
# test with InnoDB
select min(a) from t1i;
select min(7) from t1i;
select min(7) from DUAL;
explain select min(7) from t2i join t1i;
select min(7) from t2i join t1i;
select max(a) from t1i;
select max(7) from t1i;
select max(7) from DUAL;
explain select max(7) from t2i join t1i;
select max(7) from t2i join t1i;
select 1, min(a) from t1i where a=99;
select 1, min(a) from t1i where 1=99;
select 1, min(1) from t1i where a=99;
select 1, min(1) from t1i where 1=99;
select 1, max(a) from t1i where a=99;
select 1, max(a) from t1i where 1=99;
select 1, max(1) from t1i where a=99;
select 1, max(1) from t1i where 1=99;
# mixed MyISAM/InnoDB test
explain select count(*), min(7), max(7) from t1m, t1i;
select count(*), min(7), max(7) from t1m, t1i;
explain select count(*), min(7), max(7) from t1m, t2i;
select count(*), min(7), max(7) from t1m, t2i;
explain select count(*), min(7), max(7) from t2m, t1i;
select count(*), min(7), max(7) from t2m, t1i;
drop table t1m, t1i, t2m, t2i;
#
# Bug #12672: primary key implcitly included in every innodb index
# (was part of group_min_max.test)
#
create table t1 (
a1 char(64), a2 char(64), b char(16), c char(16) not null, d char(16), dummy char(64) default ' '
);
insert into t1 (a1, a2, b, c, d) values
('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4'),
('d','a','a','a411','xy1'),('d','a','a','b411','xy2'),('d','a','a','c411','xy3'),('d','a','a','d411','xy4'),
('d','a','b','e412','xy1'),('d','a','b','f412','xy2'),('d','a','b','g412','xy3'),('d','a','b','h412','xy4'),
('d','b','a','i421','xy1'),('d','b','a','j421','xy2'),('d','b','a','k421','xy3'),('d','b','a','l421','xy4'),
('d','b','b','m422','xy1'),('d','b','b','n422','xy2'),('d','b','b','o422','xy3'),('d','b','b','p422','xy4'),
('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4'),
('d','a','a','a411','xy1'),('d','a','a','b411','xy2'),('d','a','a','c411','xy3'),('d','a','a','d411','xy4'),
('d','a','b','e412','xy1'),('d','a','b','f412','xy2'),('d','a','b','g412','xy3'),('d','a','b','h412','xy4'),
('d','b','a','i421','xy1'),('d','b','a','j421','xy2'),('d','b','a','k421','xy3'),('d','b','a','l421','xy4'),
('d','b','b','m422','xy1'),('d','b','b','n422','xy2'),('d','b','b','o422','xy3'),('d','b','b','p422','xy4');
--disable_warnings
create table t4 (
pk_col int auto_increment primary key, a1 char(64), a2 char(64), b char(16), c char(16) not null, d char(16), dummy char(64) default ' '
) engine=innodb;
--enable_warnings
insert into t4 (a1, a2, b, c, d, dummy) select * from t1;
create index idx12672_0 on t4 (a1);
create index idx12672_1 on t4 (a1,a2,b,c);
create index idx12672_2 on t4 (a1,a2,b);
analyze table t1;
select distinct a1 from t4 where pk_col not in (1,2,3,4);
drop table t1,t4;
#
# Bug #6142: a problem with the empty innodb table
# (was part of group_min_max.test)
#
--disable_warnings
create table t1 (
a varchar(30), b varchar(30), primary key(a), key(b)
) engine=innodb;
--enable_warnings
select distinct a from t1;
drop table t1;
#
# Bug #9798: group by with rollup
# (was part of group_min_max.test)
#
--disable_warnings
create table t1(a int, key(a)) engine=innodb;
--enable_warnings
insert into t1 values(1);
select a, count(a) from t1 group by a with rollup;
drop table t1;
#
# Bug #13293 Wrongly used index results in endless loop.
# (was part of group_min_max.test)
#
create table t1 (f1 int, f2 char(1), primary key(f1,f2)) engine=innodb;
insert into t1 values ( 1,"e"),(2,"a"),( 3,"c"),(4,"d");
alter table t1 drop primary key, add primary key (f2, f1);
explain select distinct f1 a, f1 b from t1;
explain select distinct f1, f2 from t1;
drop table t1;
#
# Test of behaviour with CREATE ... SELECT
#
set storage_engine=innodb;
CREATE TABLE t1 (a int, b int);
insert into t1 values (1,1),(1,2);
--error 1062
CREATE TABLE t2 (primary key (a)) select * from t1;
# This should give warning
drop table if exists t2;
--error 1062
CREATE TEMPORARY TABLE t2 (primary key (a)) select * from t1;
# This should give warning
drop table if exists t2;
CREATE TABLE t2 (a int, b int, primary key (a));
BEGIN;
INSERT INTO t2 values(100,100);
--error 1062
CREATE TABLE IF NOT EXISTS t2 (primary key (a)) select * from t1;
SELECT * from t2;
ROLLBACK;
SELECT * from t2;
TRUNCATE table t2;
--error 1062
INSERT INTO t2 select * from t1;
SELECT * from t2;
drop table t2;
CREATE TEMPORARY TABLE t2 (a int, b int, primary key (a));
BEGIN;
INSERT INTO t2 values(100,100);
--error 1062
CREATE TEMPORARY TABLE IF NOT EXISTS t2 (primary key (a)) select * from t1;
SELECT * from t2;
COMMIT;
BEGIN;
INSERT INTO t2 values(101,101);
--error 1062
CREATE TEMPORARY TABLE IF NOT EXISTS t2 (primary key (a)) select * from t1;
SELECT * from t2;
ROLLBACK;
SELECT * from t2;
TRUNCATE table t2;
--error 1062
INSERT INTO t2 select * from t1;
SELECT * from t2;
drop table t1,t2;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment