MDEV-17399 JSON_TABLE.
atch to get rid of duplicating code of the Create_tmp_table.
This commit is contained in:
parent
a5b454f98a
commit
f82947e48d
80
sql/create_tmp_table.h
Normal file
80
sql/create_tmp_table.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#ifndef CREATE_TMP_TABLE_INCLUDED
|
||||||
|
#define CREATE_TMP_TABLE_INCLUDED
|
||||||
|
|
||||||
|
/* Copyright (c) 2021, MariaDB Corporation.
|
||||||
|
|
||||||
|
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
|
||||||
|
the Free Software Foundation; version 2 of the License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Class for creating internal tempory tables in sql_select.cc
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Create_tmp_table: public Data_type_statistics
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
// The following members are initialized only in start()
|
||||||
|
Field **m_from_field, **m_default_field;
|
||||||
|
KEY_PART_INFO *m_key_part_info;
|
||||||
|
uchar *m_group_buff, *m_bitmaps;
|
||||||
|
// The following members are initialized in ctor
|
||||||
|
uint m_alloced_field_count;
|
||||||
|
bool m_using_unique_constraint;
|
||||||
|
uint m_temp_pool_slot;
|
||||||
|
ORDER *m_group;
|
||||||
|
bool m_distinct;
|
||||||
|
bool m_save_sum_fields;
|
||||||
|
bool m_with_cycle;
|
||||||
|
ulonglong m_select_options;
|
||||||
|
ha_rows m_rows_limit;
|
||||||
|
uint m_group_null_items;
|
||||||
|
|
||||||
|
// counter for distinct/other fields
|
||||||
|
uint m_field_count[2];
|
||||||
|
// counter for distinct/other fields which can be NULL
|
||||||
|
uint m_null_count[2];
|
||||||
|
// counter for distinct/other blob fields
|
||||||
|
uint m_blobs_count[2];
|
||||||
|
// counter for "tails" of bit fields which do not fit in a byte
|
||||||
|
uint m_uneven_bit[2];
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum counter {distinct, other};
|
||||||
|
/*
|
||||||
|
shows which field we are processing: distinct/other (set in processing
|
||||||
|
cycles)
|
||||||
|
*/
|
||||||
|
counter current_counter;
|
||||||
|
Create_tmp_table(ORDER *group, bool distinct, bool save_sum_fields,
|
||||||
|
ulonglong select_options, ha_rows rows_limit);
|
||||||
|
virtual ~Create_tmp_table() {}
|
||||||
|
virtual bool choose_engine(THD *thd, TABLE *table, TMP_TABLE_PARAM *param);
|
||||||
|
void add_field(TABLE *table, Field *field, uint fieldnr,
|
||||||
|
bool force_not_null_cols);
|
||||||
|
TABLE *start(THD *thd,
|
||||||
|
TMP_TABLE_PARAM *param,
|
||||||
|
const LEX_CSTRING *table_alias);
|
||||||
|
bool add_fields(THD *thd, TABLE *table,
|
||||||
|
TMP_TABLE_PARAM *param, List<Item> &fields);
|
||||||
|
|
||||||
|
bool add_schema_fields(THD *thd, TABLE *table,
|
||||||
|
TMP_TABLE_PARAM *param,
|
||||||
|
const ST_SCHEMA_TABLE &schema_table);
|
||||||
|
|
||||||
|
bool finalize(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
|
||||||
|
bool do_not_open, bool keep_row_order);
|
||||||
|
void cleanup_on_failure(THD *thd, TABLE *table);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CREATE_TMP_TABLE_INCLUDED */
|
@ -23,6 +23,7 @@
|
|||||||
#include "json_table.h"
|
#include "json_table.h"
|
||||||
#include "sql_show.h"
|
#include "sql_show.h"
|
||||||
#include "sql_select.h"
|
#include "sql_select.h"
|
||||||
|
#include "create_tmp_table.h"
|
||||||
|
|
||||||
#define HA_ERR_JSON_TABLE (HA_ERR_LAST+1)
|
#define HA_ERR_JSON_TABLE (HA_ERR_LAST+1)
|
||||||
|
|
||||||
@ -223,28 +224,21 @@ public:
|
|||||||
represents the table function in the query.
|
represents the table function in the query.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Create_json_table: public Data_type_statistics
|
class Create_json_table final: public Create_tmp_table
|
||||||
{
|
{
|
||||||
// The following members are initialized only in start()
|
|
||||||
Field **m_default_field;
|
|
||||||
uchar *m_bitmaps;
|
|
||||||
// The following members are initialized in ctor
|
|
||||||
uint m_temp_pool_slot;
|
|
||||||
uint m_null_count;
|
|
||||||
public:
|
public:
|
||||||
Create_json_table(const TMP_TABLE_PARAM *param,
|
Create_json_table() :
|
||||||
bool save_sum_fields)
|
Create_tmp_table((ORDER*) 0, 0, 0, 0, 0)
|
||||||
:m_temp_pool_slot(MY_BIT_NONE),
|
{}
|
||||||
m_null_count(0)
|
virtual ~Create_json_table() {};
|
||||||
{ }
|
|
||||||
|
|
||||||
void add_field(TABLE *table, Field *field, uint fieldnr);
|
|
||||||
|
|
||||||
TABLE *start(THD *thd,
|
TABLE *start(THD *thd,
|
||||||
TMP_TABLE_PARAM *param,
|
TMP_TABLE_PARAM *param,
|
||||||
Table_function_json_table *jt,
|
Table_function_json_table *jt,
|
||||||
const LEX_CSTRING *table_alias);
|
const LEX_CSTRING *table_alias);
|
||||||
|
bool choose_engine(THD *thd, TABLE *table, TMP_TABLE_PARAM *param) override
|
||||||
|
{
|
||||||
|
return 0; // Engine already choosen
|
||||||
|
}
|
||||||
bool add_json_table_fields(THD *thd, TABLE *table,
|
bool add_json_table_fields(THD *thd, TABLE *table,
|
||||||
Table_function_json_table *jt);
|
Table_function_json_table *jt);
|
||||||
bool finalize(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
|
bool finalize(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
|
||||||
@ -618,27 +612,6 @@ int ha_json_table::info(uint)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Create_json_table::add_field(TABLE *table, Field *field, uint fieldnr)
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(!field->field_name.str ||
|
|
||||||
strlen(field->field_name.str) == field->field_name.length);
|
|
||||||
|
|
||||||
if (!(field->flags & NOT_NULL_FLAG))
|
|
||||||
m_null_count++;
|
|
||||||
|
|
||||||
table->s->reclength+= field->pack_length();
|
|
||||||
|
|
||||||
// Assign it here, before update_data_type_statistics() changes m_blob_count
|
|
||||||
if (field->flags & BLOB_FLAG)
|
|
||||||
table->s->blob_field[m_blob_count]= fieldnr;
|
|
||||||
|
|
||||||
table->field[fieldnr]= field;
|
|
||||||
field->field_index= fieldnr;
|
|
||||||
|
|
||||||
field->update_data_type_statistics(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create a json table according to a field list.
|
Create a json table according to a field list.
|
||||||
|
|
||||||
@ -653,98 +626,19 @@ TABLE *Create_json_table::start(THD *thd,
|
|||||||
Table_function_json_table *jt,
|
Table_function_json_table *jt,
|
||||||
const LEX_CSTRING *table_alias)
|
const LEX_CSTRING *table_alias)
|
||||||
{
|
{
|
||||||
MEM_ROOT *mem_root_save, own_root;
|
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
TABLE_SHARE *share;
|
TABLE_SHARE *share;
|
||||||
uint copy_func_count= param->func_count;
|
|
||||||
char *tmpname,path[FN_REFLEN];
|
|
||||||
Field **reg_field;
|
|
||||||
uint *blob_field;
|
|
||||||
DBUG_ENTER("Create_json_table::start");
|
DBUG_ENTER("Create_json_table::start");
|
||||||
DBUG_PRINT("enter",
|
|
||||||
("table_alias: '%s' ", table_alias->str));
|
|
||||||
|
|
||||||
if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES))
|
param->tmp_name= "json";
|
||||||
m_temp_pool_slot = bitmap_lock_set_next(&temp_pool);
|
if (!(table= Create_tmp_table::start(thd, param, table_alias)))
|
||||||
|
DBUG_RETURN(0);
|
||||||
if (m_temp_pool_slot != MY_BIT_NONE) // we got a slot
|
share= table->s;
|
||||||
sprintf(path, "%s-%lx-%i", tmp_file_prefix,
|
|
||||||
current_pid, m_temp_pool_slot);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* if we run out of slots or we are not using tempool */
|
|
||||||
sprintf(path, "%s-%lx-%lx-%x", tmp_file_prefix,current_pid,
|
|
||||||
(ulong) thd->thread_id, thd->tmp_table++);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
No need to change table name to lower case.
|
|
||||||
*/
|
|
||||||
fn_format(path, path, mysql_tmpdir, "",
|
|
||||||
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
|
|
||||||
|
|
||||||
const uint field_count= param->field_count;
|
|
||||||
DBUG_ASSERT(field_count);
|
|
||||||
|
|
||||||
init_sql_alloc(key_memory_TABLE, &own_root,
|
|
||||||
TABLE_ALLOC_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC));
|
|
||||||
|
|
||||||
if (!multi_alloc_root(&own_root,
|
|
||||||
&table, sizeof(*table),
|
|
||||||
&share, sizeof(*share),
|
|
||||||
®_field, sizeof(Field*) * (field_count+1),
|
|
||||||
&m_default_field, sizeof(Field*) * (field_count),
|
|
||||||
&blob_field, sizeof(uint)*(field_count+1),
|
|
||||||
¶m->items_to_copy,
|
|
||||||
sizeof(param->items_to_copy[0])*(copy_func_count+1),
|
|
||||||
¶m->keyinfo, sizeof(*param->keyinfo),
|
|
||||||
¶m->start_recinfo,
|
|
||||||
sizeof(*param->recinfo)*(field_count*2+4),
|
|
||||||
&tmpname, (uint) strlen(path)+1,
|
|
||||||
&m_bitmaps, bitmap_buffer_size(field_count)*6,
|
|
||||||
NullS))
|
|
||||||
{
|
|
||||||
DBUG_RETURN(NULL); /* purecov: inspected */
|
|
||||||
}
|
|
||||||
strmov(tmpname, path);
|
|
||||||
/* make table according to fields */
|
|
||||||
|
|
||||||
bzero((char*) table,sizeof(*table));
|
|
||||||
bzero((char*) reg_field, sizeof(Field*) * (field_count+1));
|
|
||||||
bzero((char*) m_default_field, sizeof(Field*) * (field_count));
|
|
||||||
|
|
||||||
table->mem_root= own_root;
|
|
||||||
mem_root_save= thd->mem_root;
|
|
||||||
thd->mem_root= &table->mem_root;
|
|
||||||
|
|
||||||
table->field=reg_field;
|
|
||||||
table->alias.set(table_alias->str, table_alias->length, table_alias_charset);
|
|
||||||
|
|
||||||
table->reginfo.lock_type=TL_WRITE; /* Will be updated */
|
|
||||||
table->map=1;
|
|
||||||
table->temp_pool_slot= m_temp_pool_slot;
|
|
||||||
table->copy_blobs= 1;
|
|
||||||
table->in_use= thd;
|
|
||||||
table->no_rows_with_nulls= param->force_not_null_cols;
|
|
||||||
|
|
||||||
table->s= share;
|
|
||||||
init_tmp_table_share(thd, share, "", 0, "(temporary)", tmpname);
|
|
||||||
share->blob_field= blob_field;
|
|
||||||
share->table_charset= param->table_charset;
|
|
||||||
share->primary_key= MAX_KEY; // Indicate no primary key
|
|
||||||
share->not_usable_by_query_cache= FALSE;
|
share->not_usable_by_query_cache= FALSE;
|
||||||
if (param->schema_table)
|
|
||||||
share->db= INFORMATION_SCHEMA_NAME;
|
|
||||||
|
|
||||||
param->using_outer_summary_function= 0;
|
|
||||||
|
|
||||||
share->db_plugin= NULL;
|
share->db_plugin= NULL;
|
||||||
if (!(table->file= new (&table->mem_root) ha_json_table(share, jt)))
|
if (!(table->file= new (&table->mem_root) ha_json_table(share, jt)))
|
||||||
DBUG_RETURN(NULL);
|
DBUG_RETURN(NULL);
|
||||||
|
|
||||||
table->file->init();
|
table->file->init();
|
||||||
|
|
||||||
thd->mem_root= mem_root_save;
|
|
||||||
DBUG_RETURN(table);
|
DBUG_RETURN(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,143 +650,18 @@ bool Create_json_table::finalize(THD *thd, TABLE *table,
|
|||||||
DBUG_ENTER("Create_json_table::finalize");
|
DBUG_ENTER("Create_json_table::finalize");
|
||||||
DBUG_ASSERT(table);
|
DBUG_ASSERT(table);
|
||||||
|
|
||||||
uint null_pack_length;
|
if (Create_tmp_table::finalize(thd, table, param, 1, 0))
|
||||||
bool use_packed_rows= false;
|
DBUG_RETURN(true);
|
||||||
uchar *pos;
|
|
||||||
uchar *null_flags;
|
|
||||||
TMP_ENGINE_COLUMNDEF *recinfo;
|
|
||||||
TABLE_SHARE *share= table->s;
|
|
||||||
|
|
||||||
MEM_ROOT *mem_root_save= thd->mem_root;
|
|
||||||
thd->mem_root= &table->mem_root;
|
|
||||||
|
|
||||||
DBUG_ASSERT(param->field_count >= share->fields);
|
|
||||||
DBUG_ASSERT(param->field_count >= share->blob_fields);
|
|
||||||
|
|
||||||
if (table->file->set_ha_share_ref(&share->ha_share))
|
|
||||||
{
|
|
||||||
delete table->file;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (share->blob_fields == 0)
|
|
||||||
m_null_count++;
|
|
||||||
|
|
||||||
null_pack_length= (m_null_count + m_uneven_bit_length + 7) / 8;
|
|
||||||
share->reclength+= null_pack_length;
|
|
||||||
if (!share->reclength)
|
|
||||||
share->reclength= 1; // Dummy select
|
|
||||||
|
|
||||||
{
|
|
||||||
uint alloc_length= ALIGN_SIZE(share->reclength + MI_UNIQUE_HASH_LENGTH+1);
|
|
||||||
share->rec_buff_length= alloc_length;
|
|
||||||
if (!(table->record[0]= (uchar*)
|
|
||||||
alloc_root(&table->mem_root, alloc_length*3)))
|
|
||||||
goto err;
|
|
||||||
table->record[1]= table->record[0]+alloc_length;
|
|
||||||
share->default_values= table->record[1]+alloc_length;
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_tmp_table_column_bitmaps(table, m_bitmaps, table->s->fields);
|
|
||||||
|
|
||||||
recinfo=param->start_recinfo;
|
|
||||||
null_flags=(uchar*) table->record[0];
|
|
||||||
pos=table->record[0]+ null_pack_length;
|
|
||||||
if (null_pack_length)
|
|
||||||
{
|
|
||||||
bzero((uchar*) recinfo,sizeof(*recinfo));
|
|
||||||
recinfo->type=FIELD_NORMAL;
|
|
||||||
recinfo->length=null_pack_length;
|
|
||||||
recinfo++;
|
|
||||||
bfill(null_flags,null_pack_length,255); // Set null fields
|
|
||||||
|
|
||||||
table->null_flags= (uchar*) table->record[0];
|
|
||||||
share->null_fields= m_null_count;
|
|
||||||
share->null_bytes= share->null_bytes_for_compare= null_pack_length;
|
|
||||||
}
|
|
||||||
m_null_count= (share->blob_fields == 0) ? 1 : 0;
|
|
||||||
for (uint i= 0; i < share->fields; i++, recinfo++)
|
|
||||||
{
|
|
||||||
Field *field= table->field[i];
|
|
||||||
uint length;
|
|
||||||
bzero((uchar*) recinfo,sizeof(*recinfo));
|
|
||||||
|
|
||||||
if (!(field->flags & NOT_NULL_FLAG))
|
|
||||||
{
|
|
||||||
recinfo->null_bit= (uint8)1 << (m_null_count & 7);
|
|
||||||
recinfo->null_pos= m_null_count/8;
|
|
||||||
field->move_field(pos, null_flags + m_null_count/8,
|
|
||||||
(uint8)1 << (m_null_count & 7));
|
|
||||||
m_null_count++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
field->move_field(pos,(uchar*) 0,0);
|
|
||||||
if (field->type() == MYSQL_TYPE_BIT)
|
|
||||||
{
|
|
||||||
/* We have to reserve place for extra bits among null bits */
|
|
||||||
((Field_bit*) field)->set_bit_ptr(null_flags + m_null_count / 8,
|
|
||||||
m_null_count & 7);
|
|
||||||
m_null_count+= (field->field_length & 7);
|
|
||||||
}
|
|
||||||
field->reset();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Test if there is a default field value. The test for ->ptr is to skip
|
|
||||||
'offset' fields generated by initialize_tables
|
|
||||||
*/
|
|
||||||
if (m_default_field[i] && m_default_field[i]->ptr)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
default_field[i] is set only in the cases when 'field' can
|
|
||||||
inherit the default value that is defined for the field referred
|
|
||||||
by the Item_field object from which 'field' has been created.
|
|
||||||
*/
|
|
||||||
const Field *orig_field= m_default_field[i];
|
|
||||||
/* Get the value from default_values */
|
|
||||||
if (orig_field->is_null_in_record(orig_field->table->s->default_values))
|
|
||||||
field->set_null();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
field->set_notnull();
|
|
||||||
memcpy(field->ptr,
|
|
||||||
orig_field->ptr_in_record(orig_field->table->s->default_values),
|
|
||||||
field->pack_length_in_rec());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
length=field->pack_length();
|
|
||||||
pos+= length;
|
|
||||||
|
|
||||||
/* Make entry for create table */
|
|
||||||
recinfo->length=length;
|
|
||||||
recinfo->type= field->tmp_engine_column_type(use_packed_rows);
|
|
||||||
|
|
||||||
// fix table name in field entry
|
|
||||||
field->set_table_name(&table->alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
param->recinfo= recinfo; // Pointer to after last field
|
|
||||||
store_record(table,s->default_values); // Make empty default record
|
|
||||||
|
|
||||||
share->max_rows= ~(ha_rows) 0;
|
|
||||||
param->end_write_records= HA_POS_ERROR;
|
|
||||||
|
|
||||||
share->db_record_offset= 1;
|
|
||||||
|
|
||||||
if (unlikely(table->file->ha_open(table, table->s->path.str, O_RDWR,
|
|
||||||
HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
table->db_stat= HA_OPEN_KEYFILE;
|
table->db_stat= HA_OPEN_KEYFILE;
|
||||||
|
if (unlikely(table->file->ha_open(table, table->s->path.str, O_RDWR,
|
||||||
|
HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
|
||||||
table->set_created();
|
table->set_created();
|
||||||
|
table->s->max_rows= ~(ha_rows) 0;
|
||||||
thd->mem_root= mem_root_save;
|
param->end_write_records= HA_POS_ERROR;
|
||||||
|
DBUG_RETURN(0);
|
||||||
DBUG_RETURN(false);
|
|
||||||
|
|
||||||
err:
|
|
||||||
thd->mem_root= mem_root_save;
|
|
||||||
DBUG_RETURN(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -910,10 +679,10 @@ bool Create_json_table::add_json_table_fields(THD *thd, TABLE *table,
|
|||||||
uint fieldnr= 0;
|
uint fieldnr= 0;
|
||||||
MEM_ROOT *mem_root_save= thd->mem_root;
|
MEM_ROOT *mem_root_save= thd->mem_root;
|
||||||
List_iterator_fast<Json_table_column> jc_i(jt->m_columns);
|
List_iterator_fast<Json_table_column> jc_i(jt->m_columns);
|
||||||
|
|
||||||
DBUG_ENTER("add_json_table_fields");
|
DBUG_ENTER("add_json_table_fields");
|
||||||
|
|
||||||
thd->mem_root= &table->mem_root;
|
thd->mem_root= &table->mem_root;
|
||||||
|
current_counter= other;
|
||||||
|
|
||||||
while ((jc= jc_i++))
|
while ((jc= jc_i++))
|
||||||
{
|
{
|
||||||
@ -963,7 +732,7 @@ bool Create_json_table::add_json_table_fields(THD *thd, TABLE *table,
|
|||||||
if (!f)
|
if (!f)
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
f->init(table);
|
f->init(table);
|
||||||
add_field(table, f, fieldnr++);
|
add_field(table, f, fieldnr++, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
share->fields= fieldnr;
|
share->fields= fieldnr;
|
||||||
@ -1009,7 +778,7 @@ TABLE *create_table_for_function(THD *thd, TABLE_LIST *sql_table)
|
|||||||
tp.table_charset= system_charset_info;
|
tp.table_charset= system_charset_info;
|
||||||
tp.field_count= field_count;
|
tp.field_count= field_count;
|
||||||
{
|
{
|
||||||
Create_json_table maker(&tp, false);
|
Create_json_table maker;
|
||||||
|
|
||||||
if (!(table= maker.start(thd, &tp,
|
if (!(table= maker.start(thd, &tp,
|
||||||
sql_table->table_function, &sql_table->alias)) ||
|
sql_table->table_function, &sql_table->alias)) ||
|
||||||
|
@ -4612,7 +4612,7 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd)
|
|||||||
table->record[1]= table->record[0]+alloc_length;
|
table->record[1]= table->record[0]+alloc_length;
|
||||||
share->default_values= table->record[1]+alloc_length;
|
share->default_values= table->record[1]+alloc_length;
|
||||||
}
|
}
|
||||||
setup_tmp_table_column_bitmaps(table, bitmaps);
|
setup_tmp_table_column_bitmaps(table, bitmaps, table->s->fields);
|
||||||
|
|
||||||
recinfo= start_recinfo;
|
recinfo= start_recinfo;
|
||||||
null_flags=(uchar*) table->record[0];
|
null_flags=(uchar*) table->record[0];
|
||||||
|
@ -4247,6 +4247,7 @@ void TMP_TABLE_PARAM::init()
|
|||||||
materialized_subquery= 0;
|
materialized_subquery= 0;
|
||||||
force_not_null_cols= 0;
|
force_not_null_cols= 0;
|
||||||
skip_create_table= 0;
|
skip_create_table= 0;
|
||||||
|
tmp_name= "temptable"; // Name of temp table on disk
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6084,6 +6084,7 @@ public:
|
|||||||
List<Item> copy_funcs;
|
List<Item> copy_funcs;
|
||||||
Copy_field *copy_field, *copy_field_end;
|
Copy_field *copy_field, *copy_field_end;
|
||||||
uchar *group_buff;
|
uchar *group_buff;
|
||||||
|
const char *tmp_name;
|
||||||
Item **items_to_copy; /* Fields in tmp table */
|
Item **items_to_copy; /* Fields in tmp table */
|
||||||
TMP_ENGINE_COLUMNDEF *recinfo, *start_recinfo;
|
TMP_ENGINE_COLUMNDEF *recinfo, *start_recinfo;
|
||||||
KEY *keyinfo;
|
KEY *keyinfo;
|
||||||
@ -6157,7 +6158,9 @@ public:
|
|||||||
schema_table(0), materialized_subquery(0), force_not_null_cols(0),
|
schema_table(0), materialized_subquery(0), force_not_null_cols(0),
|
||||||
precomputed_group_by(0),
|
precomputed_group_by(0),
|
||||||
force_copy_fields(0), bit_fields_as_long(0), skip_create_table(0)
|
force_copy_fields(0), bit_fields_as_long(0), skip_create_table(0)
|
||||||
{}
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
~TMP_TABLE_PARAM()
|
~TMP_TABLE_PARAM()
|
||||||
{
|
{
|
||||||
cleanup();
|
cleanup();
|
||||||
@ -7723,9 +7726,8 @@ public:
|
|||||||
|
|
||||||
extern THD_list server_threads;
|
extern THD_list server_threads;
|
||||||
|
|
||||||
void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps);
|
void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps,
|
||||||
void
|
uint field_count);
|
||||||
setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps, uint field_count);
|
|
||||||
|
|
||||||
#endif /* MYSQL_SERVER */
|
#endif /* MYSQL_SERVER */
|
||||||
#endif /* SQL_CLASS_INCLUDED */
|
#endif /* SQL_CLASS_INCLUDED */
|
||||||
|
@ -67,6 +67,7 @@
|
|||||||
#include "select_handler.h"
|
#include "select_handler.h"
|
||||||
#include "my_json_writer.h"
|
#include "my_json_writer.h"
|
||||||
#include "opt_trace.h"
|
#include "opt_trace.h"
|
||||||
|
#include "create_tmp_table.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A key part number that means we're using a fulltext scan.
|
A key part number that means we're using a fulltext scan.
|
||||||
@ -18263,50 +18264,10 @@ setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps, uint field_count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
Create_tmp_table::Create_tmp_table(ORDER *group, bool distinct,
|
||||||
setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps)
|
bool save_sum_fields,
|
||||||
{
|
ulonglong select_options,
|
||||||
setup_tmp_table_column_bitmaps(table, bitmaps, table->s->fields);
|
ha_rows rows_limit)
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Create_tmp_table: public Data_type_statistics
|
|
||||||
{
|
|
||||||
// The following members are initialized only in start()
|
|
||||||
Field **m_from_field, **m_default_field;
|
|
||||||
KEY_PART_INFO *m_key_part_info;
|
|
||||||
uchar *m_group_buff, *m_bitmaps;
|
|
||||||
// The following members are initialized in ctor
|
|
||||||
uint m_alloced_field_count;
|
|
||||||
bool m_using_unique_constraint;
|
|
||||||
uint m_temp_pool_slot;
|
|
||||||
ORDER *m_group;
|
|
||||||
bool m_distinct;
|
|
||||||
bool m_save_sum_fields;
|
|
||||||
bool m_with_cycle;
|
|
||||||
ulonglong m_select_options;
|
|
||||||
ha_rows m_rows_limit;
|
|
||||||
uint m_group_null_items;
|
|
||||||
|
|
||||||
// counter for distinct/other fields
|
|
||||||
uint m_field_count[2];
|
|
||||||
// counter for distinct/other fields which can be NULL
|
|
||||||
uint m_null_count[2];
|
|
||||||
// counter for distinct/other blob fields
|
|
||||||
uint m_blobs_count[2];
|
|
||||||
// counter for "tails" of bit fields which do not fit in a byte
|
|
||||||
uint m_uneven_bit[2];
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum counter {distinct, other};
|
|
||||||
/*
|
|
||||||
shows which field we are processing: distinct/other (set in processing
|
|
||||||
cycles)
|
|
||||||
*/
|
|
||||||
counter current_counter;
|
|
||||||
Create_tmp_table(const TMP_TABLE_PARAM *param,
|
|
||||||
ORDER *group, bool distinct, bool save_sum_fields,
|
|
||||||
ulonglong select_options, ha_rows rows_limit)
|
|
||||||
:m_alloced_field_count(0),
|
:m_alloced_field_count(0),
|
||||||
m_using_unique_constraint(false),
|
m_using_unique_constraint(false),
|
||||||
m_temp_pool_slot(MY_BIT_NONE),
|
m_temp_pool_slot(MY_BIT_NONE),
|
||||||
@ -18318,39 +18279,23 @@ public:
|
|||||||
m_rows_limit(rows_limit),
|
m_rows_limit(rows_limit),
|
||||||
m_group_null_items(0),
|
m_group_null_items(0),
|
||||||
current_counter(other)
|
current_counter(other)
|
||||||
{
|
|
||||||
m_field_count[Create_tmp_table::distinct]= 0;
|
|
||||||
m_field_count[Create_tmp_table::other]= 0;
|
|
||||||
m_null_count[Create_tmp_table::distinct]= 0;
|
|
||||||
m_null_count[Create_tmp_table::other]= 0;
|
|
||||||
m_blobs_count[Create_tmp_table::distinct]= 0;
|
|
||||||
m_blobs_count[Create_tmp_table::other]= 0;
|
|
||||||
m_uneven_bit[Create_tmp_table::distinct]= 0;
|
|
||||||
m_uneven_bit[Create_tmp_table::other]= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_field(TABLE *table, Field *field, uint fieldnr, bool force_not_null_cols);
|
|
||||||
|
|
||||||
TABLE *start(THD *thd,
|
|
||||||
TMP_TABLE_PARAM *param,
|
|
||||||
const LEX_CSTRING *table_alias);
|
|
||||||
|
|
||||||
bool add_fields(THD *thd, TABLE *table,
|
|
||||||
TMP_TABLE_PARAM *param, List<Item> &fields);
|
|
||||||
|
|
||||||
bool add_schema_fields(THD *thd, TABLE *table,
|
|
||||||
TMP_TABLE_PARAM *param,
|
|
||||||
const ST_SCHEMA_TABLE &schema_table);
|
|
||||||
|
|
||||||
bool finalize(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
|
|
||||||
bool do_not_open, bool keep_row_order);
|
|
||||||
void cleanup_on_failure(THD *thd, TABLE *table);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void Create_tmp_table::add_field(TABLE *table, Field *field, uint fieldnr, bool force_not_null_cols)
|
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(!field->field_name.str || strlen(field->field_name.str) == field->field_name.length);
|
m_field_count[Create_tmp_table::distinct]= 0;
|
||||||
|
m_field_count[Create_tmp_table::other]= 0;
|
||||||
|
m_null_count[Create_tmp_table::distinct]= 0;
|
||||||
|
m_null_count[Create_tmp_table::other]= 0;
|
||||||
|
m_blobs_count[Create_tmp_table::distinct]= 0;
|
||||||
|
m_blobs_count[Create_tmp_table::other]= 0;
|
||||||
|
m_uneven_bit[Create_tmp_table::distinct]= 0;
|
||||||
|
m_uneven_bit[Create_tmp_table::other]= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Create_tmp_table::add_field(TABLE *table, Field *field, uint fieldnr,
|
||||||
|
bool force_not_null_cols)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(!field->field_name.str ||
|
||||||
|
strlen(field->field_name.str) == field->field_name.length);
|
||||||
|
|
||||||
if (force_not_null_cols)
|
if (force_not_null_cols)
|
||||||
{
|
{
|
||||||
@ -18436,13 +18381,13 @@ TABLE *Create_tmp_table::start(THD *thd,
|
|||||||
m_temp_pool_slot = bitmap_lock_set_next(&temp_pool);
|
m_temp_pool_slot = bitmap_lock_set_next(&temp_pool);
|
||||||
|
|
||||||
if (m_temp_pool_slot != MY_BIT_NONE) // we got a slot
|
if (m_temp_pool_slot != MY_BIT_NONE) // we got a slot
|
||||||
sprintf(path, "%s-temptable-%lx-%i", tmp_file_prefix,
|
sprintf(path, "%s-%s-%lx-%i", tmp_file_prefix, param->tmp_name,
|
||||||
current_pid, m_temp_pool_slot);
|
current_pid, m_temp_pool_slot);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* if we run out of slots or we are not using tempool */
|
/* if we run out of slots or we are not using tempool */
|
||||||
sprintf(path, "%s-temptable-%lx-%llx-%x", tmp_file_prefix,current_pid,
|
sprintf(path, "%s-%s-%lx-%llx-%x", tmp_file_prefix, param->tmp_name,
|
||||||
thd->thread_id, thd->tmp_table++);
|
current_pid, thd->thread_id, thd->tmp_table++);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -18785,6 +18730,40 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Create_tmp_table::choose_engine(THD *thd, TABLE *table,
|
||||||
|
TMP_TABLE_PARAM *param)
|
||||||
|
{
|
||||||
|
TABLE_SHARE *share= table->s;
|
||||||
|
DBUG_ENTER("Create_tmp_table::choose_engine");
|
||||||
|
/*
|
||||||
|
If result table is small; use a heap, otherwise TMP_TABLE_HTON (Aria)
|
||||||
|
In the future we should try making storage engine selection more dynamic
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (share->blob_fields || m_using_unique_constraint ||
|
||||||
|
(thd->variables.big_tables &&
|
||||||
|
!(m_select_options & SELECT_SMALL_RESULT)) ||
|
||||||
|
(m_select_options & TMP_TABLE_FORCE_MYISAM) ||
|
||||||
|
thd->variables.tmp_memory_table_size == 0)
|
||||||
|
{
|
||||||
|
share->db_plugin= ha_lock_engine(0, TMP_ENGINE_HTON);
|
||||||
|
table->file= get_new_handler(share, &table->mem_root,
|
||||||
|
share->db_type());
|
||||||
|
if (m_group &&
|
||||||
|
(param->group_parts > table->file->max_key_parts() ||
|
||||||
|
param->group_length > table->file->max_key_length()))
|
||||||
|
m_using_unique_constraint= true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
share->db_plugin= ha_lock_engine(0, heap_hton);
|
||||||
|
table->file= get_new_handler(share, &table->mem_root,
|
||||||
|
share->db_type());
|
||||||
|
}
|
||||||
|
DBUG_RETURN(!table->file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Create_tmp_table::finalize(THD *thd,
|
bool Create_tmp_table::finalize(THD *thd,
|
||||||
TABLE *table,
|
TABLE *table,
|
||||||
TMP_TABLE_PARAM *param,
|
TMP_TABLE_PARAM *param,
|
||||||
@ -18811,28 +18790,7 @@ bool Create_tmp_table::finalize(THD *thd,
|
|||||||
DBUG_ASSERT(m_alloced_field_count >= share->fields);
|
DBUG_ASSERT(m_alloced_field_count >= share->fields);
|
||||||
DBUG_ASSERT(m_alloced_field_count >= share->blob_fields);
|
DBUG_ASSERT(m_alloced_field_count >= share->blob_fields);
|
||||||
|
|
||||||
/* If result table is small; use a heap */
|
if (choose_engine(thd, table, param))
|
||||||
/* future: storage engine selection can be made dynamic? */
|
|
||||||
if (share->blob_fields || m_using_unique_constraint
|
|
||||||
|| (thd->variables.big_tables && !(m_select_options & SELECT_SMALL_RESULT))
|
|
||||||
|| (m_select_options & TMP_TABLE_FORCE_MYISAM)
|
|
||||||
|| thd->variables.tmp_memory_table_size == 0)
|
|
||||||
{
|
|
||||||
share->db_plugin= ha_lock_engine(0, TMP_ENGINE_HTON);
|
|
||||||
table->file= get_new_handler(share, &table->mem_root,
|
|
||||||
share->db_type());
|
|
||||||
if (m_group &&
|
|
||||||
(param->group_parts > table->file->max_key_parts() ||
|
|
||||||
param->group_length > table->file->max_key_length()))
|
|
||||||
m_using_unique_constraint= true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
share->db_plugin= ha_lock_engine(0, heap_hton);
|
|
||||||
table->file= get_new_handler(share, &table->mem_root,
|
|
||||||
share->db_type());
|
|
||||||
}
|
|
||||||
if (!table->file)
|
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (table->file->set_ha_share_ref(&share->ha_share))
|
if (table->file->set_ha_share_ref(&share->ha_share))
|
||||||
@ -18884,7 +18842,7 @@ bool Create_tmp_table::finalize(THD *thd,
|
|||||||
share->default_values= table->record[1]+alloc_length;
|
share->default_values= table->record[1]+alloc_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_tmp_table_column_bitmaps(table, m_bitmaps);
|
setup_tmp_table_column_bitmaps(table, m_bitmaps, table->s->fields);
|
||||||
|
|
||||||
recinfo=param->start_recinfo;
|
recinfo=param->start_recinfo;
|
||||||
null_flags=(uchar*) table->record[0];
|
null_flags=(uchar*) table->record[0];
|
||||||
@ -19339,8 +19297,8 @@ TABLE *create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
|
|||||||
bool keep_row_order)
|
bool keep_row_order)
|
||||||
{
|
{
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
Create_tmp_table maker(param, group,
|
Create_tmp_table maker(group, distinct, save_sum_fields, select_options,
|
||||||
distinct, save_sum_fields, select_options, rows_limit);
|
rows_limit);
|
||||||
if (!(table= maker.start(thd, param, table_alias)) ||
|
if (!(table= maker.start(thd, param, table_alias)) ||
|
||||||
maker.add_fields(thd, table, param, fields) ||
|
maker.add_fields(thd, table, param, fields) ||
|
||||||
maker.finalize(thd, table, param, do_not_open, keep_row_order))
|
maker.finalize(thd, table, param, do_not_open, keep_row_order))
|
||||||
@ -19359,7 +19317,7 @@ TABLE *create_tmp_table_for_schema(THD *thd, TMP_TABLE_PARAM *param,
|
|||||||
bool do_not_open, bool keep_row_order)
|
bool do_not_open, bool keep_row_order)
|
||||||
{
|
{
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
Create_tmp_table maker(param, (ORDER *) NULL, false, false,
|
Create_tmp_table maker((ORDER *) NULL, false, false,
|
||||||
select_options, HA_POS_ERROR);
|
select_options, HA_POS_ERROR);
|
||||||
if (!(table= maker.start(thd, param, &table_alias)) ||
|
if (!(table= maker.start(thd, param, &table_alias)) ||
|
||||||
maker.add_schema_fields(thd, table, param, schema_table) ||
|
maker.add_schema_fields(thd, table, param, schema_table) ||
|
||||||
|
Loading…
x
Reference in New Issue
Block a user