~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table/instance.cc

  • Committer: Brian Aker
  • Date: 2010-11-19 19:42:44 UTC
  • mto: (1945.2.1 quick)
  • mto: This revision was merged to the branch mainline in revision 1944.
  • Revision ID: brian@tangent.org-20101119194244-7vx6u5vwzvu9uvex
Remove dead getShare() call which should have been a call on the cache
directly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
36
namespace table
 
37
{
 
38
 
 
39
Instance::Instance(Session *session, List<CreateField> &field_list) :
 
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
 
 
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();
 
58
 
 
59
  in_use= session;           /* field_arg->reset() may access in_use */
 
60
 
 
61
  /* Create all fields and calculate the total length of record */
 
62
  List_iterator_fast<CreateField> it(field_list);
 
63
  while ((cdef= it++))
 
64
  {
 
65
    *field_arg= getMutableShare()->make_field(NULL,
 
66
                                                 cdef->length,
 
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,
 
70
                                                 cdef->decimals,
 
71
                                                 cdef->sql_type,
 
72
                                                 cdef->charset,
 
73
                                                 cdef->unireg_check,
 
74
                                                 cdef->interval,
 
75
                                                 cdef->field_name);
 
76
    if (!*field_arg)
 
77
    {
 
78
      throw "Memory allocation failure";
 
79
    }
 
80
 
 
81
    (*field_arg)->init(this);
 
82
    record_length+= (*field_arg)->pack_length();
 
83
    if (! ((*field_arg)->flags & NOT_NULL_FLAG))
 
84
      null_count++;
 
85
 
 
86
    if ((*field_arg)->flags & BLOB_FLAG)
 
87
      getMutableShare()->blob_field[blob_count++]= (uint32_t) (field_arg - getFields());
 
88
 
 
89
    field_arg++;
 
90
  }
 
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;
 
94
 
 
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())
 
100
  {
 
101
    throw "Memory allocation failure";
 
102
  }
 
103
 
 
104
  if (null_pack_length)
 
105
  {
 
106
    null_flags= (unsigned char*) getInsertRecord();
 
107
    getMutableShare()->null_fields= null_count;
 
108
    getMutableShare()->null_bytes= null_pack_length;
 
109
  }
 
110
  {
 
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;
 
115
 
 
116
    for (field_arg= getFields(); *field_arg; ++field_arg)
 
117
    {
 
118
      Field *cur_field= *field_arg;
 
119
      if ((cur_field->flags & NOT_NULL_FLAG))
 
120
        cur_field->move_field(field_pos);
 
121
      else
 
122
      {
 
123
        cur_field->move_field(field_pos, (unsigned char*) null_pos, null_bit);
 
124
        null_bit<<= 1;
 
125
        if (null_bit == (1 << 8))
 
126
        {
 
127
          ++null_pos;
 
128
          null_bit= 1;
 
129
        }
 
130
      }
 
131
      cur_field->reset();
 
132
 
 
133
      field_pos+= cur_field->pack_length();
 
134
    }
 
135
  }
 
136
}
 
137
 
 
138
bool Instance::open_tmp_table()
 
