~drizzle-trunk/drizzle/development

1843.8.3 by Brian Aker
Break out table types (first pass).
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2010 Brian Aker
5
 *
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.
10
 *
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.
15
 *
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
19
 */
20
21
#include "config.h"
22
23
#include <sys/types.h>
24
#include <sys/stat.h>
25
#include <fcntl.h>
26
27
#include "drizzled/session.h"
28
#include "plugin/myisam/myisam.h"
29
#include "drizzled/plugin/transactional_storage_engine.h"
30
31
#include "drizzled/table.h"
32
33
namespace drizzled
34
{
35
1843.8.4 by Brian Aker
Committing refactor of table out (this is part of the concurrency work).
36
namespace table
37
{
1843.8.3 by Brian Aker
Break out table types (first pass).
38
2069.4.2 by Brian Aker
Clear up naming convention for table type.
39
Singular::Singular(Session *session, List<CreateField> &field_list) :
1878.5.1 by Brian Aker
Update instance for handling construction of virtual_tmp
40
  _share(message::Table::INTERNAL),
41
  _has_variable_width(false)
42
{
43
  uint32_t field_count= field_list.elements;
44
  uint32_t blob_count= 0;
45
  Field **field_arg;
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 */
50
1878.5.2 by Brian Aker
Encapsulation of record.
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);
2040.4.1 by Brian Aker
Update to time and field.
55
  getMutableShare()->setFieldSize(field_count);
1878.5.2 by Brian Aker
Encapsulation of record.
56
  getMutableShare()->blob_ptr_size= portable_sizeof_char_ptr;
57
  setup_tmp_table_column_bitmaps();
1878.5.1 by Brian Aker
Update instance for handling construction of virtual_tmp
58
1878.5.2 by Brian Aker
Encapsulation of record.
59
  in_use= session;           /* field_arg->reset() may access in_use */
1878.5.1 by Brian Aker
Update instance for handling construction of virtual_tmp
60
61
  /* Create all fields and calculate the total length of record */
62
  List_iterator_fast<CreateField> it(field_list);
2040.4.1 by Brian Aker
Update to time and field.
63
  message::Table::Field null_field;
1878.5.1 by Brian Aker
Update instance for handling construction of virtual_tmp
64
  while ((cdef= it++))
65
  {
2040.4.1 by Brian Aker
Update to time and field.
66
    *field_arg= getMutableShare()->make_field(null_field,
67
                                              NULL,
2008.2.3 by Brian Aker
Fixing up a, somewhat, hidden unsigned type to solve a few issues around
68
                                              cdef->length,
69
                                              (cdef->flags & NOT_NULL_FLAG) ? false : true,
70
                                              (unsigned char *) ((cdef->flags & NOT_NULL_FLAG) ? 0 : ""),
71
                                              (cdef->flags & NOT_NULL_FLAG) ? 0 : 1,
72
                                              cdef->decimals,
73
                                              cdef->sql_type,
74
                                              cdef->charset,
75
                                              cdef->unireg_check,
76
                                              cdef->interval,
77
                                              cdef->field_name,
78
                                              cdef->flags & UNSIGNED_FLAG ? true : false);
1878.5.1 by Brian Aker
Update instance for handling construction of virtual_tmp
79
    if (!*field_arg)
80
    {
81
      throw "Memory allocation failure";
82
    }
83
1878.5.2 by Brian Aker
Encapsulation of record.
84
    (*field_arg)->init(this);
1878.5.1 by Brian Aker
Update instance for handling construction of virtual_tmp
85
    record_length+= (*field_arg)->pack_length();
86
    if (! ((*field_arg)->flags & NOT_NULL_FLAG))
87
      null_count++;
88
89
    if ((*field_arg)->flags & BLOB_FLAG)
1878.5.2 by Brian Aker
Encapsulation of record.
90
      getMutableShare()->blob_field[blob_count++]= (uint32_t) (field_arg - getFields());
1878.5.1 by Brian Aker
Update instance for handling construction of virtual_tmp
91
92
    field_arg++;
93
  }
94
  *field_arg= NULL;                             /* mark the end of the list */
1878.5.2 by Brian Aker
Encapsulation of record.
95
  getMutableShare()->blob_field[blob_count]= 0;            /* mark the end of the list */
96
  getMutableShare()->blob_fields= blob_count;
1878.5.1 by Brian Aker
Update instance for handling construction of virtual_tmp
97
98
  null_pack_length= (null_count + 7)/8;
1878.5.2 by Brian Aker
Encapsulation of record.
99
  getMutableShare()->setRecordLength(record_length + null_pack_length);
100
  getMutableShare()->rec_buff_length= ALIGN_SIZE(getMutableShare()->getRecordLength() + 1);
101
  record[0]= (unsigned char*)session->alloc(getMutableShare()->rec_buff_length);
102
  if (not getInsertRecord())
1878.5.1 by Brian Aker
Update instance for handling construction of virtual_tmp
103
  {
104
    throw "Memory allocation failure";
105
  }
106
107
  if (null_pack_length)
108
  {
1878.5.2 by Brian Aker
Encapsulation of record.
109
    null_flags= (unsigned char*) getInsertRecord();
110
    getMutableShare()->null_fields= null_count;
111
    getMutableShare()->null_bytes= null_pack_length;
1878.5.1 by Brian Aker
Update instance for handling construction of virtual_tmp
112
  }
113
  {
114
    /* Set up field pointers */
1878.5.2 by Brian Aker
Encapsulation of record.
115
    unsigned char *null_pos= getInsertRecord();
116
    unsigned char *field_pos= null_pos + getMutableShare()->null_bytes;
1878.5.1 by Brian Aker
Update instance for handling construction of virtual_tmp
117
    uint32_t null_bit= 1;
118
1878.5.2 by Brian Aker
Encapsulation of record.
119
    for (field_arg= getFields(); *field_arg; ++field_arg)
1878.5.1 by Brian Aker
Update instance for handling construction of virtual_tmp
120
    {
121
      Field *cur_field= *field_arg;
122
      if ((cur_field->flags & NOT_NULL_FLAG))
123
        cur_field->move_field(field_pos);
124
      else
125
      {
126
        cur_field->move_field(field_pos, (unsigned char*) null_pos, null_bit);
127
        null_bit<<= 1;
128
        if (null_bit == (1 << 8))
129
        {
130
          ++null_pos;
131
          null_bit= 1;
132
        }
133
      }
134
      cur_field->reset();
135
136
      field_pos+= cur_field->pack_length();
137
    }
138
  }
139
}
140
2069.4.2 by Brian Aker
Clear up naming convention for table type.
141
bool Singular::open_tmp_table()
1843.8.3 by Brian Aker
Break out table types (first pass).
142
{
143
  int error;
144
  
145
  TableIdentifier identifier(getShare()->getSchemaName(), getShare()->getTableName(), getShare()->getPath());
146
  if ((error=cursor->ha_open(identifier,
147
                             O_RDWR,
148
                             HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
149
  {
150
    print_error(error, MYF(0));
151
    db_stat= 0;
152
    return true;
153
  }
154
  (void) cursor->extra(HA_EXTRA_QUICK);		/* Faster */
155
  return false;
156
}
157
158
159
/*
160
  Create MyISAM temporary table
161
162
  SYNOPSIS
163
    create_myisam_tmp_table()
164
      keyinfo         Description of the index (there is always one index)
165
      start_recinfo   MyISAM's column descriptions
166
      recinfo INOUT   End of MyISAM's column descriptions
167
      options         Option bits
168
169
  DESCRIPTION
170
    Create a MyISAM temporary table according to passed description. The is
171
    assumed to have one unique index or constraint.
172
173
    The passed array or MI_COLUMNDEF structures must have this form:
174
175
      1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte
176
         when there are many nullable columns)
177
      2. Table columns
178
      3. One free MI_COLUMNDEF element (*recinfo points here)
179
180
    This function may use the free element to create hash column for unique
181
    constraint.
182
183
   RETURN
184
     false - OK
185
     true  - Error
186
*/
187
2069.4.2 by Brian Aker
Clear up naming convention for table type.
188
bool Singular::create_myisam_tmp_table(KeyInfo *keyinfo,
1843.8.3 by Brian Aker
Break out table types (first pass).
189
                                                 MI_COLUMNDEF *start_recinfo,
190
                                                 MI_COLUMNDEF **recinfo,
191
                                                 uint64_t options)
192
{
193
  int error;
194
  MI_KEYDEF keydef;
195
  MI_UNIQUEDEF uniquedef;
196
197
  if (getShare()->sizeKeys())
198
  {						// Get keys for ni_create
199
    bool using_unique_constraint= false;
200
    HA_KEYSEG *seg= (HA_KEYSEG*) getMemRoot()->alloc_root(sizeof(*seg) * keyinfo->key_parts);
201
    if (not seg)
202
      return true;
203
204
    memset(seg, 0, sizeof(*seg) * keyinfo->key_parts);
205
    if (keyinfo->key_length >= cursor->getEngine()->max_key_length() ||
1855 by Brian Aker
Merge in refactoring on table (broken it up by type, this will allow me to
206
        keyinfo->key_parts > cursor->getEngine()->max_key_parts() ||
207
        getShare()->uniques)
1843.8.3 by Brian Aker
Break out table types (first pass).
208
    {
209
      /* Can't create a key; Make a unique constraint instead of a key */
210
      getMutableShare()->keys=    0;
211
      getMutableShare()->uniques= 1;
212
      using_unique_constraint= true;
213
      memset(&uniquedef, 0, sizeof(uniquedef));
214
      uniquedef.keysegs=keyinfo->key_parts;
215
      uniquedef.seg=seg;
216
      uniquedef.null_are_equal=1;
217
218
      /* Create extra column for hash value */
219
      memset(*recinfo, 0, sizeof(**recinfo));
220
      (*recinfo)->type= FIELD_CHECK;
221
      (*recinfo)->length=MI_UNIQUE_HASH_LENGTH;
222
      (*recinfo)++;
223
      getMutableShare()->setRecordLength(getShare()->getRecordLength() + MI_UNIQUE_HASH_LENGTH);
224
    }
225
    else
226
    {
227
      /* Create an unique key */
228
      memset(&keydef, 0, sizeof(keydef));
229
      keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
230
      keydef.keysegs=  keyinfo->key_parts;
231
      keydef.seg= seg;
232
    }
233
    for (uint32_t i= 0; i < keyinfo->key_parts ; i++,seg++)
234
    {
235
      Field *key_field=keyinfo->key_part[i].field;
236
      seg->flag=     0;
237
      seg->language= key_field->charset()->number;
238
      seg->length=   keyinfo->key_part[i].length;
239
      seg->start=    keyinfo->key_part[i].offset;
240
      if (key_field->flags & BLOB_FLAG)
241
      {
1855 by Brian Aker
Merge in refactoring on table (broken it up by type, this will allow me to
242
        seg->type= ((keyinfo->key_part[i].key_type & 1 /* binary */) ?
243
                    HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
244
        seg->bit_start= (uint8_t)(key_field->pack_length() - getShare()->blob_ptr_size);
245
        seg->flag= HA_BLOB_PART;
246
        seg->length= 0;			// Whole blob in unique constraint
1843.8.3 by Brian Aker
Break out table types (first pass).
247
      }
248
      else
249
      {
1855 by Brian Aker
Merge in refactoring on table (broken it up by type, this will allow me to
250
        seg->type= keyinfo->key_part[i].type;
1843.8.3 by Brian Aker
Break out table types (first pass).
251
      }
252
      if (!(key_field->flags & NOT_NULL_FLAG))
253
      {
1855 by Brian Aker
Merge in refactoring on table (broken it up by type, this will allow me to
254
        seg->null_bit= key_field->null_bit;
255
        seg->null_pos= (uint32_t) (key_field->null_ptr - (unsigned char*) getInsertRecord());
256
        /*
257
          We are using a GROUP BY on something that contains NULL
258
          In this case we have to tell MyISAM that two NULL should
259
          on INSERT be regarded at the same value
260
        */
261
        if (! using_unique_constraint)
262
          keydef.flag|= HA_NULL_ARE_EQUAL;
1843.8.3 by Brian Aker
Break out table types (first pass).
263
      }
264
    }
265
  }
266
  MI_CREATE_INFO create_info;
267
268
  if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
269
      OPTION_BIG_TABLES)
270
    create_info.data_file_length= ~(uint64_t) 0;
271
272
  if ((error= mi_create(getShare()->getTableName(), getShare()->sizeKeys(), &keydef,
273
                        (uint32_t) (*recinfo-start_recinfo),
274
                        start_recinfo,
275
                        getShare()->uniques, &uniquedef,
276
                        &create_info,
277
                        HA_CREATE_TMP_TABLE)))
278
  {
279
    print_error(error, MYF(0));
280
    db_stat= 0;
281
282
    return true;
283
  }
284
  in_use->status_var.created_tmp_disk_tables++;
285
  getMutableShare()->db_record_offset= 1;
286
  return false;
287
}
288
1843.8.4 by Brian Aker
Committing refactor of table out (this is part of the concurrency work).
289
/*
290
  Set up column usage bitmaps for a temporary table
291
292
  IMPLEMENTATION
293
    For temporary tables, we need one bitmap with all columns set and
294
    a tmp_set bitmap to be used by things like filesort.
295
*/
296
2069.4.2 by Brian Aker
Clear up naming convention for table type.
297
void Singular::setup_tmp_table_column_bitmaps()
1843.8.4 by Brian Aker
Committing refactor of table out (this is part of the concurrency work).
298
{
299
  uint32_t field_count= getShare()->sizeFields();
300
1859.2.1 by Brian Aker
Small moveable.
301
  def_read_set.resize(field_count);
302
  def_write_set.resize(field_count);
303
  tmp_set.resize(field_count);
304
  getMutableShare()->all_set.resize(field_count);
305
  getMutableShare()->all_set.set();
306
  def_write_set.set();
307
  def_read_set.set();
1843.8.4 by Brian Aker
Committing refactor of table out (this is part of the concurrency work).
308
  default_column_bitmaps();
309
}
310
2069.4.2 by Brian Aker
Clear up naming convention for table type.
311
Singular::~Singular()
1859.2.1 by Brian Aker
Small moveable.
312
{
1864.4.2 by Brian Aker
Cleanup destructor on instance.
313
  const char *save_proc_info;
314
315
  save_proc_info= in_use->get_proc_info();
316
  in_use->set_proc_info("removing tmp table");
317
318
  // Release latches since this can take a long time
319
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(in_use);
320
321
  if (cursor)
322
  {
323
    if (db_stat)
324
    {
325
      cursor->closeMarkForDelete(getShare()->getTableName());
326
    }
327
328
    TableIdentifier identifier(getShare()->getSchemaName(), getShare()->getTableName(), getShare()->getTableName());
2068.7.1 by Brian Aker
First pass through error correction in SE interface for drop table.
329
    drizzled::error_t ignored;
2017.2.2 by Brian Aker
Additional encapsulation around the SE api.
330
    plugin::StorageEngine::dropTable(*in_use,
331
                                     *getShare()->getEngine(),
2068.7.1 by Brian Aker
First pass through error correction in SE interface for drop table.
332
                                     identifier,
333
                                     ignored);
1864.4.2 by Brian Aker
Cleanup destructor on instance.
334
335
    delete cursor;
336
  }
337
338
  /* free blobs */
339
  for (Field **ptr= getFields() ; *ptr ; ptr++)
340
  {
341
    (*ptr)->free();
342
  }
343
  free_io_cache();
344
345
  getMemRoot()->free_root(MYF(0));
346
  in_use->set_proc_info(save_proc_info);
1859.2.1 by Brian Aker
Small moveable.
347
}
348
1843.8.4 by Brian Aker
Committing refactor of table out (this is part of the concurrency work).
349
350
} /* namespace table */
1843.8.3 by Brian Aker
Break out table types (first pass).
351
} /* namespace drizzled */