~drizzle-trunk/drizzle/development

1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
1239.3.28 by Toru Maesaka
Added UNIQUE constraint check for UPDATE queries on VARCHAR key(s) and some tests for it.
4
 *  Copyright (C) 2009 - 2010 Toru Maesaka
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
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; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19
1239.3.103 by Toru Maesaka
Took out config.h from ha_blitz.h and updated the index test for the build farm.
20
#include "config.h"
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
21
#include "ha_blitz.h"
22
1239.5.4 by Stewart Smith
cpplint for BlitzDB: Do not use namespace using-directives in headers.
23
using namespace std;
1239.3.42 by Toru Maesaka
Merged Drizzle's Trunk.
24
using namespace drizzled;
25
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
26
static pthread_mutex_t blitz_utility_mutex;
27
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
28
static const char *ha_blitz_exts[] = {
29
  BLITZ_DATA_EXT,
30
  BLITZ_INDEX_EXT,
31
  BLITZ_SYSTEM_EXT,
32
  NULL
33
};
34
1239.3.128 by Toru Maesaka
Added base work for sysvar handling in BlitzDB.
35
/* Global Variables for Startup Options */
36
uint64_t blitz_estimated_rows;
37
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
38
class BlitzEngine : public drizzled::plugin::StorageEngine {
1239.3.91 by Toru Maesaka
Encapsulated 'share' mechanism to BlitzEngine class.
39
private:
40
  TCMAP *blitz_table_cache;
41
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
42
public:
43
  BlitzEngine(const std::string &name_arg) :
44
    drizzled::plugin::StorageEngine(name_arg,
45
                                    drizzled::HTON_NULL_IN_KEY |
46
                                    drizzled::HTON_PRIMARY_KEY_IN_READ_INDEX |
47
                                    drizzled::HTON_STATS_RECORDS_IS_EXACT |
1239.3.96 by Toru Maesaka
Supported interfaces changes in StorageEngine::doGetTableNames().
48
                                    drizzled::HTON_SKIP_STORE_LOCK) {
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
49
    table_definition_ext = BLITZ_SYSTEM_EXT;
50
  }
51
52
  virtual ~BlitzEngine() {
53
    pthread_mutex_destroy(&blitz_utility_mutex);
54
    tcmapdel(blitz_table_cache);
55
  }
56
1680.6.1 by Brian Aker
Remove call for using special new for a cursor.
57
  virtual drizzled::Cursor *create(drizzled::TableShare &table) {
58
    return new ha_blitz(*this, table);
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
59
  }
60
61
  const char **bas_ext() const {
62
    return ha_blitz_exts;
63
  }
64
1239.3.95 by Toru Maesaka
Supported the interface change for StorageEngine::doCreateTable().
65
  int doCreateTable(drizzled::Session &session,
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
66
                    drizzled::Table &table_arg,
1627.2.6 by Monty Taylor
Merged in constification of TableIdentifier from Brian.
67
                    const drizzled::TableIdentifier &identifier,
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
68
                    drizzled::message::Table &table_proto);
69
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
70
  int doRenameTable(drizzled::Session &session,
1627.2.6 by Monty Taylor
Merged in constification of TableIdentifier from Brian.
71
                    const drizzled::TableIdentifier &from_identifier,
72
                    const drizzled::TableIdentifier &to_identifier);
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
73
74
  int doDropTable(drizzled::Session &session,
1627.2.6 by Monty Taylor
Merged in constification of TableIdentifier from Brian.
75
                  const drizzled::TableIdentifier &identifier);
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
76
77
  int doGetTableDefinition(drizzled::Session &session,
1627.2.6 by Monty Taylor
Merged in constification of TableIdentifier from Brian.
78
                           const drizzled::TableIdentifier &identifier,
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
79
                           drizzled::message::Table &table_proto);
80
1239.3.97 by Toru Maesaka
Merged up to rev:1477. Supported StorageEngine::doGetTableIdentifiers().
81
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
1642 by Brian Aker
This adds const to SchemaIdentifier.
82
                             const drizzled::SchemaIdentifier &schema_identifier,
1239.3.97 by Toru Maesaka
Merged up to rev:1477. Supported StorageEngine::doGetTableIdentifiers().
83
                             drizzled::TableIdentifiers &set_of_identifiers);
84
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
85
  bool doDoesTableExist(drizzled::Session &session,
1627.2.6 by Monty Taylor
Merged in constification of TableIdentifier from Brian.
86
                        const drizzled::TableIdentifier &identifier);
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
87
1239.3.131 by Toru Maesaka
Implemented StorageEngine::validateCreateTableOption() in BlitzDB to extend the CREATE TABLE syntax.
88
  bool validateCreateTableOption(const std::string &key,
89
                                 const std::string &state);
90
1239.3.91 by Toru Maesaka
Encapsulated 'share' mechanism to BlitzEngine class.
91
  bool doCreateTableCache(void);
92
93
  BlitzShare *getTableShare(const std::string &name);
94
  void cacheTableShare(const std::string &name, BlitzShare *share);
95
  void deleteTableShare(const std::string &name);
96
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
97
  uint32_t max_supported_keys() const { return BLITZ_MAX_INDEX; }
98
  uint32_t max_supported_key_length() const { return BLITZ_MAX_KEY_LEN; }
99
  uint32_t max_supported_key_part_length() const { return BLITZ_MAX_KEY_LEN; }
100
101
  uint32_t index_flags(enum drizzled::ha_key_alg) const {
102
    return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER |
103
            HA_READ_RANGE | HA_ONLY_WHOLE_INDEX | HA_KEYREAD_ONLY);
104
  }
105
};
106
1239.3.48 by Toru Maesaka
Added more tests for index scan and DECIMAL type. B+Tree handling code is slightly slimmer now.
107
/* A key stored in BlitzDB's B+Tree is a byte array that also includes
108
   a key to that row in the data dictionary. Two keys are merged and
109
   stored as a key because we want to avoid reading the leaf node and
110
   thus save disk IO and some computation in the tree. Note that the
111
   comparison function of BlitzDB's btree only takes into accound the
112
   actual index key. See blitzcmp.cc for details.
113
114
   With the above in mind, this helper function returns a pointer to
115
   the dictionary key by calculating the offset. */
116
static char *skip_btree_key(const char *key, const size_t skip_len,
117
                            int *return_klen);
118
1239.3.131 by Toru Maesaka
Implemented StorageEngine::validateCreateTableOption() in BlitzDB to extend the CREATE TABLE syntax.
119
static bool str_is_numeric(const std::string &str);
120
1239.3.95 by Toru Maesaka
Supported the interface change for StorageEngine::doCreateTable().
121
int BlitzEngine::doCreateTable(drizzled::Session &,
1239.3.87 by Toru Maesaka
Merged up to rev:1375.
122
                               drizzled::Table &table,
1627.2.6 by Monty Taylor
Merged in constification of TableIdentifier from Brian.
123
                               const drizzled::TableIdentifier &identifier,
1239.3.32 by Toru Maesaka
Write the number of keys to TC's Meta Buffer on table creation. Made minor changes to BlitzTree's interface.
124
                               drizzled::message::Table &proto) {
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
125
  BlitzData dict;
1239.3.35 by Toru Maesaka
Made index file(s) droppable and renamable.
126
  BlitzTree btree;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
127
  int ecode;
128
1239.3.123 by Toru Maesaka
Return error on composite indexes at CREATE syntax. Added tests for it as well.
129
  /* Temporary fix for blocking composite keys. We need to add this
130
     check because version 1 doesn't handle composite indexes. */
131
  for (uint32_t i = 0; i < table.s->keys; i++) {
132
    if (table.key_info[i].key_parts > 1)
133
      return HA_ERR_UNSUPPORTED;
134
  }
135
1239.3.34 by Toru Maesaka
Separated the codebase for Data Dictionary and System Table. TC object is no longer exposed to the handler.
136
  /* Create relevant files for a new table and close them immediately.
137
     All we want to do here is somewhat like UNIX touch(1). */
1239.3.88 by Toru Maesaka
Minor cleanup and interface changes to suit the updated Drizzle Storage API.
138
  if ((ecode = dict.create_data_table(proto, table, identifier)) != 0)
1239.3.35 by Toru Maesaka
Made index file(s) droppable and renamable.
139
    return ecode;
1239.3.34 by Toru Maesaka
Separated the codebase for Data Dictionary and System Table. TC object is no longer exposed to the handler.
140
1239.3.88 by Toru Maesaka
Minor cleanup and interface changes to suit the updated Drizzle Storage API.
141
  if ((ecode = dict.create_system_table(identifier.getPath())) != 0)
1239.3.35 by Toru Maesaka
Made index file(s) droppable and renamable.
142
    return ecode;
143
144
  /* Create b+tree index(es) for this table. */
145
  for (uint32_t i = 0; i < table.s->keys; i++) {
1239.3.87 by Toru Maesaka
Merged up to rev:1375.
146
    if ((ecode = btree.create(identifier.getPath().c_str(), i)) != 0)
1239.3.35 by Toru Maesaka
Made index file(s) droppable and renamable.
147
      return ecode;
148
  }
1239.3.34 by Toru Maesaka
Separated the codebase for Data Dictionary and System Table. TC object is no longer exposed to the handler.
149
150
  /* Write the table definition to system table. */
1239.3.88 by Toru Maesaka
Minor cleanup and interface changes to suit the updated Drizzle Storage API.
151
  if ((ecode = dict.open_system_table(identifier.getPath(), HDBOWRITER)) != 0)
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
152
    return ecode;
1239.3.34 by Toru Maesaka
Separated the codebase for Data Dictionary and System Table. TC object is no longer exposed to the handler.
153
154
  if (!dict.write_table_definition(proto)) {
155
    dict.close_system_table();
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
156
    return HA_ERR_CRASHED_ON_USAGE;
157
  }
158
1239.3.34 by Toru Maesaka
Separated the codebase for Data Dictionary and System Table. TC object is no longer exposed to the handler.
159
  dict.close_system_table();
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
160
  return 0;
161
}
162
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
163
int BlitzEngine::doRenameTable(drizzled::Session &,
1627.2.6 by Monty Taylor
Merged in constification of TableIdentifier from Brian.
164
                               const drizzled::TableIdentifier &from,
165
                               const drizzled::TableIdentifier &to) {
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
166
  int rv = 0;
167
168
  BlitzData blitz_table;
169
  uint32_t nkeys;
170
171
  /* Find out the number of indexes in this table. This information
172
     is required because BlitzDB creates a file for each indexes.*/
173
  if (blitz_table.open_data_table(from.getPath().c_str(), HDBOREADER) != 0)
174
    return HA_ERR_CRASHED_ON_USAGE;
175
176
  nkeys = blitz_table.read_meta_keycount();
177
178
  if (blitz_table.close_data_table() != 0)
179
    return HA_ERR_CRASHED_ON_USAGE;
180
181
  /* We're now ready to rename the file(s) for this table. Start by
182
     attempting to rename the data and system files. */
183
  if (rename_file_ext(from.getPath().c_str(),
184
                      to.getPath().c_str(), BLITZ_DATA_EXT)) {
185
    if ((rv = errno) != ENOENT)
186
      return rv;
187
  }
188
189
  if (rename_file_ext(from.getPath().c_str(),
190
                      to.getPath().c_str(), BLITZ_SYSTEM_EXT)) {
191
    if ((rv = errno) != ENOENT)
192
      return rv;
193
  }
194
195
  /* So far so good. Rename the index file(s) and we're done. */
1239.3.35 by Toru Maesaka
Made index file(s) droppable and renamable.
196
  BlitzTree btree;
197
198
  for (uint32_t i = 0; i < nkeys; i++) {
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
199
    if (btree.rename(from.getPath().c_str(), to.getPath().c_str(), i) != 0)
200
      return HA_ERR_CRASHED_ON_USAGE;
1239.3.35 by Toru Maesaka
Made index file(s) droppable and renamable.
201
  }
202
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
203
  return rv;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
204
}
205
1239.3.87 by Toru Maesaka
Merged up to rev:1375.
206
int BlitzEngine::doDropTable(drizzled::Session &,
1627.2.6 by Monty Taylor
Merged in constification of TableIdentifier from Brian.
207
                             const drizzled::TableIdentifier &identifier) {
1239.3.35 by Toru Maesaka
Made index file(s) droppable and renamable.
208
  BlitzData dict;
209
  BlitzTree btree;
210
  char buf[FN_REFLEN];
211
  uint32_t nkeys;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
212
  int err;
1239.3.35 by Toru Maesaka
Made index file(s) droppable and renamable.
213
214
  /* We open the dictionary to extract meta data from it */
1239.3.88 by Toru Maesaka
Minor cleanup and interface changes to suit the updated Drizzle Storage API.
215
  if ((err = dict.open_data_table(identifier.getPath().c_str(),
216
                                  HDBOREADER)) != 0) {
1239.3.35 by Toru Maesaka
Made index file(s) droppable and renamable.
217
    return err;
1239.3.88 by Toru Maesaka
Minor cleanup and interface changes to suit the updated Drizzle Storage API.
218
  }
1239.3.35 by Toru Maesaka
Made index file(s) droppable and renamable.
219
220
  nkeys = dict.read_meta_keycount();
221
222
  /* We no longer need the dictionary to be open */
223
  dict.close_data_table();
224
225
  /* Drop the Data Dictionary */
1239.3.87 by Toru Maesaka
Merged up to rev:1375.
226
  snprintf(buf, FN_REFLEN, "%s%s", identifier.getPath().c_str(), BLITZ_DATA_EXT);
1239.3.35 by Toru Maesaka
Made index file(s) droppable and renamable.
227
  if ((err = unlink(buf)) == -1) {
228
    return err;
229
  }
230
231
  /* Drop the System Table */
1239.3.87 by Toru Maesaka
Merged up to rev:1375.
232
  snprintf(buf, FN_REFLEN, "%s%s", identifier.getPath().c_str(), BLITZ_SYSTEM_EXT);
1239.3.35 by Toru Maesaka
Made index file(s) droppable and renamable.
233
  if ((err = unlink(buf)) == -1) {
234
    return err;
235
  }
236
237
  /* Drop Index file(s) */
238
  for (uint32_t i = 0; i < nkeys; i++) {
1239.3.87 by Toru Maesaka
Merged up to rev:1375.
239
    if ((err = btree.drop(identifier.getPath().c_str(), i)) != 0) {
1239.3.35 by Toru Maesaka
Made index file(s) droppable and renamable.
240
      return err;
241
    }
242
  }
243
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
244
  return 0;
245
}
246
1239.3.87 by Toru Maesaka
Merged up to rev:1375.
247
int BlitzEngine::doGetTableDefinition(drizzled::Session &,
1627.2.6 by Monty Taylor
Merged in constification of TableIdentifier from Brian.
248
                                      const drizzled::TableIdentifier &identifier,
1239.3.86 by Toru Maesaka
Merged up to rev:1360. drizzled::TableIdentifier Support.
249
                                      drizzled::message::Table &proto) {
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
250
  struct stat stat_info;
1239.3.88 by Toru Maesaka
Minor cleanup and interface changes to suit the updated Drizzle Storage API.
251
  std::string path(identifier.getPath());
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
252
1239.3.88 by Toru Maesaka
Minor cleanup and interface changes to suit the updated Drizzle Storage API.
253
  path.append(BLITZ_SYSTEM_EXT);
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
254
1239.3.88 by Toru Maesaka
Minor cleanup and interface changes to suit the updated Drizzle Storage API.
255
  if (stat(path.c_str(), &stat_info)) {
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
256
    return errno;
257
  }
258
1239.3.86 by Toru Maesaka
Merged up to rev:1360. drizzled::TableIdentifier Support.
259
  BlitzData db;
260
  char *proto_string;
261
  int proto_string_len;
262
1239.3.88 by Toru Maesaka
Minor cleanup and interface changes to suit the updated Drizzle Storage API.
263
  if (db.open_system_table(identifier.getPath(), HDBOREADER) != 0) {
1239.3.86 by Toru Maesaka
Merged up to rev:1360. drizzled::TableIdentifier Support.
264
    return HA_ERR_CRASHED_ON_USAGE;
265
  }
266
267
  proto_string = db.get_system_entry(BLITZ_TABLE_PROTO_KEY.c_str(),
268
                                     BLITZ_TABLE_PROTO_KEY.length(),
269
                                     &proto_string_len);
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
270
1239.3.86 by Toru Maesaka
Merged up to rev:1360. drizzled::TableIdentifier Support.
271
  if (db.close_system_table() != 0) {
272
    return HA_ERR_CRASHED_ON_USAGE;
273
  }
274
275
  if (proto_string == NULL) {
276
    return ENOMEM;
277
  }
278
279
  if (!proto.ParseFromArray(proto_string, proto_string_len)) {
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
280
    free(proto_string);
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
281
    return HA_ERR_CRASHED_ON_USAGE;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
282
  }
1239.3.34 by Toru Maesaka
Separated the codebase for Data Dictionary and System Table. TC object is no longer exposed to the handler.
283
1239.3.86 by Toru Maesaka
Merged up to rev:1360. drizzled::TableIdentifier Support.
284
  free(proto_string);
285
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
286
  return EEXIST;
287
}
288
1239.3.97 by Toru Maesaka
Merged up to rev:1477. Supported StorageEngine::doGetTableIdentifiers().
289
void BlitzEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
1642 by Brian Aker
This adds const to SchemaIdentifier.
290
                                        const drizzled::SchemaIdentifier &schema_id,
