~drizzle-trunk/drizzle/development

575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
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
 */
1 by brian
clean slate
19
20
/**
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
21
  @file Cursor.cc
1 by brian
clean slate
22
23
  Handler-calling-functions
24
*/
25
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
26
#include "config.h"
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
27
28
#include <fcntl.h>
29
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
30
#include "drizzled/my_hash.h"
873.1.17 by Jay Pipes
Fix for incomplete class definition in handler.cc. Forgot to commit it
31
#include "drizzled/error.h"
32
#include "drizzled/gettext.h"
33
#include "drizzled/probes.h"
34
#include "drizzled/sql_parse.h"
1336.3.2 by Djellel E. Difallah
rename class COST_VECT to CostVector and move it to ./drizzled/optimizer directory
35
#include "drizzled/optimizer/cost_vector.h"
873.1.17 by Jay Pipes
Fix for incomplete class definition in handler.cc. Forgot to commit it
36
#include "drizzled/session.h"
37
#include "drizzled/sql_base.h"
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
38
#include "drizzled/transaction_services.h"
873.1.17 by Jay Pipes
Fix for incomplete class definition in handler.cc. Forgot to commit it
39
#include "drizzled/lock.h"
40
#include "drizzled/item/int.h"
41
#include "drizzled/item/empty_string.h"
1999.4.9 by Brian Aker
Created EPOCH
42
#include "drizzled/field/epoch.h"
988.1.1 by Jay Pipes
Changes libserialize to libdrizzledmessage per ML discussion. All GPB messages are now in the drizzled::message namespace.
43
#include "drizzled/message/table.pb.h"
971.6.1 by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way.
44
#include "drizzled/plugin/client.h"
1241.9.64 by Monty Taylor
Moved remaining non-public portions of mysys and mystrings to drizzled/internal.
45
#include "drizzled/internal/my_sys.h"
1502.5.7 by Barry.Leslie at PrimeBase
Renamed the 'Event' plugin to 'EventObserver' plugin along with some internal class renames to make things clearer.
46
#include "drizzled/plugin/event_observer.h"
572.1.4 by Monty Taylor
Removed a bunch of unusued tests and defines from autoconf.
47
919.2.14 by Monty Taylor
Use math.h instead of cmath... one of these days...
48
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
49
50
namespace drizzled
51
{
1 by brian
clean slate
52
53
/****************************************************************************
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
54
** General Cursor functions
1 by brian
clean slate
55
****************************************************************************/
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
56
Cursor::Cursor(plugin::StorageEngine &engine_arg,
1869.1.4 by Brian Aker
TableShare is no longer in the house (i.e. we no longer directly have a copy
57
               Table &arg)
1869.1.5 by Brian Aker
getTable()
58
  : table(arg),
1869.1.7 by Brian Aker
Cleanup of caller to ha_open().
59
    engine(engine_arg),
60
    estimation_rows_to_insert(0),
1492 by Brian Aker
Dead code removal.
61
    ref(0),
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
62
    key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
63
    ref_length(sizeof(internal::my_off_t)),
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
64
    inited(NONE),
1491.1.8 by Jay Pipes
Removes HEAP-specific Cursor::implicit_emptied member. Was unused.
65
    locked(false),
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
66
    next_insert_id(0), insert_id_for_cur_row(0)
67
{ }
68
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
69
Cursor::~Cursor(void)
1022.2.29 by Monty Taylor
Fixed some no-inline warnings.
70
{
71
  assert(locked == false);
72
  /* TODO: assert(inited == NONE); */
73
}
74
75
1626.3.3 by Brian Aker
Additional checks on path.
76
/*
77
 * @note this only used in
78
 * optimizer::QuickRangeSelect::init_ror_merged_scan(bool reuse_handler) as
79
 * of the writing of this comment. -Brian
80
 */
1253.1.3 by Monty Taylor
MEM_ROOT == memory::Root
81
Cursor *Cursor::clone(memory::Root *mem_root)
1 by brian
clean slate
82
{
1869.1.5 by Brian Aker
getTable()
83
  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
1185 by Brian Aker
Merge Engine changes.
84
1 by brian
clean slate
85
  /*
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
86
    Allocate Cursor->ref here because otherwise ha_open will allocate it
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
87
    on this->table->mem_root and we will not be able to reclaim that memory
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
88
    when the clone Cursor object is destroyed.
1 by brian
clean slate
89
  */
1485 by Brian Aker
Updates to confine memroot
90
  if (!(new_handler->ref= (unsigned char*) mem_root->alloc_root(ALIGN_SIZE(ref_length)*2)))
1 by brian
clean slate
91
    return NULL;
1578.2.9 by Brian Aker
Simplify ha_open.
92
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
93
  identifier::Table identifier(getTable()->getShare()->getSchemaName(),
1869.1.5 by Brian Aker
getTable()
94
                             getTable()->getShare()->getTableName(),
95
                             getTable()->getShare()->getType());
1626.3.1 by Brian Aker
Adding in TableIdentifier for ha_open; (first pass)
96
97
  if (new_handler && !new_handler->ha_open(identifier,
1869.1.5 by Brian Aker
getTable()
98
                                           getTable()->getDBStat(),
1 by brian
clean slate
99
                                           HA_OPEN_IGNORE_IF_LOCKED))
100
    return new_handler;
101
  return NULL;
102
}
103
1483 by Brian Aker
Small change to move over call to cursor API.
104
/*
105
  DESCRIPTION
106
    given a buffer with a key value, and a map of keyparts
107
    that are present in this value, returns the length of the value
108
*/
109
uint32_t Cursor::calculate_key_len(uint32_t key_position, key_part_map keypart_map_arg)
110
{
111
  /* works only with key prefixes */
112
  assert(((keypart_map_arg + 1) & keypart_map_arg) == 0);
113
1869.1.5 by Brian Aker
getTable()
114
  const KeyPartInfo *key_part_found= getTable()->getShare()->getKeyInfo(key_position).key_part;
115
  const KeyPartInfo *end_key_part_found= key_part_found + getTable()->getShare()->getKeyInfo(key_position).key_parts;
1483 by Brian Aker
Small change to move over call to cursor API.
116
  uint32_t length= 0;
117
118
  while (key_part_found < end_key_part_found && keypart_map_arg)
119
  {
120
    length+= key_part_found->store_length;
121
    keypart_map_arg >>= 1;
122
    key_part_found++;
123
  }
124
  return length;
125
}
126
1491.1.6 by Jay Pipes
Cursor::ha_index_init() -> Cursor::startIndexScan(). Cursor::ha_index_end() -> Cursor::endIndexScan()
127
int Cursor::startIndexScan(uint32_t idx, bool sorted)
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
128
{
129
  int result;
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
130
  assert(inited == NONE);
1491.1.6 by Jay Pipes
Cursor::ha_index_init() -> Cursor::startIndexScan(). Cursor::ha_index_end() -> Cursor::endIndexScan()
131
  if (!(result= doStartIndexScan(idx, sorted)))
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
132
    inited=INDEX;
133
  end_range= NULL;
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
134
  return result;
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
135
}
136
1491.1.6 by Jay Pipes
Cursor::ha_index_init() -> Cursor::startIndexScan(). Cursor::ha_index_end() -> Cursor::endIndexScan()
137
int Cursor::endIndexScan()
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
138
{
139
  assert(inited==INDEX);
140
  inited=NONE;
141
  end_range= NULL;
1491.1.6 by Jay Pipes
Cursor::ha_index_init() -> Cursor::startIndexScan(). Cursor::ha_index_end() -> Cursor::endIndexScan()
142
  return(doEndIndexScan());
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
143
}
144
1491.1.10 by Jay Pipes
ha_rnd_init -> startTableScan, rnd_init -> doStartTableScan, ha_rnd_end -> endTableScan, rnd_end -> doEndTableScan
145
int Cursor::startTableScan(bool scan)
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
146
{
147
  int result;
148
  assert(inited==NONE || (inited==RND && scan));
1491.1.10 by Jay Pipes
ha_rnd_init -> startTableScan, rnd_init -> doStartTableScan, ha_rnd_end -> endTableScan, rnd_end -> doEndTableScan
149
  inited= (result= doStartTableScan(scan)) ? NONE: RND;
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
150
151
  return result;
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
152
}
153
1491.1.10 by Jay Pipes
ha_rnd_init -> startTableScan, rnd_init -> doStartTableScan, ha_rnd_end -> endTableScan, rnd_end -> doEndTableScan
154
int Cursor::endTableScan()
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
155
{
156
  assert(inited==RND);
157
  inited=NONE;
1491.1.10 by Jay Pipes
ha_rnd_init -> startTableScan, rnd_init -> doStartTableScan, ha_rnd_end -> endTableScan, rnd_end -> doEndTableScan
158
  return(doEndTableScan());
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
159
}
160
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
161
int Cursor::ha_index_or_rnd_end()
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
162
{
1491.1.10 by Jay Pipes
ha_rnd_init -> startTableScan, rnd_init -> doStartTableScan, ha_rnd_end -> endTableScan, rnd_end -> doEndTableScan
163
  return inited == INDEX ? endIndexScan() : inited == RND ? endTableScan() : 0;
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
164
}
165
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
166
void Cursor::ha_start_bulk_insert(ha_rows rows)
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
167
{
168
  estimation_rows_to_insert= rows;
169
  start_bulk_insert(rows);
170
}
171
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
172
int Cursor::ha_end_bulk_insert()
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
173
{
174
  estimation_rows_to_insert= 0;
175
  return end_bulk_insert();
176
}
177
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
178
const key_map *Cursor::keys_to_use_for_scanning()
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
179
{
180
  return &key_map_empty;
181
}
182
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
183
bool Cursor::has_transactions()
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
184
{
1869.1.5 by Brian Aker
getTable()
185
  return (getTable()->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
186
}
1 by brian
clean slate
187
1561.3.12 by Joe Daly
add missing header file, and change ha_statistic_increment from ulong to uint64_t
188
void Cursor::ha_statistic_increment(uint64_t system_status_var::*offset) const
1 by brian
clean slate
189
{
1869.1.5 by Brian Aker
getTable()
190
  (getTable()->in_use->status_var.*offset)++;
1 by brian
clean slate
191
}
192
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
193
void **Cursor::ha_data(Session *session) const
1 by brian
clean slate
194
{
1869.1.3 by Brian Aker
Engine now as a referene.
195
  return session->getEngineData(getEngine());
1 by brian
clean slate
196
}
197
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
198
bool Cursor::is_fatal_error(int error, uint32_t flags)
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
199
{
200
  if (!error ||
201
      ((flags & HA_CHECK_DUP_KEY) &&
202
       (error == HA_ERR_FOUND_DUPP_KEY ||
203
        error == HA_ERR_FOUND_DUPP_UNIQUE)))
204
    return false;
205
  return true;
206
}
207
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
208
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
209
ha_rows Cursor::records() { return stats.records; }
1320.1.18 by Brian Aker
Overhaul of SHOW TABLE STATUS.
210
uint64_t Cursor::tableSize() { return stats.index_file_length + stats.data_file_length; }
1869.1.5 by Brian Aker
getTable()
211
uint64_t Cursor::rowSize() { return getTable()->getRecordLength() + getTable()->sizeFields(); }
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
212
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
213
int Cursor::doOpen(const identifier::Table &identifier, int mode, uint32_t test_if_locked)
1626.3.3 by Brian Aker
Additional checks on path.
214
{
215
  return open(identifier.getPath().c_str(), mode, test_if_locked);
216
}
217
1 by brian
clean slate
218
/**
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
219
  Open database-Cursor.
1 by brian
clean slate
220
221
  Try O_RDONLY if cannot open as O_RDWR
222
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
223
*/
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
224
int Cursor::ha_open(const identifier::Table &identifier,
1749.3.9 by Brian Aker
Remove table name from ha_open (we modified this a while ago to just use
225
                    int mode,
1626.3.1 by Brian Aker
Adding in TableIdentifier for ha_open; (first pass)
226
                    int test_if_locked)
1 by brian
clean slate
227
{
228
  int error;
229
1626.3.3 by Brian Aker
Additional checks on path.
230
  if ((error= doOpen(identifier, mode, test_if_locked)))
1 by brian
clean slate
231
  {
232
    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
1869.1.5 by Brian Aker
getTable()
233
        (getTable()->db_stat & HA_TRY_READ_ONLY))
1 by brian
clean slate
234
    {
1869.1.5 by Brian Aker
getTable()
235
      getTable()->db_stat|=HA_READ_ONLY;
1626.3.3 by Brian Aker
Additional checks on path.
236
      error= doOpen(identifier, O_RDONLY,test_if_locked);
1 by brian
clean slate
237
    }
238
  }
239
  if (error)
240
  {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
241
    errno= error;                            /* Safeguard */
1 by brian
clean slate
242
  }
243
  else
244
  {
1869.1.5 by Brian Aker
getTable()
245
    if (getTable()->getShare()->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
246
      getTable()->db_stat|=HA_READ_ONLY;
1 by brian
clean slate
247
    (void) extra(HA_EXTRA_NO_READCHECK);	// Not needed in SQL
248
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
249
    /* ref is already allocated for us if we're called from Cursor::clone() */
1869.1.5 by Brian Aker
getTable()
250
    if (!ref && !(ref= (unsigned char*) getTable()->alloc_root(ALIGN_SIZE(ref_length)*2)))
1 by brian
clean slate
251
    {
252
      close();
253
      error=HA_ERR_OUT_OF_MEM;
254
    }
255
    else
256
      dup_ref=ref+ALIGN_SIZE(ref_length);
257
  }
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
258
  return error;
1 by brian
clean slate
259
}
260
261
/**
262
  Read first row (only) from a table.
263
264
  This is never called for InnoDB tables, as these table types
265
  has the HA_STATS_RECORDS_IS_EXACT set.
266
*/
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
267
int Cursor::read_first_row(unsigned char * buf, uint32_t primary_key)
1 by brian
clean slate
268
{
269
  register int error;
270
1273.16.8 by Brian Aker
Remove typedef.
271
  ha_statistic_increment(&system_status_var::ha_read_first_count);
1 by brian
clean slate
272
273
  /*
274
    If there is very few deleted rows in the table, find the first row by
275
    scanning the table.
276
    TODO remove the test for HA_READ_ORDER
277
  */
278
  if (stats.deleted < 10 || primary_key >= MAX_KEY ||
1869.1.5 by Brian Aker
getTable()
279
      !(getTable()->index_flags(primary_key) & HA_READ_ORDER))
1 by brian
clean slate
280
  {
2049.2.1 by Stewart Smith
doStartTableScan() result not checked.
281
    error= startTableScan(1);
282
    if (error == 0)
283
    {
284
      while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
285
      (void) endTableScan();
286
    }
1 by brian
clean slate
287
  }
288
  else
289
  {
290
    /* Find the first row through the primary key */
2049.2.5 by Stewart Smith
check return value of Cursor::startIndexScan in read_first_row
291
    error= startIndexScan(primary_key, 0);
292
    if (error == 0)
293
    {
294
      error=index_first(buf);
295
      (void) endIndexScan();
296
    }
1 by brian
clean slate
297
  }
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
298
  return error;
1 by brian
clean slate
299
}
300
301
/**
302
  Generate the next auto-increment number based on increment and offset.
303
  computes the lowest number
304
  - strictly greater than "nr"
305
  - of the form: auto_increment_offset + N * auto_increment_increment
306
307
  In most cases increment= offset= 1, in which case we get:
308
  @verbatim 1,2,3,4,5,... @endverbatim
309
    If increment=10 and offset=5 and previous number is 1, we get:
310
  @verbatim 1,5,15,25,35,... @endverbatim
311
*/
312
inline uint64_t
1878.3.2 by Monty Taylor
Split out show_type into its own header and made sys_var work through
313
compute_next_insert_id(uint64_t nr, drizzle_system_variables *variables)
1 by brian
clean slate
314
{
315
  if (variables->auto_increment_increment == 1)
316
    return (nr+1); // optimization of the formula below
317
  nr= (((nr+ variables->auto_increment_increment -
318
         variables->auto_increment_offset)) /
319
       (uint64_t) variables->auto_increment_increment);
320
  return (nr* (uint64_t) variables->auto_increment_increment +
321
          variables->auto_increment_offset);
322
}
323
324
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
325
void Cursor::adjust_next_insert_id_after_explicit_value(uint64_t nr)
1 by brian
clean slate
326
{
327
  /*
520.1.21 by Brian Aker
THD -> Session rename
328
    If we have set Session::next_insert_id previously and plan to insert an
1 by brian
clean slate
329
    explicitely-specified value larger than this, we need to increase
520.1.21 by Brian Aker
THD -> Session rename
330
    Session::next_insert_id to be greater than the explicit value.
1 by brian
clean slate
331
  */
332
  if ((next_insert_id > 0) && (nr >= next_insert_id))
1869.1.5 by Brian Aker
getTable()
333
    set_next_insert_id(compute_next_insert_id(nr, &getTable()->in_use->variables));
1 by brian
clean slate
334
}
335
336
337
/**
338
  Compute a previous insert id
339
340
  Computes the largest number X:
341
  - smaller than or equal to "nr"
342
  - of the form: auto_increment_offset + N * auto_increment_increment
343
    where N>=0.
344
345
  @param nr            Number to "round down"
346
  @param variables     variables struct containing auto_increment_increment and
347
                       auto_increment_offset
348
349
  @return
350
    The number X if it exists, "nr" otherwise.
351
*/
352
inline uint64_t
1878.3.2 by Monty Taylor
Split out show_type into its own header and made sys_var work through
353
prev_insert_id(uint64_t nr, drizzle_system_variables *variables)
1 by brian
clean slate
354
{
355
  if (unlikely(nr < variables->auto_increment_offset))
356
  {
357
    /*
358
      There's nothing good we can do here. That is a pathological case, where
359
      the offset is larger than the column's max possible value, i.e. not even
360
      the first sequence value may be inserted. User will receive warning.
361
    */
362
    return nr;
363
  }
364
  if (variables->auto_increment_increment == 1)
365
    return nr; // optimization of the formula below
366
  nr= (((nr - variables->auto_increment_offset)) /
367
       (uint64_t) variables->auto_increment_increment);
368
  return (nr * (uint64_t) variables->auto_increment_increment +
369
          variables->auto_increment_offset);
370
}
371
372
373
/**
374
  Update the auto_increment field if necessary.
375
376
  Updates columns with type NEXT_NUMBER if:
377
1055.2.2 by Jay Pipes
Cleanup of style, indentation, and documentation of Table class members. Removed 5 or 6 dead Table member variables.
378
  - If column value is set to NULL (in which case auto_increment_field_not_null is false)
1 by brian
clean slate
379
  - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
380
    set. In the future we will only set NEXT_NUMBER fields if one sets them
381
    to NULL (or they are not included in the insert list).
382
383
    In those cases, we check if the currently reserved interval still has
384
    values we have not used. If yes, we pick the smallest one and use it.
385
    Otherwise:
386
387
  - If a list of intervals has been provided to the statement via SET
388
    INSERT_ID or via an Intvar_log_event (in a replication slave), we pick the
389
    first unused interval from this list, consider it as reserved.
390
391
  - Otherwise we set the column for the first row to the value
392
    next_insert_id(get_auto_increment(column))) which is usually
393
    max-used-column-value+1.
394
    We call get_auto_increment() for the first row in a multi-row
395
    statement. get_auto_increment() will tell us the interval of values it
396
    reserved for us.
397
398
  - In both cases, for the following rows we use those reserved values without
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
399
    calling the Cursor again (we just progress in the interval, computing
1 by brian
clean slate
400
    each new value from the previous one). Until we have exhausted them, then
401
    we either take the next provided interval or call get_auto_increment()
402
    again to reserve a new interval.
403
404
  - In both cases, the reserved intervals are remembered in
520.1.22 by Brian Aker
Second pass of thd cleanup
405
    session->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
1 by brian
clean slate
406
    binlogging; the last reserved interval is remembered in
407
    auto_inc_interval_for_cur_row.
408
409
    The idea is that generated auto_increment values are predictable and
410
    independent of the column values in the table.  This is needed to be
411
    able to replicate into a table that already has rows with a higher
412
    auto-increment value than the one that is inserted.
413
414
    After we have already generated an auto-increment number and the user
415
    inserts a column with a higher value than the last used one, we will
416
    start counting from the inserted value.
417
418
    This function's "outputs" are: the table's auto_increment field is filled
520.1.22 by Brian Aker
Second pass of thd cleanup
419
    with a value, session->next_insert_id is filled with the value to use for the
1 by brian
clean slate
420
    next row, if a value was autogenerated for the current row it is stored in
520.1.22 by Brian Aker
Second pass of thd cleanup
421
    session->insert_id_for_cur_row, if get_auto_increment() was called
422
    session->auto_inc_interval_for_cur_row is modified, if that interval is not
423
    present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
1 by brian
clean slate
424
    this list.
425
426
  @todo
427
    Replace all references to "next number" or NEXT_NUMBER to
428
    "auto_increment", everywhere (see below: there is
429
    table->auto_increment_field_not_null, and there also exists
430
    table->next_number_field, it's not consistent).
431
432
  @retval
433
    0	ok
434
  @retval
435
    HA_ERR_AUTOINC_READ_FAILED  get_auto_increment() was called and
436
    returned ~(uint64_t) 0
437
  @retval
438
    HA_ERR_AUTOINC_ERANGE storing value in field caused strict mode
439
    failure.
440
*/
441
442
#define AUTO_INC_DEFAULT_NB_ROWS 1 // Some prefer 1024 here
443
#define AUTO_INC_DEFAULT_NB_MAX_BITS 16
444
#define AUTO_INC_DEFAULT_NB_MAX ((1 << AUTO_INC_DEFAULT_NB_MAX_BITS) - 1)
445
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
446
int Cursor::update_auto_increment()
1 by brian
clean slate
447
{
448
  uint64_t nr, nb_reserved_values;
56 by brian
Next pass of true/false update.
449
  bool append= false;
1869.1.5 by Brian Aker
getTable()
450
  Session *session= getTable()->in_use;
1878.3.2 by Monty Taylor
Split out show_type into its own header and made sys_var work through
451
  drizzle_system_variables *variables= &session->variables;
1 by brian
clean slate
452
453
  /*
454
    next_insert_id is a "cursor" into the reserved interval, it may go greater
455
    than the interval, but not smaller.
456
  */
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
457
  assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
1 by brian
clean slate
458
1055.2.2 by Jay Pipes
Cleanup of style, indentation, and documentation of Table class members. Removed 5 or 6 dead Table member variables.
459
  /* We check if auto_increment_field_not_null is false
1008.3.2 by Stewart Smith
Make sql_mode=NO_AUTO_VALUE_ON_ZERO default for Drizzle.
460
     for an auto increment column, not a magic value like NULL is.
461
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
462
1869.1.5 by Brian Aker
getTable()
463
  if ((nr= getTable()->next_number_field->val_int()) != 0
464
      || getTable()->auto_increment_field_not_null)
1 by brian
clean slate
465
  {
466
    /*
467
      Update next_insert_id if we had already generated a value in this
468
      statement (case of INSERT VALUES(null),(3763),(null):
469
      the last NULL needs to insert 3764, not the value of the first NULL plus
470
      1).
471
    */
472
    adjust_next_insert_id_after_explicit_value(nr);
473
    insert_id_for_cur_row= 0; // didn't generate anything
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
474
475
    return 0;
1 by brian
clean slate
476
  }
477
478
  if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum())
479
  {
480
    /* next_insert_id is beyond what is reserved, so we reserve more. */
481
    const Discrete_interval *forced=
520.1.22 by Brian Aker
Second pass of thd cleanup
482
      session->auto_inc_intervals_forced.get_next();
1 by brian
clean slate
483
    if (forced != NULL)
484
    {
485
      nr= forced->minimum();
486
      nb_reserved_values= forced->values();
487
    }
488
    else
489
    {
490
      /*
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
491
        Cursor::estimation_rows_to_insert was set by
492
        Cursor::ha_start_bulk_insert(); if 0 it means "unknown".
1 by brian
clean slate
493
      */
482 by Brian Aker
Remove uint.
494
      uint32_t nb_already_reserved_intervals=
520.1.22 by Brian Aker
Second pass of thd cleanup
495
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
1 by brian
clean slate
496
      uint64_t nb_desired_values;
497
      /*
498
        If an estimation was given to the engine:
499
        - use it.
500
        - if we already reserved numbers, it means the estimation was
501
        not accurate, then we'll reserve 2*AUTO_INC_DEFAULT_NB_ROWS the 2nd
502
        time, twice that the 3rd time etc.
503
        If no estimation was given, use those increasing defaults from the
504
        start, starting from AUTO_INC_DEFAULT_NB_ROWS.
505
        Don't go beyond a max to not reserve "way too much" (because
506
        reservation means potentially losing unused values).
507
      */
508
      if (nb_already_reserved_intervals == 0 &&
509
          (estimation_rows_to_insert > 0))
510
        nb_desired_values= estimation_rows_to_insert;
511
      else /* go with the increasing defaults */
512
      {
513
        /* avoid overflow in formula, with this if() */
514
        if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
515
        {
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
516
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
1 by brian
clean slate
517
            (1 << nb_already_reserved_intervals);
937.2.6 by Stewart Smith
make set_if_bigger typesafe for C and C++. Fix up everywhere.
518
          set_if_smaller(nb_desired_values, (uint64_t)AUTO_INC_DEFAULT_NB_MAX);
1 by brian
clean slate
519
        }
520
        else
521
          nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
522
      }
523
      /* This call ignores all its parameters but nr, currently */
524
      get_auto_increment(variables->auto_increment_offset,
525
                         variables->auto_increment_increment,
526
                         nb_desired_values, &nr,
527
                         &nb_reserved_values);
528
      if (nr == ~(uint64_t) 0)
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
529
        return HA_ERR_AUTOINC_READ_FAILED;  // Mark failure
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
530
1 by brian
clean slate
531
      /*
532
        That rounding below should not be needed when all engines actually
533
        respect offset and increment in get_auto_increment(). But they don't
534
        so we still do it. Wonder if for the not-first-in-index we should do
535
        it. Hope that this rounding didn't push us out of the interval; even
536
        if it did we cannot do anything about it (calling the engine again
537
        will not help as we inserted no row).
538
      */
539
      nr= compute_next_insert_id(nr-1, variables);
540
    }
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
541
1869.1.5 by Brian Aker
getTable()
542
    if (getTable()->getShare()->next_number_keypart == 0)
1 by brian
clean slate
543
    {
544
      /* We must defer the appending until "nr" has been possibly truncated */
56 by brian
Next pass of true/false update.
545
      append= true;
1 by brian
clean slate
546
    }
547
  }
548
1869.1.5 by Brian Aker
getTable()
549
  if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
1 by brian
clean slate
550
  {
551
    /*
552
      first test if the query was aborted due to strict mode constraints
553
    */
1910.2.8 by Brian Aker
Enapsulate Kill.
554
    if (session->getKilled() == Session::KILL_BAD_DATA)
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
555
      return HA_ERR_AUTOINC_ERANGE;
1 by brian
clean slate
556
557
    /*
558
      field refused this value (overflow) and truncated it, use the result of
559
      the truncation (which is going to be inserted); however we try to
560
      decrease it to honour auto_increment_* variables.
561
      That will shift the left bound of the reserved interval, we don't
562
      bother shifting the right bound (anyway any other value from this
563
      interval will cause a duplicate key).
564
    */
1869.1.5 by Brian Aker
getTable()
565
    nr= prev_insert_id(getTable()->next_number_field->val_int(), variables);
566
    if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
567
      nr= getTable()->next_number_field->val_int();
1 by brian
clean slate
568
  }
569
  if (append)
570
  {
571
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
572
                                          variables->auto_increment_increment);
573
  }
574
575
  /*
576
    Record this autogenerated value. If the caller then
577
    succeeds to insert this value, it will call
578
    record_first_successful_insert_id_in_cur_stmt()
579
    which will set first_successful_insert_id_in_cur_stmt if it's not
580
    already set.
581
  */
582
  insert_id_for_cur_row= nr;
583
  /*
584
    Set next insert id to point to next auto-increment value to be able to
585
    handle multi-row statements.
586
  */
587
  set_next_insert_id(compute_next_insert_id(nr, variables));
588
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
589
  return 0;
1 by brian
clean slate
590
}
591
592
593
/**
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
594
  Reserves an interval of auto_increment values from the Cursor.
1 by brian
clean slate
595
596
  offset and increment means that we want values to be of the form
597
  offset + N * increment, where N>=0 is integer.
598
  If the function sets *first_value to ~(uint64_t)0 it means an error.
163 by Brian Aker
Merge Monty's code.
599
  If the function sets *nb_reserved_values to UINT64_MAX it means it has
1 by brian
clean slate
600
  reserved to "positive infinite".
601
602
  @param offset
603
  @param increment
604
  @param nb_desired_values   how many values we want
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
605
  @param first_value         (OUT) the first value reserved by the Cursor
606
  @param nb_reserved_values  (OUT) how many values the Cursor reserved
1 by brian
clean slate
607
*/
608
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
609
void Cursor::ha_release_auto_increment()
1 by brian
clean slate
610
{
611
  release_auto_increment();
612
  insert_id_for_cur_row= 0;
613
  auto_inc_interval_for_cur_row.replace(0, 0, 0);
614
  if (next_insert_id > 0)
615
  {
616
    next_insert_id= 0;
617
    /*
618
      this statement used forced auto_increment values if there were some,
619
      wipe them away for other statements.
620
    */
1869.1.5 by Brian Aker
getTable()
621
    getTable()->in_use->auto_inc_intervals_forced.empty();
1 by brian
clean slate
622
  }
623
}
624
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
625
void Cursor::drop_table(const char *)
1 by brian
clean slate
626
{
627
  close();
628
}
629
630
631
/**
632
  Performs checks upon the table.
633
520.1.22 by Brian Aker
Second pass of thd cleanup
634
  @param session                thread doing CHECK Table operation
1 by brian
clean slate
635
  @param check_opt          options from the parser
636
637
  @retval
638
    HA_ADMIN_OK               Successful upgrade
639
  @retval
640
    HA_ADMIN_NEEDS_UPGRADE    Table has structures requiring upgrade
641
  @retval
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
642
    HA_ADMIN_NEEDS_ALTER      Table has structures requiring ALTER Table
1 by brian
clean slate
643
  @retval
644
    HA_ADMIN_NOT_IMPLEMENTED
645
*/
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
646
int Cursor::ha_check(Session *, HA_CHECK_OPT *)
1 by brian
clean slate
647
{
590.1.4 by Stewart Smith
remove frm_version from TABLE_SHARE
648
  return HA_ADMIN_OK;
1 by brian
clean slate
649
}
650
651
/**
652
  A helper function to mark a transaction read-write,
653
  if it is started.
654
*/
655
656
inline
657
void
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
658
Cursor::setTransactionReadWrite()
1 by brian
clean slate
659
{
1578.6.1 by Brian Aker
Remove ha_session where table->in_use should have been checked.
660
  ResourceContext *resource_context;
661
662
  /*
663
   * If the cursor has not context for execution then there should be no
664
   * possible resource to gain (and if there is... then there is a bug such
665
   * that in_use should have been set.
666
 */
1869.1.5 by Brian Aker
getTable()
667
  if (not getTable()->in_use)
1578.6.1 by Brian Aker
Remove ha_session where table->in_use should have been checked.
668
    return;
669
1869.1.5 by Brian Aker
getTable()
670
  resource_context= getTable()->in_use->getResourceContext(getEngine());
1 by brian
clean slate
671
  /*
672
    When a storage engine method is called, the transaction must
673
    have been started, unless it's a DDL call, for which the
674
    storage engine starts the transaction internally, and commits
675
    it internally, without registering in the ha_list.
676
    Unfortunately here we can't know know for sure if the engine
677
    has registered the transaction or not, so we must check.
678
  */
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
679
  if (resource_context->isStarted())
1 by brian
clean slate
680
  {
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
681
    resource_context->markModifiedData();
1 by brian
clean slate
682
  }
683
}
684
685
686
/**
687
  Delete all rows: public interface.
688
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
689
  @sa Cursor::delete_all_rows()
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
690
691
  @note
692
693
  This is now equalivalent to TRUNCATE TABLE.
1 by brian
clean slate
694
*/
695
696
int
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
697
Cursor::ha_delete_all_rows()
1 by brian
clean slate
698
{
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
699
  setTransactionReadWrite();
1 by brian
clean slate
700
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
701
  int result= delete_all_rows();
702
703
  if (result == 0)
704
  {
705
    /** 
706
     * Trigger post-truncate notification to plugins... 
707
     *
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
708
     * @todo Make TransactionServices generic to AfterTriggerServices
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
709
     * or similar...
710
     */
1869.1.5 by Brian Aker
getTable()
711
    Session *const session= getTable()->in_use;
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
712
    TransactionServices &transaction_services= TransactionServices::singleton();
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
713
    transaction_services.truncateTable(*session, *getTable());
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
714
  }
715
716
  return result;
1 by brian
clean slate
717
}
718
719
720
/**
721
  Reset auto increment: public interface.
722
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
723
  @sa Cursor::reset_auto_increment()
1 by brian
clean slate
724
*/
725
726
int
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
727
Cursor::ha_reset_auto_increment(uint64_t value)
1 by brian
clean slate
728
{
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
729
  setTransactionReadWrite();
1 by brian
clean slate
730
731
  return reset_auto_increment(value);
732
}
733
734
735
/**
736
  Analyze table: public interface.
737
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
738
  @sa Cursor::analyze()
1 by brian
clean slate
739
*/
740
741
int
1222.1.10 by Brian Aker
Removes options from DDL left in Cursor for admin operations (they were
742
Cursor::ha_analyze(Session* session, HA_CHECK_OPT*)
1 by brian
clean slate
743
{
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
744
  setTransactionReadWrite();
1 by brian
clean slate
745
1222.1.10 by Brian Aker
Removes options from DDL left in Cursor for admin operations (they were
746
  return analyze(session);
1 by brian
clean slate
747
}
748
749
/**
750
  Disable indexes: public interface.
751
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
752
  @sa Cursor::disable_indexes()
1 by brian
clean slate
753
*/
754
755
int
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
756
Cursor::ha_disable_indexes(uint32_t mode)
1 by brian
clean slate
757
{
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
758
  setTransactionReadWrite();
1 by brian
clean slate
759
760
  return disable_indexes(mode);
761
}
762
763
764
/**
765
  Enable indexes: public interface.
766
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
767
  @sa Cursor::enable_indexes()
1 by brian
clean slate
768
*/
769
770
int
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
771
Cursor::ha_enable_indexes(uint32_t mode)
1 by brian
clean slate
772
{
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
773
  setTransactionReadWrite();
1 by brian
clean slate
774
775
  return enable_indexes(mode);
776
}
777
778
779
/**
780
  Discard or import tablespace: public interface.
781
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
782
  @sa Cursor::discard_or_import_tablespace()
1 by brian
clean slate
783
*/
784
785
int
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
786
Cursor::ha_discard_or_import_tablespace(bool discard)
1 by brian
clean slate
787
{
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
788
  setTransactionReadWrite();
1 by brian
clean slate
789
790
  return discard_or_import_tablespace(discard);
791
}
792
793
/**
794
  Drop table in the engine: public interface.
795
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
796
  @sa Cursor::drop_table()
1 by brian
clean slate
797
*/
798
799
void
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
800
Cursor::closeMarkForDelete(const char *name)
1 by brian
clean slate
801
{
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
802
  setTransactionReadWrite();
1 by brian
clean slate
803
804
  return drop_table(name);
805
}
806
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
807
int Cursor::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
1 by brian
clean slate
808
{
809
  int error;
810
  if (!(error=index_next(buf)))
811
  {
1869.1.5 by Brian Aker
getTable()
812
    ptrdiff_t ptrdiff= buf - getTable()->getInsertRecord();
481 by Brian Aker
Remove all of uchar.
813
    unsigned char *save_record_0= NULL;
1535 by Brian Aker
Rename of KEY to KeyInfo
814
    KeyInfo *key_info= NULL;
1534 by Brian Aker
Remove of KeyPartInfo
815
    KeyPartInfo *key_part;
816
    KeyPartInfo *key_part_end= NULL;
1 by brian
clean slate
817
818
    /*
1672.3.6 by Brian Aker
First pass in encapsulating row
819
      key_cmp_if_same() compares table->getInsertRecord() against 'key'.
820
      In parts it uses table->getInsertRecord() directly, in parts it uses
821
      field objects with their local pointers into table->getInsertRecord().
822
      If 'buf' is distinct from table->getInsertRecord(), we need to move
823
      all record references. This is table->getInsertRecord() itself and
1 by brian
clean slate
824
      the field pointers of the fields used in this key.
825
    */
826
    if (ptrdiff)
827
    {
1869.1.5 by Brian Aker
getTable()
828
      save_record_0= getTable()->getInsertRecord();
829
      getTable()->record[0]= buf;
830
      key_info= getTable()->key_info + active_index;
1 by brian
clean slate
831
      key_part= key_info->key_part;
832
      key_part_end= key_part + key_info->key_parts;
833
      for (; key_part < key_part_end; key_part++)
834
      {
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
835
        assert(key_part->field);
1 by brian
clean slate
836
        key_part->field->move_field_offset(ptrdiff);
837
      }
838
    }
839
1869.1.5 by Brian Aker
getTable()
840
    if (key_cmp_if_same(getTable(), key, active_index, keylen))
1 by brian
clean slate
841
    {
1869.1.5 by Brian Aker
getTable()
842
      getTable()->status=STATUS_NOT_FOUND;
1 by brian
clean slate
843
      error=HA_ERR_END_OF_FILE;
844
    }
845
846
    /* Move back if necessary. */
847
    if (ptrdiff)
848
    {
1869.1.5 by Brian Aker
getTable()
849
      getTable()->record[0]= save_record_0;
1 by brian
clean slate
850
      for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
851
        key_part->field->move_field_offset(-ptrdiff);
852
    }
853
  }
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
854
  return error;
1 by brian
clean slate
855
}
856
857
858
/****************************************************************************
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
859
** Some general functions that isn't in the Cursor class
1 by brian
clean slate
860
****************************************************************************/
861
862
/**
863
  Calculate cost of 'index only' scan for given index and number of records
864
865
  @param keynr    Index number
866
  @param records  Estimated number of records to be retrieved
867
868
  @note
869
    It is assumed that we will read trough the whole key range and that all
870
    key blocks are half full (normally things are much better). It is also
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
871
    assumed that each time we read the next key from the index, the Cursor
1 by brian
clean slate
872
    performs a random seek, thus the cost is proportional to the number of
873
    blocks read.
874
875
  @todo
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
876
    Consider joining this function and Cursor::read_time() into one
877
    Cursor::read_time(keynr, records, ranges, bool index_only) function.
1 by brian
clean slate
878
879
  @return
880
    Estimated cost of 'index only' scan
881
*/
882
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
883
double Cursor::index_only_read_time(uint32_t keynr, double key_records)
1 by brian
clean slate
884
{
482 by Brian Aker
Remove uint.
885
  uint32_t keys_per_block= (stats.block_size/2/
1869.1.5 by Brian Aker
getTable()
886
			(getTable()->key_info[keynr].key_length + ref_length) + 1);
779.3.10 by Monty Taylor
Turned on -Wshadow.
887
  return ((double) (key_records + keys_per_block-1) /
888
          (double) keys_per_block);
1 by brian
clean slate
889
}
890
891
892
/****************************************************************************
893
 * Default MRR implementation (MRR to non-MRR converter)
894
 ***************************************************************************/
895
896
/**
897
  Get cost and other information about MRR scan over a known list of ranges
898
899
  Calculate estimated cost and other information about an MRR scan for given
900
  sequence of ranges.
901
902
  @param keyno           Index number
903
  @param seq             Range sequence to be traversed
904
  @param seq_init_param  First parameter for seq->init()
905
  @param n_ranges_arg    Number of ranges in the sequence, or 0 if the caller
906
                         can't efficiently determine it
907
  @param bufsz    INOUT  IN:  Size of the buffer available for use
908
                         OUT: Size of the buffer that is expected to be actually
909
                              used, or 0 if buffer is not needed.
910
  @param flags    INOUT  A combination of HA_MRR_* flags
911
  @param cost     OUT    Estimated cost of MRR access
912
913
  @note
914
    This method (or an overriding one in a derived class) must check for
1910.2.8 by Brian Aker
Enapsulate Kill.
915
    session->getKilled() and return HA_POS_ERROR if it is not zero. This is required
1 by brian
clean slate
916
    for a user to be able to interrupt the calculation by killing the
917
    connection/query.
918
919
  @retval
920
    HA_POS_ERROR  Error or the engine is unable to perform the requested
921
                  scan. Values of OUT parameters are undefined.
922
  @retval
923
    other         OK, *cost contains cost of the scan, *bufsz and *flags
924
                  contain scan parameters.
925
*/
926
77.1.15 by Monty Taylor
Bunch of warning cleanups.
927
ha_rows
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
928
Cursor::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
77.1.15 by Monty Taylor
Bunch of warning cleanups.
929
                                     void *seq_init_param,
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
930
                                     uint32_t ,
1336.3.2 by Djellel E. Difallah
rename class COST_VECT to CostVector and move it to ./drizzled/optimizer directory
931
                                     uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
1 by brian
clean slate
932
{
933
  KEY_MULTI_RANGE range;
934
  range_seq_t seq_it;
935
  ha_rows rows, total_rows= 0;
482 by Brian Aker
Remove uint.
936
  uint32_t n_ranges=0;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
937
1 by brian
clean slate
938
  /* Default MRR implementation doesn't need buffer */
939
  *bufsz= 0;
940
941
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
942
  while (!seq->next(seq_it, &range))
943
  {
944
    n_ranges++;
945
    key_range *min_endp, *max_endp;
946
    {
947
      min_endp= range.start_key.length? &range.start_key : NULL;
948
      max_endp= range.end_key.length? &range.end_key : NULL;
949
    }
950
    if ((range.range_flag & UNIQUE_RANGE) && !(range.range_flag & NULL_RANGE))
951
      rows= 1; /* there can be at most one row */
952
    else
953
    {
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
954
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
1 by brian
clean slate
955
                                                        max_endp)))
956
      {
957
        /* Can't scan one range => can't do MRR scan at all */
958
        total_rows= HA_POS_ERROR;
959
        break;
960
      }
961
    }
962
    total_rows += rows;
963
  }
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
964
1 by brian
clean slate
965
  if (total_rows != HA_POS_ERROR)
966
  {
967
    /* The following calculation is the same as in multi_range_read_info(): */
968
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
969
    cost->zero();
1336.3.2 by Djellel E. Difallah
rename class COST_VECT to CostVector and move it to ./drizzled/optimizer directory
970
    cost->setAvgIOCost(1); /* assume random seeks */
1 by brian
clean slate
971
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
1336.3.2 by Djellel E. Difallah
rename class COST_VECT to CostVector and move it to ./drizzled/optimizer directory
972
      cost->setIOCount(index_only_read_time(keyno, (uint32_t)total_rows));
1 by brian
clean slate
973
    else
1336.3.2 by Djellel E. Difallah
rename class COST_VECT to CostVector and move it to ./drizzled/optimizer directory
974
      cost->setIOCount(read_time(keyno, n_ranges, total_rows));
975
    cost->setCpuCost((double) total_rows / TIME_FOR_COMPARE + 0.01);
1 by brian
clean slate
976
  }
977
  return total_rows;
978
}
979
980
981
/**
982
  Get cost and other information about MRR scan over some sequence of ranges
983
984
  Calculate estimated cost and other information about an MRR scan for some
985
  sequence of ranges.
986
987
  The ranges themselves will be known only at execution phase. When this
988
  function is called we only know number of ranges and a (rough) E(#records)
989
  within those ranges.
990
991
  Currently this function is only called for "n-keypart singlepoint" ranges,
992
  i.e. each range is "keypart1=someconst1 AND ... AND keypartN=someconstN"
993
994
  The flags parameter is a combination of those flags: HA_MRR_SORTED,
995
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION, HA_MRR_LIMITS.
996
997
  @param keyno           Index number
998
  @param n_ranges        Estimated number of ranges (i.e. intervals) in the
999
                         range sequence.
1000
  @param n_rows          Estimated total number of records contained within all
1001
                         of the ranges
1002
  @param bufsz    INOUT  IN:  Size of the buffer available for use
1003
                         OUT: Size of the buffer that will be actually used, or
1004
                              0 if buffer is not needed.
1005
  @param flags    INOUT  A combination of HA_MRR_* flags
1006
  @param cost     OUT    Estimated cost of MRR access
1007
1008
  @retval
1009
    0     OK, *cost contains cost of the scan, *bufsz and *flags contain scan
1010
          parameters.
1011
  @retval
1012
    other Error or can't perform the requested scan
1013
*/
1014
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1015
int Cursor::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
1336.3.2 by Djellel E. Difallah
rename class COST_VECT to CostVector and move it to ./drizzled/optimizer directory
1016
                                   uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
