~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table/instance.cc

  • Committer: Stewart Smith
  • Date: 2010-03-18 12:01:34 UTC
  • mto: (1666.2.3 build)
  • mto: This revision was merged to the branch mainline in revision 1596.
  • Revision ID: stewart@flamingspork.com-20100318120134-45fdnsw8g3j6c7oy
move RAND() into a plugin

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 */