1239.3.97 by Toru Maesaka
Merged up to rev:1477. Supported StorageEngine::doGetTableIdentifiers().
291
                                        drizzled::TableIdentifiers &ids) {
292
  drizzled::CachedDirectory::Entries entries = directory.getEntries();
293
294
  for (drizzled::CachedDirectory::Entries::iterator entry_iter = entries.begin();
295
       entry_iter != entries.end(); ++entry_iter) {
296
297
    drizzled::CachedDirectory::Entry *entry = *entry_iter;
298
    const std::string *filename = &entry->filename;
299
300
    assert(filename->size());
301
302
    const char *ext = strchr(filename->c_str(), '.');
303
1239.3.99 by Toru Maesaka
Fixed a 'show tables' problem due to a bug in BlitzEngine::doGetTableIdentifiers(). Also added tests for this bug.
304
    if (ext == NULL || my_strcasecmp(system_charset_info, ext, BLITZ_SYSTEM_EXT) ||
1239.3.97 by Toru Maesaka
Merged up to rev:1477. Supported StorageEngine::doGetTableIdentifiers().
305
        (filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0)) {
306
    } else {
307
      char uname[NAME_LEN + 1];
308
      uint32_t file_name_len;
309
1239.3.124 by Toru Maesaka
Merged Drizzle's Trunk.
310
      file_name_len = TableIdentifier::filename_to_tablename(filename->c_str(),
311
                                                             uname,
312
                                                             sizeof(uname));
1239.3.97 by Toru Maesaka
Merged up to rev:1477. Supported StorageEngine::doGetTableIdentifiers().
313
314
      uname[file_name_len - sizeof(BLITZ_DATA_EXT) + 1]= '\0';
315
      ids.push_back(TableIdentifier(schema_id, uname));
316
    }
317
  }
318
}
319
1239.3.86 by Toru Maesaka
Merged up to rev:1360. drizzled::TableIdentifier Support.
320
bool BlitzEngine::doDoesTableExist(drizzled::Session &,
1627.2.6 by Monty Taylor
Merged in constification of TableIdentifier from Brian.
321
                                   const drizzled::TableIdentifier &identifier) {
1239.3.86 by Toru Maesaka
Merged up to rev:1360. drizzled::TableIdentifier Support.
322
  std::string proto_path(identifier.getPath());
323
  proto_path.append(BLITZ_DATA_EXT);
324
325
  return (access(proto_path.c_str(), F_OK)) ? false : true;
326
}
327
1239.3.131 by Toru Maesaka
Implemented StorageEngine::validateCreateTableOption() in BlitzDB to extend the CREATE TABLE syntax.
328
bool BlitzEngine::validateCreateTableOption(const std::string &key,
329
                                            const std::string &state) {
330
  if (key == "ESTIMATED_ROWS" || key == "estimated_rows") {
331
    if (str_is_numeric(state))
332
      return true;
333
  }
334
  return false;
335
}
336
1239.3.91 by Toru Maesaka
Encapsulated 'share' mechanism to BlitzEngine class.
337
bool BlitzEngine::doCreateTableCache(void) {
338
  return ((blitz_table_cache = tcmapnew()) == NULL) ? false : true;
339
}
340
341
BlitzShare *BlitzEngine::getTableShare(const std::string &table_name) {
342
  int vlen;
343
  const void *fetched;
344
  BlitzShare *rv = NULL;
345
346
  fetched = tcmapget(blitz_table_cache, table_name.c_str(),
347
                     table_name.length(), &vlen);
348
349
  /* dereference the object */
350
  if (fetched)
351
    rv = *(BlitzShare **)fetched;
352
353
  return rv;
354
}
355
356
void BlitzEngine::cacheTableShare(const std::string &table_name,
357
                                  BlitzShare *share) {
358
  /* Cache the memory address of the share object */
359
  tcmapput(blitz_table_cache, table_name.c_str(), table_name.length(),
360
           &share, sizeof(share));
361
}
362
363
void BlitzEngine::deleteTableShare(const std::string &table_name) {
364
  tcmapout2(blitz_table_cache, table_name.c_str());
365
}
1239.3.86 by Toru Maesaka
Merged up to rev:1360. drizzled::TableIdentifier Support.
366
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
367
ha_blitz::ha_blitz(drizzled::plugin::StorageEngine &engine_arg,
368
                   TableShare &table_arg) : Cursor(engine_arg, table_arg),
1239.3.106 by Toru Maesaka
First step in splitting BlitzTree's cursor object.
369
                                            btree_cursor(NULL),
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
370
                                            table_scan(false),
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
371
                                            table_based(false),
1239.3.31 by Toru Maesaka
Use TC's Meta Buffer for storing auto increment value instead of the system table. Fixed a valgrind warning too.
372
                                            thread_locked(false),
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
373
                                            held_key(NULL),
374
                                            held_key_len(0),
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
375
                                            current_key(NULL),
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
376
                                            current_key_len(0),
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
377
                                            key_buffer(NULL),