1 by brian
clean slate
1017
{
1018
  *bufsz= 0; /* Default implementation doesn't need a buffer */
1019
1020
  *flags |= HA_MRR_USE_DEFAULT_IMPL;
1021
1022
  cost->zero();
1336.3.2 by Djellel E. Difallah
rename class COST_VECT to CostVector and move it to ./drizzled/optimizer directory
1023
  cost->setAvgIOCost(1); /* assume random seeks */
1 by brian
clean slate
1024
1025
  /* Produce the same cost as non-MRR code does */
1026
  if (*flags & HA_MRR_INDEX_ONLY)
1336.3.2 by Djellel E. Difallah
rename class COST_VECT to CostVector and move it to ./drizzled/optimizer directory
1027
    cost->setIOCount(index_only_read_time(keyno, n_rows));
1 by brian
clean slate
1028
  else
1336.3.2 by Djellel E. Difallah
rename class COST_VECT to CostVector and move it to ./drizzled/optimizer directory
1029
    cost->setIOCount(read_time(keyno, n_ranges, n_rows));
1 by brian
clean slate
1030
  return 0;
1031
}
1032
1033
1034
/**
1035
  Initialize the MRR scan
1036
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
1037
  Initialize the MRR scan. This function may do heavyweight scan
1 by brian
clean slate
1038
  initialization like row prefetching/sorting/etc (NOTE: but better not do
1039
  it here as we may not need it, e.g. if we never satisfy WHERE clause on
1040
  previous tables. For many implementations it would be natural to do such
1041
  initializations in the first multi_read_range_next() call)
1042
1043
  mode is a combination of the following flags: HA_MRR_SORTED,
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
1044
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
1 by brian
clean slate
1045
1046
  @param seq             Range sequence to be traversed
1047
  @param seq_init_param  First parameter for seq->init()
1048
  @param n_ranges        Number of ranges in the sequence
1049
  @param mode            Flags, see the description section for the details
1050
  @param buf             INOUT: memory buffer to be used
1051
1052
  @note
1491.1.6 by Jay Pipes
Cursor::ha_index_init() -> Cursor::startIndexScan(). Cursor::ha_index_end() -> Cursor::endIndexScan()
1053
    One must have called doStartIndexScan() before calling this function. Several
1 by brian
clean slate
1054
    multi_range_read_init() calls may be made in course of one query.
1055
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
1056
    Until WL#2623 is done (see its text, section 3.2), the following will
1 by brian
clean slate
1057
    also hold:
1058
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
1059
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1060
    This property will only be used by NDB Cursor until WL#2623 is done.
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
1061
1 by brian
clean slate
1062
    Buffer memory management is done according to the following scenario:
1063
    The caller allocates the buffer and provides it to the callee by filling
1064
    the members of HANDLER_BUFFER structure.
1065
    The callee consumes all or some fraction of the provided buffer space, and
1066
    sets the HANDLER_BUFFER members accordingly.
1067
    The callee may use the buffer memory until the next multi_range_read_init()
1491.1.6 by Jay Pipes
Cursor::ha_index_init() -> Cursor::startIndexScan(). Cursor::ha_index_end() -> Cursor::endIndexScan()
1068
    call is made, all records have been read, or until doEndIndexScan() call is
1 by brian
clean slate
1069
    made, whichever comes first.
1070
1071
  @retval 0  OK
1072
  @retval 1  Error
1073
*/
1074
1075
int
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1076
Cursor::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
1491 by Brian Aker
Remove call bits in dead mrr caller.
1077
                               uint32_t n_ranges, uint32_t mode)
