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