1239.3.13 by Toru Maesaka
Added basic index key handling. Started working on PRIMARY KEY support and added tests for it.
378
                                            errkey_id(0) {}
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
379
380
int ha_blitz::open(const char *table_name, int, uint32_t) {
381
  if ((share = get_share(table_name)) == NULL)
382
    return HA_ERR_CRASHED_ON_USAGE;
383
384
  pthread_mutex_lock(&blitz_utility_mutex);
385
1239.3.113 by Toru Maesaka
Improved cursor resource management. TC's cursor allocation only happens once per worker now.
386
  btree_cursor = new BlitzCursor[share->nkeys];
387
388
  for (uint32_t i = 0; i < share->nkeys; i++) {
389
    if (!share->btrees[i].create_cursor(&btree_cursor[i])) {
390
      free_share();
391
      pthread_mutex_unlock(&blitz_utility_mutex);
392
      return HA_ERR_OUT_OF_MEM;
393
    }
394
  }
395
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
396
  if ((key_buffer = (char *)malloc(BLITZ_MAX_KEY_LEN)) == NULL) {
1239.3.90 by Toru Maesaka
free_share() is now a member of Cursor::ha_blitz.
397
    free_share();
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
398
    pthread_mutex_unlock(&blitz_utility_mutex);
399
    return HA_ERR_OUT_OF_MEM;
400
  }
401
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
402
  if ((key_merge_buffer = (char *)malloc(BLITZ_MAX_KEY_LEN)) == NULL) {
1239.3.90 by Toru Maesaka
free_share() is now a member of Cursor::ha_blitz.
403
    free_share();
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
404
    pthread_mutex_unlock(&blitz_utility_mutex);
405
    return HA_ERR_OUT_OF_MEM;
406
  }
407
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
408
  if ((held_key_buf = (char *)malloc(BLITZ_MAX_KEY_LEN)) == NULL) {
1239.3.90 by Toru Maesaka
free_share() is now a member of Cursor::ha_blitz.
409
    free_share();
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
410
    free(key_buffer);
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
411
    free(key_merge_buffer);
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
412
    pthread_mutex_unlock(&blitz_utility_mutex);
413
    return HA_ERR_OUT_OF_MEM;
414
  }
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
415
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
416
  secondary_row_buffer = NULL;
417
  secondary_row_buffer_size = 0;
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
418
  key_merge_buffer_len = BLITZ_MAX_KEY_LEN;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
419
1239.3.29 by Toru Maesaka
Added UNIQUE constraint check on fixed length fields and more tests. Moved get_share() to ha_blitz class.
420
  /* 'ref_length' determines the size of the buffer that the kernel
421
     will use to uniquely identify a row. The actual allocation is
422
     done by the kernel so all we do here is specify the size of it.*/
423
  if (share->primary_key_exists) {
1239.3.124 by Toru Maesaka
Merged Drizzle's Trunk.
424
    ref_length = table->key_info[table->s->getPrimaryKey()].key_length;
1239.3.29 by Toru Maesaka
Added UNIQUE constraint check on fixed length fields and more tests. Moved get_share() to ha_blitz class.
425
  } else {
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
426
    ref_length = sizeof(held_key_len) + sizeof(uint64_t);
1239.3.4 by Toru Maesaka
Reworked position() and rnd_pos(). Started reworking update_row() for UPDATES with ORDER BY.
427
  }
428
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
429
  pthread_mutex_unlock(&blitz_utility_mutex);
430
  return 0;
431
}
432
433
int ha_blitz::close(void) {
1239.3.113 by Toru Maesaka
Improved cursor resource management. TC's cursor allocation only happens once per worker now.
434
  for (uint32_t i = 0; i < share->nkeys; i++) {
435
    share->btrees[i].destroy_cursor(&btree_cursor[i]);
436
  }
437
  delete [] btree_cursor;
438
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
439
  free(key_buffer);
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
440
  free(key_merge_buffer);
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
441
  free(held_key_buf);
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
442
  free(secondary_row_buffer);
1239.3.90 by Toru Maesaka
free_share() is now a member of Cursor::ha_blitz.
443
  return free_share();
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
444
}
445
446
int ha_blitz::info(uint32_t flag) {
1239.3.19 by Toru Maesaka
Removed all thr_lock related code. Supported primary key based deletion and added a test for it.
447
  if (flag & HA_STATUS_VARIABLE) {
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
448
    stats.records = share->dict.nrecords();
1239.3.19 by Toru Maesaka
Removed all thr_lock related code. Supported primary key based deletion and added a test for it.
449
    stats.data_file_length = share->dict.table_size();
450
  }
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
451
1239.3.22 by Toru Maesaka
Added Auto Increment support on INSERT and tests for it. Nextup: UPDATE.
452
  if (flag & HA_STATUS_AUTO)
1239.3.120 by Toru Maesaka
Protected Drizzle's update_auto_increment() with a lock. In the future this may become thread safe.
453
    stats.auto_increment_value = share->auto_increment_value + 1;
1239.3.22 by Toru Maesaka
Added Auto Increment support on INSERT and tests for it. Nextup: UPDATE.
454
1239.3.13 by Toru Maesaka
Added basic index key handling. Started working on PRIMARY KEY support and added tests for it.
455
  if (flag & HA_STATUS_ERRKEY)
456
    errkey = errkey_id;
457
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
458
  return 0;
459
}
460
1239.3.105 by Toru Maesaka
Merged Drizzle's Trunk.
461
int ha_blitz::doStartTableScan(bool scan) {
1239.3.116 by Toru Maesaka
Merged Drizzle's Trunk.
462
  /* Obtain the query type for this scan */
1239.3.125 by Toru Maesaka
BlitzDB no longer uses current_session directly. Cleaned up the author file. Acknowledgement file will be added for simplicity.
463
  sql_command_type = session_sql_command(table->getSession());
1239.3.9 by Toru Maesaka
Remove store_lock() because BlitzDB does it's own concurrency control.
464
  table_scan = scan;
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
465
  table_based = true;
1239.3.9 by Toru Maesaka
Remove store_lock() because BlitzDB does it's own concurrency control.
466
1239.3.116 by Toru Maesaka
Merged Drizzle's Trunk.
467
  /* Obtain the most suitable lock for the given statement type. */
1239.3.127 by Toru Maesaka
Added more index related tests and renamed BlitzDB's lock functions.
468
  blitz_optimal_lock();
1239.3.5 by Toru Maesaka
Supported UPDATEs with ORDER BY and added a test for it.
469
1239.3.4 by Toru Maesaka
Reworked position() and rnd_pos(). Started reworking update_row() for UPDATES with ORDER BY.
470
  /* Get the first record from TCHDB. Let the scanner take
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
471
     care of checking return value errors. */
1239.3.5 by Toru Maesaka
Supported UPDATEs with ORDER BY and added a test for it.
472
  if (table_scan) {
1239.3.4 by Toru Maesaka
Reworked position() and rnd_pos(). Started reworking update_row() for UPDATES with ORDER BY.
473
    current_key = share->dict.next_key_and_row(NULL, 0,
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
474
                                               &current_key_len,
1239.3.4 by Toru Maesaka
Reworked position() and rnd_pos(). Started reworking update_row() for UPDATES with ORDER BY.
475
                                               &current_row,
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
476
                                               &current_row_len);
1239.3.4 by Toru Maesaka
Reworked position() and rnd_pos(). Started reworking update_row() for UPDATES with ORDER BY.
477
  }
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
478
  return 0;
479
}
480
481
int ha_blitz::rnd_next(unsigned char *drizzle_buf) {
482
  char *next_key;
483
  const char *next_row;
1239.3.26 by Toru Maesaka
Fixed the bug on tables with only 1 row and added a new test file for testing JOIN operations.
484
  int next_row_len;
485
  int next_key_len;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
486
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
487
  free(held_key);
488
  held_key = NULL;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
489
1239.3.26 by Toru Maesaka
Fixed the bug on tables with only 1 row and added a new test file for testing JOIN operations.
490
  if (current_key == NULL) {
491
    table->status = STATUS_NOT_FOUND;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
492
    return HA_ERR_END_OF_FILE;
1239.3.26 by Toru Maesaka
Fixed the bug on tables with only 1 row and added a new test file for testing JOIN operations.
493
  }
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
494
1239.3.59 by Stewart Smith
BlitzDB build fixes for drizzle changes: system status variable and DRIZZLE_PLUGIN
495
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
1239.3.8 by Toru Maesaka
Remove redundant calculation in row packing mechanism.
496
1239.3.23 by Toru Maesaka
Supported VARCHAR to be usable as index key(s). Also added basic tests where VARCHAR is used as PK.
497
  /* Unpack and copy the current row to Drizzle's result buffer. */
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
498
  unpack_row(drizzle_buf, current_row, current_row_len);
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
499
1239.3.23 by Toru Maesaka
Supported VARCHAR to be usable as index key(s). Also added basic tests where VARCHAR is used as PK.
500
  /* Retrieve both key and row of the next record with one allocation. */
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
501
  next_key = share->dict.next_key_and_row(current_key, current_key_len,
1239.3.26 by Toru Maesaka
Fixed the bug on tables with only 1 row and added a new test file for testing JOIN operations.
502
                                          &next_key_len, &next_row,
503
                                          &next_row_len);
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
504
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
505
  /* Memory region for "current_row" will be freed as "held key" on
506
     the next iteration. This is because "current_key" points to the
507
     region of memory that contains "current_row" and "held_key" points
1239.3.105 by Toru Maesaka
Merged Drizzle's Trunk.
508
     to it. If there isn't another iteration then it is freed in doEndTableScan(). */
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
509
  current_row = next_row;
1239.3.26 by Toru Maesaka
Fixed the bug on tables with only 1 row and added a new test file for testing JOIN operations.
510
  current_row_len = next_row_len;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
511
512
  /* Remember the current row because delete, update or replace
513
     function could be called after this function. This pointer is
514
     also used to free the previous key and row, which resides on
515
     the same buffer. */
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
516
  held_key = current_key;
517
  held_key_len = current_key_len;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
518
519
  /* It is now memory-leak-safe to point current_key to next_key. */
520
  current_key = next_key;
1239.3.26 by Toru Maesaka
Fixed the bug on tables with only 1 row and added a new test file for testing JOIN operations.
521
  current_key_len = next_key_len;
522
  table->status = 0;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
523
  return 0;
524
}
525
1239.3.105 by Toru Maesaka
Merged Drizzle's Trunk.
526
int ha_blitz::doEndTableScan() {
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
527
  if (table_scan && current_key)
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
528
    free(current_key);
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
529
  if (table_scan && held_key)
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
530
    free(held_key);
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
531
532
  current_key = NULL;
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
533
  held_key = NULL;
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
534
  current_key_len = 0;
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
535
  held_key_len = 0;
1239.3.4 by Toru Maesaka
Reworked position() and rnd_pos(). Started reworking update_row() for UPDATES with ORDER BY.
536
  table_scan = false;
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
537
  table_based = false;
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
538
1239.3.4 by Toru Maesaka
Reworked position() and rnd_pos(). Started reworking update_row() for UPDATES with ORDER BY.
539
  if (thread_locked)
1239.3.127 by Toru Maesaka
Added more index related tests and renamed BlitzDB's lock functions.
540
    blitz_optimal_unlock();
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
541
542
  return 0;
543
}
544
1239.3.3 by Toru Maesaka
Catch up with Drizzle's Storage API and started reworking position() and rnd_pos().
545
int ha_blitz::rnd_pos(unsigned char *copy_to, unsigned char *pos) {
546
  char *row;
547
  char *key = NULL;
1239.3.26 by Toru Maesaka
Fixed the bug on tables with only 1 row and added a new test file for testing JOIN operations.
548
  int key_len, row_len;
1239.3.3 by Toru Maesaka
Catch up with Drizzle's Storage API and started reworking position() and rnd_pos().
549
1239.3.26 by Toru Maesaka
Fixed the bug on tables with only 1 row and added a new test file for testing JOIN operations.
550
  memcpy(&key_len, pos, sizeof(key_len));
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
551
  key = (char *)(pos + sizeof(key_len));
1239.3.3 by Toru Maesaka
Catch up with Drizzle's Storage API and started reworking position() and rnd_pos().
552
553
  /* TODO: Find a better error type. */
554
  if (key == NULL)
555
    return HA_ERR_KEY_NOT_FOUND;
556
1239.3.26 by Toru Maesaka
Fixed the bug on tables with only 1 row and added a new test file for testing JOIN operations.
557
  row = share->dict.get_row(key, key_len, &row_len);
1239.3.3 by Toru Maesaka
Catch up with Drizzle's Storage API and started reworking position() and rnd_pos().
558
559
  if (row == NULL)
560
    return HA_ERR_KEY_NOT_FOUND;
561
1239.3.26 by Toru Maesaka
Fixed the bug on tables with only 1 row and added a new test file for testing JOIN operations.
562
  unpack_row(copy_to, row, row_len);
1239.3.5 by Toru Maesaka
Supported UPDATEs with ORDER BY and added a test for it.
563
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
564
  /* Remember the key location on memory if the thread is not doing
565
     a table scan. This is because either update_row() or delete_row()
566
     might be called after this function. */
1239.3.5 by Toru Maesaka
Supported UPDATEs with ORDER BY and added a test for it.
567
  if (!table_scan) {
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
568
    held_key = key;
569
    held_key_len = key_len;
1239.3.5 by Toru Maesaka
Supported UPDATEs with ORDER BY and added a test for it.
570
  }
571
1239.3.3 by Toru Maesaka
Catch up with Drizzle's Storage API and started reworking position() and rnd_pos().
572
  free(row);
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
573
  return 0;
574
}
575
576
void ha_blitz::position(const unsigned char *) {
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
577
  int length = sizeof(held_key_len);
578
  memcpy(ref, &held_key_len, length);
579
  memcpy(ref + length, (unsigned char *)held_key, held_key_len);
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
580
}
581
1239.3.46 by Toru Maesaka
Provided TC's B+Tree cursor object to each individual BlitzTree classes.
582
const char *ha_blitz::index_type(uint32_t /*key_num*/) {
583
  return "BTREE";
1239.3.17 by Toru Maesaka
Implemented index_read() and index_read_idx() for PK and added a simple needle in a haystack test.
584
}
585
1239.3.105 by Toru Maesaka
Merged Drizzle's Trunk.
586
int ha_blitz::doStartIndexScan(uint32_t key_num, bool) {
1239.3.17 by Toru Maesaka
Implemented index_read() and index_read_idx() for PK and added a simple needle in a haystack test.
587
  active_index = key_num;
1239.3.125 by Toru Maesaka
BlitzDB no longer uses current_session directly. Cleaned up the author file. Acknowledgement file will be added for simplicity.
588
  sql_command_type = session_sql_command(table->getSession());
1239.3.17 by Toru Maesaka
Implemented index_read() and index_read_idx() for PK and added a simple needle in a haystack test.
589
590
  /* This is unlikely to happen but just for assurance, re-obtain
591
     the lock if this thread already has a certain lock. This makes
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
592
     sure that this thread will get the most appropriate lock for
593
     the current statement. */
1239.3.17 by Toru Maesaka
Implemented index_read() and index_read_idx() for PK and added a simple needle in a haystack test.
594
  if (thread_locked)
1239.3.127 by Toru Maesaka
Added more index related tests and renamed BlitzDB's lock functions.
595
    blitz_optimal_unlock();
1239.3.17 by Toru Maesaka
Implemented index_read() and index_read_idx() for PK and added a simple needle in a haystack test.
596
1239.3.127 by Toru Maesaka
Added more index related tests and renamed BlitzDB's lock functions.
597
  blitz_optimal_lock();
1239.3.16 by Toru Maesaka
Added index_init() and index_first() for Primary Keys.
598
  return 0;
599
}
600
601
int ha_blitz::index_first(unsigned char *buf) {
1239.3.48 by Toru Maesaka
Added more tests for index scan and DECIMAL type. B+Tree handling code is slightly slimmer now.
602
  char *dict_key, *bt_key, *row;
603
  int dict_klen, bt_klen, prefix_len, rlen;
604
1239.3.113 by Toru Maesaka
Improved cursor resource management. TC's cursor allocation only happens once per worker now.
605
  bt_key = btree_cursor[active_index].first_key(&bt_klen);
1239.3.48 by Toru Maesaka
Added more tests for index scan and DECIMAL type. B+Tree handling code is slightly slimmer now.
606
607
  if (bt_key == NULL)
1239.3.51 by Toru Maesaka
Added more tests to BlitzDB's test suite.
608
    return HA_ERR_END_OF_FILE;
1239.3.47 by Toru Maesaka
Implemented forward index scan and basic tests for it. More tests to come.
609
1239.3.48 by Toru Maesaka
Added more tests for index scan and DECIMAL type. B+Tree handling code is slightly slimmer now.
610
  prefix_len = btree_key_length(bt_key, active_index);
611
  dict_key = skip_btree_key(bt_key, prefix_len, &dict_klen);
612
613
  if ((row = share->dict.get_row(dict_key, dict_klen, &rlen)) == NULL) {
614
    free(bt_key);
1239.3.47 by Toru Maesaka
Implemented forward index scan and basic tests for it. More tests to come.
615
    return HA_ERR_KEY_NOT_FOUND;
616
  }
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
617
1239.3.47 by Toru Maesaka
Implemented forward index scan and basic tests for it. More tests to come.
618
  unpack_row(buf, row, rlen);
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
619
  keep_track_of_key(bt_key, bt_klen);
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
620
1239.3.48 by Toru Maesaka
Added more tests for index scan and DECIMAL type. B+Tree handling code is slightly slimmer now.
621
  free(bt_key);
1239.3.47 by Toru Maesaka
Implemented forward index scan and basic tests for it. More tests to come.
622
  free(row);
623
  return 0;
624
}
625
626
int ha_blitz::index_next(unsigned char *buf) {
1239.3.48 by Toru Maesaka
Added more tests for index scan and DECIMAL type. B+Tree handling code is slightly slimmer now.
627
  char *dict_key, *bt_key, *row;
628
  int dict_klen, bt_klen, prefix_len, rlen;
629
1239.3.113 by Toru Maesaka
Improved cursor resource management. TC's cursor allocation only happens once per worker now.
630
  bt_key = btree_cursor[active_index].next_key(&bt_klen);
1239.3.48 by Toru Maesaka
Added more tests for index scan and DECIMAL type. B+Tree handling code is slightly slimmer now.
631
1239.3.78 by Toru Maesaka
ha_blitz::records_in_range() can now return the real number of keys if min and max keys are both provided.
632
  if (bt_key == NULL) {
633
    table->status = STATUS_NOT_FOUND;
1239.3.51 by Toru Maesaka
Added more tests to BlitzDB's test suite.
634
    return HA_ERR_END_OF_FILE;
1239.3.78 by Toru Maesaka
ha_blitz::records_in_range() can now return the real number of keys if min and max keys are both provided.
635
  }
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
636
1239.3.48 by Toru Maesaka
Added more tests for index scan and DECIMAL type. B+Tree handling code is slightly slimmer now.
637
  prefix_len = btree_key_length(bt_key, active_index);
638
  dict_key = skip_btree_key(bt_key, prefix_len, &dict_klen);
639
640
  if ((row = share->dict.get_row(dict_key, dict_klen, &rlen)) == NULL) {
641
    free(bt_key);
1239.3.78 by Toru Maesaka
ha_blitz::records_in_range() can now return the real number of keys if min and max keys are both provided.
642
    table->status = STATUS_NOT_FOUND;
1239.3.47 by Toru Maesaka
Implemented forward index scan and basic tests for it. More tests to come.
643
    return HA_ERR_KEY_NOT_FOUND;
644
  }
645
646
  unpack_row(buf, row, rlen);
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
647
  keep_track_of_key(bt_key, bt_klen);
1239.3.47 by Toru Maesaka
Implemented forward index scan and basic tests for it. More tests to come.
648
1239.3.48 by Toru Maesaka
Added more tests for index scan and DECIMAL type. B+Tree handling code is slightly slimmer now.
649
  free(bt_key);
1239.3.47 by Toru Maesaka
Implemented forward index scan and basic tests for it. More tests to come.
650
  free(row);
651
  return 0;
1239.3.16 by Toru Maesaka
Added index_init() and index_first() for Primary Keys.
652
}
653
1239.3.50 by Toru Maesaka
Implemented reverse index scan and added tests for it. Fixed a bug in delete_all_rows().
654
int ha_blitz::index_prev(unsigned char *buf) {
655
  char *dict_key, *bt_key, *row;
656
  int dict_klen, bt_klen, prefix_len, rlen;
657
1239.3.113 by Toru Maesaka
Improved cursor resource management. TC's cursor allocation only happens once per worker now.
658
  bt_key = btree_cursor[active_index].prev_key(&bt_klen);
1239.3.50 by Toru Maesaka
Implemented reverse index scan and added tests for it. Fixed a bug in delete_all_rows().
659
660
  if (bt_key == NULL)
1239.3.83 by Toru Maesaka
Supported HA_READ_BEFORE_KEY by adding BlitzTree::prev_logical_key(). This allows BlitzDB to properly run a reverse index scan. Tests are added as well.
661
    return HA_ERR_END_OF_FILE;
1239.3.50 by Toru Maesaka
Implemented reverse index scan and added tests for it. Fixed a bug in delete_all_rows().
662
663
  prefix_len = btree_key_length(bt_key, active_index);
664
  dict_key = skip_btree_key(bt_key, prefix_len, &dict_klen);
665
666
  if ((row = share->dict.get_row(dict_key, dict_klen, &rlen)) == NULL) {
667
    free(bt_key);
668
    return HA_ERR_KEY_NOT_FOUND;
669
  }
670
671
  unpack_row(buf, row, rlen);
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
672
  keep_track_of_key(bt_key, bt_klen);
1239.3.50 by Toru Maesaka
Implemented reverse index scan and added tests for it. Fixed a bug in delete_all_rows().
673
674
  free(bt_key);
675
  free(row);
676
  return 0;
677
}
678
679
int ha_blitz::index_last(unsigned char *buf) {
680
  char *dict_key, *bt_key, *row;
681
  int dict_klen, bt_klen, prefix_len, rlen;
682
1239.3.113 by Toru Maesaka
Improved cursor resource management. TC's cursor allocation only happens once per worker now.
683
  bt_key = btree_cursor[active_index].final_key(&bt_klen);
1239.3.50 by Toru Maesaka
Implemented reverse index scan and added tests for it. Fixed a bug in delete_all_rows().
684
685
  if (bt_key == NULL)
686
    return HA_ERR_KEY_NOT_FOUND;
687
688
  prefix_len = btree_key_length(bt_key, active_index);
689
  dict_key = skip_btree_key(bt_key, prefix_len, &dict_klen);
690
691
  if ((row = share->dict.get_row(dict_key, dict_klen, &rlen)) == NULL) {
692
    free(bt_key);
1239.3.51 by Toru Maesaka
Added more tests to BlitzDB's test suite.
693
    errkey_id = active_index;
1239.3.50 by Toru Maesaka
Implemented reverse index scan and added tests for it. Fixed a bug in delete_all_rows().
694
    return HA_ERR_KEY_NOT_FOUND;
695
  }
696
697
  unpack_row(buf, row, rlen);
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
698
  keep_track_of_key(bt_key, bt_klen);
1239.3.50 by Toru Maesaka
Implemented reverse index scan and added tests for it. Fixed a bug in delete_all_rows().
699
700
  free(bt_key);
701
  free(row);
702
  return 0;
703
}
704
1239.3.17 by Toru Maesaka
Implemented index_read() and index_read_idx() for PK and added a simple needle in a haystack test.
705
int ha_blitz::index_read(unsigned char *buf, const unsigned char *key,
706
                         uint32_t key_len, enum ha_rkey_function find_flag) {
1239.3.54 by Toru Maesaka
Supported secondary index insertion, Added meta information on the B+Tree cursor and some tests.
707
  return index_read_idx(buf, active_index, key, key_len, find_flag);
1239.3.17 by Toru Maesaka
Implemented index_read() and index_read_idx() for PK and added a simple needle in a haystack test.
708
}
709
710
/* This is where the read related index logic lives. It is used by both
711
   BlitzDB and the Database Kernel (specifically, by the optimizer). */