1 by brian
clean slate
1078
{
1079
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
1080
  mrr_funcs= *seq_funcs;
1081
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
56 by brian
Next pass of true/false update.
1082
  mrr_have_range= false;
1491 by Brian Aker
Remove call bits in dead mrr caller.
1083
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1084
  return 0;
1 by brian
clean slate
1085
}
1086
1087
1088
/**
1089
  Get next record in MRR scan
1090
1091
  Default MRR implementation: read the next record
1092
1093
  @param range_info  OUT  Undefined if HA_MRR_NO_ASSOCIATION flag is in effect
1094
                          Otherwise, the opaque value associated with the range
1095
                          that contains the returned record.
1096
1097
  @retval 0      OK
1098
  @retval other  Error code
1099
*/
1100
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1101
int Cursor::multi_range_read_next(char **range_info)
1 by brian
clean slate
1102
{
1103
  int result= 0;
236.2.2 by rbradfor
Using correct coding standards for variable initialization
1104
  int range_res= 0;
1 by brian
clean slate
1105
1492 by Brian Aker
Dead code removal.
1106
  if (not mrr_have_range)
1 by brian
clean slate
1107
  {
56 by brian
Next pass of true/false update.
1108
    mrr_have_range= true;
1 by brian
clean slate
1109
    goto start;
1110
  }
1111
1112
  do
1113
  {
1114
    /* Save a call if there can be only one row in range. */
1115
    if (mrr_cur_range.range_flag != (UNIQUE_RANGE | EQ_RANGE))
1116
    {
1117
      result= read_range_next();
1118
      /* On success or non-EOF errors jump to the end. */
1119
      if (result != HA_ERR_END_OF_FILE)
1120
        break;
1121
    }
1122
    else
1123
    {
1124
      if (was_semi_consistent_read())
1125
        goto scan_it_again;
1126
      /*
1127
        We need to set this for the last range only, but checking this
1128
        condition is more expensive than just setting the result code.
1129
      */
1130
      result= HA_ERR_END_OF_FILE;
1131
    }
1132
1133
start:
1134
    /* Try the next range(s) until one matches a record. */
1135
    while (!(range_res= mrr_funcs.next(mrr_iter, &mrr_cur_range)))
1136
    {
1137
scan_it_again:
1138
      result= read_range_first(mrr_cur_range.start_key.keypart_map ?
1139
                                 &mrr_cur_range.start_key : 0,
1140
                               mrr_cur_range.end_key.keypart_map ?
1141
                                 &mrr_cur_range.end_key : 0,
1142
                               test(mrr_cur_range.range_flag & EQ_RANGE),
1143
                               mrr_is_output_sorted);
1144
      if (result != HA_ERR_END_OF_FILE)
1145
        break;
1146
    }
1147
  }
1148
  while ((result == HA_ERR_END_OF_FILE) && !range_res);
1149
1150
  *range_info= mrr_cur_range.ptr;
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1151
  return result;
1 by brian
clean slate
1152
}
1153
1154
1155
/* **************************************************************************
1156
 * DS-MRR implementation ends
1157
 ***************************************************************************/