139
{
 
140
  int error;
 
141
  
 
142
  TableIdentifier identifier(getShare()->getSchemaName(), getShare()->getTableName(), getShare()->getPath());
 
143
  if ((error=cursor->ha_open(identifier,
 
144
                             O_RDWR,
 
145
                             HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
 
146
  {
 
147
    print_error(error, MYF(0));
 
148
    db_stat= 0;
 
149
    return true;
 
150
  }
 
151
  (void) cursor->extra(HA_EXTRA_QUICK);         /* Faster */
 
152
  return false;
 
153
}
 
154
 
 
155
 
 
156
/*
 
157
  Create MyISAM temporary table
 
158
 
 
159
  SYNOPSIS
 
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
 
164
      options         Option bits
 
165
 
 
166
  DESCRIPTION
 
167
    Create a MyISAM temporary table according to passed description. The is
 
168
    assumed to have one unique index or constraint.
 
169
 
 
170
    The passed array or MI_COLUMNDEF structures must have this form:
 
171
 
 
172
      1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte
 
173
         when there are many nullable columns)
 
174
      2. Table columns
 
175
      3. One free MI_COLUMNDEF element (*recinfo points here)
 
176
 
 
177
    This function may use the free element to create hash column for unique
 
178
    constraint.
 
179
 
 
180
   RETURN
 
181
     false - OK
 
182
     true  - Error
 
183
*/
 
184
 
 
185
bool Instance::create_myisam_tmp_table(KeyInfo *keyinfo,
 
186
                                                 MI_COLUMNDEF *start_recinfo,
 
187
                                                 MI_COLUMNDEF **recinfo,
 
188
                                                 uint64_t options)
 
189
{
 
190
  int error;
 
191
  MI_KEYDEF keydef;
 
192
  MI_UNIQUEDEF uniquedef;
 
193
 
 
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);
 
198
    if (not seg)
 
199
      return true;
 
200
 
 
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() ||
 
204
        getShare()->uniques)
 
205
    {
 
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;
 
212
      uniquedef.seg=seg;
 
213
      uniquedef.null_are_equal=1;
 
214
 
 
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;
 
219
      (*recinfo)++;
 
220
      getMutableShare()->setRecordLength(getShare()->getRecordLength() + MI_UNIQUE_HASH_LENGTH);
 
221
    }
 
222
    else
 
223
    {
 
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;
 
228
      keydef.seg= seg;
 
229
    }
 
230
    for (uint32_t i= 0; i < keyinfo->key_parts ; i++,seg++)
 
231
    {
 
232
      Field *key_field=keyinfo->key_part[i].field;
 
233
      seg->flag=     0;
 
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)
 
238
      {
 
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
 
244
      }
 
245
      else
 
246
      {
 
247
        seg->type= keyinfo->key_part[i].type;
 
248
      }
 
249
      if (!(key_field->flags & NOT_NULL_FLAG))
 
250
      {
 
251
        seg->null_bit= key_field->null_bit;
 
252
        seg->null_pos= (uint32_t) (key_field->null_ptr - (unsigned char*) getInsertRecord());
 
253
        /*
 
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
 
257
        */
 
258
        if (! using_unique_constraint)
 
259
          keydef.flag|= HA_NULL_ARE_EQUAL;
 
260
      }
 
261
    }
 
262
  }
 
263
  MI_CREATE_INFO create_info;
 
264
 
 
265
  if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
 
266
      OPTION_BIG_TABLES)
 
267
    create_info.data_file_length= ~(uint64_t) 0;
 
268
 
 
269
  if ((error= mi_create(getShare()->getTableName(), getShare()->sizeKeys(), &keydef,
 
270
                        (uint32_t) (*recinfo-start_recinfo),
 
271
                        start_recinfo,
 
272
                        getShare()->uniques, &uniquedef,
 
273
                        &create_info,
 
274
                        HA_CREATE_TMP_TABLE)))
 
275
  {
 
276
    print_error(error, MYF(0));
 
277
    db_stat= 0;
 
278
 
 
279
    return true;
 
280
  }
 
281
  in_use->status_var.created_tmp_disk_tables++;
 
282
  getMutableShare()->db_record_offset= 1;
 
283
  return false;
 
284
}
 
285
 
 
286
/*
 
287
  Set up column usage bitmaps for a temporary table
 
288
 
 
289
  IMPLEMENTATION
 
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.
 
292
*/
 
293
 
 
294
void Instance::setup_tmp_table_column_bitmaps()
 
295
{
 
296
  uint32_t field_count= getShare()->sizeFields();
 
297
 
 
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();
 
303
  def_write_set.set();
 
304
  def_read_set.set();
 
305
  default_column_bitmaps();
 
306
}
 
307
 
 
308
Instance::~Instance()
 
309
{
 
310
  const char *save_proc_info;
 
311
 
 
312
  save_proc_info= in_use->get_proc_info();
 
313
  in_use->set_proc_info("removing tmp table");
 
314
 
 
315
  // Release latches since this can take a long time
 
316
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(in_use);
 
317
 
 
318
  if (cursor)
 
319
  {
 
320
    if (db_stat)
 
321
    {
 
322
      cursor->closeMarkForDelete(getShare()->getTableName());
 
323
    }
 
324
 
 
325
    TableIdentifier identifier(getShare()->getSchemaName(), getShare()->getTableName(), getShare()->getTableName());
 
326
    getShare()->getEngine()->doDropTable(*in_use, identifier);
 
327
 
 
328
    delete cursor;
 
329
  }
 
330
 
 
331
  /* free blobs */
 
332
  for (Field **ptr= getFields() ; *ptr ; ptr++)
 
333
  {
 
334
    (*ptr)->free();
 
335
  }
 
336
  free_io_cache();
 
337
 
 
338
  getMemRoot()->free_root(MYF(0));
 
339
  in_use->set_proc_info(save_proc_info);
 
340
}
 
341
 
 
342
 
 
343
} /* namespace table */
 
344
} /* namespace drizzled */