712
int ha_blitz::index_read_idx(unsigned char *buf, uint32_t key_num,
1239.3.62 by Toru Maesaka
More work on NULLable keys. Supported direct B+Tree lookup and added tests for it.
713
                             const unsigned char *key, uint32_t,
1239.3.80 by Toru Maesaka
First step to make BlitzTree::find_key() respect ha_rkey_function enumerators.
714
                             enum ha_rkey_function search_mode) {
1239.3.66 by Toru Maesaka
Started working on completing ha_blitz::delete_row(). Refactored index_read_idx() to suit the new comparator. Index update tests are disabled until ha_blitz::update_row() is completed.
715
716
  /* If the provided key is NULL, we are required to return the first
717
     row in the active_index. */
718
  if (key == NULL)
719
    return this->index_first(buf);
720
721
  /* Otherwise we search for it. Prepare the key to look up the tree. */
722
  int packed_klen;
723
  char *packed_key = native_to_blitz_key(key, key_num, &packed_klen);
724
725
  /* Lookup the tree and get the master key. */
726
  int unique_klen;
1239.3.109 by Toru Maesaka
Still not optimal but the cursor object is now separated between workers. This build survived sysbench's read-only OLTP test.
727
  char *unique_key;
728
1239.3.113 by Toru Maesaka
Improved cursor resource management. TC's cursor allocation only happens once per worker now.
729
  unique_key = btree_cursor[key_num].find_key(search_mode, packed_key,
730
                                              packed_klen, &unique_klen);
1239.3.109 by Toru Maesaka
Still not optimal but the cursor object is now separated between workers. This build survived sysbench's read-only OLTP test.
731
1239.3.66 by Toru Maesaka
Started working on completing ha_blitz::delete_row(). Refactored index_read_idx() to suit the new comparator. Index update tests are disabled until ha_blitz::update_row() is completed.
732
  if (unique_key == NULL) {
733
    errkey_id = key_num;
734
    return HA_ERR_KEY_NOT_FOUND;
1239.3.17 by Toru Maesaka
Implemented index_read() and index_read_idx() for PK and added a simple needle in a haystack test.
735
  }
736
1239.3.66 by Toru Maesaka
Started working on completing ha_blitz::delete_row(). Refactored index_read_idx() to suit the new comparator. Index update tests are disabled until ha_blitz::update_row() is completed.
737
  /* Got the master key. Prepare it to lookup the data dictionary. */
738
  int dict_klen;
739
  int skip_len = btree_key_length(unique_key, key_num);
740
  char *dict_key = skip_btree_key(unique_key, skip_len, &dict_klen);
741
742
  /* Fetch the packed row from the data dictionary. */
743
  int row_len;
744
  char *fetched_row = share->dict.get_row(dict_key, dict_klen, &row_len);
745
1239.3.51 by Toru Maesaka
Added more tests to BlitzDB's test suite.
746
  if (fetched_row == NULL) {
747
    errkey_id = key_num;
1239.3.67 by Toru Maesaka
Reduced allocation costs for creating a B+Tree cursor. TC's cursor object now has a same lifespan as the ha_blitz object.
748
    free(unique_key);
1239.3.45 by Toru Maesaka
Optimized key generation (much leaner keys). Wrote a workaround for a HA_KEYTYPE_VARTEXT1 bug in Drizzle's Field_varstring. Added tests for a VARCHAR field less than 255 bytes.
749
    return HA_ERR_KEY_NOT_FOUND;
1239.3.51 by Toru Maesaka
Added more tests to BlitzDB's test suite.
750
  }
1239.3.45 by Toru Maesaka
Optimized key generation (much leaner keys). Wrote a workaround for a HA_KEYTYPE_VARTEXT1 bug in Drizzle's Field_varstring. Added tests for a VARCHAR field less than 255 bytes.
751
1239.3.66 by Toru Maesaka
Started working on completing ha_blitz::delete_row(). Refactored index_read_idx() to suit the new comparator. Index update tests are disabled until ha_blitz::update_row() is completed.
752
  /* Unpack it into Drizzle's return buffer and keep track of the
753
     master key for future use (before index_end() is called). */
1239.3.45 by Toru Maesaka
Optimized key generation (much leaner keys). Wrote a workaround for a HA_KEYTYPE_VARTEXT1 bug in Drizzle's Field_varstring. Added tests for a VARCHAR field less than 255 bytes.
754
  unpack_row(buf, fetched_row, row_len);
1239.3.66 by Toru Maesaka
Started working on completing ha_blitz::delete_row(). Refactored index_read_idx() to suit the new comparator. Index update tests are disabled until ha_blitz::update_row() is completed.
755
  keep_track_of_key(unique_key, unique_klen);
1239.3.45 by Toru Maesaka
Optimized key generation (much leaner keys). Wrote a workaround for a HA_KEYTYPE_VARTEXT1 bug in Drizzle's Field_varstring. Added tests for a VARCHAR field less than 255 bytes.
756
1239.3.67 by Toru Maesaka
Reduced allocation costs for creating a B+Tree cursor. TC's cursor object now has a same lifespan as the ha_blitz object.
757
  free(unique_key);
1239.3.45 by Toru Maesaka
Optimized key generation (much leaner keys). Wrote a workaround for a HA_KEYTYPE_VARTEXT1 bug in Drizzle's Field_varstring. Added tests for a VARCHAR field less than 255 bytes.
758
  free(fetched_row);
759
  return 0;
1239.3.17 by Toru Maesaka
Implemented index_read() and index_read_idx() for PK and added a simple needle in a haystack test.
760
}
761
1239.3.105 by Toru Maesaka
Merged Drizzle's Trunk.
762
int ha_blitz::doEndIndexScan(void) {
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
763
  held_key = NULL;
764
  held_key_len = 0;
1239.3.17 by Toru Maesaka
Implemented index_read() and index_read_idx() for PK and added a simple needle in a haystack test.
765
1239.3.113 by Toru Maesaka
Improved cursor resource management. TC's cursor allocation only happens once per worker now.
766
  btree_cursor[active_index].moved = false;
1239.3.106 by Toru Maesaka
First step in splitting BlitzTree's cursor object.
767
1239.3.17 by Toru Maesaka
Implemented index_read() and index_read_idx() for PK and added a simple needle in a haystack test.
768
  if (thread_locked)
1239.3.127 by Toru Maesaka
Added more index related tests and renamed BlitzDB's lock functions.
769
    blitz_optimal_unlock();
1239.3.17 by Toru Maesaka
Implemented index_read() and index_read_idx() for PK and added a simple needle in a haystack test.
770
1239.3.16 by Toru Maesaka
Added index_init() and index_first() for Primary Keys.
771
  return 0;
772
}
773
1239.3.122 by Toru Maesaka
Implemented Cursor::enable_indexes() and Cursor::disable_indexes(). Added a test file it as well.
774
int ha_blitz::enable_indexes(uint32_t) {
775
  return HA_ERR_UNSUPPORTED;
776
}
777
778
int ha_blitz::disable_indexes(uint32_t) {
779
  return HA_ERR_UNSUPPORTED;
780
}
781
1239.3.79 by Toru Maesaka
Make records_in_range() return BLITZ_WORST_CASE_RANGE at all times for now.
782
/* Find the estimated number of rows between min_key and max_key.
783
   Leave the proper implementation of this for now since there are
784
   too many exceptions to cover. */
