~thomir-deactivatedaccount/drizzle/drizzle-fix-bug653747

« back to all changes in this revision

Viewing changes to drizzled/table/instance.cc

  • Committer: Brian Aker
  • Date: 2010-10-10 02:07:52 UTC
  • mfrom: (1827.2.3 staging)
  • Revision ID: brian@tangent.org-20101010020752-ktv73isay5dxtvp3
Merge in switch on table_share_instance inheritance.

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