~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table/instance.cc

  • Committer: Brian Aker
  • Date: 2010-10-15 05:30:39 UTC
  • mfrom: (1843.8.7 trunk-drizzle)
  • Revision ID: brian@tangent.org-20101015053039-ebmv3hnn1yaq4wqy
Merge in refactoring on table (broken it up by type, this will allow me to
insert the new locking).

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
bool Instance::open_tmp_table()
 
40
{
 
41
  int error;
 
42
  
 
43
  TableIdentifier identifier(getShare()->getSchemaName(), getShare()->getTableName(), getShare()->getPath());
 
44
  if ((error=cursor->ha_open(identifier,
 
45
                             this,
 
46
                             O_RDWR,
 
47
                             HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
 
48
  {
 
49
    print_error(error, MYF(0));
 
50
    db_stat= 0;
 
51
    return true;
 
52
  }
 
53
  (void) cursor->extra(HA_EXTRA_QUICK);         /* Faster */
 
54
  return false;
 
55
}
 
56
 
 
57
 
 
58
/*
 
59
  Create MyISAM temporary table
 
60
 
 
61
  SYNOPSIS
 
62
    create_myisam_tmp_table()
 
63
      keyinfo         Description of the index (there is always one index)
 
64
      start_recinfo   MyISAM's column descriptions
 
65
      recinfo INOUT   End of MyISAM's column descriptions
 
66
      options         Option bits
 
67
 
 
68
  DESCRIPTION
 
69
    Create a MyISAM temporary table according to passed description. The is
 
70
    assumed to have one unique index or constraint.
 
71
 
 
72
    The passed array or MI_COLUMNDEF structures must have this form:
 
73
 
 
74
      1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte
 
75
         when there are many nullable columns)
 
76
      2. Table columns
 
77
      3. One free MI_COLUMNDEF element (*recinfo points here)
 
78
 
 
79
    This function may use the free element to create hash column for unique
 
80
    constraint.
 
81
 
 
82
   RETURN
 
83
     false - OK
 
84
     true  - Error
 
85
*/
 
86
 
 
87
bool Instance::create_myisam_tmp_table(KeyInfo *keyinfo,
 
88
                                                 MI_COLUMNDEF *start_recinfo,
 
89
                                                 MI_COLUMNDEF **recinfo,
 
90
                                                 uint64_t options)
 
91
{
 
92
  int error;
 
93
  MI_KEYDEF keydef;
 
94
  MI_UNIQUEDEF uniquedef;
 
95
 
 
96
  if (getShare()->sizeKeys())
 
97
  {                                             // Get keys for ni_create
 
98
    bool using_unique_constraint= false;
 
99
    HA_KEYSEG *seg= (HA_KEYSEG*) getMemRoot()->alloc_root(sizeof(*seg) * keyinfo->key_parts);
 
100
    if (not seg)
 
101
      return true;
 
102
 
 
103
    memset(seg, 0, sizeof(*seg) * keyinfo->key_parts);
 
104
    if (keyinfo->key_length >= cursor->getEngine()->max_key_length() ||
 
105
        keyinfo->key_parts > cursor->getEngine()->max_key_parts() ||
 
106
        getShare()->uniques)
 
107
    {
 
108
      /* Can't create a key; Make a unique constraint instead of a key */
 
109
      getMutableShare()->keys=    0;
 
110
      getMutableShare()->uniques= 1;
 
111
      using_unique_constraint= true;
 
112
      memset(&uniquedef, 0, sizeof(uniquedef));
 
113
      uniquedef.keysegs=keyinfo->key_parts;
 
114
      uniquedef.seg=seg;
 
115
      uniquedef.null_are_equal=1;
 
116
 
 
117
      /* Create extra column for hash value */
 
118
      memset(*recinfo, 0, sizeof(**recinfo));
 
119
      (*recinfo)->type= FIELD_CHECK;
 
120
      (*recinfo)->length=MI_UNIQUE_HASH_LENGTH;
 
121
      (*recinfo)++;
 
122
      getMutableShare()->setRecordLength(getShare()->getRecordLength() + MI_UNIQUE_HASH_LENGTH);
 
123
    }
 
124
    else
 
125
    {
 
126
      /* Create an unique key */
 
127
      memset(&keydef, 0, sizeof(keydef));
 
128
      keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
 
129
      keydef.keysegs=  keyinfo->key_parts;
 
130
      keydef.seg= seg;
 
131
    }
 
132
    for (uint32_t i= 0; i < keyinfo->key_parts ; i++,seg++)
 
133
    {
 
134
      Field *key_field=keyinfo->key_part[i].field;
 
135
      seg->flag=     0;
 
136
      seg->language= key_field->charset()->number;
 
137
      seg->length=   keyinfo->key_part[i].length;
 
138
      seg->start=    keyinfo->key_part[i].offset;
 
139
      if (key_field->flags & BLOB_FLAG)
 
140
      {
 
141
        seg->type= ((keyinfo->key_part[i].key_type & 1 /* binary */) ?
 
142
                    HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
 
143
        seg->bit_start= (uint8_t)(key_field->pack_length() - getShare()->blob_ptr_size);
 
144
        seg->flag= HA_BLOB_PART;
 
145
        seg->length= 0;                 // Whole blob in unique constraint
 
146
      }
 
147
      else
 
148
      {
 
149
        seg->type= keyinfo->key_part[i].type;
 
150
      }
 
151
      if (!(key_field->flags & NOT_NULL_FLAG))
 
152
      {
 
153
        seg->null_bit= key_field->null_bit;
 
154
        seg->null_pos= (uint32_t) (key_field->null_ptr - (unsigned char*) getInsertRecord());
 
155
        /*
 
156
          We are using a GROUP BY on something that contains NULL
 
157
          In this case we have to tell MyISAM that two NULL should
 
158
          on INSERT be regarded at the same value
 
159
        */
 
160
        if (! using_unique_constraint)
 
161
          keydef.flag|= HA_NULL_ARE_EQUAL;
 
162
      }
 
163
    }
 
164
  }
 
165
  MI_CREATE_INFO create_info;
 
166
 
 
167
  if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
 
168
      OPTION_BIG_TABLES)
 
169
    create_info.data_file_length= ~(uint64_t) 0;
 
170
 
 
171
  if ((error= mi_create(getShare()->getTableName(), getShare()->sizeKeys(), &keydef,
 
172
                        (uint32_t) (*recinfo-start_recinfo),
 
173
                        start_recinfo,
 
174
                        getShare()->uniques, &uniquedef,
 
175
                        &create_info,
 
176
                        HA_CREATE_TMP_TABLE)))
 
177
  {
 
178
    print_error(error, MYF(0));
 
179
    db_stat= 0;
 
180
 
 
181
    return true;
 
182
  }
 
183
  in_use->status_var.created_tmp_disk_tables++;
 
184
  getMutableShare()->db_record_offset= 1;
 
185
  return false;
 
186
}
 
187
 
 
188
 
 
189
void Instance::free_tmp_table(Session *session)
 
190
{
 
191
  const char *save_proc_info;
 
192
 
 
193
  save_proc_info= session->get_proc_info();
 
194
  session->set_proc_info("removing tmp table");
 
195
 
 
196
  // Release latches since this can take a long time
 
197
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
 
198
 
 
199
  if (cursor)
 
200
  {
 
201
    if (db_stat)
 
202
    {
 
203
      cursor->closeMarkForDelete(getShare()->getTableName());
 
204
    }
 
205
 
 
206
    TableIdentifier identifier(getShare()->getSchemaName(), getShare()->getTableName(), getShare()->getTableName());
 
207
    getShare()->getEngine()->doDropTable(*session, identifier);
 
208
 
 
209
    delete cursor;
 
210
  }
 
211
 
 
212
  /* free blobs */
 
213
  for (Field **ptr= getFields() ; *ptr ; ptr++)
 
214
  {
 
215
    (*ptr)->free();
 
216
  }
 
217
  free_io_cache();
 
218
 
 
219
  getMemRoot()->free_root(MYF(0));
 
220
  session->set_proc_info(save_proc_info);
 
221
}
 
222
 
 
223
/*
 
224
  Set up column usage bitmaps for a temporary table
 
225
 
 
226
  IMPLEMENTATION
 
227
    For temporary tables, we need one bitmap with all columns set and
 
228
    a tmp_set bitmap to be used by things like filesort.
 
229
*/
 
230
 
 
231
void Instance::setup_tmp_table_column_bitmaps()
 
232
{
 
233
  uint32_t field_count= getShare()->sizeFields();
 
234
 
 
235
  this->def_read_set.resize(field_count);
 
236
  this->def_write_set.resize(field_count);
 
237
  this->tmp_set.resize(field_count);
 
238
  this->getMutableShare()->all_set.resize(field_count);
 
239
  this->getMutableShare()->all_set.set();
 
240
  this->def_write_set.set();
 
241
  this->def_read_set.set();
 
242
  default_column_bitmaps();
 
243
}
 
244
 
 
245
 
 
246
} /* namespace table */
 
247
} /* namespace drizzled */