785
ha_rows ha_blitz::records_in_range(uint32_t /*key_num*/,
786
                                   drizzled::key_range * /*min_key*/,
787
                                   drizzled::key_range * /*max_key*/) {
1239.3.76 by Toru Maesaka
Base work for implementing ha_blitz::records_in_range().
788
  return BLITZ_WORST_CASE_RANGE;
789
}
790
1239.3.98 by Toru Maesaka
Merged Trunk.
791
int ha_blitz::doInsertRecord(unsigned char *drizzle_row) {
1239.3.12 by Toru Maesaka
Resolve Primary Key and cleanup BlitzData API. Index Support Prep Work 2.
792
  int rv;
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
793
1239.3.59 by Stewart Smith
BlitzDB build fixes for drizzle changes: system status variable and DRIZZLE_PLUGIN
794
  ha_statistic_increment(&system_status_var::ha_write_count);
1239.3.14 by Toru Maesaka
Separated the index key packing mechanism to it's own function. Primary Key data is now stored on it's own thread local buffer.
795
1239.3.117 by Toru Maesaka
Removed overchecking of auto increment value which was blocking valid queries. Tests added as well.
796
  /* Prepare Auto Increment field if one exists. */
1672.3.6 by Brian Aker
First pass in encapsulating row
797
  if (table->next_number_field && drizzle_row == table->getInsertRecord()) {
1239.3.120 by Toru Maesaka
Protected Drizzle's update_auto_increment() with a lock. In the future this may become thread safe.
798
    pthread_mutex_lock(&blitz_utility_mutex);
799
    if ((rv = update_auto_increment()) != 0) {
800
      pthread_mutex_unlock(&blitz_utility_mutex);
1239.3.22 by Toru Maesaka
Added Auto Increment support on INSERT and tests for it. Nextup: UPDATE.
801
      return rv;
1239.3.120 by Toru Maesaka
Protected Drizzle's update_auto_increment() with a lock. In the future this may become thread safe.
802
    }
1239.3.22 by Toru Maesaka
Added Auto Increment support on INSERT and tests for it. Nextup: UPDATE.
803
804
    uint64_t next_val = table->next_number_field->val_int();
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
805
1239.3.22 by Toru Maesaka
Added Auto Increment support on INSERT and tests for it. Nextup: UPDATE.
806
    if (next_val > share->auto_increment_value) {
807
      share->auto_increment_value = next_val;
808
      stats.auto_increment_value = share->auto_increment_value + 1;
809
    }
1239.3.120 by Toru Maesaka
Protected Drizzle's update_auto_increment() with a lock. In the future this may become thread safe.
810
    pthread_mutex_unlock(&blitz_utility_mutex);
1239.3.22 by Toru Maesaka
Added Auto Increment support on INSERT and tests for it. Nextup: UPDATE.
811
  }
812
1239.3.14 by Toru Maesaka
Separated the index key packing mechanism to it's own function. Primary Key data is now stored on it's own thread local buffer.
813
  /* Serialize a primary key for this row. If a PK doesn't exist,
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
814
     an internal hidden ID will be generated. We obtain the PK here
815
     and pack it to this function's local buffer instead of the
816
     thread's own 'key_buffer' because the PK value needs to be
817
     remembered when writing non-PK keys AND because the 'key_buffer'
818
     will be used to generate these non-PK keys. */
819
  char temp_pkbuf[BLITZ_MAX_KEY_LEN];
1239.3.39 by Toru Maesaka
Reworked the key packer to support null fields and deleted now a redundant function: pack_index_key_from_row().
820
  size_t pk_len = make_primary_key(temp_pkbuf, drizzle_row);
1239.3.14 by Toru Maesaka
Separated the index key packing mechanism to it's own function. Primary Key data is now stored on it's own thread local buffer.
821
1239.3.44 by Toru Maesaka
Added basic JOIN tests, optimized B+Tree usage and added slotted lock to write_row().
822
  /* Obtain a buffer that can accommodate this row. We then pack
823
     the provided row into it. Note that this code works most
824
     efficiently for rows smaller than BLITZ_MAX_ROW_STACK */
825
  unsigned char *row_buf = get_pack_buffer(max_row_length());
826
  size_t row_len = pack_row(row_buf, drizzle_row);
827
1239.3.49 by Toru Maesaka
Merged Drizzle's Trunk.
828
  uint32_t curr_key = 0;
829
  uint32_t lock_id = 0;
1239.3.44 by Toru Maesaka
Added basic JOIN tests, optimized B+Tree usage and added slotted lock to write_row().
830
831
  if (share->nkeys > 0) {
832
    lock_id = share->blitz_lock.slot_id(temp_pkbuf, pk_len);
833
    share->blitz_lock.slotted_lock(lock_id);
834
  }
835
1239.3.38 by Toru Maesaka
More work on indexing component. PK now gets a tree.
836
  /* We isolate this condition outside the key loop to avoid the CPU
837
     from going through unnecessary conditional branching on heavy
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
838
     insertion load. TODO: Optimize this block. PK should not need
839
     to go through merge_key() since this information is redundant. */
1239.3.12 by Toru Maesaka
Resolve Primary Key and cleanup BlitzData API. Index Support Prep Work 2.
840
  if (share->primary_key_exists) {
1239.3.84 by Toru Maesaka
Fixed warnings on OS X.
841
    char *key = NULL;
842
    size_t klen = 0;
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
843
844
    key = merge_key(temp_pkbuf, pk_len, temp_pkbuf, pk_len, &klen);
845
846
    rv = share->btrees[curr_key].write_unique(key, klen);
1239.3.73 by Toru Maesaka
Merged Stewart's lint fixes.
847
1239.3.38 by Toru Maesaka
More work on indexing component. PK now gets a tree.
848
    if (rv == HA_ERR_FOUND_DUPP_KEY) {
1239.3.54 by Toru Maesaka
Supported secondary index insertion, Added meta information on the B+Tree cursor and some tests.
849
      errkey_id = curr_key;
850
      share->blitz_lock.slotted_unlock(lock_id);
1239.3.38 by Toru Maesaka
More work on indexing component. PK now gets a tree.
851
      return rv;
852
    }
853
    curr_key = 1;
854
  }
855
1239.3.61 by Toru Maesaka
Worked on reducing the execution path of row insertion and supported NULL for key values. Added tests for NULL values in full index scan.
856
  /* Loop over the keys and write them to it's exclusive tree. */
1239.3.38 by Toru Maesaka
More work on indexing component. PK now gets a tree.
857
  while (curr_key < share->nkeys) {
1239.3.84 by Toru Maesaka
Fixed warnings on OS X.
858
    char *key = NULL;
1239.3.100 by Toru Maesaka
Allow NULL to be duplicately inserted into a UNIQUE INDEX. Added some tests for it as well. More patches to come.
859
    size_t prefix_len = 0;
860
    size_t klen = 0;
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
861
862
    prefix_len = make_index_key(key_buffer, curr_key, drizzle_row);
863
    key = merge_key(key_buffer, prefix_len, temp_pkbuf, pk_len, &klen);
1239.3.54 by Toru Maesaka
Supported secondary index insertion, Added meta information on the B+Tree cursor and some tests.
864
865
    if (share->btrees[curr_key].unique) {
1239.3.101 by Toru Maesaka
Fixed a bug for UNIQUE INDEX in BlitzDB's B+Tree key comparator.
866
      rv = share->btrees[curr_key].write_unique(key, klen);
1239.3.54 by Toru Maesaka
Supported secondary index insertion, Added meta information on the B+Tree cursor and some tests.
867
    } else {
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
868
      rv = share->btrees[curr_key].write(key, klen);
1239.3.100 by Toru Maesaka
Allow NULL to be duplicately inserted into a UNIQUE INDEX. Added some tests for it as well. More patches to come.
869
    }
870
871
    if (rv != 0) {
872
      errkey_id = curr_key;
873
      share->blitz_lock.slotted_unlock(lock_id);
874
      return rv;
875
    }
876
1239.3.38 by Toru Maesaka
More work on indexing component. PK now gets a tree.
877
    curr_key++;
878
  }
879
1239.3.61 by Toru Maesaka
Worked on reducing the execution path of row insertion and supported NULL for key values. Added tests for NULL values in full index scan.
880
  /* Write the row to the Data Dictionary. */
1239.3.38 by Toru Maesaka
More work on indexing component. PK now gets a tree.
881
  rv = share->dict.write_row(temp_pkbuf, pk_len, row_buf, row_len);
882
1239.3.44 by Toru Maesaka
Added basic JOIN tests, optimized B+Tree usage and added slotted lock to write_row().
883
  if (share->nkeys > 0)
884
    share->blitz_lock.slotted_unlock(lock_id);
885
1239.3.12 by Toru Maesaka
Resolve Primary Key and cleanup BlitzData API. Index Support Prep Work 2.
886
  return rv;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
887
}
888
1239.3.98 by Toru Maesaka
Merged Trunk.
889
int ha_blitz::doUpdateRecord(const unsigned char *old_row,
890
                             unsigned char *new_row) {
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
891
  int rv;
892
  uint32_t lock_id = 0;
893
894
  ha_statistic_increment(&system_status_var::ha_update_count);
895
896
  /* Handle Indexes */
897
  if (share->nkeys > 0) {
898
    /* BlitzDB cannot update an indexed row on table scan. */
899
    if (table_scan)
900
      return HA_ERR_UNSUPPORTED;
901
902
    if ((rv = compare_rows_for_unique_violation(old_row, new_row)) != 0)
903
      return rv;
904
905
    lock_id = share->blitz_lock.slot_id(held_key, held_key_len);
906
    share->blitz_lock.slotted_lock(lock_id);
907
908
    /* Update all relevant index entries. Start by deleting the
909
       the existing key then write the new key. Something we should
910
       consider in the future is to take a diff of the keys and only
911
       update changed keys. */
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
912
    int skip = btree_key_length(held_key, active_index);
1239.3.78 by Toru Maesaka
ha_blitz::records_in_range() can now return the real number of keys if min and max keys are both provided.
913
    char *suffix = held_key + skip;
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
914
    uint16_t suffix_len = uint2korr(suffix);
915
916
    suffix += sizeof(suffix_len);
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
917
918
    for (uint32_t i = 0; i < share->nkeys; i++) {
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
919
      char *key;
920
      size_t prefix_len, klen;
921
1239.3.84 by Toru Maesaka
Fixed warnings on OS X.
922
      klen = 0;
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
923
      prefix_len = make_index_key(key_buffer, i, old_row);
924
      key = merge_key(key_buffer, prefix_len, suffix, suffix_len, &klen);
925
926
      if (share->btrees[i].delete_key(key, klen) != 0) {
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
927
        errkey_id = i;
928
        share->blitz_lock.slotted_unlock(lock_id);
929
        return HA_ERR_KEY_NOT_FOUND;
930
      }
931
932
      /* Now write the new key. */
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
933
      prefix_len = make_index_key(key_buffer, i, new_row);
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
934
1239.3.124 by Toru Maesaka
Merged Drizzle's Trunk.
935
      if (i == table->s->getPrimaryKey()) {
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
936
        key = merge_key(key_buffer, prefix_len, key_buffer, prefix_len, &klen);
937
        rv = share->btrees[i].write(key, klen);
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
938
      } else {
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
939
        key = merge_key(key_buffer, prefix_len, suffix, suffix_len, &klen);
940
        rv = share->btrees[i].write(key, klen);
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
941
      }
942
943
      if (rv != 0) {
944
        errkey_id = i;
945
        share->blitz_lock.slotted_unlock(lock_id);
946
        return rv;
947
      }
948
    }
949
  }
950
951
  /* Getting this far means that the index has been successfully
952
     updated. We now update the Data Dictionary. This implementation
953
     is admittedly far from optimial and will be revisited. */
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
954
  size_t row_len = max_row_length();
955
  unsigned char *row_buf = get_pack_buffer(row_len);
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
956
  row_len = pack_row(row_buf, new_row);
957
958
  /* This is a basic case where we can simply overwrite the key. */
959
  if (table_based) {
960
    rv = share->dict.write_row(held_key, held_key_len, row_buf, row_len);
961
  } else {
1239.3.124 by Toru Maesaka
Merged Drizzle's Trunk.
962
    int klen = make_index_key(key_buffer, table->s->getPrimaryKey(), old_row);
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
963
964
    /* Delete with the old key. */
965
    share->dict.delete_row(key_buffer, klen);
966
967
    /* Write with the new key. */
1239.3.124 by Toru Maesaka
Merged Drizzle's Trunk.
968
    klen = make_index_key(key_buffer, table->s->getPrimaryKey(), new_row);
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
969
    rv = share->dict.write_row(key_buffer, klen, row_buf, row_len);
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
970
  }
1239.3.28 by Toru Maesaka
Added UNIQUE constraint check for UPDATE queries on VARCHAR key(s) and some tests for it.
971
1239.3.69 by Toru Maesaka
First attempt at completing update_row(). Still needs cleaning and tuning but the flow is there and doesn't break existing tests.
972
  if (share->nkeys > 0)
973
    share->blitz_lock.slotted_unlock(lock_id);
974
1239.3.12 by Toru Maesaka
Resolve Primary Key and cleanup BlitzData API. Index Support Prep Work 2.
975
  return rv;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
976
}
977
1239.3.98 by Toru Maesaka
Merged Trunk.
978
int ha_blitz::doDeleteRecord(const unsigned char *row_to_delete) {
1239.3.66 by Toru Maesaka
Started working on completing ha_blitz::delete_row(). Refactored index_read_idx() to suit the new comparator. Index update tests are disabled until ha_blitz::update_row() is completed.
979
  int rv;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
980
1239.3.59 by Stewart Smith
BlitzDB build fixes for drizzle changes: system status variable and DRIZZLE_PLUGIN
981
  ha_statistic_increment(&system_status_var::ha_delete_count);
1239.3.8 by Toru Maesaka
Remove redundant calculation in row packing mechanism.
982
1239.3.66 by Toru Maesaka
Started working on completing ha_blitz::delete_row(). Refactored index_read_idx() to suit the new comparator. Index update tests are disabled until ha_blitz::update_row() is completed.
983
  char *dict_key = held_key;
984
  int dict_klen = held_key_len;
1239.3.100 by Toru Maesaka
Allow NULL to be duplicately inserted into a UNIQUE INDEX. Added some tests for it as well. More patches to come.
985
  uint32_t lock_id = 0;
1239.3.66 by Toru Maesaka
Started working on completing ha_blitz::delete_row(). Refactored index_read_idx() to suit the new comparator. Index update tests are disabled until ha_blitz::update_row() is completed.
986
987
  if (share->nkeys > 0) {
988
    lock_id = share->blitz_lock.slot_id(held_key, held_key_len);
989
    share->blitz_lock.slotted_lock(lock_id);
990
1239.3.68 by Toru Maesaka
ha_blitz::delete_row() can now delete all index entries. Added basic tests for it as well. More to come.
991
    /* Loop over the indexes and delete all relevant entries for
992
       this row. We do this by reproducing the key in BlitzDB's
993
       unique key format. The procedure is simple.
994
995
       (1): Compute the key value for this index from the row then
996
            pack it into key_buffer (not unique at this point).
997
998
       (2): Append the suffix of the held_key to the key generated
999
            in step 1. The key is then guaranteed to be unique. */
1000
    for (uint32_t i = 0; i < share->nkeys; i++) {
1001
      /* In this case, we don't need to search for the key because
1002
         TC's cursor is already pointing at the key that we want
1003
         to delete. We wouldn't be here otherwise. */
1004
      if (i == active_index) {
1239.3.113 by Toru Maesaka
Improved cursor resource management. TC's cursor allocation only happens once per worker now.
1005
        btree_cursor[active_index].delete_position();
1239.3.68 by Toru Maesaka
ha_blitz::delete_row() can now delete all index entries. Added basic tests for it as well. More to come.
1006
        continue;
1007
      }
1008
1009
      int klen = make_index_key(key_buffer, i, row_to_delete);
1010
      int skip_len = btree_key_length(held_key, active_index);
1011
      uint16_t suffix_len = uint2korr(held_key + skip_len);
1012
1013
      /* Append the suffix to the key */
1014
      memcpy(key_buffer + klen, held_key + skip_len,
1015
             sizeof(suffix_len) + suffix_len);
1016
1017
      /* Update the key length to cover the generated key. */
1018
      klen = klen + sizeof(suffix_len) + suffix_len;
1019
1020
      if (share->btrees[i].delete_key(key_buffer, klen) != 0)
1021
        return HA_ERR_KEY_NOT_FOUND;
1022
    }
1023
1239.3.66 by Toru Maesaka
Started working on completing ha_blitz::delete_row(). Refactored index_read_idx() to suit the new comparator. Index update tests are disabled until ha_blitz::update_row() is completed.
1024
    /* Skip to the data dictionary key. */
1239.3.68 by Toru Maesaka
ha_blitz::delete_row() can now delete all index entries. Added basic tests for it as well. More to come.
1025
    int dict_key_offset = btree_key_length(dict_key, active_index);
1026
    dict_key = skip_btree_key(dict_key, dict_key_offset, &dict_klen);
1239.3.66 by Toru Maesaka
Started working on completing ha_blitz::delete_row(). Refactored index_read_idx() to suit the new comparator. Index update tests are disabled until ha_blitz::update_row() is completed.
1027
  }
1028
1029
  rv = share->dict.delete_row(dict_key, dict_klen);
1030
1031
  if (share->nkeys > 0)
1032
    share->blitz_lock.slotted_unlock(lock_id);
1033
1034
  return rv;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1035
}
1036
1239.3.22 by Toru Maesaka
Added Auto Increment support on INSERT and tests for it. Nextup: UPDATE.
1037
void ha_blitz::get_auto_increment(uint64_t, uint64_t,
1038
                                  uint64_t, uint64_t *first_value,
1039
                                  uint64_t *nb_reserved_values) {
1040
  *first_value = share->auto_increment_value + 1;
1041
  *nb_reserved_values = UINT64_MAX;
1042
}
1043
1044
int ha_blitz::reset_auto_increment(uint64_t value) {
1045
  share->auto_increment_value = (value == 0) ? 1 : value;
1046
  return 0;
1047
}
1048
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1049
int ha_blitz::delete_all_rows(void) {
1239.3.38 by Toru Maesaka
More work on indexing component. PK now gets a tree.
1050
  for (uint32_t i = 0; i < share->nkeys; i++) {
1051
    if (share->btrees[i].delete_all() != 0) {
1052
      errkey = i;
1053
      return HA_ERR_CRASHED_ON_USAGE;
1054
    }
1055
  }
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1056
  return (share->dict.delete_all_rows()) ? 0 : -1;
1057
}
1058
1059
uint32_t ha_blitz::max_row_length(void) {
1060
  uint32_t length = (table->getRecordLength() + table->sizeFields() * 2);
1061
  uint32_t *pos = table->getBlobField();
1062
  uint32_t *end = pos + table->sizeBlobFields();
1063
1064
  while (pos != end) {
1239.3.119 by Toru Maesaka
Merged Drizzle's Trunk.
1065
    length += 2 + ((Field_blob *)table->getField(*pos))->get_length();
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1066
    pos++;
1067
  }
1068
1069
  return length;
1070
}
1071
1239.3.39 by Toru Maesaka
Reworked the key packer to support null fields and deleted now a redundant function: pack_index_key_from_row().
1072
size_t ha_blitz::make_primary_key(char *pack_to, const unsigned char *row) {
1239.3.10 by Toru Maesaka
Started hacking on indexing. Prep Work 1.
1073
  if (!share->primary_key_exists) {
1074
    uint64_t next_id = share->dict.next_hidden_row_id();
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
1075
    int8store(pack_to, next_id);
1076
    return sizeof(next_id);
1239.3.10 by Toru Maesaka
Started hacking on indexing. Prep Work 1.
1077
  }
1239.3.13 by Toru Maesaka
Added basic index key handling. Started working on PRIMARY KEY support and added tests for it.
1078
1079
  /* Getting here means that there is a PK in this table. Get the
1080
     binary representation of the PK, pack it to BlitzDB's key buffer
1239.3.14 by Toru Maesaka
Separated the index key packing mechanism to it's own function. Primary Key data is now stored on it's own thread local buffer.
1081
     and return the size of it. */
1239.3.124 by Toru Maesaka
Merged Drizzle's Trunk.
1082
  return make_index_key(pack_to, table->s->getPrimaryKey(), row);
1239.3.14 by Toru Maesaka
Separated the index key packing mechanism to it's own function. Primary Key data is now stored on it's own thread local buffer.
1083
}
1084
1239.3.39 by Toru Maesaka
Reworked the key packer to support null fields and deleted now a redundant function: pack_index_key_from_row().
1085
size_t ha_blitz::make_index_key(char *pack_to, int key_num,
1086
                                const unsigned char *row) {
1239.3.112 by Toru Maesaka
Merged Drizzle's Trunk.
1087
  KeyInfo *key = &table->key_info[key_num];
1088
  KeyPartInfo *key_part = key->key_part;
1089
  KeyPartInfo *key_part_end = key_part + key->key_parts;
1239.3.13 by Toru Maesaka
Added basic index key handling. Started working on PRIMARY KEY support and added tests for it.
1090
1239.3.14 by Toru Maesaka
Separated the index key packing mechanism to it's own function. Primary Key data is now stored on it's own thread local buffer.
1091
  unsigned char *pos = (unsigned char *)pack_to;
1239.3.45 by Toru Maesaka
Optimized key generation (much leaner keys). Wrote a workaround for a HA_KEYTYPE_VARTEXT1 bug in Drizzle's Field_varstring. Added tests for a VARCHAR field less than 255 bytes.
1092
  unsigned char *end;
1093
  int offset = 0;
1239.3.14 by Toru Maesaka
Separated the index key packing mechanism to it's own function. Primary Key data is now stored on it's own thread local buffer.
1094
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
1095
  memset(pack_to, 0, BLITZ_MAX_KEY_LEN);
1239.3.23 by Toru Maesaka
Supported VARCHAR to be usable as index key(s). Also added basic tests where VARCHAR is used as PK.
1096
1239.3.39 by Toru Maesaka
Reworked the key packer to support null fields and deleted now a redundant function: pack_index_key_from_row().
1097
  /* Loop through key part(s) and pack them as we go. */
1239.3.14 by Toru Maesaka
Separated the index key packing mechanism to it's own function. Primary Key data is now stored on it's own thread local buffer.
1098
  for (; key_part != key_part_end; key_part++) {
1239.3.39 by Toru Maesaka
Reworked the key packer to support null fields and deleted now a redundant function: pack_index_key_from_row().
1099
    if (key_part->null_bit) {
1100
      if (row[key_part->null_offset] & key_part->null_bit) {
1101
        *pos++ = 0;
1102
        continue;
1103
      }
1104
      *pos++ = 1;
1105
    }
1106
1239.3.45 by Toru Maesaka
Optimized key generation (much leaner keys). Wrote a workaround for a HA_KEYTYPE_VARTEXT1 bug in Drizzle's Field_varstring. Added tests for a VARCHAR field less than 255 bytes.
1107
    end = key_part->field->pack(pos, row + key_part->offset);
1108
    offset = end - pos;
1109
    pos += offset;
1239.3.39 by Toru Maesaka
Reworked the key packer to support null fields and deleted now a redundant function: pack_index_key_from_row().
1110
  }
1111
1112
  return ((char *)pos - pack_to);
1239.3.28 by Toru Maesaka
Added UNIQUE constraint check for UPDATE queries on VARCHAR key(s) and some tests for it.
1113
}
1114
1239.3.72 by Toru Maesaka
Fixed a critical concurrency bug that would cause inconsistency. Reworked BlitzTree and refactored memory management a little.
1115
char *ha_blitz::merge_key(const char *a, const size_t a_len, const char *b,
1116
                          const size_t b_len, size_t *merged_len) {
1117
1118
  size_t total = a_len + sizeof(uint16_t) + b_len;
1119
1120
  if (total > key_merge_buffer_len) {
1121
    key_merge_buffer = (char *)realloc(key_merge_buffer, total);
1122
1123
    if (key_merge_buffer == NULL) {
1124
      errno = HA_ERR_OUT_OF_MEM;
1125
      return NULL;
1126
    }
1127
    key_merge_buffer_len = total;
1128
  }
1129
1130
  char *pos = key_merge_buffer;
1131
1132
  /* Copy the prefix. */
1133
  memcpy(pos, a, a_len);
1134
  pos += a_len;
1135
1136
  /* Copy the length of b. */
1137
  int2store(pos, (uint16_t)b_len);
1138
  pos += sizeof(uint16_t);
1139
1140
  /* Copy the suffix and we're done. */
1141
  memcpy(pos, b, b_len);
1142
1143
  *merged_len = total;
1144
  return key_merge_buffer;
1145
}
1146
1239.3.47 by Toru Maesaka
Implemented forward index scan and basic tests for it. More tests to come.
1147
size_t ha_blitz::btree_key_length(const char *key, const int key_num) {
1239.3.112 by Toru Maesaka
Merged Drizzle's Trunk.
1148
  KeyInfo *key_info = &table->key_info[key_num];
1149
  KeyPartInfo *key_part = key_info->key_part;
1150
  KeyPartInfo *key_part_end = key_part + key_info->key_parts;
1239.3.47 by Toru Maesaka
Implemented forward index scan and basic tests for it. More tests to come.
1151
  char *pos = (char *)key;
1152
  uint64_t len = 0;
1153
  size_t rv = 0;
1154
1155
  for (; key_part != key_part_end; key_part++) {
1239.3.61 by Toru Maesaka
Worked on reducing the execution path of row insertion and supported NULL for key values. Added tests for NULL values in full index scan.
1156
    if (key_part->null_bit) {
1239.3.47 by Toru Maesaka
Implemented forward index scan and basic tests for it. More tests to come.
1157
      rv++;
1239.3.61 by Toru Maesaka
Worked on reducing the execution path of row insertion and supported NULL for key values. Added tests for NULL values in full index scan.
1158
      if (*key == 0)
1159
        continue;
1160
    }
1161
1239.3.47 by Toru Maesaka
Implemented forward index scan and basic tests for it. More tests to come.
1162
    if (key_part->type == HA_KEYTYPE_VARTEXT1) {
1163
      len = *(uint8_t *)pos;
1164
      rv += len + sizeof(uint8_t);
1165
    } else if (key_part->type == HA_KEYTYPE_VARTEXT2) {
1166
      len = uint2korr(pos);
1167
      rv += len + sizeof(uint16_t);
1168
    } else {
1169
      len = key_part->field->key_length();
1170
      rv += len;
1171
    }
1172
    pos += len;
1173
    len = 0;
1174
  }
1175
1176
  return rv;
1177
}
1178
1239.3.53 by Toru Maesaka
Removed dead variables, shuffled ha_blitz class around and added a 1KB buffer for exclusive use on keeping track of keys.
1179
void ha_blitz::keep_track_of_key(const char *key, const int klen) {
1180
  memcpy(held_key_buf, key, klen);
1181
  held_key = held_key_buf;
1182
  held_key_len = klen;
1183
}
1184
1239.3.23 by Toru Maesaka
Supported VARCHAR to be usable as index key(s). Also added basic tests where VARCHAR is used as PK.
1185
/* Converts a native Drizzle index key to BlitzDB's format. */
1186
char *ha_blitz::native_to_blitz_key(const unsigned char *native_key,
1187
                                    const int key_num, int *return_key_len) {
1239.3.112 by Toru Maesaka
Merged Drizzle's Trunk.
1188
  KeyInfo *key = &table->key_info[key_num];
1189
  KeyPartInfo *key_part = key->key_part;
1190
  KeyPartInfo *key_part_end = key_part + key->key_parts;
1239.3.23 by Toru Maesaka
Supported VARCHAR to be usable as index key(s). Also added basic tests where VARCHAR is used as PK.
1191
1192
  unsigned char *key_pos = (unsigned char *)native_key;
1239.3.45 by Toru Maesaka
Optimized key generation (much leaner keys). Wrote a workaround for a HA_KEYTYPE_VARTEXT1 bug in Drizzle's Field_varstring. Added tests for a VARCHAR field less than 255 bytes.
1193
  unsigned char *keybuf_pos = (unsigned char *)key_buffer;
1194
  unsigned char *end;
1195
  int key_size = 0;
1196
  int offset = 0;
1239.3.23 by Toru Maesaka
Supported VARCHAR to be usable as index key(s). Also added basic tests where VARCHAR is used as PK.
1197
1239.3.25 by Toru Maesaka
Obtain memory for key packing from heap instead from the stack. Minor memory handling changes in write_row() and code-cosmetic changes.
1198
  memset(key_buffer, 0, BLITZ_MAX_KEY_LEN);
1239.3.23 by Toru Maesaka
Supported VARCHAR to be usable as index key(s). Also added basic tests where VARCHAR is used as PK.
1199
1200
  for (; key_part != key_part_end; key_part++) {
1239.3.45 by Toru Maesaka
Optimized key generation (much leaner keys). Wrote a workaround for a HA_KEYTYPE_VARTEXT1 bug in Drizzle's Field_varstring. Added tests for a VARCHAR field less than 255 bytes.
1201
    if (key_part->null_bit) {
1239.3.62 by Toru Maesaka
More work on NULLable keys. Supported direct B+Tree lookup and added tests for it.
1202
      key_size++;
1203
1204
      /* This key is NULL */
1205
      if (!(*keybuf_pos++ = (*key_pos++ == 0)))
1239.3.45 by Toru Maesaka
Optimized key generation (much leaner keys). Wrote a workaround for a HA_KEYTYPE_VARTEXT1 bug in Drizzle's Field_varstring. Added tests for a VARCHAR field less than 255 bytes.
1206
        continue;
1207
    }
1208
1209
    /* This is a temporary workaround for a bug in Drizzle's VARCHAR
1210
       where a 1 byte representable length varchar's actual data is
1211
       positioned 2 bytes ahead of the beginning of the buffer. The
1212
       correct behavior is to be positioned 1 byte ahead. Furthermore,
1213
       this is only applicable with varchar keys on READ. */
1214
    if (key_part->type == HA_KEYTYPE_VARTEXT1) {
1215
      /* Dereference the 1 byte length of the value. */
1216
      uint8_t varlen = *(uint8_t *)key_pos;
1217
      *keybuf_pos++ = varlen;
1218
1219
      /* Read the value by skipping 2 bytes. This is the workaround. */
1220
      memcpy(keybuf_pos, key_pos + sizeof(uint16_t), varlen);
1221
      offset = (sizeof(uint8_t) + varlen);
1222
      keybuf_pos += varlen;
1223
    } else {
1224
      end = key_part->field->pack(keybuf_pos, key_pos);
1225
      offset = end - keybuf_pos;
1226
      keybuf_pos += offset;
1227
    }
1228
1229
    key_size += offset;
1239.3.23 by Toru Maesaka
Supported VARCHAR to be usable as index key(s). Also added basic tests where VARCHAR is used as PK.
1230
    key_pos += key_part->field->key_length();
1231
  }
1232
1239.3.45 by Toru Maesaka
Optimized key generation (much leaner keys). Wrote a workaround for a HA_KEYTYPE_VARTEXT1 bug in Drizzle's Field_varstring. Added tests for a VARCHAR field less than 255 bytes.
1233
  *return_key_len = key_size;
1234
  return key_buffer;
1239.3.23 by Toru Maesaka
Supported VARCHAR to be usable as index key(s). Also added basic tests where VARCHAR is used as PK.
1235
}
1236
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1237
size_t ha_blitz::pack_row(unsigned char *row_buffer,
1238
                          unsigned char *row_to_pack) {
1239
  unsigned char *pos;
1240
1241
  /* Nothing special to do if the table is fixed length */
1242
  if (share->fixed_length_table) {
1239.3.119 by Toru Maesaka
Merged Drizzle's Trunk.
1243
    memcpy(row_buffer, row_to_pack, table->s->getRecordLength());
1244
    return (size_t)table->s->getRecordLength();
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1245
  }
1246
1247
  /* Copy NULL bits */
1248
  memcpy(row_buffer, row_to_pack, table->s->null_bytes);
1249
  pos = row_buffer + table->s->null_bytes;
1250
1251
  /* Pack each field into the buffer */
1239.3.119 by Toru Maesaka
Merged Drizzle's Trunk.
1252
  for (Field **field = table->getFields(); *field; field++) {
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1253
    if (!((*field)->is_null()))
1254
      pos = (*field)->pack(pos, row_to_pack + (*field)->offset(row_to_pack));
1255
  }
1256
1257
  return (size_t)(pos - row_buffer);
1258
}
1259
1239.3.8 by Toru Maesaka
Remove redundant calculation in row packing mechanism.
1260
bool ha_blitz::unpack_row(unsigned char *to, const char *from,
1261
                          const size_t from_len) {
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1262
  const unsigned char *pos;
1263
1264
  /* Nothing special to do */
1265
  if (share->fixed_length_table) {
1239.3.8 by Toru Maesaka
Remove redundant calculation in row packing mechanism.
1266
    memcpy(to, from, from_len);
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1267
    return true;
1268
  }
1269
1270
  /* Start by copying NULL bits which is the beginning block
1271
     of a Drizzle row. */
1272
  pos = (const unsigned char *)from;
1273
  memcpy(to, pos, table->s->null_bytes);
1274
  pos += table->s->null_bytes;
1275
1239.3.23 by Toru Maesaka
Supported VARCHAR to be usable as index key(s). Also added basic tests where VARCHAR is used as PK.
1276
  /* Unpack all fields in the provided row. */
1239.3.119 by Toru Maesaka
Merged Drizzle's Trunk.
1277
  for (Field **field = table->getFields(); *field; field++) {
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1278
    if (!((*field)->is_null())) {
1672.3.6 by Brian Aker
First pass in encapsulating row
1279
      pos = (*field)->unpack(to + (*field)->offset(table->getInsertRecord()), pos);
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1280
    }
1281
  }
1282
1283
  return true;
1284
}
1285
1239.3.8 by Toru Maesaka
Remove redundant calculation in row packing mechanism.
1286
unsigned char *ha_blitz::get_pack_buffer(const size_t size) {
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1287
  unsigned char *buf = pack_buffer;
1288
1289
  /* This is a shitty case where the row size is larger than 2KB. */
1239.3.8 by Toru Maesaka
Remove redundant calculation in row packing mechanism.
1290
  if (size > BLITZ_MAX_ROW_STACK) {
1291
    if (size > secondary_row_buffer_size) {
1292
      void *new_ptr = realloc(secondary_row_buffer, size);
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1293
1294
      if (new_ptr == NULL) {
1295
        errno = HA_ERR_OUT_OF_MEM;
1296
        return NULL;
1297
      }
1298
1239.3.8 by Toru Maesaka
Remove redundant calculation in row packing mechanism.
1299
      secondary_row_buffer_size = size;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1300
      secondary_row_buffer = (unsigned char *)new_ptr;
1301
    }
1239.3.134 by Toru Maesaka
Fixed a bug in BlitzDB's row buffer management and added tests for it.
1302
    buf = secondary_row_buffer;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1303
  }
1304
  return buf;
1305
}
1306
1307
static BlitzEngine *blitz_engine = NULL;
1308
1239.3.93 by Toru Maesaka
Codebase cleanup. Actively use std::string over const char * where it makes sense.
1309
BlitzShare *ha_blitz::get_share(const char *name) {
1239.3.29 by Toru Maesaka
Added UNIQUE constraint check on fixed length fields and more tests. Moved get_share() to ha_blitz class.
1310
  BlitzShare *share_ptr;
1239.3.91 by Toru Maesaka
Encapsulated 'share' mechanism to BlitzEngine class.
1311
  BlitzEngine *bz_engine = (BlitzEngine *)engine;
1239.3.93 by Toru Maesaka
Codebase cleanup. Actively use std::string over const char * where it makes sense.
1312
  std::string table_path(name);
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1313
1314
  pthread_mutex_lock(&blitz_utility_mutex);
1315
1316
  /* Look up the table cache to see if the table resource is available */
1239.3.93 by Toru Maesaka
Codebase cleanup. Actively use std::string over const char * where it makes sense.
1317
  share_ptr = bz_engine->getTableShare(table_path);
1239.3.91 by Toru Maesaka
Encapsulated 'share' mechanism to BlitzEngine class.
1318
1319
  if (share_ptr) {
1239.3.29 by Toru Maesaka
Added UNIQUE constraint check on fixed length fields and more tests. Moved get_share() to ha_blitz class.
1320
    share_ptr->use_count++;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1321
    pthread_mutex_unlock(&blitz_utility_mutex);
1239.3.29 by Toru Maesaka
Added UNIQUE constraint check on fixed length fields and more tests. Moved get_share() to ha_blitz class.
1322
    return share_ptr;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1323
  }
1324
1325
  /* Table wasn't cached so create a new table handler */
1239.3.29 by Toru Maesaka
Added UNIQUE constraint check on fixed length fields and more tests. Moved get_share() to ha_blitz class.
1326
  share_ptr = new BlitzShare();
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1327
1239.3.36 by Toru Maesaka
Added code to allocate/deallocate b+tree indexes.
1328
  /* Prepare the Data Dictionary */
1239.3.93 by Toru Maesaka
Codebase cleanup. Actively use std::string over const char * where it makes sense.
1329
  if (share_ptr->dict.startup(table_path.c_str()) != 0) {
1239.3.29 by Toru Maesaka
Added UNIQUE constraint check on fixed length fields and more tests. Moved get_share() to ha_blitz class.
1330
    delete share_ptr;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1331
    pthread_mutex_unlock(&blitz_utility_mutex);
1332
    return NULL;
1333
  }
1334
1239.3.36 by Toru Maesaka
Added code to allocate/deallocate b+tree indexes.
1335
  /* Prepare Index Structure(s) */
1239.3.119 by Toru Maesaka
Merged Drizzle's Trunk.
1336
  KeyInfo *curr = &table->s->getKeyInfo(0);
1239.3.36 by Toru Maesaka
Added code to allocate/deallocate b+tree indexes.
1337
  share_ptr->btrees = new BlitzTree[table->s->keys];
1338
1239.3.40 by Toru Maesaka
Extract useful key information from the internal KEY structure at open() and keep it in BlitzDB.
1339
  for (uint32_t i = 0; i < table->s->keys; i++, curr++) {
1239.3.93 by Toru Maesaka
Codebase cleanup. Actively use std::string over const char * where it makes sense.
1340
    share_ptr->btrees[i].open(table_path.c_str(), i, BDBOWRITER);
1239.3.40 by Toru Maesaka
Extract useful key information from the internal KEY structure at open() and keep it in BlitzDB.
1341
    share_ptr->btrees[i].parts = new BlitzKeyPart[curr->key_parts];
1239.3.36 by Toru Maesaka
Added code to allocate/deallocate b+tree indexes.
1342
1239.3.38 by Toru Maesaka
More work on indexing component. PK now gets a tree.
1343
    if (table->key_info[i].flags & HA_NOSAME)
1344
      share_ptr->btrees[i].unique = true;
1239.3.40 by Toru Maesaka
Extract useful key information from the internal KEY structure at open() and keep it in BlitzDB.
1345
1239.3.45 by Toru Maesaka
Optimized key generation (much leaner keys). Wrote a workaround for a HA_KEYTYPE_VARTEXT1 bug in Drizzle's Field_varstring. Added tests for a VARCHAR field less than 255 bytes.
1346
    share_ptr->btrees[i].length = curr->key_length;
1239.3.40 by Toru Maesaka
Extract useful key information from the internal KEY structure at open() and keep it in BlitzDB.
1347
    share_ptr->btrees[i].nparts = curr->key_parts;
1348
1349
    /* Record Meta Data of the Key Segments */
1350
    for (uint32_t j = 0; j < curr->key_parts; j++) {
1351
      Field *f = curr->key_part[j].field;
1352
1353
      if (f->null_ptr) {
1354
        share_ptr->btrees[i].parts[j].null_bitmask = f->null_bit;
1355
        share_ptr->btrees[i].parts[j].null_pos
1672.3.6 by Brian Aker
First pass in encapsulating row
1356
          = (uint32_t)(f->null_ptr - (unsigned char *)table->getInsertRecord());
1239.3.40 by Toru Maesaka
Extract useful key information from the internal KEY structure at open() and keep it in BlitzDB.
1357
      }
1358
1359
      share_ptr->btrees[i].parts[j].flag = curr->key_part[j].key_part_flag;
1360
1361
      if (f->type() == DRIZZLE_TYPE_BLOB) {
1362
        share_ptr->btrees[i].parts[j].flag |= HA_BLOB_PART;
1363
      }
1364
1239.3.43 by Toru Maesaka
Further hack on the key comparator. Use HA_KEYTYPE instead of DRIZZLE_TYPE. Added support for TIMESTAMP and DATETIME.
1365
      share_ptr->btrees[i].parts[j].type = curr->key_part[j].type;
1239.3.40 by Toru Maesaka
Extract useful key information from the internal KEY structure at open() and keep it in BlitzDB.
1366
      share_ptr->btrees[i].parts[j].offset = curr->key_part[j].offset;
1367
      share_ptr->btrees[i].parts[j].length = curr->key_part[j].length;
1368
    }
1239.3.38 by Toru Maesaka
More work on indexing component. PK now gets a tree.
1369
  }
1370
1239.3.36 by Toru Maesaka
Added code to allocate/deallocate b+tree indexes.
1371
  /* Set Meta Data */
1239.3.31 by Toru Maesaka
Use TC's Meta Buffer for storing auto increment value instead of the system table. Fixed a valgrind warning too.
1372
  share_ptr->auto_increment_value = share_ptr->dict.read_meta_autoinc();
1239.3.93 by Toru Maesaka
Codebase cleanup. Actively use std::string over const char * where it makes sense.
1373
  share_ptr->table_name = table_path;
1239.3.29 by Toru Maesaka
Added UNIQUE constraint check on fixed length fields and more tests. Moved get_share() to ha_blitz class.
1374
  share_ptr->nkeys = table->s->keys;
1375
  share_ptr->use_count = 1;
1376
1377
  share_ptr->fixed_length_table = !(table->s->db_create_options
1378
                                    & HA_OPTION_PACK_RECORD);
1379
1239.3.124 by Toru Maesaka
Merged Drizzle's Trunk.
1380
  if (table->s->getPrimaryKey() >= MAX_KEY)
1239.3.29 by Toru Maesaka
Added UNIQUE constraint check on fixed length fields and more tests. Moved get_share() to ha_blitz class.
1381
    share_ptr->primary_key_exists = false;
1382
  else
1383
    share_ptr->primary_key_exists = true;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1384
1239.3.91 by Toru Maesaka
Encapsulated 'share' mechanism to BlitzEngine class.
1385
  /* Done creating the share object. Cache it for later
1386
     use by another cursor object.*/
1239.3.93 by Toru Maesaka
Codebase cleanup. Actively use std::string over const char * where it makes sense.
1387
  bz_engine->cacheTableShare(table_path, share_ptr);
1239.3.91 by Toru Maesaka
Encapsulated 'share' mechanism to BlitzEngine class.
1388
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1389
  pthread_mutex_unlock(&blitz_utility_mutex);
1239.3.29 by Toru Maesaka
Added UNIQUE constraint check on fixed length fields and more tests. Moved get_share() to ha_blitz class.
1390
  return share_ptr;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1391
}
1392
1239.3.90 by Toru Maesaka
free_share() is now a member of Cursor::ha_blitz.
1393
int ha_blitz::free_share(void) {
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1394
  pthread_mutex_lock(&blitz_utility_mutex);
1395
1396
  /* BlitzShare could still be used by another thread. Check the
1397
     reference counter to see if it's safe to free it */
1398
  if (--share->use_count == 0) {
1239.3.31 by Toru Maesaka
Use TC's Meta Buffer for storing auto increment value instead of the system table. Fixed a valgrind warning too.
1399
    share->dict.write_meta_autoinc(share->auto_increment_value);
1239.3.22 by Toru Maesaka
Added Auto Increment support on INSERT and tests for it. Nextup: UPDATE.
1400
1239.3.34 by Toru Maesaka
Separated the codebase for Data Dictionary and System Table. TC object is no longer exposed to the handler.
1401
    if (share->dict.shutdown() != 0) {
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1402
      pthread_mutex_unlock(&blitz_utility_mutex);
1403
      return HA_ERR_CRASHED_ON_USAGE;
1404
    }
1239.3.31 by Toru Maesaka
Use TC's Meta Buffer for storing auto increment value instead of the system table. Fixed a valgrind warning too.
1405
1239.3.40 by Toru Maesaka
Extract useful key information from the internal KEY structure at open() and keep it in BlitzDB.
1406
    for (uint32_t i = 0; i < share->nkeys; i++) {
1407
      delete[] share->btrees[i].parts;
1239.3.36 by Toru Maesaka
Added code to allocate/deallocate b+tree indexes.
1408
      share->btrees[i].close();
1239.3.40 by Toru Maesaka
Extract useful key information from the internal KEY structure at open() and keep it in BlitzDB.
1409
    }
1239.3.36 by Toru Maesaka
Added code to allocate/deallocate b+tree indexes.
1410
1239.3.91 by Toru Maesaka
Encapsulated 'share' mechanism to BlitzEngine class.
1411
    BlitzEngine *bz_engine = (BlitzEngine *)engine;
1412
    bz_engine->deleteTableShare(share->table_name);
1413
1239.3.36 by Toru Maesaka
Added code to allocate/deallocate b+tree indexes.
1414
    delete[] share->btrees;
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1415
    delete share;
1416
  }
1417
1418
  pthread_mutex_unlock(&blitz_utility_mutex);
1419
  return 0;
1420
}
1421
1239.3.116 by Toru Maesaka
Merged Drizzle's Trunk.
1422
static int blitz_init(drizzled::module::Context &context) {
1239.3.92 by Toru Maesaka
Merged up to rev:1400. Supported the new doRenameTable() interface.
1423
  blitz_engine = new BlitzEngine("BLITZDB");
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
1424
1239.3.91 by Toru Maesaka
Encapsulated 'share' mechanism to BlitzEngine class.
1425
  if (!blitz_engine->doCreateTableCache()) {
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1426
    delete blitz_engine;
1427
    return HA_ERR_OUT_OF_MEM;
1428
  }
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
1429
1239.4.3 by Monty Taylor
Updated for out of tree builds.
1430
  pthread_mutex_init(&blitz_utility_mutex, NULL);
1239.3.89 by Toru Maesaka
Merged up to rev:1385. No more deinit in the API.
1431
  context.add(blitz_engine);
1239.3.1 by Toru Maesaka
Initial import of Project BlitzDB.
1432
  return 0;
1433
}
1434
1239.3.48 by Toru Maesaka
Added more tests for index scan and DECIMAL type. B+Tree handling code is slightly slimmer now.
1435
/* Read the prototype of this function for details. */
1436
static char *skip_btree_key(const char *key, const size_t skip_len,
1437
                            int *return_klen) {
1438
  char *pos = (char *)key;
1439
  *return_klen = uint2korr(pos + skip_len);
1440
  return pos + skip_len + sizeof(uint16_t);
1441
}
1442
1239.3.131 by Toru Maesaka
Implemented StorageEngine::validateCreateTableOption() in BlitzDB to extend the CREATE TABLE syntax.
1443
static bool str_is_numeric(const std::string &str) {
1444
  for (uint32_t i = 0; i < str.length(); i++) {
1445
    if (!std::isdigit(str[i]))
1446
      return false;
1447
  }
1448
  return true;
1449
}
1239.3.128 by Toru Maesaka
Added base work for sysvar handling in BlitzDB.
1450
1451
static DRIZZLE_SYSVAR_ULONGLONG (
1452
  estimated_rows,
1453
  blitz_estimated_rows,
1454
  PLUGIN_VAR_RQCMDARG,
1455
  "Estimated number of rows that a BlitzDB table will store.",
1456
  NULL,
1457
  NULL,
1458
  0,
1459
  0,
1460
  UINT64_MAX,
1461
  0
1462
);
1463
1464
static drizzle_sys_var *blitz_system_variables[] = {
1465
  DRIZZLE_SYSVAR(estimated_rows),
1466
  NULL
1467
};
1468
1239.3.133 by Toru Maesaka
Merged Drizzle's Trunk.
1469
DRIZZLE_PLUGIN(blitz_init, blitz_system_variables, NULL);