1158
1159
/**
1160
  Read first row between two ranges.
1161
1162
  @param start_key		Start key. Is 0 if no min range
1163
  @param end_key		End key.  Is 0 if no max range
1164
  @param eq_range_arg	        Set to 1 if start_key == end_key
1165
  @param sorted		Set to 1 if result should be sorted per key
1166
1167
  @note
1672.3.6 by Brian Aker
First pass in encapsulating row
1168
    Record is read into table->getInsertRecord()
1 by brian
clean slate
1169
1170
  @retval
1171
    0			Found row
1172
  @retval
1173
    HA_ERR_END_OF_FILE	No rows in range
1174
  @retval
1175
    \#			Error code
1176
*/
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1177
int Cursor::read_range_first(const key_range *start_key,
1183.1.4 by Brian Aker
Minor interface bits around Cursor.
1178
                             const key_range *end_key,
1179
                             bool eq_range_arg,
1180
                             bool )
1 by brian
clean slate
1181
{
1182
  int result;
1183
1184
  eq_range= eq_range_arg;
1185
  end_range= 0;
1186
  if (end_key)
1187
  {
1188
    end_range= &save_end_range;
1189
    save_end_range= *end_key;
1190
    key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
1191
				  (end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
1192
  }
1869.1.5 by Brian Aker
getTable()
1193
  range_key_part= getTable()->key_info[active_index].key_part;
1 by brian
clean slate
1194
1195
  if (!start_key)			// Read first record
1869.1.5 by Brian Aker
getTable()
1196
    result= index_first(getTable()->getInsertRecord());
1 by brian
clean slate
1197
  else
1869.1.5 by Brian Aker
getTable()
1198
    result= index_read_map(getTable()->getInsertRecord(),
1 by brian
clean slate
1199
                           start_key->key,
1200
                           start_key->keypart_map,
1201
                           start_key->flag);
1202
  if (result)
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
1203
    return((result == HA_ERR_KEY_NOT_FOUND)
1 by brian
clean slate
1204
		? HA_ERR_END_OF_FILE
1205
		: result);
1206
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1207
  return (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1 by brian
clean slate
1208
}
1209
1210
1211
/**
1212
  Read next row between two endpoints.
1213
1214
  @note
1672.3.6 by Brian Aker
First pass in encapsulating row
1215
    Record is read into table->getInsertRecord()
1 by brian
clean slate
1216
1217
  @retval
1218
    0			Found row
1219
  @retval
1220
    HA_ERR_END_OF_FILE	No rows in range
1221
  @retval
1222
    \#			Error code
1223
*/
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1224
int Cursor::read_range_next()
1 by brian
clean slate
1225
{
1226
  int result;
1227
1228
  if (eq_range)
1229
  {
1230
    /* We trust that index_next_same always gives a row in range */
1869.1.5 by Brian Aker
getTable()
1231
    return(index_next_same(getTable()->getInsertRecord(),
1 by brian
clean slate
1232
                                end_range->key,
1233
                                end_range->length));
1234
  }
1869.1.5 by Brian Aker
getTable()
1235
  result= index_next(getTable()->getInsertRecord());
1 by brian
clean slate
1236
  if (result)
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1237
    return result;
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1238
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1 by brian
clean slate
1239
}
1240
1241
1242
/**
1243
  Compare if found key (in row) is over max-value.
1244
1245
  @param range		range to compare to row. May be 0 for no range
1246
1247
  @seealso
1248
    key.cc::key_cmp()
1249
1250
  @return
1251
    The return value is SIGN(key_in_row - range_key):
1252
1253
    - 0   : Key is equal to range or 'range' == 0 (no range)
1254
    - -1  : Key is less than range
1255
    - 1   : Key is larger than range
1256
*/
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1257
int Cursor::compare_key(key_range *range)
1 by brian
clean slate
1258
{
1259
  int cmp;
1492 by Brian Aker
Dead code removal.
1260
  if (not range)
1 by brian
clean slate
1261
    return 0;					// No max range
1262
  cmp= key_cmp(range_key_part, range->key, range->length);
1263
  if (!cmp)
1264
    cmp= key_compare_result_on_equal;
1265
  return cmp;
1266
}
1267
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1268
int Cursor::index_read_idx_map(unsigned char * buf, uint32_t index,
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
1269
                                const unsigned char * key,
1 by brian
clean slate
1270
                                key_part_map keypart_map,
1271
                                enum ha_rkey_function find_flag)
1272
{
1273
  int error, error1;
1491.1.6 by Jay Pipes
Cursor::ha_index_init() -> Cursor::startIndexScan(). Cursor::ha_index_end() -> Cursor::endIndexScan()
1274
  error= doStartIndexScan(index, 0);
1 by brian
clean slate
1275
  if (!error)
1276
  {
1277
    error= index_read_map(buf, key, keypart_map, find_flag);
1491.1.6 by Jay Pipes
Cursor::ha_index_init() -> Cursor::startIndexScan(). Cursor::ha_index_end() -> Cursor::endIndexScan()
1278
    error1= doEndIndexScan();
1 by brian
clean slate
1279
  }
1280
  return error ?  error : error1;
1281
}
1282
1283
/**
1284
  Check if the conditions for row-based binlogging is correct for the table.
1285
1286
  A row in the given table should be replicated if:
1287
  - It is not a temporary table
1288
*/
1289
1039.1.16 by Brian Aker
A lot of little cleanups (most based off lcov)
1290
static bool log_row_for_replication(Table* table,
1143.2.20 by Jay Pipes
* Fixes bug in replication where inserts, updates, and
1291
                                    const unsigned char *before_record,
1292
                                    const unsigned char *after_record)
1 by brian
clean slate
1293
{
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1294
  TransactionServices &transaction_services= TransactionServices::singleton();
520.1.22 by Brian Aker
Second pass of thd cleanup
1295
  Session *const session= table->in_use;
1 by brian
clean slate
1296
1608.2.3 by Brian Aker
Encapsulate type for TableShare.
1297
  if (table->getShare()->getType() || not transaction_services.shouldConstructMessages())
1143.2.20 by Jay Pipes
* Fixes bug in replication where inserts, updates, and
1298
    return false;
1299
1143.4.15 by Jay Pipes
Adds error for when a record is inserted into a table containing
1300
  bool result= false;
1301
661 by Brian Aker
First major pass through new replication.
1302
  switch (session->lex->sql_command)
1303
  {
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1304
  case SQLCOM_CREATE_TABLE:
1305
    /*
1306
     * We are in a CREATE TABLE ... SELECT statement
1307
     * and the kernel has already created the table
1308
     * and put a CreateTableStatement in the active
1309
     * Transaction message.  Here, we add a new InsertRecord
1310
     * to a new Transaction message (because the above
1311
     * CREATE TABLE will commit the transaction containing
1312
     * it).
1313
     */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1314
    result= transaction_services.insertRecord(*session, *table);
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1315
    break;
661 by Brian Aker
First major pass through new replication.
1316
  case SQLCOM_REPLACE:
1143.2.22 by Jay Pipes
Adds functionality to handle REPLACE statements correctly in the replication
1317
  case SQLCOM_REPLACE_SELECT:
1143.2.24 by Jay Pipes
Fixes some stuff from make check (include guards). Also adds stuff for REPLACE logic that does not work.
1318
    /*
1143.2.27 by Jay Pipes
Corrects problems where REPLACE and INSERT ... ON DUPLICATE KEY UPDATE
1319
     * This is a total hack because of the code that is
1320
     * in write_record() in sql_insert.cc. During
1491.1.2 by Jay Pipes
Cursor::write_row() -> Cursor::doInsertRecord(). Cursor::ha_write_row() -> Cursor::insertRecord()
1321
     * a REPLACE statement, a call to insertRecord() is
1491.1.4 by Jay Pipes
delete_row() is now deleteRecord() and doDeleteRecord() in Cursor
1322
     * called.  If it fails, then a call to deleteRecord()
1143.2.24 by Jay Pipes
Fixes some stuff from make check (include guards). Also adds stuff for REPLACE logic that does not work.
1323
     * is called, followed by a repeat of the original
1491.1.2 by Jay Pipes
Cursor::write_row() -> Cursor::doInsertRecord(). Cursor::ha_write_row() -> Cursor::insertRecord()
1324
     * call to insertRecord().  So, log_row_for_replication
1730.5.3 by David Shrewsbury
Correct comments regarding REPLACE logic.
1325
     * could be called multiple times for a REPLACE
1143.2.24 by Jay Pipes
Fixes some stuff from make check (include guards). Also adds stuff for REPLACE logic that does not work.
1326
     * statement.  The below looks at the values of before_record
1327
     * and after_record to determine which call to this
1328
     * function is for the delete or the insert, since NULL
1329
     * is passed for after_record for the delete and NULL is
1330
     * passed for before_record for the insert...
1143.2.27 by Jay Pipes
Corrects problems where REPLACE and INSERT ... ON DUPLICATE KEY UPDATE
1331
     *
1332
     * In addition, there is an optimization that allows an
1333
     * engine to convert the above delete + insert into an
1334
     * update, so we must also check for this case below...
1143.2.22 by Jay Pipes
Adds functionality to handle REPLACE statements correctly in the replication
1335
     */
1143.2.24 by Jay Pipes
Fixes some stuff from make check (include guards). Also adds stuff for REPLACE logic that does not work.
1336
    if (after_record == NULL)
1337
    {
1730.5.3 by David Shrewsbury
Correct comments regarding REPLACE logic.
1338
      /*
1339
       * The storage engine is passed the record in table->record[1]
1340
       * as the row to delete (this is the conflicting row), so
1341
       * we need to notify TransactionService to use that row.
1342
       */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1343
      transaction_services.deleteRecord(*session, *table, true);
1143.2.24 by Jay Pipes
Fixes some stuff from make check (include guards). Also adds stuff for REPLACE logic that does not work.
1344
      /* 
1345
       * We set the "current" statement message to NULL.  This triggers
1346
       * the replication services component to generate a new statement
1347
       * message for the inserted record which will come next.
1348
       */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1349
      transaction_services.finalizeStatementMessage(*session->getStatementMessage(), *session);
1143.2.24 by Jay Pipes
Fixes some stuff from make check (include guards). Also adds stuff for REPLACE logic that does not work.
1350
    }
1351
    else
1352
    {
1143.2.27 by Jay Pipes
Corrects problems where REPLACE and INSERT ... ON DUPLICATE KEY UPDATE
1353
      if (before_record == NULL)
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1354
        result= transaction_services.insertRecord(*session, *table);
1143.2.27 by Jay Pipes
Corrects problems where REPLACE and INSERT ... ON DUPLICATE KEY UPDATE
1355
      else
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1356
        transaction_services.updateRecord(*session, *table, before_record, after_record);
1143.2.24 by Jay Pipes
Fixes some stuff from make check (include guards). Also adds stuff for REPLACE logic that does not work.
1357
    }
1143.2.22 by Jay Pipes
Adds functionality to handle REPLACE statements correctly in the replication
1358
    break;
661 by Brian Aker
First major pass through new replication.
1359
  case SQLCOM_INSERT:
1360
  case SQLCOM_INSERT_SELECT:
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1361
  case SQLCOM_LOAD:
1143.2.27 by Jay Pipes
Corrects problems where REPLACE and INSERT ... ON DUPLICATE KEY UPDATE
1362
    /*
1363
     * The else block below represents an 
1364
     * INSERT ... ON DUPLICATE KEY UPDATE that
1365
     * has hit a key conflict and actually done
1366
     * an update.
1367
     */
1368
    if (before_record == NULL)
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1369
      result= transaction_services.insertRecord(*session, *table);
1143.2.27 by Jay Pipes
Corrects problems where REPLACE and INSERT ... ON DUPLICATE KEY UPDATE
1370
    else
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1371
      transaction_services.updateRecord(*session, *table, before_record, after_record);
661 by Brian Aker
First major pass through new replication.
1372
    break;
1373
1374
  case SQLCOM_UPDATE:
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1375
    transaction_services.updateRecord(*session, *table, before_record, after_record);
661 by Brian Aker
First major pass through new replication.
1376
    break;
1377
1378
  case SQLCOM_DELETE:
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1379
    transaction_services.deleteRecord(*session, *table);
661 by Brian Aker
First major pass through new replication.
1380
    break;
1381
  default:
1382
    break;
1 by brian
clean slate
1383
  }
592 by Brian Aker
Remove one set.
1384
1143.4.15 by Jay Pipes
Adds error for when a record is inserted into a table containing
1385
  return result;
1 by brian
clean slate
1386
}
1387
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1388
int Cursor::ha_external_lock(Session *session, int lock_type)
1 by brian
clean slate
1389
{
1390
  /*
1391
    Whether this is lock or unlock, this should be true, and is to verify that
1392
    if get_auto_increment() was called (thus may have reserved intervals or
1393
    taken a table lock), ha_release_auto_increment() was too.
1394
  */
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1395
  assert(next_insert_id == 0);
1 by brian
clean slate
1396
1241.7.5 by Padraig O'Sullivan
Added the lock related dtrace probes to the cursor interface.
1397
  if (DRIZZLE_CURSOR_RDLOCK_START_ENABLED() ||
1398
      DRIZZLE_CURSOR_WRLOCK_START_ENABLED() ||
1399
      DRIZZLE_CURSOR_UNLOCK_START_ENABLED())
1400
  {
1401
    if (lock_type == F_RDLCK)
1402
    {
1869.1.2 by Brian Aker
Remove table_share from being required in a cursor.
1403
      DRIZZLE_CURSOR_RDLOCK_START(getTable()->getShare()->getSchemaName(),
1404
                                  getTable()->getShare()->getTableName());
1241.7.5 by Padraig O'Sullivan
Added the lock related dtrace probes to the cursor interface.
1405
    }
1406
    else if (lock_type == F_WRLCK)
1407
    {
1869.1.2 by Brian Aker
Remove table_share from being required in a cursor.
1408
      DRIZZLE_CURSOR_WRLOCK_START(getTable()->getShare()->getSchemaName(),
1409
                                  getTable()->getShare()->getTableName());
1241.7.5 by Padraig O'Sullivan
Added the lock related dtrace probes to the cursor interface.
1410
    }
1411
    else if (lock_type == F_UNLCK)
1412
    {
1869.1.2 by Brian Aker
Remove table_share from being required in a cursor.
1413
      DRIZZLE_CURSOR_UNLOCK_START(getTable()->getShare()->getSchemaName(),
1414
                                  getTable()->getShare()->getTableName());
1241.7.5 by Padraig O'Sullivan
Added the lock related dtrace probes to the cursor interface.
1415
    }
1416
  }
1417
1 by brian
clean slate
1418
  /*
1419
    We cache the table flags if the locking succeeded. Otherwise, we
1420
    keep them as they were when they were fetched in ha_open().
1421
  */
1422
520.1.22 by Brian Aker
Second pass of thd cleanup
1423
  int error= external_lock(session, lock_type);
1126.10.11 by Padraig O'Sullivan
Added calls to the dtrace probes related to locks.
1424
1241.7.5 by Padraig O'Sullivan
Added the lock related dtrace probes to the cursor interface.
1425
  if (DRIZZLE_CURSOR_RDLOCK_DONE_ENABLED() ||
1426
      DRIZZLE_CURSOR_WRLOCK_DONE_ENABLED() ||
1427
      DRIZZLE_CURSOR_UNLOCK_DONE_ENABLED())
1428
  {
1429
    if (lock_type == F_RDLCK)
1430
    {
1431
      DRIZZLE_CURSOR_RDLOCK_DONE(error);
1432
    }
1433
    else if (lock_type == F_WRLCK)
1434
    {
1435
      DRIZZLE_CURSOR_WRLOCK_DONE(error);
1436
    }
1437
    else if (lock_type == F_UNLCK)
1438
    {
1439
      DRIZZLE_CURSOR_UNLOCK_DONE(error);
1440
    }
1441
  }
1442
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1443
  return error;
1 by brian
clean slate
1444
}
1445
1446
1447
/**
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1448
  Check Cursor usage and reset state of file to after 'open'
1 by brian
clean slate
1449
*/
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1450
int Cursor::ha_reset()
1 by brian
clean slate
1451
{
1005.2.3 by Monty Taylor
Further reversion of P.
1452
  /* Check that we have called all proper deallocation functions */
1869.1.5 by Brian Aker
getTable()
1453
  assert(! getTable()->getShare()->all_set.none());
1454
  assert(getTable()->key_read == 0);
1491.1.10 by Jay Pipes
ha_rnd_init -> startTableScan, rnd_init -> doStartTableScan, ha_rnd_end -> endTableScan, rnd_end -> doEndTableScan
1455
  /* ensure that ha_index_end / endTableScan has been called */
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1456
  assert(inited == NONE);
1 by brian
clean slate
1457
  /* Free cache used by filesort */
1869.1.5 by Brian Aker
getTable()
1458
  getTable()->free_io_cache();
1 by brian
clean slate
1459
  /* reset the bitmaps to point to defaults */
1869.1.5 by Brian Aker
getTable()
1460
  getTable()->default_column_bitmaps();
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1461
  return(reset());
1 by brian
clean slate
1462
}
1463
1464
1491.1.2 by Jay Pipes
Cursor::write_row() -> Cursor::doInsertRecord(). Cursor::ha_write_row() -> Cursor::insertRecord()
1465
int Cursor::insertRecord(unsigned char *buf)
1 by brian
clean slate
1466
{
1467
  int error;
1468
1235.1.11 by Brian Aker
Small cleanups, did in MERGE table only engine flag.
1469
  /*
1470
   * If we have a timestamp column, update it to the current time
1471
   *
873.1.16 by Jay Pipes
This patch pulls the setting of the auto-set timestamp out of the individual
1472
   * @TODO Technically, the below two lines can be take even further out of the
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1473
   * Cursor interface and into the fill_record() method.
873.1.16 by Jay Pipes
This patch pulls the setting of the auto-set timestamp out of the individual
1474
   */
1869.1.5 by Brian Aker
getTable()
1475
  if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1607 by Brian Aker
Cursor now fully handles the update to timestamp for the engine.
1476
  {
1869.1.5 by Brian Aker
getTable()
1477
    getTable()->timestamp_field->set_time();
1607 by Brian Aker
Cursor now fully handles the update to timestamp for the engine.
1478
  }
873.1.16 by Jay Pipes
This patch pulls the setting of the auto-set timestamp out of the individual
1479
1869.1.2 by Brian Aker
Remove table_share from being required in a cursor.
1480
  DRIZZLE_INSERT_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
1481
  setTransactionReadWrite();
1502.5.2 by Barry.Leslie at PrimeBase
Changes made to drizzle source when building in the events plugin.
1482
  
1869.1.5 by Brian Aker
getTable()
1483
  if (unlikely(plugin::EventObserver::beforeInsertRecord(*getTable(), buf)))
1502.5.7 by Barry.Leslie at PrimeBase
Renamed the 'Event' plugin to 'EventObserver' plugin along with some internal class renames to make things clearer.
1484
  {
1485
    error= ER_EVENT_OBSERVER_PLUGIN;
1486
  }
1502.5.2 by Barry.Leslie at PrimeBase
Changes made to drizzle source when building in the events plugin.
1487
  else
1488
  {
1489
    error= doInsertRecord(buf);
1869.1.5 by Brian Aker
getTable()
1490
    if (unlikely(plugin::EventObserver::afterInsertRecord(*getTable(), buf, error))) 
1502.5.7 by Barry.Leslie at PrimeBase
Renamed the 'Event' plugin to 'EventObserver' plugin along with some internal class renames to make things clearer.
1491
    {
1492
      error= ER_EVENT_OBSERVER_PLUGIN;
1493
    }
1502.5.2 by Barry.Leslie at PrimeBase
Changes made to drizzle source when building in the events plugin.
1494
  }
1619.3.3 by Stewart Smith
move ha_statistic_increment for ha_write count (the Handler_write status variable) to the Cursor layer so that each Storage Engine's Cursor doesn't have to increment it.
1495
1496
  ha_statistic_increment(&system_status_var::ha_write_count);
1497
1241.7.4 by Padraig O'Sullivan
Inserted calls to the cursor related probes that fire on inserts, updates, and deletes.
1498
  DRIZZLE_INSERT_ROW_DONE(error);
1 by brian
clean slate
1499
1241.7.4 by Padraig O'Sullivan
Inserted calls to the cursor related probes that fire on inserts, updates, and deletes.
1500
  if (unlikely(error))
1126.10.17 by Padraig O'Sullivan
Added calls to the update related dtrace probes.
1501
  {
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1502
    return error;
1126.10.17 by Padraig O'Sullivan
Added calls to the update related dtrace probes.
1503
  }
662 by Brian Aker
Remove dead methods.
1504
1869.1.5 by Brian Aker
getTable()
1505
  if (unlikely(log_row_for_replication(getTable(), NULL, buf)))
971.6.11 by Eric Day
Removed purecov messages.
1506
    return HA_ERR_RBR_LOGGING_FAILED;
662 by Brian Aker
Remove dead methods.
1507
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1508
  return 0;
1 by brian
clean slate
1509
}
1510
1511
1491.1.3 by Jay Pipes
Cursor::update_row() changed to doUpdateRecord() and updateRecord()
1512
int Cursor::updateRecord(const unsigned char *old_data, unsigned char *new_data)
1 by brian
clean slate
1513
{
1514
  int error;
1515
1516
  /*
1672.3.6 by Brian Aker
First pass in encapsulating row
1517
    Some storage engines require that the new record is in getInsertRecord()
1518
    (and the old record is in getUpdateRecord()).
1 by brian
clean slate
1519
   */
1869.1.5 by Brian Aker
getTable()
1520
  assert(new_data == getTable()->getInsertRecord());
1 by brian
clean slate
1521
1869.1.2 by Brian Aker
Remove table_share from being required in a cursor.
1522
  DRIZZLE_UPDATE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
1523
  setTransactionReadWrite();
1869.1.5 by Brian Aker
getTable()
1524
  if (unlikely(plugin::EventObserver::beforeUpdateRecord(*getTable(), old_data, new_data)))
1502.5.7 by Barry.Leslie at PrimeBase
Renamed the 'Event' plugin to 'EventObserver' plugin along with some internal class renames to make things clearer.
1525
  {
1526
    error= ER_EVENT_OBSERVER_PLUGIN;
1527
  }
1502.5.2 by Barry.Leslie at PrimeBase
Changes made to drizzle source when building in the events plugin.
1528
  else
1529
  {
1869.1.5 by Brian Aker
getTable()
1530
    if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1607 by Brian Aker
Cursor now fully handles the update to timestamp for the engine.
1531
    {
1869.1.5 by Brian Aker
getTable()
1532
      getTable()->timestamp_field->set_time();
1607 by Brian Aker
Cursor now fully handles the update to timestamp for the engine.
1533
    }
1534
1502.5.2 by Barry.Leslie at PrimeBase
Changes made to drizzle source when building in the events plugin.
1535
    error= doUpdateRecord(old_data, new_data);
1869.1.5 by Brian Aker
getTable()
1536
    if (unlikely(plugin::EventObserver::afterUpdateRecord(*getTable(), old_data, new_data, error)))
1502.5.7 by Barry.Leslie at PrimeBase
Renamed the 'Event' plugin to 'EventObserver' plugin along with some internal class renames to make things clearer.
1537
    {
1538
      error= ER_EVENT_OBSERVER_PLUGIN;
1539
    }
1502.5.2 by Barry.Leslie at PrimeBase
Changes made to drizzle source when building in the events plugin.
1540
  }
1541
1619.3.5 by Stewart Smith
move ha_statistic_increment for ha_update_count (the Handler_update status variable) to the Cursor layer so that each Storage Engine's Cursor doesn't have to increment it.
1542
  ha_statistic_increment(&system_status_var::ha_update_count);
1543
1241.7.4 by Padraig O'Sullivan
Inserted calls to the cursor related probes that fire on inserts, updates, and deletes.
1544
  DRIZZLE_UPDATE_ROW_DONE(error);
1 by brian
clean slate
1545
1241.7.4 by Padraig O'Sullivan
Inserted calls to the cursor related probes that fire on inserts, updates, and deletes.
1546
  if (unlikely(error))
1126.10.17 by Padraig O'Sullivan
Added calls to the update related dtrace probes.
1547
  {
1 by brian
clean slate
1548
    return error;
1126.10.17 by Padraig O'Sullivan
Added calls to the update related dtrace probes.
1549
  }
1550
1869.1.5 by Brian Aker
getTable()
1551
  if (unlikely(log_row_for_replication(getTable(), old_data, new_data)))
662 by Brian Aker
Remove dead methods.
1552
    return HA_ERR_RBR_LOGGING_FAILED;
1553
1 by brian
clean slate
1554
  return 0;
1555
}
1869.1.2 by Brian Aker
Remove table_share from being required in a cursor.
1556
TableShare *Cursor::getShare()
1557
{
1558
  return getTable()->getMutableShare();
1559
}
1 by brian
clean slate
1560
1491.1.4 by Jay Pipes
delete_row() is now deleteRecord() and doDeleteRecord() in Cursor
1561
int Cursor::deleteRecord(const unsigned char *buf)
1 by brian
clean slate
1562
{
1563
  int error;
1564
1869.1.2 by Brian Aker
Remove table_share from being required in a cursor.
1565
  DRIZZLE_DELETE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
1566
  setTransactionReadWrite();
1869.1.5 by Brian Aker
getTable()
1567
  if (unlikely(plugin::EventObserver::beforeDeleteRecord(*getTable(), buf)))
1502.5.7 by Barry.Leslie at PrimeBase
Renamed the 'Event' plugin to 'EventObserver' plugin along with some internal class renames to make things clearer.
1568
  {
1569
    error= ER_EVENT_OBSERVER_PLUGIN;
1570
  }
1502.5.2 by Barry.Leslie at PrimeBase
Changes made to drizzle source when building in the events plugin.
1571
  else
1572
  {
1573
    error= doDeleteRecord(buf);
1869.1.5 by Brian Aker
getTable()
1574
    if (unlikely(plugin::EventObserver::afterDeleteRecord(*getTable(), buf, error)))
1502.5.7 by Barry.Leslie at PrimeBase
Renamed the 'Event' plugin to 'EventObserver' plugin along with some internal class renames to make things clearer.
1575
    {
1576
      error= ER_EVENT_OBSERVER_PLUGIN;
1577
    }
1502.5.2 by Barry.Leslie at PrimeBase
Changes made to drizzle source when building in the events plugin.
1578
  }
1579
1619.3.7 by Stewart Smith
move ha_statistic_increment for ha_delete_count (the Handler_delete status variable) to the Cursor layer so that each Storage Engine's Cursor doesn't have to increment it.
1580
  ha_statistic_increment(&system_status_var::ha_delete_count);
1581
1241.7.4 by Padraig O'Sullivan
Inserted calls to the cursor related probes that fire on inserts, updates, and deletes.
1582
  DRIZZLE_DELETE_ROW_DONE(error);
1 by brian
clean slate
1583
1241.7.4 by Padraig O'Sullivan
Inserted calls to the cursor related probes that fire on inserts, updates, and deletes.
1584
  if (unlikely(error))
1 by brian
clean slate
1585
    return error;
662 by Brian Aker
Remove dead methods.
1586
1869.1.5 by Brian Aker
getTable()
1587
  if (unlikely(log_row_for_replication(getTable(), buf, NULL)))
662 by Brian Aker
Remove dead methods.
1588
    return HA_ERR_RBR_LOGGING_FAILED;
1589
1 by brian
clean slate
1590
  return 0;
1591
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1592
1593
} /* namespace drizzled */