summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2017-06-01 11:02:32 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2017-06-02 09:36:04 +0300
commit3d615e4b1aa4f945f69d310f9a19de80fbaccdca (patch)
tree1d23c043ef41badf359760b70db84bc825a8b4a5 /sql
parent896c2c73a02c7e82299b00e66ee3ff5f85aa3adc (diff)
parent959891662dfbb0b860f0bc70e09bc2c92dab831b (diff)
downloadmariadb-git-3d615e4b1aa4f945f69d310f9a19de80fbaccdca.tar.gz
Merge branch 'bb-10.2-ext' into 10.3
This excludes MDEV-12472 (InnoDB should accept XtraDB parameters, warning that they are ignored). In other words, MariaDB 10.3 will not recognize any XtraDB-specific parameters.
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt36
-rw-r--r--sql/datadict.cc9
-rw-r--r--sql/field.cc82
-rw-r--r--sql/field.h11
-rw-r--r--sql/ha_sequence.cc89
-rw-r--r--sql/ha_sequence.h37
-rw-r--r--sql/handler.cc8
-rw-r--r--sql/innodb_priv.h1
-rw-r--r--sql/item.cc162
-rw-r--r--sql/item.h105
-rw-r--r--sql/item_cmpfunc.cc39
-rw-r--r--sql/item_cmpfunc.h101
-rw-r--r--sql/item_create.cc178
-rw-r--r--sql/item_create.h16
-rw-r--r--sql/item_func.cc212
-rw-r--r--sql/item_func.h390
-rw-r--r--sql/item_geofunc.h358
-rw-r--r--sql/item_inetfunc.h4
-rw-r--r--sql/item_jsonfunc.cc7
-rw-r--r--sql/item_jsonfunc.h29
-rw-r--r--sql/item_strfunc.cc21
-rw-r--r--sql/item_strfunc.h8
-rw-r--r--sql/item_subselect.h7
-rw-r--r--sql/item_sum.cc2
-rw-r--r--sql/item_sum.h5
-rw-r--r--sql/item_timefunc.h79
-rw-r--r--sql/item_xmlfunc.cc15
-rw-r--r--sql/log.cc2
-rw-r--r--sql/log_event.cc31
-rw-r--r--sql/log_event.h1
-rw-r--r--sql/log_event_old.cc2
-rw-r--r--sql/mdl.cc6
-rw-r--r--sql/mysqld.cc52
-rw-r--r--sql/mysqld.h21
-rw-r--r--sql/share/errmsg-utf8.txt4
-rw-r--r--sql/slave.cc6
-rw-r--r--sql/sp.cc4
-rw-r--r--sql/sp_head.cc11
-rw-r--r--sql/sp_head.h1
-rw-r--r--sql/sql_acl.cc20
-rw-r--r--sql/sql_base.cc5
-rw-r--r--sql/sql_class.cc9
-rw-r--r--sql/sql_const.h1
-rw-r--r--sql/sql_load.cc124
-rw-r--r--sql/sql_parse.cc29
-rw-r--r--sql/sql_plugin.cc30
-rw-r--r--sql/sql_plugin_services.ic26
-rw-r--r--sql/sql_select.cc99
-rw-r--r--sql/sql_sequence.cc140
-rw-r--r--sql/sql_sequence.h44
-rw-r--r--sql/sql_signal.cc14
-rw-r--r--sql/sql_table.cc57
-rw-r--r--sql/sql_type.cc390
-rw-r--r--sql/sql_type.h166
-rw-r--r--sql/sql_yacc.yy44
-rw-r--r--sql/sql_yacc_ora.yy48
-rw-r--r--sql/unireg.h4
57 files changed, 2225 insertions, 1177 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index c84867e1c4f..87e41817857 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -70,6 +70,7 @@ ENDIF()
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lex_token.h
COMMAND gen_lex_token > lex_token.h
+ DEPENDS gen_lex_token
)
ADD_DEFINITIONS(-DMYSQL_SERVER -DHAVE_EVENT_SCHEDULER)
@@ -84,39 +85,39 @@ SET (SQL_SOURCE
filesort_utils.cc
filesort.cc gstream.cc
signal_handler.cc
- handler.cc hash_filo.h
+ handler.cc
hostname.cc init.cc item.cc item_buff.cc item_cmpfunc.cc
item_create.cc item_func.cc item_geofunc.cc item_row.cc
item_strfunc.cc item_subselect.cc item_sum.cc item_timefunc.cc
key.cc log.cc lock.cc
log_event.cc rpl_record.cc rpl_reporting.cc
log_event_old.cc rpl_record_old.cc
- message.h mf_iocache.cc my_decimal.cc
+ mf_iocache.cc my_decimal.cc
mysqld.cc net_serv.cc keycaches.cc
../sql-common/client_plugin.c
- opt_range.cc opt_range.h opt_sum.cc
+ opt_range.cc opt_sum.cc
../sql-common/pack.c parse_file.cc password.c procedure.cc
protocol.cc records.cc repl_failsafe.cc rpl_filter.cc
session_tracker.cc
set_var.cc
slave.cc sp.cc sp_cache.cc sp_head.cc sp_pcontext.cc
sp_rcontext.cc spatial.cc sql_acl.cc sql_analyse.cc sql_base.cc
- sql_cache.cc sql_class.cc sql_client.cc sql_crypt.cc sql_crypt.h
+ sql_cache.cc sql_class.cc sql_client.cc sql_crypt.cc
sql_cursor.cc sql_db.cc sql_delete.cc sql_derived.cc
sql_digest.cc sql_do.cc
sql_error.cc sql_handler.cc sql_get_diagnostics.cc
sql_help.cc sql_insert.cc sql_lex.cc
sql_list.cc sql_load.cc sql_manager.cc
- sql_parse.cc sql_bootstrap.cc sql_bootstrap.h
+ sql_parse.cc sql_bootstrap.cc
sql_partition.cc sql_plugin.cc sql_prepare.cc sql_rename.cc
- debug_sync.cc debug_sync.h
+ debug_sync.cc
sql_repl.cc sql_select.cc sql_show.cc sql_state.c
group_by_handler.cc
sql_statistics.cc sql_string.cc
sql_table.cc sql_test.cc sql_trigger.cc sql_udf.cc sql_union.cc
sql_update.cc sql_view.cc strfunc.cc table.cc thr_malloc.cc
sql_time.cc tztime.cc unireg.cc item_xmlfunc.cc
- uniques.cc uniques.h
+ uniques.cc
rpl_tblmap.cc sql_binlog.cc event_scheduler.cc event_data_objects.cc
event_queue.cc event_db_repository.cc
sql_tablespace.cc events.cc ../sql-common/my_user.c
@@ -126,23 +127,23 @@ SET (SQL_SOURCE
sql_profile.cc event_parse_data.cc sql_alter.cc
sql_signal.cc rpl_handler.cc mdl.cc sql_admin.cc
transaction.cc sys_vars.cc sql_truncate.cc datadict.cc
- sql_reload.cc sql_cmd.h item_inetfunc.cc
+ sql_reload.cc item_inetfunc.cc
# added in MariaDB:
- sql_explain.h sql_explain.cc
- sql_analyze_stmt.h sql_analyze_stmt.cc
- sql_lifo_buffer.h sql_join_cache.h sql_join_cache.cc
+ sql_explain.cc
+ sql_analyze_stmt.cc
+ sql_join_cache.cc
create_options.cc multi_range_read.cc
opt_index_cond_pushdown.cc opt_subselect.cc
opt_table_elimination.cc sql_expression_cache.cc
gcalc_slicescan.cc gcalc_tools.cc
threadpool_common.cc ../sql-common/mysql_async.c
- my_apc.cc my_apc.h mf_iocache_encr.cc item_jsonfunc.cc
- my_json_writer.cc my_json_writer.h
+ my_apc.cc mf_iocache_encr.cc item_jsonfunc.cc
+ my_json_writer.cc
rpl_gtid.cc rpl_parallel.cc
- sql_type.cc sql_type.h
+ sql_type.cc
item_windowfunc.cc sql_window.cc
- sql_cte.cc sql_cte.h
+ sql_cte.cc
sql_sequence.cc sql_sequence.h ha_sequence.h
${WSREP_SOURCES}
table_cache.cc encryption.cc temporary_tables.cc
@@ -181,7 +182,7 @@ TARGET_LINK_LIBRARIES(sql ${MYSQLD_STATIC_PLUGIN_LIBS}
${LIBSYSTEMD})
IF(WIN32)
- SET(MYSQLD_SOURCE main.cc nt_servc.cc nt_servc.h message.rc)
+ SET(MYSQLD_SOURCE main.cc nt_servc.cc message.rc)
TARGET_LINK_LIBRARIES(sql psapi)
ELSE()
SET(MYSQLD_SOURCE main.cc ${DTRACE_PROBES_ALL})
@@ -340,6 +341,7 @@ ENDIF()
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lex_hash.h
COMMAND gen_lex_hash > lex_hash.h
+ DEPENDS gen_lex_hash
)
MYSQL_ADD_EXECUTABLE(mysql_tzinfo_to_sql tztime.cc COMPONENT Server)
@@ -458,7 +460,7 @@ IF(WIN32)
${CMAKE_CURRENT_BINARY_DIR}/my_bootstrap.sql
mysql_bootstrap_sql.c
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- DEPENDS ${my_bootstrap_sql}
+ DEPENDS comp_sql ${my_bootstrap_sql}
)
MYSQL_ADD_EXECUTABLE(mysql_install_db
diff --git a/sql/datadict.cc b/sql/datadict.cc
index b5a6a6794ce..edc9fe5681b 100644
--- a/sql/datadict.cc
+++ b/sql/datadict.cc
@@ -88,6 +88,12 @@ Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name,
engine_name->length= 0;
dbt= header[3];
+ if (((header[39] >> 4) & 3) == HA_CHOICE_YES)
+ {
+ DBUG_PRINT("info", ("Sequence found"));
+ *is_sequence= 1;
+ }
+
/* cannot use ha_resolve_by_legacy_type without a THD */
if (thd && dbt < DB_TYPE_FIRST_DYNAMIC)
{
@@ -99,9 +105,6 @@ Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name,
}
}
- if (((header[39] >> 4) & 3) == HA_CHOICE_YES)
- *is_sequence= 1;
-
/* read the true engine name */
{
MY_STAT state;
diff --git a/sql/field.cc b/sql/field.cc
index 577b09e948d..6320121d1c3 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -9805,61 +9805,6 @@ void Column_definition::create_length_to_internal_length_newdecimal()
}
-/**
- Convert create_field::length from number of characters to number of bytes.
-*/
-
-void Column_definition::create_length_to_internal_length(void)
-{
- switch (real_field_type()) {
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_GEOMETRY:
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_STRING:
- case MYSQL_TYPE_VARCHAR:
- create_length_to_internal_length_string();
- break;
- case MYSQL_TYPE_ENUM:
- case MYSQL_TYPE_SET:
- create_length_to_internal_length_typelib();
- break;
- case MYSQL_TYPE_BIT:
- create_length_to_internal_length_bit();
- break;
- case MYSQL_TYPE_NEWDECIMAL:
- create_length_to_internal_length_newdecimal();
- break;
-
- case MYSQL_TYPE_NULL:
- create_length_to_internal_length_null();
- break;
-
- case MYSQL_TYPE_DECIMAL:
- case MYSQL_TYPE_TINY:
- case MYSQL_TYPE_SHORT:
- case MYSQL_TYPE_INT24:
- case MYSQL_TYPE_LONG:
- case MYSQL_TYPE_LONGLONG:
- case MYSQL_TYPE_YEAR:
- case MYSQL_TYPE_FLOAT:
- case MYSQL_TYPE_DOUBLE:
- case MYSQL_TYPE_TIME:
- case MYSQL_TYPE_TIME2:
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_NEWDATE:
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_DATETIME2:
- case MYSQL_TYPE_TIMESTAMP:
- case MYSQL_TYPE_TIMESTAMP2:
- create_length_to_internal_length_simple();
- break;
- }
-}
-
-
bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name,
enum_vcol_info_type type)
@@ -10497,6 +10442,33 @@ Column_definition::Column_definition(THD *thd, Field *old_field,
/**
+ The common part for data type redefinition:
+ CREATE TABLE t1 (a INT) AS SELECT a FROM t2;
+ See Type_handler::Column_definition_redefine_stage1()
+ for data type specific code.
+*/
+void
+Column_definition::redefine_stage1_common(const Column_definition *dup_field,
+ const handler *file,
+ const Schema_specification_st *schema)
+{
+ set_handler(dup_field->type_handler());
+ default_value= dup_field->default_value;
+ charset= dup_field->charset ? dup_field->charset :
+ schema->default_table_charset;
+ length= dup_field->char_length;
+ pack_length= dup_field->pack_length;
+ key_length= dup_field->key_length;
+ decimals= dup_field->decimals;
+ unireg_check= dup_field->unireg_check;
+ flags= dup_field->flags;
+ interval= dup_field->interval;
+ vcol_info= dup_field->vcol_info;
+}
+
+
+
+/**
maximum possible character length for blob.
This method is used in Item_field::set_field to calculate
diff --git a/sql/field.h b/sql/field.h
index 10363fd855b..bfdb06984af 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -3887,7 +3887,6 @@ public:
}
Column_definition(THD *thd, Field *field, Field *orig_field);
void set_attributes(const Lex_field_type_st &type, CHARSET_INFO *cs);
- void create_length_to_internal_length(void);
void create_length_to_internal_length_null()
{
DBUG_ASSERT(length == 0);
@@ -3955,6 +3954,16 @@ public:
bool prepare_stage1_bit(THD *thd, MEM_ROOT *mem_root,
handler *file, ulonglong table_flags);
+ void redefine_stage1_common(const Column_definition *dup_field,
+ const handler *file,
+ const Schema_specification_st *schema);
+ bool redefine_stage1(const Column_definition *dup_field, const handler *file,
+ const Schema_specification_st *schema)
+ {
+ const Type_handler *handler= dup_field->type_handler();
+ return handler->Column_definition_redefine_stage1(this, dup_field,
+ file, schema);
+ }
bool prepare_stage2(handler *handler, ulonglong table_flags);
bool prepare_stage2_blob(handler *handler,
ulonglong table_flags, uint field_flags);
diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc
index a918da92be2..e0e9e2a42e7 100644
--- a/sql/ha_sequence.cc
+++ b/sql/ha_sequence.cc
@@ -48,7 +48,7 @@ handlerton *sql_sequence_hton;
*/
ha_sequence::ha_sequence(handlerton *hton, TABLE_SHARE *share)
- :handler(hton, share), sequence_locked(0)
+ :handler(hton, share), write_locked(0)
{
sequence= share->sequence;
DBUG_ASSERT(share->sequence);
@@ -179,7 +179,7 @@ int ha_sequence::create(const char *name, TABLE *form,
@retval != 0 Failure
NOTES:
- sequence_locked is set if we are called from SEQUENCE::next_value
+ write_locked is set if we are called from SEQUENCE::next_value
In this case the mutex is already locked and we should not update
the sequence with 'buf' as the sequence object is already up to date.
*/
@@ -187,6 +187,8 @@ int ha_sequence::create(const char *name, TABLE *form,
int ha_sequence::write_row(uchar *buf)
{
int error;
+ sequence_definition tmp_seq;
+ bool sequence_locked;
DBUG_ENTER("ha_sequence::write_row");
DBUG_ASSERT(table->record[0] == buf);
@@ -199,23 +201,38 @@ int ha_sequence::write_row(uchar *buf)
if (unlikely(sequence->initialized != SEQUENCE::SEQ_READY_TO_USE))
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
- /*
- User tries to write a row
- - Check that the new row is an accurate object
- - Update the first row in the table
- */
+ sequence_locked= write_locked;
+ if (!write_locked) // If not from next_value()
+ {
+ /*
+ User tries to write a full row directly to the sequence table with
+ INSERT or LOAD DATA.
+
+ - Get an exclusive lock for the table. This is needed to ensure that
+ we excute all full inserts (same as ALTER SEQUENCE) in same order
+ on master and slaves
+ - Check that we are only using one table.
+ This is to avoid deadlock problems when upgrading lock to exlusive.
+ - Check that the new row is an accurate SEQUENCE object
+ */
- sequence_definition tmp_seq;
- tmp_seq.read_fields(table);
- if (tmp_seq.check_and_adjust())
- DBUG_RETURN(HA_ERR_SEQUENCE_INVALID_DATA);
+ THD *thd= table->in_use;
+ if (thd->lock->table_count != 1)
+ DBUG_RETURN(ER_WRONG_INSERT_INTO_SEQUENCE);
+ if (thd->mdl_context.upgrade_shared_lock(table->mdl_ticket, MDL_EXCLUSIVE,
+ thd->variables.lock_wait_timeout))
+ DBUG_RETURN(ER_LOCK_WAIT_TIMEOUT);
- /*
- Lock sequence to ensure that no one can come in between
- while sequence, table and binary log are updated.
- */
- if (!sequence_locked) // If not from next_value()
- sequence->lock();
+ tmp_seq.read_fields(table);
+ if (tmp_seq.check_and_adjust(0))
+ DBUG_RETURN(HA_ERR_SEQUENCE_INVALID_DATA);
+
+ /*
+ Lock sequence to ensure that no one can come in between
+ while sequence, table and binary log are updated.
+ */
+ sequence->write_lock(table);
+ }
if (!(error= file->update_first_row(buf)))
{
@@ -230,40 +247,7 @@ int ha_sequence::write_row(uchar *buf)
sequence->all_values_used= 0;
if (!sequence_locked)
- sequence->unlock();
- DBUG_RETURN(error);
-}
-
-
-int ha_sequence::update_row(const uchar *old_data, const uchar *new_data)
-{
- int error;
- sequence_definition tmp_seq;
- DBUG_ENTER("ha_sequence::update_row");
- DBUG_ASSERT(new_data == table->record[0]);
-
- row_already_logged= 0;
-
- tmp_seq.read_fields(table);
- if (tmp_seq.check_and_adjust())
- DBUG_RETURN(HA_ERR_SEQUENCE_INVALID_DATA);
-
- /*
- Lock sequence to ensure that no one can come in between
- while sequence, table and binary log is updated.
- */
- sequence->lock();
- if (!(error= file->update_row(old_data, new_data)))
- {
- sequence->copy(&tmp_seq);
- rows_changed++;
- /* We have to do the logging while we hold the sequence mutex */
- error= binlog_log_row(table, old_data, new_data,
- Update_rows_log_event::binlog_row_logging_function);
- row_already_logged= 1;
- }
- sequence->all_values_used= 0;
- sequence->unlock();
+ sequence->write_unlock(table);
DBUG_RETURN(error);
}
@@ -346,6 +330,9 @@ void ha_sequence::print_error(int error, myf errflag)
case HA_ERR_WRONG_COMMAND:
my_error(ER_ILLEGAL_HA, MYF(0), "SEQUENCE", sequence_db, sequence_name);
DBUG_VOID_RETURN;
+ case ER_WRONG_INSERT_INTO_SEQUENCE:
+ my_error(error, MYF(0));
+ DBUG_VOID_RETURN;
}
file->print_error(error, errflag);
DBUG_VOID_RETURN;
diff --git a/sql/ha_sequence.h b/sql/ha_sequence.h
index f753d038114..fd9da05b591 100644
--- a/sql/ha_sequence.h
+++ b/sql/ha_sequence.h
@@ -60,6 +60,9 @@ private:
SEQUENCE *sequence; /* From table_share->sequence */
public:
+ /* Set when handler is write locked */
+ bool write_locked;
+
ha_sequence(handlerton *hton, TABLE_SHARE *share);
~ha_sequence();
@@ -69,9 +72,10 @@ public:
HA_CREATE_INFO *create_info);
handler *clone(const char *name, MEM_ROOT *mem_root);
int write_row(uchar *buf);
- int update_row(const uchar *old_data, const uchar *new_data);
Table_flags table_flags() const;
- /* One can't delete from sequence engine */
+ /* One can't update or delete from sequence engine */
+ int update_row(const uchar *old_data, const uchar *new_data)
+ { return HA_ERR_WRONG_COMMAND; }
int delete_row(const uchar *buf)
{ return HA_ERR_WRONG_COMMAND; }
/* One can't delete from sequence engine */
@@ -88,16 +92,36 @@ public:
/* For ALTER ONLINE TABLE */
bool check_if_incompatible_data(HA_CREATE_INFO *create_info,
uint table_changes);
+ void write_lock() { write_locked= 1;}
+ void unlock() { write_locked= 0; }
+ bool is_locked() { return write_locked; }
/* Functions that are directly mapped to the underlying handler */
int rnd_init(bool scan)
{ return file->rnd_init(scan); }
+ /*
+ We need to have a lock here to protect engines like MyISAM from
+ simultaneous read and write. For sequence's this is not critical
+ as this function is used extremely seldom.
+ */
int rnd_next(uchar *buf)
- { return file->rnd_next(buf); }
+ {
+ int error;
+ table->s->sequence->read_lock(table);
+ error= file->rnd_next(buf);
+ table->s->sequence->read_unlock(table);
+ return error;
+ }
int rnd_end()
{ return file->rnd_end(); }
int rnd_pos(uchar *buf, uchar *pos)
- { return file->rnd_pos(buf, pos); }
+ {
+ int error;
+ table->s->sequence->read_lock(table);
+ error= file->rnd_pos(buf, pos);
+ table->s->sequence->read_unlock(table);
+ return error;
+ }
void position(const uchar *record)
{ return file->position(record); }
const char *table_type() const
@@ -128,6 +152,8 @@ public:
{ return file->check_and_repair(thd); }
bool is_crashed() const
{ return file->is_crashed(); }
+ void column_bitmaps_signal()
+ { return file->column_bitmaps_signal(); }
/* New methods */
void register_original_handler(handler *file_arg)
@@ -135,8 +161,5 @@ public:
file= file_arg;
init(); /* Update cached_table_flags */
}
-
- /* To inform handler that sequence is already locked by called */
- bool sequence_locked;
};
#endif
diff --git a/sql/handler.cc b/sql/handler.cc
index a5832be30e1..9b66801b109 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -6041,7 +6041,13 @@ int handler::update_first_row(uchar *new_data)
{
int end_error;
if (!(error= ha_rnd_next(table->record[1])))
- error= update_row(table->record[1], new_data);
+ {
+ /*
+ We have to do the memcmp as otherwise we may get error 169 from InnoDB
+ */
+ if (memcmp(table->record[0], table->record[1], table->s->reclength))
+ error= update_row(table->record[1], new_data);
+ }
end_error= ha_rnd_end();
if (!error)
error= end_error;
diff --git a/sql/innodb_priv.h b/sql/innodb_priv.h
index ec85aa352f8..27aa9ac8645 100644
--- a/sql/innodb_priv.h
+++ b/sql/innodb_priv.h
@@ -28,6 +28,7 @@ void localtime_to_TIME(MYSQL_TIME *to, struct tm *from);
uint strconvert(CHARSET_INFO *from_cs, const char *from, uint from_length,
CHARSET_INFO *to_cs, char *to, uint to_length,
uint *errors);
+
void sql_print_error(const char *format, ...);
#define thd_binlog_pos(X, Y, Z) mysql_bin_log_commit_pos(X, Z, Y)
diff --git a/sql/item.cc b/sql/item.cc
index a9c7604d154..f4236eee013 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -311,6 +311,56 @@ bool Item::is_null_from_temporal()
}
+longlong Item::val_int_from_str(int *error)
+{
+ char buff[MAX_FIELD_WIDTH];
+ String tmp(buff,sizeof(buff), &my_charset_bin), *res;
+
+ /*
+ For a string result, we must first get the string and then convert it
+ to a longlong
+ */
+ if (!(res= val_str(&tmp)))
+ {
+ *error= 0;
+ return 0;
+ }
+ Converter_strtoll10_with_warn cnv(NULL, Warn_filter_all(),
+ res->charset(), res->ptr(), res->length());
+ *error= cnv.error();
+ return cnv.result();
+}
+
+
+longlong Item::val_int_signed_typecast_from_str()
+{
+ int error;
+ longlong value= val_int_from_str(&error);
+ if (!null_value && value < 0 && error == 0)
+ push_note_converted_to_negative_complement(current_thd);
+ return value;
+}
+
+
+longlong Item::val_int_unsigned_typecast_from_str()
+{
+ int error;
+ longlong value= val_int_from_str(&error);
+ if (!null_value && error < 0)
+ push_note_converted_to_positive_complement(current_thd);
+ return value;
+}
+
+
+longlong Item::val_int_unsigned_typecast_from_int()
+{
+ longlong value= val_int();
+ if (!null_value && unsigned_flag == 0 && value < 0)
+ push_note_converted_to_positive_complement(current_thd);
+ return value;
+}
+
+
String *Item::val_string_from_date(String *str)
{
MYSQL_TIME ltime;
@@ -428,6 +478,18 @@ longlong Item::val_int_from_decimal()
return result;
}
+
+longlong Item::val_int_unsigned_typecast_from_decimal()
+{
+ longlong result;
+ my_decimal tmp, *dec= val_decimal(&tmp);
+ if (null_value)
+ return 0;
+ my_decimal2int(E_DEC_FATAL_ERROR, dec, 1, &result);
+ return result;
+}
+
+
int Item::save_time_in_field(Field *field, bool no_conversions)
{
MYSQL_TIME ltime;
@@ -997,6 +1059,75 @@ bool Item::check_cols(uint c)
return 0;
}
+
+bool Item::check_type_or_binary(const char *opname,
+ const Type_handler *expect) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler == expect ||
+ (handler->is_general_purpose_string_type() &&
+ collation.collation == &my_charset_bin))
+ return false;
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ handler->name().ptr(), opname);
+ return true;
+}
+
+
+bool Item::check_type_general_purpose_string(const char *opname) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler->is_general_purpose_string_type())
+ return false;
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ handler->name().ptr(), opname);
+ return true;
+}
+
+
+bool Item::check_type_traditional_scalar(const char *opname) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler->is_traditional_type() && handler->is_scalar_type())
+ return false;
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ handler->name().ptr(), opname);
+ return true;
+}
+
+
+bool Item::check_type_can_return_int(const char *opname) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler->can_return_int())
+ return false;
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ handler->name().ptr(), opname);
+ return true;
+}
+
+
+bool Item::check_type_can_return_real(const char *opname) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler->can_return_real())
+ return false;
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ handler->name().ptr(), opname);
+ return true;
+}
+
+
+bool Item::check_type_scalar(const char *opname) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler->is_scalar_type())
+ return false;
+ my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
+ return true;
+}
+
+
void Item::set_name(THD *thd, const char *str, uint length, CHARSET_INFO *cs)
{
if (!length)
@@ -1563,7 +1694,9 @@ Item_splocal::Item_splocal(THD *thd, const LEX_CSTRING *sp_var_name,
bool Item_splocal::fix_fields(THD *thd, Item **ref)
{
- return fix_fields_from_item(thd, ref, thd->spcont->get_item(m_var_idx));
+ Item *item= thd->spcont->get_item(m_var_idx);
+ set_handler(item->type_handler());
+ return fix_fields_from_item(thd, ref, item);
}
@@ -3489,7 +3622,16 @@ Item_param::Item_param(THD *thd, const LEX_CSTRING *name_arg,
uint pos_in_query_arg, uint len_in_query_arg):
Item_basic_value(thd),
Rewritable_query_parameter(pos_in_query_arg, len_in_query_arg),
- Type_handler_hybrid_field_type(&type_handler_varchar),
+ /*
+ Set handler to type_handler_null. Its data type test methods such as:
+ - is_scalar_type()
+ - can_return_int()
+ - can_return_real(),
+ - is_general_purpose_string_type()
+ all return "true". This is needed to avoid any "illegal parameter type"
+ errors in Item::check_type_xxx() at PS prepare time.
+ */
+ Type_handler_hybrid_field_type(&type_handler_null),
state(NO_VALUE),
/* Don't pretend to be a literal unless value for this item is set. */
item_type(PARAM_ITEM),
@@ -6656,6 +6798,22 @@ void Item_hex_hybrid::print(String *str, enum_query_type query_type)
}
+uint Item_hex_hybrid::decimal_precision() const
+{
+ switch (max_length) {// HEX DEC
+ case 0: // ---- ---
+ case 1: return 3; // 0xFF 255
+ case 2: return 5; // 0xFFFF 65535
+ case 3: return 8; // 0xFFFFFF 16777215
+ case 4: return 10; // 0xFFFFFFFF 4294967295
+ case 5: return 13; // 0xFFFFFFFFFF 1099511627775
+ case 6: return 15; // 0xFFFFFFFFFFFF 281474976710655
+ case 7: return 17; // 0xFFFFFFFFFFFFFF 72057594037927935
+ }
+ return 20; // 0xFFFFFFFFFFFFFFFF 18446744073709551615
+}
+
+
void Item_hex_string::print(String *str, enum_query_type query_type)
{
str->append("X'");
diff --git a/sql/item.h b/sql/item.h
index 2de5214c99e..76ce4aa935f 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -337,19 +337,6 @@ typedef struct replace_equal_field_arg
struct st_join_table *context_tab;
} REPLACE_EQUAL_FIELD_ARG;
-
-class Load_data_out_param
-{
-public:
- Load_data_out_param() { }
- virtual ~Load_data_out_param() { }
- virtual void load_data_set_null_value(CHARSET_INFO *cs) = 0;
- virtual void load_data_set_value(const char *str, uint length,
- CHARSET_INFO *cs) = 0;
- virtual void load_data_print(THD *thd, String *str) = 0;
-};
-
-
class Settable_routine_parameter
{
public:
@@ -567,6 +554,15 @@ protected:
SEL_TREE *get_mm_tree_for_const(RANGE_OPT_PARAM *param);
/**
+ Create a field based on the exact data type handler.
+ */
+ Field *create_table_field_from_handler(TABLE *table)
+ {
+ const Type_handler *h= type_handler();
+ return h->make_and_init_table_field(&name, Record_addr(maybe_null),
+ *this, table);
+ }
+ /**
Create a field based on field_type of argument.
This is used to create a field for
- IFNULL(x,something)
@@ -582,7 +578,7 @@ protected:
return h->make_and_init_table_field(&name, Record_addr(maybe_null),
*this, table);
}
- Field *create_tmp_field(bool group, TABLE *table, uint convert_int_length);
+ Field *create_tmp_field_int(TABLE *table, uint convert_int_length);
void push_note_converted_to_negative_complement(THD *thd);
void push_note_converted_to_positive_complement(THD *thd);
@@ -880,14 +876,24 @@ public:
to negative complements.
Values of non-integer data types are adjusted to the SIGNED range.
*/
- virtual longlong val_int_signed_typecast();
+ virtual longlong val_int_signed_typecast()
+ {
+ return cast_to_int_type_handler()->Item_val_int_signed_typecast(this);
+ }
+ longlong val_int_signed_typecast_from_str();
/**
Get a value for CAST(x AS UNSIGNED).
Negative signed integer values are converted
to positive complements.
Values of non-integer data types are adjusted to the UNSIGNED range.
*/
- virtual longlong val_int_unsigned_typecast();
+ virtual longlong val_int_unsigned_typecast()
+ {
+ return cast_to_int_type_handler()->Item_val_int_unsigned_typecast(this);
+ }
+ longlong val_int_unsigned_typecast_from_decimal();
+ longlong val_int_unsigned_typecast_from_int();
+ longlong val_int_unsigned_typecast_from_str();
/*
This is just a shortcut to avoid the cast. You should still use
unsigned_flag to check the sign of the item.
@@ -1200,6 +1206,10 @@ public:
return const_item() ? type_handler()->Item_datetime_precision(this) :
MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
}
+ virtual longlong val_int_min() const
+ {
+ return LONGLONG_MIN;
+ }
/*
Returns true if this is constant (during query execution, i.e. its value
will not change until next fix_fields) and its value is known.
@@ -1622,18 +1632,25 @@ public:
}
virtual Item** addr(uint i) { return 0; }
virtual bool check_cols(uint c);
+ bool check_type_traditional_scalar(const char *opname) const;
+ bool check_type_scalar(const char *opname) const;
+ bool check_type_or_binary(const char *opname, const Type_handler *handler) const;
+ bool check_type_general_purpose_string(const char *opname) const;
+ bool check_type_can_return_int(const char *opname) const;
+ bool check_type_can_return_real(const char *opname) const;
// It is not row => null inside is impossible
virtual bool null_inside() { return 0; }
// used in row subselects to get value of elements
virtual void bring_value() {}
+ const Type_handler *type_handler_long_or_longlong() const
+ {
+ return Type_handler::type_handler_long_or_longlong(max_char_length());
+ }
+
virtual Field *create_tmp_field(bool group, TABLE *table)
{
- /*
- Values with MY_INT32_NUM_DECIMAL_DIGITS digits may or may not fit into
- Field_long : make them Field_longlong.
- */
- return create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS - 2);
+ return tmp_table_field_from_field_type(table);
}
virtual Item_field *field_for_view_update() { return 0; }
@@ -1700,14 +1717,6 @@ public:
delete this;
}
- virtual Load_data_out_param *get_load_data_out_param() { return 0; }
- Load_data_out_param *get_load_data_out_param_or_error()
- {
- Load_data_out_param *res= get_load_data_out_param();
- if (!res)
- my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), full_name());
- return res;
- }
virtual Item_splocal *get_item_splocal() { return 0; }
virtual Rewritable_query_parameter *get_rewritable_query_parameter()
{ return 0; }
@@ -2269,6 +2278,18 @@ public:
bool append_for_log(THD *thd, String *str);
Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
+
+ /*
+ Override the inherited create_field_for_create_select(),
+ because we want to preserve the exact data type for:
+ DECLARE a1 INT;
+ DECLARE a2 TYPE OF t1.a2;
+ CREATE TABLE t1 AS SELECT a1, a2;
+ The inherited implementation would create a column
+ based on result_type(), which is less exact.
+ */
+ Field *create_field_for_create_select(TABLE *table)
+ { return tmp_table_field_from_field_type(table); }
};
@@ -2300,23 +2321,6 @@ public:
:Item_splocal(thd, sp_var_name, sp_var_idx, MYSQL_TYPE_NULL,
pos_in_q, len_in_q)
{ }
- bool fix_fields(THD *thd, Item **it)
- {
- if (Item_splocal::fix_fields(thd, it))
- return true;
- set_handler(this_item()->type_handler());
- return false;
- }
- /*
- Override the inherited create_field_for_create_select(),
- because we want to preserve the exact data type for:
- DECLARE a t1.a%TYPE;
- CREATE TABLE t1 AS SELECT a;
- The inherited implementation would create a column
- based on result_type(), which is less exact.
- */
- Field *create_field_for_create_select(TABLE *table)
- { return tmp_table_field_from_field_type(table); }
};
@@ -3231,17 +3235,13 @@ public:
Item_int(THD *thd, const char *str_arg, uint length=64);
enum Type type() const { return INT_ITEM; }
const Type_handler *type_handler() const
- {
- // The same condition is repeated in Item::create_tmp_field()
- if (max_length > MY_INT32_NUM_DECIMAL_DIGITS - 2)
- return &type_handler_longlong;
- return &type_handler_long;
- }
+ { return type_handler_long_or_longlong(); }
Field *create_tmp_field(bool group, TABLE *table)
{ return tmp_table_field_from_field_type(table); }
Field *create_field_for_create_select(TABLE *table)
{ return tmp_table_field_from_field_type(table); }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
+ longlong val_int_min() const { DBUG_ASSERT(fixed == 1); return value; }
double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
my_decimal *val_decimal(my_decimal *);
String *val_str(String*);
@@ -3800,6 +3800,7 @@ public:
Item_hex_hybrid(THD *thd): Item_hex_constant(thd) {}
Item_hex_hybrid(THD *thd, const char *str, uint str_length):
Item_hex_constant(thd, str, str_length) {}
+ uint decimal_precision() const;
double val_real()
{
DBUG_ASSERT(fixed == 1);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 717a65489f6..07b5f90bf69 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -3738,30 +3738,6 @@ bool Predicant_to_list_comparator::make_unique_cmp_items(THD *thd,
}
-cmp_item* cmp_item::get_comparator(Item_result type, Item *warn_item,
- CHARSET_INFO *cs)
-{
- switch (type) {
- case STRING_RESULT:
- return new cmp_item_sort_string(cs);
- case INT_RESULT:
- return new cmp_item_int;
- case REAL_RESULT:
- return new cmp_item_real;
- case ROW_RESULT:
- return new cmp_item_row;
- case DECIMAL_RESULT:
- return new cmp_item_decimal;
- case TIME_RESULT:
- DBUG_ASSERT(warn_item);
- return warn_item->field_type() == MYSQL_TYPE_TIME ?
- (cmp_item *) new cmp_item_time() :
- (cmp_item *) new cmp_item_datetime();
- }
- return 0; // to satisfy compiler :)
-}
-
-
cmp_item* cmp_item_sort_string::make_same()
{
return new cmp_item_sort_string_in_static(cmp_charset);
@@ -3814,7 +3790,8 @@ bool cmp_item_row::alloc_comparators(THD *thd, uint cols)
void cmp_item_row::store_value(Item *item)
{
DBUG_ENTER("cmp_item_row::store_value");
- if (!alloc_comparators(current_thd, item->cols()))
+ THD *thd= current_thd;
+ if (!alloc_comparators(thd, item->cols()))
{
item->bring_value();
item->null_value= 0;
@@ -3836,10 +3813,11 @@ void cmp_item_row::store_value(Item *item)
- predicate0, value00, value01
- predicate1, value10, value11
*/
- DBUG_ASSERT(item->element_index(i)->cmp_type() != TIME_RESULT);
+ Item *elem= item->element_index(i);
+ const Type_handler *handler= elem->type_handler();
+ DBUG_ASSERT(elem->cmp_type() != TIME_RESULT);
if (!(comparators[i]=
- cmp_item::get_comparator(item->element_index(i)->result_type(), 0,
- item->element_index(i)->collation.collation)))
+ handler->make_cmp_item(thd, elem->collation.collation)))
break; // new failed
}
comparators[i]->store_value(item->element_index(i));
@@ -5519,6 +5497,7 @@ Item_func_regexp_instr::fix_length_and_dec()
re.init(cmp_collation.collation, 0, 1);
re.fix_owner(this, args[0], args[1]);
+ max_length= MY_INT32_NUM_DECIMAL_DIGITS; // See also Item_func_locate
}
@@ -6550,8 +6529,8 @@ longlong Item_equal::val_int()
void Item_equal::fix_length_and_dec()
{
Item *item= get_first(NO_PARTICULAR_TAB, NULL);
- eval_item= cmp_item::get_comparator(item->cmp_type(), item,
- item->collation.collation);
+ const Type_handler *handler= item->type_handler();
+ eval_item= handler->make_cmp_item(current_thd, item->collation.collation);
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 6d604b3a2fc..e21e074a7a3 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -204,6 +204,7 @@ public:
Item_bool_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
Item_bool_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { }
Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
+ const Type_handler *type_handler() const { return &type_handler_long; }
bool is_bool_type() { return true; }
virtual CHARSET_INFO *compare_collation() const { return NULL; }
void fix_length_and_dec() { decimals=0; max_length=1; }
@@ -480,12 +481,14 @@ class Item_bool_rowready_func2 :public Item_bool_func2_with_rev
{
protected:
Arg_comparator cmp;
+ bool check_arguments() const
+ {
+ return check_argument_types_like_args0();
+ }
public:
Item_bool_rowready_func2(THD *thd, Item *a, Item *b):
Item_bool_func2_with_rev(thd, a, b), cmp(tmp_arg, tmp_arg + 1)
- {
- allowed_arg_cols= 0; // Fetch this value from first argument
- }
+ { }
void print(String *str, enum_query_type query_type)
{
Item_func::print_op(str, query_type);
@@ -919,13 +922,13 @@ public:
};
-class Item_func_strcmp :public Item_int_func
+class Item_func_strcmp :public Item_long_func
{
String value1, value2;
DTCollation cmp_collation;
public:
Item_func_strcmp(THD *thd, Item *a, Item *b):
- Item_int_func(thd, a, b) {}
+ Item_long_func(thd, a, b) {}
longlong val_int();
uint decimal_precision() const { return 1; }
const char *func_name() const { return "strcmp"; }
@@ -946,17 +949,19 @@ struct interval_range
my_decimal dec;
};
-class Item_func_interval :public Item_int_func
+class Item_func_interval :public Item_long_func
{
Item_row *row;
bool use_decimal_comparison;
interval_range *intervals;
-public:
- Item_func_interval(THD *thd, Item_row *a):
- Item_int_func(thd, a), row(a), intervals(0)
+ bool check_arguments() const
{
- allowed_arg_cols= 0; // Fetch this value from first argument
+ return check_argument_types_like_args0();
}
+public:
+ Item_func_interval(THD *thd, Item_row *a):
+ Item_long_func(thd, a), row(a), intervals(0)
+ { }
longlong val_int();
void fix_length_and_dec();
const char *func_name() const { return "interval"; }
@@ -1466,8 +1471,6 @@ public:
virtual int cmp(Item *item)= 0;
// for optimized IN with row
virtual int compare(cmp_item *item)= 0;
- static cmp_item* get_comparator(Item_result type, Item * warn_item,
- CHARSET_INFO *cs);
virtual cmp_item *make_same()= 0;
virtual void store_value_by_template(THD *thd, cmp_item *tmpl, Item *item)
{
@@ -2118,6 +2121,10 @@ class Item_func_in :public Item_func_opt_neg,
return true;
}
bool prepare_predicant_and_values(THD *thd, uint *found_types);
+ bool check_arguments() const
+ {
+ return check_argument_types_like_args0();
+ }
protected:
SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
Field *field, Item *value);
@@ -2142,9 +2149,7 @@ public:
Predicant_to_list_comparator(thd, arg_count - 1),
array(0), have_null(0),
arg_types_compatible(FALSE)
- {
- allowed_arg_cols= 0; // Fetch this value from first argument
- }
+ { }
longlong val_int();
bool fix_fields(THD *, Item **);
void fix_length_and_dec();
@@ -2661,12 +2666,19 @@ public:
};
-class Item_func_regexp_instr :public Item_int_func
+/*
+ In the corner case REGEXP_INSTR could return (2^32 + 1),
+ which would not fit into Item_long_func range.
+ But string lengths are limited with max_allowed_packet,
+ which cannot be bigger than 1024*1024*1024.
+*/
+class Item_func_regexp_instr :public Item_long_func
{
Regexp_processor_pcre re;
DTCollation cmp_collation;
public:
- Item_func_regexp_instr(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b)
+ Item_func_regexp_instr(THD *thd, Item *a, Item *b)
+ :Item_long_func(thd, a, b)
{}
void cleanup()
{
@@ -3130,6 +3142,61 @@ public:
{ return get_item_copy<Item_func_dyncol_exists>(thd, mem_root, this); }
};
+
+class Item_func_cursor_bool_attr: public Item_bool_func, public Cursor_ref
+{
+public:
+ Item_func_cursor_bool_attr(THD *thd, const LEX_CSTRING *name, uint offset)
+ :Item_bool_func(thd), Cursor_ref(name, offset)
+ { }
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), arg, VCOL_SESSION_FUNC);
+ }
+ void print(String *str, enum_query_type query_type)
+ {
+ Cursor_ref::print_func(str, func_name());
+ }
+};
+
+
+class Item_func_cursor_isopen: public Item_func_cursor_bool_attr
+{
+public:
+ Item_func_cursor_isopen(THD *thd, const LEX_CSTRING *name, uint offset)
+ :Item_func_cursor_bool_attr(thd, name, offset) { }
+ const char *func_name() const { return "%ISOPEN"; }
+ longlong val_int();
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_cursor_isopen>(thd, mem_root, this); }
+};
+
+
+class Item_func_cursor_found: public Item_func_cursor_bool_attr
+{
+public:
+ Item_func_cursor_found(THD *thd, const LEX_CSTRING *name, uint offset)
+ :Item_func_cursor_bool_attr(thd, name, offset) { maybe_null= true; }
+ const char *func_name() const { return "%FOUND"; }
+ longlong val_int();
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_cursor_found>(thd, mem_root, this); }
+};
+
+
+class Item_func_cursor_notfound: public Item_func_cursor_bool_attr
+{
+public:
+ Item_func_cursor_notfound(THD *thd, const LEX_CSTRING *name, uint offset)
+ :Item_func_cursor_bool_attr(thd, name, offset) { maybe_null= true; }
+ const char *func_name() const { return "%NOTFOUND"; }
+ longlong val_int();
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_cursor_notfound>(thd, mem_root, this); }
+};
+
+
+
inline bool is_cond_or(Item *item)
{
if (item->type() != Item::COND_ITEM)
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 60b39035d1b..8ab45e5dbe1 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -38,68 +38,6 @@
/*
=============================================================================
- HELPER FUNCTIONS
-=============================================================================
-*/
-
-static const char* item_name(Item *a, String *str)
-{
- if (a->name.str)
- return a->name.str;
- str->length(0);
- a->print(str, QT_ORDINARY);
- return str->c_ptr_safe();
-}
-
-
-static void wrong_precision_error(uint errcode, Item *a,
- ulonglong number, uint maximum)
-{
- char buff[1024];
- String buf(buff, sizeof(buff), system_charset_info);
-
- my_error(errcode, MYF(0), number, item_name(a, &buf), maximum);
-}
-
-
-/**
- Get precision and scale for a declaration
-
- return
- 0 ok
- 1 error
-*/
-
-bool get_length_and_scale(ulonglong length, ulonglong decimals,
- ulong *out_length, uint *out_decimals,
- uint max_precision, uint max_scale,
- Item *a)
-{
- if (length > (ulonglong) max_precision)
- {
- wrong_precision_error(ER_TOO_BIG_PRECISION, a, length, max_precision);
- return 1;
- }
- if (decimals > (ulonglong) max_scale)
- {
- wrong_precision_error(ER_TOO_BIG_SCALE, a, decimals, max_scale);
- return 1;
- }
-
- *out_decimals= (uint) decimals;
- my_decimal_trim(&length, out_decimals);
- *out_length= (ulong) length;
-
- if (*out_length < *out_decimals)
- {
- my_error(ER_M_BIGGER_THAN_D, MYF(0), "");
- return 1;
- }
- return 0;
-}
-
-/*
-=============================================================================
LOCAL DECLARATIONS
=============================================================================
*/
@@ -5684,11 +5622,9 @@ Create_func_length Create_func_length::s_singleton;
Item*
Create_func_length::create_1_arg(THD *thd, Item *arg1)
{
-#if 0 // Not yet
if (thd->variables.sql_mode & MODE_ORACLE)
return new (thd->mem_root) Item_func_char_length(thd, arg1);
else
-#endif
return new (thd->mem_root) Item_func_octet_length(thd, arg1);
}
@@ -6978,6 +6914,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("LCASE") }, BUILDER(Create_func_lcase)},
{ { C_STRING_WITH_LEN("LEAST") }, BUILDER(Create_func_least)},
{ { C_STRING_WITH_LEN("LENGTH") }, BUILDER(Create_func_length)},
+ { { C_STRING_WITH_LEN("LENGTHB") }, BUILDER(Create_func_octet_length)},
#ifndef DBUG_OFF
{ { C_STRING_WITH_LEN("LIKE_RANGE_MIN") }, BUILDER(Create_func_like_range_min)},
{ { C_STRING_WITH_LEN("LIKE_RANGE_MAX") }, BUILDER(Create_func_like_range_max)},
@@ -7271,114 +7208,6 @@ find_qualified_function_builder(THD *thd)
}
-Item *
-create_func_cast(THD *thd, Item *a, Cast_target cast_type,
- const char *c_len, const char *c_dec,
- CHARSET_INFO *cs)
-{
- Item *UNINIT_VAR(res);
- ulonglong length= 0, decimals= 0;
- int error;
-
- /*
- We don't have to check for error here as sql_yacc.yy has guaranteed
- that the values are in range of ulonglong
- */
- if (c_len)
- length= (ulonglong) my_strtoll10(c_len, NULL, &error);
- if (c_dec)
- decimals= (ulonglong) my_strtoll10(c_dec, NULL, &error);
-
- switch (cast_type) {
- case ITEM_CAST_BINARY:
- res= new (thd->mem_root) Item_func_binary(thd, a);
- break;
- case ITEM_CAST_SIGNED_INT:
- res= new (thd->mem_root) Item_func_signed(thd, a);
- break;
- case ITEM_CAST_UNSIGNED_INT:
- res= new (thd->mem_root) Item_func_unsigned(thd, a);
- break;
- case ITEM_CAST_DATE:
- res= new (thd->mem_root) Item_date_typecast(thd, a);
- break;
- case ITEM_CAST_TIME:
- if (decimals > MAX_DATETIME_PRECISION)
- {
- wrong_precision_error(ER_TOO_BIG_PRECISION, a, decimals,
- MAX_DATETIME_PRECISION);
- return 0;
- }
- res= new (thd->mem_root) Item_time_typecast(thd, a, (uint) decimals);
- break;
- case ITEM_CAST_DATETIME:
- if (decimals > MAX_DATETIME_PRECISION)
- {
- wrong_precision_error(ER_TOO_BIG_PRECISION, a, decimals,
- MAX_DATETIME_PRECISION);
- return 0;
- }
- res= new (thd->mem_root) Item_datetime_typecast(thd, a, (uint) decimals);
- break;
- case ITEM_CAST_DECIMAL:
- {
- ulong len;
- uint dec;
- if (get_length_and_scale(length, decimals, &len, &dec,
- DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE,
- a))
- return NULL;
- res= new (thd->mem_root) Item_decimal_typecast(thd, a, len, dec);
- break;
- }
- case ITEM_CAST_DOUBLE:
- {
- ulong len;
- uint dec;
-
- if (!c_len)
- {
- length= DBL_DIG+7;
- decimals= NOT_FIXED_DEC;
- }
- else if (get_length_and_scale(length, decimals, &len, &dec,
- DECIMAL_MAX_PRECISION, NOT_FIXED_DEC-1,
- a))
- return NULL;
- res= new (thd->mem_root) Item_double_typecast(thd, a, (uint) length,
- (uint) decimals);
- break;
- }
- case ITEM_CAST_CHAR:
- {
- int len= -1;
- CHARSET_INFO *real_cs= (cs ? cs : thd->variables.collation_connection);
- if (c_len)
- {
- if (length > MAX_FIELD_BLOBLENGTH)
- {
- char buff[1024];
- String buf(buff, sizeof(buff), system_charset_info);
- my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), item_name(a, &buf),
- MAX_FIELD_BLOBLENGTH);
- return NULL;
- }
- len= (int) length;
- }
- res= new (thd->mem_root) Item_char_typecast(thd, a, len, real_cs);
- break;
- }
- default:
- {
- DBUG_ASSERT(0);
- res= 0;
- break;
- }
- }
- return res;
-}
-
-
static bool
have_important_literal_warnings(const MYSQL_TIME_STATUS *status)
{
@@ -7536,7 +7365,7 @@ Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums)
Item *create_func_dyncol_get(THD *thd, Item *str, Item *num,
- Cast_target cast_type,
+ const Type_handler *handler,
const char *c_len, const char *c_dec,
CHARSET_INFO *cs)
{
@@ -7544,5 +7373,6 @@ Item *create_func_dyncol_get(THD *thd, Item *str, Item *num,
if (!(res= new (thd->mem_root) Item_dyncol_get(thd, str, num)))
return res; // Return NULL
- return create_func_cast(thd, res, cast_type, c_len, c_dec, cs);
+ return handler->create_typecast_item(thd, res,
+ Type_cast_attributes(c_len, c_dec, cs));
}
diff --git a/sql/item_create.h b/sql/item_create.h
index a2d985dd3e8..128a19a1c15 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -157,20 +157,6 @@ protected:
#endif
-/**
- Builder for cast expressions.
- @param thd The current thread
- @param a The item to cast
- @param cast_type the type casted into
- @param len TODO
- @param dec TODO
- @param cs The character set
-*/
-Item *
-create_func_cast(THD *thd, Item *a, Cast_target cast_type,
- const char *len, const char *dec,
- CHARSET_INFO *cs);
-
Item *create_temporal_literal(THD *thd,
const char *str, uint length,
CHARSET_INFO *cs,
@@ -194,7 +180,7 @@ Item *create_func_dyncol_add(THD *thd, Item *str,
List<DYNCALL_CREATE_DEF> &list);
Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums);
Item *create_func_dyncol_get(THD *thd, Item *num, Item *str,
- Cast_target cast_type,
+ const Type_handler *handler,
const char *c_len, const char *c_dec,
CHARSET_INFO *cs);
Item *create_func_dyncol_json(THD *thd, Item *str);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 1f1523e738a..63a3937a12e 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -151,15 +151,81 @@ void Item_func::sync_with_sum_func_and_with_field(List<Item> &list)
}
-bool Item_func::check_allowed_arg_cols(uint n)
+bool Item_func::check_argument_types_like_args0() const
{
- if (allowed_arg_cols)
- return args[n]->check_cols(allowed_arg_cols);
+ uint cols;
+ if (arg_count == 0)
+ return false;
+ cols= args[0]->cols();
+ for (uint i= 1; i < arg_count; i++)
+ {
+ if (args[i]->check_cols(cols))
+ return true;
+ }
+ return false;
+}
+
+
+bool Item_func::check_argument_types_or_binary(const Type_handler *handler,
+ uint start, uint end) const
+{
+ for (uint i= start; i < end ; i++)
+ {
+ DBUG_ASSERT(i < arg_count);
+ if (args[i]->check_type_or_binary(func_name(), handler))
+ return true;
+ }
+ return false;
+}
- /* we have to fetch allowed_arg_cols from first argument */
- DBUG_ASSERT(n == 0); // it is first argument
- allowed_arg_cols= args[n]->cols();
- DBUG_ASSERT(allowed_arg_cols); // Can't be 0 any more
+
+bool Item_func::check_argument_types_traditional_scalar(uint start,
+ uint end) const
+{
+ for (uint i= start; i < end ; i++)
+ {
+ DBUG_ASSERT(i < arg_count);
+ if (args[i]->check_type_traditional_scalar(func_name()))
+ return true;
+ }
+ return false;
+}
+
+
+bool Item_func::check_argument_types_can_return_int(uint start,
+ uint end) const
+{
+ for (uint i= start; i < end ; i++)
+ {
+ DBUG_ASSERT(i < arg_count);
+ if (args[i]->check_type_can_return_int(func_name()))
+ return true;
+ }
+ return false;
+}
+
+
+bool Item_func::check_argument_types_can_return_real(uint start,
+ uint end) const
+{
+ for (uint i= start; i < end ; i++)
+ {
+ DBUG_ASSERT(i < arg_count);
+ if (args[i]->check_type_can_return_real(func_name()))
+ return true;
+ }
+ return false;
+}
+
+
+bool Item_func::check_argument_types_scalar(uint start, uint end) const
+{
+ for (uint i= start; i < end; i++)
+ {
+ DBUG_ASSERT(i < arg_count);
+ if (args[i]->check_type_scalar(func_name()))
+ return true;
+ }
return false;
}
@@ -236,9 +302,6 @@ Item_func::fix_fields(THD *thd, Item **ref)
return TRUE; /* purecov: inspected */
item= *arg;
- if (check_allowed_arg_cols(arg - args))
- return true;
-
if (item->maybe_null)
maybe_null=1;
@@ -249,6 +312,8 @@ Item_func::fix_fields(THD *thd, Item **ref)
with_subselect|= item->has_subquery();
}
}
+ if (check_arguments())
+ return true;
fix_length_and_dec();
if (thd->is_error()) // An error inside fix_length_and_dec occurred
return TRUE;
@@ -632,7 +697,7 @@ String *Item_int_func::val_str(String *str)
void Item_func_connection_id::fix_length_and_dec()
{
- Item_int_func::fix_length_and_dec();
+ Item_long_func::fix_length_and_dec();
max_length= 10;
}
@@ -879,41 +944,6 @@ void Item_func_signed::print(String *str, enum_query_type query_type)
}
-longlong Item::val_int_from_str(int *error)
-{
- char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff), &my_charset_bin), *res;
-
- /*
- For a string result, we must first get the string and then convert it
- to a longlong
- */
-
- if (!(res= val_str(&tmp)))
- {
- *error= 0;
- return 0;
- }
- Converter_strtoll10_with_warn cnv(NULL, Warn_filter_all(),
- res->charset(), res->ptr(), res->length());
- *error= cnv.error();
- return cnv.result();
-}
-
-
-longlong Item::val_int_signed_typecast()
-{
- if (cast_to_int_type_handler()->cmp_type() != STRING_RESULT)
- return val_int();
-
- int error;
- longlong value= val_int_from_str(&error);
- if (!null_value && value < 0 && error == 0)
- push_note_converted_to_negative_complement(current_thd);
- return value;
-}
-
-
void Item_func_unsigned::print(String *str, enum_query_type query_type)
{
str->append(STRING_WITH_LEN("cast("));
@@ -923,34 +953,6 @@ void Item_func_unsigned::print(String *str, enum_query_type query_type)
}
-longlong Item::val_int_unsigned_typecast()
-{
- if (cast_to_int_type_handler()->cmp_type() == DECIMAL_RESULT)
- {
- longlong value;
- my_decimal tmp, *dec= val_decimal(&tmp);
- if (!null_value)
- my_decimal2int(E_DEC_FATAL_ERROR, dec, 1, &value);
- else
- value= 0;
- return value;
- }
- else if (cast_to_int_type_handler()->cmp_type() != STRING_RESULT)
- {
- longlong value= val_int();
- if (!null_value && unsigned_flag == 0 && value < 0)
- push_note_converted_to_positive_complement(current_thd);
- return value;
- }
-
- int error;
- longlong value= val_int_from_str(&error);
- if (!null_value && error < 0)
- push_note_converted_to_positive_complement(current_thd);
- return value;
-}
-
-
String *Item_decimal_typecast::val_str(String *str)
{
my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
@@ -1804,8 +1806,8 @@ my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value)
void Item_func_neg::fix_length_and_dec_int()
{
- set_handler(&type_handler_longlong);
max_length= args[0]->max_length + 1;
+ set_handler(type_handler_long_or_longlong());
/*
If this is in integer context keep the context as integer if possible
@@ -1898,9 +1900,9 @@ my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value)
void Item_func_abs::fix_length_and_dec_int()
{
- set_handler(&type_handler_longlong);
max_length= args[0]->max_length;
unsigned_flag= args[0]->unsigned_flag;
+ set_handler(type_handler_long_or_longlong());
}
@@ -2181,7 +2183,7 @@ void Item_func_int_val::fix_length_and_dec_int_or_decimal()
else
{
unsigned_flag= args[0]->unsigned_flag;
- set_handler(&type_handler_longlong);
+ set_handler(type_handler_long_or_longlong());
}
}
@@ -2372,9 +2374,9 @@ void Item_func_round::fix_arg_int()
int length_can_increase= MY_TEST(!truncate && val1_is_negative);
max_length= args[0]->max_length + length_can_increase;
// Here we can keep INT_RESULT
- set_handler(&type_handler_longlong);
unsigned_flag= args[0]->unsigned_flag;
decimals= 0;
+ set_handler(type_handler_long_or_longlong());
}
else
fix_length_and_dec_decimal(decimals_to_set);
@@ -2773,6 +2775,14 @@ my_decimal *Item_func_min_max::val_decimal_native(my_decimal *dec)
}
+longlong Item_func_bit_length::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ String *res= args[0]->val_str(&value);
+ return (null_value= !res) ? 0 : (longlong) res->length() * 8;
+}
+
+
longlong Item_func_octet_length::val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -2809,13 +2819,6 @@ longlong Item_func_coercibility::val_int()
}
-void Item_func_locate::fix_length_and_dec()
-{
- max_length= MY_INT32_NUM_DECIMAL_DIGITS;
- agg_arg_charsets_for_comparison(cmp_collation, args, 2);
-}
-
-
longlong Item_func_locate::val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -4414,8 +4417,27 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
m_var_entry->set_charset(args[0]->collation.derivation == DERIVATION_NUMERIC ?
default_charset() : args[0]->collation.collation);
collation.set(m_var_entry->charset(), DERIVATION_IMPLICIT);
- set_handler_by_result_type(args[0]->result_type(),
- max_length, collation.collation);
+ switch (args[0]->result_type()) {
+ case STRING_RESULT:
+ case TIME_RESULT:
+ set_handler(type_handler_long_blob.
+ type_handler_adjusted_to_max_octet_length(max_length,
+ collation.collation));
+ break;
+ case REAL_RESULT:
+ set_handler(&type_handler_double);
+ break;
+ case INT_RESULT:
+ set_handler(Type_handler::type_handler_long_or_longlong(max_char_length()));
+ break;
+ case DECIMAL_RESULT:
+ set_handler(&type_handler_newdecimal);
+ break;
+ case ROW_RESULT:
+ DBUG_ASSERT(0);
+ set_handler(&type_handler_row);
+ break;
+ }
if (thd->lex->current_select)
{
/*
@@ -5321,7 +5343,6 @@ void Item_func_get_user_var::fix_length_and_dec()
break;
case STRING_RESULT:
max_length= MAX_BLOB_WIDTH - 1;
- set_handler(&type_handler_medium_blob);
break;
case DECIMAL_RESULT:
fix_char_length(DECIMAL_MAX_STR_LENGTH);
@@ -5406,15 +5427,14 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
}
-void Item_user_var_as_out_param::load_data_set_null_value(CHARSET_INFO* cs)
+void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
{
::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs, 0 /* unsigned_arg */);
}
-void Item_user_var_as_out_param::load_data_set_value(const char *str,
- uint length,
- CHARSET_INFO* cs)
+void Item_user_var_as_out_param::set_value(const char *str, uint length,
+ CHARSET_INFO* cs)
{
::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
0 /* unsigned_arg */);
@@ -5449,7 +5469,7 @@ my_decimal* Item_user_var_as_out_param::val_decimal(my_decimal *decimal_buffer)
}
-void Item_user_var_as_out_param::load_data_print(THD *thd, String *str)
+void Item_user_var_as_out_param::print_for_load(THD *thd, String *str)
{
str->append('@');
append_identifier(thd, str, name.str, name.length);
@@ -6688,14 +6708,14 @@ void Item_func_last_value::fix_length_and_dec()
}
-void Item_func_cursor_int_attr::print(String *str, enum_query_type query_type)
+void Cursor_ref::print_func(String *str, const char *func_name)
{
append_identifier(current_thd, str, m_cursor_name.str, m_cursor_name.length);
- str->append(func_name());
+ str->append(func_name);
}
-sp_cursor *Item_func_cursor_int_attr::get_open_cursor_or_error()
+sp_cursor *Cursor_ref::get_open_cursor_or_error()
{
THD *thd= current_thd;
sp_cursor *c= thd->spcont->get_cursor(m_cursor_offset);
diff --git a/sql/item_func.h b/sql/item_func.h
index 860a4fdcc7d..077f69fe0f5 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -35,14 +35,19 @@ class Item_func :public Item_func_or_sum
{
void sync_with_sum_func_and_with_field(List<Item> &list);
protected:
- /*
- Allowed numbers of columns in result (usually 1, which means scalar value)
- 0 means get this number from first argument
- */
- uint allowed_arg_cols;
String *val_str_from_val_str_ascii(String *str, String *str2);
- virtual bool check_allowed_arg_cols(uint argno);
+ virtual bool check_arguments() const
+ {
+ return check_argument_types_scalar(0, arg_count);
+ }
+ bool check_argument_types_like_args0() const;
+ bool check_argument_types_scalar(uint start, uint end) const;
+ bool check_argument_types_traditional_scalar(uint start, uint end) const;
+ bool check_argument_types_or_binary(const Type_handler *handler,
+ uint start, uint end) const;
+ bool check_argument_types_can_return_int(uint start, uint end) const;
+ bool check_argument_types_can_return_real(uint start, uint end) const;
public:
table_map not_null_tables_cache;
@@ -65,30 +70,30 @@ public:
NEG_FUNC, GSYSVAR_FUNC, DYNCOL_FUNC };
enum Type type() const { return FUNC_ITEM; }
virtual enum Functype functype() const { return UNKNOWN_FUNC; }
- Item_func(THD *thd): Item_func_or_sum(thd), allowed_arg_cols(1)
+ Item_func(THD *thd): Item_func_or_sum(thd)
{
with_sum_func= 0;
with_field= 0;
}
- Item_func(THD *thd, Item *a): Item_func_or_sum(thd, a), allowed_arg_cols(1)
+ Item_func(THD *thd, Item *a): Item_func_or_sum(thd, a)
{
with_sum_func= a->with_sum_func;
with_field= a->with_field;
}
Item_func(THD *thd, Item *a, Item *b):
- Item_func_or_sum(thd, a, b), allowed_arg_cols(1)
+ Item_func_or_sum(thd, a, b)
{
with_sum_func= a->with_sum_func || b->with_sum_func;
with_field= a->with_field || b->with_field;
}
Item_func(THD *thd, Item *a, Item *b, Item *c):
- Item_func_or_sum(thd, a, b, c), allowed_arg_cols(1)
+ Item_func_or_sum(thd, a, b, c)
{
with_sum_func= a->with_sum_func || b->with_sum_func || c->with_sum_func;
with_field= a->with_field || b->with_field || c->with_field;
}
Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d):
- Item_func_or_sum(thd, a, b, c, d), allowed_arg_cols(1)
+ Item_func_or_sum(thd, a, b, c, d)
{
with_sum_func= a->with_sum_func || b->with_sum_func ||
c->with_sum_func || d->with_sum_func;
@@ -96,7 +101,7 @@ public:
c->with_field || d->with_field;
}
Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e):
- Item_func_or_sum(thd, a, b, c, d, e), allowed_arg_cols(1)
+ Item_func_or_sum(thd, a, b, c, d, e)
{
with_sum_func= a->with_sum_func || b->with_sum_func ||
c->with_sum_func || d->with_sum_func || e->with_sum_func;
@@ -104,14 +109,13 @@ public:
c->with_field || d->with_field || e->with_field;
}
Item_func(THD *thd, List<Item> &list):
- Item_func_or_sum(thd, list), allowed_arg_cols(1)
+ Item_func_or_sum(thd, list)
{
set_arguments(thd, list);
}
// Constructor used for Item_cond_and/or (see Item comment)
Item_func(THD *thd, Item_func *item):
Item_func_or_sum(thd, item),
- allowed_arg_cols(item->allowed_arg_cols),
not_null_tables_cache(item->not_null_tables_cache)
{
}
@@ -141,7 +145,6 @@ public:
virtual Item *key_item() const { return args[0]; }
void set_arguments(THD *thd, List<Item> &list)
{
- allowed_arg_cols= 1;
Item_args::set_arguments(thd, list);
sync_with_sum_func_and_with_field(list);
list.empty(); // Fields are used
@@ -169,11 +172,7 @@ public:
void signal_divide_by_null();
friend class udf_handler;
Field *create_field_for_create_select(TABLE *table)
- {
- return result_type() != STRING_RESULT ?
- create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) :
- tmp_table_field_from_field_type(table);
- }
+ { return tmp_table_field_from_field_type(table); }
Item *get_tmp_table_item(THD *thd);
my_decimal *val_decimal(my_decimal *);
@@ -624,10 +623,6 @@ public:
Item_func_case_expression(THD *thd, List<Item> &list):
Item_func_hybrid_field_type(thd, list)
{ }
- Field *create_tmp_field(bool group, TABLE *table)
- { return tmp_table_field_from_field_type(table); }
- Field *create_field_for_create_select(TABLE *table)
- { return tmp_table_field_from_field_type(table); }
};
@@ -700,13 +695,14 @@ class Item_num_op :public Item_func_numhybrid
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
result_precision();
decimals= 0;
+ set_handler(type_handler_long_or_longlong());
}
void fix_length_and_dec_temporal()
{
set_handler(&type_handler_newdecimal);
fix_length_and_dec_decimal();
if (decimals == 0)
- set_handler(&type_handler_longlong);
+ set_handler(type_handler_long_or_longlong());
}
bool need_parentheses_in_default() { return true; }
};
@@ -715,6 +711,12 @@ class Item_num_op :public Item_func_numhybrid
class Item_int_func :public Item_func
{
public:
+ /*
+ QQ: shouldn't 20 characters be enough:
+ Max unsigned = 18,446,744,073,709,551,615 = 20 digits, 20 characters
+ Max signed = 9,223,372,036,854,775,807 = 19 digits, 19 characters
+ Min signed = -9,223,372,036,854,775,808 = 19 digits, 20 characters
+ */
Item_int_func(THD *thd): Item_func(thd)
{ collation.set_numeric(); fix_char_length(21); }
Item_int_func(THD *thd, Item *a): Item_func(thd, a)
@@ -732,87 +734,82 @@ public:
{ collation.set_numeric(); }
double val_real();
String *val_str(String*str);
- const Type_handler *type_handler() const { return &type_handler_longlong; }
+ const Type_handler *type_handler() const= 0;
void fix_length_and_dec() {}
};
-class Item_func_cursor_int_attr: public Item_int_func
+class Item_long_func: public Item_int_func
{
-protected:
- LEX_CSTRING m_cursor_name;
- uint m_cursor_offset;
- class sp_cursor *get_open_cursor_or_error();
public:
- Item_func_cursor_int_attr(THD *thd, const LEX_CSTRING *name, uint offset)
- :Item_int_func(thd), m_cursor_name(*name), m_cursor_offset(offset)
- { }
- bool check_vcol_func_processor(void *arg)
- {
- return mark_unsupported_function(func_name(), arg, VCOL_SESSION_FUNC);
- }
- void print(String *str, enum_query_type query_type);
+ Item_long_func(THD *thd): Item_int_func(thd) { }
+ Item_long_func(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_long_func(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_long_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
+ Item_long_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { }
+ Item_long_func(THD *thd, Item_long_func *item) :Item_int_func(thd, item) {}
+ const Type_handler *type_handler() const { return &type_handler_long; }
+ void fix_length_and_dec() { max_length= 11; }
};
-class Item_func_cursor_isopen: public Item_func_cursor_int_attr
+class Item_longlong_func: public Item_int_func
{
public:
- Item_func_cursor_isopen(THD *thd, const LEX_CSTRING *name, uint offset)
- :Item_func_cursor_int_attr(thd, name, offset) { }
- const char *func_name() const { return "%ISOPEN"; }
- void fix_length_and_dec() { max_length= 1; }
- longlong val_int();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_cursor_isopen>(thd, mem_root, this); }
+ Item_longlong_func(THD *thd): Item_int_func(thd) { }
+ Item_longlong_func(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_longlong_func(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_longlong_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
+ Item_longlong_func(THD *thd, Item *a, Item *b, Item *c, Item *d):
+ Item_int_func(thd, a, b, c, d) {}
+ Item_longlong_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { }
+ Item_longlong_func(THD *thd, Item_longlong_func *item) :Item_int_func(thd, item) {}
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
};
-class Item_func_cursor_found: public Item_func_cursor_int_attr
+class Cursor_ref
{
-public:
- Item_func_cursor_found(THD *thd, const LEX_CSTRING *name, uint offset)
- :Item_func_cursor_int_attr(thd, name, offset) { }
- const char *func_name() const { return "%FOUND"; }
- void fix_length_and_dec() { max_length= 1; maybe_null= true; }
- longlong val_int();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_cursor_found>(thd, mem_root, this); }
+protected:
+ LEX_CSTRING m_cursor_name;
+ uint m_cursor_offset;
+ class sp_cursor *get_open_cursor_or_error();
+ Cursor_ref(const LEX_CSTRING *name, uint offset)
+ :m_cursor_name(*name), m_cursor_offset(offset)
+ { }
+ void print_func(String *str, const char *func_name);
};
-class Item_func_cursor_notfound: public Item_func_cursor_int_attr
-{
-public:
- Item_func_cursor_notfound(THD *thd, const LEX_CSTRING *name, uint offset)
- :Item_func_cursor_int_attr(thd, name, offset) { }
- const char *func_name() const { return "%NOTFOUND"; }
- void fix_length_and_dec() { max_length= 1; maybe_null= true; }
- longlong val_int();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_cursor_notfound>(thd, mem_root, this); }
-};
-
-class Item_func_cursor_rowcount: public Item_func_cursor_int_attr
+class Item_func_cursor_rowcount: public Item_longlong_func,
+ public Cursor_ref
{
public:
Item_func_cursor_rowcount(THD *thd, const LEX_CSTRING *name, uint offset)
- :Item_func_cursor_int_attr(thd, name, offset) { }
+ :Item_longlong_func(thd), Cursor_ref(name, offset) { maybe_null= true; }
const char *func_name() const { return "%ROWCOUNT"; }
longlong val_int();
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), arg, VCOL_SESSION_FUNC);
+ }
+ void print(String *str, enum_query_type query_type)
+ {
+ return Cursor_ref::print_func(str, func_name());
+ }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_cursor_rowcount>(thd, mem_root, this); }
};
-class Item_func_connection_id :public Item_int_func
+class Item_func_connection_id :public Item_long_func
{
longlong value;
public:
- Item_func_connection_id(THD *thd): Item_int_func(thd) {}
+ Item_func_connection_id(THD *thd): Item_long_func(thd) {}
const char *func_name() const { return "connection_id"; }
void fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
@@ -834,12 +831,18 @@ public:
unsigned_flag= 0;
}
const char *func_name() const { return "cast_as_signed"; }
+ const Type_handler *type_handler() const
+ { return type_handler_long_or_longlong(); }
longlong val_int()
{
longlong value= args[0]->val_int_signed_typecast();
null_value= args[0]->null_value;
return value;
}
+ void fix_length_and_dec_double()
+ {
+ fix_char_length(MAX_BIGINT_WIDTH);
+ }
void fix_length_and_dec_generic()
{
uint32 char_length= MY_MIN(args[0]->max_char_length(),
@@ -852,6 +855,19 @@ public:
set_if_bigger(char_length, 1U + (unsigned_flag ? 0 : 1));
fix_char_length(char_length);
}
+ void fix_length_and_dec_string()
+ {
+ /*
+ For strings, use decimal_int_part() instead of max_char_length().
+ This is important for Item_hex_hybrid:
+ SELECT CAST(0x1FFFFFFFF AS SIGNED);
+ Length is 5, decimal_int_part() is 13.
+ */
+ uint32 char_length= MY_MIN(args[0]->decimal_int_part(),
+ MY_INT64_NUM_DECIMAL_DIGITS);
+ set_if_bigger(char_length, 1U + (unsigned_flag ? 0 : 1));
+ fix_char_length(char_length);
+ }
void fix_length_and_dec()
{
args[0]->type_handler()->Item_func_signed_fix_length_and_dec(this);
@@ -872,6 +888,12 @@ public:
unsigned_flag= 1;
}
const char *func_name() const { return "cast_as_unsigned"; }
+ const Type_handler *type_handler() const
+ {
+ if (max_char_length() <= MY_INT32_NUM_DECIMAL_DIGITS - 1)
+ return &type_handler_long;
+ return &type_handler_longlong;
+ }
longlong val_int()
{
longlong value= args[0]->val_int_unsigned_typecast();
@@ -882,6 +904,7 @@ public:
{
args[0]->type_handler()->Item_func_unsigned_fix_length_and_dec(this);
}
+ uint decimal_precision() const { return max_length; }
virtual void print(String *str, enum_query_type query_type);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_unsigned>(thd, mem_root, this); }
@@ -1044,6 +1067,8 @@ public:
longlong val_int();
const char *func_name() const { return "DIV"; }
enum precedence precedence() const { return MUL_PRECEDENCE; }
+ const Type_handler *type_handler() const
+ { return type_handler_long_or_longlong(); }
void fix_length_and_dec();
void print(String *str, enum_query_type query_type)
{
@@ -1084,6 +1109,7 @@ public:
max_length= MY_MAX(args[0]->max_length, args[1]->max_length);
decimals= 0;
unsigned_flag= args[0]->unsigned_flag;
+ set_handler(type_handler_long_or_longlong());
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -1384,11 +1410,13 @@ private:
};
-class Item_func_sign :public Item_int_func
+class Item_func_sign :public Item_long_func
{
public:
- Item_func_sign(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_sign(THD *thd, Item *a): Item_long_func(thd, a) {}
const char *func_name() const { return "sign"; }
+ uint decimal_precision() const { return 1; }
+ void fix_length_and_dec() { fix_char_length(2); }
longlong val_int();
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_sign>(thd, mem_root, this); }
@@ -1433,10 +1461,6 @@ public:
Item_func_min_max(THD *thd, List<Item> &list, int cmp_sign_arg):
Item_hybrid_func(thd, list), cmp_sign(cmp_sign_arg)
{}
- Field *create_tmp_field(bool group, TABLE *table)
- { return tmp_table_field_from_field_type(table); }
- Field *create_field_for_create_select(TABLE *table)
- { return tmp_table_field_from_field_type(table); }
String *val_str_native(String *str);
double val_real_native();
longlong val_int_native();
@@ -1552,11 +1576,11 @@ public:
};
-class Item_func_octet_length :public Item_int_func
+class Item_func_octet_length :public Item_long_func
{
String value;
public:
- Item_func_octet_length(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_octet_length(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "octet_length"; }
void fix_length_and_dec() { max_length=10; }
@@ -1564,22 +1588,26 @@ public:
{ return get_item_copy<Item_func_octet_length>(thd, mem_root, this); }
};
-class Item_func_bit_length :public Item_func_octet_length
+class Item_func_bit_length :public Item_longlong_func
{
+ String value;
public:
- Item_func_bit_length(THD *thd, Item *a): Item_func_octet_length(thd, a) {}
- longlong val_int()
- { DBUG_ASSERT(fixed == 1); return Item_func_octet_length::val_int()*8; }
+ Item_func_bit_length(THD *thd, Item *a): Item_longlong_func(thd, a) {}
+ void fix_length_and_dec()
+ {
+ max_length= 11; // 0x100000000*8 = 34,359,738,368
+ }
+ longlong val_int();
const char *func_name() const { return "bit_length"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_bit_length>(thd, mem_root, this); }
};
-class Item_func_char_length :public Item_int_func
+class Item_func_char_length :public Item_long_func
{
String value;
public:
- Item_func_char_length(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_char_length(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "char_length"; }
void fix_length_and_dec() { max_length=10; }
@@ -1587,10 +1615,10 @@ public:
{ return get_item_copy<Item_func_char_length>(thd, mem_root, this); }
};
-class Item_func_coercibility :public Item_int_func
+class Item_func_coercibility :public Item_long_func
{
public:
- Item_func_coercibility(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_coercibility(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "coercibility"; }
void fix_length_and_dec() { max_length=10; maybe_null= 0; }
@@ -1602,29 +1630,42 @@ public:
{ return get_item_copy<Item_func_coercibility>(thd, mem_root, this); }
};
-class Item_func_locate :public Item_int_func
+
+/*
+ In the corner case LOCATE could return (4,294,967,296 + 1),
+ which would not fit into Item_long_func range.
+ But string lengths are limited with max_allowed_packet,
+ which cannot be bigger than 1024*1024*1024.
+*/
+class Item_func_locate :public Item_long_func
{
String value1,value2;
DTCollation cmp_collation;
public:
- Item_func_locate(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
- Item_func_locate(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
+ Item_func_locate(THD *thd, Item *a, Item *b)
+ :Item_long_func(thd, a, b) {}
+ Item_func_locate(THD *thd, Item *a, Item *b, Item *c)
+ :Item_long_func(thd, a, b, c) {}
const char *func_name() const { return "locate"; }
longlong val_int();
- void fix_length_and_dec();
+ void fix_length_and_dec()
+ {
+ max_length= MY_INT32_NUM_DECIMAL_DIGITS;
+ agg_arg_charsets_for_comparison(cmp_collation, args, 2);
+ }
virtual void print(String *str, enum_query_type query_type);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_locate>(thd, mem_root, this); }
};
-class Item_func_field :public Item_int_func
+class Item_func_field :public Item_long_func
{
String value,tmp;
Item_result cmp_type;
DTCollation cmp_collation;
public:
- Item_func_field(THD *thd, List<Item> &list): Item_int_func(thd, list) {}
+ Item_func_field(THD *thd, List<Item> &list): Item_long_func(thd, list) {}
longlong val_int();
const char *func_name() const { return "field"; }
void fix_length_and_dec();
@@ -1633,11 +1674,11 @@ public:
};
-class Item_func_ascii :public Item_int_func
+class Item_func_ascii :public Item_long_func
{
String value;
public:
- Item_func_ascii(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_ascii(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "ascii"; }
void fix_length_and_dec() { max_length=3; }
@@ -1645,18 +1686,19 @@ public:
{ return get_item_copy<Item_func_ascii>(thd, mem_root, this); }
};
-class Item_func_ord :public Item_int_func
+class Item_func_ord :public Item_long_func
{
String value;
public:
- Item_func_ord(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_ord(THD *thd, Item *a): Item_long_func(thd, a) {}
+ void fix_length_and_dec() { fix_char_length(7); }
longlong val_int();
const char *func_name() const { return "ord"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_ord>(thd, mem_root, this); }
};
-class Item_func_find_in_set :public Item_int_func
+class Item_func_find_in_set :public Item_long_func
{
String value,value2;
uint enum_value;
@@ -1664,7 +1706,7 @@ class Item_func_find_in_set :public Item_int_func
DTCollation cmp_collation;
public:
Item_func_find_in_set(THD *thd, Item *a, Item *b):
- Item_int_func(thd, a, b), enum_value(0) {}
+ Item_long_func(thd, a, b), enum_value(0) {}
longlong val_int();
const char *func_name() const { return "find_in_set"; }
void fix_length_and_dec();
@@ -1674,11 +1716,11 @@ public:
/* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */
-class Item_func_bit: public Item_int_func
+class Item_func_bit: public Item_longlong_func
{
public:
- Item_func_bit(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
- Item_func_bit(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_bit(THD *thd, Item *a, Item *b): Item_longlong_func(thd, a, b) {}
+ Item_func_bit(THD *thd, Item *a): Item_longlong_func(thd, a) {}
void fix_length_and_dec() { unsigned_flag= 1; }
virtual inline void print(String *str, enum_query_type query_type)
@@ -1710,10 +1752,10 @@ public:
{ return get_item_copy<Item_func_bit_and>(thd, mem_root, this); }
};
-class Item_func_bit_count :public Item_int_func
+class Item_func_bit_count :public Item_long_func
{
public:
- Item_func_bit_count(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_bit_count(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "bit_count"; }
void fix_length_and_dec() { max_length=2; }
@@ -1760,19 +1802,18 @@ public:
};
-class Item_func_last_insert_id :public Item_int_func
+class Item_func_last_insert_id :public Item_longlong_func
{
public:
- Item_func_last_insert_id(THD *thd): Item_int_func(thd) {}
- Item_func_last_insert_id(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_last_insert_id(THD *thd): Item_longlong_func(thd) {}
+ Item_func_last_insert_id(THD *thd, Item *a): Item_longlong_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "last_insert_id"; }
void fix_length_and_dec()
{
- unsigned_flag= TRUE;
+ unsigned_flag= true;
if (arg_count)
max_length= args[0]->max_length;
- unsigned_flag=1;
}
bool fix_fields(THD *thd, Item **ref);
bool check_vcol_func_processor(void *arg)
@@ -1784,11 +1825,11 @@ public:
};
-class Item_func_benchmark :public Item_int_func
+class Item_func_benchmark :public Item_long_func
{
public:
Item_func_benchmark(THD *thd, Item *count_expr, Item *expr):
- Item_int_func(thd, count_expr, expr)
+ Item_long_func(thd, count_expr, expr)
{}
longlong val_int();
const char *func_name() const { return "benchmark"; }
@@ -1806,10 +1847,11 @@ public:
void item_func_sleep_init(void);
void item_func_sleep_free(void);
-class Item_func_sleep :public Item_int_func
+class Item_func_sleep :public Item_long_func
{
public:
- Item_func_sleep(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_sleep(THD *thd, Item *a): Item_long_func(thd, a) {}
+ void fix_length_and_dec() { fix_char_length(1); }
bool const_item() const { return 0; }
const char *func_name() const { return "sleep"; }
table_map used_tables() const
@@ -2045,6 +2087,7 @@ public:
Item_int_func(thd) {}
Item_func_udf_int(THD *thd, udf_func *udf_arg, List<Item> &list):
Item_int_func(thd, list) {}
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; }
};
@@ -2056,6 +2099,7 @@ public:
Item_int_func(thd) {}
Item_func_udf_decimal(THD *thd, udf_func *udf_arg, List<Item> &list):
Item_int_func(thd, list) {}
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; }
};
@@ -2079,11 +2123,11 @@ public:
void mysql_ull_cleanup(THD *thd);
void mysql_ull_set_explicit_lock_duration(THD *thd);
-class Item_func_get_lock :public Item_int_func
+class Item_func_get_lock :public Item_long_func
{
String value;
public:
- Item_func_get_lock(THD *thd, Item *a, Item *b) :Item_int_func(thd, a, b) {}
+ Item_func_get_lock(THD *thd, Item *a, Item *b) :Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "get_lock"; }
void fix_length_and_dec() { max_length=1; maybe_null=1;}
@@ -2101,11 +2145,11 @@ class Item_func_get_lock :public Item_int_func
{ return get_item_copy<Item_func_get_lock>(thd, mem_root, this); }
};
-class Item_func_release_lock :public Item_int_func
+class Item_func_release_lock :public Item_long_func
{
String value;
public:
- Item_func_release_lock(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_release_lock(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "release_lock"; }
void fix_length_and_dec() { max_length= 1; maybe_null= 1;}
@@ -2125,15 +2169,16 @@ public:
/* replication functions */
-class Item_master_pos_wait :public Item_int_func
+class Item_master_pos_wait :public Item_longlong_func
{
String value;
public:
- Item_master_pos_wait(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_master_pos_wait(THD *thd, Item *a, Item *b)
+ :Item_longlong_func(thd, a, b) {}
Item_master_pos_wait(THD *thd, Item *a, Item *b, Item *c):
- Item_int_func(thd, a, b, c) {}
+ Item_longlong_func(thd, a, b, c) {}
Item_master_pos_wait(THD *thd, Item *a, Item *b, Item *c, Item *d):
- Item_int_func(thd, a, b, c, d) {}
+ Item_longlong_func(thd, a, b, c, d) {}
longlong val_int();
const char *func_name() const { return "master_pos_wait"; }
void fix_length_and_dec() { max_length=21; maybe_null=1;}
@@ -2146,15 +2191,17 @@ public:
};
-class Item_master_gtid_wait :public Item_int_func
+class Item_master_gtid_wait :public Item_long_func
{
String value;
public:
- Item_master_gtid_wait(THD *thd, Item *a): Item_int_func(thd, a) {}
- Item_master_gtid_wait(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_master_gtid_wait(THD *thd, Item *a)
+ :Item_long_func(thd, a) {}
+ Item_master_gtid_wait(THD *thd, Item *a, Item *b)
+ :Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "master_gtid_wait"; }
- void fix_length_and_dec() { max_length=10+1+10+1+20+1; maybe_null=0;}
+ void fix_length_and_dec() { max_length= 2; maybe_null=0;}
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
@@ -2185,6 +2232,10 @@ public:
Item_func_user_var(THD *thd, Item_func_user_var *item)
:Item_hybrid_func(thd, item),
m_var_entry(item->m_var_entry), name(item->name) { }
+ Field *create_tmp_field(bool group, TABLE *table)
+ { return create_table_field_from_handler(table); }
+ Field *create_field_for_create_select(TABLE *table)
+ { return create_table_field_from_handler(table); }
bool check_vcol_func_processor(void *arg);
};
@@ -2287,14 +2338,6 @@ public:
my_decimal *val_decimal(my_decimal*);
String *val_str(String* str);
void fix_length_and_dec();
- Field *create_field_for_create_select(TABLE *table)
- {
- return Type_handler_hybrid_field_type::cmp_type() == STRING_RESULT ?
- type_handler_long_blob.make_and_init_table_field(&(Item::name),
- Record_addr(maybe_null),
- *this, table) :
- create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS);
- }
virtual void print(String *str, enum_query_type query_type);
/*
We must always return variables as strings to guard against selects of type
@@ -2327,8 +2370,7 @@ public:
in List<Item> and desire to place this code somewhere near other functions
working with user variables.
*/
-class Item_user_var_as_out_param :public Item,
- public Load_data_out_param
+class Item_user_var_as_out_param :public Item
{
LEX_CSTRING name;
user_var_entry *entry;
@@ -2344,10 +2386,9 @@ public:
my_decimal *val_decimal(my_decimal *decimal_buffer);
/* fix_fields() binds variable name with its entry structure */
bool fix_fields(THD *thd, Item **ref);
- Load_data_out_param *get_load_data_out_param() { return this; }
- void load_data_print(THD *thd, String *str);
- void load_data_set_null_value(CHARSET_INFO* cs);
- void load_data_set_value(const char *str, uint length, CHARSET_INFO* cs);
+ void print_for_load(THD *thd, String *str);
+ void set_null_value(CHARSET_INFO* cs);
+ void set_value(const char *str, uint length, CHARSET_INFO* cs);
const Type_handler *type_handler() const { return &type_handler_double; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_user_var_as_out_param>(thd, mem_root, this); }
@@ -2506,11 +2547,11 @@ public:
{ return get_item_copy<Item_func_bit_xor>(thd, mem_root, this); }
};
-class Item_func_is_free_lock :public Item_int_func
+class Item_func_is_free_lock :public Item_long_func
{
String value;
public:
- Item_func_is_free_lock(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_is_free_lock(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "is_free_lock"; }
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
@@ -2522,11 +2563,11 @@ public:
{ return get_item_copy<Item_func_is_free_lock>(thd, mem_root, this); }
};
-class Item_func_is_used_lock :public Item_int_func
+class Item_func_is_used_lock :public Item_long_func
{
String value;
public:
- Item_func_is_used_lock(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_is_used_lock(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "is_used_lock"; }
void fix_length_and_dec() { decimals=0; max_length=10; maybe_null=1;}
@@ -2538,47 +2579,44 @@ public:
{ return get_item_copy<Item_func_is_used_lock>(thd, mem_root, this); }
};
-/* For type casts */
-
-enum Cast_target
-{
- ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT,
- ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR,
- ITEM_CAST_DECIMAL, ITEM_CAST_DOUBLE
-};
-
struct Lex_cast_type_st: public Lex_length_and_dec_st
{
private:
- Cast_target m_type;
+ const Type_handler *m_type_handler;
public:
- void set(Cast_target type, const char *length, const char *dec)
+ void set(const Type_handler *handler, const char *length, const char *dec)
{
- m_type= type;
+ m_type_handler= handler;
Lex_length_and_dec_st::set(length, dec);
}
- void set(Cast_target type, Lex_length_and_dec_st length_and_dec)
+ void set(const Type_handler *handler, Lex_length_and_dec_st length_and_dec)
{
- m_type= type;
+ m_type_handler= handler;
Lex_length_and_dec_st::operator=(length_and_dec);
}
- void set(Cast_target type, const char *length)
+ void set(const Type_handler *handler, const char *length)
+ {
+ set(handler, length, 0);
+ }
+ void set(const Type_handler *handler)
{
- set(type, length, 0);
+ set(handler, 0, 0);
}
- void set(Cast_target type)
+ const Type_handler *type_handler() const { return m_type_handler; }
+ Item *create_typecast_item(THD *thd, Item *item, CHARSET_INFO *cs= NULL)
{
- set(type, 0, 0);
+ return m_type_handler->
+ create_typecast_item(thd, item,
+ Type_cast_attributes(length(), dec(), cs));
}
- Cast_target type() const { return m_type; }
};
-class Item_func_row_count :public Item_int_func
+class Item_func_row_count :public Item_longlong_func
{
public:
- Item_func_row_count(THD *thd): Item_int_func(thd) {}
+ Item_func_row_count(THD *thd): Item_longlong_func(thd) {}
longlong val_int();
const char *func_name() const { return "row_count"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; }
@@ -2622,7 +2660,7 @@ protected:
bool is_expensive_processor(void *arg)
{ return is_expensive(); }
- bool check_allowed_arg_cols(uint n)
+ bool check_arguments() const
{
// sp_prepare_func_item() checks that the number of columns is correct
return false;
@@ -2734,10 +2772,10 @@ public:
};
-class Item_func_found_rows :public Item_int_func
+class Item_func_found_rows :public Item_longlong_func
{
public:
- Item_func_found_rows(THD *thd): Item_int_func(thd) {}
+ Item_func_found_rows(THD *thd): Item_longlong_func(thd) {}
longlong val_int();
const char *func_name() const { return "found_rows"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; }
@@ -2750,10 +2788,10 @@ public:
};
-class Item_func_oracle_sql_rowcount :public Item_int_func
+class Item_func_oracle_sql_rowcount :public Item_longlong_func
{
public:
- Item_func_oracle_sql_rowcount(THD *thd): Item_int_func(thd) {}
+ Item_func_oracle_sql_rowcount(THD *thd): Item_longlong_func(thd) {}
longlong val_int();
const char *func_name() const { return "SQL%ROWCOUNT"; }
void print(String *str, enum_query_type query_type)
@@ -2769,10 +2807,10 @@ public:
};
-class Item_func_sqlcode: public Item_int_func
+class Item_func_sqlcode: public Item_long_func
{
public:
- Item_func_sqlcode(THD *thd): Item_int_func(thd) { }
+ Item_func_sqlcode(THD *thd): Item_long_func(thd) { }
longlong val_int();
const char *func_name() const { return "SQLCODE"; }
void print(String *str, enum_query_type query_type)
@@ -2795,10 +2833,10 @@ public:
void uuid_short_init();
-class Item_func_uuid_short :public Item_int_func
+class Item_func_uuid_short :public Item_longlong_func
{
public:
- Item_func_uuid_short(THD *thd): Item_int_func(thd) {}
+ Item_func_uuid_short(THD *thd): Item_longlong_func(thd) {}
const char *func_name() const { return "uuid_short"; }
longlong val_int();
void fix_length_and_dec()
@@ -2841,13 +2879,13 @@ public:
/* Implementation for sequences: NEXT VALUE FOR sequence and NEXTVAL() */
-class Item_func_nextval :public Item_int_func
+class Item_func_nextval :public Item_longlong_func
{
protected:
TABLE_LIST *table_list;
public:
Item_func_nextval(THD *thd, TABLE_LIST *table):
- Item_int_func(thd), table_list(table) {}
+ Item_longlong_func(thd), table_list(table) {}
longlong val_int();
const char *func_name() const { return "nextval"; }
void fix_length_and_dec()
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index cf6d9bb1360..838f0b21d56 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -42,8 +42,160 @@ public:
const Type_handler *type_handler() const { return &type_handler_geometry; }
};
+
+/*
+ Functions returning REAL measurements of a single GEOMETRY argument
+*/
+class Item_real_func_args_geometry: public Item_real_func
+{
+protected:
+ String value;
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count == 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_real_func_args_geometry(THD *thd, Item *a)
+ :Item_real_func(thd, a) {}
+};
+
+
+/*
+ Functions returning INT measurements of a single GEOMETRY argument
+*/
+class Item_long_func_args_geometry: public Item_long_func
+{
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count == 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+protected:
+ String value;
+public:
+ Item_long_func_args_geometry(THD *thd, Item *a)
+ :Item_long_func(thd, a) {}
+};
+
+
+/*
+ Functions returning BOOL measurements of a single GEOMETRY argument
+*/
+class Item_bool_func_args_geometry: public Item_bool_func
+{
+protected:
+ String value;
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count == 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_bool_func_args_geometry(THD *thd, Item *a)
+ :Item_bool_func(thd, a) {}
+};
+
+
+/*
+ Functions returning ASCII string measurements of a single GEOMETRY argument
+*/
+class Item_str_ascii_func_args_geometry: public Item_str_ascii_func
+{
+protected:
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_str_ascii_func_args_geometry(THD *thd, Item *a)
+ :Item_str_ascii_func(thd, a) {}
+ Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b)
+ :Item_str_ascii_func(thd, a, b) {}
+ Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b, Item *c)
+ :Item_str_ascii_func(thd, a, b, c) {}
+};
+
+
+/*
+ Functions returning binary string measurements of a single GEOMETRY argument
+*/
+class Item_binary_func_args_geometry: public Item_str_func
+{
+protected:
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_binary_func_args_geometry(THD *thd, Item *a)
+ :Item_str_func(thd, a) {}
+};
+
+
+/*
+ Functions returning GEOMETRY measurements of a single GEOEMETRY argument
+*/
+class Item_geometry_func_args_geometry: public Item_geometry_func
+{
+protected:
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_geometry_func_args_geometry(THD *thd, Item *a)
+ :Item_geometry_func(thd, a) {}
+ Item_geometry_func_args_geometry(THD *thd, Item *a, Item *b)
+ :Item_geometry_func(thd, a, b) {}
+};
+
+
+/*
+ Functions returning REAL result relationships between two GEOMETRY arguments
+*/
+class Item_real_func_args_geometry_geometry: public Item_real_func
+{
+protected:
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 2);
+ return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+ }
+public:
+ Item_real_func_args_geometry_geometry(THD *thd, Item *a, Item *b)
+ :Item_real_func(thd, a, b) {}
+};
+
+
+/*
+ Functions returning BOOL result relationships between two GEOMETRY arguments
+*/
+class Item_bool_func_args_geometry_geometry: public Item_bool_func
+{
+protected:
+ String value;
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 2);
+ return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+ }
+public:
+ Item_bool_func_args_geometry_geometry(THD *thd, Item *a, Item *b, Item *c)
+ :Item_bool_func(thd, a, b, c) {}
+};
+
+
class Item_func_geometry_from_text: public Item_geometry_func
{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_general_purpose_string(func_name()) ||
+ check_argument_types_can_return_int(1, MY_MIN(2, arg_count));
+ }
public:
Item_func_geometry_from_text(THD *thd, Item *a): Item_geometry_func(thd, a) {}
Item_func_geometry_from_text(THD *thd, Item *a, Item *srid):
@@ -56,6 +208,11 @@ public:
class Item_func_geometry_from_wkb: public Item_geometry_func
{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry) ||
+ check_argument_types_can_return_int(1, MY_MIN(2, arg_count));
+ }
public:
Item_func_geometry_from_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {}
Item_func_geometry_from_wkb(THD *thd, Item *a, Item *srid):
@@ -70,6 +227,12 @@ public:
class Item_func_geometry_from_json: public Item_geometry_func
{
String tmp_js;
+ bool check_arguments() const
+ {
+ // TODO: check with Alexey, for better args[1] and args[2] type control
+ return args[0]->check_type_general_purpose_string(func_name()) ||
+ check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count));
+ }
public:
Item_func_geometry_from_json(THD *thd, Item *js): Item_geometry_func(thd, js) {}
Item_func_geometry_from_json(THD *thd, Item *js, Item *opt):
@@ -83,10 +246,11 @@ public:
};
-class Item_func_as_wkt: public Item_str_ascii_func
+class Item_func_as_wkt: public Item_str_ascii_func_args_geometry
{
public:
- Item_func_as_wkt(THD *thd, Item *a): Item_str_ascii_func(thd, a) {}
+ Item_func_as_wkt(THD *thd, Item *a)
+ :Item_str_ascii_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_astext"; }
String *val_str_ascii(String *);
void fix_length_and_dec();
@@ -94,26 +258,41 @@ public:
{ return get_item_copy<Item_func_as_wkt>(thd, mem_root, this); }
};
-class Item_func_as_wkb: public Item_geometry_func
+class Item_func_as_wkb: public Item_binary_func_args_geometry
{
public:
- Item_func_as_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+ Item_func_as_wkb(THD *thd, Item *a)
+ :Item_binary_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_aswkb"; }
String *val_str(String *);
const Type_handler *type_handler() const { return &type_handler_long_blob; }
+ void fix_length_and_dec()
+ {
+ collation.set(&my_charset_bin);
+ decimals=0;
+ max_length= (uint32) UINT_MAX32;
+ maybe_null= 1;
+ }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_as_wkb>(thd, mem_root, this); }
};
-class Item_func_as_geojson: public Item_str_ascii_func
+class Item_func_as_geojson: public Item_str_ascii_func_args_geometry
{
+ bool check_arguments() const
+ {
+ // TODO: check with Alexey, for better args[1] and args[2] type control
+ return Item_str_ascii_func_args_geometry::check_arguments() ||
+ check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count));
+ }
public:
- Item_func_as_geojson(THD *thd, Item *js): Item_str_ascii_func(thd, js) {}
- Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits):
- Item_str_ascii_func(thd, js, max_dec_digits) {}
- Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt):
- Item_str_ascii_func(thd, js, max_dec_digits, opt) {}
+ Item_func_as_geojson(THD *thd, Item *js)
+ :Item_str_ascii_func_args_geometry(thd, js) {}
+ Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits)
+ :Item_str_ascii_func_args_geometry(thd, js, max_dec_digits) {}
+ Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt)
+ :Item_str_ascii_func_args_geometry(thd, js, max_dec_digits, opt) {}
const char *func_name() const { return "st_asgeojson"; }
void fix_length_and_dec();
String *val_str_ascii(String *);
@@ -122,10 +301,11 @@ public:
};
-class Item_func_geometry_type: public Item_str_ascii_func
+class Item_func_geometry_type: public Item_str_ascii_func_args_geometry
{
public:
- Item_func_geometry_type(THD *thd, Item *a): Item_str_ascii_func(thd, a) {}
+ Item_func_geometry_type(THD *thd, Item *a)
+ :Item_str_ascii_func_args_geometry(thd, a) {}
String *val_str_ascii(String *);
const char *func_name() const { return "st_geometrytype"; }
void fix_length_and_dec()
@@ -140,7 +320,7 @@ public:
// #define HEAVY_CONVEX_HULL
-class Item_func_convexhull: public Item_geometry_func
+class Item_func_convexhull: public Item_geometry_func_args_geometry
{
class ch_node: public Gcalc_dyn_list::Item
{
@@ -163,7 +343,8 @@ class Item_func_convexhull: public Item_geometry_func
ch_node *new_ch_node() { return (ch_node *) res_heap.new_item(); }
int add_node_to_line(ch_node **p_cur, int dir, const Gcalc_heap::Info *pi);
public:
- Item_func_convexhull(THD *thd, Item *a): Item_geometry_func(thd, a),
+ Item_func_convexhull(THD *thd, Item *a)
+ :Item_geometry_func_args_geometry(thd, a),
res_heap(8192, sizeof(ch_node))
{}
const char *func_name() const { return "st_convexhull"; }
@@ -173,10 +354,11 @@ public:
};
-class Item_func_centroid: public Item_geometry_func
+class Item_func_centroid: public Item_geometry_func_args_geometry
{
public:
- Item_func_centroid(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+ Item_func_centroid(THD *thd, Item *a)
+ :Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_centroid"; }
String *val_str(String *);
Field::geometry_type get_geometry_type() const;
@@ -184,10 +366,11 @@ public:
{ return get_item_copy<Item_func_centroid>(thd, mem_root, this); }
};
-class Item_func_envelope: public Item_geometry_func
+class Item_func_envelope: public Item_geometry_func_args_geometry
{
public:
- Item_func_envelope(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+ Item_func_envelope(THD *thd, Item *a)
+ :Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_envelope"; }
String *val_str(String *);
Field::geometry_type get_geometry_type() const;
@@ -196,7 +379,7 @@ public:
};
-class Item_func_boundary: public Item_geometry_func
+class Item_func_boundary: public Item_geometry_func_args_geometry
{
class Transporter : public Gcalc_shape_transporter
{
@@ -221,7 +404,8 @@ class Item_func_boundary: public Item_geometry_func
};
Gcalc_result_receiver res_receiver;
public:
- Item_func_boundary(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+ Item_func_boundary(THD *thd, Item *a)
+ :Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_boundary"; }
String *val_str(String *);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -231,6 +415,8 @@ public:
class Item_func_point: public Item_geometry_func
{
+ bool check_arguments() const
+ { return check_argument_types_can_return_real(0, 2); }
public:
Item_func_point(THD *thd, Item *a, Item *b): Item_geometry_func(thd, a, b) {}
Item_func_point(THD *thd, Item *a, Item *b, Item *srid):
@@ -242,12 +428,12 @@ public:
{ return get_item_copy<Item_func_point>(thd, mem_root, this); }
};
-class Item_func_spatial_decomp: public Item_geometry_func
+class Item_func_spatial_decomp: public Item_geometry_func_args_geometry
{
enum Functype decomp_func;
public:
Item_func_spatial_decomp(THD *thd, Item *a, Item_func::Functype ft):
- Item_geometry_func(thd, a) { decomp_func = ft; }
+ Item_geometry_func_args_geometry(thd, a) { decomp_func = ft; }
const char *func_name() const
{
switch (decomp_func)
@@ -268,12 +454,19 @@ public:
{ return get_item_copy<Item_func_spatial_decomp>(thd, mem_root, this); }
};
-class Item_func_spatial_decomp_n: public Item_geometry_func
+class Item_func_spatial_decomp_n: public Item_geometry_func_args_geometry
{
enum Functype decomp_func_n;
+ bool check_arguments() const
+ {
+ return Item_geometry_func_args_geometry::check_arguments() ||
+ args[1]->check_type_can_return_int(func_name());
+ }
public:
- Item_func_spatial_decomp_n(THD *thd, Item *a, Item *b, Item_func::Functype ft):
- Item_geometry_func(thd, a, b) { decomp_func_n = ft; }
+ Item_func_spatial_decomp_n(THD *thd, Item *a, Item *b, Item_func::Functype ft)
+ :Item_geometry_func_args_geometry(thd, a, b),
+ decomp_func_n(ft)
+ { }
const char *func_name() const
{
switch (decomp_func_n)
@@ -296,6 +489,10 @@ public:
class Item_func_spatial_collection: public Item_geometry_func
{
+ bool check_arguments() const
+ {
+ return check_argument_types_or_binary(&type_handler_geometry, 0, arg_count);
+ }
String tmp_value;
enum Geometry::wkbType coll_type;
enum Geometry::wkbType item_type;
@@ -342,6 +539,11 @@ protected:
SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field,
KEY_PART *key_part,
Item_func::Functype type, Item *value);
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 2);
+ return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+ }
public:
Item_func_spatial_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel):
Item_bool_func2_with_rev(thd, a, b), spatial_rel(sp_rel)
@@ -392,15 +594,20 @@ public:
};
-class Item_func_spatial_relate: public Item_bool_func
+class Item_func_spatial_relate: public Item_bool_func_args_geometry_geometry
{
Gcalc_heap collector;
Gcalc_scan_iterator scan_it;
Gcalc_function func;
String tmp_value1, tmp_value2, tmp_matrix;
+ bool check_arguments() const
+ {
+ return Item_bool_func_args_geometry_geometry::check_arguments() ||
+ args[2]->check_type_general_purpose_string(func_name());
+ }
public:
Item_func_spatial_relate(THD *thd, Item *a, Item *b, Item *matrix):
- Item_bool_func(thd, a, b, matrix)
+ Item_bool_func_args_geometry_geometry(thd, a, b, matrix)
{ }
longlong val_int();
const char *func_name() const { return "st_relate"; }
@@ -416,6 +623,11 @@ public:
class Item_func_spatial_operation: public Item_geometry_func
{
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 2);
+ return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+ }
public:
Gcalc_function::op_type spatial_op;
Gcalc_heap collector;
@@ -441,8 +653,13 @@ public:
};
-class Item_func_buffer: public Item_geometry_func
+class Item_func_buffer: public Item_geometry_func_args_geometry
{
+ bool check_arguments() const
+ {
+ return Item_geometry_func_args_geometry::check_arguments() ||
+ args[1]->check_type_can_return_real(func_name());
+ }
protected:
class Transporter : public Gcalc_operation_transporter
{
@@ -485,8 +702,8 @@ protected:
String tmp_value;
public:
- Item_func_buffer(THD *thd, Item *obj, Item *distance):
- Item_geometry_func(thd, obj, distance) {}
+ Item_func_buffer(THD *thd, Item *obj, Item *distance)
+ :Item_geometry_func_args_geometry(thd, obj, distance) {}
const char *func_name() const { return "st_buffer"; }
String *val_str(String *);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -494,10 +711,11 @@ public:
};
-class Item_func_isempty: public Item_bool_func
+class Item_func_isempty: public Item_bool_func_args_geometry
{
public:
- Item_func_isempty(THD *thd, Item *a): Item_bool_func(thd, a) {}
+ Item_func_isempty(THD *thd, Item *a)
+ :Item_bool_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_isempty"; }
void fix_length_and_dec() { maybe_null= 1; }
@@ -506,14 +724,15 @@ public:
{ return get_item_copy<Item_func_isempty>(thd, mem_root, this); }
};
-class Item_func_issimple: public Item_int_func
+class Item_func_issimple: public Item_long_func_args_geometry
{
Gcalc_heap collector;
Gcalc_function func;
Gcalc_scan_iterator scan_it;
String tmp;
public:
- Item_func_issimple(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_issimple(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_issimple"; }
void fix_length_and_dec() { decimals=0; max_length=2; }
@@ -522,10 +741,11 @@ public:
{ return get_item_copy<Item_func_issimple>(thd, mem_root, this); }
};
-class Item_func_isclosed: public Item_int_func
+class Item_func_isclosed: public Item_long_func_args_geometry
{
public:
- Item_func_isclosed(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_isclosed(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_isclosed"; }
void fix_length_and_dec() { decimals=0; max_length=2; }
@@ -544,11 +764,11 @@ public:
{ return get_item_copy<Item_func_isring>(thd, mem_root, this); }
};
-class Item_func_dimension: public Item_int_func
+class Item_func_dimension: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_dimension(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_dimension(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_dimension"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -556,11 +776,11 @@ public:
{ return get_item_copy<Item_func_dimension>(thd, mem_root, this); }
};
-class Item_func_x: public Item_real_func
+
+class Item_func_x: public Item_real_func_args_geometry
{
- String value;
public:
- Item_func_x(THD *thd, Item *a): Item_real_func(thd, a) {}
+ Item_func_x(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_x"; }
void fix_length_and_dec()
@@ -573,11 +793,10 @@ public:
};
-class Item_func_y: public Item_real_func
+class Item_func_y: public Item_real_func_args_geometry
{
- String value;
public:
- Item_func_y(THD *thd, Item *a): Item_real_func(thd, a) {}
+ Item_func_y(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_y"; }
void fix_length_and_dec()
@@ -590,11 +809,11 @@ public:
};
-class Item_func_numgeometries: public Item_int_func
+class Item_func_numgeometries: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_numgeometries(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_numgeometries(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numgeometries"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -603,11 +822,11 @@ public:
};
-class Item_func_numinteriorring: public Item_int_func
+class Item_func_numinteriorring: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_numinteriorring(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_numinteriorring(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numinteriorrings"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -616,11 +835,11 @@ public:
};
-class Item_func_numpoints: public Item_int_func
+class Item_func_numpoints: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_numpoints(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_numpoints(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numpoints"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -629,11 +848,10 @@ public:
};
-class Item_func_area: public Item_real_func
+class Item_func_area: public Item_real_func_args_geometry
{
- String value;
public:
- Item_func_area(THD *thd, Item *a): Item_real_func(thd, a) {}
+ Item_func_area(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_area"; }
void fix_length_and_dec()
@@ -646,11 +864,12 @@ public:
};
-class Item_func_glength: public Item_real_func
+class Item_func_glength: public Item_real_func_args_geometry
{
String value;
public:
- Item_func_glength(THD *thd, Item *a): Item_real_func(thd, a) {}
+ Item_func_glength(THD *thd, Item *a)
+ :Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_length"; }
void fix_length_and_dec()
@@ -663,11 +882,11 @@ public:
};
-class Item_func_srid: public Item_int_func
+class Item_func_srid: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_srid(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_srid(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "srid"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -676,7 +895,7 @@ public:
};
-class Item_func_distance: public Item_real_func
+class Item_func_distance: public Item_real_func_args_geometry_geometry
{
String tmp_value1;
String tmp_value2;
@@ -684,7 +903,8 @@ class Item_func_distance: public Item_real_func
Gcalc_function func;
Gcalc_scan_iterator scan_it;
public:
- Item_func_distance(THD *thd, Item *a, Item *b): Item_real_func(thd, a, b) {}
+ Item_func_distance(THD *thd, Item *a, Item *b)
+ :Item_real_func_args_geometry_geometry(thd, a, b) {}
double val_real();
const char *func_name() const { return "st_distance"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -692,14 +912,15 @@ public:
};
-class Item_func_pointonsurface: public Item_geometry_func
+class Item_func_pointonsurface: public Item_geometry_func_args_geometry
{
String tmp_value;
Gcalc_heap collector;
Gcalc_function func;
Gcalc_scan_iterator scan_it;
public:
- Item_func_pointonsurface(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+ Item_func_pointonsurface(THD *thd, Item *a)
+ :Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_pointonsurface"; }
String *val_str(String *);
Field::geometry_type get_geometry_type() const;
@@ -709,11 +930,12 @@ public:
#ifndef DBUG_OFF
-class Item_func_gis_debug: public Item_int_func
+class Item_func_gis_debug: public Item_long_func
{
public:
- Item_func_gis_debug(THD *thd, Item *a): Item_int_func(thd, a)
+ Item_func_gis_debug(THD *thd, Item *a): Item_long_func(thd, a)
{ null_value= false; }
+ void fix_length_and_dec() { fix_char_length(10); }
const char *func_name() const { return "st_gis_debug"; }
longlong val_int();
bool check_vcol_func_processor(void *arg)
diff --git a/sql/item_inetfunc.h b/sql/item_inetfunc.h
index 741b9f7d997..33586c29175 100644
--- a/sql/item_inetfunc.h
+++ b/sql/item_inetfunc.h
@@ -24,10 +24,10 @@
Item_func_inet_aton implements INET_ATON() SQL-function.
*************************************************************************/
-class Item_func_inet_aton : public Item_int_func
+class Item_func_inet_aton : public Item_longlong_func
{
public:
- Item_func_inet_aton(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_inet_aton(THD *thd, Item *a): Item_longlong_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "inet_aton"; }
void fix_length_and_dec()
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index fd5b4a98e0e..9e9b26e2119 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -390,7 +390,7 @@ longlong Item_func_json_valid::val_int()
void Item_func_json_exists::fix_length_and_dec()
{
- Item_int_func::fix_length_and_dec();
+ Item_bool_func::fix_length_and_dec();
maybe_null= 1;
path.set_constant_flag(args[1]->const_item());
}
@@ -890,7 +890,7 @@ void Item_func_json_contains::fix_length_and_dec()
maybe_null= 1;
if (arg_count > 2)
path.set_constant_flag(args[2]->const_item());
- Item_int_func::fix_length_and_dec();
+ Item_bool_func::fix_length_and_dec();
}
@@ -1135,7 +1135,7 @@ void Item_func_json_contains_path::fix_length_and_dec()
ooa_parsed= FALSE;
maybe_null= 1;
mark_constant_paths(paths, args+2, arg_count-2);
- Item_int_func::fix_length_and_dec();
+ Item_bool_func::fix_length_and_dec();
}
@@ -2050,6 +2050,7 @@ void Item_func_json_length::fix_length_and_dec()
if (arg_count > 1)
path.set_constant_flag(args[1]->const_item());
maybe_null= 1;
+ max_length= 10;
}
diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h
index 394ed5f189a..4235bd3ea9f 100644
--- a/sql/item_jsonfunc.h
+++ b/sql/item_jsonfunc.h
@@ -40,27 +40,26 @@ public:
};
-class Item_func_json_valid: public Item_int_func
+class Item_func_json_valid: public Item_bool_func
{
protected:
String tmp_value;
public:
- Item_func_json_valid(THD *thd, Item *json) : Item_int_func(thd, json) {}
+ Item_func_json_valid(THD *thd, Item *json) : Item_bool_func(thd, json) {}
longlong val_int();
const char *func_name() const { return "json_valid"; }
void fix_length_and_dec()
{
- Item_int_func::fix_length_and_dec();
+ Item_bool_func::fix_length_and_dec();
maybe_null= 1;
}
- bool is_bool_type() { return true; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_json_valid>(thd, mem_root, this); }
};
-class Item_func_json_exists: public Item_int_func
+class Item_func_json_exists: public Item_bool_func
{
protected:
json_path_with_flags path;
@@ -68,9 +67,8 @@ protected:
public:
Item_func_json_exists(THD *thd, Item *js, Item *i_path):
- Item_int_func(thd, js, i_path) {}
+ Item_bool_func(thd, js, i_path) {}
const char *func_name() const { return "json_exists"; }
- bool is_bool_type() { return true; }
void fix_length_and_dec();
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_json_exists>(thd, mem_root, this); }
@@ -170,7 +168,7 @@ public:
};
-class Item_func_json_contains: public Item_int_func
+class Item_func_json_contains: public Item_bool_func
{
protected:
String tmp_js;
@@ -180,7 +178,7 @@ protected:
String tmp_val, *val;
public:
Item_func_json_contains(THD *thd, List<Item> &list):
- Item_int_func(thd, list) {}
+ Item_bool_func(thd, list) {}
const char *func_name() const { return "json_contains"; }
void fix_length_and_dec();
longlong val_int();
@@ -189,7 +187,7 @@ public:
};
-class Item_func_json_contains_path: public Item_int_func
+class Item_func_json_contains_path: public Item_bool_func
{
protected:
String tmp_js;
@@ -201,7 +199,7 @@ protected:
public:
Item_func_json_contains_path(THD *thd, List<Item> &list):
- Item_int_func(thd, list), tmp_paths(0) {}
+ Item_bool_func(thd, list), tmp_paths(0) {}
const char *func_name() const { return "json_contains_path"; }
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
@@ -290,7 +288,7 @@ public:
};
-class Item_func_json_length: public Item_int_func
+class Item_func_json_length: public Item_long_func
{
protected:
json_path_with_flags path;
@@ -298,7 +296,7 @@ protected:
String tmp_path;
public:
Item_func_json_length(THD *thd, List<Item> &list):
- Item_int_func(thd, list) {}
+ Item_long_func(thd, list) {}
const char *func_name() const { return "json_length"; }
void fix_length_and_dec();
longlong val_int();
@@ -307,13 +305,14 @@ public:
};
-class Item_func_json_depth: public Item_int_func
+class Item_func_json_depth: public Item_long_func
{
protected:
String tmp_js;
public:
- Item_func_json_depth(THD *thd, Item *js): Item_int_func(thd, js) {}
+ Item_func_json_depth(THD *thd, Item *js): Item_long_func(thd, js) {}
const char *func_name() const { return "json_depth"; }
+ void fix_length_and_dec() { max_length= 10; }
longlong val_int();
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_json_depth>(thd, mem_root, this); }
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index ee5646bdfc5..4fcff4c0d2e 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2013, Monty Program Ab.
+ Copyright (c) 2000, 2017, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -4005,6 +4005,7 @@ String *Item_func_quote::val_str(String *str)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+ ulong max_allowed_packet= current_thd->variables.max_allowed_packet;
char *from, *to, *end, *start;
String *arg= args[0]->val_str(str);
uint arg_length, new_length;
@@ -4023,11 +4024,14 @@ String *Item_func_quote::val_str(String *str)
new_length= arg_length + 2; /* for beginning and ending ' signs */
for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++)
new_length+= get_esc_bit(escmask, (uchar) *from);
+ if (new_length > max_allowed_packet)
+ goto toolong;
}
else
{
new_length= (arg_length * 2) + /* For string characters */
(2 * collation.collation->mbmaxlen); /* For quotes */
+ set_if_smaller(new_length, max_allowed_packet);
}
if (tmp_value.alloc(new_length))
@@ -4043,7 +4047,7 @@ String *Item_func_quote::val_str(String *str)
/* Put leading quote */
if ((mblen= cs->cset->wc_mb(cs, '\'', (uchar *) to, to_end)) <= 0)
- goto null;
+ goto toolong;
to+= mblen;
for (start= (char*) arg->ptr(), end= start + arg_length; start < end; )
@@ -4063,17 +4067,17 @@ String *Item_func_quote::val_str(String *str)
if (escape)
{
if ((mblen= cs->cset->wc_mb(cs, '\\', (uchar*) to, to_end)) <= 0)
- goto null;
+ goto toolong;
to+= mblen;
}
if ((mblen= cs->cset->wc_mb(cs, wc, (uchar*) to, to_end)) <= 0)
- goto null;
+ goto toolong;
to+= mblen;
}
/* Put trailing quote */
if ((mblen= cs->cset->wc_mb(cs, '\'', (uchar *) to, to_end)) <= 0)
- goto null;
+ goto toolong;
to+= mblen;
new_length= to - tmp_value.ptr();
goto ret;
@@ -4117,6 +4121,11 @@ ret:
null_value= 0;
return &tmp_value;
+toolong:
+ push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
+ ER_THD(current_thd, ER_WARN_ALLOWED_PACKET_OVERFLOWED),
+ func_name(), max_allowed_packet);
null:
null_value= 1;
return 0;
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 6e31d489574..6310d15b4e7 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -1444,11 +1444,11 @@ public:
{ return get_item_copy<Item_func_weight_string>(thd, mem_root, this); }
};
-class Item_func_crc32 :public Item_int_func
+class Item_func_crc32 :public Item_long_func
{
String value;
public:
- Item_func_crc32(THD *thd, Item *a): Item_int_func(thd, a)
+ Item_func_crc32(THD *thd, Item *a): Item_long_func(thd, a)
{ unsigned_flag= 1; }
const char *func_name() const { return "crc32"; }
void fix_length_and_dec() { max_length=10; }
@@ -1457,11 +1457,11 @@ public:
{ return get_item_copy<Item_func_crc32>(thd, mem_root, this); }
};
-class Item_func_uncompressed_length : public Item_int_func
+class Item_func_uncompressed_length : public Item_long_func
{
String value;
public:
- Item_func_uncompressed_length(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_uncompressed_length(THD *thd, Item *a): Item_long_func(thd, a) {}
const char *func_name() const{return "uncompressed_length";}
void fix_length_and_dec() { max_length=10; maybe_null= true; }
longlong val_int();
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 5d9e2e7c0cd..cb60b646979 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -721,6 +721,13 @@ public:
in_strategy= (SUBS_STRATEGY_CHOSEN | strategy);
DBUG_VOID_RETURN;
}
+
+ bool walk(Item_processor processor, bool walk_subquery, void *arg)
+ {
+ return left_expr->walk(processor, walk_subquery, arg) ||
+ Item_subselect::walk(processor, walk_subquery, arg);
+ }
+
bool exists2in_processor(void *opt_arg __attribute__((unused)))
{
return 0;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 77cd20e7386..9e26bd6f75e 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1210,7 +1210,7 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table)
field->flags&= ~NOT_NULL_FLAG;
return field;
}
- return Item_sum::create_tmp_field(group, table);
+ return tmp_table_field_from_field_type(table);
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index c1485738b11..65306ab6f48 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -508,10 +508,7 @@ public:
}
virtual void make_unique() { force_copy_fields= TRUE; }
Item *get_tmp_table_item(THD *thd);
- Field *create_tmp_field(bool group, TABLE *table)
- {
- return Item::create_tmp_field(group, table, MY_INT32_NUM_DECIMAL_DIGITS);
- }
+ Field *create_tmp_field(bool group, TABLE *table);
virtual bool collect_outer_ref_processor(void *param);
bool init_sum_func_check(THD *thd);
bool check_sum_func(THD *thd, Item **ref);
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index ced4bf4b31e..4cdf7b63158 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -33,10 +33,10 @@ enum date_time_format_types
bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval);
-class Item_func_period_add :public Item_int_func
+class Item_func_period_add :public Item_long_func
{
public:
- Item_func_period_add(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_func_period_add(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "period_add"; }
void fix_length_and_dec()
@@ -48,10 +48,10 @@ public:
};
-class Item_func_period_diff :public Item_int_func
+class Item_func_period_diff :public Item_long_func
{
public:
- Item_func_period_diff(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_func_period_diff(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "period_diff"; }
void fix_length_and_dec()
@@ -64,10 +64,10 @@ public:
};
-class Item_func_to_days :public Item_int_func
+class Item_func_to_days :public Item_long_func
{
public:
- Item_func_to_days(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_to_days(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "to_days"; }
void fix_length_and_dec()
@@ -89,16 +89,16 @@ public:
};
-class Item_func_to_seconds :public Item_int_func
+class Item_func_to_seconds :public Item_longlong_func
{
public:
- Item_func_to_seconds(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_to_seconds(THD *thd, Item *a): Item_longlong_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "to_seconds"; }
void fix_length_and_dec()
{
decimals=0;
- max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
+ fix_char_length(12);
maybe_null= 1;
}
enum_monotonicity_info get_monotonicity_info() const;
@@ -115,10 +115,10 @@ public:
};
-class Item_func_dayofmonth :public Item_int_func
+class Item_func_dayofmonth :public Item_long_func
{
public:
- Item_func_dayofmonth(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_dayofmonth(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "dayofmonth"; }
void fix_length_and_dec()
@@ -155,7 +155,7 @@ public:
return str;
}
const char *func_name() const { return "month"; }
- const Type_handler *type_handler() const { return &type_handler_longlong; }
+ const Type_handler *type_handler() const { return &type_handler_long; }
void fix_length_and_dec()
{
decimals= 0;
@@ -196,10 +196,10 @@ public:
};
-class Item_func_dayofyear :public Item_int_func
+class Item_func_dayofyear :public Item_long_func
{
public:
- Item_func_dayofyear(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_dayofyear(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "dayofyear"; }
void fix_length_and_dec()
@@ -219,10 +219,10 @@ public:
};
-class Item_func_hour :public Item_int_func
+class Item_func_hour :public Item_long_func
{
public:
- Item_func_hour(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_hour(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "hour"; }
void fix_length_and_dec()
@@ -242,10 +242,10 @@ public:
};
-class Item_func_minute :public Item_int_func
+class Item_func_minute :public Item_long_func
{
public:
- Item_func_minute(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_minute(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "minute"; }
void fix_length_and_dec()
@@ -265,10 +265,10 @@ public:
};
-class Item_func_quarter :public Item_int_func
+class Item_func_quarter :public Item_long_func
{
public:
- Item_func_quarter(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_quarter(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "quarter"; }
void fix_length_and_dec()
@@ -288,10 +288,10 @@ public:
};
-class Item_func_second :public Item_int_func
+class Item_func_second :public Item_long_func
{
public:
- Item_func_second(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_second(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "second"; }
void fix_length_and_dec()
@@ -311,11 +311,11 @@ public:
};
-class Item_func_week :public Item_int_func
+class Item_func_week :public Item_long_func
{
public:
- Item_func_week(THD *thd, Item *a): Item_int_func(thd, a) {}
- Item_func_week(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_func_week(THD *thd, Item *a): Item_long_func(thd, a) {}
+ Item_func_week(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "week"; }
void fix_length_and_dec()
@@ -338,10 +338,10 @@ public:
{ return get_item_copy<Item_func_week>(thd, mem_root, this); }
};
-class Item_func_yearweek :public Item_int_func
+class Item_func_yearweek :public Item_long_func
{
public:
- Item_func_yearweek(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_func_yearweek(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "yearweek"; }
void fix_length_and_dec()
@@ -361,10 +361,10 @@ public:
};
-class Item_func_year :public Item_int_func
+class Item_func_year :public Item_long_func
{
public:
- Item_func_year(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_year(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "year"; }
enum_monotonicity_info get_monotonicity_info() const;
@@ -404,7 +404,7 @@ public:
{
return (odbc_type ? "dayofweek" : "weekday");
}
- const Type_handler *type_handler() const { return &type_handler_longlong; }
+ const Type_handler *type_handler() const { return &type_handler_long; }
void fix_length_and_dec()
{
decimals= 0;
@@ -449,7 +449,10 @@ public:
decimals= dec;
max_length=17 + (decimals ? decimals + 1 : 0);
maybe_null= true;
- set_handler_by_result_type(decimals ? DECIMAL_RESULT : INT_RESULT);
+ if (decimals)
+ set_handler(&type_handler_newdecimal);
+ else
+ set_handler(type_handler_long_or_longlong());
}
double real_op() { DBUG_ASSERT(0); return 0; }
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
@@ -530,8 +533,6 @@ public:
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date) { DBUG_ASSERT(0); return 1; }
my_decimal *val_decimal(my_decimal *decimal_value)
{ return val_decimal_from_date(decimal_value); }
- Field *create_field_for_create_select(TABLE *table)
- { return tmp_table_field_from_field_type(table); }
int save_in_field(Field *field, bool no_conversions)
{ return save_date_in_field(field, no_conversions); }
};
@@ -1012,9 +1013,6 @@ class Item_extract :public Item_int_func
}
return true;
}
- Field *create_field_for_create_select(TABLE *table)
- { return tmp_table_field_from_field_type(table); }
-
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_extract>(thd, mem_root, this); }
};
@@ -1177,16 +1175,17 @@ public:
};
-class Item_func_microsecond :public Item_int_func
+class Item_func_microsecond :public Item_long_func
{
public:
- Item_func_microsecond(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_microsecond(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "microsecond"; }
void fix_length_and_dec()
{
decimals=0;
maybe_null=1;
+ fix_char_length(6);
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -1199,12 +1198,12 @@ public:
};
-class Item_func_timestamp_diff :public Item_int_func
+class Item_func_timestamp_diff :public Item_longlong_func
{
const interval_type int_type;
public:
Item_func_timestamp_diff(THD *thd, Item *a, Item *b, interval_type type_arg):
- Item_int_func(thd, a, b), int_type(type_arg) {}
+ Item_longlong_func(thd, a, b), int_type(type_arg) {}
const char *func_name() const { return "timestampdiff"; }
longlong val_int();
void fix_length_and_dec()
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index 90df6e27f6c..ba33d103d0c 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -1,4 +1,5 @@
-/* Copyright (c) 2005, 2013, Oracle and/or its affiliates.
+/* Copyright (c) 2005, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -461,13 +462,13 @@ public:
};
-class Item_func_xpath_position :public Item_int_func
+class Item_func_xpath_position :public Item_long_func
{
String *pxml;
String tmp_value;
public:
Item_func_xpath_position(THD *thd, Item *a, String *p):
- Item_int_func(thd, a), pxml(p) {}
+ Item_long_func(thd, a), pxml(p) {}
const char *func_name() const { return "xpath_position"; }
void fix_length_and_dec() { max_length=10; }
longlong val_int()
@@ -482,13 +483,13 @@ public:
};
-class Item_func_xpath_count :public Item_int_func
+class Item_func_xpath_count :public Item_long_func
{
String *pxml;
String tmp_value;
public:
Item_func_xpath_count(THD *thd, Item *a, String *p):
- Item_int_func(thd, a), pxml(p) {}
+ Item_long_func(thd, a), pxml(p) {}
const char *func_name() const { return "xpath_count"; }
void fix_length_and_dec() { max_length=10; }
longlong val_int()
@@ -2836,9 +2837,9 @@ int xml_enter(MY_XML_PARSER *st,const char *attr, size_t len)
node.parent= data->parent; // Set parent for the new node to old parent
data->parent= numnodes; // Remember current node as new parent
- DBUG_ASSERT(data->level <= MAX_LEVEL);
+ DBUG_ASSERT(data->level < MAX_LEVEL);
data->pos[data->level]= numnodes;
- if (data->level < MAX_LEVEL)
+ if (data->level < MAX_LEVEL - 1)
node.level= data->level++;
else
return MY_XML_ERROR;
diff --git a/sql/log.cc b/sql/log.cc
index 83e1724b195..0ffa4a5a82d 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -9662,6 +9662,8 @@ binlog_background_thread(void *arg __attribute__((unused)))
{
THD_STAGE_INFO(thd, stage_binlog_processing_checkpoint_notify);
DEBUG_SYNC(thd, "binlog_background_thread_before_mark_xid_done");
+ /* Set the thread start time */
+ thd->set_time();
/* Grab next pointer first, as mark_xid_done() may free the element. */
next= queue->next_in_queue;
mysql_bin_log.mark_xid_done(queue->binlog_id, true);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 383972d1a54..3c062975041 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -12525,7 +12525,9 @@ Rows_log_event::write_row(rpl_group_info *rgi,
TODO: Add safety measures against infinite looping.
*/
- while ((error= table->file->ha_write_row(table->record[0])))
+ if (table->s->sequence)
+ error= update_sequence();
+ else while ((error= table->file->ha_write_row(table->record[0])))
{
if (error == HA_ERR_LOCK_DEADLOCK ||
error == HA_ERR_LOCK_WAIT_TIMEOUT ||
@@ -12692,6 +12694,33 @@ Rows_log_event::write_row(rpl_group_info *rgi,
DBUG_RETURN(error);
}
+
+int Rows_log_event::update_sequence()
+{
+ TABLE *table= m_table; // pointer to event's table
+
+ if (!bitmap_is_set(table->rpl_write_set, MIN_VALUE_FIELD_NO))
+ {
+ /* This event come from a setval function executed on the master.
+ Update the sequence next_number and round, like we do with setval()
+ */
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table,
+ table->read_set);
+ longlong nextval= table->field[NEXT_FIELD_NO]->val_int();
+ longlong round= table->field[ROUND_FIELD_NO]->val_int();
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+
+ return table->s->sequence->set_value(table, nextval, round, 0);
+ }
+
+ /*
+ Update all fields in table and update the active sequence, like with
+ ALTER SEQUENCE
+ */
+ return table->file->ha_write_row(table->record[0]);
+}
+
+
#endif
int
diff --git a/sql/log_event.h b/sql/log_event.h
index e79c88c28f1..3497ffab26d 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -4606,6 +4606,7 @@ protected:
int find_key(); // Find a best key to use in find_row()
int find_row(rpl_group_info *);
int write_row(rpl_group_info *, const bool);
+ int update_sequence();
// Unpack the current row into m_table->record[0], but with
// a different columns bitmap.
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index 381f4129321..9ba29ddb0f6 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -221,6 +221,8 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, rpl_group_info *rgi)
/* A small test to verify that objects have consistent types */
DBUG_ASSERT(sizeof(ev_thd->variables.option_bits) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS));
+ table->rpl_write_set= table->write_set;
+
error= do_before_row_operations(table);
while (error == 0 && row_start < ev->m_rows_end)
{
diff --git a/sql/mdl.cc b/sql/mdl.cc
index db7291d9b6a..87a0171a193 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -2328,12 +2328,6 @@ MDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket,
if (mdl_ticket->has_stronger_or_equal_type(new_type))
DBUG_RETURN(FALSE);
- /* Only allow upgrades from SHARED_UPGRADABLE/NO_WRITE/NO_READ_WRITE/READ */
- DBUG_ASSERT(mdl_ticket->m_type == MDL_SHARED_UPGRADABLE ||
- mdl_ticket->m_type == MDL_SHARED_NO_WRITE ||
- mdl_ticket->m_type == MDL_SHARED_NO_READ_WRITE ||
- mdl_ticket->m_type == MDL_SHARED_READ);
-
mdl_xlock_request.init(&mdl_ticket->m_lock->key, new_type,
MDL_TRANSACTION);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index eb39e542c41..d7c46071c38 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -330,9 +330,13 @@ static PSI_thread_key key_thread_handle_con_sockets;
static PSI_thread_key key_thread_handle_shutdown;
#endif /* __WIN__ */
-#if defined (HAVE_OPENSSL) && !defined(HAVE_YASSL)
+#ifdef HAVE_OPENSSL
+#include <ssl_compat.h>
+
+#ifdef HAVE_OPENSSL10
static PSI_rwlock_key key_rwlock_openssl;
#endif
+#endif
#endif /* HAVE_PSI_INTERFACE */
#ifdef HAVE_NPTL
@@ -623,6 +627,7 @@ Time_zone *default_tz;
const char *mysql_real_data_home_ptr= mysql_real_data_home;
char server_version[SERVER_VERSION_LENGTH], *server_version_ptr;
+bool using_custom_server_version= false;
char *mysqld_unix_port, *opt_mysql_tmpdir;
ulong thread_handling;
@@ -920,8 +925,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
key_PARTITION_LOCK_auto_inc;
PSI_mutex_key key_RELAYLOG_LOCK_index;
PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state,
- key_LOCK_rpl_thread, key_LOCK_rpl_thread_pool, key_LOCK_parallel_entry,
- key_LOCK_SEQUENCE;
+ key_LOCK_rpl_thread, key_LOCK_rpl_thread_pool, key_LOCK_parallel_entry;
PSI_mutex_key key_LOCK_stats,
key_LOCK_global_user_client_stats, key_LOCK_global_table_stats,
@@ -1006,7 +1010,6 @@ static PSI_mutex_info all_server_mutexes[]=
{ &key_LOCK_slave_state, "LOCK_slave_state", 0},
{ &key_LOCK_start_thread, "LOCK_start_thread", PSI_FLAG_GLOBAL},
{ &key_LOCK_binlog_state, "LOCK_binlog_state", 0},
- { &key_LOCK_SEQUENCE, "SQUENCE::LOCK_SEQUENCE", 0},
{ &key_LOCK_rpl_thread, "LOCK_rpl_thread", 0},
{ &key_LOCK_rpl_thread_pool, "LOCK_rpl_thread_pool", 0},
{ &key_LOCK_parallel_entry, "LOCK_parallel_entry", 0}
@@ -1014,17 +1017,20 @@ static PSI_mutex_info all_server_mutexes[]=
PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
- key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock;
+ key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock,
+ key_LOCK_SEQUENCE;
+
static PSI_rwlock_info all_server_rwlocks[]=
{
-#if defined (HAVE_OPENSSL) && !defined(HAVE_YASSL)
+#ifdef HAVE_OPENSSL10
{ &key_rwlock_openssl, "CRYPTO_dynlock_value::lock", 0},
#endif
{ &key_rwlock_LOCK_grant, "LOCK_grant", PSI_FLAG_GLOBAL},
{ &key_rwlock_LOCK_logger, "LOGGER::LOCK_logger", 0},
{ &key_rwlock_LOCK_sys_init_connect, "LOCK_sys_init_connect", PSI_FLAG_GLOBAL},
{ &key_rwlock_LOCK_sys_init_slave, "LOCK_sys_init_slave", PSI_FLAG_GLOBAL},
+ { &key_LOCK_SEQUENCE, "LOCK_SEQUENCE", 0},
{ &key_rwlock_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL},
{ &key_rwlock_query_cache_query_lock, "Query_cache_query::lock", 0}
};
@@ -1494,7 +1500,7 @@ scheduler_functions *thread_scheduler= &thread_scheduler_struct,
#ifdef HAVE_OPENSSL
#include <openssl/crypto.h>
-#ifndef HAVE_YASSL
+#ifdef HAVE_OPENSSL10
typedef struct CRYPTO_dynlock_value
{
mysql_rwlock_t lock;
@@ -1505,7 +1511,7 @@ static openssl_lock_t *openssl_dynlock_create(const char *, int);
static void openssl_dynlock_destroy(openssl_lock_t *, const char *, int);
static void openssl_lock_function(int, int, const char *, int);
static void openssl_lock(int, openssl_lock_t *, const char *, int);
-#endif
+#endif /* HAVE_OPENSSL10 */
char *des_key_file;
#ifndef EMBEDDED_LIBRARY
struct st_VioSSLFd *ssl_acceptor_fd;
@@ -2325,11 +2331,11 @@ static void clean_up_mutexes()
mysql_mutex_destroy(&LOCK_global_index_stats);
#ifdef HAVE_OPENSSL
mysql_mutex_destroy(&LOCK_des_key_file);
-#ifndef HAVE_YASSL
+#ifdef HAVE_OPENSSL10
for (int i= 0; i < CRYPTO_num_locks(); ++i)
mysql_rwlock_destroy(&openssl_stdlocks[i].lock);
OPENSSL_free(openssl_stdlocks);
-#endif /* HAVE_YASSL */
+#endif /* HAVE_OPENSSL10 */
#endif /* HAVE_OPENSSL */
#ifdef HAVE_REPLICATION
mysql_mutex_destroy(&LOCK_rpl_status);
@@ -3184,7 +3190,7 @@ LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers)
}
-static void init_signals(void)
+void init_signals(void)
{
if(opt_console)
SetConsoleCtrlHandler(console_event_handler,TRUE);
@@ -3315,7 +3321,7 @@ static size_t my_setstacksize(pthread_attr_t *attr, size_t stacksize)
#ifndef EMBEDDED_LIBRARY
-static void init_signals(void)
+void init_signals(void)
{
sigset_t set;
struct sigaction sa;
@@ -4140,6 +4146,14 @@ static int init_common_variables()
return 1;
}
+#ifdef HAVE_OPENSSL
+ if (check_openssl_compatibility())
+ {
+ sql_print_error("Incompatible OpenSSL version. Cannot continue...");
+ return 1;
+ }
+#endif
+
if (init_thread_environment() ||
mysql_init_variables())
return 1;
@@ -4699,7 +4713,7 @@ static int init_thread_environment()
#ifdef HAVE_OPENSSL
mysql_mutex_init(key_LOCK_des_key_file,
&LOCK_des_key_file, MY_MUTEX_INIT_FAST);
-#ifndef HAVE_YASSL
+#ifdef HAVE_OPENSSL10
openssl_stdlocks= (openssl_lock_t*) OPENSSL_malloc(CRYPTO_num_locks() *
sizeof(openssl_lock_t));
for (int i= 0; i < CRYPTO_num_locks(); ++i)
@@ -4708,8 +4722,8 @@ static int init_thread_environment()
CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy);
CRYPTO_set_dynlock_lock_callback(openssl_lock);
CRYPTO_set_locking_callback(openssl_lock_function);
-#endif
-#endif
+#endif /* HAVE_OPENSSL10 */
+#endif /* HAVE_OPENSSL */
mysql_rwlock_init(key_rwlock_LOCK_sys_init_connect, &LOCK_sys_init_connect);
mysql_rwlock_init(key_rwlock_LOCK_sys_init_slave, &LOCK_sys_init_slave);
mysql_rwlock_init(key_rwlock_LOCK_grant, &LOCK_grant);
@@ -4743,7 +4757,7 @@ static int init_thread_environment()
}
-#if defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)
+#ifdef HAVE_OPENSSL10
static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
{
openssl_lock_t *lock= new openssl_lock_t;
@@ -4803,8 +4817,7 @@ static void openssl_lock(int mode, openssl_lock_t *lock, const char *file,
abort();
}
}
-#endif /* HAVE_OPENSSL */
-
+#endif /* HAVE_OPENSSL10 */
static void init_ssl()
{
@@ -6302,7 +6315,7 @@ static void bootstrap(MYSQL_FILE *file)
thd->variables.wsrep_on= 0;
#endif
thd->bootstrap=1;
- my_net_init(&thd->net,(st_vio*) 0, (void*) 0, MYF(0));
+ my_net_init(&thd->net,(st_vio*) 0, thd, MYF(0));
thd->max_client_packet_length= thd->net.max_packet;
thd->security_ctx->master_access= ~(ulong)0;
in_bootstrap= TRUE;
@@ -8967,6 +8980,7 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument)
{
strmake(server_version, argument, sizeof(server_version) - 1);
set_sys_var_value_origin(&server_version_ptr, sys_var::CONFIG);
+ using_custom_server_version= true;
}
#ifndef EMBEDDED_LIBRARY
else
diff --git a/sql/mysqld.h b/sql/mysqld.h
index edda7e530fe..b7de4ecc324 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -301,7 +301,7 @@ extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
key_rpl_group_info_sleep_lock,
key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
- key_LOCK_start_thread, key_LOCK_SEQUENCE,
+ key_LOCK_start_thread,
key_LOCK_error_messages, key_LOCK_thread_count, key_PARTITION_LOCK_auto_inc;
extern PSI_mutex_key key_RELAYLOG_LOCK_index;
extern PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state,
@@ -314,8 +314,8 @@ extern PSI_mutex_key key_LOCK_gtid_waiting;
extern PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
- key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock;
-
+ key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock,
+ key_LOCK_SEQUENCE;
#ifdef HAVE_MMAP
extern PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
#endif /* HAVE_MMAP */
@@ -545,6 +545,7 @@ extern const char *mysql_real_data_home_ptr;
extern ulong thread_handling;
extern "C" MYSQL_PLUGIN_IMPORT char server_version[SERVER_VERSION_LENGTH];
extern char *server_version_ptr;
+extern bool using_custom_server_version;
extern MYSQL_PLUGIN_IMPORT char mysql_real_data_home[];
extern char mysql_unpacked_real_data_home[];
extern MYSQL_PLUGIN_IMPORT struct system_variables global_system_variables;
@@ -781,20 +782,6 @@ inline void dec_thread_running()
extern void set_server_version(char *buf, size_t size);
-#if defined(MYSQL_DYNAMIC_PLUGIN) && defined(_WIN32)
-extern "C" THD *_current_thd_noinline();
-#define _current_thd() _current_thd_noinline()
-#else
-/*
- THR_THD is a key which will be used to set/get THD* for a thread,
- using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr().
-*/
-extern pthread_key(THD*, THR_THD);
-inline THD *_current_thd(void)
-{
- return my_pthread_getspecific_ptr(THD*,THR_THD);
-}
-#endif
#define current_thd _current_thd()
inline int set_current_thd(THD *thd)
{
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 97a6421ec5c..1f282e6aee5 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -7486,3 +7486,7 @@ ER_UNKNOWN_SEQUENCES 42S02
eng "Unknown SEQUENCE: '%-.300s'"
ER_UNKNOWN_VIEW 42S02
eng "Unknown VIEW: '%-.300s'"
+ER_WRONG_INSERT_INTO_SEQUENCE
+ eng "Wrong INSERT into a SEQUENCE. One can only do single table INSERT into a squence object (like with mysqldump). If you want to change the SEQUENCE, use ALTER SEQUENCE instead."
+ER_SP_STACK_TRACE
+ eng "At line %u in %s"
diff --git a/sql/slave.cc b/sql/slave.cc
index b2cbac44c1b..641bdae9e31 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -40,6 +40,7 @@
#include <my_dir.h>
#include <sql_common.h>
#include <errmsg.h>
+#include <ssl_compat.h>
#include <mysqld_error.h>
#include <mysys_err.h>
#include "rpl_handler.h"
@@ -60,7 +61,6 @@
#include "debug_sync.h"
#include "rpl_parallel.h"
-
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
#define MAX_SLAVE_RETRY_PAUSE 5
@@ -4671,9 +4671,7 @@ err_during_init:
DBUG_LEAVE; // Must match DBUG_ENTER()
my_thread_end();
-#ifdef HAVE_OPENSSL
ERR_remove_state(0);
-#endif
pthread_exit(0);
return 0; // Avoid compiler warnings
}
@@ -5336,9 +5334,7 @@ err_during_init:
DBUG_LEAVE; // Must match DBUG_ENTER()
my_thread_end();
-#ifdef HAVE_OPENSSL
ERR_remove_state(0);
-#endif
pthread_exit(0);
return 0; // Avoid compiler warnings
}
diff --git a/sql/sp.cc b/sql/sp.cc
index aa353f8d594..9c130eac52d 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2002, 2015, Oracle and/or its affiliates.
- Copyright (c) 2009, 2015, MariaDB
+ Copyright (c) 2002, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 80730a9b060..f8ad3c305a7 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1178,11 +1178,10 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
/* Discard the initial part of executing routines. */
thd->profiling.discard_current_query();
#endif
+ sp_instr *i;
DEBUG_SYNC(thd, "sp_head_execute_before_loop");
do
{
- sp_instr *i;
-
#if defined(ENABLED_PROFILING)
/*
Treat each "instr" of a routine as discrete unit that could be profiled.
@@ -1342,6 +1341,13 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
da->opt_clear_warning_info(thd->query_id);
da->copy_sql_conditions_from_wi(thd, &sp_wi);
da->remove_marked_sql_conditions();
+ if (i != NULL)
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_SP_STACK_TRACE,
+ ER_THD(thd, ER_SP_STACK_TRACE),
+ i->m_lineno,
+ m_qname.str != NULL ? m_qname.str :
+ "anonymous block");
}
}
@@ -2770,6 +2776,7 @@ int sp_head::add_instr(sp_instr *instr)
entire stored procedure, as their life span is equal.
*/
instr->mem_root= &main_mem_root;
+ instr->m_lineno= m_thd->m_parser_state->m_lip.yylineno;
return insert_dynamic(&m_instr, (uchar*)&instr);
}
diff --git a/sql/sp_head.h b/sql/sp_head.h
index cfc2e6861d7..a96ef514429 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -888,6 +888,7 @@ public:
uint marked;
uint m_ip; ///< My index
sp_pcontext *m_ctx; ///< My parse context
+ uint m_lineno;
/// Should give each a name or type code for debugging purposes?
sp_instr(uint ip, sp_pcontext *ctx)
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index d6cdb252a85..d63a2f2bc51 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -7524,7 +7524,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
Security_context *sctx= thd->security_ctx;
uint i;
- ulong orig_want_access= want_access;
+ ulong original_want_access= want_access;
bool locked= 0;
GRANT_TABLE *grant_table;
GRANT_TABLE *grant_table_role= NULL;
@@ -7558,6 +7558,16 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
TABLE_LIST *const t_ref=
tl->correspondent_table ? tl->correspondent_table : tl;
sctx= t_ref->security_ctx ? t_ref->security_ctx : thd->security_ctx;
+ ulong orig_want_access= original_want_access;
+
+ if (t_ref->sequence)
+ {
+ /* We want to have either SELECT or INSERT rights to sequences depending
+ on how they are accessed
+ */
+ orig_want_access= ((t_ref->lock_type == TL_WRITE_ALLOW_WRITE) ?
+ INSERT_ACL : SELECT_ACL);
+ }
const ACL_internal_table_access *access=
get_cached_table_access(&t_ref->grant.m_internal,
@@ -12067,7 +12077,13 @@ static bool send_server_handshake_packet(MPVIO_EXT *mpvio,
data_len= SCRAMBLE_LENGTH;
}
- end= strxnmov(end, SERVER_VERSION_LENGTH, RPL_VERSION_HACK, server_version, NullS) + 1;
+ /* When server version is specified in config file, don't include
+ the replication hack prefix. */
+ if (using_custom_server_version)
+ end= strnmov(end, server_version, SERVER_VERSION_LENGTH) + 1;
+ else
+ end= strxnmov(end, SERVER_VERSION_LENGTH, RPL_VERSION_HACK, server_version, NullS) + 1;
+
int4store((uchar*) end, mpvio->auth_info.thd->thread_id);
end+= 4;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 5e13d7cd759..9fab6c5e252 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -4262,8 +4262,9 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx,
else
lock_type= TL_READ;
- if (table_already_fk_prelocked(table_list, fk->foreign_db,
- fk->foreign_table, lock_type))
+ if (table_already_fk_prelocked(prelocking_ctx->query_tables,
+ fk->foreign_db, fk->foreign_table,
+ lock_type))
continue;
TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 5b8aa9ce2aa..076ae8b9923 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1985,7 +1985,7 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use,
if (!thd_table->needs_reopen())
{
signalled|= mysql_lock_abort_for_thread(this, thd_table);
- if (this && WSREP(this) && wsrep_thd_is_BF(this, FALSE))
+ if (WSREP(this) && wsrep_thd_is_BF(this, FALSE))
{
WSREP_DEBUG("remove_table_from_cache: %llu",
(unsigned long long) this->real_id);
@@ -4106,16 +4106,12 @@ my_bool thd_net_is_killed()
void thd_increment_bytes_received(void *thd, ulong length)
{
- if (unlikely(!thd)) // Called from federatedx
- thd= current_thd;
((THD*) thd)->status_var.bytes_received+= length;
}
void thd_increment_net_big_packet_count(void *thd, ulong length)
{
- if (unlikely(!thd)) // Called from federatedx
- thd= current_thd;
((THD*) thd)->status_var.net_big_packet_count+= length;
}
@@ -5922,8 +5918,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
table->table->file->ht)
multi_write_engine= TRUE;
if (table->table->s->non_determinstic_insert &&
- lex->sql_command != SQLCOM_CREATE_SEQUENCE &&
- lex->sql_command != SQLCOM_CREATE_TABLE)
+ !(sql_command_flags[lex->sql_command] & CF_SCHEMA_CHANGE))
has_write_tables_with_unsafe_statements= true;
trans= table->table->file->has_transactions();
diff --git a/sql/sql_const.h b/sql/sql_const.h
index 2fa4b01b0a5..8d5f56de6b0 100644
--- a/sql/sql_const.h
+++ b/sql/sql_const.h
@@ -69,6 +69,7 @@
#define RAND_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-1))
#define PSEUDO_TABLE_BITS (PARAM_TABLE_BIT | OUTER_REF_TABLE_BIT | \
RAND_TABLE_BIT)
+#define CONNECT_STRING_MAXLEN 65535 /* stored in 2 bytes in .frm */
#define MAX_FIELDS 4096 /* Limit in the .frm file */
#define MAX_PARTITIONS 8192
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 1a5fac30536..132da4dff65 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -431,7 +431,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
else
tot_length+= field->field_length;
}
- else if (item->get_load_data_out_param())
+ else if (item->type() == Item::STRING_ITEM)
use_vars= 1;
}
if (use_blobs && !ex->line_term->length() && !field_term->length())
@@ -814,7 +814,11 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
if (item->real_type() == Item::FIELD_ITEM)
append_identifier(thd, &query_str, item->name.str, item->name.length);
else
- item->get_load_data_out_param()->load_data_print(thd, &query_str);
+ {
+ /* Actually Item_user_var_as_out_param despite claiming STRING_ITEM. */
+ DBUG_ASSERT(item->type() == Item::STRING_ITEM);
+ ((Item_user_var_as_out_param *)item)->print_for_load(thd, &query_str);
+ }
}
query_str.append(")");
}
@@ -1057,8 +1061,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
{
uint length;
uchar *pos;
- Item *real_item;
- Load_data_out_param *out_param;
+ Item_field *real_item;
if (read_info.read_field())
break;
@@ -1070,16 +1073,26 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
pos=read_info.row_start;
length=(uint) (read_info.row_end-pos);
- real_item= item->real_item();
+ real_item= item->field_for_view_update();
if ((!read_info.enclosed &&
(enclosed_length && length == 4 &&
!memcmp(pos, STRING_WITH_LEN("NULL")))) ||
(length == 1 && read_info.found_null))
{
- if (real_item->type() == Item::FIELD_ITEM)
+ if (item->type() == Item::STRING_ITEM)
+ {
+ ((Item_user_var_as_out_param *)item)->set_null_value(
+ read_info.read_charset);
+ }
+ else if (!real_item)
{
- Field *field= ((Item_field *)real_item)->field;
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name.str);
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ Field *field= real_item->field;
if (field->reset())
{
my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name.str,
@@ -1101,17 +1114,24 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
}
/* Do not auto-update this field. */
field->set_has_explicit_value();
- }
- else if ((out_param= item->get_load_data_out_param_or_error()))
- out_param->load_data_set_null_value(read_info.read_charset);
- else
- DBUG_RETURN(1);
+ }
+
continue;
}
- if (real_item->type() == Item::FIELD_ITEM)
+ if (item->type() == Item::STRING_ITEM)
{
- Field *field= ((Item_field *)real_item)->field;
+ ((Item_user_var_as_out_param *)item)->set_value((char*) pos, length,
+ read_info.read_charset);
+ }
+ else if (!real_item)
+ {
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name.str);
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ Field *field= real_item->field;
field->set_notnull();
read_info.row_end[0]=0; // Safe to change end marker
if (field == table->next_number_field)
@@ -1119,11 +1139,6 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
field->store((char*) pos, length, read_info.read_charset);
field->set_has_explicit_value();
}
- else if ((out_param= item->get_load_data_out_param_or_error()))
- out_param->load_data_set_value((const char *) pos, length,
- read_info.read_charset);
- else
- DBUG_RETURN(1);
}
if (thd->is_error())
@@ -1143,11 +1158,20 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
break;
for (; item ; item= it++)
{
- Load_data_out_param *out_param;
- Item *real_item= item->real_item();
- if (real_item->type() == Item::FIELD_ITEM)
+ Item_field *real_item= item->field_for_view_update();
+ if (item->type() == Item::STRING_ITEM)
+ {
+ ((Item_user_var_as_out_param *)item)->set_null_value(
+ read_info.read_charset);
+ }
+ else if (!real_item)
{
- Field *field= ((Item_field *)real_item)->field;
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name.str);
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ Field *field= real_item->field;
if (field->reset())
{
my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name.str,
@@ -1169,10 +1193,6 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
ER_THD(thd, ER_WARN_TOO_FEW_RECORDS),
thd->get_stmt_da()->current_row_for_warning());
}
- else if ((out_param= item->get_load_data_out_param_or_error()))
- out_param->load_data_set_null_value(read_info.read_charset);
- else
- DBUG_RETURN(1);
}
}
@@ -1268,7 +1288,6 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
while ((item= it++))
{
- Load_data_out_param *out_param;
/* If this line is to be skipped we don't want to fill field or var */
if (skip_lines)
continue;
@@ -1280,11 +1299,19 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
while(tag && strcmp(tag->field.c_ptr(), item->name.str) != 0)
tag= xmlit++;
+ Item_field *real_item= item->field_for_view_update();
if (!tag) // found null
{
- if (item->type() == Item::FIELD_ITEM)
+ if (item->type() == Item::STRING_ITEM)
+ ((Item_user_var_as_out_param *) item)->set_null_value(cs);
+ else if (!real_item)
+ {
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name.str);
+ DBUG_RETURN(1);
+ }
+ else
{
- Field *field= ((Item_field *) item)->field;
+ Field *field= real_item->field;
field->reset();
field->set_null();
if (field == table->next_number_field)
@@ -1300,15 +1327,21 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
/* Do not auto-update this field. */
field->set_has_explicit_value();
}
- else if ((out_param= item->get_load_data_out_param_or_error()))
- out_param->load_data_set_null_value(cs);
- else
- DBUG_RETURN(1);
continue;
}
- if (item->type() == Item::FIELD_ITEM)
+ if (item->type() == Item::STRING_ITEM)
+ ((Item_user_var_as_out_param *) item)->set_value(
+ (char *) tag->value.ptr(),
+ tag->value.length(), cs);
+ else if (!real_item)
+ {
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name.str);
+ DBUG_RETURN(1);
+ }
+ else
{
+
Field *field= ((Item_field *)item)->field;
field->set_notnull();
if (field == table->next_number_field)
@@ -1316,12 +1349,6 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
field->store((char *) tag->value.ptr(), tag->value.length(), cs);
field->set_has_explicit_value();
}
- else if ((out_param= item->get_load_data_out_param_or_error()))
- out_param->load_data_set_value((const char *) tag->value.ptr(),
- tag->value.length(), cs);
- else
- DBUG_RETURN(1);
-
}
if (read_info.error)
@@ -1341,8 +1368,15 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
for ( ; item; item= it++)
{
- Load_data_out_param *out_param;
- if (item->type() == Item::FIELD_ITEM)
+ Item_field *real_item= item->field_for_view_update();
+ if (item->type() == Item::STRING_ITEM)
+ ((Item_user_var_as_out_param *)item)->set_null_value(cs);
+ else if (!real_item)
+ {
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name.str);
+ DBUG_RETURN(1);
+ }
+ else
{
/*
QQ: We probably should not throw warning for each field.
@@ -1356,10 +1390,6 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
ER_THD(thd, ER_WARN_TOO_FEW_RECORDS),
thd->get_stmt_da()->current_row_for_warning());
}
- else if ((out_param= item->get_load_data_out_param_or_error()))
- out_param->load_data_set_null_value(cs);
- else
- DBUG_RETURN(1);
}
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 4ff988659c7..174d57b99af 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2008, 2016, MariaDB Corporation
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
+ Copyright (c) 2008, 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -557,7 +557,7 @@ void init_update_queries(void)
CF_AUTO_COMMIT_TRANS | CF_REPORT_PROGRESS |
CF_INSERTS_DATA;
sql_command_flags[SQLCOM_ALTER_SEQUENCE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
- CF_AUTO_COMMIT_TRANS;
+ CF_AUTO_COMMIT_TRANS | CF_SCHEMA_CHANGE;
sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_SCHEMA_CHANGE;
@@ -1456,7 +1456,7 @@ static my_bool deny_updates_if_read_only_option(THD *thd,
if (lex->sql_command == SQLCOM_UPDATE_MULTI)
DBUG_RETURN(FALSE);
- /* Check if we created and dropped temporary tables */
+ /* Check if we created or dropped temporary tables */
if ((sql_command_flags[lex->sql_command] & CF_SCHEMA_CHANGE) &&
lex->tmp_table())
DBUG_RETURN(FALSE);
@@ -5790,9 +5790,15 @@ end_with_restore_list:
if (!(sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
&thd->sp_proc_cache, TRUE)))
{
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
- ErrConvDQName(lex->spname).ptr());
- goto error;
+ /*
+ sp_find_routine can have issued an ER_SP_RECURSION_LIMIT error.
+ Send message ER_SP_DOES_NOT_EXIST only if procedure is not found in
+ cache.
+ */
+ if (!sp_cache_lookup(&thd->sp_proc_cache, lex->spname))
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
+ ErrConvDQName(lex->spname).ptr());
+ goto error;
}
else
{
@@ -7039,6 +7045,15 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
thd->security_ctx= sctx;
+ if (table_ref->sequence)
+ {
+ /* We want to have either SELECT or INSERT rights to sequences depending
+ on how they are accessed
+ */
+ want_access= ((table_ref->lock_type == TL_WRITE_ALLOW_WRITE) ?
+ INSERT_ACL : SELECT_ACL);
+ }
+
if (check_access(thd, want_access, table_ref->get_db_name(),
&table_ref->grant.privilege,
&table_ref->grant.m_internal,
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 6107595e930..e9fc0f62617 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -1620,22 +1620,28 @@ int plugin_init(int *argc, char **argv, int flags)
}
}
- /* First, we initialize only MyISAM - that should always succeed */
+ /*
+ First, we initialize only MyISAM - that should almost always succeed
+ (almost always, because plugins can be loaded outside of the server, too).
+ */
plugin_ptr= plugin_find_internal(&MyISAM, MYSQL_STORAGE_ENGINE_PLUGIN);
- DBUG_ASSERT(plugin_ptr);
- DBUG_ASSERT(plugin_ptr->load_option == PLUGIN_FORCE);
+ DBUG_ASSERT(plugin_ptr || !mysql_mandatory_plugins[0]);
+ if (plugin_ptr)
+ {
+ DBUG_ASSERT(plugin_ptr->load_option == PLUGIN_FORCE);
- if (plugin_initialize(&tmp_root, plugin_ptr, argc, argv, false))
- goto err_unlock;
+ if (plugin_initialize(&tmp_root, plugin_ptr, argc, argv, false))
+ goto err_unlock;
- /*
- set the global default storage engine variable so that it will
- not be null in any child thread.
- */
- global_system_variables.table_plugin=
- intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
- DBUG_ASSERT(plugin_ptr->ref_count == 1);
+ /*
+ set the global default storage engine variable so that it will
+ not be null in any child thread.
+ */
+ global_system_variables.table_plugin =
+ intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
+ DBUG_ASSERT(plugin_ptr->ref_count == 1);
+ }
mysql_mutex_unlock(&LOCK_plugin);
/* Register (not initialize!) all dynamic plugins */
diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic
index 2e71fac50be..ea6aefa5993 100644
--- a/sql/sql_plugin_services.ic
+++ b/sql/sql_plugin_services.ic
@@ -133,7 +133,7 @@ static struct base64_service_st base64_handler= {
my_base64_decode
};
-static struct thd_error_context_service_st thd_error_conext_handler= {
+static struct thd_error_context_service_st thd_error_context_handler= {
thd_get_error_message,
thd_get_error_number,
thd_get_error_row,
@@ -196,6 +196,24 @@ static struct encryption_scheme_service_st encryption_scheme_handler=
encryption_scheme_decrypt
};
+static struct my_crypt_service_st crypt_handler=
+{
+ my_aes_crypt_init,
+ my_aes_crypt_update,
+ my_aes_crypt_finish,
+ my_aes_crypt,
+ my_aes_get_size,
+ my_aes_ctx_size,
+ my_random_bytes
+};
+
+static struct my_print_error_service_st my_print_error_handler=
+{
+ my_error,
+ my_printf_error,
+ my_printv_error
+};
+
static struct st_service_ref list_of_services[]=
{
{ "base64_service", VERSION_base64, &base64_handler },
@@ -203,19 +221,21 @@ static struct st_service_ref list_of_services[]=
{ "encryption_scheme_service", VERSION_encryption_scheme, &encryption_scheme_handler },
{ "encryption_service", VERSION_encryption, &encryption_handler },
{ "logger_service", VERSION_logger, &logger_service_handler },
+ { "my_crypt_service", VERSION_my_crypt, &crypt_handler},
{ "my_md5_service", VERSION_my_md5, &my_md5_handler},
+ { "my_print_error_service", VERSION_my_print_error, &my_print_error_handler},
{ "my_sha1_service", VERSION_my_sha1, &my_sha1_handler},
{ "my_sha2_service", VERSION_my_sha2, &my_sha2_handler},
{ "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler },
{ "progress_report_service", VERSION_progress_report, &progress_report_handler },
{ "thd_alloc_service", VERSION_thd_alloc, &thd_alloc_handler },
{ "thd_autoinc_service", VERSION_thd_autoinc, &thd_autoinc_handler },
- { "thd_error_context_service", VERSION_thd_error_context, &thd_error_conext_handler },
+ { "thd_error_context_service", VERSION_thd_error_context, &thd_error_context_handler },
{ "thd_kill_statement_service", VERSION_kill_statement, &thd_kill_statement_handler },
{ "thd_rnd_service", VERSION_thd_rnd, &thd_rnd_handler },
{ "thd_specifics_service", VERSION_thd_specifics, &thd_specifics_handler },
{ "thd_timezone_service", VERSION_thd_timezone, &thd_timezone_handler },
{ "thd_wait_service", VERSION_thd_wait, &thd_wait_handler },
- { "wsrep_service", VERSION_wsrep, &wsrep_handler },
+ { "wsrep_service", VERSION_wsrep, &wsrep_handler }
};
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index a71d5240593..c6613facde7 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1138,6 +1138,8 @@ int JOIN::init_join_caches()
}
if (tab->cache && tab->cache->init(select_options & SELECT_DESCRIBE))
revise_cache_usage(tab);
+ else
+ tab->remove_redundant_bnl_scan_conds();
}
return 0;
}
@@ -8785,8 +8787,6 @@ bool JOIN::get_best_combination()
full_join=0;
hash_join= FALSE;
- used_tables= OUTER_REF_TABLE_BIT; // Outer row is already read
-
fix_semijoin_strategies_for_picked_join_order(this);
JOIN_TAB_RANGE *root_range;
@@ -8850,7 +8850,6 @@ bool JOIN::get_best_combination()
j->bush_root_tab= sjm_nest_root;
form= table[tablenr]= j->table;
- used_tables|= form->map;
form->reginfo.join_tab=j;
DBUG_PRINT("info",("type: %d", j->type));
if (j->type == JT_CONST)
@@ -8877,9 +8876,6 @@ bool JOIN::get_best_combination()
best_positions[tablenr].loosescan_picker.loosescan_key);
j->index= best_positions[tablenr].loosescan_picker.loosescan_key;
}*/
-
- if (keyuse && create_ref_for_key(this, j, keyuse, TRUE, used_tables))
- DBUG_RETURN(TRUE); // Something went wrong
if ((j->type == JT_REF || j->type == JT_EQ_REF) &&
is_hash_join_key_no(j->ref.key))
@@ -8905,6 +8901,23 @@ bool JOIN::get_best_combination()
}
root_range->end= j;
+ used_tables= OUTER_REF_TABLE_BIT; // Outer row is already read
+ for (j=join_tab, tablenr=0 ; tablenr < table_count ; tablenr++,j++)
+ {
+ if (j->bush_children)
+ j= j->bush_children->start;
+
+ used_tables|= j->table->map;
+ if (j->type != JT_CONST && j->type != JT_SYSTEM)
+ {
+ if ((keyuse= best_positions[tablenr].key) &&
+ create_ref_for_key(this, j, keyuse, TRUE, used_tables))
+ DBUG_RETURN(TRUE); // Something went wrong
+ }
+ if (j->last_leaf_in_bush)
+ j= j->bush_root_tab;
+ }
+
top_join_tab_count= join_tab_ranges.head()->end -
join_tab_ranges.head()->start;
@@ -9757,7 +9770,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5
*/
if (tab == join->join_tab + join->top_join_tab_count - 1)
- current_map|= OUTER_REF_TABLE_BIT | RAND_TABLE_BIT;
+ current_map|= RAND_TABLE_BIT;
used_tables|=current_map;
if (tab->type == JT_REF && tab->quick &&
@@ -11168,8 +11181,8 @@ void JOIN_TAB::remove_redundant_bnl_scan_conds()
select->cond is not processed separately. This method assumes it is always
the same as select_cond.
*/
- DBUG_ASSERT(!select || !select->cond ||
- (select->cond == select_cond));
+ if (select && select->cond != select_cond)
+ return;
if (is_cond_and(select_cond))
{
@@ -11479,7 +11492,6 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
/* purecov: end */
}
- tab->remove_redundant_bnl_scan_conds();
DBUG_EXECUTE("where",
char buff[256];
String str(buff,sizeof(buff),system_charset_info);
@@ -15869,7 +15881,17 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field,
}
-Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length)
+Field *Item::create_tmp_field_int(TABLE *table, uint convert_int_length)
+{
+ const Type_handler *h= &type_handler_long;
+ if (max_char_length() > convert_int_length)
+ h= &type_handler_longlong;
+ return h->make_and_init_table_field(&name, Record_addr(maybe_null),
+ *this, table);
+}
+
+
+Field *Item_sum::create_tmp_field(bool group, TABLE *table)
{
Field *UNINIT_VAR(new_field);
MEM_ROOT *mem_root= table->in_use->mem_root;
@@ -15878,23 +15900,10 @@ Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length)
case REAL_RESULT:
{
new_field= new (mem_root)
- Field_double(max_length, maybe_null, &name, decimals, TRUE);
+ Field_double(max_char_length(), maybe_null, &name, decimals, TRUE);
break;
}
case INT_RESULT:
- {
- /*
- Select an integer type with the minimal fit precision.
- convert_int_length is sign inclusive, don't consider the sign.
- */
- if (max_char_length() > convert_int_length)
- new_field= new (mem_root)
- Field_longlong(max_char_length(), maybe_null, &name, unsigned_flag);
- else
- new_field= new (mem_root)
- Field_long(max_char_length(), maybe_null, &name, unsigned_flag);
- break;
- }
case TIME_RESULT:
case DECIMAL_RESULT:
case STRING_RESULT:
@@ -15912,6 +15921,22 @@ Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length)
}
+static void create_tmp_field_from_item_finalize(THD *thd,
+ Field *new_field,
+ Item *item,
+ Item ***copy_func,
+ bool modify_item)
+{
+ if (copy_func &&
+ (item->is_result_field() ||
+ (item->real_item()->is_result_field())))
+ *((*copy_func)++) = item; // Save for copy_funcs
+ if (modify_item)
+ item->set_result_field(new_field);
+ if (item->type() == Item::NULL_ITEM)
+ new_field->is_created_from_null_item= TRUE;
+}
+
/**
Create field for temporary table using type of given item.
@@ -15942,16 +15967,9 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
{
Field *UNINIT_VAR(new_field);
DBUG_ASSERT(thd == table->in_use);
- new_field= item->Item::create_tmp_field(false, table);
-
- if (copy_func &&
- (item->is_result_field() ||
- (item->real_item()->is_result_field())))
- *((*copy_func)++) = item; // Save for copy_funcs
- if (modify_item)
- item->set_result_field(new_field);
- if (item->type() == Item::NULL_ITEM)
- new_field->is_created_from_null_item= TRUE;
+ if ((new_field= item->create_tmp_field(false, table)))
+ create_tmp_field_from_item_finalize(thd, new_field, item,
+ copy_func, modify_item);
return new_field;
}
@@ -16026,6 +16044,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item::Type orig_type= type;
Item *orig_item= 0;
+ DBUG_ASSERT(thd == table->in_use);
+
if (type != Item::FIELD_ITEM &&
item->real_item()->type() == Item::FIELD_ITEM)
{
@@ -16084,9 +16104,14 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
else if (table_cant_handle_bit_fields && field->field->type() ==
MYSQL_TYPE_BIT)
{
+ const Type_handler *handler= item->type_handler_long_or_longlong();
*from_field= field->field;
- result= create_tmp_field_from_item(thd, item, table, copy_func,
- modify_item);
+ if ((result=
+ handler->make_and_init_table_field(&item->name,
+ Record_addr(item->maybe_null),
+ *item, table)))
+ create_tmp_field_from_item_finalize(thd, result, item,
+ copy_func, modify_item);
if (result && modify_item)
field->result_field= result;
}
diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc
index a6e7b073251..35792bfe72e 100644
--- a/sql/sql_sequence.cc
+++ b/sql/sql_sequence.cc
@@ -20,6 +20,7 @@
#include "sql_sequence.h"
#include "ha_sequence.h"
#include "sql_base.h"
+#include "sql_table.h" // write_bin_log
#include "transaction.h"
#include "lock.h"
#include "sql_acl.h"
@@ -70,50 +71,60 @@ static Field_definition sequence_structure[]=
Check whether sequence values are valid.
Sets default values for fields that are not used, according to Oracle spec.
- Note that reserved_until is not checked as it's ok that it's outside of
- the range (to indicate that sequence us used up).
-
RETURN VALUES
false valid
true invalid
*/
-bool sequence_definition::check_and_adjust()
+bool sequence_definition::check_and_adjust(bool set_reserved_until)
{
longlong max_increment;
DBUG_ENTER("sequence_definition::check");
+ if (!(real_increment= increment))
+ real_increment= global_system_variables.auto_increment_increment;
+
/*
If min_value is not set, set it to LONGLONG_MIN or 1, depending on
increment
*/
if (!(used_fields & seq_field_used_min_value))
- min_value= increment < 0 ? LONGLONG_MIN+1 : 1;
+ min_value= real_increment < 0 ? LONGLONG_MIN+1 : 1;
/*
If min_value is not set, set it to LONGLONG_MAX or -1, depending on
- increment
+ real_increment
*/
if (!(used_fields & seq_field_used_max_value))
- max_value= increment < 0 ? -1 : LONGLONG_MAX-1;
+ max_value= real_increment < 0 ? -1 : LONGLONG_MAX-1;
if (!(used_fields & seq_field_used_start))
{
- /* Use min_value or max_value for start depending on increment */
- start= increment < 0 ? max_value : min_value;
+ /* Use min_value or max_value for start depending on real_increment */
+ start= real_increment < 0 ? max_value : min_value;
}
- /* To ensure that cache * increment will never overflow */
- max_increment= increment ? labs(increment) : MAX_AUTO_INCREMENT_VALUE;
+ if (set_reserved_until)
+ reserved_until= start;
+
+ adjust_values(reserved_until);
+
+ /* To ensure that cache * real_increment will never overflow */
+ max_increment= (real_increment ?
+ labs(real_increment) :
+ MAX_AUTO_INCREMENT_VALUE);
if (max_value >= start &&
max_value > min_value &&
start >= min_value &&
max_value != LONGLONG_MAX &&
min_value != LONGLONG_MIN &&
- cache < (LONGLONG_MAX - max_increment) / max_increment)
+ cache < (LONGLONG_MAX - max_increment) / max_increment &&
+ ((real_increment > 0 && reserved_until >= min_value) ||
+ (real_increment < 0 && reserved_until <= max_value)))
DBUG_RETURN(FALSE);
- DBUG_RETURN(TRUE);
+
+ DBUG_RETURN(TRUE); // Error
}
@@ -331,14 +342,46 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *table_list)
SEQUENCE::SEQUENCE() :all_values_used(0), initialized(SEQ_UNINTIALIZED), table(0)
{
- mysql_mutex_init(key_LOCK_SEQUENCE, &mutex, MY_MUTEX_INIT_SLOW);
+ mysql_rwlock_init(key_LOCK_SEQUENCE, &mutex);
}
SEQUENCE::~SEQUENCE()
{
- mysql_mutex_destroy(&mutex);
+ mysql_rwlock_destroy(&mutex);
}
+/*
+ The following functions is to ensure that we when reserve new values
+ trough sequence object sequence we have only one writer at at time.
+ A sequence table can have many readers (trough normal SELECT's).
+
+ We mark that we have a write lock in the table object so that
+ ha_sequence::ha_write() can check if we have a lock. If already locked, then
+ ha_write() knows that we are running a sequence operation. If not, then
+ ha_write() knows that it's an INSERT.
+*/
+
+void SEQUENCE::write_lock(TABLE *table)
+{
+ DBUG_ASSERT(((ha_sequence*) table->file)->is_locked() == 0);
+ mysql_rwlock_wrlock(&mutex);
+ ((ha_sequence*) table->file)->write_lock();
+}
+void SEQUENCE::write_unlock(TABLE *table)
+{
+ ((ha_sequence*) table->file)->unlock();
+ mysql_rwlock_unlock(&mutex);
+}
+void SEQUENCE::read_lock(TABLE *table)
+{
+ if (!((ha_sequence*) table->file)->is_locked())
+ mysql_rwlock_rdlock(&mutex);
+}
+void SEQUENCE::read_unlock(TABLE *table)
+{
+ if (!((ha_sequence*) table->file)->is_locked())
+ mysql_rwlock_unlock(&mutex);
+}
/**
Read values from the sequence tables to table_share->sequence.
@@ -355,7 +398,7 @@ int SEQUENCE::read_initial_values(TABLE *table_arg)
if (likely(initialized != SEQ_UNINTIALIZED))
DBUG_RETURN(0);
table= table_arg;
- mysql_mutex_lock(&mutex);
+ write_lock(table);
if (likely(initialized == SEQ_UNINTIALIZED))
{
MYSQL_LOCK *lock;
@@ -411,7 +454,7 @@ int SEQUENCE::read_initial_values(TABLE *table_arg)
if (!has_active_transaction && !thd->transaction.stmt.is_empty())
trans_commit_stmt(thd);
}
- mysql_mutex_unlock(&mutex);
+ write_unlock(table);
DBUG_RETURN(error);
}
@@ -425,7 +468,6 @@ int SEQUENCE::read_stored_values()
int error;
my_bitmap_map *save_read_set;
DBUG_ENTER("SEQUENCE::read_stored_values");
- mysql_mutex_assert_owner(&mutex);
save_read_set= tmp_use_all_columns(table, table->read_set);
error= table->file->ha_read_first_row(table->record[0], MAX_KEY);
@@ -448,7 +490,7 @@ int SEQUENCE::read_stored_values()
Adjust values after reading a the stored state
*/
-void SEQUENCE::adjust_values(longlong next_value)
+void sequence_definition::adjust_values(longlong next_value)
{
next_free_value= next_value;
if (!(real_increment= increment))
@@ -531,25 +573,36 @@ int sequence_definition::write_initial_sequence(TABLE *table)
Store current sequence values into the sequence table
*/
-int sequence_definition::write(TABLE *table)
+int sequence_definition::write(TABLE *table, bool all_fields)
{
int error;
- MY_BITMAP *save_rpl_write_set, *save_write_set;
+ MY_BITMAP *save_rpl_write_set, *save_write_set, *save_read_set;
+ DBUG_ASSERT(((ha_sequence*) table->file)->is_locked());
- /* Log a full insert (ok as table is small) */
save_rpl_write_set= table->rpl_write_set;
+ if (likely(!all_fields))
+ {
+ /* Only write next_value and round to binary log */
+ table->rpl_write_set= &table->def_rpl_write_set;
+ bitmap_clear_all(table->rpl_write_set);
+ bitmap_set_bit(table->rpl_write_set, NEXT_FIELD_NO);
+ bitmap_set_bit(table->rpl_write_set, ROUND_FIELD_NO);
+ }
+ else
+ table->rpl_write_set= &table->s->all_set;
/* Update table */
save_write_set= table->write_set;
- table->rpl_write_set= table->write_set= &table->s->all_set;
+ save_read_set= table->read_set;
+ table->read_set= table->write_set= &table->s->all_set;
+ table->file->column_bitmaps_signal();
store_fields(table);
- /* Tell ha_sequence::write_row that we already hold the mutex */
- ((ha_sequence*) table->file)->sequence_locked= 1;
if ((error= table->file->ha_write_row(table->record[0])))
table->file->print_error(error, MYF(0));
- ((ha_sequence*) table->file)->sequence_locked= 0;
table->rpl_write_set= save_rpl_write_set;
+ table->read_set= save_read_set;
table->write_set= save_write_set;
+ table->file->column_bitmaps_signal();
return error;
}
@@ -590,7 +643,7 @@ longlong SEQUENCE::next_value(TABLE *table, bool second_round, int *error)
*error= 0;
if (!second_round)
- lock();
+ write_lock(table);
res_value= next_free_value;
next_free_value= increment_value(next_free_value);
@@ -598,7 +651,7 @@ longlong SEQUENCE::next_value(TABLE *table, bool second_round, int *error)
if ((real_increment > 0 && res_value < reserved_until) ||
(real_increment < 0 && res_value > reserved_until))
{
- unlock();
+ write_unlock(table);
DBUG_RETURN(res_value);
}
@@ -612,7 +665,7 @@ longlong SEQUENCE::next_value(TABLE *table, bool second_round, int *error)
The cache value is checked on insert so the following can't
overflow
*/
- add_to= cache ? real_increment * cache : 1;
+ add_to= cache ? real_increment * cache : real_increment;
out_of_values= 0;
if (real_increment > 0)
@@ -651,17 +704,17 @@ longlong SEQUENCE::next_value(TABLE *table, bool second_round, int *error)
DBUG_RETURN(next_value(table, 1, error));
}
- if ((*error= write(table)))
+ if ((*error= write(table, 0)))
{
reserved_until= org_reserved_until;
next_free_value= res_value;
}
- unlock();
+ write_unlock(table);
DBUG_RETURN(res_value);
err:
- unlock();
+ write_unlock(table);
my_error(ER_SEQUENCE_RUN_OUT, MYF(0), table->s->db.str,
table->s->table_name.str);
*error= ER_SEQUENCE_RUN_OUT;
@@ -720,7 +773,7 @@ bool SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round,
ulonglong org_round= round;
DBUG_ENTER("SEQUENCE::set_value");
- lock();
+ write_lock(table);
if (is_used)
next_val= increment_value(next_val);
@@ -751,7 +804,7 @@ bool SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round,
needs_to_be_stored)
{
reserved_until= next_free_value;
- if (write(table))
+ if (write(table, 0))
{
reserved_until= org_reserved_until;
next_free_value= org_next_free_value;
@@ -762,7 +815,7 @@ bool SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round,
error= 0;
end:
- unlock();
+ write_unlock(table);
DBUG_RETURN(error);
}
@@ -842,7 +895,7 @@ bool Sql_cmd_alter_sequence::execute(THD *thd)
/* Let check_and_adjust think all fields are used */
new_seq->used_fields= ~0;
- if (new_seq->check_and_adjust())
+ if (new_seq->check_and_adjust(0))
{
my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
first_table->db,
@@ -851,17 +904,24 @@ bool Sql_cmd_alter_sequence::execute(THD *thd)
goto end;
}
- if (!(error= new_seq->write(table)))
+ table->s->sequence->write_lock(table);
+ if (!(error= new_seq->write(table, 1)))
{
/* Store the sequence values in table share */
table->s->sequence->copy(new_seq);
}
- trans_commit_stmt(thd);
- trans_commit_implicit(thd);
+ else
+ table->file->print_error(error, MYF(0));
+ table->s->sequence->write_unlock(table);
+ if (trans_commit_stmt(thd))
+ error= 1;
+ if (trans_commit_implicit(thd))
+ error= 1;
+ if (!error)
+ error= write_bin_log(thd, 1, thd->query(), thd->query_length());
if (!error)
my_ok(thd);
end:
- close_thread_tables(thd);
DBUG_RETURN(error);
}
diff --git a/sql/sql_sequence.h b/sql/sql_sequence.h
index ffe5ded4cff..b560d03ca52 100644
--- a/sql/sql_sequence.h
+++ b/sql/sql_sequence.h
@@ -26,6 +26,11 @@
#define seq_field_used_restart 64
#define seq_field_used_restart_value 128
+/* Field position in sequence table for some fields we refer to directly */
+#define NEXT_FIELD_NO 0
+#define MIN_VALUE_FIELD_NO 1
+#define ROUND_FIELD_NO 7
+
/**
sequence_definition is used when defining a sequence as part of create
*/
@@ -35,7 +40,7 @@ class sequence_definition :public Sql_alloc
public:
sequence_definition():
min_value(1), max_value(LONGLONG_MAX-1), start(1), increment(1),
- cache(1000), round(0), cycle(0), used_fields(0)
+ cache(1000), round(0), restart(0), cycle(0), used_fields(0)
{}
longlong reserved_until;
longlong min_value;
@@ -44,21 +49,30 @@ public:
longlong increment;
longlong cache;
ulonglong round;
+ longlong restart; // alter sequence restart value
bool cycle;
uint used_fields; // Which fields where used in CREATE
- longlong restart; // alter sequence restart value
- bool check_and_adjust();
+ bool check_and_adjust(bool set_reserved_until);
void store_fields(TABLE *table);
void read_fields(TABLE *table);
int write_initial_sequence(TABLE *table);
- int write(TABLE *table);
+ int write(TABLE *table, bool all_fields);
+ /* This must be called after sequence data has been updated */
+ void adjust_values(longlong next_value);
inline void print_dbug()
{
DBUG_PRINT("sequence", ("reserved: %lld start: %lld increment: %lld min_value: %lld max_value: %lld cache: %lld round: %lld",
reserved_until, start, increment, min_value,
max_value, cache, round));
}
+protected:
+ /*
+ The following values are the values from sequence_definition
+ merged with global auto_increment_offset and auto_increment_increment
+ */
+ longlong real_increment;
+ longlong next_free_value;
};
/**
@@ -79,16 +93,10 @@ public:
~SEQUENCE();
int read_initial_values(TABLE *table);
int read_stored_values();
- void lock()
- {
- mysql_mutex_lock(&mutex);
- }
- void unlock()
- {
- mysql_mutex_unlock(&mutex);
- }
- /* This must be called after sequence data has been updated */
- void adjust_values(longlong next_value);
+ void write_lock(TABLE *table);
+ void write_unlock(TABLE *table);
+ void read_lock(TABLE *table);
+ void read_unlock(TABLE *table);
void copy(sequence_definition *seq)
{
sequence_definition::operator= (*seq);
@@ -123,13 +131,7 @@ public:
private:
TABLE *table;
- mysql_mutex_t mutex;
- longlong next_free_value;
- /*
- The following values are the values from sequence_definition
- merged with global auto_increment_offset and auto_increment_increment
- */
- longlong real_increment;
+ mysql_rwlock_t mutex;
};
diff --git a/sql/sql_signal.cc b/sql/sql_signal.cc
index 828149f3035..6a57b8fc9ce 100644
--- a/sql/sql_signal.cc
+++ b/sql/sql_signal.cc
@@ -434,13 +434,19 @@ bool Sql_cmd_resignal::execute(THD *thd)
/* Check if the old condition still exists. */
if (da->has_sql_condition(signaled->message, strlen(signaled->message)))
{
- /* Make room for the new RESIGNAL condition. */
- da->reserve_space(thd, 1);
+ /*
+ Make room for the new RESIGNAL condition and one for the stack trace
+ note.
+ */
+ da->reserve_space(thd, 2);
}
else
{
- /* Make room for old condition + the new RESIGNAL condition. */
- da->reserve_space(thd, 2);
+ /*
+ Make room for old condition + the new RESIGNAL condition + the stack
+ trace note.
+ */
+ da->reserve_space(thd, 3);
da->push_warning(thd, &signaled_err);
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index e202552ac8a..462b78aeb62 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2243,7 +2243,9 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
uint32 comment_len;
built_query.set_charset(thd->charset());
- built_query.append("DROP TABLE ");
+ built_query.append("DROP ");
+ built_query.append(object_to_drop);
+ built_query.append(' ');
if (if_exists)
built_query.append("IF EXISTS ");
@@ -3276,6 +3278,22 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
bool tmp_table= create_table_mode == C_ALTER_TABLE;
DBUG_ENTER("mysql_prepare_create_table");
+ LEX_CSTRING* connect_string = &create_info->connect_string;
+ if (connect_string->length != 0 &&
+ connect_string->length > CONNECT_STRING_MAXLEN &&
+ (system_charset_info->cset->charpos(system_charset_info,
+ connect_string->str,
+ (connect_string->str +
+ connect_string->length),
+ CONNECT_STRING_MAXLEN)
+ < connect_string->length))
+ {
+ my_error(ER_WRONG_STRING_LENGTH, MYF(0),
+ connect_string->str, "CONNECTION", CONNECT_STRING_MAXLEN);
+ DBUG_RETURN(TRUE);
+ }
+
+ select_field_pos= alter_info->create_list.elements - select_field_count;
null_fields= 0;
create_info->varchar= 0;
max_key_length= file->max_key_length();
@@ -3355,30 +3373,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
file->ha_table_flags() & HA_CAN_BIT_FIELD)
total_uneven_bit_length-= sql_field->length & 7;
- sql_field->default_value= dup_field->default_value;
- sql_field->set_handler(dup_field->type_handler());
-
- /*
- If we are replacing a field with a BIT field, we need
- to initialize pack_flag. Note that we do not need to
- increment total_uneven_bit_length here as this dup_field
- has already been processed.
- */
- if (sql_field->real_field_type() == MYSQL_TYPE_BIT)
- {
- sql_field->pack_flag= FIELDFLAG_NUMBER;
- if (!(file->ha_table_flags() & HA_CAN_BIT_FIELD))
- sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
- }
-
- sql_field->charset= (dup_field->charset ?
- dup_field->charset :
- create_info->default_table_charset);
- sql_field->length= dup_field->char_length;
- sql_field->pack_length= dup_field->pack_length;
- sql_field->key_length= dup_field->key_length;
- sql_field->decimals= dup_field->decimals;
- sql_field->unireg_check= dup_field->unireg_check;
/*
We're making one field from two, the result field will have
dup_field->flags as flags. If we've incremented null_fields
@@ -3386,10 +3380,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
*/
if (!(sql_field->flags & NOT_NULL_FLAG))
null_fields--;
- sql_field->flags= dup_field->flags;
- sql_field->create_length_to_internal_length();
- sql_field->interval= dup_field->interval;
- sql_field->vcol_info= dup_field->vcol_info;
+
+ if (sql_field->redefine_stage1(dup_field, file, create_info))
+ DBUG_RETURN(true);
+
it2.remove(); // Remove first (create) definition
select_field_pos--;
break;
@@ -5580,9 +5574,8 @@ int mysql_discard_or_import_tablespace(THD *thd,
error= trans_commit_stmt(thd);
if (trans_commit_implicit(thd))
error=1;
- if (error)
- goto err;
- error= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
+ if (!error)
+ error= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
err:
thd->tablespace_op=FALSE;
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index 90f8d674e67..6e99655c28b 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -30,6 +30,7 @@ Type_handler_short type_handler_short;
Type_handler_long type_handler_long;
Type_handler_int24 type_handler_int24;
Type_handler_longlong type_handler_longlong;
+Type_handler_longlong type_handler_ulonglong; // Only used for CAST() for now
Type_handler_float type_handler_float;
Type_handler_double type_handler_double;
Type_handler_bit type_handler_bit;
@@ -528,6 +529,14 @@ Type_handler_hybrid_field_type::aggregate_for_result(const Type_handler *other)
}
+const Type_handler *
+Type_handler::type_handler_long_or_longlong(uint max_char_length)
+{
+ if (max_char_length <= MY_INT32_NUM_DECIMAL_DIGITS - 2)
+ return &type_handler_long;
+ return &type_handler_longlong;
+}
+
/*
This method is called for CASE (and its abbreviations) and LEAST/GREATEST
when data type aggregation returned LONGLONG and there were some BIT
@@ -1637,6 +1646,93 @@ bool Type_handler_geometry::
/*************************************************************************/
bool Type_handler::
+ Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+{
+ def->redefine_stage1_common(dup, file, schema);
+ def->create_length_to_internal_length_simple();
+ return false;
+}
+
+
+bool Type_handler_null::
+ Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+{
+ def->redefine_stage1_common(dup, file, schema);
+ def->create_length_to_internal_length_null();
+ return false;
+}
+
+
+bool Type_handler_newdecimal::
+ Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+{
+ def->redefine_stage1_common(dup, file, schema);
+ def->create_length_to_internal_length_newdecimal();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+{
+ def->redefine_stage1_common(dup, file, schema);
+ def->create_length_to_internal_length_string();
+ return false;
+}
+
+
+bool Type_handler_typelib::
+ Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+{
+ def->redefine_stage1_common(dup, file, schema);
+ def->create_length_to_internal_length_typelib();
+ return false;
+}
+
+
+bool Type_handler_bit::
+ Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+{
+ def->redefine_stage1_common(dup, file, schema);
+ /*
+ If we are replacing a field with a BIT field, we need
+ to initialize pack_flag.
+ */
+ def->pack_flag= FIELDFLAG_NUMBER;
+ if (!(file->ha_table_flags() & HA_CAN_BIT_FIELD))
+ def->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
+ def->create_length_to_internal_length_bit();
+ return false;
+}
+
+
+/*************************************************************************/
+
+bool Type_handler::
Column_definition_prepare_stage2_legacy(Column_definition *def,
enum_field_types type) const
{
@@ -1859,7 +1955,8 @@ Field *Type_handler_tiny::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_tiny(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field_tiny(addr.ptr, attr.max_char_length(),
+ addr.null_ptr, addr.null_bit,
Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag);
}
@@ -1871,7 +1968,8 @@ Field *Type_handler_short::make_table_field(const LEX_CSTRING *name,
{
return new (table->in_use->mem_root)
- Field_short(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field_short(addr.ptr, attr.max_char_length(),
+ addr.null_ptr, addr.null_bit,
Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag);
}
@@ -1882,7 +1980,8 @@ Field *Type_handler_int24::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_medium(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field_medium(addr.ptr, attr.max_char_length(),
+ addr.null_ptr, addr.null_bit,
Field::NONE, name,
0/*zerofill*/, attr.unsigned_flag);
}
@@ -1894,7 +1993,8 @@ Field *Type_handler_long::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_long(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field_long(addr.ptr, attr.max_char_length(),
+ addr.null_ptr, addr.null_bit,
Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag);
}
@@ -1905,7 +2005,7 @@ Field *Type_handler_longlong::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_longlong(addr.ptr, attr.max_length,
+ Field_longlong(addr.ptr, attr.max_char_length(),
addr.null_ptr, addr.null_bit,
Field::NONE, name,
0/*zerofill*/, attr.unsigned_flag);
@@ -1918,7 +2018,8 @@ Field *Type_handler_float::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_float(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field_float(addr.ptr, attr.max_char_length(),
+ addr.null_ptr, addr.null_bit,
Field::NONE, name,
attr.decimals, 0/*zerofill*/, attr.unsigned_flag);
}
@@ -1930,7 +2031,7 @@ Field *Type_handler_double::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_double(addr.ptr, attr.max_length,
+ Field_double(addr.ptr, attr.max_char_length(),
addr.null_ptr, addr.null_bit,
Field::NONE, name,
attr.decimals, 0/*zerofill*/, attr.unsigned_flag);
@@ -2978,6 +3079,70 @@ bool Type_handler_geometry::
/*************************************************************************/
+longlong Type_handler_real_result::
+ Item_val_int_signed_typecast(Item *item) const
+{
+ return item->val_int();
+}
+
+longlong Type_handler_int_result::
+ Item_val_int_signed_typecast(Item *item) const
+{
+ return item->val_int();
+}
+
+longlong Type_handler_decimal_result::
+ Item_val_int_signed_typecast(Item *item) const
+{
+ return item->val_int();
+}
+
+longlong Type_handler_temporal_result::
+ Item_val_int_signed_typecast(Item *item) const
+{
+ return item->val_int();
+}
+
+longlong Type_handler_string_result::
+ Item_val_int_signed_typecast(Item *item) const
+{
+ return item->val_int_signed_typecast_from_str();
+}
+
+/*************************************************************************/
+
+longlong Type_handler_real_result::
+ Item_val_int_unsigned_typecast(Item *item) const
+{
+ return item->val_int_unsigned_typecast_from_int();
+}
+
+longlong Type_handler_int_result::
+ Item_val_int_unsigned_typecast(Item *item) const
+{
+ return item->val_int_unsigned_typecast_from_int();
+}
+
+longlong Type_handler_decimal_result::
+ Item_val_int_unsigned_typecast(Item *item) const
+{
+ return item->val_int_unsigned_typecast_from_decimal();
+}
+
+longlong Type_handler_temporal_result::
+ Item_val_int_unsigned_typecast(Item *item) const
+{
+ return item->val_int_unsigned_typecast_from_int();
+}
+
+longlong Type_handler_string_result::
+ Item_val_int_unsigned_typecast(Item *item) const
+{
+ return item->val_int_unsigned_typecast_from_str();
+}
+
+/*************************************************************************/
+
String *
Type_handler_real_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
String *str) const
@@ -4012,11 +4177,60 @@ bool Type_handler::
bool Type_handler::
Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const
{
+ const Item *arg= item->arguments()[0];
+ if (!arg->unsigned_flag && arg->val_int_min() < 0)
+ {
+ /*
+ Negative arguments produce long results:
+ CAST(1-2 AS UNSIGNED) -> 18446744073709551615
+ */
+ item->max_length= MAX_BIGINT_WIDTH;
+ return false;
+ }
item->fix_length_and_dec_generic();
return false;
}
+bool Type_handler_string_result::
+ Item_func_signed_fix_length_and_dec(Item_func_signed *item) const
+{
+ item->fix_length_and_dec_string();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const
+{
+ const Item *arg= item->arguments()[0];
+ if (!arg->unsigned_flag && // Not HEX hybrid
+ arg->max_char_length() > 1) // Can be negative
+ {
+ // String arguments can give long results: '-1' -> 18446744073709551614
+ item->max_length= MAX_BIGINT_WIDTH;
+ return false;
+ }
+ item->fix_length_and_dec_string();
+ return false;
+}
+
+bool Type_handler_real_result::
+ Item_func_signed_fix_length_and_dec(Item_func_signed *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
bool Type_handler::
Item_double_typecast_fix_length_and_dec(Item_double_typecast *item) const
{
@@ -5002,3 +5216,165 @@ Item *Type_handler_row::
}
/***************************************************************************/
+
+static const char* item_name(Item *a, String *str)
+{
+ if (a->name.str)
+ return a->name.str;
+ str->length(0);
+ a->print(str, QT_ORDINARY);
+ return str->c_ptr_safe();
+}
+
+
+static void wrong_precision_error(uint errcode, Item *a,
+ ulonglong number, uint maximum)
+{
+ StringBuffer<1024> buf(system_charset_info);
+ my_error(errcode, MYF(0), number, item_name(a, &buf), maximum);
+}
+
+
+/**
+ Get precision and scale for a declaration
+
+ return
+ 0 ok
+ 1 error
+*/
+
+bool get_length_and_scale(ulonglong length, ulonglong decimals,
+ ulong *out_length, uint *out_decimals,
+ uint max_precision, uint max_scale,
+ Item *a)
+{
+ if (length > (ulonglong) max_precision)
+ {
+ wrong_precision_error(ER_TOO_BIG_PRECISION, a, length, max_precision);
+ return 1;
+ }
+ if (decimals > (ulonglong) max_scale)
+ {
+ wrong_precision_error(ER_TOO_BIG_SCALE, a, decimals, max_scale);
+ return 1;
+ }
+
+ *out_decimals= (uint) decimals;
+ my_decimal_trim(&length, out_decimals);
+ *out_length= (ulong) length;
+
+ if (*out_length < *out_decimals)
+ {
+ my_error(ER_M_BIGGER_THAN_D, MYF(0), "");
+ return 1;
+ }
+ return 0;
+}
+
+
+Item *Type_handler_longlong::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ if (this != &type_handler_ulonglong)
+ return new (thd->mem_root) Item_func_signed(thd, item);
+ return new (thd->mem_root) Item_func_unsigned(thd, item);
+
+}
+
+
+Item *Type_handler_date_common::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ return new (thd->mem_root) Item_date_typecast(thd, item);
+}
+
+
+
+Item *Type_handler_time_common::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ if (attr.decimals() > MAX_DATETIME_PRECISION)
+ {
+ wrong_precision_error(ER_TOO_BIG_PRECISION, item, attr.decimals(),
+ MAX_DATETIME_PRECISION);
+ return 0;
+ }
+ return new (thd->mem_root)
+ Item_time_typecast(thd, item, (uint) attr.decimals());
+}
+
+
+Item *Type_handler_datetime_common::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ if (attr.decimals() > MAX_DATETIME_PRECISION)
+ {
+ wrong_precision_error(ER_TOO_BIG_PRECISION, item, attr.decimals(),
+ MAX_DATETIME_PRECISION);
+ return 0;
+ }
+ return new (thd->mem_root)
+ Item_datetime_typecast(thd, item, (uint) attr.decimals());
+
+}
+
+
+Item *Type_handler_decimal_result::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ ulong len;
+ uint dec;
+ if (get_length_and_scale(attr.length(), attr.decimals(), &len, &dec,
+ DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE, item))
+ return NULL;
+ return new (thd->mem_root) Item_decimal_typecast(thd, item, len, dec);
+}
+
+
+Item *Type_handler_double::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ ulong len;
+ uint dec;
+ if (!attr.length_specified())
+ return new (thd->mem_root) Item_double_typecast(thd, item,
+ DBL_DIG + 7,
+ NOT_FIXED_DEC);
+
+ if (get_length_and_scale(attr.length(), attr.decimals(), &len, &dec,
+ DECIMAL_MAX_PRECISION, NOT_FIXED_DEC - 1, item))
+ return NULL;
+ return new (thd->mem_root) Item_double_typecast(thd, item, len, dec);
+}
+
+
+Item *Type_handler_long_blob::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ int len= -1;
+ CHARSET_INFO *real_cs= attr.charset() ?
+ attr.charset() :
+ thd->variables.collation_connection;
+ if (attr.length_specified())
+ {
+ if (attr.length() > MAX_FIELD_BLOBLENGTH)
+ {
+ char buff[1024];
+ String buf(buff, sizeof(buff), system_charset_info);
+ my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), item_name(item, &buf),
+ MAX_FIELD_BLOBLENGTH);
+ return NULL;
+ }
+ len= (int) attr.length();
+ }
+ return new (thd->mem_root) Item_char_typecast(thd, item, len, real_cs);
+}
+
+/***************************************************************************/
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 28bb2a2edc9..27fb8a8f7da 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -68,6 +68,7 @@ class Arg_comparator;
struct st_value;
class Protocol;
class handler;
+struct Schema_specification_st;
struct TABLE;
struct SORT_FIELD_ATTR;
@@ -487,6 +488,44 @@ public:
};
+class Type_cast_attributes
+{
+ CHARSET_INFO *m_charset;
+ ulonglong m_length;
+ ulonglong m_decimals;
+ bool m_length_specified;
+ bool m_decimals_specified;
+public:
+ Type_cast_attributes(const char *c_len, const char *c_dec, CHARSET_INFO *cs)
+ :m_charset(cs), m_length(0), m_decimals(0),
+ m_length_specified(false), m_decimals_specified(false)
+ {
+ set_length_and_dec(c_len, c_dec);
+ }
+ Type_cast_attributes(CHARSET_INFO *cs)
+ :m_charset(cs), m_length(0), m_decimals(0),
+ m_length_specified(false), m_decimals_specified(false)
+ { }
+ void set_length_and_dec(const char *c_len, const char *c_dec)
+ {
+ int error;
+ /*
+ We don't have to check for error here as sql_yacc.yy has guaranteed
+ that the values are in range of ulonglong
+ */
+ if ((m_length_specified= (c_len != NULL)))
+ m_length= (ulonglong) my_strtoll10(c_len, NULL, &error);
+ if ((m_decimals_specified= (c_dec != NULL)))
+ m_decimals= (ulonglong) my_strtoll10(c_dec, NULL, &error);
+ }
+ CHARSET_INFO *charset() const { return m_charset; }
+ bool length_specified() const { return m_length_specified; }
+ bool decimals_specified() const { return m_decimals_specified; }
+ ulonglong length() const { return m_length; }
+ ulonglong decimals() const { return m_decimals; }
+};
+
+
class Name: private LEX_CSTRING
{
public:
@@ -563,6 +602,7 @@ public:
static const Type_handler *blob_type_handler(uint max_octet_length);
static const Type_handler *string_type_handler(uint max_octet_length);
static const Type_handler *bit_and_int_mixture_handler(uint max_char_len);
+ static const Type_handler *type_handler_long_or_longlong(uint max_char_len);
/**
Return a string type handler for Item
If too_big_for_varchar() returns a BLOB variant, according to length.
@@ -656,6 +696,10 @@ public:
{
return true;
}
+ virtual bool is_scalar_type() const { return true; }
+ virtual bool can_return_int() const { return true; }
+ virtual bool can_return_real() const { return true; }
+ virtual bool is_general_purpose_string_type() const { return false; }
virtual uint Item_time_precision(Item *item) const;
virtual uint Item_datetime_precision(Item *item) const;
virtual uint Item_decimal_scale(const Item *item) const;
@@ -707,6 +751,28 @@ public:
Column_definition *c,
handler *file,
ulonglong table_flags) const;
+ /*
+ This method is called on queries like:
+ CREATE TABLE t2 (a INT) AS SELECT a FROM t1;
+ I.e. column "a" is queried from another table,
+ but its data type is redefined.
+ @param OUT def - The column definition to be redefined
+ @param IN dup - The column definition to take the data type from
+ (i.e. "a INT" in the above example).
+ @param IN file - Table owner handler. If it does not support certain
+ data types, some conversion can be applied.
+ I.g. true BIT to BIT-AS-CHAR.
+ @param IN schema - the owner schema definition, e.g. for the default
+ character set and collation.
+ @retval true - on error
+ @retval false - on success
+ */
+ virtual bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *
+ schema)
+ const;
virtual bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const= 0;
@@ -802,6 +868,12 @@ public:
Item *src,
const Item *cmp) const= 0;
virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0;
+ virtual Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
virtual bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
@@ -819,6 +891,9 @@ public:
virtual
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const= 0;
+ virtual longlong Item_val_int_signed_typecast(Item *item) const= 0;
+ virtual longlong Item_val_int_unsigned_typecast(Item *item) const= 0;
+
virtual String *Item_func_hex_val_str_ascii(Item_func_hex *item,
String *str) const= 0;
@@ -917,6 +992,9 @@ class Type_handler_row: public Type_handler
public:
virtual ~Type_handler_row() {}
const Name name() const { return m_name_row; }
+ bool is_scalar_type() const { return false; }
+ bool can_return_int() const { return false; }
+ bool can_return_real() const { return false; }
enum_field_types field_type() const
{
DBUG_ASSERT(0);
@@ -963,6 +1041,15 @@ public:
DBUG_ASSERT(0);
return true;
}
+ bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
@@ -1060,6 +1147,16 @@ public:
DBUG_ASSERT(0);
return true;
}
+ longlong Item_val_int_signed_typecast(Item *item) const
+ {
+ DBUG_ASSERT(0);
+ return 0;
+ }
+ longlong Item_val_int_unsigned_typecast(Item *item) const
+ {
+ DBUG_ASSERT(0);
+ return 0;
+ }
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const
{
DBUG_ASSERT(0);
@@ -1253,6 +1350,10 @@ public:
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
+ bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const;
+ bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const;
+ longlong Item_val_int_signed_typecast(Item *item) const;
+ longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
String *) const;
@@ -1301,6 +1402,8 @@ public:
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
uint32 max_display_length(const Item *item) const;
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
uint Item_decimal_precision(const Item *item) const;
bool Item_save_in_value(Item *item, st_value *value) const;
bool Item_param_set_from_value(THD *thd,
@@ -1324,6 +1427,8 @@ public:
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
+ longlong Item_val_int_signed_typecast(Item *item) const;
+ longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
String *) const;
@@ -1389,6 +1494,8 @@ public:
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
+ longlong Item_val_int_signed_typecast(Item *item) const;
+ longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
String *) const;
@@ -1457,6 +1564,8 @@ public:
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
+ longlong Item_val_int_signed_typecast(Item *item) const;
+ longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
String *) const;
@@ -1515,6 +1624,11 @@ public:
Column_definition *c,
handler *file,
ulonglong table_flags) const;
+ bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const;
uint32 max_display_length(const Item *item) const;
uint Item_time_precision(Item *item) const
{
@@ -1557,6 +1671,10 @@ public:
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
+ bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const;
+ bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const;
+ longlong Item_val_int_signed_typecast(Item *item) const;
+ longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
String *) const;
@@ -1595,6 +1713,13 @@ public:
};
+class Type_handler_general_purpose_string: public Type_handler_string_result
+{
+public:
+ bool is_general_purpose_string_type() const { return true; }
+};
+
+
/***
Instantiable classes for every MYSQL_TYPE_XXX
@@ -1708,6 +1833,8 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
uint32 max_display_length(const Item *item) const { return 20; }
uint32 calc_pack_length(uint32 length) const { return 8; }
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{
return Item_send_longlong(item, protocol, buf);
@@ -1807,6 +1934,11 @@ public:
Column_definition *c,
handler *file,
ulonglong table_flags) const;
+ bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
@@ -1856,6 +1988,8 @@ public:
bool type_can_have_auto_increment_attribute() const { return true; }
uint32 max_display_length(const Item *item) const { return 53; }
uint32 calc_pack_length(uint32 length) const { return sizeof(double); }
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{
return Item_send_double(item, protocol, buf);
@@ -1885,6 +2019,8 @@ public:
{
return MYSQL_TIMESTAMP_TIME;
}
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
uint Item_decimal_scale(const Item *item) const
{
return Item_decimal_scale_with_seconds(item);
@@ -1984,6 +2120,8 @@ public:
{
return MYSQL_TIMESTAMP_DATE;
}
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
bool Column_definition_fix_attributes(Column_definition *c) const;
uint Item_decimal_precision(const Item *item) const;
String *print_item_value(THD *thd, Item *item, String *str) const;
@@ -2043,6 +2181,8 @@ public:
{
return MYSQL_TIMESTAMP_DATETIME;
}
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
bool Column_definition_fix_attributes(Column_definition *c) const;
uint Item_decimal_scale(const Item *item) const
{
@@ -2227,6 +2367,11 @@ public:
Column_definition *c,
handler *file,
ulonglong table_flags) const;
+ bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
@@ -2237,7 +2382,7 @@ public:
};
-class Type_handler_null: public Type_handler_string_result
+class Type_handler_null: public Type_handler_general_purpose_string
{
static const Name m_name_null;
public:
@@ -2259,6 +2404,11 @@ public:
Column_definition *c,
handler *file,
ulonglong table_flags) const;
+ bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
@@ -2270,7 +2420,7 @@ public:
};
-class Type_handler_longstr: public Type_handler_string_result
+class Type_handler_longstr: public Type_handler_general_purpose_string
{
public:
bool type_can_have_key_part() const
@@ -2436,6 +2586,8 @@ public:
const Name name() const { return m_name_longblob; }
enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; }
uint32 calc_pack_length(uint32 length) const;
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
@@ -2502,6 +2654,8 @@ public:
const Type_all_attributes &attr,
TABLE *table) const;
+ bool can_return_int() const { return false; }
+ bool can_return_real() const { return false; }
bool is_traditional_type() const
{
return false;
@@ -2533,7 +2687,7 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_geometry type_handler_geometry;
#endif
-class Type_handler_typelib: public Type_handler_string_result
+class Type_handler_typelib: public Type_handler_general_purpose_string
{
public:
virtual ~Type_handler_typelib() { }
@@ -2550,6 +2704,11 @@ public:
Column_definition *c,
handler *file,
ulonglong table_flags) const;
+ bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const;
};
@@ -2698,6 +2857,7 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_short type_handler_short;
extern MYSQL_PLUGIN_IMPORT Type_handler_int24 type_handler_int24;
extern MYSQL_PLUGIN_IMPORT Type_handler_long type_handler_long;
extern MYSQL_PLUGIN_IMPORT Type_handler_longlong type_handler_longlong;
+extern MYSQL_PLUGIN_IMPORT Type_handler_longlong type_handler_ulonglong;
extern MYSQL_PLUGIN_IMPORT Type_handler_newdecimal type_handler_newdecimal;
extern MYSQL_PLUGIN_IMPORT Type_handler_olddecimal type_handler_olddecimal;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index f7d6861fecc..a0bbf39b138 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2509,7 +2509,7 @@ create:
{
LEX *lex= thd->lex;
- if (lex->create_info.seq_create_info->check_and_adjust())
+ if (lex->create_info.seq_create_info->check_and_adjust(1))
{
my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
lex->select_lex.table_list.first->db,
@@ -9413,10 +9413,7 @@ column_default_non_parenthesized_expr:
}
| CAST_SYM '(' expr AS cast_type ')'
{
- LEX *lex= Lex;
- $$= create_func_cast(thd, $3, $5.type(), $5.length(), $5.dec(),
- lex->charset);
- if ($$ == NULL)
+ if (!($$= $5.create_typecast_item(thd, $3, Lex->charset)))
MYSQL_YYABORT;
}
| CASE_SYM opt_expr when_list opt_else END
@@ -9427,9 +9424,7 @@ column_default_non_parenthesized_expr:
}
| CONVERT_SYM '(' expr ',' cast_type ')'
{
- $$= create_func_cast(thd, $3, $5.type(), $5.length(), $5.dec(),
- Lex->charset);
- if ($$ == NULL)
+ if (!($$= $5.create_typecast_item(thd, $3, Lex->charset)))
MYSQL_YYABORT;
}
| CONVERT_SYM '(' expr USING charset_name ')'
@@ -9508,9 +9503,8 @@ simple_expr:
| '(' parenthesized_expr ')' { $$= $2; }
| BINARY simple_expr %prec NEG
{
- $$= create_func_cast(thd, $2, ITEM_CAST_CHAR, NULL, NULL,
- &my_charset_bin);
- if ($$ == NULL)
+ Type_cast_attributes at(&my_charset_bin);
+ if (!($$= type_handler_long_blob.create_typecast_item(thd, $2, at)))
MYSQL_YYABORT;
}
| simple_expr OR_OR_SYM simple_expr
@@ -9955,7 +9949,7 @@ function_call_nonkeyword:
COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
{
LEX *lex= Lex;
- $$= create_func_dyncol_get(thd, $3, $5, $7.type(),
+ $$= create_func_dyncol_get(thd, $3, $5, $7.type_handler(),
$7.length(), $7.dec(),
lex->charset);
if ($$ == NULL)
@@ -10778,34 +10772,34 @@ in_sum_expr:
cast_type:
BINARY opt_field_length
- { $$.set(ITEM_CAST_CHAR, $2); Lex->charset= &my_charset_bin; }
+ { $$.set(&type_handler_long_blob, $2); Lex->charset= &my_charset_bin; }
| CHAR_SYM opt_field_length
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
- { $$.set(ITEM_CAST_CHAR, $2); }
+ { $$.set(&type_handler_long_blob, $2); }
| NCHAR_SYM opt_field_length
{
Lex->charset= national_charset_info;
- $$.set(ITEM_CAST_CHAR, $2, 0);
+ $$.set(&type_handler_long_blob, $2, 0);
}
| cast_type_numeric { $$= $1; Lex->charset= NULL; }
| cast_type_temporal { $$= $1; Lex->charset= NULL; }
;
cast_type_numeric:
- INT_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
- | SIGNED_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
- | SIGNED_SYM INT_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
- | UNSIGNED { $$.set(ITEM_CAST_UNSIGNED_INT); }
- | UNSIGNED INT_SYM { $$.set(ITEM_CAST_UNSIGNED_INT); }
- | DECIMAL_SYM float_options { $$.set(ITEM_CAST_DECIMAL, $2); }
- | DOUBLE_SYM opt_precision { $$.set(ITEM_CAST_DOUBLE, $2); }
+ INT_SYM { $$.set(&type_handler_longlong); }
+ | SIGNED_SYM { $$.set(&type_handler_longlong); }
+ | SIGNED_SYM INT_SYM { $$.set(&type_handler_longlong); }
+ | UNSIGNED { $$.set(&type_handler_ulonglong); }
+ | UNSIGNED INT_SYM { $$.set(&type_handler_ulonglong); }
+ | DECIMAL_SYM float_options { $$.set(&type_handler_newdecimal, $2); }
+ | DOUBLE_SYM opt_precision { $$.set(&type_handler_double, $2); }
;
cast_type_temporal:
- DATE_SYM { $$.set(ITEM_CAST_DATE); }
- | TIME_SYM opt_field_length { $$.set(ITEM_CAST_TIME, 0, $2); }
- | DATETIME opt_field_length { $$.set(ITEM_CAST_DATETIME, 0, $2); }
+ DATE_SYM { $$.set(&type_handler_newdate); }
+ | TIME_SYM opt_field_length { $$.set(&type_handler_time2, 0, $2); }
+ | DATETIME opt_field_length { $$.set(&type_handler_datetime2, 0, $2); }
;
opt_expr_list:
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index 89fd9b223f5..3787f34aec4 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -1950,7 +1950,7 @@ create:
{
LEX *lex= thd->lex;
- if (lex->create_info.seq_create_info->check_and_adjust())
+ if (lex->create_info.seq_create_info->check_and_adjust(1))
{
my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
lex->select_lex.table_list.first->db,
@@ -9434,10 +9434,7 @@ column_default_non_parenthesized_expr:
}
| CAST_SYM '(' expr AS cast_type ')'
{
- LEX *lex= Lex;
- $$= create_func_cast(thd, $3, $5.type(), $5.length(), $5.dec(),
- lex->charset);
- if ($$ == NULL)
+ if (!($$= $5.create_typecast_item(thd, $3, Lex->charset)))
MYSQL_YYABORT;
}
| CASE_SYM opt_expr when_list opt_else END
@@ -9448,9 +9445,7 @@ column_default_non_parenthesized_expr:
}
| CONVERT_SYM '(' expr ',' cast_type ')'
{
- $$= create_func_cast(thd, $3, $5.type(), $5.length(), $5.dec(),
- Lex->charset);
- if ($$ == NULL)
+ if (!($$= $5.create_typecast_item(thd, $3, Lex->charset)))
MYSQL_YYABORT;
}
| CONVERT_SYM '(' expr USING charset_name ')'
@@ -9560,9 +9555,8 @@ simple_expr:
| '(' parenthesized_expr ')' { $$= $2; }
| BINARY simple_expr %prec NEG
{
- $$= create_func_cast(thd, $2, ITEM_CAST_CHAR, NULL, NULL,
- &my_charset_bin);
- if ($$ == NULL)
+ Type_cast_attributes at(&my_charset_bin);
+ if (!($$= type_handler_long_blob.create_typecast_item(thd, $2, at)))
MYSQL_YYABORT;
}
| simple_expr OR_OR_SYM simple_expr
@@ -10010,7 +10004,7 @@ function_call_nonkeyword:
COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
{
LEX *lex= Lex;
- $$= create_func_dyncol_get(thd, $3, $5, $7.type(),
+ $$= create_func_dyncol_get(thd, $3, $5, $7.type_handler(),
$7.length(), $7.dec(),
lex->charset);
if ($$ == NULL)
@@ -10833,42 +10827,42 @@ in_sum_expr:
cast_type:
BINARY opt_field_length
- { $$.set(ITEM_CAST_CHAR, $2); Lex->charset= &my_charset_bin; }
+ { $$.set(&type_handler_long_blob, $2); Lex->charset= &my_charset_bin; }
| CHAR_SYM opt_field_length
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
- { $$.set(ITEM_CAST_CHAR, $2); }
+ { $$.set(&type_handler_long_blob, $2); }
| VARCHAR field_length
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
- { $$.set(ITEM_CAST_CHAR, $2); }
+ { $$.set(&type_handler_long_blob, $2); }
| VARCHAR2 field_length
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
- { $$.set(ITEM_CAST_CHAR, $2); }
+ { $$.set(&type_handler_long_blob, $2); }
| NCHAR_SYM opt_field_length
{
Lex->charset= national_charset_info;
- $$.set(ITEM_CAST_CHAR, $2, 0);
+ $$.set(&type_handler_long_blob, $2, 0);
}
| cast_type_numeric { $$= $1; Lex->charset= NULL; }
| cast_type_temporal { $$= $1; Lex->charset= NULL; }
;
cast_type_numeric:
- INT_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
- | SIGNED_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
- | SIGNED_SYM INT_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
- | UNSIGNED { $$.set(ITEM_CAST_UNSIGNED_INT); }
- | UNSIGNED INT_SYM { $$.set(ITEM_CAST_UNSIGNED_INT); }
- | DECIMAL_SYM float_options { $$.set(ITEM_CAST_DECIMAL, $2); }
- | DOUBLE_SYM opt_precision { $$.set(ITEM_CAST_DOUBLE, $2); }
+ INT_SYM { $$.set(&type_handler_longlong); }
+ | SIGNED_SYM { $$.set(&type_handler_longlong); }
+ | SIGNED_SYM INT_SYM { $$.set(&type_handler_longlong); }
+ | UNSIGNED { $$.set(&type_handler_ulonglong); }
+ | UNSIGNED INT_SYM { $$.set(&type_handler_ulonglong); }
+ | DECIMAL_SYM float_options { $$.set(&type_handler_newdecimal, $2); }
+ | DOUBLE_SYM opt_precision { $$.set(&type_handler_double, $2); }
;
cast_type_temporal:
- DATE_SYM { $$.set(ITEM_CAST_DATE); }
- | TIME_SYM opt_field_length { $$.set(ITEM_CAST_TIME, 0, $2); }
- | DATETIME opt_field_length { $$.set(ITEM_CAST_DATETIME, 0, $2); }
+ DATE_SYM { $$.set(&type_handler_newdate); }
+ | TIME_SYM opt_field_length { $$.set(&type_handler_time2, 0, $2); }
+ | DATETIME opt_field_length { $$.set(&type_handler_datetime2, 0, $2); }
;
opt_expr_list:
diff --git a/sql/unireg.h b/sql/unireg.h
index b1cab841092..b0cfb3841ef 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -54,8 +54,8 @@
#define ER(X) ER_THD(current_thd, (X))
#define ER_THD_OR_DEFAULT(thd,X) ((thd) ? ER_THD(thd, (X)) : ER_DEFAULT(X))
-#define ME_INFO (ME_HOLDTANG+ME_OLDWIN+ME_NOREFRESH)
-#define ME_ERROR (ME_BELL+ME_OLDWIN+ME_NOREFRESH)
+#define ME_INFO (ME_HOLDTANG | ME_NOREFRESH)
+#define ME_ERROR (ME_BELL | ME_NOREFRESH)
#define MYF_RW MYF(MY_WME+MY_NABP) /* Vid my_read & my_write */
#define SPECIAL_USE_LOCKS 1 /* Lock used databases */