Merge tulin@bk-internal.mysql.com:/home/bk/mysql-5.0
into poseidon.ndb.mysql.com:/home/tomas/mysql-5.0
This commit is contained in:
commit
ca336ad1de
@ -7,6 +7,7 @@ Greg@greg-laptop.
|
|||||||
Miguel@light.local
|
Miguel@light.local
|
||||||
Sinisa@sinisa.nasamreza.org
|
Sinisa@sinisa.nasamreza.org
|
||||||
WAX@sergbook.mysql.com
|
WAX@sergbook.mysql.com
|
||||||
|
acurtis@ltantony.rdg.cyberkinetica.homeunix.net
|
||||||
acurtis@pcgem.rdg.cyberkinetica.com
|
acurtis@pcgem.rdg.cyberkinetica.com
|
||||||
administrador@light.hegel.local
|
administrador@light.hegel.local
|
||||||
ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
|
ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
|
||||||
|
@ -3047,7 +3047,10 @@ loop:
|
|||||||
|
|
||||||
mutex_enter(&kernel_mutex);
|
mutex_enter(&kernel_mutex);
|
||||||
|
|
||||||
/* Check that there are no longer transactions */
|
/* Check that there are no longer transactions. We need this wait even
|
||||||
|
for the 'very fast' shutdown, because the InnoDB layer may have
|
||||||
|
committed or prepared transactions and we don't want to lose them. */
|
||||||
|
|
||||||
if (trx_n_mysql_transactions > 0
|
if (trx_n_mysql_transactions > 0
|
||||||
|| UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
|
|| UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
|
||||||
|
|
||||||
@ -3056,6 +3059,23 @@ loop:
|
|||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (srv_very_fast_shutdown) {
|
||||||
|
/* In a 'very fast' shutdown we do not flush the buffer pool:
|
||||||
|
it is essentially a 'crash' of the InnoDB server.
|
||||||
|
Make sure that the log is all flushed to disk, so that
|
||||||
|
we can recover all committed transactions in a crash
|
||||||
|
recovery.
|
||||||
|
In a 'very fast' shutdown we do not flush the buffer pool:
|
||||||
|
it is essentially a 'crash' of the InnoDB server. Then we must
|
||||||
|
not write the lsn stamps to the data files, since at a
|
||||||
|
startup InnoDB deduces from the stamps if the previous
|
||||||
|
shutdown was clean. */
|
||||||
|
|
||||||
|
log_buffer_flush_to_disk();
|
||||||
|
return; /* We SKIP ALL THE REST !! */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check that the master thread is suspended */
|
/* Check that the master thread is suspended */
|
||||||
|
|
||||||
if (srv_n_threads_active[SRV_MASTER] != 0) {
|
if (srv_n_threads_active[SRV_MASTER] != 0) {
|
||||||
@ -3092,24 +3112,13 @@ loop:
|
|||||||
log_archive_all();
|
log_archive_all();
|
||||||
#endif /* UNIV_LOG_ARCHIVE */
|
#endif /* UNIV_LOG_ARCHIVE */
|
||||||
|
|
||||||
if (!srv_very_fast_shutdown) {
|
|
||||||
/* In a 'very fast' shutdown we do not flush the buffer pool:
|
|
||||||
it is essentially a 'crash' of the InnoDB server. */
|
|
||||||
|
|
||||||
log_make_checkpoint_at(ut_dulint_max, TRUE);
|
log_make_checkpoint_at(ut_dulint_max, TRUE);
|
||||||
} else {
|
|
||||||
/* Make sure that the log is all flushed to disk, so that
|
|
||||||
we can recover all committed transactions in a crash
|
|
||||||
recovery */
|
|
||||||
log_buffer_flush_to_disk();
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_enter(&(log_sys->mutex));
|
mutex_enter(&(log_sys->mutex));
|
||||||
|
|
||||||
lsn = log_sys->lsn;
|
lsn = log_sys->lsn;
|
||||||
|
|
||||||
if ((ut_dulint_cmp(lsn, log_sys->last_checkpoint_lsn) != 0
|
if ((ut_dulint_cmp(lsn, log_sys->last_checkpoint_lsn) != 0)
|
||||||
&& !srv_very_fast_shutdown)
|
|
||||||
#ifdef UNIV_LOG_ARCHIVE
|
#ifdef UNIV_LOG_ARCHIVE
|
||||||
|| (srv_log_archive_on
|
|| (srv_log_archive_on
|
||||||
&& ut_dulint_cmp(lsn,
|
&& ut_dulint_cmp(lsn,
|
||||||
@ -3158,7 +3167,7 @@ loop:
|
|||||||
completely flushed to disk! (We do not call fil_write... if the
|
completely flushed to disk! (We do not call fil_write... if the
|
||||||
'very fast' shutdown is enabled.) */
|
'very fast' shutdown is enabled.) */
|
||||||
|
|
||||||
if (!srv_very_fast_shutdown && !buf_all_freed()) {
|
if (!buf_all_freed()) {
|
||||||
|
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
@ -3181,7 +3190,7 @@ loop:
|
|||||||
|
|
||||||
/* Make some checks that the server really is quiet */
|
/* Make some checks that the server really is quiet */
|
||||||
ut_a(srv_n_threads_active[SRV_MASTER] == 0);
|
ut_a(srv_n_threads_active[SRV_MASTER] == 0);
|
||||||
ut_a(srv_very_fast_shutdown || buf_all_freed());
|
ut_a(buf_all_freed());
|
||||||
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
|
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
|
||||||
|
|
||||||
if (ut_dulint_cmp(lsn, srv_start_lsn) < 0) {
|
if (ut_dulint_cmp(lsn, srv_start_lsn) < 0) {
|
||||||
@ -3196,15 +3205,7 @@ loop:
|
|||||||
|
|
||||||
srv_shutdown_lsn = lsn;
|
srv_shutdown_lsn = lsn;
|
||||||
|
|
||||||
if (!srv_very_fast_shutdown) {
|
|
||||||
/* In a 'very fast' shutdown we do not flush the buffer pool:
|
|
||||||
it is essentially a 'crash' of the InnoDB server. Then we must
|
|
||||||
not write the lsn stamps to the data files, since at a
|
|
||||||
startup InnoDB deduces from the stamps if the previous
|
|
||||||
shutdown was clean. */
|
|
||||||
|
|
||||||
fil_write_flushed_lsn_to_data_files(lsn, arch_log_no);
|
fil_write_flushed_lsn_to_data_files(lsn, arch_log_no);
|
||||||
}
|
|
||||||
|
|
||||||
fil_flush_file_spaces(FIL_TABLESPACE);
|
fil_flush_file_spaces(FIL_TABLESPACE);
|
||||||
|
|
||||||
@ -3212,7 +3213,7 @@ loop:
|
|||||||
|
|
||||||
/* Make some checks that the server really is quiet */
|
/* Make some checks that the server really is quiet */
|
||||||
ut_a(srv_n_threads_active[SRV_MASTER] == 0);
|
ut_a(srv_n_threads_active[SRV_MASTER] == 0);
|
||||||
ut_a(srv_very_fast_shutdown || buf_all_freed());
|
ut_a(buf_all_freed());
|
||||||
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
|
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1740,6 +1740,13 @@ innobase_shutdown_for_mysql(void)
|
|||||||
|
|
||||||
srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
|
srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
|
||||||
|
|
||||||
|
/* In a 'very fast' shutdown, we do not need to wait for these threads
|
||||||
|
to die; all which counts is that we flushed the log; a 'very fast'
|
||||||
|
shutdown is essentially a crash. */
|
||||||
|
|
||||||
|
if (srv_fast_shutdown)
|
||||||
|
return((int) DB_SUCCESS);
|
||||||
|
|
||||||
/* All threads end up waiting for certain events. Put those events
|
/* All threads end up waiting for certain events. Put those events
|
||||||
to the signaled state. Then the threads will exit themselves in
|
to the signaled state. Then the threads will exit themselves in
|
||||||
os_thread_event_wait(). */
|
os_thread_event_wait(). */
|
||||||
|
@ -203,7 +203,7 @@ select parameter_style, sql_data_access, dtd_identifier
|
|||||||
from information_schema.routines;
|
from information_schema.routines;
|
||||||
parameter_style sql_data_access dtd_identifier
|
parameter_style sql_data_access dtd_identifier
|
||||||
SQL CONTAINS SQL NULL
|
SQL CONTAINS SQL NULL
|
||||||
SQL CONTAINS SQL int
|
SQL CONTAINS SQL int(11)
|
||||||
show procedure status;
|
show procedure status;
|
||||||
Db Name Type Definer Modified Created Security_type Comment
|
Db Name Type Definer Modified Created Security_type Comment
|
||||||
test sel2 PROCEDURE root@localhost # # DEFINER
|
test sel2 PROCEDURE root@localhost # # DEFINER
|
||||||
@ -258,7 +258,7 @@ Function sql_mode Create Function
|
|||||||
sub1
|
sub1
|
||||||
show create function sub2;
|
show create function sub2;
|
||||||
Function sql_mode Create Function
|
Function sql_mode Create Function
|
||||||
sub2 CREATE FUNCTION `test`.`sub2`(i int) RETURNS int
|
sub2 CREATE FUNCTION `test`.`sub2`(i int) RETURNS int(11)
|
||||||
return i+1
|
return i+1
|
||||||
drop function sub2;
|
drop function sub2;
|
||||||
show create procedure sel2;
|
show create procedure sel2;
|
||||||
|
@ -962,7 +962,7 @@ comment 'Characteristics procedure test'
|
|||||||
return 42|
|
return 42|
|
||||||
show create function chistics|
|
show create function chistics|
|
||||||
Function sql_mode Create Function
|
Function sql_mode Create Function
|
||||||
chistics CREATE FUNCTION `test`.`chistics`() RETURNS int
|
chistics CREATE FUNCTION `test`.`chistics`() RETURNS int(11)
|
||||||
DETERMINISTIC
|
DETERMINISTIC
|
||||||
SQL SECURITY INVOKER
|
SQL SECURITY INVOKER
|
||||||
COMMENT 'Characteristics procedure test'
|
COMMENT 'Characteristics procedure test'
|
||||||
@ -975,7 +975,7 @@ no sql
|
|||||||
comment 'Characteristics function test'|
|
comment 'Characteristics function test'|
|
||||||
show create function chistics|
|
show create function chistics|
|
||||||
Function sql_mode Create Function
|
Function sql_mode Create Function
|
||||||
chistics CREATE FUNCTION `test`.`chistics`() RETURNS int
|
chistics CREATE FUNCTION `test`.`chistics`() RETURNS int(11)
|
||||||
NO SQL
|
NO SQL
|
||||||
DETERMINISTIC
|
DETERMINISTIC
|
||||||
SQL SECURITY INVOKER
|
SQL SECURITY INVOKER
|
||||||
@ -2026,11 +2026,11 @@ bug2564_2 ANSI_QUOTES CREATE PROCEDURE "test"."bug2564_2"()
|
|||||||
insert into "t1" values ('foo', 1)
|
insert into "t1" values ('foo', 1)
|
||||||
show create function bug2564_3|
|
show create function bug2564_3|
|
||||||
Function sql_mode Create Function
|
Function sql_mode Create Function
|
||||||
bug2564_3 CREATE FUNCTION `test`.`bug2564_3`(x int, y int) RETURNS int
|
bug2564_3 CREATE FUNCTION `test`.`bug2564_3`(x int, y int) RETURNS int(11)
|
||||||
return x || y
|
return x || y
|
||||||
show create function bug2564_4|
|
show create function bug2564_4|
|
||||||
Function sql_mode Create Function
|
Function sql_mode Create Function
|
||||||
bug2564_4 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI CREATE FUNCTION "test"."bug2564_4"(x int, y int) RETURNS int
|
bug2564_4 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI CREATE FUNCTION "test"."bug2564_4"(x int, y int) RETURNS int(11)
|
||||||
return x || y
|
return x || y
|
||||||
drop procedure bug2564_1|
|
drop procedure bug2564_1|
|
||||||
drop procedure bug2564_2|
|
drop procedure bug2564_2|
|
||||||
@ -2095,6 +2095,28 @@ drop procedure bug4579_1|
|
|||||||
drop procedure bug4579_2|
|
drop procedure bug4579_2|
|
||||||
drop table t3|
|
drop table t3|
|
||||||
drop table if exists t3|
|
drop table if exists t3|
|
||||||
|
drop procedure if exists bug2773|
|
||||||
|
create function bug2773() returns int return null|
|
||||||
|
create table t3 as select bug2773()|
|
||||||
|
show create table t3|
|
||||||
|
Table Create Table
|
||||||
|
t3 CREATE TABLE `t3` (
|
||||||
|
`bug2773()` int(11) default NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
drop table t3|
|
||||||
|
drop function bug2773|
|
||||||
|
drop procedure if exists bug3788|
|
||||||
|
create function bug3788() returns date return cast("2005-03-04" as date)|
|
||||||
|
select bug3788()|
|
||||||
|
bug3788()
|
||||||
|
2005-03-04
|
||||||
|
drop function bug3788|
|
||||||
|
create function bug3788() returns binary(5) return 5|
|
||||||
|
select bug3788()|
|
||||||
|
bug3788()
|
||||||
|
5
|
||||||
|
drop function bug3788|
|
||||||
|
drop table if exists t3|
|
||||||
create table t3 (f1 int, f2 int, f3 int)|
|
create table t3 (f1 int, f2 int, f3 int)|
|
||||||
insert into t3 values (1,1,1)|
|
insert into t3 values (1,1,1)|
|
||||||
drop procedure if exists bug4726|
|
drop procedure if exists bug4726|
|
||||||
|
@ -2546,6 +2546,35 @@ drop procedure bug4579_1|
|
|||||||
drop procedure bug4579_2|
|
drop procedure bug4579_2|
|
||||||
drop table t3|
|
drop table t3|
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#2773: Function's data type ignored in stored procedures
|
||||||
|
#
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t3|
|
||||||
|
drop procedure if exists bug2773|
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
create function bug2773() returns int return null|
|
||||||
|
create table t3 as select bug2773()|
|
||||||
|
show create table t3|
|
||||||
|
drop table t3|
|
||||||
|
drop function bug2773|
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#3788: Stored procedure packet error
|
||||||
|
#
|
||||||
|
--disable_warnings
|
||||||
|
drop procedure if exists bug3788|
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
create function bug3788() returns date return cast("2005-03-04" as date)|
|
||||||
|
select bug3788()|
|
||||||
|
drop function bug3788|
|
||||||
|
|
||||||
|
create function bug3788() returns binary(5) return 5|
|
||||||
|
select bug3788()|
|
||||||
|
drop function bug3788|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# BUG#4726
|
# BUG#4726
|
||||||
|
@ -3521,7 +3521,7 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
enum_parsing_place place= NO_MATTER;
|
enum_parsing_place place= NO_MATTER;
|
||||||
SELECT_LEX *current_sel= thd->lex->current_select;
|
SELECT_LEX *current_sel= thd->lex->current_select;
|
||||||
|
|
||||||
if (!ref)
|
if (!ref || ref == not_found_item)
|
||||||
{
|
{
|
||||||
SELECT_LEX_UNIT *prev_unit= current_sel->master_unit();
|
SELECT_LEX_UNIT *prev_unit= current_sel->master_unit();
|
||||||
SELECT_LEX *outer_sel= prev_unit->outer_select();
|
SELECT_LEX *outer_sel= prev_unit->outer_select();
|
||||||
|
@ -4368,13 +4368,33 @@ longlong Item_func_row_count::val_int()
|
|||||||
Item_func_sp::Item_func_sp(sp_name *name)
|
Item_func_sp::Item_func_sp(sp_name *name)
|
||||||
:Item_func(), m_name(name), m_sp(NULL)
|
:Item_func(), m_name(name), m_sp(NULL)
|
||||||
{
|
{
|
||||||
|
char *empty_name= (char *) "";
|
||||||
|
maybe_null= 1;
|
||||||
m_name->init_qname(current_thd);
|
m_name->init_qname(current_thd);
|
||||||
|
bzero(&dummy_table, sizeof(dummy_table));
|
||||||
|
dummy_table.share.table_cache_key = empty_name;
|
||||||
|
dummy_table.share.table_name = empty_name;
|
||||||
|
dummy_table.table.alias = empty_name;
|
||||||
|
dummy_table.share.table_name = empty_name;
|
||||||
|
dummy_table.table.maybe_null = maybe_null;
|
||||||
|
dummy_table.table.in_use= current_thd;
|
||||||
|
dummy_table.table.s = &dummy_table.share;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list)
|
Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list)
|
||||||
:Item_func(list), m_name(name), m_sp(NULL)
|
:Item_func(list), m_name(name), m_sp(NULL)
|
||||||
{
|
{
|
||||||
|
char *empty_name= (char *) "";
|
||||||
|
maybe_null= 1;
|
||||||
m_name->init_qname(current_thd);
|
m_name->init_qname(current_thd);
|
||||||
|
bzero(&dummy_table, sizeof(dummy_table));
|
||||||
|
dummy_table.share.table_cache_key = empty_name;
|
||||||
|
dummy_table.share.table_name = empty_name;
|
||||||
|
dummy_table.table.alias = empty_name;
|
||||||
|
dummy_table.share.table_name = empty_name;
|
||||||
|
dummy_table.table.maybe_null = maybe_null;
|
||||||
|
dummy_table.table.in_use= current_thd;
|
||||||
|
dummy_table.table.s = &dummy_table.share;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
@ -4399,6 +4419,18 @@ Item_func_sp::func_name() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *
|
||||||
|
Item_func_sp::sp_result_field(void) const
|
||||||
|
{
|
||||||
|
Field *field= 0;
|
||||||
|
THD *thd= current_thd;
|
||||||
|
DBUG_ENTER("Item_func_sp::sp_result_field");
|
||||||
|
if (m_sp)
|
||||||
|
field= m_sp->make_field(max_length, name, &dummy_table.table);
|
||||||
|
DBUG_RETURN(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
Item_func_sp::execute(Item **itp)
|
Item_func_sp::execute(Item **itp)
|
||||||
{
|
{
|
||||||
@ -4449,17 +4481,38 @@ Item_func_sp::execute(Item **itp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Item_func_sp::make_field(Send_field *tmp_field)
|
||||||
|
{
|
||||||
|
Field *field;
|
||||||
|
DBUG_ENTER("Item_func_sp::make_field");
|
||||||
|
if (! m_sp)
|
||||||
|
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
|
||||||
|
if ((field= sp_result_field()))
|
||||||
|
{
|
||||||
|
field->make_field(tmp_field);
|
||||||
|
delete field;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
|
||||||
|
init_make_field(tmp_field, MYSQL_TYPE_VARCHAR);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
enum enum_field_types
|
enum enum_field_types
|
||||||
Item_func_sp::field_type() const
|
Item_func_sp::field_type() const
|
||||||
{
|
{
|
||||||
|
Field *field= 0;
|
||||||
DBUG_ENTER("Item_func_sp::field_type");
|
DBUG_ENTER("Item_func_sp::field_type");
|
||||||
|
|
||||||
if (! m_sp)
|
if (! m_sp)
|
||||||
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
|
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
|
||||||
if (m_sp)
|
if ((field= sp_result_field()))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("m_returns = %d", m_sp->m_returns));
|
enum_field_types result= field->type();
|
||||||
DBUG_RETURN(m_sp->m_returns);
|
delete field;
|
||||||
|
DBUG_RETURN(result);
|
||||||
}
|
}
|
||||||
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
|
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
|
||||||
DBUG_RETURN(MYSQL_TYPE_VARCHAR);
|
DBUG_RETURN(MYSQL_TYPE_VARCHAR);
|
||||||
@ -4469,14 +4522,17 @@ Item_func_sp::field_type() const
|
|||||||
Item_result
|
Item_result
|
||||||
Item_func_sp::result_type() const
|
Item_func_sp::result_type() const
|
||||||
{
|
{
|
||||||
|
Field *field= 0;
|
||||||
DBUG_ENTER("Item_func_sp::result_type");
|
DBUG_ENTER("Item_func_sp::result_type");
|
||||||
DBUG_PRINT("info", ("m_sp = %p", m_sp));
|
DBUG_PRINT("info", ("m_sp = %p", m_sp));
|
||||||
|
|
||||||
if (! m_sp)
|
if (! m_sp)
|
||||||
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
|
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
|
||||||
if (m_sp)
|
if ((field= sp_result_field()))
|
||||||
{
|
{
|
||||||
DBUG_RETURN(m_sp->result());
|
Item_result result= field->result_type();
|
||||||
|
delete field;
|
||||||
|
DBUG_RETURN(result);
|
||||||
}
|
}
|
||||||
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
|
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
|
||||||
DBUG_RETURN(STRING_RESULT);
|
DBUG_RETURN(STRING_RESULT);
|
||||||
@ -4495,7 +4551,7 @@ Item_func_sp::fix_length_and_dec()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (m_sp->result()) {
|
switch (result_type()) {
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
maybe_null= 1;
|
maybe_null= 1;
|
||||||
max_length= MAX_BLOB_WIDTH;
|
max_length= MAX_BLOB_WIDTH;
|
||||||
@ -4530,3 +4586,19 @@ longlong Item_func_found_rows::val_int()
|
|||||||
|
|
||||||
return thd->found_rows();
|
return thd->found_rows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Field *
|
||||||
|
Item_func_sp::tmp_table_field(TABLE *t_arg)
|
||||||
|
{
|
||||||
|
Field *res= 0;
|
||||||
|
enum_field_types ftype;
|
||||||
|
DBUG_ENTER("Item_func_sp::tmp_table_field");
|
||||||
|
|
||||||
|
if (m_sp)
|
||||||
|
res= m_sp->make_field(max_length, (const char *)name, t_arg);
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
res= Item_func::tmp_table_field(t_arg);
|
||||||
|
|
||||||
|
DBUG_RETURN(res);
|
||||||
|
}
|
||||||
|
@ -1252,8 +1252,13 @@ class Item_func_sp :public Item_func
|
|||||||
private:
|
private:
|
||||||
sp_name *m_name;
|
sp_name *m_name;
|
||||||
mutable sp_head *m_sp;
|
mutable sp_head *m_sp;
|
||||||
|
mutable struct {
|
||||||
|
TABLE table;
|
||||||
|
TABLE_SHARE share;
|
||||||
|
} dummy_table;
|
||||||
|
|
||||||
int execute(Item **itp);
|
int execute(Item **itp);
|
||||||
|
Field *sp_result_field(void) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -1268,6 +1273,10 @@ public:
|
|||||||
|
|
||||||
enum enum_field_types field_type() const;
|
enum enum_field_types field_type() const;
|
||||||
|
|
||||||
|
Field *tmp_table_field(TABLE *t_arg);
|
||||||
|
|
||||||
|
void make_field(Send_field *tmp_field);
|
||||||
|
|
||||||
Item_result result_type() const;
|
Item_result result_type() const;
|
||||||
|
|
||||||
longlong val_int()
|
longlong val_int()
|
||||||
|
@ -629,6 +629,10 @@ int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t);
|
|||||||
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
||||||
Item ***copy_func, Field **from_field,
|
Item ***copy_func, Field **from_field,
|
||||||
bool group, bool modify_item, uint convert_blob_length);
|
bool group, bool modify_item, uint convert_blob_length);
|
||||||
|
int prepare_create_field(create_field *sql_field,
|
||||||
|
uint &blob_columns,
|
||||||
|
int ×tamps, int ×tamps_with_niladic,
|
||||||
|
uint table_flags);
|
||||||
int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||||
List<create_field> &fields,
|
List<create_field> &fields,
|
||||||
List<Key> &keys, uint &db_options,
|
List<Key> &keys, uint &db_options,
|
||||||
@ -838,6 +842,13 @@ bool add_field_to_list(THD *thd, char *field_name, enum enum_field_types type,
|
|||||||
char *change, List<String> *interval_list,
|
char *change, List<String> *interval_list,
|
||||||
CHARSET_INFO *cs,
|
CHARSET_INFO *cs,
|
||||||
uint uint_geom_type);
|
uint uint_geom_type);
|
||||||
|
create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
|
||||||
|
char *length, char *decimals,
|
||||||
|
uint type_modifier,
|
||||||
|
Item *default_value, Item *on_update_value,
|
||||||
|
LEX_STRING *comment, char *change,
|
||||||
|
List<String> *interval_list, CHARSET_INFO *cs,
|
||||||
|
uint uint_geom_type);
|
||||||
void store_position_for_column(const char *name);
|
void store_position_for_column(const char *name);
|
||||||
bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc=0);
|
bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc=0);
|
||||||
void add_join_on(TABLE_LIST *b,Item *expr);
|
void add_join_on(TABLE_LIST *b,Item *expr);
|
||||||
|
24
sql/sp.cc
24
sql/sp.cc
@ -334,6 +334,22 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
sp_returns_type(THD *thd, String &result, sp_head *sp)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
TABLE table;
|
||||||
|
TABLE_SHARE share;
|
||||||
|
} dummy;
|
||||||
|
Field *field;
|
||||||
|
bzero(&dummy, sizeof(dummy));
|
||||||
|
dummy.table.in_use= thd;
|
||||||
|
dummy.table.s = &dummy.share;
|
||||||
|
field= sp->make_field(0, 0, &dummy.table);
|
||||||
|
field->sql_type(result);
|
||||||
|
delete field;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
db_create_routine(THD *thd, int type, sp_head *sp)
|
db_create_routine(THD *thd, int type, sp_head *sp)
|
||||||
{
|
{
|
||||||
@ -388,9 +404,13 @@ db_create_routine(THD *thd, int type, sp_head *sp)
|
|||||||
store((longlong)sp->m_chistics->suid);
|
store((longlong)sp->m_chistics->suid);
|
||||||
table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
|
table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
|
||||||
store(sp->m_params.str, sp->m_params.length, system_charset_info);
|
store(sp->m_params.str, sp->m_params.length, system_charset_info);
|
||||||
if (sp->m_retstr.str)
|
if (sp->m_type == TYPE_ENUM_FUNCTION)
|
||||||
|
{
|
||||||
|
String retstr(64);
|
||||||
|
sp_returns_type(thd, retstr, sp);
|
||||||
table->field[MYSQL_PROC_FIELD_RETURNS]->
|
table->field[MYSQL_PROC_FIELD_RETURNS]->
|
||||||
store(sp->m_retstr.str, sp->m_retstr.length, system_charset_info);
|
store(retstr.ptr(), retstr.length(), system_charset_info);
|
||||||
|
}
|
||||||
table->field[MYSQL_PROC_FIELD_BODY]->
|
table->field[MYSQL_PROC_FIELD_BODY]->
|
||||||
store(sp->m_body.str, sp->m_body.length, system_charset_info);
|
store(sp->m_body.str, sp->m_body.length, system_charset_info);
|
||||||
table->field[MYSQL_PROC_FIELD_DEFINER]->
|
table->field[MYSQL_PROC_FIELD_DEFINER]->
|
||||||
|
@ -305,11 +305,11 @@ sp_head::init(LEX *lex)
|
|||||||
*/
|
*/
|
||||||
lex->trg_table_fields.empty();
|
lex->trg_table_fields.empty();
|
||||||
my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8);
|
my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8);
|
||||||
m_param_begin= m_param_end= m_returns_begin= m_returns_end= m_body_begin= 0;
|
m_param_begin= m_param_end= m_body_begin= 0;
|
||||||
m_qname.str= m_db.str= m_name.str= m_params.str= m_retstr.str=
|
m_qname.str= m_db.str= m_name.str= m_params.str=
|
||||||
m_body.str= m_defstr.str= 0;
|
m_body.str= m_defstr.str= 0;
|
||||||
m_qname.length= m_db.length= m_name.length= m_params.length=
|
m_qname.length= m_db.length= m_name.length= m_params.length=
|
||||||
m_retstr.length= m_body.length= m_defstr.length= 0;
|
m_body.length= m_defstr.length= 0;
|
||||||
m_returns_cs= NULL;
|
m_returns_cs= NULL;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -351,41 +351,6 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
|
|||||||
(char *)m_param_begin, m_params.length);
|
(char *)m_param_begin, m_params.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_returns_begin && m_returns_end)
|
|
||||||
{
|
|
||||||
/* QQ KLUDGE: We can't seem to cut out just the type in the parser
|
|
||||||
(without the RETURNS), so we'll have to do it here. :-(
|
|
||||||
Furthermore, if there's a character type as well, it's not include
|
|
||||||
(beyond the m_returns_end pointer), in which case we need
|
|
||||||
m_returns_cs. */
|
|
||||||
char *p= (char *)m_returns_begin+strspn((char *)m_returns_begin,"\t\n\r ");
|
|
||||||
p+= strcspn(p, "\t\n\r ");
|
|
||||||
p+= strspn(p, "\t\n\r ");
|
|
||||||
if (p < (char *)m_returns_end)
|
|
||||||
m_returns_begin= (uchar *)p;
|
|
||||||
/* While we're at it, trim the end too. */
|
|
||||||
p= (char *)m_returns_end-1;
|
|
||||||
while (p > (char *)m_returns_begin &&
|
|
||||||
(*p == '\t' || *p == '\n' || *p == '\r' || *p == ' '))
|
|
||||||
p-= 1;
|
|
||||||
m_returns_end= (uchar *)p+1;
|
|
||||||
if (m_returns_cs)
|
|
||||||
{
|
|
||||||
String s((char *)m_returns_begin, m_returns_end - m_returns_begin,
|
|
||||||
system_charset_info);
|
|
||||||
|
|
||||||
s.append(' ');
|
|
||||||
s.append(m_returns_cs->csname);
|
|
||||||
m_retstr.length= s.length();
|
|
||||||
m_retstr.str= strmake_root(root, s.ptr(), m_retstr.length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_retstr.length= m_returns_end - m_returns_begin;
|
|
||||||
m_retstr.str= strmake_root(root,
|
|
||||||
(char *)m_returns_begin, m_retstr.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_body.length= lex->ptr - m_body_begin;
|
m_body.length= lex->ptr - m_body_begin;
|
||||||
/* Trim nuls at the end */
|
/* Trim nuls at the end */
|
||||||
n= 0;
|
n= 0;
|
||||||
@ -401,6 +366,27 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TYPELIB *
|
||||||
|
sp_head::create_typelib(List<String> *src)
|
||||||
|
{
|
||||||
|
TYPELIB *result= NULL;
|
||||||
|
DBUG_ENTER("sp_head::clone_typelib");
|
||||||
|
if (src->elements)
|
||||||
|
{
|
||||||
|
result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
|
||||||
|
result->count= src->elements;
|
||||||
|
result->name= "";
|
||||||
|
if (!(result->type_names=(const char **)
|
||||||
|
alloc_root(mem_root,sizeof(char *)*(result->count+1))))
|
||||||
|
return 0;
|
||||||
|
List_iterator<String> it(*src);
|
||||||
|
for (uint i=0; i<result->count; i++)
|
||||||
|
result->type_names[i]= strdup_root(mem_root, (it++)->c_ptr());
|
||||||
|
result->type_names[result->count]= 0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_head::create(THD *thd)
|
sp_head::create(THD *thd)
|
||||||
{
|
{
|
||||||
@ -481,6 +467,21 @@ sp_head::destroy()
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *
|
||||||
|
sp_head::make_field(uint max_length, const char *name, TABLE *dummy)
|
||||||
|
{
|
||||||
|
Field *field;
|
||||||
|
DBUG_ENTER("sp_head::make_field");
|
||||||
|
field= ::make_field((char *)0,
|
||||||
|
!m_returns_len ? max_length : m_returns_len,
|
||||||
|
(uchar *)"", 0, m_returns_pack, m_returns, m_returns_cs,
|
||||||
|
(enum Field::geometry_type)0, Field::NONE,
|
||||||
|
m_returns_typelib,
|
||||||
|
name ? name : (const char *)m_name.str, dummy);
|
||||||
|
DBUG_RETURN(field);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_head::execute(THD *thd)
|
sp_head::execute(THD *thd)
|
||||||
{
|
{
|
||||||
|
@ -84,6 +84,9 @@ public:
|
|||||||
int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
|
int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
|
||||||
enum enum_field_types m_returns; // For FUNCTIONs only
|
enum enum_field_types m_returns; // For FUNCTIONs only
|
||||||
CHARSET_INFO *m_returns_cs; // For FUNCTIONs only
|
CHARSET_INFO *m_returns_cs; // For FUNCTIONs only
|
||||||
|
TYPELIB *m_returns_typelib; // For FUNCTIONs only
|
||||||
|
uint m_returns_len; // For FUNCTIONs only
|
||||||
|
uint m_returns_pack; // For FUNCTIONs only
|
||||||
my_bool m_has_return; // For FUNCTIONs only
|
my_bool m_has_return; // For FUNCTIONs only
|
||||||
my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise
|
my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise
|
||||||
my_bool m_multi_results; // TRUE if a procedure with SELECT(s)
|
my_bool m_multi_results; // TRUE if a procedure with SELECT(s)
|
||||||
@ -96,7 +99,6 @@ public:
|
|||||||
LEX_STRING m_db;
|
LEX_STRING m_db;
|
||||||
LEX_STRING m_name;
|
LEX_STRING m_name;
|
||||||
LEX_STRING m_params;
|
LEX_STRING m_params;
|
||||||
LEX_STRING m_retstr; // For FUNCTIONs only
|
|
||||||
LEX_STRING m_body;
|
LEX_STRING m_body;
|
||||||
LEX_STRING m_defstr;
|
LEX_STRING m_defstr;
|
||||||
LEX_STRING m_definer_user;
|
LEX_STRING m_definer_user;
|
||||||
@ -112,8 +114,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
HASH m_spfuns, m_spprocs;
|
HASH m_spfuns, m_spprocs;
|
||||||
// Pointers set during parsing
|
// Pointers set during parsing
|
||||||
uchar *m_param_begin, *m_param_end, *m_returns_begin, *m_returns_end,
|
uchar *m_param_begin, *m_param_end, *m_body_begin;
|
||||||
*m_body_begin;
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
operator new(size_t size);
|
operator new(size_t size);
|
||||||
@ -131,6 +132,9 @@ public:
|
|||||||
void
|
void
|
||||||
init_strings(THD *thd, LEX *lex, sp_name *name);
|
init_strings(THD *thd, LEX *lex, sp_name *name);
|
||||||
|
|
||||||
|
TYPELIB *
|
||||||
|
create_typelib(List<String> *src);
|
||||||
|
|
||||||
int
|
int
|
||||||
create(THD *thd);
|
create(THD *thd);
|
||||||
|
|
||||||
@ -204,10 +208,7 @@ public:
|
|||||||
|
|
||||||
char *create_string(THD *thd, ulong *lenp);
|
char *create_string(THD *thd, ulong *lenp);
|
||||||
|
|
||||||
inline Item_result result()
|
Field *make_field(uint max_length, const char *name, TABLE *dummy);
|
||||||
{
|
|
||||||
return sp_map_result_type(m_returns);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_info(char *definer, uint definerlen,
|
void set_info(char *definer, uint definerlen,
|
||||||
longlong created, longlong modified,
|
longlong created, longlong modified,
|
||||||
|
@ -5207,9 +5207,6 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
|
|||||||
{
|
{
|
||||||
register create_field *new_field;
|
register create_field *new_field;
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
uint allowed_type_modifier=0;
|
|
||||||
uint sign_len;
|
|
||||||
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
|
|
||||||
DBUG_ENTER("add_field_to_list");
|
DBUG_ENTER("add_field_to_list");
|
||||||
|
|
||||||
if (strlen(field_name) > NAME_LEN)
|
if (strlen(field_name) > NAME_LEN)
|
||||||
@ -5270,9 +5267,38 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
|
|||||||
my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name);
|
my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(new_field=new create_field()))
|
if (!(new_field= new_create_field(thd, field_name, type, length, decimals,
|
||||||
|
type_modifier, default_value, on_update_value,
|
||||||
|
comment, change, interval_list, cs, uint_geom_type)))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
|
lex->create_list.push_back(new_field);
|
||||||
|
lex->last_field=new_field;
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** Create field definition for create
|
||||||
|
** Return 0 on failure, otherwise return create_field instance
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
create_field *
|
||||||
|
new_create_field(THD *thd, char *field_name, enum_field_types type,
|
||||||
|
char *length, char *decimals,
|
||||||
|
uint type_modifier,
|
||||||
|
Item *default_value, Item *on_update_value,
|
||||||
|
LEX_STRING *comment,
|
||||||
|
char *change, List<String> *interval_list, CHARSET_INFO *cs,
|
||||||
|
uint uint_geom_type)
|
||||||
|
{
|
||||||
|
register create_field *new_field;
|
||||||
|
uint sign_len, allowed_type_modifier=0;
|
||||||
|
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
|
||||||
|
DBUG_ENTER("new_create_field");
|
||||||
|
|
||||||
|
if (!(new_field=new create_field()))
|
||||||
|
DBUG_RETURN(NULL);
|
||||||
new_field->field=0;
|
new_field->field=0;
|
||||||
new_field->field_name=field_name;
|
new_field->field_name=field_name;
|
||||||
new_field->def= default_value;
|
new_field->def= default_value;
|
||||||
@ -5344,7 +5370,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
|
|||||||
new_field->length >= new_field->decimals)
|
new_field->length >= new_field->decimals)
|
||||||
break;
|
break;
|
||||||
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
|
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(NULL);
|
||||||
case MYSQL_TYPE_VARCHAR:
|
case MYSQL_TYPE_VARCHAR:
|
||||||
/*
|
/*
|
||||||
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
|
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
|
||||||
@ -5367,7 +5393,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
|
|||||||
{
|
{
|
||||||
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0),
|
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0),
|
||||||
field_name); /* purecov: inspected */
|
field_name); /* purecov: inspected */
|
||||||
DBUG_RETURN(1); /* purecov: inspected */
|
DBUG_RETURN(NULL);
|
||||||
}
|
}
|
||||||
new_field->def=0;
|
new_field->def=0;
|
||||||
}
|
}
|
||||||
@ -5387,7 +5413,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
|
|||||||
if (tmp_length > PRECISION_FOR_DOUBLE)
|
if (tmp_length > PRECISION_FOR_DOUBLE)
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
|
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(NULL);
|
||||||
}
|
}
|
||||||
else if (tmp_length > PRECISION_FOR_FLOAT)
|
else if (tmp_length > PRECISION_FOR_FLOAT)
|
||||||
{
|
{
|
||||||
@ -5484,7 +5510,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
|
|||||||
if (interval_list->elements > sizeof(longlong)*8)
|
if (interval_list->elements > sizeof(longlong)*8)
|
||||||
{
|
{
|
||||||
my_error(ER_TOO_BIG_SET, MYF(0), field_name); /* purecov: inspected */
|
my_error(ER_TOO_BIG_SET, MYF(0), field_name); /* purecov: inspected */
|
||||||
DBUG_RETURN(1); /* purecov: inspected */
|
DBUG_RETURN(NULL);
|
||||||
}
|
}
|
||||||
new_field->pack_length= (interval_list->elements + 7) / 8;
|
new_field->pack_length= (interval_list->elements + 7) / 8;
|
||||||
if (new_field->pack_length > 4)
|
if (new_field->pack_length > 4)
|
||||||
@ -5525,7 +5551,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
|
|||||||
{
|
{
|
||||||
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name,
|
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name,
|
||||||
MAX_BIT_FIELD_LENGTH);
|
MAX_BIT_FIELD_LENGTH);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(NULL);
|
||||||
}
|
}
|
||||||
new_field->pack_length= (new_field->length + 7) / 8;
|
new_field->pack_length= (new_field->length + 7) / 8;
|
||||||
break;
|
break;
|
||||||
@ -5544,17 +5570,15 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
|
|||||||
{
|
{
|
||||||
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0),
|
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0),
|
||||||
field_name, max_field_charlength); /* purecov: inspected */
|
field_name, max_field_charlength); /* purecov: inspected */
|
||||||
DBUG_RETURN(1); /* purecov: inspected */
|
DBUG_RETURN(NULL);
|
||||||
}
|
}
|
||||||
type_modifier&= AUTO_INCREMENT_FLAG;
|
type_modifier&= AUTO_INCREMENT_FLAG;
|
||||||
if ((~allowed_type_modifier) & type_modifier)
|
if ((~allowed_type_modifier) & type_modifier)
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
|
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(NULL);
|
||||||
}
|
}
|
||||||
lex->create_list.push_back(new_field);
|
DBUG_RETURN(new_field);
|
||||||
lex->last_field=new_field;
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
314
sql/sql_table.cc
314
sql/sql_table.cc
@ -431,6 +431,173 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Prepare a create_table instance for packing
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
prepare_create_field()
|
||||||
|
sql_field field to prepare for packing
|
||||||
|
blob_columns count for BLOBs
|
||||||
|
timestamps count for timestamps
|
||||||
|
table_flags table flags
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
This function prepares a create_field instance.
|
||||||
|
Fields such as pack_flag are valid after this call.
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
0 ok
|
||||||
|
1 Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
int prepare_create_field(create_field *sql_field,
|
||||||
|
uint &blob_columns,
|
||||||
|
int ×tamps, int ×tamps_with_niladic,
|
||||||
|
uint table_flags)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("prepare_field");
|
||||||
|
{
|
||||||
|
/* This code came from mysql_prepare_table.
|
||||||
|
Indent preserved to make patching easier */
|
||||||
|
DBUG_ASSERT(sql_field->charset);
|
||||||
|
|
||||||
|
switch (sql_field->sql_type) {
|
||||||
|
case FIELD_TYPE_BLOB:
|
||||||
|
case FIELD_TYPE_MEDIUM_BLOB:
|
||||||
|
case FIELD_TYPE_TINY_BLOB:
|
||||||
|
case FIELD_TYPE_LONG_BLOB:
|
||||||
|
sql_field->pack_flag=FIELDFLAG_BLOB |
|
||||||
|
pack_length_to_packflag(sql_field->pack_length -
|
||||||
|
portable_sizeof_char_ptr);
|
||||||
|
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||||
|
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||||
|
sql_field->length=8; // Unireg field length
|
||||||
|
sql_field->unireg_check=Field::BLOB_FIELD;
|
||||||
|
blob_columns++;
|
||||||
|
break;
|
||||||
|
case FIELD_TYPE_GEOMETRY:
|
||||||
|
#ifdef HAVE_SPATIAL
|
||||||
|
if (!(table_flags & HA_CAN_GEOMETRY))
|
||||||
|
{
|
||||||
|
my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
|
||||||
|
MYF(0), "GEOMETRY");
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
sql_field->pack_flag=FIELDFLAG_GEOM |
|
||||||
|
pack_length_to_packflag(sql_field->pack_length -
|
||||||
|
portable_sizeof_char_ptr);
|
||||||
|
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||||
|
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||||
|
sql_field->length=8; // Unireg field length
|
||||||
|
sql_field->unireg_check=Field::BLOB_FIELD;
|
||||||
|
blob_columns++;
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0),
|
||||||
|
sym_group_geom.name, sym_group_geom.needed_define);
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
#endif /*HAVE_SPATIAL*/
|
||||||
|
case MYSQL_TYPE_VARCHAR:
|
||||||
|
#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
|
||||||
|
if (table_flags & HA_NO_VARCHAR)
|
||||||
|
{
|
||||||
|
/* convert VARCHAR to CHAR because handler is not yet up to date */
|
||||||
|
sql_field->sql_type= MYSQL_TYPE_VAR_STRING;
|
||||||
|
sql_field->pack_length= calc_pack_length(sql_field->sql_type,
|
||||||
|
(uint) sql_field->length);
|
||||||
|
if ((sql_field->length / sql_field->charset->mbmaxlen) >
|
||||||
|
MAX_FIELD_CHARLENGTH)
|
||||||
|
{
|
||||||
|
my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
|
||||||
|
MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* fall through */
|
||||||
|
case FIELD_TYPE_STRING:
|
||||||
|
sql_field->pack_flag=0;
|
||||||
|
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||||
|
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||||
|
break;
|
||||||
|
case FIELD_TYPE_ENUM:
|
||||||
|
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
|
||||||
|
FIELDFLAG_INTERVAL;
|
||||||
|
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||||
|
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||||
|
sql_field->unireg_check=Field::INTERVAL_FIELD;
|
||||||
|
check_duplicates_in_interval("ENUM",sql_field->field_name,
|
||||||
|
sql_field->interval,
|
||||||
|
sql_field->charset);
|
||||||
|
break;
|
||||||
|
case FIELD_TYPE_SET:
|
||||||
|
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
|
||||||
|
FIELDFLAG_BITFIELD;
|
||||||
|
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||||
|
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||||
|
sql_field->unireg_check=Field::BIT_FIELD;
|
||||||
|
check_duplicates_in_interval("SET",sql_field->field_name,
|
||||||
|
sql_field->interval,
|
||||||
|
sql_field->charset);
|
||||||
|
break;
|
||||||
|
case FIELD_TYPE_DATE: // Rest of string types
|
||||||
|
case FIELD_TYPE_NEWDATE:
|
||||||
|
case FIELD_TYPE_TIME:
|
||||||
|
case FIELD_TYPE_DATETIME:
|
||||||
|
case FIELD_TYPE_NULL:
|
||||||
|
sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
|
||||||
|
break;
|
||||||
|
case FIELD_TYPE_BIT:
|
||||||
|
if (!(table_flags & HA_CAN_BIT_FIELD))
|
||||||
|
{
|
||||||
|
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "BIT FIELD");
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
sql_field->pack_flag= FIELDFLAG_NUMBER;
|
||||||
|
break;
|
||||||
|
case FIELD_TYPE_NEWDECIMAL:
|
||||||
|
sql_field->pack_flag=(FIELDFLAG_NUMBER |
|
||||||
|
(sql_field->flags & UNSIGNED_FLAG ? 0 :
|
||||||
|
FIELDFLAG_DECIMAL) |
|
||||||
|
(sql_field->flags & ZEROFILL_FLAG ?
|
||||||
|
FIELDFLAG_ZEROFILL : 0) |
|
||||||
|
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
|
||||||
|
break;
|
||||||
|
case FIELD_TYPE_TIMESTAMP:
|
||||||
|
/* We should replace old TIMESTAMP fields with their newer analogs */
|
||||||
|
if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
|
||||||
|
{
|
||||||
|
if (!timestamps)
|
||||||
|
{
|
||||||
|
sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
|
||||||
|
timestamps_with_niladic++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sql_field->unireg_check= Field::NONE;
|
||||||
|
}
|
||||||
|
else if (sql_field->unireg_check != Field::NONE)
|
||||||
|
timestamps_with_niladic++;
|
||||||
|
|
||||||
|
timestamps++;
|
||||||
|
/* fall-through */
|
||||||
|
default:
|
||||||
|
sql_field->pack_flag=(FIELDFLAG_NUMBER |
|
||||||
|
(sql_field->flags & UNSIGNED_FLAG ? 0 :
|
||||||
|
FIELDFLAG_DECIMAL) |
|
||||||
|
(sql_field->flags & ZEROFILL_FLAG ?
|
||||||
|
FIELDFLAG_ZEROFILL : 0) |
|
||||||
|
f_settype((uint) sql_field->sql_type) |
|
||||||
|
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!(sql_field->flags & NOT_NULL_FLAG))
|
||||||
|
sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
|
||||||
|
if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
|
||||||
|
sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
|
||||||
|
}
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Preparation for table creation
|
Preparation for table creation
|
||||||
|
|
||||||
@ -690,142 +857,17 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
{
|
{
|
||||||
DBUG_ASSERT(sql_field->charset != 0);
|
DBUG_ASSERT(sql_field->charset != 0);
|
||||||
|
|
||||||
switch (sql_field->sql_type) {
|
if (prepare_create_field(sql_field, blob_columns,
|
||||||
case FIELD_TYPE_BLOB:
|
timestamps, timestamps_with_niladic,
|
||||||
case FIELD_TYPE_MEDIUM_BLOB:
|
file->table_flags()))
|
||||||
case FIELD_TYPE_TINY_BLOB:
|
|
||||||
case FIELD_TYPE_LONG_BLOB:
|
|
||||||
sql_field->pack_flag=FIELDFLAG_BLOB |
|
|
||||||
pack_length_to_packflag(sql_field->pack_length -
|
|
||||||
portable_sizeof_char_ptr);
|
|
||||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
|
||||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
|
||||||
sql_field->length=8; // Unireg field length
|
|
||||||
sql_field->unireg_check=Field::BLOB_FIELD;
|
|
||||||
blob_columns++;
|
|
||||||
create_info->varchar= 1;
|
|
||||||
break;
|
|
||||||
case FIELD_TYPE_GEOMETRY:
|
|
||||||
#ifdef HAVE_SPATIAL
|
|
||||||
if (!(file->table_flags() & HA_CAN_GEOMETRY))
|
|
||||||
{
|
|
||||||
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "GEOMETRY");
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
}
|
|
||||||
sql_field->pack_flag=FIELDFLAG_GEOM |
|
|
||||||
pack_length_to_packflag(sql_field->pack_length -
|
|
||||||
portable_sizeof_char_ptr);
|
|
||||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
|
||||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
|
||||||
sql_field->length=8; // Unireg field length
|
|
||||||
sql_field->unireg_check=Field::BLOB_FIELD;
|
|
||||||
blob_columns++;
|
|
||||||
create_info->varchar= 1;
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
my_error(ER_FEATURE_DISABLED, MYF(0),
|
|
||||||
sym_group_geom.name, sym_group_geom.needed_define);
|
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
#endif /*HAVE_SPATIAL*/
|
if (sql_field->sql_type == FIELD_TYPE_BLOB ||
|
||||||
case MYSQL_TYPE_VARCHAR:
|
sql_field->sql_type == FIELD_TYPE_MEDIUM_BLOB ||
|
||||||
#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
|
sql_field->sql_type == FIELD_TYPE_TINY_BLOB ||
|
||||||
if (file->table_flags() & HA_NO_VARCHAR)
|
sql_field->sql_type == FIELD_TYPE_LONG_BLOB ||
|
||||||
{
|
sql_field->sql_type == FIELD_TYPE_GEOMETRY ||
|
||||||
/* convert VARCHAR to CHAR because handler is not yet up to date */
|
sql_field->sql_type == MYSQL_TYPE_VARCHAR)
|
||||||
sql_field->sql_type= MYSQL_TYPE_VAR_STRING;
|
create_info->varchar= 1;
|
||||||
sql_field->pack_length= calc_pack_length(sql_field->sql_type,
|
|
||||||
(uint) sql_field->length);
|
|
||||||
if ((sql_field->length / sql_field->charset->mbmaxlen) >
|
|
||||||
MAX_FIELD_CHARLENGTH)
|
|
||||||
{
|
|
||||||
my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
|
|
||||||
MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
create_info->varchar= 1;
|
|
||||||
/* fall through */
|
|
||||||
case MYSQL_TYPE_STRING:
|
|
||||||
sql_field->pack_flag=0;
|
|
||||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
|
||||||
sql_field->pack_flag|= FIELDFLAG_BINARY;
|
|
||||||
break;
|
|
||||||
case FIELD_TYPE_ENUM:
|
|
||||||
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
|
|
||||||
FIELDFLAG_INTERVAL;
|
|
||||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
|
||||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
|
||||||
sql_field->unireg_check=Field::INTERVAL_FIELD;
|
|
||||||
check_duplicates_in_interval("ENUM",sql_field->field_name,
|
|
||||||
sql_field->interval,
|
|
||||||
sql_field->charset);
|
|
||||||
break;
|
|
||||||
case FIELD_TYPE_SET:
|
|
||||||
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
|
|
||||||
FIELDFLAG_BITFIELD;
|
|
||||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
|
||||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
|
||||||
sql_field->unireg_check=Field::BIT_FIELD;
|
|
||||||
check_duplicates_in_interval("SET",sql_field->field_name,
|
|
||||||
sql_field->interval,
|
|
||||||
sql_field->charset);
|
|
||||||
break;
|
|
||||||
case FIELD_TYPE_DATE: // Rest of string types
|
|
||||||
case FIELD_TYPE_NEWDATE:
|
|
||||||
case FIELD_TYPE_TIME:
|
|
||||||
case FIELD_TYPE_DATETIME:
|
|
||||||
case FIELD_TYPE_NULL:
|
|
||||||
sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
|
|
||||||
break;
|
|
||||||
case FIELD_TYPE_BIT:
|
|
||||||
if (!(file->table_flags() & HA_CAN_BIT_FIELD))
|
|
||||||
{
|
|
||||||
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "BIT FIELD");
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
}
|
|
||||||
sql_field->pack_flag= FIELDFLAG_NUMBER;
|
|
||||||
break;
|
|
||||||
case FIELD_TYPE_NEWDECIMAL:
|
|
||||||
sql_field->pack_flag=(FIELDFLAG_NUMBER |
|
|
||||||
(sql_field->flags & UNSIGNED_FLAG ? 0 :
|
|
||||||
FIELDFLAG_DECIMAL) |
|
|
||||||
(sql_field->flags & ZEROFILL_FLAG ?
|
|
||||||
FIELDFLAG_ZEROFILL : 0) |
|
|
||||||
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
|
|
||||||
break;
|
|
||||||
case FIELD_TYPE_TIMESTAMP:
|
|
||||||
/* We should replace old TIMESTAMP fields with their newer analogs */
|
|
||||||
if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
|
|
||||||
{
|
|
||||||
if (!timestamps)
|
|
||||||
{
|
|
||||||
sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
|
|
||||||
timestamps_with_niladic++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sql_field->unireg_check= Field::NONE;
|
|
||||||
}
|
|
||||||
else if (sql_field->unireg_check != Field::NONE)
|
|
||||||
timestamps_with_niladic++;
|
|
||||||
|
|
||||||
timestamps++;
|
|
||||||
/* fall-through */
|
|
||||||
default:
|
|
||||||
sql_field->pack_flag=(FIELDFLAG_NUMBER |
|
|
||||||
(sql_field->flags & UNSIGNED_FLAG ? 0 :
|
|
||||||
FIELDFLAG_DECIMAL) |
|
|
||||||
(sql_field->flags & ZEROFILL_FLAG ?
|
|
||||||
FIELDFLAG_ZEROFILL : 0) |
|
|
||||||
f_settype((uint) sql_field->sql_type) |
|
|
||||||
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!(sql_field->flags & NOT_NULL_FLAG))
|
|
||||||
sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
|
|
||||||
if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
|
|
||||||
sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
|
|
||||||
sql_field->offset= pos;
|
sql_field->offset= pos;
|
||||||
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
|
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
|
||||||
auto_increment++;
|
auto_increment++;
|
||||||
@ -1592,6 +1634,8 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
((Item_field *)item)->field :
|
((Item_field *)item)->field :
|
||||||
(Field*) 0))))
|
(Field*) 0))))
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
if (item->maybe_null)
|
||||||
|
cr_field->flags &= ~NOT_NULL_FLAG;
|
||||||
extra_fields->push_back(cr_field);
|
extra_fields->push_back(cr_field);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -1372,19 +1372,37 @@ create_function_tail:
|
|||||||
RETURNS_SYM
|
RETURNS_SYM
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_head *sp= lex->sphead;
|
lex->charset= NULL;
|
||||||
|
lex->length= lex->dec= NULL;
|
||||||
sp->m_returns_begin= lex->tok_start;
|
lex->interval_list.empty();
|
||||||
sp->m_returns_cs= lex->charset= NULL;
|
lex->type= 0;
|
||||||
}
|
}
|
||||||
type
|
type
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_head *sp= lex->sphead;
|
sp_head *sp= lex->sphead;
|
||||||
|
LEX_STRING cmt = { 0, 0 };
|
||||||
|
create_field *new_field;
|
||||||
|
uint unused1= 0;
|
||||||
|
int unused2= 0;
|
||||||
|
|
||||||
|
if (!(new_field= new_create_field(YYTHD, "", (enum enum_field_types)$8,
|
||||||
|
lex->length, lex->dec, lex->type,
|
||||||
|
(Item *)0, (Item *) 0, &cmt, 0, &lex->interval_list,
|
||||||
|
(lex->charset ? lex->charset : default_charset_info),
|
||||||
|
lex->uint_geom_type)))
|
||||||
|
YYABORT;
|
||||||
|
|
||||||
|
if (prepare_create_field(new_field, unused1, unused2, unused2, 0))
|
||||||
|
YYABORT;
|
||||||
|
|
||||||
|
sp->m_returns= new_field->sql_type;
|
||||||
|
sp->m_returns_cs= new_field->charset;
|
||||||
|
sp->m_returns_len= new_field->length;
|
||||||
|
sp->m_returns_pack= new_field->pack_flag;
|
||||||
|
sp->m_returns_typelib=
|
||||||
|
sp->create_typelib(&new_field->interval_list);
|
||||||
|
|
||||||
sp->m_returns_end= lex->tok_start;
|
|
||||||
sp->m_returns= (enum enum_field_types)$8;
|
|
||||||
sp->m_returns_cs= lex->charset;
|
|
||||||
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
||||||
}
|
}
|
||||||
sp_c_chistics
|
sp_c_chistics
|
||||||
|
@ -695,6 +695,7 @@ static bool make_empty_rec(File file,enum db_type table_type,
|
|||||||
field->interval,
|
field->interval,
|
||||||
field->field_name,
|
field->field_name,
|
||||||
&table);
|
&table);
|
||||||
|
DBUG_ASSERT(regfield);
|
||||||
|
|
||||||
if (!(field->flags & NOT_NULL_FLAG))
|
if (!(field->flags & NOT_NULL_FLAG))
|
||||||
null_count++;
|
null_count++;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user