1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2010 Brian Aker
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
#include <sys/types.h>
27
#include "drizzled/session.h"
28
#include "plugin/myisam/myisam.h"
29
#include "drizzled/plugin/transactional_storage_engine.h"
31
#include "drizzled/table.h"
39
Instance::Instance(Session *session, List<CreateField> &field_list) :
40
_share(message::Table::INTERNAL),
41
_has_variable_width(false)
43
uint32_t field_count= field_list.elements;
44
uint32_t blob_count= 0;
46
CreateField *cdef; /* column definition */
47
uint32_t record_length= 0;
48
uint32_t null_count= 0; /* number of columns which may be null */
49
uint32_t null_pack_length; /* NULL representation array length */
51
getMutableShare()->setFields(field_count + 1);
52
setFields(getMutableShare()->getFields(true));
53
field_arg= getMutableShare()->getFields(true);
54
getMutableShare()->blob_field.resize(field_count+1);
55
getMutableShare()->fields= field_count;
56
getMutableShare()->blob_ptr_size= portable_sizeof_char_ptr;
57
setup_tmp_table_column_bitmaps();
59
in_use= session; /* field_arg->reset() may access in_use */
61
/* Create all fields and calculate the total length of record */
62
List_iterator_fast<CreateField> it(field_list);
65
*field_arg= getMutableShare()->make_field(NULL,
67
(cdef->flags & NOT_NULL_FLAG) ? false : true,
68
(unsigned char *) ((cdef->flags & NOT_NULL_FLAG) ? 0 : ""),
69
(cdef->flags & NOT_NULL_FLAG) ? 0 : 1,
78
throw "Memory allocation failure";
81
(*field_arg)->init(this);
82
record_length+= (*field_arg)->pack_length();
83
if (! ((*field_arg)->flags & NOT_NULL_FLAG))
86
if ((*field_arg)->flags & BLOB_FLAG)
87
getMutableShare()->blob_field[blob_count++]= (uint32_t) (field_arg - getFields());
91
*field_arg= NULL; /* mark the end of the list */
92
getMutableShare()->blob_field[blob_count]= 0; /* mark the end of the list */
93
getMutableShare()->blob_fields= blob_count;
95
null_pack_length= (null_count + 7)/8;
96
getMutableShare()->setRecordLength(record_length + null_pack_length);
97
getMutableShare()->rec_buff_length= ALIGN_SIZE(getMutableShare()->getRecordLength() + 1);
98
record[0]= (unsigned char*)session->alloc(getMutableShare()->rec_buff_length);
99
if (not getInsertRecord())
101
throw "Memory allocation failure";
104
if (null_pack_length)
106
null_flags= (unsigned char*) getInsertRecord();
107
getMutableShare()->null_fields= null_count;
108
getMutableShare()->null_bytes= null_pack_length;
111
/* Set up field pointers */
112
unsigned char *null_pos= getInsertRecord();
113
unsigned char *field_pos= null_pos + getMutableShare()->null_bytes;
114
uint32_t null_bit= 1;
116
for (field_arg= getFields(); *field_arg; ++field_arg)
118
Field *cur_field= *field_arg;
119
if ((cur_field->flags & NOT_NULL_FLAG))
120
cur_field->move_field(field_pos);
123
cur_field->move_field(field_pos, (unsigned char*) null_pos, null_bit);
125
if (null_bit == (1 << 8))
133
field_pos+= cur_field->pack_length();
138
bool Instance::open_tmp_table()
142
TableIdentifier identifier(getShare()->getSchemaName(), getShare()->getTableName(), getShare()->getPath());
143
if ((error=cursor->ha_open(identifier,
145
HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
147
print_error(error, MYF(0));
151
(void) cursor->extra(HA_EXTRA_QUICK); /* Faster */
157
Create MyISAM temporary table
160
create_myisam_tmp_table()
161
keyinfo Description of the index (there is always one index)
162
start_recinfo MyISAM's column descriptions
163
recinfo INOUT End of MyISAM's column descriptions
167
Create a MyISAM temporary table according to passed description. The is
168
assumed to have one unique index or constraint.
170
The passed array or MI_COLUMNDEF structures must have this form:
172
1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte
173
when there are many nullable columns)
175
3. One free MI_COLUMNDEF element (*recinfo points here)
177
This function may use the free element to create hash column for unique
185
bool Instance::create_myisam_tmp_table(KeyInfo *keyinfo,
186
MI_COLUMNDEF *start_recinfo,
187
MI_COLUMNDEF **recinfo,
192
MI_UNIQUEDEF uniquedef;
194
if (getShare()->sizeKeys())
195
{ // Get keys for ni_create
196
bool using_unique_constraint= false;
197
HA_KEYSEG *seg= (HA_KEYSEG*) getMemRoot()->alloc_root(sizeof(*seg) * keyinfo->key_parts);
201
memset(seg, 0, sizeof(*seg) * keyinfo->key_parts);
202
if (keyinfo->key_length >= cursor->getEngine()->max_key_length() ||
203
keyinfo->key_parts > cursor->getEngine()->max_key_parts() ||
206
/* Can't create a key; Make a unique constraint instead of a key */
207
getMutableShare()->keys= 0;
208
getMutableShare()->uniques= 1;
209
using_unique_constraint= true;
210
memset(&uniquedef, 0, sizeof(uniquedef));
211
uniquedef.keysegs=keyinfo->key_parts;
213
uniquedef.null_are_equal=1;
215
/* Create extra column for hash value */
216
memset(*recinfo, 0, sizeof(**recinfo));
217
(*recinfo)->type= FIELD_CHECK;
218
(*recinfo)->length=MI_UNIQUE_HASH_LENGTH;
220
getMutableShare()->setRecordLength(getShare()->getRecordLength() + MI_UNIQUE_HASH_LENGTH);
224
/* Create an unique key */
225
memset(&keydef, 0, sizeof(keydef));
226
keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
227
keydef.keysegs= keyinfo->key_parts;
230
for (uint32_t i= 0; i < keyinfo->key_parts ; i++,seg++)
232
Field *key_field=keyinfo->key_part[i].field;
234
seg->language= key_field->charset()->number;
235
seg->length= keyinfo->key_part[i].length;
236
seg->start= keyinfo->key_part[i].offset;
237
if (key_field->flags & BLOB_FLAG)
239
seg->type= ((keyinfo->key_part[i].key_type & 1 /* binary */) ?
240
HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
241
seg->bit_start= (uint8_t)(key_field->pack_length() - getShare()->blob_ptr_size);
242
seg->flag= HA_BLOB_PART;
243
seg->length= 0; // Whole blob in unique constraint
247
seg->type= keyinfo->key_part[i].type;
249
if (!(key_field->flags & NOT_NULL_FLAG))
251
seg->null_bit= key_field->null_bit;
252
seg->null_pos= (uint32_t) (key_field->null_ptr - (unsigned char*) getInsertRecord());
254
We are using a GROUP BY on something that contains NULL
255
In this case we have to tell MyISAM that two NULL should
256
on INSERT be regarded at the same value
258
if (! using_unique_constraint)
259
keydef.flag|= HA_NULL_ARE_EQUAL;
263
MI_CREATE_INFO create_info;
265
if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
267
create_info.data_file_length= ~(uint64_t) 0;
269
if ((error= mi_create(getShare()->getTableName(), getShare()->sizeKeys(), &keydef,
270
(uint32_t) (*recinfo-start_recinfo),
272
getShare()->uniques, &uniquedef,
274
HA_CREATE_TMP_TABLE)))
276
print_error(error, MYF(0));
281
in_use->status_var.created_tmp_disk_tables++;
282
getMutableShare()->db_record_offset= 1;
287
Set up column usage bitmaps for a temporary table
290
For temporary tables, we need one bitmap with all columns set and
291
a tmp_set bitmap to be used by things like filesort.
294
void Instance::setup_tmp_table_column_bitmaps()
296
uint32_t field_count= getShare()->sizeFields();
298
def_read_set.resize(field_count);
299
def_write_set.resize(field_count);
300
tmp_set.resize(field_count);
301
getMutableShare()->all_set.resize(field_count);
302
getMutableShare()->all_set.set();
305
default_column_bitmaps();
308
Instance::~Instance()
310
const char *save_proc_info;
312
save_proc_info= in_use->get_proc_info();
313
in_use->set_proc_info("removing tmp table");
315
// Release latches since this can take a long time
316
plugin::TransactionalStorageEngine::releaseTemporaryLatches(in_use);
322
cursor->closeMarkForDelete(getShare()->getTableName());
325
TableIdentifier identifier(getShare()->getSchemaName(), getShare()->getTableName(), getShare()->getTableName());
326
getShare()->getEngine()->doDropTable(*in_use, identifier);
332
for (Field **ptr= getFields() ; *ptr ; ptr++)
338
getMemRoot()->free_root(MYF(0));
339
in_use->set_proc_info(save_proc_info);
343
} /* namespace table */
344
} /* namespace drizzled */