~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA */
15
16
/* This file defines the InnoDB handler: the interface between MySQL and InnoDB
17
NOTE: You can only use noninlined InnoDB functions in this file, because we
18
have disabled the InnoDB inlining in this file. */
19
20
/* TODO list for the InnoDB handler in 5.0:
21
  - Remove the flag trx->active_trans and look at trx->conc_state
22
  - fix savepoint functions to use savepoint storage area
23
  - Find out what kind of problems the OS X case-insensitivity causes to
24
    table and database names; should we 'normalize' the names like we do
25
    in Windows?
26
*/
27
28
243.1.14 by Jay Pipes
* Ensured all drizzled/field/x.cc files to include mysql_priv.h
29
#include <drizzled/common_includes.h>
212.5.13 by Monty Taylor
Moved my_sys/my_pthread/my_nosys and mysys_err to mysys.
30
#include <mysys/mysys_err.h>
1 by brian
clean slate
31
#include "ha_innodb.h"
481.1.24 by Monty Taylor
Split a method out into innodb_plugin_extras. Innodb is the only thing that uses it. I imagine we probably want to do something totally different with this...
32
#include <drizzled/innodb_plugin_extras.h>
1 by brian
clean slate
33
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
34
#ifndef DRIZZLE_SERVER
1 by brian
clean slate
35
/* This is needed because of Bug #3596.  Let us hope that pthread_mutex_t
36
is defined the same in both builds: the MySQL server and the InnoDB plugin. */
37
extern pthread_mutex_t LOCK_thread_count;
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
38
#endif /* DRIZZLE_SERVER */
1 by brian
clean slate
39
40
/** to protect innobase_open_files */
41
static pthread_mutex_t innobase_share_mutex;
42
/** to force correct commit order in binlog */
43
static pthread_mutex_t prepare_commit_mutex;
44
static ulong commit_threads = 0;
45
static pthread_mutex_t commit_threads_m;
46
static pthread_cond_t commit_cond;
47
static pthread_mutex_t commit_cond_m;
48
static bool innodb_inited = 0;
49
50
/*
51
  This needs to exist until the query cache callback is removed
52
  or learns to pass hton.
53
*/
54
static handlerton *innodb_hton_ptr;
55
398.1.9 by Monty Taylor
Cleaned up stuff out of global.h.
56
#ifdef __cplusplus
57
extern "C" {
58
#endif
59
286 by Brian Aker
Fix for Innodb bool issue.
60
static int64_t index_cond_func_innodb(void *arg);
1 by brian
clean slate
61
398.1.9 by Monty Taylor
Cleaned up stuff out of global.h.
62
#ifdef __cplusplus
63
}
64
#endif
1 by brian
clean slate
65
66
67
#define INSIDE_HA_INNOBASE_CC
68
69
/* Include necessary InnoDB headers */
70
extern "C" {
212.5.45 by Monty Taylor
Removed excess AM_CPPFLAGS from the tree. Now the only thing that should be in the include path should be -I${top_srcdir} and -I${top_builddir}w
71
#include "storage/innobase/include/univ.i"
72
#include "storage/innobase/include/os0file.h"
73
#include "storage/innobase/include/os0thread.h"
74
#include "storage/innobase/include/srv0start.h"
75
#include "storage/innobase/include/srv0srv.h"
76
#include "storage/innobase/include/trx0roll.h"
77
#include "storage/innobase/include/trx0trx.h"
78
#include "storage/innobase/include/trx0sys.h"
79
#include "storage/innobase/include/mtr0mtr.h"
80
#include "storage/innobase/include/row0ins.h"
81
#include "storage/innobase/include/row0mysql.h"
82
#include "storage/innobase/include/row0sel.h"
83
#include "storage/innobase/include/row0upd.h"
84
#include "storage/innobase/include/log0log.h"
85
#include "storage/innobase/include/lock0lock.h"
86
#include "storage/innobase/include/dict0crea.h"
87
#include "storage/innobase/include/btr0cur.h"
88
#include "storage/innobase/include/btr0btr.h"
89
#include "storage/innobase/include/fsp0fsp.h"
90
#include "storage/innobase/include/sync0sync.h"
91
#include "storage/innobase/include/fil0fil.h"
92
#include "storage/innobase/include/trx0xa.h"
93
#include "storage/innobase/include/thr0loc.h"
94
#include "storage/innobase/include/ha_prototypes.h"
1 by brian
clean slate
95
}
96
97
static const long AUTOINC_OLD_STYLE_LOCKING = 0;
98
static const long AUTOINC_NEW_STYLE_LOCKING = 1;
99
static const long AUTOINC_NO_LOCKING = 2;
100
101
static long innobase_mirrored_log_groups, innobase_log_files_in_group,
102
	innobase_log_buffer_size, innobase_buffer_pool_awe_mem_mb,
103
	innobase_additional_mem_pool_size, innobase_file_io_threads,
104
	innobase_lock_wait_timeout, innobase_force_recovery,
105
	innobase_open_files, innobase_autoinc_lock_mode;
106
53.2.2 by Monty Taylor
Updated everything that needs updating to compile with -std=gnu99 -pedantic
107
static int64_t innobase_buffer_pool_size, innobase_log_file_size;
1 by brian
clean slate
108
109
/* The default values for the following char* start-up parameters
110
are determined in innobase_init below: */
111
112
static char*	innobase_data_home_dir			= NULL;
113
static char*	innobase_data_file_path			= NULL;
114
static char*	innobase_log_group_home_dir		= NULL;
115
/* The following has a misleading name: starting from 4.0.5, this also
116
affects Windows: */
117
static char*	innobase_unix_file_flush_method		= NULL;
118
119
/* Below we have boolean-valued start-up parameters, and their default
120
values */
121
122
static ulong	innobase_fast_shutdown			= 1;
123
#ifdef UNIV_LOG_ARCHIVE
284 by Brian Aker
First pass Innodb my_bool removal.
124
static bool	innobase_log_archive			= FALSE;
1 by brian
clean slate
125
static char*	innobase_log_arch_dir			= NULL;
126
#endif /* UNIV_LOG_ARCHIVE */
278 by Brian Aker
Fixed my_bool issue in options.
127
static bool	innobase_use_doublewrite		= TRUE;
128
static bool	innobase_use_checksums			= TRUE;
129
static bool	innobase_file_per_table			= FALSE;
130
static bool	innobase_locks_unsafe_for_binlog	= FALSE;
131
static bool	innobase_rollback_on_timeout		= FALSE;
132
static bool	innobase_create_status_file		= FALSE;
133
static bool innobase_stats_on_metadata		= TRUE;
134
static bool	innobase_use_adaptive_hash_indexes	= TRUE;
1 by brian
clean slate
135
136
static char*	internal_innobase_data_file_path	= NULL;
137
138
/* The following counter is used to convey information to InnoDB
139
about server activity: in selects it is not sensible to call
140
srv_active_wake_master_thread after each fetch or search, we only do
141
it every INNOBASE_WAKE_INTERVAL'th step. */
142
143
#define INNOBASE_WAKE_INTERVAL	32
144
static ulong	innobase_active_counter	= 0;
145
146
static HASH	innobase_open_tables;
147
481 by Brian Aker
Remove all of uchar.
148
static unsigned char* innobase_get_key(INNOBASE_SHARE *share, size_t *length,
284 by Brian Aker
First pass Innodb my_bool removal.
149
                               bool not_used __attribute__((unused)));
1 by brian
clean slate
150
static INNOBASE_SHARE *get_share(const char *table_name);
151
static void free_share(INNOBASE_SHARE *share);
152
static int innobase_close_connection(handlerton *hton, THD* thd);
153
static int innobase_commit(handlerton *hton, THD* thd, bool all);
154
static int innobase_rollback(handlerton *hton, THD* thd, bool all);
155
static int innobase_rollback_to_savepoint(handlerton *hton, THD* thd, 
156
           void *savepoint);
157
static int innobase_savepoint(handlerton *hton, THD* thd, void *savepoint);
158
static int innobase_release_savepoint(handlerton *hton, THD* thd, 
159
           void *savepoint);
160
static handler *innobase_create_handler(handlerton *hton,
161
                                        TABLE_SHARE *table,
162
                                        MEM_ROOT *mem_root);
163
164
static const char innobase_hton_name[]= "InnoDB";
165
166
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
167
static DRIZZLE_THDVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG,
1 by brian
clean slate
168
  "Enable InnoDB support for the XA two-phase commit",
169
  /* check_func */ NULL, /* update_func */ NULL,
170
  /* default */ TRUE);
171
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
172
static DRIZZLE_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
1 by brian
clean slate
173
  "Enable InnoDB locking in LOCK TABLES",
174
  /* check_func */ NULL, /* update_func */ NULL,
175
  /* default */ TRUE);
176
177
static handler *innobase_create_handler(handlerton *hton,
178
                                        TABLE_SHARE *table, 
179
                                        MEM_ROOT *mem_root)
180
{
181
  return new (mem_root) ha_innobase(hton, table);
182
}
183
184
/***********************************************************************
185
This function is used to prepare X/Open XA distributed transaction   */
186
static
187
int
188
innobase_xa_prepare(
189
/*================*/
190
			/* out: 0 or error number */
191
	handlerton* hton,
192
	THD*	thd,	/* in: handle to the MySQL thread of the user
193
			whose XA transaction should be prepared */
194
	bool	all);	/* in: TRUE - commit transaction
195
			FALSE - the current SQL statement ended */
196
/***********************************************************************
197
This function is used to recover X/Open XA distributed transactions   */
198
static
199
int
200
innobase_xa_recover(
201
/*================*/
202
				/* out: number of prepared transactions
203
				stored in xid_list */
204
	handlerton* hton,
205
	XID*	xid_list,	/* in/out: prepared transactions */
206
	uint	len);		/* in: number of slots in xid_list */
207
/***********************************************************************
208
This function is used to commit one X/Open XA distributed transaction
209
which is in the prepared state */
210
static
211
int
212
innobase_commit_by_xid(
213
/*===================*/
214
			/* out: 0 or error number */
215
	handlerton* hton,
216
	XID*	xid);	/* in: X/Open XA transaction identification */
217
/***********************************************************************
218
This function is used to rollback one X/Open XA distributed transaction
219
which is in the prepared state */
220
static
221
int
222
innobase_rollback_by_xid(
223
/*=====================*/
224
			/* out: 0 or error number */
225
	handlerton* hton,
226
	XID	*xid);	/* in: X/Open XA transaction identification */
227
/***********************************************************************
228
Create a consistent view for a cursor based on current transaction
229
which is created if the corresponding MySQL thread still lacks one.
230
This consistent view is then used inside of MySQL when accessing records
231
using a cursor. */
232
static
233
void*
234
innobase_create_cursor_view(
235
/*========================*/
236
				/* out: pointer to cursor view or NULL */
237
	handlerton*	hton,	/* in: innobase hton */
238
	THD*		thd);	/* in: user thread handle */
239
/***********************************************************************
240
Set the given consistent cursor view to a transaction which is created
241
if the corresponding MySQL thread still lacks one. If the given
242
consistent cursor view is NULL global read view of a transaction is
243
restored to a transaction read view. */
244
static
245
void
246
innobase_set_cursor_view(
247
/*=====================*/
248
	handlerton* hton,
249
	THD*	thd,	/* in: user thread handle */
250
	void*	curview);/* in: Consistent cursor view to be set */
251
/***********************************************************************
252
Close the given consistent cursor view of a transaction and restore
253
global read view to a transaction read view. Transaction is created if the
254
corresponding MySQL thread still lacks one. */
255
static
256
void
257
innobase_close_cursor_view(
258
/*=======================*/
259
	handlerton* hton,
260
	THD*	thd,	/* in: user thread handle */
261
	void*	curview);/* in: Consistent read view to be closed */
262
/*********************************************************************
263
Removes all tables in the named database inside InnoDB. */
264
static
265
void
266
innobase_drop_database(
267
/*===================*/
268
			/* out: error number */
269
	handlerton* hton, /* in: handlerton of Innodb */
270
	char*	path);	/* in: database path; inside InnoDB the name
271
			of the last directory in the path is used as
272
			the database name: for example, in 'mysql/data/test'
273
			the database name is 'test' */
274
275
/*********************************************************************
276
Creates an InnoDB transaction struct for the thd if it does not yet have one.
277
Starts a new InnoDB transaction if a transaction is not yet started. And
278
assigns a new snapshot for a consistent read if the transaction does not yet
279
have one. */
280
static
281
int
282
innobase_start_trx_and_assign_read_view(
283
/*====================================*/
284
			/* out: 0 */
285
	handlerton* hton, /* in: Innodb handlerton */ 
286
	THD*	thd);	/* in: MySQL thread handle of the user for whom
287
			the transaction should be committed */
288
/********************************************************************
289
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
290
the logs, and the name of this function should be innobase_checkpoint. */
291
static
292
bool
293
innobase_flush_logs(
294
/*================*/
295
				/* out: TRUE if error */
296
	handlerton*	hton);	/* in: InnoDB handlerton */
297
298
/****************************************************************************
299
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
300
Monitor to the client. */
301
static
302
bool
303
innodb_show_status(
304
/*===============*/
305
	handlerton*	hton,	/* in: the innodb handlerton */
306
	THD*	thd,	/* in: the MySQL query thread of the caller */
307
	stat_print_fn *stat_print);
308
static
309
bool innobase_show_status(handlerton *hton, THD* thd, 
310
                          stat_print_fn* stat_print,
311
                          enum ha_stat_type stat_type);
312
313
/*********************************************************************
314
Commits a transaction in an InnoDB database. */
315
static
316
void
317
innobase_commit_low(
318
/*================*/
319
	trx_t*	trx);	/* in: transaction handle */
320
321
static SHOW_VAR innodb_status_variables[]= {
322
  {"buffer_pool_pages_data",
323
  (char*) &export_vars.innodb_buffer_pool_pages_data,	  SHOW_LONG},
324
  {"buffer_pool_pages_dirty",
325
  (char*) &export_vars.innodb_buffer_pool_pages_dirty,	  SHOW_LONG},
326
  {"buffer_pool_pages_flushed",
327
  (char*) &export_vars.innodb_buffer_pool_pages_flushed,  SHOW_LONG},
328
  {"buffer_pool_pages_free",
329
  (char*) &export_vars.innodb_buffer_pool_pages_free,	  SHOW_LONG},
330
  {"buffer_pool_pages_latched",
331
  (char*) &export_vars.innodb_buffer_pool_pages_latched,  SHOW_LONG},
332
  {"buffer_pool_pages_misc",
333
  (char*) &export_vars.innodb_buffer_pool_pages_misc,	  SHOW_LONG},
334
  {"buffer_pool_pages_total",
335
  (char*) &export_vars.innodb_buffer_pool_pages_total,	  SHOW_LONG},
336
  {"buffer_pool_read_ahead_rnd",
337
  (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
338
  {"buffer_pool_read_ahead_seq",
339
  (char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
340
  {"buffer_pool_read_requests",
341
  (char*) &export_vars.innodb_buffer_pool_read_requests,  SHOW_LONG},
342
  {"buffer_pool_reads",
343
  (char*) &export_vars.innodb_buffer_pool_reads,	  SHOW_LONG},
344
  {"buffer_pool_wait_free",
345
  (char*) &export_vars.innodb_buffer_pool_wait_free,	  SHOW_LONG},
346
  {"buffer_pool_write_requests",
347
  (char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
348
  {"data_fsyncs",
349
  (char*) &export_vars.innodb_data_fsyncs,		  SHOW_LONG},
350
  {"data_pending_fsyncs",
351
  (char*) &export_vars.innodb_data_pending_fsyncs,	  SHOW_LONG},
352
  {"data_pending_reads",
353
  (char*) &export_vars.innodb_data_pending_reads,	  SHOW_LONG},
354
  {"data_pending_writes",
355
  (char*) &export_vars.innodb_data_pending_writes,	  SHOW_LONG},
356
  {"data_read",
357
  (char*) &export_vars.innodb_data_read,		  SHOW_LONG},
358
  {"data_reads",
359
  (char*) &export_vars.innodb_data_reads,		  SHOW_LONG},
360
  {"data_writes",
361
  (char*) &export_vars.innodb_data_writes,		  SHOW_LONG},
362
  {"data_written",
363
  (char*) &export_vars.innodb_data_written,		  SHOW_LONG},
364
  {"dblwr_pages_written",
365
  (char*) &export_vars.innodb_dblwr_pages_written,	  SHOW_LONG},
366
  {"dblwr_writes",
367
  (char*) &export_vars.innodb_dblwr_writes,		  SHOW_LONG},
368
  {"log_waits",
369
  (char*) &export_vars.innodb_log_waits,		  SHOW_LONG},
370
  {"log_write_requests",
371
  (char*) &export_vars.innodb_log_write_requests,	  SHOW_LONG},
372
  {"log_writes",
373
  (char*) &export_vars.innodb_log_writes,		  SHOW_LONG},
374
  {"os_log_fsyncs",
375
  (char*) &export_vars.innodb_os_log_fsyncs,		  SHOW_LONG},
376
  {"os_log_pending_fsyncs",
377
  (char*) &export_vars.innodb_os_log_pending_fsyncs,	  SHOW_LONG},
378
  {"os_log_pending_writes",
379
  (char*) &export_vars.innodb_os_log_pending_writes,	  SHOW_LONG},
380
  {"os_log_written",
381
  (char*) &export_vars.innodb_os_log_written,		  SHOW_LONG},
382
  {"page_size",
383
  (char*) &export_vars.innodb_page_size,		  SHOW_LONG},
384
  {"pages_created",
385
  (char*) &export_vars.innodb_pages_created,		  SHOW_LONG},
386
  {"pages_read",
387
  (char*) &export_vars.innodb_pages_read,		  SHOW_LONG},
388
  {"pages_written",
389
  (char*) &export_vars.innodb_pages_written,		  SHOW_LONG},
390
  {"row_lock_current_waits",
391
  (char*) &export_vars.innodb_row_lock_current_waits,	  SHOW_LONG},
392
  {"row_lock_time",
393
  (char*) &export_vars.innodb_row_lock_time,		  SHOW_LONGLONG},
394
  {"row_lock_time_avg",
395
  (char*) &export_vars.innodb_row_lock_time_avg,	  SHOW_LONG},
396
  {"row_lock_time_max",
397
  (char*) &export_vars.innodb_row_lock_time_max,	  SHOW_LONG},
398
  {"row_lock_waits",
399
  (char*) &export_vars.innodb_row_lock_waits,		  SHOW_LONG},
400
  {"rows_deleted",
401
  (char*) &export_vars.innodb_rows_deleted,		  SHOW_LONG},
402
  {"rows_inserted",
403
  (char*) &export_vars.innodb_rows_inserted,		  SHOW_LONG},
404
  {"rows_read",
405
  (char*) &export_vars.innodb_rows_read,		  SHOW_LONG},
406
  {"rows_updated",
407
  (char*) &export_vars.innodb_rows_updated,		  SHOW_LONG},
461 by Monty Taylor
Removed NullS. bu-bye.
408
  {NULL, NULL, SHOW_LONG}
1 by brian
clean slate
409
};
410
411
/* General functions */
412
413
/**********************************************************************
414
Returns true if the thread is the replication thread on the slave
415
server. Used in srv_conc_enter_innodb() to determine if the thread
416
should be allowed to enter InnoDB - the replication thread is treated
417
differently than other threads. Also used in
418
srv_conc_force_exit_innodb(). */
419
extern "C"
420
ibool
421
thd_is_replication_slave_thread(
422
/*============================*/
423
			/* out: true if thd is the replication thread */
424
	void*	thd)	/* in: thread handle (THD*) */
425
{
426
	return((ibool) thd_slave_thread((THD*) thd));
427
}
428
429
/**********************************************************************
430
Save some CPU by testing the value of srv_thread_concurrency in inline
431
functions. */
432
inline
433
void
434
innodb_srv_conc_enter_innodb(
435
/*=========================*/
436
	trx_t*	trx)	/* in: transaction handle */
437
{
438
	if (UNIV_LIKELY(!srv_thread_concurrency)) {
439
440
		return;
441
	}
442
443
	srv_conc_enter_innodb(trx);
444
}
445
446
/**********************************************************************
447
Save some CPU by testing the value of srv_thread_concurrency in inline
448
functions. */
449
inline
450
void
451
innodb_srv_conc_exit_innodb(
452
/*========================*/
453
	trx_t*	trx)	/* in: transaction handle */
454
{
455
	if (UNIV_LIKELY(!srv_thread_concurrency)) {
456
457
		return;
458
	}
459
460
	srv_conc_exit_innodb(trx);
461
}
462
463
/**********************************************************************
464
Releases possible search latch and InnoDB thread FIFO ticket. These should
465
be released at each SQL statement end, and also when mysqld passes the
466
control to the client. It does no harm to release these also in the middle
467
of an SQL statement. */
468
inline
469
void
470
innobase_release_stat_resources(
471
/*============================*/
472
	trx_t*	trx)	/* in: transaction object */
473
{
474
	if (trx->has_search_latch) {
475
		trx_search_latch_release_if_reserved(trx);
476
	}
477
478
	if (trx->declared_to_be_inside_innodb) {
479
		/* Release our possible ticket in the FIFO */
480
481
		srv_conc_force_exit_innodb(trx);
482
	}
483
}
484
485
/**********************************************************************
486
Returns true if the transaction this thread is processing has edited
487
non-transactional tables. Used by the deadlock detector when deciding
488
which transaction to rollback in case of a deadlock - we try to avoid
489
rolling back transactions that have edited non-transactional tables. */
490
extern "C"
491
ibool
492
thd_has_edited_nontrans_tables(
493
/*===========================*/
494
			/* out: true if non-transactional tables have
495
			been edited */
496
	void*	thd)	/* in: thread handle (THD*) */
497
{
498
	return((ibool) thd_non_transactional_update((THD*) thd));
499
}
500
501
/************************************************************************
502
Obtain the InnoDB transaction of a MySQL thread. */
503
inline
504
trx_t*&
505
thd_to_trx(
506
/*=======*/
507
			/* out: reference to transaction pointer */
508
	THD*	thd)	/* in: MySQL thread */
509
{
510
	return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr));
511
}
512
513
/************************************************************************
514
Call this function when mysqld passes control to the client. That is to
515
avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
516
documentation, see handler.cc. */
517
static
518
int
519
innobase_release_temporary_latches(
520
/*===============================*/
521
				/* out: 0 */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
522
        handlerton*	hton __attribute__((unused)),	/* in: handlerton */
1 by brian
clean slate
523
	THD*		thd)	/* in: MySQL thread */
524
{
525
	trx_t*	trx;
526
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
527
	assert(hton == innodb_hton_ptr);
1 by brian
clean slate
528
529
	if (!innodb_inited) {
530
531
		return 0;
532
	}
533
534
	trx = thd_to_trx(thd);
535
536
	if (trx) {
537
		innobase_release_stat_resources(trx);
538
	}
539
	return 0;
540
}
541
542
/************************************************************************
543
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
544
time calls srv_active_wake_master_thread. This function should be used
545
when a single database operation may introduce a small need for
546
server utility activity, like checkpointing. */
547
inline
548
void
549
innobase_active_small(void)
550
/*=======================*/
551
{
552
	innobase_active_counter++;
553
554
	if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
555
		srv_active_wake_master_thread();
556
	}
557
}
558
559
/************************************************************************
560
Converts an InnoDB error code to a MySQL error code and also tells to MySQL
561
about a possible transaction rollback inside InnoDB caused by a lock wait
562
timeout or a deadlock. */
563
static
564
int
565
convert_error_code_to_mysql(
566
/*========================*/
567
			/* out: MySQL error code */
568
	int	error,	/* in: InnoDB error code */
569
	THD*	thd)	/* in: user thread handle or NULL */
570
{
571
	if (error == DB_SUCCESS) {
572
573
		return(0);
574
575
	} else if (error == (int) DB_DUPLICATE_KEY) {
576
577
		return(HA_ERR_FOUND_DUPP_KEY);
578
579
	} else if (error == (int) DB_FOREIGN_DUPLICATE_KEY) {
580
581
		return(HA_ERR_FOREIGN_DUPLICATE_KEY);
582
583
	} else if (error == (int) DB_RECORD_NOT_FOUND) {
584
585
		return(HA_ERR_NO_ACTIVE_RECORD);
586
587
	} else if (error == (int) DB_ERROR) {
588
589
		return(-1); /* unspecified error */
590
591
	} else if (error == (int) DB_DEADLOCK) {
592
		/* Since we rolled back the whole transaction, we must
593
		tell it also to MySQL so that MySQL knows to empty the
594
		cached binlog for this transaction */
595
596
                thd_mark_transaction_to_rollback(thd, TRUE);
597
598
		return(HA_ERR_LOCK_DEADLOCK);
599
	} else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {
600
601
		/* Starting from 5.0.13, we let MySQL just roll back the
602
		latest SQL statement in a lock wait timeout. Previously, we
603
		rolled back the whole transaction. */
604
605
                thd_mark_transaction_to_rollback(thd,
606
                                             (bool)row_rollback_on_timeout);
607
608
		return(HA_ERR_LOCK_WAIT_TIMEOUT);
609
610
	} else if (error == (int) DB_NO_REFERENCED_ROW) {
611
612
		return(HA_ERR_NO_REFERENCED_ROW);
613
614
	} else if (error == (int) DB_ROW_IS_REFERENCED) {
615
616
		return(HA_ERR_ROW_IS_REFERENCED);
617
618
	} else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) {
619
620
		return(HA_ERR_CANNOT_ADD_FOREIGN);
621
622
	} else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) {
623
624
		return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
625
						misleading, a new MySQL error
626
						code should be introduced */
627
	} else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
628
629
		return(HA_ERR_CRASHED);
630
631
	} else if (error == (int) DB_OUT_OF_FILE_SPACE) {
632
633
		return(HA_ERR_RECORD_FILE_FULL);
634
635
	} else if (error == (int) DB_TABLE_IS_BEING_USED) {
636
637
		return(HA_ERR_WRONG_COMMAND);
638
639
	} else if (error == (int) DB_TABLE_NOT_FOUND) {
640
641
		return(HA_ERR_NO_SUCH_TABLE);
642
643
	} else if (error == (int) DB_TOO_BIG_RECORD) {
644
645
		return(HA_ERR_TO_BIG_ROW);
646
647
	} else if (error == (int) DB_CORRUPTION) {
648
649
		return(HA_ERR_CRASHED);
650
	} else if (error == (int) DB_NO_SAVEPOINT) {
651
652
		return(HA_ERR_NO_SAVEPOINT);
653
	} else if (error == (int) DB_LOCK_TABLE_FULL) {
654
 		/* Since we rolled back the whole transaction, we must
655
 		tell it also to MySQL so that MySQL knows to empty the
656
 		cached binlog for this transaction */
657
658
                thd_mark_transaction_to_rollback(thd, TRUE);
659
660
    		return(HA_ERR_LOCK_TABLE_FULL);
661
	} else if (error == DB_TOO_MANY_CONCURRENT_TRXS) {
662
663
		/* Once MySQL add the appropriate code to errmsg.txt then
664
		we can get rid of this #ifdef. NOTE: The code checked by
665
		the #ifdef is the suggested name for the error condition
666
		and the actual error code name could very well be different.
667
		This will require some monitoring, ie. the status
668
		of this request on our part.*/
669
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
670
		return(ER_TOO_MANY_CONCURRENT_TRXS);
671
#else
672
		return(HA_ERR_RECORD_FILE_FULL);
673
#endif
674
675
	} else if (error == DB_UNSUPPORTED) {
676
677
		return(HA_ERR_UNSUPPORTED);
678
    	} else {
679
    		return(-1);			// Unknown error
680
    	}
681
}
682
683
/*****************************************************************
684
If you want to print a thd that is not associated with the current thread,
685
you must call this function before reserving the InnoDB kernel_mutex, to
686
protect MySQL from setting thd->query NULL. If you print a thd of the current
687
thread, we know that MySQL cannot modify thd->query, and it is not necessary
688
to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release
689
the kernel_mutex.
690
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
691
function! */
692
extern "C"
693
void
694
innobase_mysql_prepare_print_arbitrary_thd(void)
695
/*============================================*/
696
{
398.1.10 by Monty Taylor
Actually removed VOID() this time.
697
	pthread_mutex_lock(&LOCK_thread_count);
1 by brian
clean slate
698
}
699
700
/*****************************************************************
701
Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
702
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
703
function! */
704
extern "C"
705
void
706
innobase_mysql_end_print_arbitrary_thd(void)
707
/*========================================*/
708
{
398.1.10 by Monty Taylor
Actually removed VOID() this time.
709
	pthread_mutex_unlock(&LOCK_thread_count);
1 by brian
clean slate
710
}
711
712
/*****************************************************************
713
Prints info of a THD object (== user session thread) to the given file.
714
NOTE that /mysql/innobase/trx/trx0trx.c must contain the prototype for
715
this function! */
716
extern "C"
717
void
718
innobase_mysql_print_thd(
719
/*=====================*/
720
	FILE*	f,		/* in: output stream */
265 by brian
First pass through cleaning up security context.
721
	void*	input_thd __attribute__((unused)),	/* in: pointer to a MySQL THD object */
722
	uint	max_query_len __attribute__((unused)))	/* in: max query length to print, or 0 to
1 by brian
clean slate
723
				   use the default max length */
724
{
265 by brian
First pass through cleaning up security context.
725
        fputs("Unknown thread accessing table", f);
1 by brian
clean slate
726
	putc('\n', f);
727
}
728
729
/**********************************************************************
730
Get the variable length bounds of the given character set.
731
732
NOTE that the exact prototype of this function has to be in
733
/innobase/include/data0type.ic! */
734
extern "C"
735
void
736
innobase_get_cset_width(
737
/*====================*/
738
	ulint	cset,		/* in: MySQL charset-collation code */
739
	ulint*	mbminlen,	/* out: minimum length of a char (in bytes) */
740
	ulint*	mbmaxlen)	/* out: maximum length of a char (in bytes) */
741
{
742
	CHARSET_INFO*	cs;
743
	ut_ad(cset < 256);
744
	ut_ad(mbminlen);
745
	ut_ad(mbmaxlen);
746
747
	cs = all_charsets[cset];
748
	if (cs) {
749
		*mbminlen = cs->mbminlen;
750
		*mbmaxlen = cs->mbmaxlen;
751
	} else {
752
		ut_a(cset == 0);
753
		*mbminlen = *mbmaxlen = 0;
754
	}
755
}
756
757
/**********************************************************************
758
Converts an identifier to a table name.
759
760
NOTE that the exact prototype of this function has to be in
761
/innobase/dict/dict0dict.c! */
762
extern "C"
763
void
764
innobase_convert_from_table_id(
765
/*===========================*/
766
	char*		to,	/* out: converted identifier */
767
	const char*	from,	/* in: identifier to convert */
768
	ulint		len)	/* in: length of 'to', in bytes */
769
{
770
	uint	errors;
771
772
	strconvert(thd_charset(current_thd), from,
773
		   &my_charset_filename, to, (uint) len, &errors);
774
}
775
776
/**********************************************************************
777
Converts an identifier to UTF-8.
778
779
NOTE that the exact prototype of this function has to be in
780
/innobase/dict/dict0dict.c! */
781
extern "C"
782
void
783
innobase_convert_from_id(
784
/*=====================*/
785
	char*		to,	/* out: converted identifier */
786
	const char*	from,	/* in: identifier to convert */
787
	ulint		len)	/* in: length of 'to', in bytes */
788
{
789
	uint	errors;
790
791
	strconvert(thd_charset(current_thd), from,
792
		   system_charset_info, to, (uint) len, &errors);
793
}
794
795
/**********************************************************************
796
Compares NUL-terminated UTF-8 strings case insensitively.
797
798
NOTE that the exact prototype of this function has to be in
799
/innobase/dict/dict0dict.c! */
800
extern "C"
801
int
802
innobase_strcasecmp(
803
/*================*/
804
				/* out: 0 if a=b, <0 if a<b, >1 if a>b */
805
	const char*	a,	/* in: first string to compare */
806
	const char*	b)	/* in: second string to compare */
807
{
808
	return(my_strcasecmp(system_charset_info, a, b));
809
}
810
811
/**********************************************************************
812
Makes all characters in a NUL-terminated UTF-8 string lower case.
813
814
NOTE that the exact prototype of this function has to be in
815
/innobase/dict/dict0dict.c! */
816
extern "C"
817
void
818
innobase_casedn_str(
819
/*================*/
820
	char*	a)	/* in/out: string to put in lower case */
821
{
822
	my_casedn_str(system_charset_info, a);
823
}
824
825
/**************************************************************************
826
Determines the connection character set.
827
828
NOTE that the exact prototype of this function has to be in
829
/innobase/dict/dict0dict.c! */
830
extern "C"
831
struct charset_info_st*
832
innobase_get_charset(
833
/*=================*/
834
				/* out: connection character set */
835
	void*	mysql_thd)	/* in: MySQL thread handle */
836
{
837
	return(thd_charset((THD*) mysql_thd));
838
}
839
840
/*************************************************************************
841
Creates a temporary file. */
842
extern "C"
843
int
844
innobase_mysql_tmpfile(void)
845
/*========================*/
846
			/* out: temporary file descriptor, or < 0 on error */
847
{
848
	int	fd2 = -1;
849
	File	fd = mysql_tmpfile("ib");
850
	if (fd >= 0) {
851
		/* Copy the file descriptor, so that the additional resources
852
		allocated by create_temp_file() can be freed by invoking
853
		my_close().
854
855
		Because the file descriptor returned by this function
856
		will be passed to fdopen(), it will be closed by invoking
857
		fclose(), which in turn will invoke close() instead of
858
		my_close(). */
859
		fd2 = dup(fd);
860
		if (fd2 < 0) {
861
			my_errno=errno;
862
			my_error(EE_OUT_OF_FILERESOURCES,
863
				 MYF(ME_BELL+ME_WAITTANG),
864
				 "ib*", my_errno);
865
		}
866
		my_close(fd, MYF(MY_WME));
867
	}
868
	return(fd2);
869
}
870
871
/*************************************************************************
872
Wrapper around MySQL's copy_and_convert function, see it for
873
documentation. */
874
extern "C"
875
ulint
876
innobase_convert_string(
877
/*====================*/
878
	void*		to,
879
	ulint		to_length,
880
	CHARSET_INFO*	to_cs,
881
	const void*	from,
882
	ulint		from_length,
883
	CHARSET_INFO*	from_cs,
884
	uint*		errors)
885
{
205 by Brian Aker
uint32 -> uin32_t
886
  return(copy_and_convert((char*)to, (uint32_t) to_length, to_cs,
887
                          (const char*)from, (uint32_t) from_length, from_cs,
1 by brian
clean slate
888
                          errors));
889
}
890
891
/*************************************************************************
892
Gets the InnoDB transaction handle for a MySQL handler object, creates
893
an InnoDB transaction struct if the corresponding MySQL thread struct still
894
lacks one. */
895
static
896
trx_t*
897
check_trx_exists(
898
/*=============*/
899
			/* out: InnoDB transaction handle */
900
	THD*	thd)	/* in: user thread handle */
901
{
902
	trx_t*&	trx = thd_to_trx(thd);
903
904
	ut_ad(thd == current_thd);
905
906
	if (trx == NULL) {
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
907
		assert(thd != NULL);
1 by brian
clean slate
908
		trx = trx_allocate_for_mysql();
909
910
		trx->mysql_thd = thd;
911
		trx->mysql_query_str = thd_query(thd);
912
913
		/* Update the info whether we should skip XA steps that eat
914
		CPU time */
915
		trx->support_xa = THDVAR(thd, support_xa);
916
	} else {
917
		if (trx->magic_n != TRX_MAGIC_N) {
918
			mem_analyze_corruption(trx);
919
920
			ut_error;
921
		}
922
	}
923
924
	if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
925
		trx->check_foreigns = FALSE;
926
	} else {
927
		trx->check_foreigns = TRUE;
928
	}
929
930
	if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
931
		trx->check_unique_secondary = FALSE;
932
	} else {
933
		trx->check_unique_secondary = TRUE;
934
	}
935
936
	return(trx);
937
}
938
939
940
/*************************************************************************
941
Construct ha_innobase handler. */
942
943
ha_innobase::ha_innobase(handlerton *hton, TABLE_SHARE *table_arg)
944
  :handler(hton, table_arg),
945
  int_table_flags(HA_REC_NOT_IN_SEQ |
946
		  HA_NULL_IN_KEY |
947
		  HA_CAN_INDEX_BLOBS |
948
		  HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
949
		  HA_PRIMARY_KEY_IN_READ_INDEX |
950
		  HA_BINLOG_ROW_CAPABLE |
413.2.2 by Brian Aker
Removed UNSIGNED from parser.
951
		  HA_PARTIAL_COLUMN_READ |
1 by brian
clean slate
952
		  HA_TABLE_SCAN_ON_INDEX | HA_NEED_READ_RANGE_BUFFER |
953
                  HA_MRR_CANT_SORT),
954
  primary_key(0), /* needs initialization because index_flags() may be called 
955
                     before this is set to the real value. It's ok to have any 
956
                     value here because it doesn't matter if we return the
957
                     HA_DO_INDEX_COND_PUSHDOWN bit from those "early" calls */
958
  start_of_scan(0),
959
  num_write_row(0)
960
{
961
//  ds_mrr.init(this, table, (DsMrr_impl::range_check_toggle_func_t)
962
//                            &ha_innobase::toggle_range_check);
963
}
964
965
/*************************************************************************
966
Updates the user_thd field in a handle and also allocates a new InnoDB
967
transaction handle if needed, and updates the transaction fields in the
968
prebuilt struct. */
969
inline
970
int
971
ha_innobase::update_thd(
972
/*====================*/
973
			/* out: 0 or error code */
974
	THD*	thd)	/* in: thd to use the handle */
975
{
976
	trx_t*		trx;
977
978
	trx = check_trx_exists(thd);
979
980
	if (prebuilt->trx != trx) {
981
982
		row_update_prebuilt_trx(prebuilt, trx);
983
	}
984
985
	user_thd = thd;
986
987
	return(0);
988
}
989
990
/*************************************************************************
991
Registers that InnoDB takes part in an SQL statement, so that MySQL knows to
992
roll back the statement if the statement results in an error. This MUST be
993
called for every SQL statement that may be rolled back by MySQL. Calling this
994
several times to register the same statement is allowed, too. */
995
inline
996
void
997
innobase_register_stmt(
998
/*===================*/
999
        handlerton*	hton,	/* in: Innobase hton */
1000
	THD*	thd)	/* in: MySQL thd (connection) object */
1001
{
1002
	/* Register the statement */
1003
	trans_register_ha(thd, FALSE, hton);
1004
}
1005
1006
/*************************************************************************
1007
Registers an InnoDB transaction in MySQL, so that the MySQL XA code knows
1008
to call the InnoDB prepare and commit, or rollback for the transaction. This
1009
MUST be called for every transaction for which the user may call commit or
1010
rollback. Calling this several times to register the same transaction is
1011
allowed, too.
1012
This function also registers the current SQL statement. */
1013
inline
1014
void
1015
innobase_register_trx_and_stmt(
1016
/*===========================*/
1017
        handlerton *hton, /* in: Innobase handlerton */
1018
	THD*	thd)	/* in: MySQL thd (connection) object */
1019
{
1020
	/* NOTE that actually innobase_register_stmt() registers also
1021
	the transaction in the AUTOCOMMIT=1 mode. */
1022
1023
	innobase_register_stmt(hton, thd);
1024
1025
	if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
1026
1027
		/* No autocommit mode, register for a transaction */
1028
		trans_register_ha(thd, TRUE, hton);
1029
	}
1030
}
1031
1032
/*   BACKGROUND INFO: HOW THE MYSQL QUERY CACHE WORKS WITH INNODB
1033
     ------------------------------------------------------------
1034
1035
1) The use of the query cache for TBL is disabled when there is an
1036
uncommitted change to TBL.
1037
1038
2) When a change to TBL commits, InnoDB stores the current value of
1039
its global trx id counter, let us denote it by INV_TRX_ID, to the table object
1040
in the InnoDB data dictionary, and does only allow such transactions whose
1041
id <= INV_TRX_ID to use the query cache.
1042
1043
3) When InnoDB does an INSERT/DELETE/UPDATE to a table TBL, or an implicit
1044
modification because an ON DELETE CASCADE, we invalidate the MySQL query cache
1045
of TBL immediately.
1046
1047
How this is implemented inside InnoDB:
1048
1049
1) Since every modification always sets an IX type table lock on the InnoDB
1050
table, it is easy to check if there can be uncommitted modifications for a
1051
table: just check if there are locks in the lock list of the table.
1052
1053
2) When a transaction inside InnoDB commits, it reads the global trx id
1054
counter and stores the value INV_TRX_ID to the tables on which it had a lock.
1055
1056
3) If there is an implicit table change from ON DELETE CASCADE or SET NULL,
1057
InnoDB calls an invalidate method for the MySQL query cache for that table.
1058
1059
How this is implemented inside sql_cache.cc:
1060
1061
1) The query cache for an InnoDB table TBL is invalidated immediately at an
1062
INSERT/UPDATE/DELETE, just like in the case of MyISAM. No need to delay
1063
invalidation to the transaction commit.
1064
1065
2) To store or retrieve a value from the query cache of an InnoDB table TBL,
1066
any query must first ask InnoDB's permission. We must pass the thd as a
1067
parameter because InnoDB will look at the trx id, if any, associated with
1068
that thd.
1069
1070
3) Use of the query cache for InnoDB tables is now allowed also when
1071
AUTOCOMMIT==0 or we are inside BEGIN ... COMMIT. Thus transactions no longer
1072
put restrictions on the use of the query cache.
1073
*/
1074
1075
/**********************************************************************
1076
The MySQL query cache uses this to check from InnoDB if the query cache at
1077
the moment is allowed to operate on an InnoDB table. The SQL query must
1078
be a non-locking SELECT.
1079
1080
The query cache is allowed to operate on certain query only if this function
1081
returns TRUE for all tables in the query.
1082
1083
If thd is not in the autocommit state, this function also starts a new
1084
transaction for thd if there is no active trx yet, and assigns a consistent
1085
read view to it if there is no read view yet.
1086
1087
Why a deadlock of threads is not possible: the query cache calls this function
1088
at the start of a SELECT processing. Then the calling thread cannot be
1089
holding any InnoDB semaphores. The calling thread is holding the
1090
query cache mutex, and this function will reserver the InnoDB kernel mutex.
1091
Thus, the 'rank' in sync0sync.h of the MySQL query cache mutex is above
1092
the InnoDB kernel mutex. */
1093
static
199 by Brian Aker
my_bool...
1094
bool
1 by brian
clean slate
1095
innobase_query_caching_of_table_permitted(
1096
/*======================================*/
1097
				/* out: TRUE if permitted, FALSE if not;
1098
				note that the value FALSE does not mean
1099
				we should invalidate the query cache:
1100
				invalidation is called explicitly */
1101
	THD*	thd,		/* in: thd of the user who is trying to
1102
				store a result to the query cache or
1103
				retrieve it */
1104
	char*	full_name,	/* in: concatenation of database name,
1105
				the null character '\0', and the table
1106
				name */
1107
	uint	full_name_len,	/* in: length of the full name, i.e.
1108
				len(dbname) + len(tablename) + 1 */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1109
	uint64_t *unused __attribute__((unused)))	/* unused for this engine */
1 by brian
clean slate
1110
{
1111
	ibool	is_autocommit;
1112
	trx_t*	trx;
1113
	char	norm_name[1000];
1114
1115
	ut_a(full_name_len < 999);
1116
1117
	trx = check_trx_exists(thd);
1118
1119
	if (trx->isolation_level == TRX_ISO_SERIALIZABLE) {
1120
		/* In the SERIALIZABLE mode we add LOCK IN SHARE MODE to every
1121
		plain SELECT if AUTOCOMMIT is not on. */
1122
285 by Brian Aker
Second pass.
1123
		return false;
1 by brian
clean slate
1124
	}
1125
1126
	if (trx->has_search_latch) {
1127
		sql_print_error("The calling thread is holding the adaptive "
1128
				"search, latch though calling "
1129
				"innobase_query_caching_of_table_permitted.");
1130
1131
		mutex_enter_noninline(&kernel_mutex);
1132
		trx_print(stderr, trx, 1024);
1133
		mutex_exit_noninline(&kernel_mutex);
1134
	}
1135
1136
	innobase_release_stat_resources(trx);
1137
1138
	if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
1139
1140
		is_autocommit = TRUE;
1141
	} else {
1142
		is_autocommit = FALSE;
1143
1144
	}
1145
1146
	if (is_autocommit && trx->n_mysql_tables_in_use == 0) {
1147
		/* We are going to retrieve the query result from the query
1148
		cache. This cannot be a store operation to the query cache
1149
		because then MySQL would have locks on tables already.
1150
1151
		TODO: if the user has used LOCK TABLES to lock the table,
1152
		then we open a transaction in the call of row_.. below.
1153
		That trx can stay open until UNLOCK TABLES. The same problem
1154
		exists even if we do not use the query cache. MySQL should be
1155
		modified so that it ALWAYS calls some cleanup function when
1156
		the processing of a query ends!
1157
1158
		We can imagine we instantaneously serialize this consistent
1159
		read trx to the current trx id counter. If trx2 would have
1160
		changed the tables of a query result stored in the cache, and
1161
		trx2 would have already committed, making the result obsolete,
1162
		then trx2 would have already invalidated the cache. Thus we
1163
		can trust the result in the cache is ok for this query. */
1164
285 by Brian Aker
Second pass.
1165
          return true;
1 by brian
clean slate
1166
	}
1167
1168
	/* Normalize the table name to InnoDB format */
1169
1170
	memcpy(norm_name, full_name, full_name_len);
1171
1172
	norm_name[strlen(norm_name)] = '/'; /* InnoDB uses '/' as the
1173
					    separator between db and table */
1174
	norm_name[full_name_len] = '\0';
1175
#ifdef __WIN__
1176
	innobase_casedn_str(norm_name);
1177
#endif
1178
	/* The call of row_search_.. will start a new transaction if it is
1179
	not yet started */
1180
1181
	if (trx->active_trans == 0) {
1182
1183
		innobase_register_trx_and_stmt(innodb_hton_ptr, thd);
1184
		trx->active_trans = 1;
1185
	}
1186
1187
	if (row_search_check_if_query_cache_permitted(trx, norm_name)) {
1188
1189
		/* printf("Query cache for %s permitted\n", norm_name); */
1190
285 by Brian Aker
Second pass.
1191
          return true;
1 by brian
clean slate
1192
	}
1193
1194
	/* printf("Query cache for %s NOT permitted\n", norm_name); */
1195
285 by Brian Aker
Second pass.
1196
        return false;
1 by brian
clean slate
1197
}
1198
1199
/*********************************************************************
1200
Invalidates the MySQL query cache for the table.
1201
NOTE that the exact prototype of this function has to be in
1202
/innobase/row/row0ins.c! */
1203
extern "C"
1204
void
1205
innobase_invalidate_query_cache(
1206
/*============================*/
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1207
	trx_t*	trx __attribute__((unused)),		/* in: transaction which modifies the table */
1208
	char*	full_name __attribute__((unused)),	/* in: concatenation of database name, null
1 by brian
clean slate
1209
				char '\0', table name, null char'\0';
1210
				NOTE that in Windows this is always
1211
				in LOWER CASE! */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1212
	ulint	full_name_len __attribute__((unused)))	/* in: full name length where also the null
1 by brian
clean slate
1213
				chars count */
1214
{
1215
	/* Note that the sync0sync.h rank of the query cache mutex is just
1216
	above the InnoDB kernel mutex. The caller of this function must not
1217
	have latches of a lower rank. */
1218
1219
	/* Argument TRUE below means we are using transactions */
1220
#ifdef HAVE_QUERY_CACHE
1221
	mysql_query_cache_invalidate4((THD*) trx->mysql_thd,
1222
				      (const char*) full_name,
205 by Brian Aker
uint32 -> uin32_t
1223
				      (uint32_t) full_name_len,
1 by brian
clean slate
1224
				      TRUE);
1225
#endif
1226
}
1227
1228
/*********************************************************************
1229
Display an SQL identifier. */
1230
extern "C"
1231
void
1232
innobase_print_identifier(
1233
/*======================*/
1234
	FILE*		f,	/* in: output stream */
1235
	trx_t*		trx,	/* in: transaction */
1236
	ibool		table_id,/* in: TRUE=print a table name,
1237
				FALSE=print other identifier */
1238
	const char*	name,	/* in: name to print */
1239
	ulint		namelen)/* in: length of name */
1240
{
1241
	const char*	s	= name;
1242
	char*		qname	= NULL;
1243
	int		q;
1244
1245
	if (table_id) {
1246
		/* Decode the table name.  The filename_to_tablename()
1247
		function expects a NUL-terminated string.  The input and
1248
		output strings buffers must not be shared.  The function
1249
		only produces more output when the name contains other
1250
		characters than [0-9A-Z_a-z]. */
1251
          char*	temp_name = (char*) my_malloc((uint) namelen + 1, MYF(MY_WME));
1252
          uint	qnamelen = (uint) (namelen
1253
                                   + (1 + sizeof srv_mysql50_table_name_prefix));
1254
1255
		if (temp_name) {
1256
                  qname = (char*) my_malloc(qnamelen, MYF(MY_WME));
1257
			if (qname) {
1258
				memcpy(temp_name, name, namelen);
1259
				temp_name[namelen] = 0;
1260
				s = qname;
1261
				namelen = filename_to_tablename(temp_name,
1262
						qname, qnamelen);
1263
			}
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1264
			free(temp_name);
1 by brian
clean slate
1265
		}
1266
	}
1267
1268
	if (!trx || !trx->mysql_thd) {
1269
1270
		q = '"';
1271
	} else {
1272
		q = get_quote_char_for_identifier((THD*) trx->mysql_thd,
1273
						s, (int) namelen);
1274
	}
1275
1276
	if (q == EOF) {
1277
		fwrite(s, 1, namelen, f);
1278
	} else {
1279
		const char*	e = s + namelen;
1280
		putc(q, f);
1281
		while (s < e) {
1282
			int	c = *s++;
1283
			if (c == q) {
1284
				putc(c, f);
1285
			}
1286
			putc(c, f);
1287
		}
1288
		putc(q, f);
1289
	}
1290
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1291
	free(qname);
1 by brian
clean slate
1292
}
1293
1294
/**************************************************************************
1295
Determines if the currently running transaction has been interrupted. */
1296
extern "C"
1297
ibool
1298
trx_is_interrupted(
1299
/*===============*/
1300
			/* out: TRUE if interrupted */
1301
	trx_t*	trx)	/* in: transaction */
1302
{
1303
	return(trx && trx->mysql_thd && thd_killed((THD*) trx->mysql_thd));
1304
}
1305
1306
/******************************************************************
1307
Resets some fields of a prebuilt struct. The template is used in fast
1308
retrieval of just those column values MySQL needs in its processing. */
1309
static
1310
void
1311
reset_template(
1312
/*===========*/
1313
	row_prebuilt_t*	prebuilt)	/* in/out: prebuilt struct */
1314
{
1315
	prebuilt->keep_other_fields_on_keyread = 0;
1316
	prebuilt->read_just_key = 0;
1317
}
1318
1319
/*********************************************************************
1320
Call this when you have opened a new table handle in HANDLER, before you
1321
call index_read_idx() etc. Actually, we can let the cursor stay open even
1322
over a transaction commit! Then you should call this before every operation,
1323
fetch next etc. This function inits the necessary things even after a
1324
transaction commit. */
1325
1326
void
1327
ha_innobase::init_table_handle_for_HANDLER(void)
1328
/*============================================*/
1329
{
1330
	/* If current thd does not yet have a trx struct, create one.
1331
	If the current handle does not yet have a prebuilt struct, create
1332
	one. Update the trx pointers in the prebuilt struct. Normally
1333
	this operation is done in external_lock. */
1334
1335
	update_thd(ha_thd());
1336
1337
	/* Initialize the prebuilt struct much like it would be inited in
1338
	external_lock */
1339
1340
	innobase_release_stat_resources(prebuilt->trx);
1341
1342
	/* If the transaction is not started yet, start it */
1343
1344
	trx_start_if_not_started_noninline(prebuilt->trx);
1345
1346
	/* Assign a read view if the transaction does not have it yet */
1347
1348
	trx_assign_read_view(prebuilt->trx);
1349
1350
	/* Set the MySQL flag to mark that there is an active transaction */
1351
1352
	if (prebuilt->trx->active_trans == 0) {
1353
1354
		innobase_register_trx_and_stmt(ht, user_thd);
1355
1356
		prebuilt->trx->active_trans = 1;
1357
	}
1358
1359
	/* We did the necessary inits in this function, no need to repeat them
1360
	in row_search_for_mysql */
1361
1362
	prebuilt->sql_stat_start = FALSE;
1363
1364
	/* We let HANDLER always to do the reads as consistent reads, even
1365
	if the trx isolation level would have been specified as SERIALIZABLE */
1366
1367
	prebuilt->select_lock_type = LOCK_NONE;
1368
	prebuilt->stored_select_lock_type = LOCK_NONE;
1369
1370
	/* Always fetch all columns in the index record */
1371
1372
	prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
1373
1374
	/* We want always to fetch all columns in the whole row? Or do
1375
	we???? */
1376
1377
	prebuilt->used_in_HANDLER = TRUE;
1378
	reset_template(prebuilt);
1379
}
1380
1381
/*************************************************************************
1382
Opens an InnoDB database. */
1383
static
1384
int
1385
innobase_init(
1386
/*==========*/
1387
			/* out: 0 on success, error code on failure */
1388
	void	*p)	/* in: InnoDB handlerton */
1389
{
1390
	static char	current_dir[3];		/* Set if using current lib */
1391
	int		err;
1392
	bool		ret;
1393
	char		*default_path;
1394
1395
        handlerton *innobase_hton= (handlerton *)p;
1396
        innodb_hton_ptr = innobase_hton;
1397
1398
        innobase_hton->state = SHOW_OPTION_YES;
1399
        innobase_hton->savepoint_offset=sizeof(trx_named_savept_t);
1400
        innobase_hton->close_connection=innobase_close_connection;
1401
        innobase_hton->savepoint_set=innobase_savepoint;
1402
        innobase_hton->savepoint_rollback=innobase_rollback_to_savepoint;
1403
        innobase_hton->savepoint_release=innobase_release_savepoint;
1404
        innobase_hton->commit=innobase_commit;
1405
        innobase_hton->rollback=innobase_rollback;
1406
        innobase_hton->prepare=innobase_xa_prepare;
1407
        innobase_hton->recover=innobase_xa_recover;
1408
        innobase_hton->commit_by_xid=innobase_commit_by_xid;
1409
        innobase_hton->rollback_by_xid=innobase_rollback_by_xid;
1410
        innobase_hton->create_cursor_read_view=innobase_create_cursor_view;
1411
        innobase_hton->set_cursor_read_view=innobase_set_cursor_view;
1412
        innobase_hton->close_cursor_read_view=innobase_close_cursor_view;
1413
        innobase_hton->create=innobase_create_handler;
1414
        innobase_hton->drop_database=innobase_drop_database;
1415
        innobase_hton->start_consistent_snapshot=innobase_start_trx_and_assign_read_view;
1416
        innobase_hton->flush_logs=innobase_flush_logs;
1417
        innobase_hton->show_status=innobase_show_status;
1418
        innobase_hton->flags=HTON_NO_FLAGS;
1419
        innobase_hton->release_temporary_latches=innobase_release_temporary_latches;
1420
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1421
        ut_a(DATA_DRIZZLE_TRUE_VARCHAR == (ulint)DRIZZLE_TYPE_VARCHAR);
1 by brian
clean slate
1422
1423
#ifdef UNIV_DEBUG
1424
	static const char	test_filename[] = "-@";
1425
	char			test_tablename[sizeof test_filename
1426
				+ sizeof srv_mysql50_table_name_prefix];
1427
	if ((sizeof test_tablename) - 1
1428
			!= filename_to_tablename(test_filename, test_tablename,
1429
			sizeof test_tablename)
1430
			|| strncmp(test_tablename,
1431
			srv_mysql50_table_name_prefix,
1432
			sizeof srv_mysql50_table_name_prefix)
1433
			|| strcmp(test_tablename
1434
			+ sizeof srv_mysql50_table_name_prefix,
1435
			test_filename)) {
1436
		sql_print_error("tablename encoding has been changed");
1437
		goto error;
1438
	}
1439
#endif /* UNIV_DEBUG */
1440
1441
	/* Check that values don't overflow on 32-bit systems. */
1442
	if (sizeof(ulint) == 4) {
163 by Brian Aker
Merge Monty's code.
1443
		if (innobase_buffer_pool_size > UINT32_MAX) {
1 by brian
clean slate
1444
			sql_print_error(
1445
				"innobase_buffer_pool_size can't be over 4GB"
1446
				" on 32-bit systems");
1447
1448
			goto error;
1449
		}
1450
163 by Brian Aker
Merge Monty's code.
1451
		if (innobase_log_file_size > UINT32_MAX) {
1 by brian
clean slate
1452
			sql_print_error(
1453
				"innobase_log_file_size can't be over 4GB"
1454
				" on 32-bit systems");
1455
1456
			goto error;
1457
		}
1458
	}
1459
1460
	os_innodb_umask = (ulint)my_umask;
1461
1462
	/* First calculate the default path for innodb_data_home_dir etc.,
30 by Brian Aker
Large file and ftruncate() support
1463
          in case the user has not given any value. */
1464
1465
        {
1 by brian
clean slate
1466
		/* It's better to use current lib, to keep paths short */
1467
		current_dir[0] = FN_CURLIB;
1468
		current_dir[1] = FN_LIBCHAR;
1469
		current_dir[2] = 0;
1470
		default_path = current_dir;
1471
	}
1472
1473
	ut_a(default_path);
1474
362 by Brian Aker
No more dead special flags...
1475
        srv_set_thread_priorities = TRUE;
1476
        srv_query_thread_priority = QUERY_PRIOR;
1 by brian
clean slate
1477
1478
	/* Set InnoDB initialization parameters according to the values
1479
	read from MySQL .cnf file */
1480
1481
	/*--------------- Data files -------------------------*/
1482
1483
	/* The default dir for data files is the datadir of MySQL */
1484
1485
	srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
1486
			 default_path);
1487
1488
	/* Set default InnoDB data file size to 10 MB and let it be
1489
	auto-extending. Thus users can use InnoDB in >= 4.0 without having
1490
	to specify any startup options. */
1491
1492
	if (!innobase_data_file_path) {
1493
		innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
1494
	}
1495
1496
	/* Since InnoDB edits the argument in the next call, we make another
1497
	copy of it: */
1498
1499
	internal_innobase_data_file_path = my_strdup(innobase_data_file_path,
1500
						   MYF(MY_FAE));
1501
1502
	ret = (bool) srv_parse_data_file_paths_and_sizes(
1503
				internal_innobase_data_file_path,
1504
				&srv_data_file_names,
1505
				&srv_data_file_sizes,
1506
				&srv_data_file_is_raw_partition,
1507
				&srv_n_data_files,
1508
				&srv_auto_extend_last_data_file,
1509
				&srv_last_file_size_max);
1510
	if (ret == FALSE) {
1511
		sql_print_error(
1512
			"InnoDB: syntax error in innodb_data_file_path");
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1513
                if (internal_innobase_data_file_path)
1514
			free(internal_innobase_data_file_path);
1 by brian
clean slate
1515
		goto error;
1516
	}
1517
1518
	/* -------------- Log files ---------------------------*/
1519
1520
	/* The default dir for log files is the datadir of MySQL */
1521
1522
	if (!innobase_log_group_home_dir) {
1523
		innobase_log_group_home_dir = default_path;
1524
	}
1525
1526
#ifdef UNIV_LOG_ARCHIVE
1527
	/* Since innodb_log_arch_dir has no relevance under MySQL,
1528
	starting from 4.0.6 we always set it the same as
1529
	innodb_log_group_home_dir: */
1530
1531
	innobase_log_arch_dir = innobase_log_group_home_dir;
1532
1533
	srv_arch_dir = innobase_log_arch_dir;
1534
#endif /* UNIG_LOG_ARCHIVE */
1535
1536
	ret = (bool)
1537
		srv_parse_log_group_home_dirs(innobase_log_group_home_dir,
1538
						&srv_log_group_home_dirs);
1539
1540
	if (ret == FALSE || innobase_mirrored_log_groups != 1) {
1541
	  sql_print_error("syntax error in innodb_log_group_home_dir, or a "
1542
			  "wrong number of mirrored log groups");
1543
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1544
		if (internal_innobase_data_file_path)
1545
			free(internal_innobase_data_file_path);
1 by brian
clean slate
1546
		goto error;
1547
	}
1548
1549
	/* --------------------------------------------------*/
1550
1551
	srv_file_flush_method_str = innobase_unix_file_flush_method;
1552
1553
	srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
1554
	srv_n_log_files = (ulint) innobase_log_files_in_group;
1555
	srv_log_file_size = (ulint) innobase_log_file_size;
1556
1557
#ifdef UNIV_LOG_ARCHIVE
1558
	srv_log_archive_on = (ulint) innobase_log_archive;
1559
#endif /* UNIV_LOG_ARCHIVE */
1560
	srv_log_buffer_size = (ulint) innobase_log_buffer_size;
1561
1562
	/* We set srv_pool_size here in units of 1 kB. InnoDB internally
1563
	changes the value so that it becomes the number of database pages. */
1564
1565
	if (innobase_buffer_pool_awe_mem_mb == 0) {
1566
		srv_pool_size = (ulint)(innobase_buffer_pool_size / 1024);
1567
	} else {
1568
		srv_use_awe = TRUE;
1569
		srv_pool_size = (ulint)
1570
				(1024 * innobase_buffer_pool_awe_mem_mb);
1571
		srv_awe_window_size = (ulint) innobase_buffer_pool_size;
1572
1573
		/* Note that what the user specified as
1574
		innodb_buffer_pool_size is actually the AWE memory window
1575
		size in this case, and the real buffer pool size is
1576
		determined by .._awe_mem_mb. */
1577
	}
1578
1579
	srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
1580
1581
	srv_n_file_io_threads = (ulint) innobase_file_io_threads;
1582
1583
	srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout;
1584
	srv_force_recovery = (ulint) innobase_force_recovery;
1585
1586
	srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
1587
	srv_use_checksums = (ibool) innobase_use_checksums;
1588
1589
#ifdef HAVE_LARGE_PAGES
1590
        if ((os_use_large_pages = (ibool) my_use_large_pages))
1591
		os_large_page_size = (ulint) opt_large_page_size;
1592
#endif
1593
1594
	row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
1595
1596
	srv_file_per_table = (ibool) innobase_file_per_table;
1597
	srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
1598
1599
	srv_max_n_open_files = (ulint) innobase_open_files;
1600
	srv_innodb_status = (ibool) innobase_create_status_file;
1601
1602
	srv_stats_on_metadata = (ibool) innobase_stats_on_metadata;
1603
1604
	srv_use_adaptive_hash_indexes =
1605
		(ibool) innobase_use_adaptive_hash_indexes;
1606
30 by Brian Aker
Large file and ftruncate() support
1607
	srv_print_verbose_log = 1;
1 by brian
clean slate
1608
1609
	/* Store the default charset-collation number of this MySQL
1610
	installation */
1611
1612
	data_mysql_default_charset_coll = (ulint)default_charset_info->number;
1613
1614
	/* Since we in this module access directly the fields of a trx
1615
	struct, and due to different headers and flags it might happen that
1616
	mutex_t has a different size in this module and in InnoDB
1617
	modules, we check at run time that the size is the same in
1618
	these compilation modules. */
1619
1620
	srv_sizeof_trx_t_in_ha_innodb_cc = sizeof(trx_t);
1621
1622
	err = innobase_start_or_create_for_mysql();
1623
1624
	if (err != DB_SUCCESS) {
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1625
                if (internal_innobase_data_file_path)
1626
                        free(internal_innobase_data_file_path);
1 by brian
clean slate
1627
		goto error;
1628
	}
1629
1630
	(void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
1631
					(hash_get_key) innobase_get_key, 0, 0);
1632
	pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
1633
	pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
1634
	pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
1635
	pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
1636
	pthread_cond_init(&commit_cond, NULL);
1637
	innodb_inited= 1;
1638
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
1639
	return(FALSE);
1 by brian
clean slate
1640
error:
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
1641
	return(TRUE);
1 by brian
clean slate
1642
}
1643
1644
/***********************************************************************
1645
Closes an InnoDB database. */
1646
static
1647
int
224.2.3 by Brian Aker
Fix for memory leak in shutdown/restart of an engine (not fixed in 5.1)
1648
innobase_deinit(void *p __attribute__((unused)))
1 by brian
clean slate
1649
/*==============*/
1650
				/* out: TRUE if error */
1651
{
1652
	int	err= 0;
1653
1654
	if (innodb_inited) {
1655
1656
		srv_fast_shutdown = (ulint) innobase_fast_shutdown;
1657
		innodb_inited = 0;
1658
		if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
1659
			err = 1;
1660
		}
1661
		hash_free(&innobase_open_tables);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1662
                if (internal_innobase_data_file_path)
1663
                        free(internal_innobase_data_file_path);
1 by brian
clean slate
1664
		pthread_mutex_destroy(&innobase_share_mutex);
1665
		pthread_mutex_destroy(&prepare_commit_mutex);
1666
		pthread_mutex_destroy(&commit_threads_m);
1667
		pthread_mutex_destroy(&commit_cond_m);
1668
		pthread_cond_destroy(&commit_cond);
1669
	}
1670
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
1671
	return(err);
1 by brian
clean slate
1672
}
1673
1674
/********************************************************************
1675
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
1676
the logs, and the name of this function should be innobase_checkpoint. */
1677
static
1678
bool
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1679
innobase_flush_logs(handlerton *hton __attribute__((unused)))
1 by brian
clean slate
1680
/*=====================*/
1681
				/* out: TRUE if error */
1682
{
1683
	bool	result = 0;
1684
1685
	log_buffer_flush_to_disk();
1686
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
1687
	return(result);
1 by brian
clean slate
1688
}
1689
1690
/*********************************************************************
1691
Commits a transaction in an InnoDB database. */
1692
static
1693
void
1694
innobase_commit_low(
1695
/*================*/
1696
	trx_t*	trx)	/* in: transaction handle */
1697
{
1698
	if (trx->conc_state == TRX_NOT_STARTED) {
1699
1700
		return;
1701
	}
1702
1703
	trx_commit_for_mysql(trx);
1704
}
1705
1706
/*********************************************************************
1707
Creates an InnoDB transaction struct for the thd if it does not yet have one.
1708
Starts a new InnoDB transaction if a transaction is not yet started. And
1709
assigns a new snapshot for a consistent read if the transaction does not yet
1710
have one. */
1711
static
1712
int
1713
innobase_start_trx_and_assign_read_view(
1714
/*====================================*/
1715
			/* out: 0 */
1716
        handlerton *hton, /* in: Innodb handlerton */ 
1717
	THD*	thd)	/* in: MySQL thread handle of the user for whom
1718
			the transaction should be committed */
1719
{
1720
	trx_t*	trx;
1721
1722
	/* Create a new trx struct for thd, if it does not yet have one */
1723
1724
	trx = check_trx_exists(thd);
1725
1726
	/* This is just to play safe: release a possible FIFO ticket and
1727
	search latch. Since we will reserve the kernel mutex, we have to
1728
	release the search system latch first to obey the latching order. */
1729
1730
	innobase_release_stat_resources(trx);
1731
1732
	/* If the transaction is not started yet, start it */
1733
1734
	trx_start_if_not_started_noninline(trx);
1735
1736
	/* Assign a read view if the transaction does not have it yet */
1737
1738
	trx_assign_read_view(trx);
1739
1740
	/* Set the MySQL flag to mark that there is an active transaction */
1741
1742
	if (trx->active_trans == 0) {
1743
		innobase_register_trx_and_stmt(hton, current_thd);
1744
		trx->active_trans = 1;
1745
	}
1746
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
1747
	return(0);
1 by brian
clean slate
1748
}
1749
1750
/*********************************************************************
1751
Commits a transaction in an InnoDB database or marks an SQL statement
1752
ended. */
1753
static
1754
int
1755
innobase_commit(
1756
/*============*/
1757
			/* out: 0 */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1758
        handlerton *hton __attribute__((unused)), /* in: Innodb handlerton */ 
1 by brian
clean slate
1759
	THD* 	thd,	/* in: MySQL thread handle of the user for whom
1760
			the transaction should be committed */
1761
	bool	all)	/* in:	TRUE - commit transaction
1762
				FALSE - the current SQL statement ended */
1763
{
1764
	trx_t*		trx;
1765
1766
	trx = check_trx_exists(thd);
1767
1768
	/* Update the info whether we should skip XA steps that eat CPU time */
1769
	trx->support_xa = THDVAR(thd, support_xa);
1770
1771
	/* Since we will reserve the kernel mutex, we have to release
1772
	the search system latch first to obey the latching order. */
1773
1774
	if (trx->has_search_latch) {
1775
		trx_search_latch_release_if_reserved(trx);
1776
	}
1777
1778
	/* The flag trx->active_trans is set to 1 in
1779
1780
	1. ::external_lock(),
1781
	2. ::start_stmt(),
1782
	3. innobase_query_caching_of_table_permitted(),
1783
	4. innobase_savepoint(),
1784
	5. ::init_table_handle_for_HANDLER(),
1785
	6. innobase_start_trx_and_assign_read_view(),
1786
	7. ::transactional_table_lock()
1787
1788
	and it is only set to 0 in a commit or a rollback. If it is 0 we know
1789
	there cannot be resources to be freed and we could return immediately.
1790
	For the time being, we play safe and do the cleanup though there should
1791
	be nothing to clean up. */
1792
1793
	if (trx->active_trans == 0
1794
		&& trx->conc_state != TRX_NOT_STARTED) {
1795
1796
		sql_print_error("trx->active_trans == 0, but"
1797
			" trx->conc_state != TRX_NOT_STARTED");
1798
	}
1799
	if (all
1800
		|| (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
1801
1802
		/* We were instructed to commit the whole transaction, or
1803
		this is an SQL statement end and autocommit is on */
1804
1805
		/* We need current binlog position for ibbackup to work.
1806
		Note, the position is current because of
1807
		prepare_commit_mutex */
1808
retry:
1809
		if (srv_commit_concurrency > 0) {
1810
			pthread_mutex_lock(&commit_cond_m);
1811
			commit_threads++;
1812
1813
			if (commit_threads > srv_commit_concurrency) {
1814
				commit_threads--;
1815
				pthread_cond_wait(&commit_cond,
1816
					&commit_cond_m);
1817
				pthread_mutex_unlock(&commit_cond_m);
1818
				goto retry;
1819
			}
1820
			else {
1821
				pthread_mutex_unlock(&commit_cond_m);
1822
			}
1823
		}
1824
1825
		trx->mysql_log_file_name = mysql_bin_log_file_name();
1826
		trx->mysql_log_offset = (ib_longlong) mysql_bin_log_file_pos();
1827
1828
		innobase_commit_low(trx);
1829
1830
		if (srv_commit_concurrency > 0) {
1831
			pthread_mutex_lock(&commit_cond_m);
1832
			commit_threads--;
1833
			pthread_cond_signal(&commit_cond);
1834
			pthread_mutex_unlock(&commit_cond_m);
1835
		}
1836
1837
		if (trx->active_trans == 2) {
1838
1839
			pthread_mutex_unlock(&prepare_commit_mutex);
1840
		}
1841
1842
		trx->active_trans = 0;
1843
1844
	} else {
1845
		/* We just mark the SQL statement ended and do not do a
1846
		transaction commit */
1847
1848
		/* If we had reserved the auto-inc lock for some
1849
		table in this SQL statement we release it now */
1850
1851
		row_unlock_table_autoinc_for_mysql(trx);
1852
1853
		/* Store the current undo_no of the transaction so that we
1854
		know where to roll back if we have to roll back the next
1855
		SQL statement */
1856
1857
		trx_mark_sql_stat_end(trx);
1858
	}
1859
1860
	trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
1861
1862
	if (trx->declared_to_be_inside_innodb) {
1863
		/* Release our possible ticket in the FIFO */
1864
1865
		srv_conc_force_exit_innodb(trx);
1866
	}
1867
1868
	/* Tell the InnoDB server that there might be work for utility
1869
	threads: */
1870
	srv_active_wake_master_thread();
1871
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
1872
	return(0);
1 by brian
clean slate
1873
}
1874
1875
/*********************************************************************
1876
Rolls back a transaction or the latest SQL statement. */
1877
static
1878
int
1879
innobase_rollback(
1880
/*==============*/
1881
			/* out: 0 or error number */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1882
        handlerton *hton __attribute__((unused)), /* in: Innodb handlerton */ 
1 by brian
clean slate
1883
	THD*	thd,	/* in: handle to the MySQL thread of the user
1884
			whose transaction should be rolled back */
1885
	bool	all)	/* in:	TRUE - commit transaction
1886
				FALSE - the current SQL statement ended */
1887
{
1888
	int	error = 0;
1889
	trx_t*	trx;
1890
1891
	trx = check_trx_exists(thd);
1892
1893
	/* Update the info whether we should skip XA steps that eat CPU time */
1894
	trx->support_xa = THDVAR(thd, support_xa);
1895
1896
	/* Release a possible FIFO ticket and search latch. Since we will
1897
	reserve the kernel mutex, we have to release the search system latch
1898
	first to obey the latching order. */
1899
1900
	innobase_release_stat_resources(trx);
1901
1902
	/* If we had reserved the auto-inc lock for some table (if
1903
	we come here to roll back the latest SQL statement) we
1904
	release it now before a possibly lengthy rollback */
1905
1906
	row_unlock_table_autoinc_for_mysql(trx);
1907
1908
	if (all
1909
		|| !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
1910
1911
		error = trx_rollback_for_mysql(trx);
1912
		trx->active_trans = 0;
1913
	} else {
1914
		error = trx_rollback_last_sql_stat_for_mysql(trx);
1915
	}
1916
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
1917
	return(convert_error_code_to_mysql(error, NULL));
1 by brian
clean slate
1918
}
1919
1920
/*********************************************************************
1921
Rolls back a transaction */
1922
static
1923
int
1924
innobase_rollback_trx(
1925
/*==================*/
1926
			/* out: 0 or error number */
1927
	trx_t*	trx)	/*  in: transaction */
1928
{
1929
	int	error = 0;
1930
1931
	/* Release a possible FIFO ticket and search latch. Since we will
1932
	reserve the kernel mutex, we have to release the search system latch
1933
	first to obey the latching order. */
1934
1935
	innobase_release_stat_resources(trx);
1936
1937
	/* If we had reserved the auto-inc lock for some table (if
1938
	we come here to roll back the latest SQL statement) we
1939
	release it now before a possibly lengthy rollback */
1940
1941
	row_unlock_table_autoinc_for_mysql(trx);
1942
1943
	error = trx_rollback_for_mysql(trx);
1944
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
1945
	return(convert_error_code_to_mysql(error, NULL));
1 by brian
clean slate
1946
}
1947
1948
/*********************************************************************
1949
Rolls back a transaction to a savepoint. */
1950
static
1951
int
1952
innobase_rollback_to_savepoint(
1953
/*===========================*/
1954
				/* out: 0 if success, HA_ERR_NO_SAVEPOINT if
1955
				no savepoint with the given name */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1956
        handlerton *hton __attribute__((unused)),       /* in: Innodb handlerton */ 
1 by brian
clean slate
1957
	THD*	thd,		/* in: handle to the MySQL thread of the user
1958
				whose transaction should be rolled back */
1959
	void*	savepoint)	/* in: savepoint data */
1960
{
1961
	ib_longlong	mysql_binlog_cache_pos;
1962
	int		error = 0;
1963
	trx_t*		trx;
1964
	char		name[64];
1965
1966
	trx = check_trx_exists(thd);
1967
1968
	/* Release a possible FIFO ticket and search latch. Since we will
1969
	reserve the kernel mutex, we have to release the search system latch
1970
	first to obey the latching order. */
1971
1972
	innobase_release_stat_resources(trx);
1973
1974
	/* TODO: use provided savepoint data area to store savepoint data */
1975
152 by Brian Aker
longlong replacement
1976
	int64_t2str((ulint)savepoint, name, 36);
1 by brian
clean slate
1977
1978
	error = (int) trx_rollback_to_savepoint_for_mysql(trx, name,
1979
						&mysql_binlog_cache_pos);
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
1980
	return(convert_error_code_to_mysql(error, NULL));
1 by brian
clean slate
1981
}
1982
1983
/*********************************************************************
1984
Release transaction savepoint name. */
1985
static
1986
int
1987
innobase_release_savepoint(
1988
/*=======================*/
1989
				/* out: 0 if success, HA_ERR_NO_SAVEPOINT if
1990
				no savepoint with the given name */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1991
        handlerton*	hton __attribute__((unused)),	/* in: handlerton for Innodb */
1 by brian
clean slate
1992
	THD*	thd,		/* in: handle to the MySQL thread of the user
1993
				whose transaction should be rolled back */
1994
	void*	savepoint)	/* in: savepoint data */
1995
{
1996
	int		error = 0;
1997
	trx_t*		trx;
1998
	char		name[64];
1999
2000
	trx = check_trx_exists(thd);
2001
2002
	/* TODO: use provided savepoint data area to store savepoint data */
2003
152 by Brian Aker
longlong replacement
2004
	int64_t2str((ulint)savepoint, name, 36);
1 by brian
clean slate
2005
2006
	error = (int) trx_release_savepoint_for_mysql(trx, name);
2007
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2008
	return(convert_error_code_to_mysql(error, NULL));
1 by brian
clean slate
2009
}
2010
2011
/*********************************************************************
2012
Sets a transaction savepoint. */
2013
static
2014
int
2015
innobase_savepoint(
2016
/*===============*/
2017
				/* out: always 0, that is, always succeeds */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
2018
	handlerton*	hton __attribute__((unused)),   /* in: handle to the Innodb handlerton */
1 by brian
clean slate
2019
	THD*	thd,		/* in: handle to the MySQL thread */
2020
	void*	savepoint)	/* in: savepoint data */
2021
{
2022
	int	error = 0;
2023
	trx_t*	trx;
2024
2025
	/*
2026
	  In the autocommit mode there is no sense to set a savepoint
2027
	  (unless we are in sub-statement), so SQL layer ensures that
2028
	  this method is never called in such situation.
2029
	*/
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2030
#ifdef DRIZZLE_SERVER /* plugins cannot access thd->in_sub_stmt */
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2031
	assert(thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
1 by brian
clean slate
2032
		thd->in_sub_stmt);
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2033
#endif /* DRIZZLE_SERVER */
1 by brian
clean slate
2034
2035
	trx = check_trx_exists(thd);
2036
2037
	/* Release a possible FIFO ticket and search latch. Since we will
2038
	reserve the kernel mutex, we have to release the search system latch
2039
	first to obey the latching order. */
2040
2041
	innobase_release_stat_resources(trx);
2042
2043
	/* cannot happen outside of transaction */
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2044
	assert(trx->active_trans);
1 by brian
clean slate
2045
2046
	/* TODO: use provided savepoint data area to store savepoint data */
2047
	char name[64];
152 by Brian Aker
longlong replacement
2048
	int64_t2str((ulint)savepoint,name,36);
1 by brian
clean slate
2049
2050
	error = (int) trx_savepoint_for_mysql(trx, name, (ib_longlong)0);
2051
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2052
	return(convert_error_code_to_mysql(error, NULL));
1 by brian
clean slate
2053
}
2054
2055
/*********************************************************************
2056
Frees a possible InnoDB trx object associated with the current THD. */
2057
static
2058
int
2059
innobase_close_connection(
2060
/*======================*/
2061
			/* out: 0 or error number */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
2062
        handlerton*	hton __attribute__((unused)),	/* in:  innobase handlerton */
1 by brian
clean slate
2063
	THD*	thd)	/* in: handle to the MySQL thread of the user
2064
			whose resources should be free'd */
2065
{
2066
	trx_t*	trx;
2067
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2068
	assert(hton == innodb_hton_ptr);
1 by brian
clean slate
2069
	trx = thd_to_trx(thd);
2070
2071
	ut_a(trx);
2072
2073
	if (trx->active_trans == 0
2074
		&& trx->conc_state != TRX_NOT_STARTED) {
2075
2076
		sql_print_error("trx->active_trans == 0, but"
2077
			" trx->conc_state != TRX_NOT_STARTED");
2078
	}
2079
2080
2081
	if (trx->conc_state != TRX_NOT_STARTED &&
2082
		global_system_variables.log_warnings) {
2083
		sql_print_warning(
2084
			"MySQL is closing a connection that has an active "
2085
			"InnoDB transaction.  %lu row modifications will "
2086
			"roll back.",
2087
			(ulong) trx->undo_no.low);
2088
	}
2089
2090
	innobase_rollback_trx(trx);
2091
2092
	thr_local_free(trx->mysql_thread_id);
2093
	trx_free_for_mysql(trx);
2094
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2095
	return(0);
1 by brian
clean slate
2096
}
2097
2098
2099
/*****************************************************************************
2100
** InnoDB database tables
2101
*****************************************************************************/
2102
2103
/********************************************************************
2104
Get the record format from the data dictionary. */
2105
enum row_type
2106
ha_innobase::get_row_type() const
2107
/*=============================*/
2108
			/* out: ROW_TYPE_REDUNDANT or ROW_TYPE_COMPACT */
2109
{
2110
	if (prebuilt && prebuilt->table) {
2111
		if (dict_table_is_comp_noninline(prebuilt->table)) {
2112
			return(ROW_TYPE_COMPACT);
2113
		} else {
2114
			return(ROW_TYPE_REDUNDANT);
2115
		}
2116
	}
2117
	ut_ad(0);
2118
	return(ROW_TYPE_NOT_USED);
2119
}
2120
2121
2122
2123
/********************************************************************
2124
Get the table flags to use for the statement. */
2125
handler::Table_flags
2126
ha_innobase::table_flags() const
2127
{
2128
       /* Need to use tx_isolation here since table flags is (also)
2129
          called before prebuilt is inited. */
2130
        ulong const tx_isolation = thd_tx_isolation(current_thd);
2131
        if (tx_isolation <= ISO_READ_COMMITTED)
2132
                return int_table_flags;
2133
        return int_table_flags | HA_BINLOG_STMT_CAPABLE;
2134
}
2135
2136
/********************************************************************
2137
Gives the file extension of an InnoDB single-table tablespace. */
2138
static const char* ha_innobase_exts[] = {
2139
  ".ibd",
461 by Monty Taylor
Removed NullS. bu-bye.
2140
  NULL
1 by brian
clean slate
2141
};
2142
2143
const char**
2144
ha_innobase::bas_ext() const
2145
/*========================*/
2146
				/* out: file extension string */
2147
{
2148
  return ha_innobase_exts;
2149
}
2150
2151
2152
/*********************************************************************
2153
Normalizes a table name string. A normalized name consists of the
2154
database name catenated to '/' and table name. An example:
2155
test/mytable. On Windows normalization puts both the database name and the
2156
table name always to lower case. */
2157
static
2158
void
2159
normalize_table_name(
2160
/*=================*/
2161
	char*		norm_name,	/* out: normalized name as a
2162
					null-terminated string */
2163
	const char*	name)		/* in: table name string */
2164
{
2165
	char*	name_ptr;
2166
	char*	db_ptr;
2167
	char*	ptr;
2168
2169
	/* Scan name from the end */
2170
376 by Brian Aker
strend remove
2171
	ptr = strchr(name, '\0')-1;
1 by brian
clean slate
2172
2173
	while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2174
		ptr--;
2175
	}
2176
2177
	name_ptr = ptr + 1;
2178
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2179
	assert(ptr > name);
1 by brian
clean slate
2180
2181
	ptr--;
2182
2183
	while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2184
		ptr--;
2185
	}
2186
2187
	db_ptr = ptr + 1;
2188
2189
	memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2190
2191
	norm_name[name_ptr - db_ptr - 1] = '/';
2192
2193
#ifdef __WIN__
2194
	innobase_casedn_str(norm_name);
2195
#endif
2196
}
2197
2198
/*********************************************************************
2199
Creates and opens a handle to a table which already exists in an InnoDB
2200
database. */
2201
2202
int
2203
ha_innobase::open(
2204
/*==============*/
2205
					/* out: 1 if error, 0 if success */
2206
	const char*	name,		/* in: table name */
2207
	int		mode,		/* in: not used */
2208
	uint		test_if_locked)	/* in: not used */
2209
{
2210
	dict_table_t*	ib_table;
2211
	char		norm_name[1000];
2212
	THD*		thd;
2213
2214
	UT_NOT_USED(mode);
2215
	UT_NOT_USED(test_if_locked);
2216
2217
	thd = ha_thd();
2218
	normalize_table_name(norm_name, name);
2219
2220
	user_thd = NULL;
2221
2222
	if (!(share=get_share(name))) {
2223
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2224
		return(1);
1 by brian
clean slate
2225
	}
2226
2227
	/* Create buffers for packing the fields of a record. Why
2228
	table->reclength did not work here? Obviously, because char
2229
	fields when packed actually became 1 byte longer, when we also
2230
	stored the string length as the first byte. */
2231
2232
	upd_and_key_val_buff_len =
2233
				table->s->reclength + table->s->max_key_length
2234
							+ MAX_REF_PARTS * 3;
481 by Brian Aker
Remove all of uchar.
2235
	if (!(unsigned char*) my_multi_malloc(MYF(MY_WME),
1 by brian
clean slate
2236
			&upd_buff, upd_and_key_val_buff_len,
2237
			&key_val_buff, upd_and_key_val_buff_len,
461 by Monty Taylor
Removed NullS. bu-bye.
2238
			NULL)) {
1 by brian
clean slate
2239
		free_share(share);
2240
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2241
		return(1);
1 by brian
clean slate
2242
	}
2243
2244
	/* Get pointer to a table object in InnoDB dictionary cache */
2245
2246
	ib_table = dict_table_get(norm_name, TRUE);
2247
2248
	if (NULL == ib_table) {
2249
		sql_print_error("Cannot find or open table %s from\n"
2250
				"the internal data dictionary of InnoDB "
2251
				"though the .frm file for the\n"
2252
				"table exists. Maybe you have deleted and "
2253
				"recreated InnoDB data\n"
2254
				"files but have forgotten to delete the "
2255
				"corresponding .frm files\n"
2256
				"of InnoDB tables, or you have moved .frm "
2257
				"files to another database?\n"
2258
				"or, the table contains indexes that this "
2259
				"version of the engine\n"
2260
				"doesn't support.\n"
2261
				"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
2262
				"how you can resolve the problem.\n",
2263
				norm_name);
2264
		free_share(share);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
2265
		free(upd_buff);
1 by brian
clean slate
2266
		my_errno = ENOENT;
2267
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2268
		return(HA_ERR_NO_SUCH_TABLE);
1 by brian
clean slate
2269
	}
2270
2271
	if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) {
2272
		sql_print_error("MySQL is trying to open a table handle but "
2273
				"the .ibd file for\ntable %s does not exist.\n"
2274
				"Have you deleted the .ibd file from the "
2275
				"database directory under\nthe MySQL datadir, "
2276
				"or have you used DISCARD TABLESPACE?\n"
2277
				"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
2278
				"how you can resolve the problem.\n",
2279
				norm_name);
2280
		free_share(share);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
2281
		free(upd_buff);
1 by brian
clean slate
2282
		my_errno = ENOENT;
2283
2284
		dict_table_decrement_handle_count(ib_table);
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2285
		return(HA_ERR_NO_SUCH_TABLE);
1 by brian
clean slate
2286
	}
2287
2288
	prebuilt = row_create_prebuilt(ib_table);
2289
2290
	prebuilt->mysql_row_len = table->s->reclength;
2291
        prebuilt->idx_cond_func= NULL;
2292
2293
	/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
2294
2295
	primary_key = table->s->primary_key;
2296
	key_used_on_scan = primary_key;
2297
2298
	/* Allocate a buffer for a 'row reference'. A row reference is
2299
	a string of bytes of length ref_length which uniquely specifies
2300
	a row in our table. Note that MySQL may also compare two row
2301
	references for equality by doing a simple memcmp on the strings
2302
	of length ref_length! */
2303
2304
	if (!row_table_got_default_clust_index(ib_table)) {
2305
		if (primary_key >= MAX_KEY) {
2306
		  sql_print_error("Table %s has a primary key in InnoDB data "
2307
				  "dictionary, but not in MySQL!", name);
2308
		}
2309
2310
		prebuilt->clust_index_was_generated = FALSE;
2311
2312
		/* MySQL allocates the buffer for ref. key_info->key_length
2313
		includes space for all key columns + one byte for each column
2314
		that may be NULL. ref_length must be as exact as possible to
2315
		save space, because all row reference buffers are allocated
2316
		based on ref_length. */
2317
2318
		ref_length = table->key_info[primary_key].key_length;
2319
	} else {
2320
		if (primary_key != MAX_KEY) {
2321
		  sql_print_error("Table %s has no primary key in InnoDB data "
2322
				  "dictionary, but has one in MySQL! If you "
2323
				  "created the table with a MySQL version < "
2324
				  "3.23.54 and did not define a primary key, "
2325
				  "but defined a unique key with all non-NULL "
2326
				  "columns, then MySQL internally treats that "
2327
				  "key as the primary key. You can fix this "
2328
				  "error by dump + DROP + CREATE + reimport "
2329
				  "of the table.", name);
2330
		}
2331
2332
		prebuilt->clust_index_was_generated = TRUE;
2333
2334
		ref_length = DATA_ROW_ID_LEN;
2335
2336
		/* If we automatically created the clustered index, then
2337
		MySQL does not know about it, and MySQL must NOT be aware
2338
		of the index used on scan, to make it avoid checking if we
2339
		update the column of the index. That is why we assert below
2340
		that key_used_on_scan is the undefined value MAX_KEY.
2341
		The column is the row id in the automatical generation case,
2342
		and it will never be updated anyway. */
2343
2344
		if (key_used_on_scan != MAX_KEY) {
2345
			sql_print_warning(
2346
				"Table %s key_used_on_scan is %lu even "
2347
				"though there is no primary key inside "
2348
				"InnoDB.", name, (ulong) key_used_on_scan);
2349
		}
2350
	}
2351
2352
	stats.block_size = 16 * 1024;	/* Index block size in InnoDB: used by MySQL
2353
				in query optimization */
2354
2355
	/* Init table lock structure */
2356
	thr_lock_data_init(&share->lock,&lock,(void*) 0);
2357
2358
	info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
2359
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2360
	return(0);
1 by brian
clean slate
2361
}
2362
2363
uint
2364
ha_innobase::max_supported_key_part_length() const
2365
{
2366
	return(DICT_MAX_INDEX_COL_LEN - 1);
2367
}
2368
2369
/**********************************************************************
2370
Closes a handle to an InnoDB table. */
2371
2372
int
2373
ha_innobase::close(void)
2374
/*====================*/
2375
				/* out: 0 */
2376
{
2377
	THD*	thd;
2378
2379
	thd = current_thd;  // avoid calling current_thd twice, it may be slow
2380
	if (thd != NULL) {
2381
		innobase_release_temporary_latches(ht, thd);
2382
	}
2383
2384
	row_prebuilt_free(prebuilt);
2385
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
2386
	free(upd_buff);
1 by brian
clean slate
2387
	free_share(share);
2388
2389
	/* Tell InnoDB server that there might be work for
2390
	utility threads: */
2391
2392
	srv_active_wake_master_thread();
2393
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2394
	return(0);
1 by brian
clean slate
2395
}
2396
2397
/* The following accessor functions should really be inside MySQL code! */
2398
2399
/******************************************************************
2400
Gets field offset for a field in a table. */
2401
inline
2402
uint
2403
get_field_offset(
2404
/*=============*/
2405
			/* out: offset */
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
2406
	Table*	table,	/* in: MySQL table object */
1 by brian
clean slate
2407
	Field*	field)	/* in: MySQL field object */
2408
{
2409
	return((uint) (field->ptr - table->record[0]));
2410
}
2411
2412
/******************************************************************
2413
Checks if a field in a record is SQL NULL. Uses the record format
2414
information in table to track the null bit in record. */
2415
static inline
2416
uint
2417
field_in_record_is_null(
2418
/*====================*/
2419
			/* out: 1 if NULL, 0 otherwise */
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
2420
	Table*	table,	/* in: MySQL table object */
1 by brian
clean slate
2421
	Field*	field,	/* in: MySQL field object */
2422
	char*	record)	/* in: a row in MySQL format */
2423
{
2424
	int	null_offset;
2425
2426
	if (!field->null_ptr) {
2427
2428
		return(0);
2429
	}
2430
2431
	null_offset = (uint) ((char*) field->null_ptr
2432
					- (char*) table->record[0]);
2433
2434
	if (record[null_offset] & field->null_bit) {
2435
2436
		return(1);
2437
	}
2438
2439
	return(0);
2440
}
2441
2442
/******************************************************************
2443
Sets a field in a record to SQL NULL. Uses the record format
2444
information in table to track the null bit in record. */
2445
inline
2446
void
2447
set_field_in_record_to_null(
2448
/*========================*/
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
2449
	Table*	table,	/* in: MySQL table object */
1 by brian
clean slate
2450
	Field*	field,	/* in: MySQL field object */
2451
	char*	record)	/* in: a row in MySQL format */
2452
{
2453
	int	null_offset;
2454
2455
	null_offset = (uint) ((char*) field->null_ptr
2456
					- (char*) table->record[0]);
2457
2458
	record[null_offset] = record[null_offset] | field->null_bit;
2459
}
2460
2461
extern "C" {
2462
/*****************************************************************
2463
InnoDB uses this function to compare two data fields for which the data type
2464
is such that we must use MySQL code to compare them. NOTE that the prototype
2465
of this function is in rem0cmp.c in InnoDB source code! If you change this
2466
function, remember to update the prototype there! */
2467
2468
int
2469
innobase_mysql_cmp(
2470
/*===============*/
2471
					/* out: 1, 0, -1, if a is greater,
2472
					equal, less than b, respectively */
2473
	int		mysql_type,	/* in: MySQL type */
2474
	uint		charset_number,	/* in: number of the charset */
2475
	unsigned char*	a,		/* in: data field */
2476
	unsigned int	a_length,	/* in: data field length,
2477
					not UNIV_SQL_NULL */
2478
	unsigned char*	b,		/* in: data field */
2479
	unsigned int	b_length)	/* in: data field length,
2480
					not UNIV_SQL_NULL */
2481
{
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
2482
	const CHARSET_INFO*	charset;
1 by brian
clean slate
2483
	enum_field_types	mysql_tp;
2484
	int			ret;
2485
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2486
	assert(a_length != UNIV_SQL_NULL);
2487
	assert(b_length != UNIV_SQL_NULL);
1 by brian
clean slate
2488
2489
	mysql_tp = (enum_field_types) mysql_type;
2490
2491
	switch (mysql_tp) {
2492
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
2493
	case DRIZZLE_TYPE_BLOB:
2494
	case DRIZZLE_TYPE_VARCHAR:
1 by brian
clean slate
2495
		/* Use the charset number to pick the right charset struct for
2496
		the comparison. Since the MySQL function get_charset may be
2497
		slow before Bar removes the mutex operation there, we first
2498
		look at 2 common charsets directly. */
2499
2500
		if (charset_number == default_charset_info->number) {
2501
			charset = default_charset_info;
2502
		} else {
2503
			charset = get_charset(charset_number, MYF(MY_WME));
2504
2505
			if (charset == NULL) {
2506
			  sql_print_error("InnoDB needs charset %lu for doing "
2507
					  "a comparison, but MySQL cannot "
2508
					  "find that charset.",
2509
					  (ulong) charset_number);
2510
				ut_a(0);
2511
			}
2512
		}
2513
2514
		/* Starting from 4.1.3, we use strnncollsp() in comparisons of
2515
		non-latin1_swedish_ci strings. NOTE that the collation order
2516
		changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
2517
		having indexes on such data need to rebuild their tables! */
2518
2519
		ret = charset->coll->strnncollsp(charset,
2520
				  a, a_length,
2521
						 b, b_length, 0);
2522
		if (ret < 0) {
2523
			return(-1);
2524
		} else if (ret > 0) {
2525
			return(1);
2526
		} else {
2527
			return(0);
2528
		}
2529
	default:
2530
		assert(0);
2531
	}
2532
2533
	return(0);
2534
}
2535
}
2536
2537
/******************************************************************
2538
Converts a MySQL type to an InnoDB type. Note that this function returns
2539
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
2540
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'. */
2541
inline
2542
ulint
2543
get_innobase_type_from_mysql_type(
2544
/*==============================*/
2545
				/* out: DATA_BINARY, DATA_VARCHAR, ... */
2546
	ulint*	unsigned_flag,	/* out: DATA_UNSIGNED if an 'unsigned type';
2547
				at least ENUM and SET, and unsigned integer
2548
				types are 'unsigned types' */
2549
	Field*	field)		/* in: MySQL field */
2550
{
2551
	/* The following asserts try to check that the MySQL type code fits in
2552
	8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
2553
	the type */
2554
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
2555
	assert((ulint)DRIZZLE_TYPE_DOUBLE < 256);
1 by brian
clean slate
2556
2557
	if (field->flags & UNSIGNED_FLAG) {
2558
2559
		*unsigned_flag = DATA_UNSIGNED;
2560
	} else {
2561
		*unsigned_flag = 0;
2562
	}
2563
325 by Brian Aker
Remove SET
2564
	if (field->real_type() == DRIZZLE_TYPE_ENUM) {
1 by brian
clean slate
2565
2566
		/* MySQL has field->type() a string type for these, but the
2567
		data is actually internally stored as an unsigned integer
2568
		code! */
2569
2570
		*unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
2571
						flag set to zero, even though
2572
						internally this is an unsigned
2573
						integer type */
2574
		return(DATA_INT);
2575
	}
2576
2577
	switch (field->type()) {
2578
		/* NOTE that we only allow string types in DATA_MYSQL and
2579
		DATA_VARMYSQL */
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
2580
	case DRIZZLE_TYPE_VARCHAR:    /* new >= 5.0.3 true VARCHAR */
1 by brian
clean slate
2581
		if (field->binary()) {
2582
			return(DATA_BINARY);
2583
		} else {
2584
			return(DATA_VARMYSQL);
2585
		}
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
2586
	case DRIZZLE_TYPE_NEWDECIMAL:
1 by brian
clean slate
2587
		return(DATA_FIXBINARY);
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
2588
	case DRIZZLE_TYPE_LONG:
2589
	case DRIZZLE_TYPE_LONGLONG:
2590
	case DRIZZLE_TYPE_TINY:
2591
	case DRIZZLE_TYPE_DATETIME:
2592
	case DRIZZLE_TYPE_NEWDATE:
2593
	case DRIZZLE_TYPE_TIME:
2594
	case DRIZZLE_TYPE_TIMESTAMP:
1 by brian
clean slate
2595
		return(DATA_INT);
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
2596
	case DRIZZLE_TYPE_DOUBLE:
1 by brian
clean slate
2597
		return(DATA_DOUBLE);
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
2598
	case DRIZZLE_TYPE_BLOB:
1 by brian
clean slate
2599
		return(DATA_BLOB);
2600
	default:
2601
		assert(0);
2602
	}
2603
2604
	return(0);
2605
}
2606
2607
/***********************************************************************
2608
Writes an unsigned integer value < 64k to 2 bytes, in the little-endian
2609
storage format. */
2610
inline
2611
void
2612
innobase_write_to_2_little_endian(
2613
/*==============================*/
2614
	byte*	buf,	/* in: where to store */
2615
	ulint	val)	/* in: value to write, must be < 64k */
2616
{
2617
	ut_a(val < 256 * 256);
2618
2619
	buf[0] = (byte)(val & 0xFF);
2620
	buf[1] = (byte)(val / 256);
2621
}
2622
2623
/***********************************************************************
2624
Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
2625
storage format. */
2626
inline
2627
uint
2628
innobase_read_from_2_little_endian(
2629
/*===============================*/
2630
				/* out: value */
481 by Brian Aker
Remove all of uchar.
2631
	const unsigned char*	buf)	/* in: from where to read */
1 by brian
clean slate
2632
{
2633
	return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
2634
}
2635
2636
/***********************************************************************
2637
Stores a key value for a row to a buffer. */
2638
2639
uint
2640
ha_innobase::store_key_val_for_row(
2641
/*===============================*/
2642
				/* out: key value length as stored in buff */
2643
	uint		keynr,	/* in: key number */
2644
	char*		buff,	/* in/out: buffer for the key value (in MySQL
2645
				format) */
2646
	uint		buff_len,/* in: buffer length */
481 by Brian Aker
Remove all of uchar.
2647
	const unsigned char*	record)/* in: row in MySQL format */
1 by brian
clean slate
2648
{
2649
	KEY*		key_info	= table->key_info + keynr;
2650
	KEY_PART_INFO*	key_part	= key_info->key_part;
2651
	KEY_PART_INFO*	end		= key_part + key_info->key_parts;
2652
	char*		buff_start	= buff;
2653
	enum_field_types mysql_type;
2654
	Field*		field;
2655
	ibool		is_null;
2656
2657
	/* The format for storing a key field in MySQL is the following:
2658
2659
	1. If the column can be NULL, then in the first byte we put 1 if the
2660
	field value is NULL, 0 otherwise.
2661
2662
	2. If the column is of a BLOB type (it must be a column prefix field
2663
	in this case), then we put the length of the data in the field to the
2664
	next 2 bytes, in the little-endian format. If the field is SQL NULL,
2665
	then these 2 bytes are set to 0. Note that the length of data in the
2666
	field is <= column prefix length.
2667
2668
	3. In a column prefix field, prefix_len next bytes are reserved for
2669
	data. In a normal field the max field length next bytes are reserved
2670
	for data. For a VARCHAR(n) the max field length is n. If the stored
2671
	value is the SQL NULL then these data bytes are set to 0.
2672
2673
	4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
2674
	in the MySQL row format, the length is stored in 1 or 2 bytes,
2675
	depending on the maximum allowed length. But in the MySQL key value
2676
	format, the length always takes 2 bytes.
2677
2678
	We have to zero-fill the buffer so that MySQL is able to use a
2679
	simple memcmp to compare two key values to determine if they are
2680
	equal. MySQL does this to compare contents of two 'ref' values. */
2681
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
2682
	memset(buff, 0, buff_len);
1 by brian
clean slate
2683
2684
	for (; key_part != end; key_part++) {
2685
		is_null = FALSE;
2686
2687
		if (key_part->null_bit) {
2688
			if (record[key_part->null_offset]
2689
						& key_part->null_bit) {
2690
				*buff = 1;
2691
				is_null = TRUE;
2692
			} else {
2693
				*buff = 0;
2694
			}
2695
			buff++;
2696
		}
2697
2698
		field = key_part->field;
2699
		mysql_type = field->type();
2700
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
2701
		if (mysql_type == DRIZZLE_TYPE_VARCHAR) {
1 by brian
clean slate
2702
						/* >= 5.0.3 true VARCHAR */
2703
			ulint	lenlen;
2704
			ulint	len;
2705
			byte*	data;
2706
			ulint	key_len;
2707
			ulint	true_len;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
2708
			const CHARSET_INFO*	cs;
1 by brian
clean slate
2709
			int	error=0;
2710
2711
			key_len = key_part->length;
2712
2713
			if (is_null) {
2714
				buff += key_len + 2;
2715
2716
				continue;
2717
			}
2718
			cs = field->charset();
2719
2720
			lenlen = (ulint)
2721
				(((Field_varstring*)field)->length_bytes);
2722
2723
			data = row_mysql_read_true_varchar(&len,
2724
				(byte*) (record
2725
				+ (ulint)get_field_offset(table, field)),
2726
				lenlen);
2727
2728
			true_len = len;
2729
2730
			/* For multi byte character sets we need to calculate
2731
			the true length of the key */
2732
2733
			if (len > 0 && cs->mbmaxlen > 1) {
2734
				true_len = (ulint) cs->cset->well_formed_len(cs,
2735
						(const char *) data,
2736
						(const char *) data + len,
2737
                                                (uint) (key_len /
2738
                                                        cs->mbmaxlen),
2739
						&error);
2740
			}
2741
2742
			/* In a column prefix index, we may need to truncate
2743
			the stored value: */
2744
2745
			if (true_len > key_len) {
2746
				true_len = key_len;
2747
			}
2748
2749
			/* The length in a key value is always stored in 2
2750
			bytes */
2751
2752
			row_mysql_store_true_var_len((byte*)buff, true_len, 2);
2753
			buff += 2;
2754
2755
			memcpy(buff, data, true_len);
2756
2757
			/* Note that we always reserve the maximum possible
2758
			length of the true VARCHAR in the key value, though
2759
			only len first bytes after the 2 length bytes contain
2760
			actual data. The rest of the space was reset to zero
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
2761
			in the memset() call above. */
1 by brian
clean slate
2762
2763
			buff += key_len;
2764
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
2765
		} else if (mysql_type == DRIZZLE_TYPE_BLOB) {
1 by brian
clean slate
2766
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
2767
			const CHARSET_INFO*	cs;
1 by brian
clean slate
2768
			ulint		key_len;
2769
			ulint		true_len;
2770
			int		error=0;
2771
			ulint		blob_len;
2772
			byte*		blob_data;
2773
2774
			ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
2775
2776
			key_len = key_part->length;
2777
2778
			if (is_null) {
2779
				buff += key_len + 2;
2780
2781
				continue;
2782
			}
2783
2784
			cs = field->charset();
2785
2786
			blob_data = row_mysql_read_blob_ref(&blob_len,
2787
				(byte*) (record
2788
				+ (ulint)get_field_offset(table, field)),
2789
					(ulint) field->pack_length());
2790
2791
			true_len = blob_len;
2792
2793
			ut_a(get_field_offset(table, field)
2794
				== key_part->offset);
2795
2796
			/* For multi byte character sets we need to calculate
2797
			the true length of the key */
2798
2799
			if (blob_len > 0 && cs->mbmaxlen > 1) {
2800
				true_len = (ulint) cs->cset->well_formed_len(cs,
2801
						(const char *) blob_data,
2802
						(const char *) blob_data
2803
							+ blob_len,
2804
                                                (uint) (key_len /
2805
                                                        cs->mbmaxlen),
2806
						&error);
2807
			}
2808
2809
			/* All indexes on BLOB and TEXT are column prefix
2810
			indexes, and we may need to truncate the data to be
2811
			stored in the key value: */
2812
2813
			if (true_len > key_len) {
2814
				true_len = key_len;
2815
			}
2816
2817
			/* MySQL reserves 2 bytes for the length and the
2818
			storage of the number is little-endian */
2819
2820
			innobase_write_to_2_little_endian(
2821
					(byte*)buff, true_len);
2822
			buff += 2;
2823
2824
			memcpy(buff, blob_data, true_len);
2825
2826
			/* Note that we always reserve the maximum possible
2827
			length of the BLOB prefix in the key value. */
2828
2829
			buff += key_len;
2830
		} else {
2831
			/* Here we handle all other data types except the
2832
			true VARCHAR, BLOB and TEXT. Note that the column
2833
			value we store may be also in a column prefix
2834
			index. */
2835
2836
			ulint			true_len;
2837
			ulint			key_len;
481 by Brian Aker
Remove all of uchar.
2838
			const unsigned char*		src_start;
1 by brian
clean slate
2839
			enum_field_types	real_type;
2840
2841
			key_len = key_part->length;
2842
2843
			if (is_null) {
2844
				 buff += key_len;
2845
2846
				 continue;
2847
			}
2848
2849
			src_start = record + key_part->offset;
2850
			real_type = field->real_type();
2851
			true_len = key_len;
2852
2853
			/* Character set for the field is defined only
2854
			to fields whose type is string and real field
2855
			type is not enum or set. For these fields check
2856
			if character set is multi byte. */
2857
2858
			memcpy(buff, src_start, true_len);
2859
			buff += true_len;
2860
2861
			/* Pad the unused space with spaces. Note that no
2862
			padding is ever needed for UCS-2 because in MySQL,
2863
			all UCS2 characters are 2 bytes, as MySQL does not
2864
			support surrogate pairs, which are needed to represent
2865
			characters in the range U+10000 to U+10FFFF. */
2866
2867
			if (true_len < key_len) {
2868
				ulint pad_len = key_len - true_len;
2869
				memset(buff, ' ', pad_len);
2870
				buff += pad_len;
2871
			}
2872
		}
2873
	}
2874
2875
	ut_a(buff <= buff_start + buff_len);
2876
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
2877
	return((uint)(buff - buff_start));
1 by brian
clean slate
2878
}
2879
2880
/******************************************************************
2881
Builds a 'template' to the prebuilt struct. The template is used in fast
2882
retrieval of just those column values MySQL needs in its processing. */
2883
static
2884
void
2885
build_template(
2886
/*===========*/
2887
	row_prebuilt_t*	prebuilt,	/* in/out: prebuilt struct */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
2888
	THD*		thd __attribute__((unused)),		/* in: current user thread, used
1 by brian
clean slate
2889
					only if templ_type is
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2890
					ROW_DRIZZLE_REC_FIELDS */
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
2891
	Table*		table,		/* in: MySQL table */
1 by brian
clean slate
2892
        ha_innobase*    file,           /* in: ha_innobase handler */
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2893
	uint		templ_type)	/* in: ROW_DRIZZLE_WHOLE_ROW or
2894
					ROW_DRIZZLE_REC_FIELDS */
1 by brian
clean slate
2895
{
2896
	dict_index_t*	index;
2897
	dict_index_t*	clust_index;
2898
	mysql_row_templ_t* templ;
2899
	Field*		field;
2900
	ulint		n_fields;
2901
	ulint		n_requested_fields	= 0;
2902
	ibool		fetch_all_in_key	= FALSE;
2903
	ibool		fetch_primary_key_cols	= FALSE;
2904
	ulint		i;
2905
	/* byte offset of the end of last requested column */
2906
	ulint		mysql_prefix_len	= 0;
2907
        ibool           do_idx_cond_push= FALSE;
2908
	ibool           need_second_pass= FALSE;
2909
        
2910
	if (prebuilt->select_lock_type == LOCK_X) {
2911
		/* We always retrieve the whole clustered index record if we
2912
		use exclusive row level locks, for example, if the read is
2913
		done in an UPDATE statement. */
2914
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2915
		templ_type = ROW_DRIZZLE_WHOLE_ROW;
1 by brian
clean slate
2916
	}
2917
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2918
	if (templ_type == ROW_DRIZZLE_REC_FIELDS) {
1 by brian
clean slate
2919
		if (prebuilt->hint_need_to_fetch_extra_cols
2920
			== ROW_RETRIEVE_ALL_COLS) {
2921
2922
			/* We know we must at least fetch all columns in the
2923
			key, or all columns in the table */
2924
2925
			if (prebuilt->read_just_key) {
2926
				/* MySQL has instructed us that it is enough
2927
				to fetch the columns in the key; looks like
2928
				MySQL can set this flag also when there is
2929
				only a prefix of the column in the key: in
2930
				that case we retrieve the whole column from
2931
				the clustered index */
2932
2933
				fetch_all_in_key = TRUE;
2934
			} else {
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2935
				templ_type = ROW_DRIZZLE_WHOLE_ROW;
1 by brian
clean slate
2936
			}
2937
		} else if (prebuilt->hint_need_to_fetch_extra_cols
2938
			== ROW_RETRIEVE_PRIMARY_KEY) {
2939
			/* We must at least fetch all primary key cols. Note
2940
			   that if the clustered index was internally generated
2941
			   by InnoDB on the row id (no primary key was
2942
			   defined), then row_search_for_mysql() will always
2943
			   retrieve the row id to a special buffer in the
2944
			   prebuilt struct. */
2945
2946
			fetch_primary_key_cols = TRUE;
2947
		}
2948
	}
2949
2950
	clust_index = dict_table_get_first_index_noninline(prebuilt->table);
2951
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2952
	if (templ_type == ROW_DRIZZLE_REC_FIELDS) {
1 by brian
clean slate
2953
		index = prebuilt->index;
2954
	} else {
2955
		index = clust_index;
2956
	}
2957
2958
	if (index == clust_index) {
2959
		prebuilt->need_to_access_clustered = TRUE;
2960
	} else {
2961
		prebuilt->need_to_access_clustered = FALSE;
2962
		/* Below we check column by column if we need to access
2963
		the clustered index */
2964
	}
2965
2966
	n_fields = (ulint)table->s->fields; /* number of columns */
2967
2968
	if (!prebuilt->mysql_template) {
2969
		prebuilt->mysql_template = (mysql_row_templ_t*)
2970
						mem_alloc_noninline(
2971
					n_fields * sizeof(mysql_row_templ_t));
2972
	}
2973
2974
	prebuilt->template_type = templ_type;
2975
	prebuilt->null_bitmap_len = table->s->null_bytes;
2976
2977
	prebuilt->templ_contains_blob = FALSE;
2978
2979
2980
        /*
2981
          Setup index condition pushdown (note: we don't need to check if
2982
          this is a scan on primary key as that is checked in idx_cond_push)
2983
        */
2984
        if (file->active_index == file->pushed_idx_cond_keyno && 
2985
            file->active_index != MAX_KEY)
2986
          do_idx_cond_push= need_second_pass= TRUE;
2987
2988
        /* 
2989
          Ok, now build an array of mysql_row_templ_struct structures. 
2990
          If index condition pushdown is used, the array is split into two
2991
          parts: first go index fields, then go table fields.
2992
	  
2993
          Note that in InnoDB, i is the column number. MySQL calls columns
2994
	  'fields'.
2995
        */
2996
	for (i = 0; i < n_fields; i++) {
2997
		templ = prebuilt->mysql_template + n_requested_fields;
2998
		field = table->field[i];
2999
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
3000
		if (UNIV_LIKELY(templ_type == ROW_DRIZZLE_REC_FIELDS)) {
1 by brian
clean slate
3001
			/* Decide which columns we should fetch
3002
			and which we can skip. */
3003
			register const ibool	index_contains_field =
3004
				dict_index_contains_col_or_prefix(index, i);
3005
                        register const ibool    index_covers_field = 
3006
                                field->part_of_key.is_set(file->active_index);
3007
3008
			if (!index_contains_field && prebuilt->read_just_key) {
3009
				/* If this is a 'key read', we do not need
3010
				columns that are not in the key */
3011
3012
				goto skip_field;
3013
			}
3014
3015
			if (index_contains_field && fetch_all_in_key) {
3016
				/* This field is needed in the query */
3017
3018
				goto include_field;
3019
			}
3020
3021
                        if (bitmap_is_set(table->read_set, i) ||
3022
                            bitmap_is_set(table->write_set, i)) {
3023
				/* This field is needed in the query */
3024
3025
				goto include_field;
3026
			}
3027
3028
			if (fetch_primary_key_cols
3029
				&& dict_table_col_in_clustered_key(
3030
					index->table, i)) {
3031
				/* This field is needed in the query */
3032
3033
				goto include_field;
3034
			}
3035
3036
			/* This field is not needed in the query, skip it */
3037
3038
			goto skip_field;
3039
include_field:
3040
			if (do_idx_cond_push && 
3041
                            ((need_second_pass && !index_covers_field) || 
3042
                             (!need_second_pass && index_covers_field)))
3043
			  goto skip_field;
3044
		}
3045
		n_requested_fields++;
3046
3047
		templ->col_no = i;
3048
3049
		if (index == clust_index) {
3050
			templ->rec_field_no = dict_col_get_clust_pos_noninline(
3051
				&index->table->cols[i], index);
3052
		} else {
3053
			templ->rec_field_no = dict_index_get_nth_col_pos(
3054
								index, i);
3055
		}
3056
3057
		if (templ->rec_field_no == ULINT_UNDEFINED) {
3058
			prebuilt->need_to_access_clustered = TRUE;
3059
		}
3060
3061
		if (field->null_ptr) {
3062
			templ->mysql_null_byte_offset =
3063
				(ulint) ((char*) field->null_ptr
3064
					- (char*) table->record[0]);
3065
3066
			templ->mysql_null_bit_mask = (ulint) field->null_bit;
3067
		} else {
3068
			templ->mysql_null_bit_mask = 0;
3069
		}
3070
3071
		templ->mysql_col_offset = (ulint)
3072
					get_field_offset(table, field);
3073
3074
		templ->mysql_col_len = (ulint) field->pack_length();
3075
		if (mysql_prefix_len < templ->mysql_col_offset
3076
				+ templ->mysql_col_len) {
3077
			mysql_prefix_len = templ->mysql_col_offset
3078
				+ templ->mysql_col_len;
3079
		}
3080
		templ->type = index->table->cols[i].mtype;
3081
		templ->mysql_type = (ulint)field->type();
3082
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
3083
		if (templ->mysql_type == DATA_DRIZZLE_TRUE_VARCHAR) {
1 by brian
clean slate
3084
			templ->mysql_length_bytes = (ulint)
3085
				(((Field_varstring*)field)->length_bytes);
3086
		}
3087
3088
		templ->charset = dtype_get_charset_coll_noninline(
3089
				index->table->cols[i].prtype);
3090
		templ->mbminlen = index->table->cols[i].mbminlen;
3091
		templ->mbmaxlen = index->table->cols[i].mbmaxlen;
3092
		templ->is_unsigned = index->table->cols[i].prtype
3093
							& DATA_UNSIGNED;
3094
		if (templ->type == DATA_BLOB) {
3095
			prebuilt->templ_contains_blob = TRUE;
3096
		}
3097
skip_field:
3098
		if (need_second_pass && (i+1 == n_fields))
3099
		{
3100
                  prebuilt->n_index_fields= n_requested_fields;
3101
		  need_second_pass= FALSE;
3102
		  i= (~(ulint)0); /* to start from 0 */
3103
		}
3104
	}
3105
3106
	prebuilt->n_template = n_requested_fields;
3107
	prebuilt->mysql_prefix_len = mysql_prefix_len;
3108
3109
        if (do_idx_cond_push)
3110
        {
3111
          prebuilt->idx_cond_func= index_cond_func_innodb;
3112
          prebuilt->idx_cond_func_arg= file;
3113
        }
3114
        else
3115
        {
3116
          prebuilt->idx_cond_func= NULL;
3117
          prebuilt->n_index_fields= n_requested_fields;
3118
        }
3119
       // file->in_range_read= FALSE;
3120
3121
	if (index != clust_index && prebuilt->need_to_access_clustered) {
3122
		/* Change rec_field_no's to correspond to the clustered index
3123
		record */
3124
		for (i = do_idx_cond_push? prebuilt->n_index_fields : 0; 
3125
                     i < n_requested_fields; i++) {
3126
			templ = prebuilt->mysql_template + i;
3127
			templ->rec_field_no = dict_col_get_clust_pos_noninline(
3128
				&index->table->cols[templ->col_no],
3129
				clust_index);
3130
		}
3131
	}
3132
}
3133
3134
/************************************************************************
3135
This special handling is really to overcome the limitations of MySQL's
3136
binlogging. We need to eliminate the non-determinism that will arise in
3137
INSERT ... SELECT type of statements, since MySQL binlog only stores the
3138
min value of the autoinc interval. Once that is fixed we can get rid of
3139
the special lock handling.*/
3140
3141
ulong
3142
ha_innobase::innobase_autoinc_lock(void)
3143
/*====================================*/
3144
					/* out: DB_SUCCESS if all OK else
3145
					error code */
3146
{
3147
	ulint		error = DB_SUCCESS;
3148
3149
	switch (innobase_autoinc_lock_mode) {
3150
	case AUTOINC_NO_LOCKING:
3151
		/* Acquire only the AUTOINC mutex. */
3152
		dict_table_autoinc_lock(prebuilt->table);
3153
		break;
3154
3155
	case AUTOINC_NEW_STYLE_LOCKING:
3156
		/* For simple (single/multi) row INSERTs, we fallback to the
3157
		old style only if another transaction has already acquired
3158
		the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
3159
		etc. type of statement. */
3160
		if (thd_sql_command(user_thd) == SQLCOM_INSERT) {
3161
			dict_table_t*	table = prebuilt->table;
3162
3163
			/* Acquire the AUTOINC mutex. */
3164
			dict_table_autoinc_lock(table);
3165
3166
			/* We need to check that another transaction isn't
3167
			already holding the AUTOINC lock on the table. */
3168
			if (table->n_waiting_or_granted_auto_inc_locks) {
3169
				/* Release the mutex to avoid deadlocks. */
3170
				dict_table_autoinc_unlock(table);
3171
			} else {
3172
				break;
3173
			}
3174
		}
3175
		/* Fall through to old style locking. */
3176
3177
	case AUTOINC_OLD_STYLE_LOCKING:
3178
		error = row_lock_table_autoinc_for_mysql(prebuilt);
3179
3180
		if (error == DB_SUCCESS) {
3181
3182
			/* Acquire the AUTOINC mutex. */
3183
			dict_table_autoinc_lock(prebuilt->table);
3184
		}
3185
		break;
3186
3187
	default:
3188
		ut_error;
3189
	}
3190
3191
	return(ulong(error));
3192
}
3193
3194
/************************************************************************
3195
Reset the autoinc value in the table.*/
3196
3197
ulong
3198
ha_innobase::innobase_reset_autoinc(
3199
/*================================*/
3200
					/* out: DB_SUCCESS if all went well
3201
					else error code */
151 by Brian Aker
Ulonglong to uint64_t
3202
	uint64_t	autoinc)	/* in: value to store */
1 by brian
clean slate
3203
{
3204
	ulint		error;
3205
3206
	error = innobase_autoinc_lock();
3207
3208
	if (error == DB_SUCCESS) {
3209
3210
		dict_table_autoinc_initialize(prebuilt->table, autoinc);
3211
3212
		dict_table_autoinc_unlock(prebuilt->table);
3213
	}
3214
3215
	return(ulong(error));
3216
}
3217
3218
/************************************************************************
3219
Store the autoinc value in the table. The autoinc value is only set if
3220
it's greater than the existing autoinc value in the table.*/
3221
3222
ulong
3223
ha_innobase::innobase_set_max_autoinc(
3224
/*==================================*/
3225
					/* out: DB_SUCCES if all went well
3226
					else error code */
151 by Brian Aker
Ulonglong to uint64_t
3227
	uint64_t	auto_inc)	/* in: value to store */
1 by brian
clean slate
3228
{
3229
	ulint		error;
3230
3231
	error = innobase_autoinc_lock();
3232
3233
	if (error == DB_SUCCESS) {
3234
3235
		dict_table_autoinc_update(prebuilt->table, auto_inc);
3236
3237
		dict_table_autoinc_unlock(prebuilt->table);
3238
	}
3239
3240
	return(ulong(error));
3241
}
3242
3243
/************************************************************************
3244
Stores a row in an InnoDB database, to the table specified in this
3245
handle. */
3246
3247
int
3248
ha_innobase::write_row(
3249
/*===================*/
3250
			/* out: error code */
481 by Brian Aker
Remove all of uchar.
3251
	unsigned char*	record)	/* in: a row in MySQL format */
1 by brian
clean slate
3252
{
3253
	int		error = 0;
3254
	ibool		auto_inc_used= FALSE;
3255
	ulint		sql_command;
3256
	trx_t*		trx = thd_to_trx(user_thd);
3257
3258
	if (prebuilt->trx != trx) {
3259
	  sql_print_error("The transaction object for the table handle is at "
3260
			  "%p, but for the current thread it is at %p",
77.1.8 by Monty Taylor
InnoDB compiles clean. Need to send this patch upstream.
3261
                          (void *)prebuilt->trx, (void *)trx);
1 by brian
clean slate
3262
3263
		fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
3264
		ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
3265
		fputs("\n"
3266
			"InnoDB: Dump of 200 bytes around ha_data: ",
3267
			stderr);
3268
		ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
3269
		putc('\n', stderr);
3270
		ut_error;
3271
	}
3272
3273
	ha_statistic_increment(&SSV::ha_write_count);
3274
3275
	if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
3276
		table->timestamp_field->set_time();
3277
3278
	sql_command = thd_sql_command(user_thd);
3279
3280
	if ((sql_command == SQLCOM_ALTER_TABLE
3281
	     || sql_command == SQLCOM_OPTIMIZE
3282
	     || sql_command == SQLCOM_CREATE_INDEX
3283
	     || sql_command == SQLCOM_DROP_INDEX)
3284
	    && num_write_row >= 10000) {
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
3285
		/* ALTER Table is COMMITted at every 10000 copied rows.
1 by brian
clean slate
3286
		The IX table lock for the original table has to be re-issued.
3287
		As this method will be called on a temporary table where the
3288
		contents of the original table is being copied to, it is
3289
		a bit tricky to determine the source table.  The cursor
3290
		position in the source table need not be adjusted after the
3291
		intermediate COMMIT, since writes by other transactions are
3292
		being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
3293
3294
		dict_table_t*	src_table;
3295
		ulint		mode;
3296
3297
		num_write_row = 0;
3298
3299
		/* Commit the transaction.  This will release the table
3300
		locks, so they have to be acquired again. */
3301
3302
		/* Altering an InnoDB table */
3303
		/* Get the source table. */
3304
		src_table = lock_get_src_table(
3305
				prebuilt->trx, prebuilt->table, &mode);
3306
		if (!src_table) {
3307
no_commit:
3308
			/* Unknown situation: do not commit */
3309
			/*
3310
			ut_print_timestamp(stderr);
3311
			fprintf(stderr,
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
3312
				"  InnoDB: ALTER Table is holding lock"
1 by brian
clean slate
3313
				" on %lu tables!\n",
3314
				prebuilt->trx->mysql_n_tables_locked);
3315
			*/
3316
			;
3317
		} else if (src_table == prebuilt->table) {
3318
			/* Source table is not in InnoDB format:
3319
			no need to re-acquire locks on it. */
3320
3321
			/* Altering to InnoDB format */
3322
			innobase_commit(ht, user_thd, 1);
3323
			/* Note that this transaction is still active. */
3324
			prebuilt->trx->active_trans = 1;
3325
			/* We will need an IX lock on the destination table. */
3326
			prebuilt->sql_stat_start = TRUE;
3327
		} else {
3328
			/* Ensure that there are no other table locks than
3329
			LOCK_IX and LOCK_AUTO_INC on the destination table. */
3330
3331
			if (!lock_is_table_exclusive(prebuilt->table,
3332
							prebuilt->trx)) {
3333
				goto no_commit;
3334
			}
3335
3336
			/* Commit the transaction.  This will release the table
3337
			locks, so they have to be acquired again. */
3338
			innobase_commit(ht, user_thd, 1);
3339
			/* Note that this transaction is still active. */
3340
			prebuilt->trx->active_trans = 1;
3341
			/* Re-acquire the table lock on the source table. */
3342
			row_lock_table_for_mysql(prebuilt, src_table, mode);
3343
			/* We will need an IX lock on the destination table. */
3344
			prebuilt->sql_stat_start = TRUE;
3345
		}
3346
	}
3347
3348
	num_write_row++;
3349
3350
	/* This is the case where the table has an auto-increment column */
3351
	if (table->next_number_field && record == table->record[0]) {
3352
3353
		if ((error = update_auto_increment())) {
3354
3355
			goto func_exit;
3356
		}
3357
3358
		auto_inc_used = TRUE;
3359
	}
3360
3361
	if (prebuilt->mysql_template == NULL
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
3362
	    || prebuilt->template_type != ROW_DRIZZLE_WHOLE_ROW) {
1 by brian
clean slate
3363
3364
		/* Build the template used in converting quickly between
3365
		the two database formats */
3366
3367
		build_template(prebuilt, NULL, table, 
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
3368
                                                   this, ROW_DRIZZLE_WHOLE_ROW);
1 by brian
clean slate
3369
	}
3370
3371
	innodb_srv_conc_enter_innodb(prebuilt->trx);
3372
3373
	error = row_insert_for_mysql((byte*) record, prebuilt);
3374
3375
	/* Handle duplicate key errors */
3376
	if (auto_inc_used) {
3377
		ulint		err;
151 by Brian Aker
Ulonglong to uint64_t
3378
		uint64_t	auto_inc;
1 by brian
clean slate
3379
3380
		/* Note the number of rows processed for this statement, used
3381
		by get_auto_increment() to determine the number of AUTO-INC
3382
		values to reserve. This is only useful for a mult-value INSERT
3383
		and is a statement level counter.*/
3384
		if (trx->n_autoinc_rows > 0) {
3385
			--trx->n_autoinc_rows;
3386
		}
3387
3388
		/* Get the value that MySQL attempted to store in the table.*/
3389
		auto_inc = table->next_number_field->val_int();
3390
3391
		switch (error) {
3392
		case DB_DUPLICATE_KEY:
3393
3394
			/* A REPLACE command and LOAD DATA INFILE REPLACE
3395
			handle a duplicate key error themselves, but we
3396
			must update the autoinc counter if we are performing
3397
			those statements. */
3398
3399
			switch (sql_command) {
3400
			case SQLCOM_LOAD:
3401
				if ((trx->duplicates
3402
				    & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
3403
3404
					goto set_max_autoinc;
3405
				}
3406
				break;
3407
3408
			case SQLCOM_REPLACE:
3409
			case SQLCOM_INSERT_SELECT:
3410
			case SQLCOM_REPLACE_SELECT:
3411
				goto set_max_autoinc;
3412
				break;
3413
3414
			default:
3415
				break;
3416
			}
3417
3418
			break;
3419
3420
		case DB_SUCCESS:
3421
			/* If the actual value inserted is greater than
3422
			the upper limit of the interval, then we try and
3423
			update the table upper limit. Note: last_value
3424
			will be 0 if get_auto_increment() was not called.*/
3425
3426
			if (auto_inc > prebuilt->last_value) {
3427
set_max_autoinc:
3428
				ut_a(prebuilt->table->autoinc_increment > 0);
3429
				auto_inc += prebuilt->table->autoinc_increment;
3430
3431
				err = innobase_set_max_autoinc(auto_inc);
3432
3433
				if (err != DB_SUCCESS) {
3434
					error = (int) err;
3435
				}
3436
			}
3437
			break;
3438
		}
3439
	}
3440
3441
	innodb_srv_conc_exit_innodb(prebuilt->trx);
3442
3443
	error = convert_error_code_to_mysql(error, user_thd);
3444
3445
func_exit:
3446
	innobase_active_small();
3447
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
3448
	return(error);
1 by brian
clean slate
3449
}
3450
3451
/**************************************************************************
3452
Checks which fields have changed in a row and stores information
3453
of them to an update vector. */
3454
static
3455
int
3456
calc_row_difference(
3457
/*================*/
3458
					/* out: error number or 0 */
3459
	upd_t*		uvect,		/* in/out: update vector */
481 by Brian Aker
Remove all of uchar.
3460
	unsigned char*		old_row,	/* in: old row in MySQL format */
3461
	unsigned char*		new_row,	/* in: new row in MySQL format */
327.1.1 by Brian Aker
First pass in encapsulating table (it is now an object, no longer a structure).
3462
        Table *table,		/* in: table in MySQL data
1 by brian
clean slate
3463
					dictionary */
481 by Brian Aker
Remove all of uchar.
3464
	unsigned char*		upd_buff,	/* in: buffer to use */
1 by brian
clean slate
3465
	ulint		buff_len,	/* in: buffer length */
3466
	row_prebuilt_t*	prebuilt,	/* in: InnoDB prebuilt struct */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
3467
	THD*		thd __attribute__((unused)))		/* in: user thread */
1 by brian
clean slate
3468
{
481 by Brian Aker
Remove all of uchar.
3469
	unsigned char*		original_upd_buff = upd_buff;
1 by brian
clean slate
3470
	Field*		field;
3471
	enum_field_types field_mysql_type;
3472
	uint		n_fields;
3473
	ulint		o_len;
3474
	ulint		n_len;
3475
	ulint		col_pack_len;
3476
	byte*		new_mysql_row_col;
3477
	byte*		o_ptr;
3478
	byte*		n_ptr;
3479
	byte*		buf;
3480
	upd_field_t*	ufield;
3481
	ulint		col_type;
3482
	ulint		n_changed = 0;
3483
	dfield_t	dfield;
3484
	dict_index_t*	clust_index;
3485
	uint		i;
3486
3487
	n_fields = table->s->fields;
3488
	clust_index = dict_table_get_first_index_noninline(prebuilt->table);
3489
3490
	/* We use upd_buff to convert changed fields */
3491
	buf = (byte*) upd_buff;
3492
3493
	for (i = 0; i < n_fields; i++) {
3494
		field = table->field[i];
3495
3496
		o_ptr = (byte*) old_row + get_field_offset(table, field);
3497
		n_ptr = (byte*) new_row + get_field_offset(table, field);
3498
3499
		/* Use new_mysql_row_col and col_pack_len save the values */
3500
3501
		new_mysql_row_col = n_ptr;
3502
		col_pack_len = field->pack_length();
3503
3504
		o_len = col_pack_len;
3505
		n_len = col_pack_len;
3506
3507
		/* We use o_ptr and n_ptr to dig up the actual data for
3508
		comparison. */
3509
3510
		field_mysql_type = field->type();
3511
3512
		col_type = prebuilt->table->cols[i].mtype;
3513
3514
		switch (col_type) {
3515
3516
		case DATA_BLOB:
3517
			o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
3518
			n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
3519
3520
			break;
3521
3522
		case DATA_VARCHAR:
3523
		case DATA_BINARY:
3524
		case DATA_VARMYSQL:
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
3525
			if (field_mysql_type == DRIZZLE_TYPE_VARCHAR) {
1 by brian
clean slate
3526
				/* This is a >= 5.0.3 type true VARCHAR where
3527
				the real payload data length is stored in
3528
				1 or 2 bytes */
3529
3530
				o_ptr = row_mysql_read_true_varchar(
3531
					&o_len, o_ptr,
3532
					(ulint)
3533
					(((Field_varstring*)field)->length_bytes));
3534
3535
				n_ptr = row_mysql_read_true_varchar(
3536
					&n_len, n_ptr,
3537
					(ulint)
3538
					(((Field_varstring*)field)->length_bytes));
3539
			}
3540
3541
			break;
3542
		default:
3543
			;
3544
		}
3545
3546
		if (field->null_ptr) {
3547
			if (field_in_record_is_null(table, field,
3548
							(char*) old_row)) {
3549
				o_len = UNIV_SQL_NULL;
3550
			}
3551
3552
			if (field_in_record_is_null(table, field,
3553
							(char*) new_row)) {
3554
				n_len = UNIV_SQL_NULL;
3555
			}
3556
		}
3557
3558
		if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
3559
					0 != memcmp(o_ptr, n_ptr, o_len))) {
3560
			/* The field has changed */
3561
3562
			ufield = uvect->fields + n_changed;
3563
3564
			/* Let us use a dummy dfield to make the conversion
3565
			from the MySQL column format to the InnoDB format */
3566
3567
			dict_col_copy_type_noninline(prebuilt->table->cols + i,
3568
						     &dfield.type);
3569
3570
			if (n_len != UNIV_SQL_NULL) {
3571
				buf = row_mysql_store_col_in_innobase_format(
3572
					&dfield,
3573
					(byte*)buf,
3574
					TRUE,
3575
					new_mysql_row_col,
3576
					col_pack_len,
3577
					dict_table_is_comp_noninline(
3578
							prebuilt->table));
3579
				ufield->new_val.data = dfield.data;
3580
				ufield->new_val.len = dfield.len;
3581
			} else {
3582
				ufield->new_val.data = NULL;
3583
				ufield->new_val.len = UNIV_SQL_NULL;
3584
			}
3585
3586
			ufield->exp = NULL;
3587
			ufield->field_no = dict_col_get_clust_pos_noninline(
3588
				&prebuilt->table->cols[i], clust_index);
3589
			n_changed++;
3590
		}
3591
	}
3592
3593
	uvect->n_fields = n_changed;
3594
	uvect->info_bits = 0;
3595
3596
	ut_a(buf <= (byte*)original_upd_buff + buff_len);
3597
3598
	return(0);
3599
}
3600
3601
/**************************************************************************
3602
Updates a row given as a parameter to a new value. Note that we are given
3603
whole rows, not just the fields which are updated: this incurs some
3604
overhead for CPU when we check which fields are actually updated.
3605
TODO: currently InnoDB does not prevent the 'Halloween problem':
3606
in a searched update a single row can get updated several times
3607
if its index columns are updated! */
3608
3609
int
3610
ha_innobase::update_row(
3611
/*====================*/
3612
					/* out: error number or 0 */
481 by Brian Aker
Remove all of uchar.
3613
	const unsigned char*	old_row,	/* in: old row in MySQL format */
3614
	unsigned char*		new_row)	/* in: new row in MySQL format */
1 by brian
clean slate
3615
{
3616
	upd_t*		uvect;
3617
	int		error = 0;
3618
	trx_t*		trx = thd_to_trx(user_thd);
3619
3620
	ut_a(prebuilt->trx == trx);
3621
3622
	if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
3623
		table->timestamp_field->set_time();
3624
3625
	if (prebuilt->upd_node) {
3626
		uvect = prebuilt->upd_node->update;
3627
	} else {
3628
		uvect = row_get_prebuilt_update_vector(prebuilt);
3629
	}
3630
3631
	/* Build an update vector from the modified fields in the rows
3632
	(uses upd_buff of the handle) */
3633
481 by Brian Aker
Remove all of uchar.
3634
	calc_row_difference(uvect, (unsigned char*) old_row, new_row, table,
1 by brian
clean slate
3635
			upd_buff, (ulint)upd_and_key_val_buff_len,
3636
			prebuilt, user_thd);
3637
3638
	/* This is not a delete */
3639
	prebuilt->upd_node->is_delete = FALSE;
3640
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
3641
	assert(prebuilt->template_type == ROW_DRIZZLE_WHOLE_ROW);
1 by brian
clean slate
3642
3643
	innodb_srv_conc_enter_innodb(trx);
3644
3645
	error = row_update_for_mysql((byte*) old_row, prebuilt);
3646
3647
	/* We need to do some special AUTOINC handling for the following case:
3648
3649
	INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
3650
3651
	We need to use the AUTOINC counter that was actually used by
3652
	MySQL in the UPDATE statement, which can be different from the
3653
	value used in the INSERT statement.*/
3654
3655
	if (error == DB_SUCCESS
3656
	    && table->next_number_field
3657
	    && new_row == table->record[0]
3658
	    && thd_sql_command(user_thd) == SQLCOM_INSERT
3659
	    && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
3660
		== TRX_DUP_IGNORE)  {
3661
152 by Brian Aker
longlong replacement
3662
		int64_t	auto_inc;
1 by brian
clean slate
3663
3664
		auto_inc = table->next_number_field->val_int();
3665
3666
		if (auto_inc != 0) {
3667
			auto_inc += prebuilt->table->autoinc_increment;
3668
3669
			error = innobase_set_max_autoinc(auto_inc);
3670
		}
3671
	}
3672
3673
	innodb_srv_conc_exit_innodb(trx);
3674
3675
	error = convert_error_code_to_mysql(error, user_thd);
3676
3677
	/* Tell InnoDB server that there might be work for
3678
	utility threads: */
3679
3680
	innobase_active_small();
3681
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
3682
	return(error);
1 by brian
clean slate
3683
}
3684
3685
/**************************************************************************
3686
Deletes a row given as the parameter. */
3687
3688
int
3689
ha_innobase::delete_row(
3690
/*====================*/
3691
				/* out: error number or 0 */
481 by Brian Aker
Remove all of uchar.
3692
	const unsigned char*	record)	/* in: a row in MySQL format */
1 by brian
clean slate
3693
{
3694
	int		error = 0;
3695
	trx_t*		trx = thd_to_trx(user_thd);
3696
3697
	ut_a(prebuilt->trx == trx);
3698
3699
	/* Only if the table has an AUTOINC column */
3700
	if (table->found_next_number_field && record == table->record[0]) {
151 by Brian Aker
Ulonglong to uint64_t
3701
		uint64_t	dummy = 0;
1 by brian
clean slate
3702
3703
		/* First check whether the AUTOINC sub-system has been
3704
		initialized using the AUTOINC mutex. If not then we
3705
		do it the "proper" way, by acquiring the heavier locks. */
3706
		dict_table_autoinc_lock(prebuilt->table);
3707
3708
		if (!prebuilt->table->autoinc_inited) {
3709
			dict_table_autoinc_unlock(prebuilt->table);
3710
3711
			error = innobase_get_auto_increment(&dummy);
3712
3713
			if (error == DB_SUCCESS) {
3714
				dict_table_autoinc_unlock(prebuilt->table);
3715
			} else {
3716
				goto error_exit;
3717
			}
3718
		} else  {
3719
			dict_table_autoinc_unlock(prebuilt->table);
3720
		}
3721
	}
3722
3723
	if (!prebuilt->upd_node) {
3724
		row_get_prebuilt_update_vector(prebuilt);
3725
	}
3726
3727
	/* This is a delete */
3728
3729
	prebuilt->upd_node->is_delete = TRUE;
3730
3731
	innodb_srv_conc_enter_innodb(trx);
3732
3733
	error = row_update_for_mysql((byte*) record, prebuilt);
3734
3735
	innodb_srv_conc_exit_innodb(trx);
3736
3737
error_exit:
3738
	error = convert_error_code_to_mysql(error, user_thd);
3739
3740
	/* Tell the InnoDB server that there might be work for
3741
	utility threads: */
3742
3743
	innobase_active_small();
3744
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
3745
	return(error);
1 by brian
clean slate
3746
}
3747
3748
/**************************************************************************
3749
Removes a new lock set on a row, if it was not read optimistically. This can
3750
be called after a row has been read in the processing of an UPDATE or a DELETE
3751
query, if the option innodb_locks_unsafe_for_binlog is set. */
3752
3753
void
3754
ha_innobase::unlock_row(void)
3755
/*=========================*/
3756
{
3757
	/* Consistent read does not take any locks, thus there is
3758
	nothing to unlock. */
3759
3760
	if (prebuilt->select_lock_type == LOCK_NONE) {
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
3761
		return;
1 by brian
clean slate
3762
	}
3763
3764
	switch (prebuilt->row_read_type) {
3765
	case ROW_READ_WITH_LOCKS:
3766
		if (!srv_locks_unsafe_for_binlog
3767
		|| prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED) {
3768
			break;
3769
		}
3770
		/* fall through */
3771
	case ROW_READ_TRY_SEMI_CONSISTENT:
3772
		row_unlock_for_mysql(prebuilt, FALSE);
3773
		break;
3774
	case ROW_READ_DID_SEMI_CONSISTENT:
3775
		prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
3776
		break;
3777
	}
3778
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
3779
	return;
1 by brian
clean slate
3780
}
3781
3782
/* See handler.h and row0mysql.h for docs on this function. */
3783
bool
3784
ha_innobase::was_semi_consistent_read(void)
3785
/*=======================================*/
3786
{
3787
	return(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
3788
}
3789
3790
/* See handler.h and row0mysql.h for docs on this function. */
3791
void
3792
ha_innobase::try_semi_consistent_read(bool yes)
3793
/*===========================================*/
3794
{
3795
	ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
3796
3797
	/* Row read type is set to semi consistent read if this was
3798
	requested by the MySQL and either innodb_locks_unsafe_for_binlog
3799
	option is used or this session is using READ COMMITTED isolation
3800
	level. */
3801
3802
	if (yes
3803
	    && (srv_locks_unsafe_for_binlog
3804
		|| prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
3805
		prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
3806
	} else {
3807
		prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
3808
	}
3809
}
3810
3811
/**********************************************************************
3812
Initializes a handle to use an index. */
3813
3814
int
3815
ha_innobase::index_init(
3816
/*====================*/
3817
			/* out: 0 or error number */
3818
	uint	keynr,	/* in: key (index) number */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
3819
	bool sorted __attribute__((unused)))	/* in: 1 if result MUST be sorted according to index */
1 by brian
clean slate
3820
{
3821
	int	error	= 0;
3822
3823
	error = change_active_index(keynr);
3824
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
3825
	return(error);
1 by brian
clean slate
3826
}
3827
3828
/**********************************************************************
3829
Currently does nothing. */
3830
3831
int
3832
ha_innobase::index_end(void)
3833
/*========================*/
3834
{
3835
	int	error	= 0;
3836
	active_index=MAX_KEY;
3837
	in_range_check_pushed_down= FALSE;
3838
	ds_mrr.dsmrr_close();
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
3839
	return(error);
1 by brian
clean slate
3840
}
3841
3842
/*************************************************************************
3843
Converts a search mode flag understood by MySQL to a flag understood
3844
by InnoDB. */
3845
inline
3846
ulint
3847
convert_search_mode_to_innobase(
3848
/*============================*/
3849
	enum ha_rkey_function	find_flag)
3850
{
3851
	switch (find_flag) {
3852
	case HA_READ_KEY_EXACT:
3853
		/* this does not require the index to be UNIQUE */
3854
		return(PAGE_CUR_GE);
3855
	case HA_READ_KEY_OR_NEXT:
3856
		return(PAGE_CUR_GE);
3857
	case HA_READ_KEY_OR_PREV:
3858
		return(PAGE_CUR_LE);
3859
	case HA_READ_AFTER_KEY:	
3860
		return(PAGE_CUR_G);
3861
	case HA_READ_BEFORE_KEY:
3862
		return(PAGE_CUR_L);
3863
	case HA_READ_PREFIX:
3864
		return(PAGE_CUR_GE);
3865
	case HA_READ_PREFIX_LAST:
3866
		return(PAGE_CUR_LE);
3867
	case HA_READ_PREFIX_LAST_OR_PREV:
3868
		return(PAGE_CUR_LE);
3869
		/* In MySQL-4.0 HA_READ_PREFIX and HA_READ_PREFIX_LAST always
3870
		pass a complete-field prefix of a key value as the search
3871
		tuple. I.e., it is not allowed that the last field would
3872
		just contain n first bytes of the full field value.
3873
		MySQL uses a 'padding' trick to convert LIKE 'abc%'
3874
		type queries so that it can use as a search tuple
3875
		a complete-field-prefix of a key value. Thus, the InnoDB
3876
		search mode PAGE_CUR_LE_OR_EXTENDS is never used.
3877
		TODO: when/if MySQL starts to use also partial-field
3878
		prefixes, we have to deal with stripping of spaces
3879
		and comparison of non-latin1 char type fields in
3880
		innobase_mysql_cmp() to get PAGE_CUR_LE_OR_EXTENDS to
3881
		work correctly. */
3882
	case HA_READ_MBR_CONTAIN:
3883
	case HA_READ_MBR_INTERSECT:
3884
	case HA_READ_MBR_WITHIN:
3885
	case HA_READ_MBR_DISJOINT:
3886
	case HA_READ_MBR_EQUAL:
3887
		my_error(ER_TABLE_CANT_HANDLE_SPKEYS, MYF(0));
3888
		return(PAGE_CUR_UNSUPP);
3889
	/* do not use "default:" in order to produce a gcc warning:
3890
	enumeration value '...' not handled in switch
3891
	(if -Wswitch or -Wall is used) */
3892
	}
3893
3894
	my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality");
3895
3896
	return(PAGE_CUR_UNSUPP);
3897
}
3898
3899
/*
3900
   BACKGROUND INFO: HOW A SELECT SQL QUERY IS EXECUTED
3901
   ---------------------------------------------------
3902
The following does not cover all the details, but explains how we determine
3903
the start of a new SQL statement, and what is associated with it.
3904
3905
For each table in the database the MySQL interpreter may have several
3906
table handle instances in use, also in a single SQL query. For each table
3907
handle instance there is an InnoDB  'prebuilt' struct which contains most
3908
of the InnoDB data associated with this table handle instance.
3909
3910
  A) if the user has not explicitly set any MySQL table level locks:
3911
3912
  1) MySQL calls ::external_lock to set an 'intention' table level lock on
3913
the table of the handle instance. There we set
3914
prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should be set
3915
true if we are taking this table handle instance to use in a new SQL
3916
statement issued by the user. We also increment trx->n_mysql_tables_in_use.
3917
3918
  2) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
3919
instructions to prebuilt->template of the table handle instance in
3920
::index_read. The template is used to save CPU time in large joins.
3921
3922
  3) In row_search_for_mysql, if prebuilt->sql_stat_start is true, we
3923
allocate a new consistent read view for the trx if it does not yet have one,
3924
or in the case of a locking read, set an InnoDB 'intention' table level
3925
lock on the table.
3926
3927
  4) We do the SELECT. MySQL may repeatedly call ::index_read for the
3928
same table handle instance, if it is a join.
3929
3930
  5) When the SELECT ends, MySQL removes its intention table level locks
3931
in ::external_lock. When trx->n_mysql_tables_in_use drops to zero,
3932
 (a) we execute a COMMIT there if the autocommit is on,
3933
 (b) we also release possible 'SQL statement level resources' InnoDB may
3934
have for this SQL statement. The MySQL interpreter does NOT execute
3935
autocommit for pure read transactions, though it should. That is why the
3936
table handler in that case has to execute the COMMIT in ::external_lock.
3937
3938
  B) If the user has explicitly set MySQL table level locks, then MySQL
3939
does NOT call ::external_lock at the start of the statement. To determine
3940
when we are at the start of a new SQL statement we at the start of
3941
::index_read also compare the query id to the latest query id where the
3942
table handle instance was used. If it has changed, we know we are at the
3943
start of a new SQL statement. Since the query id can theoretically
3944
overwrap, we use this test only as a secondary way of determining the
3945
start of a new SQL statement. */
3946
3947
3948
/**************************************************************************
3949
Positions an index cursor to the index specified in the handle. Fetches the
3950
row if any. */
3951
3952
int
3953
ha_innobase::index_read(
3954
/*====================*/
3955
					/* out: 0, HA_ERR_KEY_NOT_FOUND,
3956
					or error number */
481 by Brian Aker
Remove all of uchar.
3957
	unsigned char*		buf,		/* in/out: buffer for the returned
1 by brian
clean slate
3958
					row */
481 by Brian Aker
Remove all of uchar.
3959
	const unsigned char*	key_ptr,	/* in: key value; if this is NULL
1 by brian
clean slate
3960
					we position the cursor at the
3961
					start or end of index; this can
3962
					also contain an InnoDB row id, in
3963
					which case key_len is the InnoDB
3964
					row id length; the key value can
3965
					also be a prefix of a full key value,
3966
					and the last column can be a prefix
3967
					of a full column */
3968
	uint			key_len,/* in: key value length */
3969
	enum ha_rkey_function find_flag)/* in: search flags from my_base.h */
3970
{
3971
	ulint		mode;
3972
	dict_index_t*	index;
3973
	ulint		match_mode	= 0;
3974
	int		error;
3975
	ulint		ret;
3976
3977
	ut_a(prebuilt->trx == thd_to_trx(user_thd));
3978
3979
	ha_statistic_increment(&SSV::ha_read_key_count);
3980
3981
	index = prebuilt->index;
3982
3983
	/* Note that if the index for which the search template is built is not
3984
	necessarily prebuilt->index, but can also be the clustered index */
3985
3986
	if (prebuilt->sql_stat_start) {
3987
		build_template(prebuilt, user_thd, table, this,
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
3988
							ROW_DRIZZLE_REC_FIELDS);
1 by brian
clean slate
3989
	}
3990
3991
	if (key_ptr) {
3992
		/* Convert the search key value to InnoDB format into
3993
		prebuilt->search_tuple */
3994
3995
		row_sel_convert_mysql_key_to_innobase(prebuilt->search_tuple,
3996
					(byte*) key_val_buff,
3997
					(ulint)upd_and_key_val_buff_len,
3998
					index,
3999
					(byte*) key_ptr,
4000
					(ulint) key_len, prebuilt->trx);
4001
	} else {
4002
		/* We position the cursor to the last or the first entry
4003
		in the index */
4004
4005
		dtuple_set_n_fields(prebuilt->search_tuple, 0);
4006
	}
4007
4008
	mode = convert_search_mode_to_innobase(find_flag);
4009
4010
	match_mode = 0;
4011
4012
	if (find_flag == HA_READ_KEY_EXACT) {
4013
		match_mode = ROW_SEL_EXACT;
4014
4015
	} else if (find_flag == HA_READ_PREFIX
4016
				|| find_flag == HA_READ_PREFIX_LAST) {
4017
		match_mode = ROW_SEL_EXACT_PREFIX;
4018
	}
4019
4020
	last_match_mode = (uint) match_mode;
4021
4022
	if (mode != PAGE_CUR_UNSUPP) {
4023
4024
		innodb_srv_conc_enter_innodb(prebuilt->trx);
4025
4026
		ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
4027
					   match_mode, 0);
4028
4029
		innodb_srv_conc_exit_innodb(prebuilt->trx);
4030
	} else {
4031
4032
		ret = DB_UNSUPPORTED;
4033
	}
4034
4035
	if (ret == DB_SUCCESS) {
4036
		error = 0;
4037
		table->status = 0;
4038
4039
	} else if (ret == DB_RECORD_NOT_FOUND) {
4040
		error = HA_ERR_KEY_NOT_FOUND;
4041
		table->status = STATUS_NOT_FOUND;
4042
4043
	} else if (ret == DB_END_OF_INDEX) {
4044
		error = HA_ERR_KEY_NOT_FOUND;
4045
		table->status = STATUS_NOT_FOUND;
4046
	} else {
4047
		error = convert_error_code_to_mysql((int) ret, user_thd);
4048
		table->status = STATUS_NOT_FOUND;
4049
	}
4050
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4051
	return(error);
1 by brian
clean slate
4052
}
4053
4054
/***********************************************************************
4055
The following functions works like index_read, but it find the last
4056
row with the current key value or prefix. */
4057
4058
int
4059
ha_innobase::index_read_last(
4060
/*=========================*/
4061
				/* out: 0, HA_ERR_KEY_NOT_FOUND, or an
4062
				error code */
481 by Brian Aker
Remove all of uchar.
4063
	unsigned char*		buf,	/* out: fetched row */
4064
	const unsigned char*	key_ptr,/* in: key value, or a prefix of a full
1 by brian
clean slate
4065
				key value */
4066
	uint		key_len)/* in: length of the key val or prefix
4067
				in bytes */
4068
{
4069
	return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
4070
}
4071
4072
/************************************************************************
4073
Get the index for a handle. Does not change active index.*/
4074
4075
dict_index_t*
4076
ha_innobase::innobase_get_index(
4077
/*============================*/
4078
				/* out: NULL or index instance. */
4079
	uint		keynr)	/* in: use this index; MAX_KEY means always
4080
				clustered index, even if it was internally
4081
				generated by InnoDB */
4082
{
4083
	KEY*		key = 0;
4084
	dict_index_t*	index = 0;
4085
4086
	ha_statistic_increment(&SSV::ha_read_key_count);
4087
4088
	ut_ad(user_thd == ha_thd());
4089
	ut_a(prebuilt->trx == thd_to_trx(user_thd));
4090
4091
	if (keynr != MAX_KEY && table->s->keys > 0) {
4092
		key = table->key_info + keynr;
4093
4094
		index = dict_table_get_index_noninline(
4095
			prebuilt->table, key->name);
4096
	} else {
4097
		index = dict_table_get_first_index_noninline(prebuilt->table);
4098
	}
4099
4100
	if (!index) {
4101
		sql_print_error(
4102
			"Innodb could not find key n:o %u with name %s "
4103
			"from dict cache for table %s",
4104
			keynr, key ? key->name : "NULL",
4105
			prebuilt->table->name);
4106
	}
4107
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4108
	return(index);
1 by brian
clean slate
4109
}
4110
4111
/************************************************************************
4112
Changes the active index of a handle. */
4113
4114
int
4115
ha_innobase::change_active_index(
4116
/*=============================*/
4117
			/* out: 0 or error code */
4118
	uint	keynr)	/* in: use this index; MAX_KEY means always clustered
4119
			index, even if it was internally generated by
4120
			InnoDB */
4121
{
4122
	ut_ad(user_thd == ha_thd());
4123
	ut_a(prebuilt->trx == thd_to_trx(user_thd));
4124
4125
	active_index = keynr;
4126
4127
	prebuilt->index = innobase_get_index(keynr);
4128
4129
	if (!prebuilt->index) {
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4130
		return(1);
1 by brian
clean slate
4131
	}
4132
4133
	assert(prebuilt->search_tuple != 0);
4134
4135
	dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
4136
4137
	dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
4138
			prebuilt->index->n_fields);
4139
4140
	/* MySQL changes the active index for a handle also during some
4141
	queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
4142
	and then calculates the sum. Previously we played safe and used
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
4143
	the flag ROW_DRIZZLE_WHOLE_ROW below, but that caused unnecessary
1 by brian
clean slate
4144
	copying. Starting from MySQL-4.1 we use a more efficient flag here. */
4145
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
4146
	build_template(prebuilt, user_thd, table, this, ROW_DRIZZLE_REC_FIELDS);
1 by brian
clean slate
4147
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4148
	return(0);
1 by brian
clean slate
4149
}
4150
4151
/**************************************************************************
4152
Positions an index cursor to the index specified in keynr. Fetches the
4153
row if any. */
4154
/* ??? This is only used to read whole keys ??? */
4155
4156
int
4157
ha_innobase::index_read_idx(
4158
/*========================*/
4159
					/* out: error number or 0 */
481 by Brian Aker
Remove all of uchar.
4160
	unsigned char*		buf,		/* in/out: buffer for the returned
1 by brian
clean slate
4161
					row */
4162
	uint		keynr,		/* in: use this index */
481 by Brian Aker
Remove all of uchar.
4163
	const unsigned char*	key,		/* in: key value; if this is NULL
1 by brian
clean slate
4164
					we position the cursor at the
4165
					start or end of index */
4166
	uint		key_len,	/* in: key value length */
4167
	enum ha_rkey_function find_flag)/* in: search flags from my_base.h */
4168
{
4169
	if (change_active_index(keynr)) {
4170
4171
		return(1);
4172
	}
4173
4174
	return(index_read(buf, key, key_len, find_flag));
4175
}
4176
4177
/***************************************************************************
4178
Reads the next or previous row from a cursor, which must have previously been
4179
positioned using index_read. */
4180
4181
int
4182
ha_innobase::general_fetch(
4183
/*=======================*/
4184
				/* out: 0, HA_ERR_END_OF_FILE, or error
4185
				number */
481 by Brian Aker
Remove all of uchar.
4186
	unsigned char*	buf,		/* in/out: buffer for next row in MySQL
1 by brian
clean slate
4187
				format */
4188
	uint	direction,	/* in: ROW_SEL_NEXT or ROW_SEL_PREV */
4189
	uint	match_mode)	/* in: 0, ROW_SEL_EXACT, or
4190
				ROW_SEL_EXACT_PREFIX */
4191
{
4192
	ulint		ret;
4193
	int		error	= 0;
4194
4195
	ut_a(prebuilt->trx == thd_to_trx(user_thd));
4196
4197
	innodb_srv_conc_enter_innodb(prebuilt->trx);
4198
4199
	ret = row_search_for_mysql((byte*)buf, 0, prebuilt, match_mode,
4200
								direction);
4201
	innodb_srv_conc_exit_innodb(prebuilt->trx);
4202
4203
	if (ret == DB_SUCCESS) {
4204
		error = 0;
4205
		table->status = 0;
4206
4207
	} else if (ret == DB_RECORD_NOT_FOUND) {
4208
		error = HA_ERR_END_OF_FILE;
4209
		table->status = STATUS_NOT_FOUND;
4210
4211
	} else if (ret == DB_END_OF_INDEX) {
4212
		error = HA_ERR_END_OF_FILE;
4213
		table->status = STATUS_NOT_FOUND;
4214
	} else {
4215
		error = convert_error_code_to_mysql((int) ret, user_thd);
4216
		table->status = STATUS_NOT_FOUND;
4217
	}
4218
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4219
	return(error);
1 by brian
clean slate
4220
}
4221
4222
/***************************************************************************
4223
Reads the next row from a cursor, which must have previously been
4224
positioned using index_read. */
4225
4226
int
4227
ha_innobase::index_next(
4228
/*====================*/
4229
				/* out: 0, HA_ERR_END_OF_FILE, or error
4230
				number */
481 by Brian Aker
Remove all of uchar.
4231
	unsigned char*		buf)	/* in/out: buffer for next row in MySQL
1 by brian
clean slate
4232
				format */
4233
{
4234
	ha_statistic_increment(&SSV::ha_read_next_count);
4235
4236
	return(general_fetch(buf, ROW_SEL_NEXT, 0));
4237
}
4238
4239
/***********************************************************************
4240
Reads the next row matching to the key value given as the parameter. */
4241
4242
int
4243
ha_innobase::index_next_same(
4244
/*=========================*/
4245
				/* out: 0, HA_ERR_END_OF_FILE, or error
4246
				number */
481 by Brian Aker
Remove all of uchar.
4247
	unsigned char*		buf,	/* in/out: buffer for the row */
4248
	const unsigned char*	key __attribute__((unused)),	/* in: key value */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
4249
	uint		keylen __attribute__((unused)))	/* in: key value length */
1 by brian
clean slate
4250
{
4251
	ha_statistic_increment(&SSV::ha_read_next_count);
4252
4253
	return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
4254
}
4255
4256
/***************************************************************************
4257
Reads the previous row from a cursor, which must have previously been
4258
positioned using index_read. */
4259
4260
int
4261
ha_innobase::index_prev(
4262
/*====================*/
4263
			/* out: 0, HA_ERR_END_OF_FILE, or error number */
481 by Brian Aker
Remove all of uchar.
4264
	unsigned char*	buf)	/* in/out: buffer for previous row in MySQL format */
1 by brian
clean slate
4265
{
4266
	ha_statistic_increment(&SSV::ha_read_prev_count);
4267
4268
	return(general_fetch(buf, ROW_SEL_PREV, 0));
4269
}
4270
4271
/************************************************************************
4272
Positions a cursor on the first record in an index and reads the
4273
corresponding row to buf. */
4274
4275
int
4276
ha_innobase::index_first(
4277
/*=====================*/
4278
			/* out: 0, HA_ERR_END_OF_FILE, or error code */
481 by Brian Aker
Remove all of uchar.
4279
	unsigned char*	buf)	/* in/out: buffer for the row */
1 by brian
clean slate
4280
{
4281
	int	error;
4282
4283
	ha_statistic_increment(&SSV::ha_read_first_count);
4284
4285
	error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
4286
4287
	/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4288
4289
	if (error == HA_ERR_KEY_NOT_FOUND) {
4290
		error = HA_ERR_END_OF_FILE;
4291
	}
4292
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4293
	return(error);
1 by brian
clean slate
4294
}
4295
4296
/************************************************************************
4297
Positions a cursor on the last record in an index and reads the
4298
corresponding row to buf. */
4299
4300
int
4301
ha_innobase::index_last(
4302
/*====================*/
4303
			/* out: 0, HA_ERR_END_OF_FILE, or error code */
481 by Brian Aker
Remove all of uchar.
4304
	unsigned char*	buf)	/* in/out: buffer for the row */
1 by brian
clean slate
4305
{
4306
	int	error;
4307
4308
	ha_statistic_increment(&SSV::ha_read_last_count);
4309
4310
	error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
4311
4312
	/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4313
4314
	if (error == HA_ERR_KEY_NOT_FOUND) {
4315
		error = HA_ERR_END_OF_FILE;
4316
	}
4317
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4318
	return(error);
1 by brian
clean slate
4319
}
4320
4321
/********************************************************************
4322
Initialize a table scan. */
4323
4324
int
4325
ha_innobase::rnd_init(
4326
/*==================*/
4327
			/* out: 0 or error number */
4328
	bool	scan)	/* in: ???????? */
4329
{
4330
	int	err;
4331
4332
	/* Store the active index value so that we can restore the original
4333
	value after a scan */
4334
4335
	if (prebuilt->clust_index_was_generated) {
4336
		err = change_active_index(MAX_KEY);
4337
	} else {
4338
		err = change_active_index(primary_key);
4339
	}
4340
4341
	/* Don't use semi-consistent read in random row reads (by position).
4342
	This means we must disable semi_consistent_read if scan is false */
4343
4344
	if (!scan) {
4345
		try_semi_consistent_read(0);
4346
	}
4347
4348
	start_of_scan = 1;
4349
4350
	return(err);
4351
}
4352
4353
/*********************************************************************
4354
Ends a table scan. */
4355
4356
int
4357
ha_innobase::rnd_end(void)
4358
/*======================*/
4359
				/* out: 0 or error number */
4360
{
4361
	return(index_end());
4362
}
4363
4364
/*********************************************************************
4365
Reads the next row in a table scan (also used to read the FIRST row
4366
in a table scan). */
4367
4368
int
4369
ha_innobase::rnd_next(
4370
/*==================*/
4371
			/* out: 0, HA_ERR_END_OF_FILE, or error number */
481 by Brian Aker
Remove all of uchar.
4372
	unsigned char*	buf)	/* in/out: returns the row in this buffer,
1 by brian
clean slate
4373
			in MySQL format */
4374
{
4375
	int	error;
4376
4377
	ha_statistic_increment(&SSV::ha_read_rnd_next_count);
4378
4379
	if (start_of_scan) {
4380
		error = index_first(buf);
4381
		if (error == HA_ERR_KEY_NOT_FOUND) {
4382
			error = HA_ERR_END_OF_FILE;
4383
		}
4384
		start_of_scan = 0;
4385
	} else {
4386
		error = general_fetch(buf, ROW_SEL_NEXT, 0);
4387
	}
4388
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4389
	return(error);
1 by brian
clean slate
4390
}
4391
4392
/**************************************************************************
4393
Fetches a row from the table based on a row reference. */
4394
4395
int
4396
ha_innobase::rnd_pos(
4397
/*=================*/
4398
			/* out: 0, HA_ERR_KEY_NOT_FOUND, or error code */
481 by Brian Aker
Remove all of uchar.
4399
	unsigned char*	buf,	/* in/out: buffer for the row */
4400
	unsigned char*	pos)	/* in: primary key value of the row in the
1 by brian
clean slate
4401
			MySQL format, or the row id if the clustered
4402
			index was internally generated by InnoDB; the
4403
			length of data in pos has to be ref_length */
4404
{
4405
	int		error;
4406
4407
	ha_statistic_increment(&SSV::ha_read_rnd_count);
4408
4409
	ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
4410
4411
	/* Note that we assume the length of the row reference is fixed
4412
	for the table, and it is == ref_length */
4413
4414
	error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
4415
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4416
	return(error);
1 by brian
clean slate
4417
}
4418
4419
/*************************************************************************
4420
Stores a reference to the current row to 'ref' field of the handle. Note
4421
that in the case where we have generated the clustered index for the
4422
table, the function parameter is illogical: we MUST ASSUME that 'record'
4423
is the current 'position' of the handle, because if row ref is actually
4424
the row id internally generated in InnoDB, then 'record' does not contain
4425
it. We just guess that the row id must be for the record where the handle
4426
was positioned the last time. */
4427
4428
void
4429
ha_innobase::position(
4430
/*==================*/
481 by Brian Aker
Remove all of uchar.
4431
	const unsigned char*	record)	/* in: row in MySQL format */
1 by brian
clean slate
4432
{
4433
	uint		len;
4434
4435
	ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
4436
4437
        /*if (ds_mrr.call_position_for != this) {
4438
                ((ha_innobase*)ds_mrr.call_position_for)->position(record);
4439
                return;
4440
        }*/
4441
	if (prebuilt->clust_index_was_generated) {
4442
		/* No primary key was defined for the table and we
4443
		generated the clustered index from row id: the
4444
		row reference will be the row id, not any key value
4445
		that MySQL knows of */
4446
4447
		len = DATA_ROW_ID_LEN;
4448
4449
		memcpy(ref, prebuilt->row_id, len);
4450
	} else {
4451
		len = store_key_val_for_row(primary_key, (char*)ref,
4452
							 ref_length, record);
4453
	}
4454
4455
	/* We assume that the 'ref' value len is always fixed for the same
4456
	table. */
4457
4458
	if (len != ref_length) {
4459
	  sql_print_error("Stored ref len is %lu, but table ref len is %lu",
4460
			  (ulong) len, (ulong) ref_length);
4461
	}
4462
}
4463
4464
/*********************************************************************
4465
If it's a DB_TOO_BIG_RECORD error then set a suitable message to
4466
return to the client.*/
4467
inline
4468
void
4469
innodb_check_for_record_too_big_error(
4470
/*==================================*/
4471
	ulint	comp,	/* in: ROW_FORMAT: nonzero=COMPACT, 0=REDUNDANT */
4472
	int	error)	/* in: error code to check */
4473
{
4474
	if (error == (int)DB_TOO_BIG_RECORD) {
4475
		ulint	max_row_size
4476
			= page_get_free_space_of_empty_noninline(comp) / 2;
4477
4478
		my_error(ER_TOO_BIG_ROWSIZE, MYF(0), max_row_size);
4479
	}
4480
}
4481
4482
/*********************************************************************
4483
Creates a table definition to an InnoDB database. */
4484
static
4485
int
4486
create_table_def(
4487
/*=============*/
4488
	trx_t*		trx,		/* in: InnoDB transaction handle */
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
4489
	Table*		form,		/* in: information on table
1 by brian
clean slate
4490
					columns and indexes */
4491
	const char*	table_name,	/* in: table name */
4492
	const char*	path_of_temp_table,/* in: if this is a table explicitly
4493
					created by the user with the
4494
					TEMPORARY keyword, then this
4495
					parameter is the dir path where the
4496
					table should be placed if we create
4497
					an .ibd file for it (no .ibd extension
4498
					in the path, though); otherwise this
4499
					is NULL */
4500
	ulint		flags)		/* in: table flags */
4501
{
4502
	Field*		field;
4503
	dict_table_t*	table;
4504
	ulint		n_cols;
4505
	int		error;
4506
	ulint		col_type;
4507
	ulint		col_len;
4508
	ulint		nulls_allowed;
4509
	ulint		unsigned_type;
4510
	ulint		binary_type;
4511
	ulint		long_true_varchar;
4512
	ulint		charset_no;
4513
	ulint		i;
4514
4515
	n_cols = form->s->fields;
4516
4517
	/* We pass 0 as the space id, and determine at a lower level the space
4518
	id where to store the table */
4519
4520
	table = dict_mem_table_create(table_name, 0, n_cols, flags);
4521
4522
	if (path_of_temp_table) {
4523
		table->dir_path_of_temp_table =
4524
			mem_heap_strdup(table->heap, path_of_temp_table);
4525
	}
4526
4527
	for (i = 0; i < n_cols; i++) {
4528
		field = form->field[i];
4529
4530
		col_type = get_innobase_type_from_mysql_type(&unsigned_type,
4531
									field);
4532
		if (field->null_ptr) {
4533
			nulls_allowed = 0;
4534
		} else {
4535
			nulls_allowed = DATA_NOT_NULL;
4536
		}
4537
4538
		if (field->binary()) {
4539
			binary_type = DATA_BINARY_TYPE;
4540
		} else {
4541
			binary_type = 0;
4542
		}
4543
4544
		charset_no = 0;
4545
4546
		if (dtype_is_string_type(col_type)) {
4547
4548
			charset_no = (ulint)field->charset()->number;
4549
4550
			ut_a(charset_no < 256); /* in data0type.h we assume
4551
						that the number fits in one
4552
						byte */
4553
		}
4554
4555
		ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
4556
					   that this fits in one byte */
4557
		col_len = field->pack_length();
4558
4559
		/* The MySQL pack length contains 1 or 2 bytes length field
4560
		for a true VARCHAR. Let us subtract that, so that the InnoDB
4561
		column length in the InnoDB data dictionary is the real
4562
		maximum byte length of the actual data. */
4563
4564
		long_true_varchar = 0;
4565
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
4566
		if (field->type() == DRIZZLE_TYPE_VARCHAR) {
1 by brian
clean slate
4567
			col_len -= ((Field_varstring*)field)->length_bytes;
4568
4569
			if (((Field_varstring*)field)->length_bytes == 2) {
4570
				long_true_varchar = DATA_LONG_TRUE_VARCHAR;
4571
			}
4572
		}
4573
4574
		dict_mem_table_add_col(table, table->heap,
4575
			(char*) field->field_name,
4576
			col_type,
4577
			dtype_form_prtype(
4578
				(ulint)field->type()
4579
				| nulls_allowed | unsigned_type
4580
				| binary_type | long_true_varchar,
4581
				charset_no),
4582
			col_len);
4583
	}
4584
4585
	error = row_create_table_for_mysql(table, trx);
4586
4587
	innodb_check_for_record_too_big_error(flags & DICT_TF_COMPACT, error);
4588
4589
	error = convert_error_code_to_mysql(error, NULL);
4590
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4591
	return(error);
1 by brian
clean slate
4592
}
4593
4594
/*********************************************************************
4595
Creates an index in an InnoDB database. */
4596
static
4597
int
4598
create_index(
4599
/*=========*/
4600
	trx_t*		trx,		/* in: InnoDB transaction handle */
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
4601
	Table*		form,		/* in: information on table
1 by brian
clean slate
4602
					columns and indexes */
4603
	const char*	table_name,	/* in: table name */
4604
	uint		key_num)	/* in: index number */
4605
{
4606
	Field*		field;
4607
	dict_index_t*	index;
4608
	int		error;
4609
	ulint		n_fields;
4610
	KEY*		key;
4611
	KEY_PART_INFO*	key_part;
4612
	ulint		ind_type;
4613
	ulint		col_type;
4614
	ulint		prefix_len;
4615
	ulint		is_unsigned;
4616
	ulint		i;
4617
	ulint		j;
4618
	ulint*		field_lengths;
4619
4620
	key = form->key_info + key_num;
4621
4622
	n_fields = key->key_parts;
4623
4624
	ind_type = 0;
4625
4626
	if (key_num == form->s->primary_key) {
4627
		ind_type = ind_type | DICT_CLUSTERED;
4628
	}
4629
4630
	if (key->flags & HA_NOSAME ) {
4631
		ind_type = ind_type | DICT_UNIQUE;
4632
	}
4633
4634
	/* We pass 0 as the space id, and determine at a lower level the space
4635
	id where to store the table */
4636
4637
	index = dict_mem_index_create((char*) table_name, key->name, 0,
4638
						ind_type, n_fields);
4639
4640
	field_lengths = (ulint*) my_malloc(sizeof(ulint) * n_fields,
4641
		MYF(MY_FAE));
4642
4643
	for (i = 0; i < n_fields; i++) {
4644
		key_part = key->key_part + i;
4645
4646
		/* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
4647
		field in an index: we only store a specified number of first
4648
		bytes of the column to the index field.) The flag does not
4649
		seem to be properly set by MySQL. Let us fall back on testing
4650
		the length of the key part versus the column. */
4651
4652
		field = NULL;
4653
		for (j = 0; j < form->s->fields; j++) {
4654
4655
			field = form->field[j];
4656
4657
			if (0 == innobase_strcasecmp(
4658
					field->field_name,
4659
					key_part->field->field_name)) {
4660
				/* Found the corresponding column */
4661
4662
				break;
4663
			}
4664
		}
4665
4666
		ut_a(j < form->s->fields);
4667
4668
		col_type = get_innobase_type_from_mysql_type(
4669
					&is_unsigned, key_part->field);
4670
4671
		if (DATA_BLOB == col_type
4672
			|| (key_part->length < field->pack_length()
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
4673
				&& field->type() != DRIZZLE_TYPE_VARCHAR)
4674
			|| (field->type() == DRIZZLE_TYPE_VARCHAR
1 by brian
clean slate
4675
				&& key_part->length < field->pack_length()
4676
				- ((Field_varstring*)field)->length_bytes)) {
4677
4678
			prefix_len = key_part->length;
4679
4680
			if (col_type == DATA_INT
4681
				|| col_type == DATA_FLOAT
4682
				|| col_type == DATA_DOUBLE
4683
				|| col_type == DATA_DECIMAL) {
4684
				sql_print_error(
4685
					"MySQL is trying to create a column "
4686
					"prefix index field, on an "
4687
					"inappropriate data type. Table "
4688
					"name %s, column name %s.",
4689
					table_name,
4690
					key_part->field->field_name);
4691
4692
				prefix_len = 0;
4693
			}
4694
		} else {
4695
			prefix_len = 0;
4696
		}
4697
4698
		field_lengths[i] = key_part->length;
4699
4700
		dict_mem_index_add_field(index,
4701
			(char*) key_part->field->field_name, prefix_len);
4702
	}
4703
4704
	/* Even though we've defined max_supported_key_part_length, we
4705
	still do our own checking using field_lengths to be absolutely
4706
	sure we don't create too long indexes. */
4707
	error = row_create_index_for_mysql(index, trx, field_lengths);
4708
4709
	innodb_check_for_record_too_big_error(form->s->row_type
4710
					      != ROW_TYPE_REDUNDANT, error);
4711
4712
	error = convert_error_code_to_mysql(error, NULL);
4713
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
4714
	free(field_lengths);
1 by brian
clean slate
4715
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4716
	return(error);
1 by brian
clean slate
4717
}
4718
4719
/*********************************************************************
4720
Creates an index to an InnoDB table when the user has defined no
4721
primary index. */
4722
static
4723
int
4724
create_clustered_index_when_no_primary(
4725
/*===================================*/
4726
	trx_t*		trx,		/* in: InnoDB transaction handle */
4727
	ulint		comp,		/* in: ROW_FORMAT:
4728
					nonzero=COMPACT, 0=REDUNDANT */
4729
	const char*	table_name)	/* in: table name */
4730
{
4731
	dict_index_t*	index;
4732
	int		error;
4733
4734
	/* We pass 0 as the space id, and determine at a lower level the space
4735
	id where to store the table */
4736
4737
	index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
4738
				      0, DICT_CLUSTERED, 0);
4739
	error = row_create_index_for_mysql(index, trx, NULL);
4740
4741
	innodb_check_for_record_too_big_error(comp, error);
4742
4743
	error = convert_error_code_to_mysql(error, NULL);
4744
4745
	return(error);
4746
}
4747
4748
/*********************************************************************
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
4749
Update create_info.  Used in SHOW CREATE Table et al. */
1 by brian
clean slate
4750
4751
void
4752
ha_innobase::update_create_info(
4753
/*============================*/
4754
	HA_CREATE_INFO* create_info)	/* in/out: create info */
4755
{
4756
  if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) {
4757
    ha_innobase::info(HA_STATUS_AUTO);
4758
    create_info->auto_increment_value = stats.auto_increment_value;
4759
  }
4760
}
4761
4762
/*********************************************************************
4763
Creates a new table to an InnoDB database. */
4764
4765
int
4766
ha_innobase::create(
4767
/*================*/
4768
					/* out: error number */
4769
	const char*	name,		/* in: table name */
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
4770
	Table*		form,		/* in: information on table
1 by brian
clean slate
4771
					columns and indexes */
4772
	HA_CREATE_INFO*	create_info)	/* in: more information of the
4773
					created table, contains also the
4774
					create statement string */
4775
{
4776
	int		error;
4777
	dict_table_t*	innobase_table;
4778
	trx_t*		parent_trx;
4779
	trx_t*		trx;
4780
	int		primary_key_no;
4781
	uint		i;
4782
	char		name2[FN_REFLEN];
4783
	char		norm_name[FN_REFLEN];
4784
	THD*		thd = ha_thd();
4785
	ib_longlong	auto_inc_value;
4786
	ulint		flags;
4787
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4788
	assert(thd != NULL);
1 by brian
clean slate
4789
4790
	if (form->s->fields > 1000) {
4791
		/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
4792
		but we play safe here */
4793
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4794
		return(HA_ERR_TO_BIG_ROW);
1 by brian
clean slate
4795
	}
4796
4797
	/* Get the transaction associated with the current thd, or create one
4798
	if not yet created */
4799
4800
	parent_trx = check_trx_exists(thd);
4801
4802
	/* In case MySQL calls this in the middle of a SELECT query, release
4803
	possible adaptive hash latch to avoid deadlocks of threads */
4804
4805
	trx_search_latch_release_if_reserved(parent_trx);
4806
4807
	trx = trx_allocate_for_mysql();
4808
4809
	trx->mysql_thd = thd;
4810
	trx->mysql_query_str = thd_query(thd);
4811
4812
	if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
4813
		trx->check_foreigns = FALSE;
4814
	}
4815
4816
	if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
4817
		trx->check_unique_secondary = FALSE;
4818
	}
4819
4820
	if (lower_case_table_names) {
4821
		srv_lower_case_table_names = TRUE;
4822
	} else {
4823
		srv_lower_case_table_names = FALSE;
4824
	}
4825
4826
	strcpy(name2, name);
4827
4828
	normalize_table_name(norm_name, name2);
4829
4830
	/* Latch the InnoDB data dictionary exclusively so that no deadlocks
4831
	or lock waits can happen in it during a table create operation.
4832
	Drop table etc. do this latching in row0mysql.c. */
4833
4834
	row_mysql_lock_data_dictionary(trx);
4835
4836
	/* Create the table definition in InnoDB */
4837
4838
	flags = 0;
4839
4840
	if (form->s->row_type != ROW_TYPE_REDUNDANT) {
4841
		flags |= DICT_TF_COMPACT;
4842
	}
4843
4844
	error = create_table_def(trx, form, norm_name,
4845
		create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
4846
		flags);
4847
4848
	if (error) {
4849
		goto cleanup;
4850
	}
4851
4852
	/* Look for a primary key */
4853
4854
	primary_key_no= (form->s->primary_key != MAX_KEY ?
4855
			 (int) form->s->primary_key :
4856
			 -1);
4857
4858
	/* Our function row_get_mysql_key_number_for_index assumes
4859
	the primary key is always number 0, if it exists */
4860
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4861
	assert(primary_key_no == -1 || primary_key_no == 0);
1 by brian
clean slate
4862
4863
	/* Create the keys */
4864
4865
	if (form->s->keys == 0 || primary_key_no == -1) {
4866
		/* Create an index which is used as the clustered index;
4867
		order the rows by their row id which is internally generated
4868
		by InnoDB */
4869
4870
		error = create_clustered_index_when_no_primary(
4871
			trx, form->s->row_type != ROW_TYPE_REDUNDANT,
4872
			norm_name);
4873
		if (error) {
4874
			goto cleanup;
4875
		}
4876
	}
4877
4878
	if (primary_key_no != -1) {
4879
		/* In InnoDB the clustered index must always be created
4880
		first */
4881
		if ((error = create_index(trx, form, norm_name,
4882
					  (uint) primary_key_no))) {
4883
			goto cleanup;
4884
		}
4885
	}
4886
4887
	for (i = 0; i < form->s->keys; i++) {
4888
4889
		if (i != (uint) primary_key_no) {
4890
4891
			if ((error = create_index(trx, form, norm_name, i))) {
4892
				goto cleanup;
4893
			}
4894
		}
4895
	}
4896
4897
	if (*trx->mysql_query_str) {
4898
		error = row_table_add_foreign_constraints(trx,
4899
			*trx->mysql_query_str, norm_name,
4900
			create_info->options & HA_LEX_CREATE_TMP_TABLE);
4901
4902
		error = convert_error_code_to_mysql(error, NULL);
4903
4904
		if (error) {
4905
			goto cleanup;
4906
		}
4907
	}
4908
4909
	innobase_commit_low(trx);
4910
4911
	row_mysql_unlock_data_dictionary(trx);
4912
4913
	/* Flush the log to reduce probability that the .frm files and
4914
	the InnoDB data dictionary get out-of-sync if the user runs
4915
	with innodb_flush_log_at_trx_commit = 0 */
4916
4917
	log_buffer_flush_to_disk();
4918
4919
	innobase_table = dict_table_get(norm_name, FALSE);
4920
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4921
	assert(innobase_table != 0);
1 by brian
clean slate
4922
4923
	if ((create_info->used_fields & HA_CREATE_USED_AUTO) &&
4924
	   (create_info->auto_increment_value != 0)) {
4925
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
4926
		/* Query was ALTER Table...AUTO_INCREMENT = x; or
4927
		CREATE Table ...AUTO_INCREMENT = x; Find out a table
1 by brian
clean slate
4928
		definition from the dictionary and get the current value
4929
		of the auto increment field. Set a new value to the
4930
		auto increment field if the value is greater than the
4931
		maximum value in the column. */
4932
4933
		auto_inc_value = create_info->auto_increment_value;
4934
4935
		dict_table_autoinc_lock(innobase_table);
4936
		dict_table_autoinc_initialize(innobase_table, auto_inc_value);
4937
		dict_table_autoinc_unlock(innobase_table);
4938
	}
4939
4940
	/* Tell the InnoDB server that there might be work for
4941
	utility threads: */
4942
4943
	srv_active_wake_master_thread();
4944
4945
	trx_free_for_mysql(trx);
4946
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4947
	return(0);
1 by brian
clean slate
4948
4949
cleanup:
4950
	innobase_commit_low(trx);
4951
4952
	row_mysql_unlock_data_dictionary(trx);
4953
4954
	trx_free_for_mysql(trx);
4955
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4956
	return(error);
1 by brian
clean slate
4957
}
4958
4959
/*********************************************************************
4960
Discards or imports an InnoDB tablespace. */
4961
4962
int
4963
ha_innobase::discard_or_import_tablespace(
4964
/*======================================*/
284 by Brian Aker
First pass Innodb my_bool removal.
4965
                                          /* out: 0 == success, -1 == error */
4966
                                          bool discard)	/* in: TRUE if discard, else import */
1 by brian
clean slate
4967
{
4968
	dict_table_t*	dict_table;
4969
	trx_t*		trx;
4970
	int		err;
4971
4972
	ut_a(prebuilt->trx);
4973
	ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
4974
	ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
4975
4976
	dict_table = prebuilt->table;
4977
	trx = prebuilt->trx;
4978
4979
	if (discard) {
4980
		err = row_discard_tablespace_for_mysql(dict_table->name, trx);
4981
	} else {
4982
		err = row_import_tablespace_for_mysql(dict_table->name, trx);
4983
	}
4984
4985
	err = convert_error_code_to_mysql(err, NULL);
4986
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
4987
	return(err);
1 by brian
clean slate
4988
}
4989
4990
/*********************************************************************
4991
Deletes all rows of an InnoDB table. */
4992
4993
int
4994
ha_innobase::delete_all_rows(void)
4995
/*==============================*/
4996
				/* out: error number */
4997
{
4998
	int		error;
4999
5000
	/* Get the transaction associated with the current thd, or create one
5001
	if not yet created, and update prebuilt->trx */
5002
5003
	update_thd(ha_thd());
5004
5005
	if (thd_sql_command(user_thd) != SQLCOM_TRUNCATE) {
5006
	fallback:
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
5007
		/* We only handle TRUNCATE Table t as a special case.
1 by brian
clean slate
5008
		DELETE FROM t will have to use ha_innobase::delete_row(). */
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
5009
		return(my_errno=HA_ERR_WRONG_COMMAND);
1 by brian
clean slate
5010
	}
5011
5012
	/* Truncate the table in InnoDB */
5013
5014
	error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
5015
	if (error == DB_ERROR) {
5016
		/* Cannot truncate; resort to ha_innobase::delete_row() */
5017
		goto fallback;
5018
	}
5019
5020
	error = convert_error_code_to_mysql(error, NULL);
5021
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
5022
	return(error);
1 by brian
clean slate
5023
}
5024
5025
/*********************************************************************
5026
Drops a table from an InnoDB database. Before calling this function,
5027
MySQL calls innobase_commit to commit the transaction of the current user.
5028
Then the current user cannot have locks set on the table. Drop table
5029
operation inside InnoDB will remove all locks any user has on the table
5030
inside InnoDB. */
5031
5032
int
5033
ha_innobase::delete_table(
5034
/*======================*/
5035
				/* out: error number */
5036
	const char*	name)	/* in: table name */
5037
{
5038
	ulint	name_len;
5039
	int	error;
5040
	trx_t*	parent_trx;
5041
	trx_t*	trx;
5042
	THD	*thd = ha_thd();
5043
	char	norm_name[1000];
5044
5045
	/* Get the transaction associated with the current thd, or create one
5046
	if not yet created */
5047
5048
	parent_trx = check_trx_exists(thd);
5049
5050
	/* In case MySQL calls this in the middle of a SELECT query, release
5051
	possible adaptive hash latch to avoid deadlocks of threads */
5052
5053
	trx_search_latch_release_if_reserved(parent_trx);
5054
5055
	if (lower_case_table_names) {
5056
		srv_lower_case_table_names = TRUE;
5057
	} else {
5058
		srv_lower_case_table_names = FALSE;
5059
	}
5060
5061
	trx = trx_allocate_for_mysql();
5062
5063
	trx->mysql_thd = thd;
5064
	trx->mysql_query_str = thd_query(thd);
5065
5066
	if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
5067
		trx->check_foreigns = FALSE;
5068
	}
5069
5070
	if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
5071
		trx->check_unique_secondary = FALSE;
5072
	}
5073
5074
	name_len = strlen(name);
5075
5076
	assert(name_len < 1000);
5077
5078
	/* Strangely, MySQL passes the table name without the '.frm'
5079
	extension, in contrast to ::create */
5080
5081
	normalize_table_name(norm_name, name);
5082
5083
	/* Drop the table in InnoDB */
5084
5085
	error = row_drop_table_for_mysql(norm_name, trx,
5086
					 thd_sql_command(thd)
5087
					 == SQLCOM_DROP_DB);
5088
5089
	/* Flush the log to reduce probability that the .frm files and
5090
	the InnoDB data dictionary get out-of-sync if the user runs
5091
	with innodb_flush_log_at_trx_commit = 0 */
5092
5093
	log_buffer_flush_to_disk();
5094
5095
	/* Tell the InnoDB server that there might be work for
5096
	utility threads: */
5097
5098
	srv_active_wake_master_thread();
5099
5100
	innobase_commit_low(trx);
5101
5102
	trx_free_for_mysql(trx);
5103
5104
	error = convert_error_code_to_mysql(error, NULL);
5105
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
5106
	return(error);
1 by brian
clean slate
5107
}
5108
5109
/*********************************************************************
5110
Removes all tables in the named database inside InnoDB. */
5111
static
5112
void
5113
innobase_drop_database(
5114
/*===================*/
5115
			/* out: error number */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
5116
        handlerton *hton __attribute__((unused)), /* in: handlerton of Innodb */
1 by brian
clean slate
5117
	char*	path)	/* in: database path; inside InnoDB the name
5118
			of the last directory in the path is used as
5119
			the database name: for example, in 'mysql/data/test'
5120
			the database name is 'test' */
5121
{
5122
	ulint	len		= 0;
5123
	trx_t*	parent_trx;
5124
	trx_t*	trx;
5125
	char*	ptr;
5126
	int	error;
5127
	char*	namebuf;
5128
	THD*	thd		= current_thd;
5129
5130
	/* Get the transaction associated with the current thd, or create one
5131
	if not yet created */
5132
5133
	parent_trx = check_trx_exists(thd);
5134
5135
	/* In case MySQL calls this in the middle of a SELECT query, release
5136
	possible adaptive hash latch to avoid deadlocks of threads */
5137
5138
	trx_search_latch_release_if_reserved(parent_trx);
5139
376 by Brian Aker
strend remove
5140
	ptr = strchr(path, '\0') - 2;
1 by brian
clean slate
5141
5142
	while (ptr >= path && *ptr != '\\' && *ptr != '/') {
5143
		ptr--;
5144
		len++;
5145
	}
5146
5147
	ptr++;
5148
	namebuf = (char*) my_malloc((uint) len + 2, MYF(0));
5149
5150
	memcpy(namebuf, ptr, len);
5151
	namebuf[len] = '/';
5152
	namebuf[len + 1] = '\0';
5153
#ifdef	__WIN__
5154
	innobase_casedn_str(namebuf);
5155
#endif
5156
	trx = trx_allocate_for_mysql();
5157
	trx->mysql_thd = thd;
5158
	trx->mysql_query_str = thd_query(thd);
5159
5160
	if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
5161
		trx->check_foreigns = FALSE;
5162
	}
5163
5164
	error = row_drop_database_for_mysql(namebuf, trx);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
5165
	free(namebuf);
1 by brian
clean slate
5166
5167
	/* Flush the log to reduce probability that the .frm files and
5168
	the InnoDB data dictionary get out-of-sync if the user runs
5169
	with innodb_flush_log_at_trx_commit = 0 */
5170
5171
	log_buffer_flush_to_disk();
5172
5173
	/* Tell the InnoDB server that there might be work for
5174
	utility threads: */
5175
5176
	srv_active_wake_master_thread();
5177
5178
	innobase_commit_low(trx);
5179
	trx_free_for_mysql(trx);
5180
#ifdef NO_LONGER_INTERESTED_IN_DROP_DB_ERROR
5181
	error = convert_error_code_to_mysql(error, NULL);
5182
5183
	return(error);
5184
#else
5185
	return;
5186
#endif
5187
}
5188
5189
/*************************************************************************
5190
Renames an InnoDB table. */
5191
5192
int
5193
ha_innobase::rename_table(
5194
/*======================*/
5195
				/* out: 0 or error code */
5196
	const char*	from,	/* in: old name of the table */
5197
	const char*	to)	/* in: new name of the table */
5198
{
5199
	ulint	name_len1;
5200
	ulint	name_len2;
5201
	int	error;
5202
	trx_t*	parent_trx;
5203
	trx_t*	trx;
5204
	char	norm_from[1000];
5205
	char	norm_to[1000];
5206
	THD*	thd		= ha_thd();
5207
5208
	/* Get the transaction associated with the current thd, or create one
5209
	if not yet created */
5210
5211
	parent_trx = check_trx_exists(thd);
5212
5213
	/* In case MySQL calls this in the middle of a SELECT query, release
5214
	possible adaptive hash latch to avoid deadlocks of threads */
5215
5216
	trx_search_latch_release_if_reserved(parent_trx);
5217
5218
	if (lower_case_table_names) {
5219
		srv_lower_case_table_names = TRUE;
5220
	} else {
5221
		srv_lower_case_table_names = FALSE;
5222
	}
5223
5224
	trx = trx_allocate_for_mysql();
5225
	trx->mysql_thd = thd;
5226
	trx->mysql_query_str = thd_query(thd);
5227
5228
	if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
5229
		trx->check_foreigns = FALSE;
5230
	}
5231
5232
	name_len1 = strlen(from);
5233
	name_len2 = strlen(to);
5234
5235
	assert(name_len1 < 1000);
5236
	assert(name_len2 < 1000);
5237
5238
	normalize_table_name(norm_from, from);
5239
	normalize_table_name(norm_to, to);
5240
5241
	/* Rename the table in InnoDB */
5242
5243
	error = row_rename_table_for_mysql(norm_from, norm_to, trx);
5244
5245
	/* Flush the log to reduce probability that the .frm files and
5246
	the InnoDB data dictionary get out-of-sync if the user runs
5247
	with innodb_flush_log_at_trx_commit = 0 */
5248
5249
	log_buffer_flush_to_disk();
5250
5251
	/* Tell the InnoDB server that there might be work for
5252
	utility threads: */
5253
5254
	srv_active_wake_master_thread();
5255
5256
	innobase_commit_low(trx);
5257
	trx_free_for_mysql(trx);
5258
5259
	error = convert_error_code_to_mysql(error, NULL);
5260
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
5261
	return(error);
1 by brian
clean slate
5262
}
5263
5264
/*************************************************************************
5265
Estimates the number of index records in a range. */
5266
5267
ha_rows
5268
ha_innobase::records_in_range(
5269
/*==========================*/
5270
						/* out: estimated number of
5271
						rows */
5272
	uint			keynr,		/* in: index number */
5273
	key_range		*min_key,	/* in: start key value of the
5274
						   range, may also be 0 */
5275
	key_range		*max_key)	/* in: range end key val, may
5276
						   also be 0 */
5277
{
5278
	KEY*		key;
5279
	dict_index_t*	index;
481 by Brian Aker
Remove all of uchar.
5280
	unsigned char*		key_val_buff2	= (unsigned char*) my_malloc(
1 by brian
clean slate
5281
						  table->s->reclength
5282
					+ table->s->max_key_length + 100,
5283
								MYF(MY_FAE));
5284
	ulint		buff2_len = table->s->reclength
5285
					+ table->s->max_key_length + 100;
5286
	dtuple_t*	range_start;
5287
	dtuple_t*	range_end;
5288
	ib_longlong	n_rows;
5289
	ulint		mode1;
5290
	ulint		mode2;
5291
	void*		heap1;
5292
	void*		heap2;
5293
5294
	ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
5295
5296
	prebuilt->trx->op_info = (char*)"estimating records in index range";
5297
5298
	/* In case MySQL calls this in the middle of a SELECT query, release
5299
	possible adaptive hash latch to avoid deadlocks of threads */
5300
5301
	trx_search_latch_release_if_reserved(prebuilt->trx);
5302
5303
	active_index = keynr;
5304
5305
	key = table->key_info + active_index;
5306
5307
	index = dict_table_get_index_noninline(prebuilt->table, key->name);
5308
5309
	range_start = dtuple_create_for_mysql(&heap1, key->key_parts);
5310
	dict_index_copy_types(range_start, index, key->key_parts);
5311
5312
	range_end = dtuple_create_for_mysql(&heap2, key->key_parts);
5313
	dict_index_copy_types(range_end, index, key->key_parts);
5314
5315
	row_sel_convert_mysql_key_to_innobase(
5316
				range_start, (byte*) key_val_buff,
5317
				(ulint)upd_and_key_val_buff_len,
5318
				index,
5319
				(byte*) (min_key ? min_key->key :
481 by Brian Aker
Remove all of uchar.
5320
					 (const unsigned char*) 0),
1 by brian
clean slate
5321
				(ulint) (min_key ? min_key->length : 0),
5322
				prebuilt->trx);
5323
5324
	row_sel_convert_mysql_key_to_innobase(
5325
				range_end, (byte*) key_val_buff2,
5326
				buff2_len, index,
5327
				(byte*) (max_key ? max_key->key :
481 by Brian Aker
Remove all of uchar.
5328
					 (const unsigned char*) 0),
1 by brian
clean slate
5329
				(ulint) (max_key ? max_key->length : 0),
5330
				prebuilt->trx);
5331
5332
	mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
5333
						HA_READ_KEY_EXACT);
5334
	mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
5335
						HA_READ_KEY_EXACT);
5336
5337
	if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
5338
5339
		n_rows = btr_estimate_n_rows_in_range(index, range_start,
5340
						      mode1, range_end,
5341
						      mode2);
5342
	} else {
5343
5344
		n_rows = 0;
5345
	}
5346
5347
	dtuple_free_for_mysql(heap1);
5348
	dtuple_free_for_mysql(heap2);
5349
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
5350
	free(key_val_buff2);
1 by brian
clean slate
5351
5352
	prebuilt->trx->op_info = (char*)"";
5353
5354
	/* The MySQL optimizer seems to believe an estimate of 0 rows is
5355
	always accurate and may return the result 'Empty set' based on that.
5356
	The accuracy is not guaranteed, and even if it were, for a locking
5357
	read we should anyway perform the search to set the next-key lock.
5358
	Add 1 to the value to make sure MySQL does not make the assumption! */
5359
5360
	if (n_rows == 0) {
5361
		n_rows = 1;
5362
	}
5363
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
5364
	return((ha_rows) n_rows);
1 by brian
clean slate
5365
}
5366
5367
/*************************************************************************
5368
Gives an UPPER BOUND to the number of rows in a table. This is used in
5369
filesort.cc. */
5370
5371
ha_rows
5372
ha_innobase::estimate_rows_upper_bound(void)
5373
/*======================================*/
5374
			/* out: upper bound of rows */
5375
{
5376
	dict_index_t*	index;
151 by Brian Aker
Ulonglong to uint64_t
5377
	uint64_t	estimate;
5378
	uint64_t	local_data_file_length;
1 by brian
clean slate
5379
5380
	/* We do not know if MySQL can call this function before calling
5381
	external_lock(). To be safe, update the thd of the current table
5382
	handle. */
5383
5384
	update_thd(ha_thd());
5385
5386
	prebuilt->trx->op_info = (char*)
5387
				 "calculating upper bound for table rows";
5388
5389
	/* In case MySQL calls this in the middle of a SELECT query, release
5390
	possible adaptive hash latch to avoid deadlocks of threads */
5391
5392
	trx_search_latch_release_if_reserved(prebuilt->trx);
5393
5394
	index = dict_table_get_first_index_noninline(prebuilt->table);
5395
151 by Brian Aker
Ulonglong to uint64_t
5396
	local_data_file_length = ((uint64_t) index->stat_n_leaf_pages)
1 by brian
clean slate
5397
							* UNIV_PAGE_SIZE;
5398
5399
	/* Calculate a minimum length for a clustered index record and from
5400
	that an upper bound for the number of rows. Since we only calculate
5401
	new statistics in row0mysql.c when a table has grown by a threshold
5402
	factor, we must add a safety factor 2 in front of the formula below. */
5403
5404
	estimate = 2 * local_data_file_length /
5405
					 dict_index_calc_min_rec_len(index);
5406
5407
	prebuilt->trx->op_info = (char*)"";
5408
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
5409
	return((ha_rows) estimate);
1 by brian
clean slate
5410
}
5411
5412
/*************************************************************************
5413
How many seeks it will take to read through the table. This is to be
5414
comparable to the number returned by records_in_range so that we can
5415
decide if we should scan the table or use keys. */
5416
5417
double
5418
ha_innobase::scan_time()
5419
/*====================*/
5420
			/* out: estimated time measured in disk seeks */
5421
{
5422
	/* Since MySQL seems to favor table scans too much over index
5423
	searches, we pretend that a sequential read takes the same time
5424
	as a random disk read, that is, we do not divide the following
5425
	by 10, which would be physically realistic. */
5426
5427
	return((double) (prebuilt->table->stat_clustered_index_size));
5428
}
5429
5430
/**********************************************************************
5431
Calculate the time it takes to read a set of ranges through an index
5432
This enables us to optimise reads for clustered indexes. */
5433
5434
double
5435
ha_innobase::read_time(
5436
/*===================*/
5437
			/* out: estimated time measured in disk seeks */
5438
	uint	index,	/* in: key number */
5439
	uint	ranges,	/* in: how many ranges */
5440
	ha_rows rows)	/* in: estimated number of rows in the ranges */
5441
{
5442
	ha_rows total_rows;
5443
	double	time_for_scan;
5444
5445
	if (index != table->s->primary_key) {
5446
		/* Not clustered */
5447
		return(handler::read_time(index, ranges, rows));
5448
	}
5449
5450
	if (rows <= 2) {
5451
5452
		return((double) rows);
5453
	}
5454
5455
	/* Assume that the read time is proportional to the scan time for all
5456
	rows + at most one seek per range. */
5457
5458
	time_for_scan = scan_time();
5459
5460
	if ((total_rows = estimate_rows_upper_bound()) < rows) {
5461
5462
		return(time_for_scan);
5463
	}
5464
5465
	return(ranges + (double) rows / (double) total_rows * time_for_scan);
5466
}
5467
5468
/*************************************************************************
5469
Returns statistics information of the table to the MySQL interpreter,
5470
in various fields of the handle object. */
5471
5472
int
5473
ha_innobase::info(
5474
/*==============*/
482 by Brian Aker
Remove uint.
5475
	uint32_t flag)	/* in: what information MySQL requests */
1 by brian
clean slate
5476
{
5477
	dict_table_t*	ib_table;
5478
	dict_index_t*	index;
5479
	ha_rows		rec_per_key;
5480
	ib_longlong	n_rows;
5481
	ulong		j;
5482
	ulong		i;
5483
	char		path[FN_REFLEN];
5484
	os_file_stat_t	stat_info;
5485
5486
	/* If we are forcing recovery at a high level, we will suppress
5487
	statistics calculation on tables, because that may crash the
5488
	server if an index is badly corrupted. */
5489
5490
	if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
5491
5492
		/* We return success (0) instead of HA_ERR_CRASHED,
5493
		because we want MySQL to process this query and not
5494
		stop, like it would do if it received the error code
5495
		HA_ERR_CRASHED. */
5496
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
5497
		return(0);
1 by brian
clean slate
5498
	}
5499
5500
	/* We do not know if MySQL can call this function before calling
5501
	external_lock(). To be safe, update the thd of the current table
5502
	handle. */
5503
5504
	update_thd(ha_thd());
5505
5506
	/* In case MySQL calls this in the middle of a SELECT query, release
5507
	possible adaptive hash latch to avoid deadlocks of threads */
5508
5509
	prebuilt->trx->op_info = (char*)"returning various info to MySQL";
5510
5511
	trx_search_latch_release_if_reserved(prebuilt->trx);
5512
5513
	ib_table = prebuilt->table;
5514
5515
	if (flag & HA_STATUS_TIME) {
5516
		if (srv_stats_on_metadata) {
5517
			/* In sql_show we call with this flag: update
5518
			then statistics so that they are up-to-date */
5519
5520
			prebuilt->trx->op_info = "updating table statistics";
5521
5522
			dict_update_statistics(ib_table);
5523
5524
			prebuilt->trx->op_info = "returning various info to MySQL";
5525
		}
5526
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
5527
		snprintf(path, sizeof(path), "%s/%s%s",
5528
		         mysql_data_home, ib_table->name, reg_ext);
1 by brian
clean slate
5529
5530
		unpack_filename(path,path);
5531
5532
		/* Note that we do not know the access time of the table,
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
5533
		nor the CHECK Table time, nor the UPDATE or INSERT time. */
1 by brian
clean slate
5534
5535
		if (os_file_get_status(path,&stat_info)) {
5536
			stats.create_time = stat_info.ctime;
5537
		}
5538
	}
5539
5540
	if (flag & HA_STATUS_VARIABLE) {
5541
		n_rows = ib_table->stat_n_rows;
5542
5543
		/* Because we do not protect stat_n_rows by any mutex in a
5544
		delete, it is theoretically possible that the value can be
5545
		smaller than zero! TODO: fix this race.
5546
5547
		The MySQL optimizer seems to assume in a left join that n_rows
5548
		is an accurate estimate if it is zero. Of course, it is not,
5549
		since we do not have any locks on the rows yet at this phase.
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
5550
		Since SHOW Table STATUS seems to call this function with the
1 by brian
clean slate
5551
		HA_STATUS_TIME flag set, while the left join optimizer does not
5552
		set that flag, we add one to a zero value if the flag is not
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
5553
		set. That way SHOW Table STATUS will show the best estimate,
1 by brian
clean slate
5554
		while the optimizer never sees the table empty. */
5555
5556
		if (n_rows < 0) {
5557
			n_rows = 0;
5558
		}
5559
5560
		if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
5561
			n_rows++;
5562
		}
5563
5564
		stats.records = (ha_rows)n_rows;
5565
		stats.deleted = 0;
151 by Brian Aker
Ulonglong to uint64_t
5566
		stats.data_file_length = ((uint64_t)
1 by brian
clean slate
5567
				ib_table->stat_clustered_index_size)
5568
					* UNIV_PAGE_SIZE;
151 by Brian Aker
Ulonglong to uint64_t
5569
		stats.index_file_length = ((uint64_t)
1 by brian
clean slate
5570
				ib_table->stat_sum_of_other_index_sizes)
5571
					* UNIV_PAGE_SIZE;
5572
		stats.delete_length = 0;
5573
		stats.check_time = 0;
5574
5575
		if (stats.records == 0) {
5576
			stats.mean_rec_length = 0;
5577
		} else {
5578
			stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
5579
		}
5580
	}
5581
5582
	if (flag & HA_STATUS_CONST) {
5583
		index = dict_table_get_first_index_noninline(ib_table);
5584
5585
		if (prebuilt->clust_index_was_generated) {
5586
			index = dict_table_get_next_index_noninline(index);
5587
		}
5588
5589
		for (i = 0; i < table->s->keys; i++) {
5590
			if (index == NULL) {
5591
				sql_print_error("Table %s contains fewer "
5592
						"indexes inside InnoDB than "
5593
						"are defined in the MySQL "
5594
						".frm file. Have you mixed up "
5595
						".frm files from different "
5596
						"installations? See "
5597
"http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n",
5598
5599
						ib_table->name);
5600
				break;
5601
			}
5602
5603
			for (j = 0; j < table->key_info[i].key_parts; j++) {
5604
5605
				if (j + 1 > index->n_uniq) {
5606
					sql_print_error(
5607
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
5608
"statistics for %lu columns. Have you mixed up .frm files from different "
5609
"installations? "
5610
"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n",
5611
							index->name,
5612
							ib_table->name,
5613
							(unsigned long)
5614
							index->n_uniq, j + 1);
5615
					break;
5616
				}
5617
5618
				if (index->stat_n_diff_key_vals[j + 1] == 0) {
5619
5620
					rec_per_key = stats.records;
5621
				} else {
5622
					rec_per_key = (ha_rows)(stats.records /
5623
					 index->stat_n_diff_key_vals[j + 1]);
5624
				}
5625
5626
				/* Since MySQL seems to favor table scans
5627
				too much over index searches, we pretend
5628
				index selectivity is 2 times better than
5629
				our estimate: */
5630
5631
				rec_per_key = rec_per_key / 2;
5632
5633
				if (rec_per_key == 0) {
5634
					rec_per_key = 1;
5635
				}
5636
5637
				table->key_info[i].rec_per_key[j]=
5638
				  rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
5639
				  (ulong) rec_per_key;
5640
			}
5641
5642
			index = dict_table_get_next_index_noninline(index);
5643
		}
5644
	}
5645
5646
	if (flag & HA_STATUS_ERRKEY) {
5647
		ut_a(prebuilt->trx);
5648
		ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
5649
5650
		errkey = (unsigned int) row_get_mysql_key_number_for_index(
5651
			(dict_index_t*) trx_get_error_info(prebuilt->trx));
5652
	}
5653
5654
	if (flag & HA_STATUS_AUTO && table->found_next_number_field) {
152 by Brian Aker
longlong replacement
5655
		int64_t	auto_inc;
1 by brian
clean slate
5656
		int		ret;
5657
5658
		/* The following function call can the first time fail in
5659
		a lock wait timeout error because it reserves the auto-inc
5660
		lock on the table. If it fails, then someone is already initing
5661
		the auto-inc counter, and the second call is guaranteed to
5662
		succeed. */
5663
5664
		ret = innobase_read_and_init_auto_inc(&auto_inc);
5665
5666
		if (ret != 0) {
5667
			ret = innobase_read_and_init_auto_inc(&auto_inc);
5668
5669
			if (ret != 0) {
5670
				sql_print_error("Cannot get table %s auto-inc"
5671
						"counter value in ::info\n",
5672
						ib_table->name);
5673
				auto_inc = 0;
5674
			}
5675
		}
5676
5677
		stats.auto_increment_value = auto_inc;
5678
	}
5679
5680
	prebuilt->trx->op_info = (char*)"";
5681
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
5682
  	return(0);
1 by brian
clean slate
5683
}
5684
5685
/**************************************************************************
5686
Updates index cardinalities of the table, based on 8 random dives into
5687
each index tree. This does NOT calculate exact statistics on the table. */
5688
5689
int
5690
ha_innobase::analyze(
5691
/*=================*/
5692
					/* out: returns always 0 (success) */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
5693
	THD*		thd __attribute__((unused)),		/* in: connection thread handle */
5694
	HA_CHECK_OPT*	check_opt __attribute__((unused)))	/* in: currently ignored */
1 by brian
clean slate
5695
{
5696
	/* Simply call ::info() with all the flags */
5697
	info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
5698
5699
	return(0);
5700
}
5701
5702
/**************************************************************************
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
5703
This is mapped to "ALTER Table tablename ENGINE=InnoDB", which rebuilds
1 by brian
clean slate
5704
the table in MySQL. */
5705
5706
int
5707
ha_innobase::optimize(
5708
/*==================*/
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
5709
	THD*		thd __attribute__((unused)),		/* in: connection thread handle */
5710
	HA_CHECK_OPT*	check_opt __attribute__((unused)))	/* in: currently ignored */
1 by brian
clean slate
5711
{
5712
	return(HA_ADMIN_TRY_ALTER);
5713
}
5714
5715
/***********************************************************************
5716
Tries to check that an InnoDB table is not corrupted. If corruption is
5717
noticed, prints to stderr information about it. In case of corruption
5718
may also assert a failure and crash the server. */
5719
5720
int
5721
ha_innobase::check(
5722
/*===============*/
5723
					/* out: HA_ADMIN_CORRUPT or
5724
					HA_ADMIN_OK */
5725
	THD*		thd,		/* in: user thread handle */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
5726
	HA_CHECK_OPT*	check_opt __attribute__((unused)))	/* in: check options, currently
1 by brian
clean slate
5727
					ignored */
5728
{
5729
	ulint		ret;
5730
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
5731
	assert(thd == ha_thd());
1 by brian
clean slate
5732
	ut_a(prebuilt->trx);
5733
	ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
5734
	ut_a(prebuilt->trx == thd_to_trx(thd));
5735
5736
	if (prebuilt->mysql_template == NULL) {
5737
		/* Build the template; we will use a dummy template
5738
		in index scans done in checking */
5739
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
5740
		build_template(prebuilt, NULL, table, this, ROW_DRIZZLE_WHOLE_ROW);
1 by brian
clean slate
5741
	}
5742
5743
	ret = row_check_table_for_mysql(prebuilt);
5744
5745
	if (ret == DB_SUCCESS) {
5746
		return(HA_ADMIN_OK);
5747
	}
5748
5749
	return(HA_ADMIN_CORRUPT);
5750
}
5751
5752
/*****************************************************************
5753
Adds information about free space in the InnoDB tablespace to a table comment
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
5754
which is printed out when a user calls SHOW Table STATUS. Adds also info on
1 by brian
clean slate
5755
foreign keys. */
5756
5757
char*
5758
ha_innobase::update_table_comment(
5759
/*==============================*/
5760
				/* out: table comment + InnoDB free space +
5761
				info on foreign keys */
5762
	const char*	comment)/* in: table comment defined by user */
5763
{
5764
	uint	length = (uint) strlen(comment);
5765
	char*	str;
5766
	long	flen;
5767
5768
	/* We do not know if MySQL can call this function before calling
5769
	external_lock(). To be safe, update the thd of the current table
5770
	handle. */
5771
5772
	if (length > 64000 - 3) {
5773
		return((char*)comment); /* string too long */
5774
	}
5775
5776
	update_thd(ha_thd());
5777
5778
	prebuilt->trx->op_info = (char*)"returning table comment";
5779
5780
	/* In case MySQL calls this in the middle of a SELECT query, release
5781
	possible adaptive hash latch to avoid deadlocks of threads */
5782
5783
	trx_search_latch_release_if_reserved(prebuilt->trx);
5784
	str = NULL;
5785
5786
	/* output the data to a temporary file */
5787
5788
	mutex_enter_noninline(&srv_dict_tmpfile_mutex);
5789
	rewind(srv_dict_tmpfile);
5790
77.1.103 by Monty Taylor
Fixed some format strings to use PRIu64 for the uint64_t types.
5791
	fprintf(srv_dict_tmpfile, "InnoDB free: %"PRIu64" kB",
1 by brian
clean slate
5792
		fsp_get_available_space_in_free_extents(
5793
			prebuilt->table->space));
5794
5795
	dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
5796
				prebuilt->trx, prebuilt->table);
5797
	flen = ftell(srv_dict_tmpfile);
5798
	if (flen < 0) {
5799
		flen = 0;
5800
	} else if (length + flen + 3 > 64000) {
5801
		flen = 64000 - 3 - length;
5802
	}
5803
5804
	/* allocate buffer for the full string, and
5805
	read the contents of the temporary file */
5806
5807
	str = (char*) my_malloc(length + flen + 3, MYF(0));
5808
5809
	if (str) {
5810
		char* pos	= str + length;
5811
		if (length) {
5812
			memcpy(str, comment, length);
5813
			*pos++ = ';';
5814
			*pos++ = ' ';
5815
		}
5816
		rewind(srv_dict_tmpfile);
5817
		flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
5818
		pos[flen] = 0;
5819
	}
5820
5821
	mutex_exit_noninline(&srv_dict_tmpfile_mutex);
5822
5823
	prebuilt->trx->op_info = (char*)"";
5824
5825
	return(str ? str : (char*) comment);
5826
}
5827
5828
/***********************************************************************
5829
Gets the foreign key create info for a table stored in InnoDB. */
5830
5831
char*
5832
ha_innobase::get_foreign_key_create_info(void)
5833
/*==========================================*/
5834
			/* out, own: character string in the form which
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
5835
			can be inserted to the CREATE Table statement,
1 by brian
clean slate
5836
			MUST be freed with ::free_foreign_key_create_info */
5837
{
5838
	char*	str	= 0;
5839
	long	flen;
5840
5841
	ut_a(prebuilt != NULL);
5842
5843
	/* We do not know if MySQL can call this function before calling
5844
	external_lock(). To be safe, update the thd of the current table
5845
	handle. */
5846
5847
	update_thd(ha_thd());
5848
5849
	prebuilt->trx->op_info = (char*)"getting info on foreign keys";
5850
5851
	/* In case MySQL calls this in the middle of a SELECT query,
5852
	release possible adaptive hash latch to avoid
5853
	deadlocks of threads */
5854
5855
	trx_search_latch_release_if_reserved(prebuilt->trx);
5856
5857
	mutex_enter_noninline(&srv_dict_tmpfile_mutex);
5858
	rewind(srv_dict_tmpfile);
5859
5860
	/* output the data to a temporary file */
5861
	dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
5862
				prebuilt->trx, prebuilt->table);
5863
	prebuilt->trx->op_info = (char*)"";
5864
5865
	flen = ftell(srv_dict_tmpfile);
5866
	if (flen < 0) {
5867
		flen = 0;
5868
	} else if (flen > 64000 - 1) {
5869
		flen = 64000 - 1;
5870
	}
5871
5872
	/* allocate buffer for the string, and
5873
	read the contents of the temporary file */
5874
5875
	str = (char*) my_malloc(flen + 1, MYF(0));
5876
5877
	if (str) {
5878
		rewind(srv_dict_tmpfile);
5879
		flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
5880
		str[flen] = 0;
5881
	}
5882
5883
	mutex_exit_noninline(&srv_dict_tmpfile_mutex);
5884
5885
	return(str);
5886
}
5887
5888
5889
int
5890
ha_innobase::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
5891
{
5892
  dict_foreign_t* foreign;
5893
5894
  ut_a(prebuilt != NULL);
5895
  update_thd(ha_thd());
5896
  prebuilt->trx->op_info = (char*)"getting list of foreign keys";
5897
  trx_search_latch_release_if_reserved(prebuilt->trx);
5898
  mutex_enter_noninline(&(dict_sys->mutex));
5899
  foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
5900
5901
  while (foreign != NULL) {
482 by Brian Aker
Remove uint.
5902
	  uint32_t i;
1 by brian
clean slate
5903
	  FOREIGN_KEY_INFO f_key_info;
5904
	  LEX_STRING *name= 0;
482 by Brian Aker
Remove uint.
5905
          uint32_t ulen;
1 by brian
clean slate
5906
          char uname[NAME_LEN+1];           /* Unencoded name */
5907
          char db_name[NAME_LEN+1];
5908
	  const char *tmp_buff;
5909
5910
	  tmp_buff= foreign->id;
5911
	  i= 0;
5912
	  while (tmp_buff[i] != '/')
5913
		  i++;
5914
	  tmp_buff+= i + 1;
5915
	  f_key_info.forein_id = thd_make_lex_string(thd, 0,
5916
		  tmp_buff, (uint) strlen(tmp_buff), 1);
5917
	  tmp_buff= foreign->referenced_table_name;
5918
5919
          /* Database name */
5920
	  i= 0;
5921
	  while (tmp_buff[i] != '/')
5922
          {
5923
            db_name[i]= tmp_buff[i];
5924
            i++;
5925
          }
5926
          db_name[i]= 0;
5927
          ulen= filename_to_tablename(db_name, uname, sizeof(uname));
5928
	  f_key_info.referenced_db = thd_make_lex_string(thd, 0,
5929
		  uname, ulen, 1);
5930
5931
          /* Table name */
5932
	  tmp_buff+= i + 1;
5933
          ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
5934
	  f_key_info.referenced_table = thd_make_lex_string(thd, 0,
5935
		  uname, ulen, 1);
5936
5937
	  for (i= 0;;) {
5938
		  tmp_buff= foreign->foreign_col_names[i];
5939
		  name = thd_make_lex_string(thd, name,
5940
			  tmp_buff, (uint) strlen(tmp_buff), 1);
5941
		  f_key_info.foreign_fields.push_back(name);
5942
		  tmp_buff= foreign->referenced_col_names[i];
5943
		  name = thd_make_lex_string(thd, name,
5944
			tmp_buff, (uint) strlen(tmp_buff), 1);
5945
		  f_key_info.referenced_fields.push_back(name);
5946
		  if (++i >= foreign->n_fields)
5947
			  break;
5948
	  }
5949
5950
          ulong length;
5951
          if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
5952
          {
5953
            length=7;
5954
            tmp_buff= "CASCADE";
5955
          }	
5956
          else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
5957
          {
5958
            length=8;
5959
            tmp_buff= "SET NULL";
5960
          }
5961
          else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
5962
          {
5963
            length=9;
5964
            tmp_buff= "NO ACTION";
5965
          }
5966
          else
5967
          {
5968
            length=8;
5969
            tmp_buff= "RESTRICT";
5970
          }
5971
	  f_key_info.delete_method = thd_make_lex_string(
5972
		  thd, f_key_info.delete_method, tmp_buff, length, 1);
5973
 
5974
 
5975
          if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
5976
          {
5977
            length=7;
5978
            tmp_buff= "CASCADE";
5979
          }
5980
          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
5981
          {
5982
            length=8;
5983
            tmp_buff= "SET NULL";
5984
          }
5985
          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
5986
          {
5987
            length=9;
5988
            tmp_buff= "NO ACTION";
5989
          }
5990
          else
5991
          {
5992
            length=8;
5993
            tmp_buff= "RESTRICT";
5994
          }
5995
	  f_key_info.update_method = thd_make_lex_string(
5996
		  thd, f_key_info.update_method, tmp_buff, length, 1);
5997
          if (foreign->referenced_index &&
5998
              foreign->referenced_index->name)
5999
          {
6000
	    f_key_info.referenced_key_name = thd_make_lex_string(
6001
		    thd, f_key_info.referenced_key_name,
6002
		    foreign->referenced_index->name,
6003
		    strlen(foreign->referenced_index->name), 1);
6004
          }
6005
          else
6006
            f_key_info.referenced_key_name= 0;
6007
6008
	  FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *)
6009
		  thd_memdup(thd, &f_key_info, sizeof(FOREIGN_KEY_INFO));
6010
	  f_key_list->push_back(pf_key_info);
6011
	  foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
6012
  }
6013
  mutex_exit_noninline(&(dict_sys->mutex));
6014
  prebuilt->trx->op_info = (char*)"";
6015
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6016
  return(0);
1 by brian
clean slate
6017
}
6018
6019
/*********************************************************************
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
6020
Checks if ALTER Table may change the storage engine of the table.
1 by brian
clean slate
6021
Changing storage engines is not allowed for tables for which there
6022
are foreign key constraints (parent or child tables). */
6023
6024
bool
6025
ha_innobase::can_switch_engines(void)
6026
/*=================================*/
6027
{
6028
	bool	can_switch;
6029
6030
	ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
6031
6032
	prebuilt->trx->op_info =
6033
			"determining if there are foreign key constraints";
6034
	row_mysql_lock_data_dictionary(prebuilt->trx);
6035
6036
	can_switch = !UT_LIST_GET_FIRST(prebuilt->table->referenced_list)
6037
			&& !UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
6038
6039
	row_mysql_unlock_data_dictionary(prebuilt->trx);
6040
	prebuilt->trx->op_info = "";
6041
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6042
	return(can_switch);
1 by brian
clean slate
6043
}
6044
6045
/***********************************************************************
6046
Checks if a table is referenced by a foreign key. The MySQL manual states that
6047
a REPLACE is either equivalent to an INSERT, or DELETE(s) + INSERT. Only a
6048
delete is then allowed internally to resolve a duplicate key conflict in
6049
REPLACE, not an update. */
6050
6051
uint
6052
ha_innobase::referenced_by_foreign_key(void)
6053
/*========================================*/
6054
			/* out: > 0 if referenced by a FOREIGN KEY */
6055
{
6056
	if (dict_table_referenced_by_foreign_key(prebuilt->table)) {
6057
6058
		return(1);
6059
	}
6060
6061
	return(0);
6062
}
6063
6064
/***********************************************************************
6065
Frees the foreign key create info for a table stored in InnoDB, if it is
6066
non-NULL. */
6067
6068
void
6069
ha_innobase::free_foreign_key_create_info(
6070
/*======================================*/
6071
	char*	str)	/* in, own: create info string to free	*/
6072
{
6073
	if (str) {
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
6074
		free(str);
1 by brian
clean slate
6075
	}
6076
}
6077
6078
/***********************************************************************
6079
Tells something additional to the handler about how to do things. */
6080
6081
int
6082
ha_innobase::extra(
6083
/*===============*/
6084
			   /* out: 0 or error number */
6085
	enum ha_extra_function operation)
6086
			   /* in: HA_EXTRA_FLUSH or some other flag */
6087
{
6088
	/* Warning: since it is not sure that MySQL calls external_lock
6089
	before calling this function, the trx field in prebuilt can be
6090
	obsolete! */
6091
6092
	switch (operation) {
6093
		case HA_EXTRA_FLUSH:
6094
			if (prebuilt->blob_heap) {
6095
				row_mysql_prebuilt_free_blob_heap(prebuilt);
6096
			}
6097
			break;
6098
		case HA_EXTRA_RESET_STATE:
6099
			reset_template(prebuilt);
6100
6101
                        /* Reset index condition pushdown state */
6102
                        pushed_idx_cond= FALSE;
6103
                        pushed_idx_cond_keyno= MAX_KEY;
6104
                        //in_range_read= FALSE;
6105
                        prebuilt->idx_cond_func= NULL;
6106
			break;
6107
		case HA_EXTRA_NO_KEYREAD:
6108
			prebuilt->read_just_key = 0;
6109
			break;
6110
		case HA_EXTRA_KEYREAD:
6111
			prebuilt->read_just_key = 1;
6112
			break;
6113
		case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
6114
			prebuilt->keep_other_fields_on_keyread = 1;
6115
			break;
6116
6117
			/* IMPORTANT: prebuilt->trx can be obsolete in
6118
			this method, because it is not sure that MySQL
6119
			calls external_lock before this method with the
6120
			parameters below.  We must not invoke update_thd()
6121
			either, because the calling threads may change.
6122
			CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
6123
		case HA_EXTRA_IGNORE_DUP_KEY:
6124
			thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
6125
			break;
6126
		case HA_EXTRA_WRITE_CAN_REPLACE:
6127
			thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
6128
			break;
6129
		case HA_EXTRA_WRITE_CANNOT_REPLACE:
6130
			thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
6131
			break;
6132
		case HA_EXTRA_NO_IGNORE_DUP_KEY:
6133
			thd_to_trx(ha_thd())->duplicates &=
6134
				~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
6135
			break;
6136
		default:/* Do nothing */
6137
			;
6138
	}
6139
6140
	return(0);
6141
}
6142
6143
int ha_innobase::reset()
6144
{
6145
  if (prebuilt->blob_heap) {
6146
    row_mysql_prebuilt_free_blob_heap(prebuilt);
6147
  }
6148
  reset_template(prebuilt);
6149
  /* Reset index condition pushdown state */
6150
  pushed_idx_cond_keyno= MAX_KEY;
6151
  pushed_idx_cond= NULL;
6152
  ds_mrr.dsmrr_close();
6153
  prebuilt->idx_cond_func= NULL;
6154
  return 0;
6155
}
6156
6157
6158
/**********************************************************************
6159
MySQL calls this function at the start of each SQL statement inside LOCK
6160
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
6161
mark SQL statement borders. Note also a special case: if a temporary table
6162
is created inside LOCK TABLES, MySQL has not called external_lock() at all
6163
on that table.
6164
MySQL-5.0 also calls this before each statement in an execution of a stored
6165
procedure. To make the execution more deterministic for binlogging, MySQL-5.0
6166
locks all tables involved in a stored procedure with full explicit table
6167
locks (thd_in_lock_tables(thd) holds in store_lock()) before executing the
6168
procedure. */
6169
6170
int
6171
ha_innobase::start_stmt(
6172
/*====================*/
6173
				/* out: 0 or error code */
6174
	THD*		thd,	/* in: handle to the user thread */
6175
	thr_lock_type	lock_type)
6176
{
6177
	trx_t*		trx;
6178
6179
	update_thd(thd);
6180
6181
	trx = prebuilt->trx;
6182
6183
	/* Here we release the search latch and the InnoDB thread FIFO ticket
6184
	if they were reserved. They should have been released already at the
6185
	end of the previous statement, but because inside LOCK TABLES the
6186
	lock count method does not work to mark the end of a SELECT statement,
6187
	that may not be the case. We MUST release the search latch before an
6188
	INSERT, for example. */
6189
6190
	innobase_release_stat_resources(trx);
6191
6192
	/* Reset the AUTOINC statement level counter for multi-row INSERTs. */
6193
	trx->n_autoinc_rows = 0;
6194
6195
	prebuilt->sql_stat_start = TRUE;
6196
	prebuilt->hint_need_to_fetch_extra_cols = 0;
6197
	reset_template(prebuilt);
6198
6199
	if (!prebuilt->mysql_has_locked) {
6200
		/* This handle is for a temporary table created inside
6201
		this same LOCK TABLES; since MySQL does NOT call external_lock
6202
		in this case, we must use x-row locks inside InnoDB to be
6203
		prepared for an update of a row */
6204
6205
		prebuilt->select_lock_type = LOCK_X;
6206
	} else {
6207
		if (trx->isolation_level != TRX_ISO_SERIALIZABLE
6208
			&& thd_sql_command(thd) == SQLCOM_SELECT
6209
			&& lock_type == TL_READ) {
6210
6211
			/* For other than temporary tables, we obtain
6212
			no lock for consistent read (plain SELECT). */
6213
6214
			prebuilt->select_lock_type = LOCK_NONE;
6215
		} else {
6216
			/* Not a consistent read: restore the
6217
			select_lock_type value. The value of
6218
			stored_select_lock_type was decided in:
6219
			1) ::store_lock(),
6220
			2) ::external_lock(),
6221
			3) ::init_table_handle_for_HANDLER(), and
6222
			4) ::transactional_table_lock(). */
6223
6224
			prebuilt->select_lock_type =
6225
				prebuilt->stored_select_lock_type;
6226
		}
6227
	}
6228
6229
	trx->detailed_error[0] = '\0';
6230
6231
	/* Set the MySQL flag to mark that there is an active transaction */
6232
	if (trx->active_trans == 0) {
6233
6234
		innobase_register_trx_and_stmt(ht, thd);
6235
		trx->active_trans = 1;
6236
	} else {
6237
		innobase_register_stmt(ht, thd);
6238
	}
6239
6240
	return(0);
6241
}
6242
6243
/**********************************************************************
6244
Maps a MySQL trx isolation level code to the InnoDB isolation level code */
6245
inline
6246
ulint
6247
innobase_map_isolation_level(
6248
/*=========================*/
6249
					/* out: InnoDB isolation level */
6250
	enum_tx_isolation	iso)	/* in: MySQL isolation level code */
6251
{
6252
	switch(iso) {
6253
		case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
6254
		case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
6255
		case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
6256
		case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
6257
		default: ut_a(0); return(0);
6258
	}
6259
}
6260
6261
/**********************************************************************
6262
As MySQL will execute an external lock for every new table it uses when it
6263
starts to process an SQL statement (an exception is when MySQL calls
6264
start_stmt for the handle) we can use this function to store the pointer to
6265
the THD in the handle. We will also use this function to communicate
6266
to InnoDB that a new SQL statement has started and that we must store a
6267
savepoint to our transaction handle, so that we are able to roll back
6268
the SQL statement in case of an error. */
6269
6270
int
6271
ha_innobase::external_lock(
6272
/*=======================*/
6273
				/* out: 0 */
6274
	THD*	thd,		/* in: handle to the user thread */
6275
	int	lock_type)	/* in: lock type */
6276
{
6277
	trx_t*		trx;
6278
6279
	update_thd(thd);
6280
6281
	/* Statement based binlogging does not work in isolation level
6282
	READ UNCOMMITTED and READ COMMITTED since the necessary
6283
	locks cannot be taken. In this case, we print an
6284
	informative error message and return with an error. */
6285
	if (lock_type == F_WRLCK)
6286
	{
6287
		ulong const binlog_format= thd_binlog_format(thd);
6288
		ulong const tx_isolation = thd_tx_isolation(current_thd);
6289
		if (tx_isolation <= ISO_READ_COMMITTED &&
6290
		    binlog_format == BINLOG_FORMAT_STMT)
6291
		{
6292
			char buf[256];
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
6293
			snprintf(buf, sizeof(buf),
6294
				 "Transaction level '%s' in"
6295
				 " InnoDB is not safe for binlog mode '%s'",
6296
				 tx_isolation_names[tx_isolation],
6297
				 binlog_format_names[binlog_format]);
1 by brian
clean slate
6298
			my_error(ER_BINLOG_LOGGING_IMPOSSIBLE, MYF(0), buf);
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6299
			return(HA_ERR_LOGGING_IMPOSSIBLE);
1 by brian
clean slate
6300
		}
6301
	}
6302
6303
6304
	trx = prebuilt->trx;
6305
6306
	prebuilt->sql_stat_start = TRUE;
6307
	prebuilt->hint_need_to_fetch_extra_cols = 0;
6308
6309
	reset_template(prebuilt);
6310
6311
	if (lock_type == F_WRLCK) {
6312
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
6313
		/* If this is a SELECT, then it is in UPDATE Table ...
1 by brian
clean slate
6314
		or SELECT ... FOR UPDATE */
6315
		prebuilt->select_lock_type = LOCK_X;
6316
		prebuilt->stored_select_lock_type = LOCK_X;
6317
	}
6318
6319
	if (lock_type != F_UNLCK) {
6320
		/* MySQL is setting a new table lock */
6321
6322
		trx->detailed_error[0] = '\0';
6323
6324
		/* Set the MySQL flag to mark that there is an active
6325
		transaction */
6326
		if (trx->active_trans == 0) {
6327
6328
			innobase_register_trx_and_stmt(ht, thd);
6329
			trx->active_trans = 1;
6330
		} else if (trx->n_mysql_tables_in_use == 0) {
6331
			innobase_register_stmt(ht, thd);
6332
		}
6333
6334
		if (trx->isolation_level == TRX_ISO_SERIALIZABLE
6335
			&& prebuilt->select_lock_type == LOCK_NONE
6336
			&& thd_test_options(thd,
6337
				OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
6338
6339
			/* To get serializable execution, we let InnoDB
6340
			conceptually add 'LOCK IN SHARE MODE' to all SELECTs
6341
			which otherwise would have been consistent reads. An
6342
			exception is consistent reads in the AUTOCOMMIT=1 mode:
6343
			we know that they are read-only transactions, and they
6344
			can be serialized also if performed as consistent
6345
			reads. */
6346
6347
			prebuilt->select_lock_type = LOCK_S;
6348
			prebuilt->stored_select_lock_type = LOCK_S;
6349
		}
6350
6351
		/* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
6352
		TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
6353
		an InnoDB table lock if it is released immediately at the end
6354
		of LOCK TABLES, and InnoDB's table locks in that case cause
6355
		VERY easily deadlocks.
6356
6357
		We do not set InnoDB table locks if user has not explicitly
6358
		requested a table lock. Note that thd_in_lock_tables(thd)
6359
		can hold in some cases, e.g., at the start of a stored
6360
		procedure call (SQLCOM_CALL). */
6361
6362
		if (prebuilt->select_lock_type != LOCK_NONE) {
6363
6364
			if (thd_sql_command(thd) == SQLCOM_LOCK_TABLES
6365
			    && THDVAR(thd, table_locks)
6366
			    && thd_test_options(thd, OPTION_NOT_AUTOCOMMIT)
6367
			    && thd_in_lock_tables(thd)) {
6368
6369
				ulint	error = row_lock_table_for_mysql(
6370
					prebuilt, NULL, 0);
6371
6372
				if (error != DB_SUCCESS) {
6373
					error = convert_error_code_to_mysql(
6374
						(int) error, thd);
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6375
					return((int) error);
1 by brian
clean slate
6376
				}
6377
			}
6378
6379
			trx->mysql_n_tables_locked++;
6380
		}
6381
6382
		trx->n_mysql_tables_in_use++;
6383
		prebuilt->mysql_has_locked = TRUE;
6384
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6385
		return(0);
1 by brian
clean slate
6386
	}
6387
6388
	/* MySQL is releasing a table lock */
6389
6390
	trx->n_mysql_tables_in_use--;
6391
	prebuilt->mysql_has_locked = FALSE;
6392
6393
	/* Release a possible FIFO ticket and search latch. Since we
6394
	may reserve the kernel mutex, we have to release the search
6395
	system latch first to obey the latching order. */
6396
6397
	innobase_release_stat_resources(trx);
6398
6399
	/* If the MySQL lock count drops to zero we know that the current SQL
6400
	statement has ended */
6401
6402
	if (trx->n_mysql_tables_in_use == 0) {
6403
6404
		trx->mysql_n_tables_locked = 0;
6405
		prebuilt->used_in_HANDLER = FALSE;
6406
6407
		if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
6408
			if (trx->active_trans != 0) {
6409
				innobase_commit(ht, thd, TRUE);
6410
			}
6411
		} else {
6412
			if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
6413
						&& trx->global_read_view) {
6414
6415
				/* At low transaction isolation levels we let
6416
				each consistent read set its own snapshot */
6417
6418
				read_view_close_for_mysql(trx);
6419
			}
6420
		}
6421
	}
6422
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6423
	return(0);
1 by brian
clean slate
6424
}
6425
6426
/**********************************************************************
6427
With this function MySQL request a transactional lock to a table when
6428
user issued query LOCK TABLES..WHERE ENGINE = InnoDB. */
6429
6430
int
6431
ha_innobase::transactional_table_lock(
6432
/*==================================*/
6433
				/* out: error code */
6434
	THD*	thd,		/* in: handle to the user thread */
6435
	int	lock_type)	/* in: lock type */
6436
{
6437
	trx_t*		trx;
6438
6439
	/* We do not know if MySQL can call this function before calling
6440
	external_lock(). To be safe, update the thd of the current table
6441
	handle. */
6442
6443
	update_thd(thd);
6444
6445
	if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(thd)) {
6446
		ut_print_timestamp(stderr);
6447
		fprintf(stderr,
6448
			"  InnoDB: MySQL is trying to use a table handle"
6449
			" but the .ibd file for\n"
6450
			"InnoDB: table %s does not exist.\n"
6451
			"InnoDB: Have you deleted the .ibd file"
6452
			" from the database directory under\n"
6453
			"InnoDB: the MySQL datadir?"
6454
			"InnoDB: See"
6455
			" http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
6456
			"InnoDB: how you can resolve the problem.\n",
6457
			prebuilt->table->name);
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6458
		return(HA_ERR_CRASHED);
1 by brian
clean slate
6459
	}
6460
6461
	trx = prebuilt->trx;
6462
6463
	prebuilt->sql_stat_start = TRUE;
6464
	prebuilt->hint_need_to_fetch_extra_cols = 0;
6465
6466
	reset_template(prebuilt);
6467
6468
	if (lock_type == F_WRLCK) {
6469
		prebuilt->select_lock_type = LOCK_X;
6470
		prebuilt->stored_select_lock_type = LOCK_X;
6471
	} else if (lock_type == F_RDLCK) {
6472
		prebuilt->select_lock_type = LOCK_S;
6473
		prebuilt->stored_select_lock_type = LOCK_S;
6474
	} else {
6475
		ut_print_timestamp(stderr);
6476
		fprintf(stderr, "  InnoDB error:\n"
6477
"MySQL is trying to set transactional table lock with corrupted lock type\n"
6478
"to table %s, lock type %d does not exist.\n",
6479
				prebuilt->table->name, lock_type);
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6480
		return(HA_ERR_CRASHED);
1 by brian
clean slate
6481
	}
6482
6483
	/* MySQL is setting a new transactional table lock */
6484
6485
	/* Set the MySQL flag to mark that there is an active transaction */
6486
	if (trx->active_trans == 0) {
6487
6488
		innobase_register_trx_and_stmt(ht, thd);
6489
		trx->active_trans = 1;
6490
	}
6491
6492
	if (THDVAR(thd, table_locks) && thd_in_lock_tables(thd)) {
6493
		ulint	error = DB_SUCCESS;
6494
6495
		error = row_lock_table_for_mysql(prebuilt, NULL, 0);
6496
6497
		if (error != DB_SUCCESS) {
6498
			error = convert_error_code_to_mysql((int) error, thd);
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6499
			return((int) error);
1 by brian
clean slate
6500
		}
6501
6502
		if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
6503
6504
			/* Store the current undo_no of the transaction
6505
			so that we know where to roll back if we have
6506
			to roll back the next SQL statement */
6507
6508
			trx_mark_sql_stat_end(trx);
6509
		}
6510
	}
6511
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6512
	return(0);
1 by brian
clean slate
6513
}
6514
6515
/****************************************************************************
6516
Here we export InnoDB status variables to MySQL.  */
77.1.23 by Monty Taylor
Rolled back innodb status var change.
6517
/* TODO: FIX the case below: */
1 by brian
clean slate
6518
static
6519
int
6520
innodb_export_status()
77.1.23 by Monty Taylor
Rolled back innodb status var change.
6521
/*==================*/
1 by brian
clean slate
6522
{
6523
	if (innodb_inited) {
6524
		srv_export_innodb_status();
6525
	}
6526
6527
	return 0;
6528
}
77.1.25 by Monty Taylor
Merged from trunk.
6529
/**/
1 by brian
clean slate
6530
6531
/****************************************************************************
6532
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
6533
Monitor to the client. */
6534
static
6535
bool
6536
innodb_show_status(
6537
/*===============*/
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
6538
	handlerton*	hton __attribute__((unused)),	/* in: the innodb handlerton */
1 by brian
clean slate
6539
	THD*	thd,	/* in: the MySQL query thread of the caller */
6540
	stat_print_fn *stat_print)
6541
{
6542
	trx_t*			trx;
6543
	static const char	truncated_msg[] = "... truncated...\n";
6544
	const long		MAX_STATUS_SIZE = 64000;
6545
	ulint			trx_list_start = ULINT_UNDEFINED;
6546
	ulint			trx_list_end = ULINT_UNDEFINED;
6547
6548
	trx = check_trx_exists(thd);
6549
6550
	innobase_release_stat_resources(trx);
6551
6552
	/* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
6553
	bytes of text. */
6554
6555
	long	flen, usable_len;
6556
	char*	str;
6557
6558
	mutex_enter_noninline(&srv_monitor_file_mutex);
6559
	rewind(srv_monitor_file);
6560
	srv_printf_innodb_monitor(srv_monitor_file,
6561
				&trx_list_start, &trx_list_end);
6562
	flen = ftell(srv_monitor_file);
6563
	os_file_set_eof(srv_monitor_file);
6564
6565
	if (flen < 0) {
6566
		flen = 0;
6567
	}
6568
6569
	if (flen > MAX_STATUS_SIZE) {
6570
		usable_len = MAX_STATUS_SIZE;
6571
	} else {
6572
		usable_len = flen;
6573
	}
6574
6575
	/* allocate buffer for the string, and
6576
	read the contents of the temporary file */
6577
6578
	if (!(str = (char*) my_malloc(usable_len + 1, MYF(0)))) {
6579
	  mutex_exit_noninline(&srv_monitor_file_mutex);
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6580
	  return(TRUE);
1 by brian
clean slate
6581
	}
6582
6583
	rewind(srv_monitor_file);
6584
	if (flen < MAX_STATUS_SIZE) {
6585
		/* Display the entire output. */
6586
		flen = (long) fread(str, 1, flen, srv_monitor_file);
6587
	} else if (trx_list_end < (ulint) flen
6588
			&& trx_list_start < trx_list_end
6589
			&& trx_list_start + (flen - trx_list_end)
6590
			< MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
6591
		/* Omit the beginning of the list of active transactions. */
6592
		long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
6593
		memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
6594
		len += sizeof truncated_msg - 1;
6595
		usable_len = (MAX_STATUS_SIZE - 1) - len;
6596
		fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
6597
		len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
6598
		flen = len;
6599
	} else {
6600
		/* Omit the end of the output. */
6601
		flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
6602
	}
6603
6604
	mutex_exit_noninline(&srv_monitor_file_mutex);
6605
6606
	bool result = FALSE;
6607
6608
	if (stat_print(thd, innobase_hton_name, strlen(innobase_hton_name),
6609
			STRING_WITH_LEN(""), str, flen)) {
6610
		result= TRUE;
6611
	}
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
6612
	free(str);
1 by brian
clean slate
6613
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6614
	return(FALSE);
1 by brian
clean slate
6615
}
6616
6617
/****************************************************************************
6618
Implements the SHOW MUTEX STATUS command. . */
6619
static
6620
bool
6621
innodb_mutex_show_status(
6622
/*=====================*/
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
6623
	handlerton*	hton __attribute__((unused)),	/* in: the innodb handlerton */
1 by brian
clean slate
6624
	THD*		thd,		/* in: the MySQL query thread of the
6625
					caller */
6626
	stat_print_fn*	stat_print)
6627
{
6628
	char buf1[IO_SIZE], buf2[IO_SIZE];
6629
	mutex_t*  mutex;
6630
#ifdef UNIV_DEBUG
6631
	ulint	  rw_lock_count= 0;
6632
	ulint	  rw_lock_count_spin_loop= 0;
6633
	ulint	  rw_lock_count_spin_rounds= 0;
6634
	ulint	  rw_lock_count_os_wait= 0;
6635
	ulint	  rw_lock_count_os_yield= 0;
151 by Brian Aker
Ulonglong to uint64_t
6636
	uint64_t rw_lock_wait_time= 0;
1 by brian
clean slate
6637
#endif /* UNIV_DEBUG */
6638
	uint	  hton_name_len= strlen(innobase_hton_name), buf1len, buf2len;
6639
6640
	mutex_enter_noninline(&mutex_list_mutex);
6641
6642
	mutex = UT_LIST_GET_FIRST(mutex_list);
6643
6644
	while (mutex != NULL) {
6645
#ifdef UNIV_DEBUG
6646
		if (mutex->mutex_type != 1) {
6647
			if (mutex->count_using > 0) {
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
6648
				buf1len= snprintf(buf1, sizeof(buf1),
1 by brian
clean slate
6649
					"%s:%s",
6650
					mutex->cmutex_name, mutex->cfile_name);
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
6651
				buf2len= snprintf(buf2, sizeof(buf2),
1 by brian
clean slate
6652
					"count=%lu, spin_waits=%lu,"
6653
					" spin_rounds=%lu, "
6654
					"os_waits=%lu, os_yields=%lu,"
6655
					" os_wait_times=%lu",
6656
					mutex->count_using,
6657
					mutex->count_spin_loop,
6658
					mutex->count_spin_rounds,
6659
					mutex->count_os_wait,
6660
					mutex->count_os_yield,
6661
					(ulong) (mutex->lspent_time/1000));
6662
6663
				if (stat_print(thd, innobase_hton_name,
6664
						hton_name_len, buf1, buf1len,
6665
						buf2, buf2len)) {
6666
					mutex_exit_noninline(
6667
						&mutex_list_mutex);
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6668
					return(1);
1 by brian
clean slate
6669
				}
6670
			}
6671
		}
6672
		else {
6673
			rw_lock_count += mutex->count_using;
6674
			rw_lock_count_spin_loop += mutex->count_spin_loop;
6675
			rw_lock_count_spin_rounds += mutex->count_spin_rounds;
6676
			rw_lock_count_os_wait += mutex->count_os_wait;
6677
			rw_lock_count_os_yield += mutex->count_os_yield;
6678
			rw_lock_wait_time += mutex->lspent_time;
6679
		}
6680
#else /* UNIV_DEBUG */
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
6681
		buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
6682
				  mutex->cfile_name, (ulong) mutex->cline);
6683
		buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
6684
				  mutex->count_os_wait);
1 by brian
clean slate
6685
6686
		if (stat_print(thd, innobase_hton_name,
6687
			       hton_name_len, buf1, buf1len,
6688
			       buf2, buf2len)) {
6689
			mutex_exit_noninline(&mutex_list_mutex);
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6690
			return(1);
1 by brian
clean slate
6691
		}
6692
#endif /* UNIV_DEBUG */
6693
6694
		mutex = UT_LIST_GET_NEXT(list, mutex);
6695
	}
6696
6697
	mutex_exit_noninline(&mutex_list_mutex);
6698
6699
#ifdef UNIV_DEBUG
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
6700
	buf2len= snprintf(buf2, sizeof(buf2),
1 by brian
clean slate
6701
		"count=%lu, spin_waits=%lu, spin_rounds=%lu, "
6702
		"os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
6703
		rw_lock_count, rw_lock_count_spin_loop,
6704
		rw_lock_count_spin_rounds,
6705
		rw_lock_count_os_wait, rw_lock_count_os_yield,
6706
		(ulong) (rw_lock_wait_time/1000));
6707
6708
	if (stat_print(thd, innobase_hton_name, hton_name_len,
6709
			STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6710
		return(1);
1 by brian
clean slate
6711
	}
6712
#endif /* UNIV_DEBUG */
6713
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6714
	return(FALSE);
1 by brian
clean slate
6715
}
6716
6717
static
6718
bool innobase_show_status(handlerton *hton, THD* thd, 
6719
                          stat_print_fn* stat_print,
6720
                          enum ha_stat_type stat_type)
6721
{
6722
	switch (stat_type) {
6723
	case HA_ENGINE_STATUS:
6724
		return innodb_show_status(hton, thd, stat_print);
6725
	case HA_ENGINE_MUTEX:
6726
		return innodb_mutex_show_status(hton, thd, stat_print);
6727
	default:
6728
		return FALSE;
6729
	}
6730
}
6731
6732
6733
/****************************************************************************
6734
 Handling the shared INNOBASE_SHARE structure that is needed to provide table
6735
 locking.
6736
****************************************************************************/
6737
481 by Brian Aker
Remove all of uchar.
6738
static unsigned char* innobase_get_key(INNOBASE_SHARE* share, size_t *length,
284 by Brian Aker
First pass Innodb my_bool removal.
6739
                               bool not_used __attribute__((unused)))
1 by brian
clean slate
6740
{
6741
	*length=share->table_name_length;
6742
481 by Brian Aker
Remove all of uchar.
6743
	return (unsigned char*) share->table_name;
1 by brian
clean slate
6744
}
6745
6746
static INNOBASE_SHARE* get_share(const char* table_name)
6747
{
6748
	INNOBASE_SHARE *share;
6749
	pthread_mutex_lock(&innobase_share_mutex);
482 by Brian Aker
Remove uint.
6750
	uint32_t length=(uint) strlen(table_name);
1 by brian
clean slate
6751
6752
	if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables,
481 by Brian Aker
Remove all of uchar.
6753
				(unsigned char*) table_name,
1 by brian
clean slate
6754
				length))) {
6755
6756
		share = (INNOBASE_SHARE *) my_malloc(sizeof(*share)+length+1,
6757
			MYF(MY_FAE | MY_ZEROFILL));
6758
6759
		share->table_name_length=length;
6760
		share->table_name=(char*) (share+1);
411.1.1 by Brian Aker
Work on removing GNU specific calls.
6761
		my_stpcpy(share->table_name,table_name);
1 by brian
clean slate
6762
6763
		if (my_hash_insert(&innobase_open_tables,
481 by Brian Aker
Remove all of uchar.
6764
				(unsigned char*) share)) {
1 by brian
clean slate
6765
			pthread_mutex_unlock(&innobase_share_mutex);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
6766
			free(share);
1 by brian
clean slate
6767
6768
			return 0;
6769
		}
6770
6771
		thr_lock_init(&share->lock);
6772
		pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
6773
	}
6774
6775
	share->use_count++;
6776
	pthread_mutex_unlock(&innobase_share_mutex);
6777
6778
	return share;
6779
}
6780
6781
static void free_share(INNOBASE_SHARE* share)
6782
{
6783
	pthread_mutex_lock(&innobase_share_mutex);
6784
6785
	if (!--share->use_count) {
481 by Brian Aker
Remove all of uchar.
6786
		hash_delete(&innobase_open_tables, (unsigned char*) share);
1 by brian
clean slate
6787
		thr_lock_delete(&share->lock);
6788
		pthread_mutex_destroy(&share->mutex);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
6789
		free(share);
1 by brian
clean slate
6790
	}
6791
6792
	pthread_mutex_unlock(&innobase_share_mutex);
6793
}
6794
6795
/*********************************************************************
6796
Converts a MySQL table lock stored in the 'lock' field of the handle to
6797
a proper type before storing pointer to the lock into an array of pointers.
6798
MySQL also calls this if it wants to reset some table locks to a not-locked
6799
state during the processing of an SQL query. An example is that during a
6800
SELECT the read lock is released early on the 'const' tables where we only
6801
fetch one row. MySQL does not call this when it releases all locks at the
6802
end of an SQL statement. */
6803
6804
THR_LOCK_DATA**
6805
ha_innobase::store_lock(
6806
/*====================*/
6807
						/* out: pointer to the next
6808
						element in the 'to' array */
6809
	THD*			thd,		/* in: user thread handle */
6810
	THR_LOCK_DATA**		to,		/* in: pointer to an array
6811
						of pointers to lock structs;
6812
						pointer to the 'lock' field
6813
						of current handle is stored
6814
						next to this array */
6815
	enum thr_lock_type	lock_type)	/* in: lock type to store in
6816
						'lock'; this may also be
6817
						TL_IGNORE */
6818
{
6819
	trx_t*		trx;
6820
6821
	/* Note that trx in this function is NOT necessarily prebuilt->trx
6822
	because we call update_thd() later, in ::external_lock()! Failure to
6823
	understand this caused a serious memory corruption bug in 5.1.11. */
6824
6825
	trx = check_trx_exists(thd);
6826
6827
	/* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
6828
	Be careful to ignore TL_IGNORE if we are going to do something with
6829
	only 'real' locks! */
6830
6831
	/* If no MySQL table is in use, we need to set the isolation level
6832
	of the transaction. */
6833
6834
	if (lock_type != TL_IGNORE
6835
	    && trx->n_mysql_tables_in_use == 0) {
6836
		trx->isolation_level = innobase_map_isolation_level(
6837
			(enum_tx_isolation) thd_tx_isolation(thd));
6838
6839
		if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
6840
		    && trx->global_read_view) {
6841
6842
			/* At low transaction isolation levels we let
6843
			each consistent read set its own snapshot */
6844
6845
			read_view_close_for_mysql(trx);
6846
		}
6847
	}
6848
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
6849
	assert(thd == current_thd);
1 by brian
clean slate
6850
	const bool in_lock_tables = thd_in_lock_tables(thd);
482 by Brian Aker
Remove uint.
6851
	const uint32_t sql_command = thd_sql_command(thd);
1 by brian
clean slate
6852
6853
	if (sql_command == SQLCOM_DROP_TABLE) {
6854
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
6855
		/* MySQL calls this function in DROP Table though this table
1 by brian
clean slate
6856
		handle may belong to another thd that is running a query. Let
6857
		us in that case skip any changes to the prebuilt struct. */ 
6858
6859
	} else if ((lock_type == TL_READ && in_lock_tables)
6860
		   || (lock_type == TL_READ_HIGH_PRIORITY && in_lock_tables)
6861
		   || lock_type == TL_READ_WITH_SHARED_LOCKS
6862
		   || lock_type == TL_READ_NO_INSERT
6863
		   || (lock_type != TL_IGNORE
6864
		       && sql_command != SQLCOM_SELECT)) {
6865
6866
		/* The OR cases above are in this order:
6867
		1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
6868
		are processing a stored procedure or function, or
6869
		2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
6870
		3) this is a SELECT ... IN SHARE MODE, or
6871
		4) we are doing a complex SQL statement like
6872
		INSERT INTO ... SELECT ... and the logical logging (MySQL
6873
		binlog) requires the use of a locking read, or
6874
		MySQL is doing LOCK TABLES ... READ.
6875
		5) we let InnoDB do locking reads for all SQL statements that
6876
		are not simple SELECTs; note that select_lock_type in this
6877
		case may get strengthened in ::external_lock() to LOCK_X.
6878
		Note that we MUST use a locking read in all data modifying
6879
		SQL statements, because otherwise the execution would not be
6880
		serializable, and also the results from the update could be
6881
		unexpected if an obsolete consistent read view would be
6882
		used. */
6883
6884
		ulint	isolation_level;
6885
6886
		isolation_level = trx->isolation_level;
6887
6888
		if ((srv_locks_unsafe_for_binlog
6889
		     || isolation_level == TRX_ISO_READ_COMMITTED)
6890
		    && isolation_level != TRX_ISO_SERIALIZABLE
6891
		    && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
6892
		    && (sql_command == SQLCOM_INSERT_SELECT
6893
			|| sql_command == SQLCOM_UPDATE
6894
			|| sql_command == SQLCOM_CREATE_TABLE)) {
6895
6896
			/* If we either have innobase_locks_unsafe_for_binlog
6897
			option set or this session is using READ COMMITTED
6898
			isolation level and isolation level of the transaction
6899
			is not set to serializable and MySQL is doing
6900
			INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
6901
			CREATE  ... SELECT... without FOR UPDATE or
6902
			IN SHARE MODE in select, then we use consistent
6903
			read for select. */
6904
6905
			prebuilt->select_lock_type = LOCK_NONE;
6906
			prebuilt->stored_select_lock_type = LOCK_NONE;
6907
		} else if (sql_command == SQLCOM_CHECKSUM) {
6908
			/* Use consistent read for checksum table */
6909
6910
			prebuilt->select_lock_type = LOCK_NONE;
6911
			prebuilt->stored_select_lock_type = LOCK_NONE;
6912
		} else {
6913
			prebuilt->select_lock_type = LOCK_S;
6914
			prebuilt->stored_select_lock_type = LOCK_S;
6915
		}
6916
6917
	} else if (lock_type != TL_IGNORE) {
6918
6919
		/* We set possible LOCK_X value in external_lock, not yet
6920
		here even if this would be SELECT ... FOR UPDATE */
6921
6922
		prebuilt->select_lock_type = LOCK_NONE;
6923
		prebuilt->stored_select_lock_type = LOCK_NONE;
6924
	}
6925
6926
	if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
6927
6928
		/* Starting from 5.0.7, we weaken also the table locks
6929
		set at the start of a MySQL stored procedure call, just like
6930
		we weaken the locks set at the start of an SQL statement.
6931
		MySQL does set in_lock_tables TRUE there, but in reality
6932
		we do not need table locks to make the execution of a
6933
		single transaction stored procedure call deterministic
6934
		(if it does not use a consistent read). */
6935
6936
		if (lock_type == TL_READ
6937
		    && sql_command == SQLCOM_LOCK_TABLES) {
6938
			/* We come here if MySQL is processing LOCK TABLES
6939
			... READ LOCAL. MyISAM under that table lock type
6940
			reads the table as it was at the time the lock was
6941
			granted (new inserts are allowed, but not seen by the
6942
			reader). To get a similar effect on an InnoDB table,
6943
			we must use LOCK TABLES ... READ. We convert the lock
6944
			type here, so that for InnoDB, READ LOCAL is
6945
			equivalent to READ. This will change the InnoDB
6946
			behavior in mysqldump, so that dumps of InnoDB tables
6947
			are consistent with dumps of MyISAM tables. */
6948
6949
			lock_type = TL_READ_NO_INSERT;
6950
		}
6951
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
6952
		/* If we are not doing a LOCK Table, DISCARD/IMPORT
6953
		TABLESPACE or TRUNCATE Table then allow multiple
6954
		writers. Note that ALTER Table uses a TL_WRITE_ALLOW_READ
1 by brian
clean slate
6955
		< TL_WRITE_CONCURRENT_INSERT.
6956
6957
		We especially allow multiple writers if MySQL is at the
6958
		start of a stored procedure call (SQLCOM_CALL) or a
6959
		stored function call (MySQL does have in_lock_tables
6960
		TRUE there). */
6961
6962
		if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
6963
		     && lock_type <= TL_WRITE)
6964
		    && !(in_lock_tables
6965
			 && sql_command == SQLCOM_LOCK_TABLES)
6966
		    && !thd_tablespace_op(thd)
6967
		    && sql_command != SQLCOM_TRUNCATE
6968
		    && sql_command != SQLCOM_OPTIMIZE
6969
		    && sql_command != SQLCOM_CREATE_TABLE) {
6970
6971
			lock_type = TL_WRITE_ALLOW_WRITE;
6972
		}
6973
6974
		/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
6975
		MySQL would use the lock TL_READ_NO_INSERT on t2, and that
6976
		would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
6977
		to t2. Convert the lock to a normal read lock to allow
6978
		concurrent inserts to t2.
6979
6980
		We especially allow concurrent inserts if MySQL is at the
6981
		start of a stored procedure call (SQLCOM_CALL)
6982
		(MySQL does have thd_in_lock_tables() TRUE there). */
6983
6984
		if (lock_type == TL_READ_NO_INSERT
6985
		    && sql_command != SQLCOM_LOCK_TABLES) {
6986
6987
			lock_type = TL_READ;
6988
		}
6989
6990
		lock.type = lock_type;
6991
	}
6992
6993
	*to++= &lock;
6994
6995
	return(to);
6996
}
6997
6998
/***********************************************************************
6999
This function initializes the auto-inc counter if it has not been
7000
initialized yet. This function does not change the value of the auto-inc
7001
counter if it already has been initialized. In parameter ret returns
7002
the value of the auto-inc counter. */
7003
7004
int
7005
ha_innobase::innobase_read_and_init_auto_inc(
7006
/*=========================================*/
7007
						/* out: 0 or generic MySQL
7008
						error code */
152 by Brian Aker
longlong replacement
7009
        int64_t*	value)			/* out: the autoinc value */
1 by brian
clean slate
7010
{
152 by Brian Aker
longlong replacement
7011
	int64_t	auto_inc;
1 by brian
clean slate
7012
	ibool		stmt_start;
7013
	int		mysql_error = 0;
7014
	dict_table_t*	innodb_table = prebuilt->table;
7015
	ibool		trx_was_not_started	= FALSE;
7016
7017
	ut_a(prebuilt);
7018
	ut_a(prebuilt->table);
7019
7020
	/* Remember if we are in the beginning of an SQL statement.
7021
	This function must not change that flag. */
7022
	stmt_start = prebuilt->sql_stat_start;
7023
7024
	/* Prepare prebuilt->trx in the table handle */
7025
	update_thd(ha_thd());
7026
7027
	if (prebuilt->trx->conc_state == TRX_NOT_STARTED) {
7028
		trx_was_not_started = TRUE;
7029
	}
7030
7031
	/* In case MySQL calls this in the middle of a SELECT query, release
7032
	possible adaptive hash latch to avoid deadlocks of threads */
7033
7034
	trx_search_latch_release_if_reserved(prebuilt->trx);
7035
7036
	dict_table_autoinc_lock(prebuilt->table);
7037
7038
	auto_inc = dict_table_autoinc_read(prebuilt->table);
7039
7040
	/* Was the AUTOINC counter reset during normal processing, if
7041
	so then we simply start count from 1. No need to go to the index.*/
7042
	if (auto_inc == 0 && innodb_table->autoinc_inited) {
7043
		++auto_inc;
7044
		dict_table_autoinc_initialize(innodb_table, auto_inc);
7045
	}
7046
7047
	if (auto_inc == 0) {
7048
		dict_index_t* index;
7049
		ulint error;
7050
		const char* autoinc_col_name;
7051
7052
		ut_a(!innodb_table->autoinc_inited);
7053
7054
		index = innobase_get_index(table->s->next_number_index);
7055
7056
		autoinc_col_name = table->found_next_number_field->field_name;
7057
7058
		error = row_search_max_autoinc(
7059
			index, autoinc_col_name, &auto_inc);
7060
7061
		if (error == DB_SUCCESS) {
7062
			++auto_inc;
7063
			dict_table_autoinc_initialize(innodb_table, auto_inc);
7064
		} else {
7065
			ut_print_timestamp(stderr);
7066
			fprintf(stderr, "  InnoDB: Error: (%lu) Couldn't read "
7067
				"the max AUTOINC value from the index (%s).\n",
7068
				error, index->name);
7069
7070
			mysql_error = 1;
7071
		}
7072
	}
7073
7074
	*value = auto_inc;
7075
7076
	dict_table_autoinc_unlock(prebuilt->table);
7077
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
7078
	/* Since MySQL does not seem to call autocommit after SHOW Table
1 by brian
clean slate
7079
	STATUS (even if we would register the trx here), we commit our
7080
	transaction here if it was started here. This is to eliminate a
7081
	dangling transaction. If the user had AUTOCOMMIT=0, then SHOW
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
7082
	Table STATUS does leave a dangling transaction if the user does not
1 by brian
clean slate
7083
	himself call COMMIT. */
7084
7085
	if (trx_was_not_started) {
7086
7087
		innobase_commit_low(prebuilt->trx);
7088
	}
7089
7090
	prebuilt->sql_stat_start = stmt_start;
7091
7092
	return(mysql_error);
7093
}
7094
7095
/*******************************************************************************
7096
Read the next autoinc value, initialize the table if it's not initialized.
7097
On return if there is no error then the tables AUTOINC lock is locked.*/
7098
7099
ulong
7100
ha_innobase::innobase_get_auto_increment(
151 by Brian Aker
Ulonglong to uint64_t
7101
	uint64_t*	value)		/* out: autoinc value */
1 by brian
clean slate
7102
{
7103
	ulong		error;
7104
7105
	*value = 0;
7106
7107
	/* Note: If the table is not initialized when we attempt the
7108
	read below. We initialize the table's auto-inc counter  and
7109
	always do a reread of the AUTOINC value. */
7110
	do {
7111
		error = innobase_autoinc_lock();
7112
7113
		if (error == DB_SUCCESS) {
7114
			ib_longlong	autoinc;
7115
7116
			/* Determine the first value of the interval */
7117
			autoinc = dict_table_autoinc_read(prebuilt->table);
7118
7119
			/* We need to initialize the AUTO-INC value, for
7120
			that we release all locks.*/
7121
			if (autoinc <= 0) {
7122
				trx_t*		trx;
7123
7124
				trx = prebuilt->trx;
7125
				dict_table_autoinc_unlock(prebuilt->table);
7126
7127
				/* If we had reserved the AUTO-INC
7128
				lock in this SQL statement we release
7129
				it before retrying.*/
7130
				row_unlock_table_autoinc_for_mysql(trx);
7131
7132
				/* Just to make sure */
7133
				ut_a(!trx->auto_inc_lock);
7134
7135
				int	mysql_error;
7136
7137
				mysql_error = innobase_read_and_init_auto_inc(
7138
					&autoinc);
7139
7140
				if (!mysql_error) {
7141
					/* Should have read the proper value */
7142
					ut_a(autoinc > 0);
7143
				} else {
7144
					error = DB_ERROR;
7145
				}
7146
			} else {
151 by Brian Aker
Ulonglong to uint64_t
7147
				*value = (uint64_t) autoinc;
1 by brian
clean slate
7148
			}
7149
		/* A deadlock error during normal processing is OK
7150
		and can be ignored. */
7151
		} else if (error != DB_DEADLOCK) {
7152
7153
			sql_print_error("InnoDB: Error: %lu in "
7154
					"::innobase_get_auto_increment()",
7155
					error);
7156
		}
7157
7158
	} while (*value == 0 && error == DB_SUCCESS);
7159
7160
	return(error);
7161
}
7162
7163
/*******************************************************************************
7164
This function initializes the auto-inc counter if it has not been
7165
initialized yet. This function does not change the value of the auto-inc
7166
counter if it already has been initialized. Returns the value of the
163 by Brian Aker
Merge Monty's code.
7167
auto-inc counter in *first_value, and UINT64_MAX in *nb_reserved_values (as
1 by brian
clean slate
7168
we have a table-level lock). offset, increment, nb_desired_values are ignored.
7169
*first_value is set to -1 if error (deadlock or lock wait timeout)            */
7170
7171
void
7172
ha_innobase::get_auto_increment(
7173
/*============================*/
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
7174
        uint64_t	offset __attribute__((unused)),              /* in: */
151 by Brian Aker
Ulonglong to uint64_t
7175
        uint64_t	increment,           /* in: table autoinc increment */
7176
        uint64_t	nb_desired_values,   /* in: number of values reqd */
7177
        uint64_t	*first_value,        /* out: the autoinc value */
7178
        uint64_t	*nb_reserved_values) /* out: count of reserved values */
1 by brian
clean slate
7179
{
7180
	trx_t*		trx;
7181
	ulint		error;
151 by Brian Aker
Ulonglong to uint64_t
7182
	uint64_t	autoinc = 0;
1 by brian
clean slate
7183
7184
	/* Prepare prebuilt->trx in the table handle */
7185
	update_thd(ha_thd());
7186
7187
	error = innobase_get_auto_increment(&autoinc);
7188
7189
	if (error != DB_SUCCESS) {
151 by Brian Aker
Ulonglong to uint64_t
7190
		*first_value = (~(uint64_t) 0);
1 by brian
clean slate
7191
		return;
7192
	}
7193
7194
	/* This is a hack, since nb_desired_values seems to be accurate only
7195
	for the first call to get_auto_increment() for multi-row INSERT and
7196
	meaningless for other statements e.g, LOAD etc. Subsequent calls to
7197
	this method for the same statement results in different values which
7198
	don't make sense. Therefore we store the value the first time we are
7199
	called and count down from that as rows are written (see write_row()).
7200
	*/
7201
7202
	trx = prebuilt->trx;
7203
7204
	/* Note: We can't rely on *first_value since some MySQL engines,
7205
	in particular the partition engine, don't initialize it to 0 when
7206
	invoking this method. So we are not sure if it's guaranteed to
7207
	be 0 or not. */
7208
7209
	/* Called for the first time ? */
7210
	if (trx->n_autoinc_rows == 0) {
7211
7212
		trx->n_autoinc_rows = (ulint) nb_desired_values;
7213
7214
		/* It's possible for nb_desired_values to be 0:
7215
		e.g., INSERT INTO T1(C) SELECT C FROM T2; */
7216
		if (nb_desired_values == 0) {
7217
7218
			trx->n_autoinc_rows = 1;
7219
		}
7220
7221
		set_if_bigger(*first_value, autoinc);
7222
	/* Not in the middle of a mult-row INSERT. */
7223
	} else if (prebuilt->last_value == 0) {
7224
		set_if_bigger(*first_value, autoinc);
7225
	}
7226
7227
	*nb_reserved_values = trx->n_autoinc_rows;
7228
7229
	/* With old style AUTOINC locking we only update the table's
7230
	AUTOINC counter after attempting to insert the row. */
7231
	if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
7232
7233
		/* Compute the last value in the interval */
7234
		prebuilt->last_value = *first_value +
7235
		    (*nb_reserved_values * increment);
7236
7237
		ut_a(prebuilt->last_value >= *first_value);
7238
7239
		/* Update the table autoinc variable */
7240
		dict_table_autoinc_update(
7241
			prebuilt->table, prebuilt->last_value);
7242
	} else {
7243
		/* This will force write_row() into attempting an update
7244
		of the table's AUTOINC counter. */
7245
		prebuilt->last_value = 0;
7246
	}
7247
7248
	/* The increment to be used to increase the AUTOINC value, we use
7249
	this in write_row() and update_row() to increase the autoinc counter
7250
	for columns that are filled by the user.*/
7251
	prebuilt->table->autoinc_increment = increment;
7252
7253
	dict_table_autoinc_unlock(prebuilt->table);
7254
}
7255
7256
/* See comment in handler.h */
7257
int
7258
ha_innobase::reset_auto_increment(
7259
/*==============================*/
151 by Brian Aker
Ulonglong to uint64_t
7260
	uint64_t	value)		/* in: new value for table autoinc */
1 by brian
clean slate
7261
{
7262
	int	error;
7263
7264
	update_thd(ha_thd());
7265
7266
	error = row_lock_table_autoinc_for_mysql(prebuilt);
7267
7268
	if (error != DB_SUCCESS) {
7269
		error = convert_error_code_to_mysql(error, user_thd);
7270
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
7271
		return(error);
1 by brian
clean slate
7272
	}
7273
7274
	innobase_reset_autoinc(value);
7275
51.3.10 by Jay Pipes
Removed DBUG symbols from innodb handler
7276
	return(0);
1 by brian
clean slate
7277
}
7278
7279
/* See comment in handler.cc */
7280
bool
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
7281
ha_innobase::get_error_message(int error __attribute__((unused)), String *buf)
1 by brian
clean slate
7282
{
7283
	trx_t*	trx = check_trx_exists(ha_thd());
7284
7285
	buf->copy(trx->detailed_error, strlen(trx->detailed_error),
7286
		system_charset_info);
7287
7288
	return FALSE;
7289
}
7290
7291
/***********************************************************************
7292
Compares two 'refs'. A 'ref' is the (internal) primary key value of the row.
7293
If there is no explicitly declared non-null unique key or a primary key, then
7294
InnoDB internally uses the row id as the primary key. */
7295
7296
int
7297
ha_innobase::cmp_ref(
7298
/*=================*/
7299
				/* out: < 0 if ref1 < ref2, 0 if equal, else
7300
				> 0 */
481 by Brian Aker
Remove all of uchar.
7301
	const unsigned char*	ref1,	/* in: an (internal) primary key value in the
1 by brian
clean slate
7302
				MySQL key value format */
481 by Brian Aker
Remove all of uchar.
7303
	const unsigned char*	ref2)	/* in: an (internal) primary key value in the
1 by brian
clean slate
7304
				MySQL key value format */
7305
{
7306
	enum_field_types mysql_type;
7307
	Field*		field;
7308
	KEY_PART_INFO*	key_part;
7309
	KEY_PART_INFO*	key_part_end;
7310
	uint		len1;
7311
	uint		len2;
7312
	int		result;
7313
7314
	if (prebuilt->clust_index_was_generated) {
7315
		/* The 'ref' is an InnoDB row id */
7316
7317
		return(memcmp(ref1, ref2, DATA_ROW_ID_LEN));
7318
	}
7319
7320
	/* Do a type-aware comparison of primary key fields. PK fields
7321
	are always NOT NULL, so no checks for NULL are performed. */
7322
7323
	key_part = table->key_info[table->s->primary_key].key_part;
7324
7325
	key_part_end = key_part
7326
			+ table->key_info[table->s->primary_key].key_parts;
7327
7328
	for (; key_part != key_part_end; ++key_part) {
7329
		field = key_part->field;
7330
		mysql_type = field->type();
7331
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
7332
		if (mysql_type == DRIZZLE_TYPE_BLOB) {
1 by brian
clean slate
7333
7334
			/* In the MySQL key value format, a column prefix of
7335
			a BLOB is preceded by a 2-byte length field */
7336
7337
			len1 = innobase_read_from_2_little_endian(ref1);
7338
			len2 = innobase_read_from_2_little_endian(ref2);
7339
7340
			ref1 += 2;
7341
			ref2 += 2;
7342
			result = ((Field_blob*)field)->cmp( ref1, len1,
7343
                                                            ref2, len2);
7344
		} else {
7345
			result = field->key_cmp(ref1, ref2);
7346
		}
7347
7348
		if (result) {
7349
7350
			return(result);
7351
		}
7352
7353
		ref1 += key_part->store_length;
7354
		ref2 += key_part->store_length;
7355
	}
7356
7357
	return(0);
7358
}
7359
7360
/***********************************************************************
7361
Ask InnoDB if a query to a table can be cached. */
7362
200 by Brian Aker
my_bool from handler and set_var
7363
bool
1 by brian
clean slate
7364
ha_innobase::register_query_cache_table(
7365
/*====================================*/
7366
					/* out: TRUE if query caching
7367
					of the table is permitted */
7368
	THD*		thd,		/* in: user thread handle */
7369
	char*		table_key,	/* in: concatenation of database name,
7370
					the null character '\0',
7371
					and the table name */
7372
	uint		key_length,	/* in: length of the full name, i.e.
7373
					len(dbname) + len(tablename) + 1 */
7374
	qc_engine_callback*
7375
			call_back,	/* out: pointer to function for
7376
					checking if query caching
7377
					is permitted */
151 by Brian Aker
Ulonglong to uint64_t
7378
	uint64_t	*engine_data)	/* in/out: data to call_back */
1 by brian
clean slate
7379
{
7380
	*call_back = innobase_query_caching_of_table_permitted;
7381
	*engine_data = 0;
7382
	return(innobase_query_caching_of_table_permitted(thd, table_key,
7383
							 key_length,
7384
							 engine_data));
7385
}
7386
7387
char*
7388
ha_innobase::get_mysql_bin_log_name()
7389
{
7390
	return(trx_sys_mysql_bin_log_name);
7391
}
7392
151 by Brian Aker
Ulonglong to uint64_t
7393
uint64_t
1 by brian
clean slate
7394
ha_innobase::get_mysql_bin_log_pos()
7395
{
7396
	/* trx... is ib_longlong, which is a typedef for a 64-bit integer
152 by Brian Aker
longlong replacement
7397
	(__int64 or int64_t) so it's ok to cast it to uint64_t. */
1 by brian
clean slate
7398
7399
	return(trx_sys_mysql_bin_log_pos);
7400
}
7401
7402
/**********************************************************************
7403
This function is used to find the storage length in bytes of the first n
7404
characters for prefix indexes using a multibyte character set. The function
7405
finds charset information and returns length of prefix_len characters in the
7406
index field in bytes.
7407
7408
NOTE: the prototype of this function is copied to data0type.c! If you change
7409
this function, you MUST change also data0type.c! */
7410
extern "C"
7411
ulint
7412
innobase_get_at_most_n_mbchars(
7413
/*===========================*/
7414
				/* out: number of bytes occupied by the first
7415
				n characters */
7416
	ulint charset_id,	/* in: character set id */
7417
	ulint prefix_len,	/* in: prefix length in bytes of the index
7418
				(this has to be divided by mbmaxlen to get the
7419
				number of CHARACTERS n in the prefix) */
7420
	ulint data_len,		/* in: length of the string in bytes */
7421
	const char* str)	/* in: character string */
7422
{
7423
	ulint char_length;	/* character length in bytes */
7424
	ulint n_chars;		/* number of characters in prefix */
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
7425
	const CHARSET_INFO* charset;	/* charset used in the field */
1 by brian
clean slate
7426
7427
	charset = get_charset((uint) charset_id, MYF(MY_WME));
7428
7429
	ut_ad(charset);
7430
	ut_ad(charset->mbmaxlen);
7431
7432
	/* Calculate how many characters at most the prefix index contains */
7433
7434
	n_chars = prefix_len / charset->mbmaxlen;
7435
7436
	/* If the charset is multi-byte, then we must find the length of the
7437
	first at most n chars in the string. If the string contains less
7438
	characters than n, then we return the length to the end of the last
7439
	character. */
7440
7441
	if (charset->mbmaxlen > 1) {
7442
		/* my_charpos() returns the byte length of the first n_chars
7443
		characters, or a value bigger than the length of str, if
7444
		there were not enough full characters in str.
7445
7446
		Why does the code below work:
7447
		Suppose that we are looking for n UTF-8 characters.
7448
7449
		1) If the string is long enough, then the prefix contains at
7450
		least n complete UTF-8 characters + maybe some extra
7451
		characters + an incomplete UTF-8 character. No problem in
7452
		this case. The function returns the pointer to the
7453
		end of the nth character.
7454
7455
		2) If the string is not long enough, then the string contains
7456
		the complete value of a column, that is, only complete UTF-8
7457
		characters, and we can store in the column prefix index the
7458
		whole string. */
7459
7460
		char_length = my_charpos(charset, str,
7461
						str + data_len, (int) n_chars);
7462
		if (char_length > data_len) {
7463
			char_length = data_len;
7464
		}
7465
	} else {
7466
		if (data_len < prefix_len) {
7467
			char_length = data_len;
7468
		} else {
7469
			char_length = prefix_len;
7470
		}
7471
	}
7472
7473
	return(char_length);
7474
}
7475
7476
/***********************************************************************
7477
This function is used to prepare X/Open XA distributed transaction   */
7478
static
7479
int
7480
innobase_xa_prepare(
7481
/*================*/
7482
			/* out: 0 or error number */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
7483
        handlerton *hton __attribute__((unused)),
1 by brian
clean slate
7484
	THD*	thd,	/* in: handle to the MySQL thread of the user
7485
			whose XA transaction should be prepared */
7486
	bool	all)	/* in: TRUE - commit transaction
7487
			FALSE - the current SQL statement ended */
7488
{
7489
	int error = 0;
7490
	trx_t* trx = check_trx_exists(thd);
7491
12.1.2 by Brian Aker
Removing dead state calls.
7492
	if (all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
1 by brian
clean slate
7493
	{
7494
7495
		/* For ibbackup to work the order of transactions in binlog
7496
		and InnoDB must be the same. Consider the situation
7497
7498
		  thread1> prepare; write to binlog; ...
7499
			  <context switch>
7500
		  thread2> prepare; write to binlog; commit
7501
		  thread1>			     ... commit
7502
7503
		To ensure this will not happen we're taking the mutex on
7504
		prepare, and releasing it on commit.
7505
7506
		Note: only do it for normal commits, done via ha_commit_trans.
7507
		If 2pc protocol is executed by external transaction
7508
		coordinator, it will be just a regular MySQL client
7509
		executing XA PREPARE and XA COMMIT commands.
7510
		In this case we cannot know how many minutes or hours
7511
		will be between XA PREPARE and XA COMMIT, and we don't want
7512
		to block for undefined period of time.
7513
		*/
7514
		pthread_mutex_lock(&prepare_commit_mutex);
7515
		trx->active_trans = 2;
7516
	}
7517
7518
	if (!THDVAR(thd, support_xa)) {
7519
7520
		return(0);
7521
	}
7522
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7523
	thd_get_xid(thd, (DRIZZLE_XID*) &trx->xid);
1 by brian
clean slate
7524
7525
	/* Release a possible FIFO ticket and search latch. Since we will
7526
	reserve the kernel mutex, we have to release the search system latch
7527
	first to obey the latching order. */
7528
7529
	innobase_release_stat_resources(trx);
7530
7531
	if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
7532
7533
	  sql_print_error("trx->active_trans == 0, but trx->conc_state != "
7534
			  "TRX_NOT_STARTED");
7535
	}
7536
7537
	if (all
7538
		|| (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
7539
7540
		/* We were instructed to prepare the whole transaction, or
7541
		this is an SQL statement end and autocommit is on */
7542
7543
		ut_ad(trx->active_trans);
7544
7545
		error = (int) trx_prepare_for_mysql(trx);
7546
	} else {
7547
		/* We just mark the SQL statement ended and do not do a
7548
		transaction prepare */
7549
7550
		/* If we had reserved the auto-inc lock for some
7551
		table in this SQL statement we release it now */
7552
7553
		row_unlock_table_autoinc_for_mysql(trx);
7554
7555
		/* Store the current undo_no of the transaction so that we
7556
		know where to roll back if we have to roll back the next
7557
		SQL statement */
7558
7559
		trx_mark_sql_stat_end(trx);
7560
	}
7561
7562
	/* Tell the InnoDB server that there might be work for utility
7563
	threads: */
7564
7565
	srv_active_wake_master_thread();
7566
7567
	return error;
7568
}
7569
7570
/***********************************************************************
7571
This function is used to recover X/Open XA distributed transactions   */
7572
static
7573
int
7574
innobase_xa_recover(
7575
/*================*/
7576
				/* out: number of prepared transactions
7577
				stored in xid_list */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
7578
        handlerton *hton __attribute__((unused)),
1 by brian
clean slate
7579
	XID*	xid_list,	/* in/out: prepared transactions */
7580
	uint	len)		/* in: number of slots in xid_list */
7581
{
7582
	if (len == 0 || xid_list == NULL) {
7583
7584
		return(0);
7585
	}
7586
7587
	return(trx_recover_for_mysql(xid_list, len));
7588
}
7589
7590
/***********************************************************************
7591
This function is used to commit one X/Open XA distributed transaction
7592
which is in the prepared state */
7593
static
7594
int
7595
innobase_commit_by_xid(
7596
/*===================*/
7597
			/* out: 0 or error number */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
7598
        handlerton *hton __attribute__((unused)),
1 by brian
clean slate
7599
	XID*	xid)	/* in: X/Open XA transaction identification */
7600
{
7601
	trx_t*	trx;
7602
7603
	trx = trx_get_trx_by_xid(xid);
7604
7605
	if (trx) {
7606
		innobase_commit_low(trx);
7607
7608
		return(XA_OK);
7609
	} else {
7610
		return(XAER_NOTA);
7611
	}
7612
}
7613
7614
/***********************************************************************
7615
This function is used to rollback one X/Open XA distributed transaction
7616
which is in the prepared state */
7617
static
7618
int
7619
innobase_rollback_by_xid(
7620
/*=====================*/
7621
			/* out: 0 or error number */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
7622
        handlerton *hton __attribute__((unused)),
1 by brian
clean slate
7623
	XID	*xid)	/* in: X/Open XA transaction identification */
7624
{
7625
	trx_t*	trx;
7626
7627
	trx = trx_get_trx_by_xid(xid);
7628
7629
	if (trx) {
7630
		return(innobase_rollback_trx(trx));
7631
	} else {
7632
		return(XAER_NOTA);
7633
	}
7634
}
7635
7636
/***********************************************************************
7637
Create a consistent view for a cursor based on current transaction
7638
which is created if the corresponding MySQL thread still lacks one.
7639
This consistent view is then used inside of MySQL when accessing records
7640
using a cursor. */
7641
static
7642
void*
7643
innobase_create_cursor_view(
7644
/*========================*/
7645
                          /* out: pointer to cursor view or NULL */
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
7646
        handlerton *hton __attribute__((unused)), /* in: innobase hton */
1 by brian
clean slate
7647
	THD* thd)	  /* in: user thread handle */
7648
{
7649
	return(read_cursor_view_create_for_mysql(check_trx_exists(thd)));
7650
}
7651
7652
/***********************************************************************
7653
Close the given consistent cursor view of a transaction and restore
7654
global read view to a transaction read view. Transaction is created if the
7655
corresponding MySQL thread still lacks one. */
7656
static
7657
void
7658
innobase_close_cursor_view(
7659
/*=======================*/
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
7660
        handlerton *hton __attribute__((unused)),
1 by brian
clean slate
7661
	THD*	thd,	/* in: user thread handle */
7662
	void*	curview)/* in: Consistent read view to be closed */
7663
{
7664
	read_cursor_view_close_for_mysql(check_trx_exists(thd),
7665
					 (cursor_view_t*) curview);
7666
}
7667
7668
/***********************************************************************
7669
Set the given consistent cursor view to a transaction which is created
7670
if the corresponding MySQL thread still lacks one. If the given
7671
consistent cursor view is NULL global read view of a transaction is
7672
restored to a transaction read view. */
7673
static
7674
void
7675
innobase_set_cursor_view(
7676
/*=====================*/
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
7677
        handlerton *hton __attribute__((unused)),
1 by brian
clean slate
7678
	THD*	thd,	/* in: user thread handle */
7679
	void*	curview)/* in: Consistent cursor view to be set */
7680
{
7681
	read_cursor_set_for_mysql(check_trx_exists(thd),
7682
				  (cursor_view_t*) curview);
7683
}
7684
7685
7686
bool ha_innobase::check_if_incompatible_data(
7687
	HA_CREATE_INFO*	info,
7688
	uint		table_changes)
7689
{
7690
	if (table_changes != IS_EQUAL_YES) {
7691
7692
		return COMPATIBLE_DATA_NO;
7693
	}
7694
7695
	/* Check that auto_increment value was not changed */
7696
	if ((info->used_fields & HA_CREATE_USED_AUTO) &&
7697
		info->auto_increment_value != 0) {
7698
7699
		return COMPATIBLE_DATA_NO;
7700
	}
7701
7702
	/* Check that row format didn't change */
7703
	if ((info->used_fields & HA_CREATE_USED_ROW_FORMAT) &&
7704
		get_row_type() != info->row_type) {
7705
7706
		return COMPATIBLE_DATA_NO;
7707
	}
7708
7709
	return COMPATIBLE_DATA_YES;
7710
}
7711
77.1.23 by Monty Taylor
Rolled back innodb status var change.
7712
/* TODO: Fix the cast below!!! */
77.1.8 by Monty Taylor
InnoDB compiles clean. Need to send this patch upstream.
7713
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
7714
static int show_innodb_vars(THD *thd __attribute__((unused)),
7715
                            SHOW_VAR *var, char *buff __attribute__((unused)))
1 by brian
clean slate
7716
{
7717
  innodb_export_status();
7718
  var->type= SHOW_ARRAY;
7719
  var->value= (char *) &innodb_status_variables;
7720
  return 0;
7721
}
7722
77.1.56 by Monty Taylor
Fixed the warnings in ha_innodb.
7723
static st_show_var_func_container
7724
show_innodb_vars_cont = { &show_innodb_vars };
7725
1 by brian
clean slate
7726
static SHOW_VAR innodb_status_variables_export[]= {
77.1.56 by Monty Taylor
Fixed the warnings in ha_innodb.
7727
  {"Innodb",                  (char *) &show_innodb_vars_cont, SHOW_FUNC},
461 by Monty Taylor
Removed NullS. bu-bye.
7728
  {NULL, NULL, SHOW_LONG}
1 by brian
clean slate
7729
};
7730
77.1.25 by Monty Taylor
Merged from trunk.
7731
/**/
77.1.23 by Monty Taylor
Rolled back innodb status var change.
7732
77.1.8 by Monty Taylor
InnoDB compiles clean. Need to send this patch upstream.
7733
1 by brian
clean slate
7734
/* plugin options */
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7735
static DRIZZLE_SYSVAR_BOOL(checksums, innobase_use_checksums,
1 by brian
clean slate
7736
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
7737
  "Enable InnoDB checksums validation (enabled by default). "
7738
  "Disable with --skip-innodb-checksums.",
7739
  NULL, NULL, TRUE);
7740
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7741
static DRIZZLE_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
1 by brian
clean slate
7742
  PLUGIN_VAR_READONLY,
7743
  "The common part for InnoDB table spaces.",
7744
  NULL, NULL, NULL);
7745
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7746
static DRIZZLE_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
1 by brian
clean slate
7747
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
7748
  "Enable InnoDB doublewrite buffer (enabled by default). "
7749
  "Disable with --skip-innodb-doublewrite.",
7750
  NULL, NULL, TRUE);
7751
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7752
static DRIZZLE_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
1 by brian
clean slate
7753
  PLUGIN_VAR_OPCMDARG,
7754
  "Speeds up the shutdown process of the InnoDB storage engine. Possible "
7755
  "values are 0, 1 (faster)"
7756
  /*
7757
    NetWare can't close unclosed files, can't automatically kill remaining
7758
    threads, etc, so on this OS we disable the crash-like InnoDB shutdown.
7759
  */
7760
  " or 2 (fastest - crash-like)"
7761
  ".",
7762
  NULL, NULL, 1, 0, 2, 0);
7763
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7764
static DRIZZLE_SYSVAR_BOOL(file_per_table, innobase_file_per_table,
1 by brian
clean slate
7765
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
7766
  "Stores each InnoDB table to an .ibd file in the database dir.",
7767
  NULL, NULL, FALSE);
7768
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7769
static DRIZZLE_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
1 by brian
clean slate
7770
  PLUGIN_VAR_OPCMDARG,
7771
  "Set to 0 (write and flush once per second),"
7772
  " 1 (write and flush at each commit)"
7773
  " or 2 (write at commit, flush once per second).",
7774
  NULL, NULL, 1, 0, 2, 0);
7775
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7776
static DRIZZLE_SYSVAR_STR(flush_method, innobase_unix_file_flush_method,
1 by brian
clean slate
7777
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7778
  "With which method to flush data.", NULL, NULL, NULL);
7779
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7780
static DRIZZLE_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
1 by brian
clean slate
7781
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
7782
  "Force InnoDB to not use next-key locking, to use only row-level locking.",
7783
  NULL, NULL, FALSE);
7784
7785
#ifdef UNIV_LOG_ARCHIVE
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7786
static DRIZZLE_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
1 by brian
clean slate
7787
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7788
  "Where full logs should be archived.", NULL, NULL, NULL);
7789
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7790
static DRIZZLE_SYSVAR_BOOL(log_archive, innobase_log_archive,
1 by brian
clean slate
7791
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
7792
  "Set to 1 if you want to have logs archived.", NULL, NULL, FALSE);
7793
#endif /* UNIV_LOG_ARCHIVE */
7794
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7795
static DRIZZLE_SYSVAR_STR(log_group_home_dir, innobase_log_group_home_dir,
1 by brian
clean slate
7796
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7797
  "Path to InnoDB log files.", NULL, NULL, NULL);
7798
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7799
static DRIZZLE_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
1 by brian
clean slate
7800
  PLUGIN_VAR_RQCMDARG,
7801
  "Percentage of dirty pages allowed in bufferpool.",
7802
  NULL, NULL, 90, 0, 100, 0);
7803
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7804
static DRIZZLE_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
1 by brian
clean slate
7805
  PLUGIN_VAR_RQCMDARG,
7806
  "Desired maximum length of the purge queue (0 = no limit)",
365.2.8 by Monty Taylor
More MAX macros.
7807
  NULL, NULL, 0, 0, INT32_MAX, 0);
1 by brian
clean slate
7808
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7809
static DRIZZLE_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
1 by brian
clean slate
7810
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
7811
  "Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)",
7812
  NULL, NULL, FALSE);
7813
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7814
static DRIZZLE_SYSVAR_BOOL(status_file, innobase_create_status_file,
1 by brian
clean slate
7815
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
7816
  "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
7817
  NULL, NULL, FALSE);
7818
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7819
static DRIZZLE_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
1 by brian
clean slate
7820
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
7821
  "Enable statistics gathering for metadata commands such as SHOW Table STATUS (on by default)",
1 by brian
clean slate
7822
  NULL, NULL, TRUE);
7823
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7824
static DRIZZLE_SYSVAR_BOOL(use_adaptive_hash_indexes, innobase_use_adaptive_hash_indexes,
1 by brian
clean slate
7825
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
7826
  "Enable the InnoDB adaptive hash indexes (enabled by default)",
7827
  NULL, NULL, TRUE);
7828
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7829
static DRIZZLE_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size,
1 by brian
clean slate
7830
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7831
  "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
365.2.8 by Monty Taylor
More MAX macros.
7832
  NULL, NULL, 1*1024*1024L, 512*1024L, INT32_MAX, 1024);
1 by brian
clean slate
7833
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7834
static DRIZZLE_SYSVAR_ULONG(autoextend_increment, srv_auto_extend_increment,
1 by brian
clean slate
7835
  PLUGIN_VAR_RQCMDARG,
7836
  "Data file autoextend increment in megabytes",
7837
  NULL, NULL, 8L, 1L, 1000L, 0);
7838
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7839
static DRIZZLE_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
1 by brian
clean slate
7840
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7841
  "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
163 by Brian Aker
Merge Monty's code.
7842
  NULL, NULL, 8*1024*1024L, 1024*1024L, INT64_MAX, 1024*1024L);
1 by brian
clean slate
7843
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7844
static DRIZZLE_SYSVAR_ULONG(commit_concurrency, srv_commit_concurrency,
1 by brian
clean slate
7845
  PLUGIN_VAR_RQCMDARG,
7846
  "Helps in performance tuning in heavily concurrent environments.",
7847
  NULL, NULL, 0, 0, 1000, 0);
7848
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7849
static DRIZZLE_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
1 by brian
clean slate
7850
  PLUGIN_VAR_RQCMDARG,
7851
  "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
365.2.8 by Monty Taylor
More MAX macros.
7852
  NULL, NULL, 500L, 1L, INT32_MAX, 0);
1 by brian
clean slate
7853
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7854
static DRIZZLE_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
1 by brian
clean slate
7855
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7856
  "Number of file I/O threads in InnoDB.",
7857
  NULL, NULL, 4, 4, 64, 0);
7858
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7859
static DRIZZLE_SYSVAR_LONG(force_recovery, innobase_force_recovery,
1 by brian
clean slate
7860
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7861
  "Helps to save your data in case the disk image of the database becomes corrupt.",
7862
  NULL, NULL, 0, 0, 6, 0);
7863
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7864
static DRIZZLE_SYSVAR_LONG(lock_wait_timeout, innobase_lock_wait_timeout,
1 by brian
clean slate
7865
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7866
  "Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back.",
7867
  NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
7868
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7869
static DRIZZLE_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
1 by brian
clean slate
7870
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7871
  "The size of the buffer which InnoDB uses to write log to the log files on disk.",
365.2.8 by Monty Taylor
More MAX macros.
7872
  NULL, NULL, 1024*1024L, 256*1024L, INT32_MAX, 1024);
1 by brian
clean slate
7873
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7874
static DRIZZLE_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size,
1 by brian
clean slate
7875
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7876
  "Size of each log file in a log group.",
163 by Brian Aker
Merge Monty's code.
7877
  NULL, NULL, 5*1024*1024L, 1*1024*1024L, INT64_MAX, 1024*1024L);
1 by brian
clean slate
7878
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7879
static DRIZZLE_SYSVAR_LONG(log_files_in_group, innobase_log_files_in_group,
1 by brian
clean slate
7880
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7881
  "Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.",
7882
  NULL, NULL, 2, 2, 100, 0);
7883
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7884
static DRIZZLE_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups,
1 by brian
clean slate
7885
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7886
  "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
7887
  NULL, NULL, 1, 1, 10, 0);
7888
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7889
static DRIZZLE_SYSVAR_LONG(open_files, innobase_open_files,
1 by brian
clean slate
7890
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7891
  "How many files at the maximum InnoDB keeps open at the same time.",
365.2.8 by Monty Taylor
More MAX macros.
7892
  NULL, NULL, 300L, 10L, INT32_MAX, 0);
1 by brian
clean slate
7893
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7894
static DRIZZLE_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
1 by brian
clean slate
7895
  PLUGIN_VAR_RQCMDARG,
7896
  "Count of spin-loop rounds in InnoDB mutexes",
365.2.8 by Monty Taylor
More MAX macros.
7897
  NULL, NULL, 20L, 0L, INT32_MAX, 0);
1 by brian
clean slate
7898
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7899
static DRIZZLE_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
1 by brian
clean slate
7900
  PLUGIN_VAR_RQCMDARG,
7901
  "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
7902
  NULL, NULL, 8, 0, 1000, 0);
7903
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7904
static DRIZZLE_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
1 by brian
clean slate
7905
  PLUGIN_VAR_RQCMDARG,
7906
  "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep",
365.2.8 by Monty Taylor
More MAX macros.
7907
  NULL, NULL, 10000, 0, INT32_MAX, 0);
1 by brian
clean slate
7908
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7909
static DRIZZLE_SYSVAR_STR(data_file_path, innobase_data_file_path,
1 by brian
clean slate
7910
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7911
  "Path to individual files and their sizes.",
7912
  NULL, NULL, NULL);
7913
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7914
static DRIZZLE_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
1 by brian
clean slate
7915
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7916
  "The AUTOINC lock modes supported by InnoDB:\n"
7917
  "  0 => Old style AUTOINC locking (for backward compatibility)\n"
7918
  "  1 => New style AUTOINC locking\n"
7919
  "  2 => No AUTOINC locking (unsafe for SBR)",
7920
  NULL, NULL,
7921
  AUTOINC_NEW_STYLE_LOCKING,	/* Default setting */
7922
  AUTOINC_OLD_STYLE_LOCKING,	/* Minimum value */
7923
  AUTOINC_NO_LOCKING, 0);	/* Maximum value */
7924
7925
static struct st_mysql_sys_var* innobase_system_variables[]= {
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7926
  DRIZZLE_SYSVAR(additional_mem_pool_size),
7927
  DRIZZLE_SYSVAR(autoextend_increment),
7928
  DRIZZLE_SYSVAR(buffer_pool_size),
7929
  DRIZZLE_SYSVAR(checksums),
7930
  DRIZZLE_SYSVAR(commit_concurrency),
7931
  DRIZZLE_SYSVAR(concurrency_tickets),
7932
  DRIZZLE_SYSVAR(data_file_path),
7933
  DRIZZLE_SYSVAR(data_home_dir),
7934
  DRIZZLE_SYSVAR(doublewrite),
7935
  DRIZZLE_SYSVAR(fast_shutdown),
7936
  DRIZZLE_SYSVAR(file_io_threads),
7937
  DRIZZLE_SYSVAR(file_per_table),
7938
  DRIZZLE_SYSVAR(flush_log_at_trx_commit),
7939
  DRIZZLE_SYSVAR(flush_method),
7940
  DRIZZLE_SYSVAR(force_recovery),
7941
  DRIZZLE_SYSVAR(locks_unsafe_for_binlog),
7942
  DRIZZLE_SYSVAR(lock_wait_timeout),
1 by brian
clean slate
7943
#ifdef UNIV_LOG_ARCHIVE
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7944
  DRIZZLE_SYSVAR(log_arch_dir),
7945
  DRIZZLE_SYSVAR(log_archive),
1 by brian
clean slate
7946
#endif /* UNIV_LOG_ARCHIVE */
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7947
  DRIZZLE_SYSVAR(log_buffer_size),
7948
  DRIZZLE_SYSVAR(log_file_size),
7949
  DRIZZLE_SYSVAR(log_files_in_group),
7950
  DRIZZLE_SYSVAR(log_group_home_dir),
7951
  DRIZZLE_SYSVAR(max_dirty_pages_pct),
7952
  DRIZZLE_SYSVAR(max_purge_lag),
7953
  DRIZZLE_SYSVAR(mirrored_log_groups),
7954
  DRIZZLE_SYSVAR(open_files),
7955
  DRIZZLE_SYSVAR(rollback_on_timeout),
7956
  DRIZZLE_SYSVAR(stats_on_metadata),
7957
  DRIZZLE_SYSVAR(use_adaptive_hash_indexes),
7958
  DRIZZLE_SYSVAR(status_file),
7959
  DRIZZLE_SYSVAR(support_xa),
7960
  DRIZZLE_SYSVAR(sync_spin_loops),
7961
  DRIZZLE_SYSVAR(table_locks),
7962
  DRIZZLE_SYSVAR(thread_concurrency),
7963
  DRIZZLE_SYSVAR(thread_sleep_delay),
7964
  DRIZZLE_SYSVAR(autoinc_lock_mode),
1 by brian
clean slate
7965
  NULL
7966
};
7967
7968
mysql_declare_plugin(innobase)
7969
{
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
7970
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
1 by brian
clean slate
7971
  innobase_hton_name,
177.4.3 by mark
ripped out more plugin ABI and API version checking, and plugin versions are now strings
7972
  "1.0", 
1 by brian
clean slate
7973
  "Innobase OY",
7974
  "Supports transactions, row-level locking, and foreign keys",
7975
  PLUGIN_LICENSE_GPL,
7976
  innobase_init, /* Plugin Init */
224.2.3 by Brian Aker
Fix for memory leak in shutdown/restart of an engine (not fixed in 5.1)
7977
  innobase_deinit, /* Plugin Deinit */
77.1.56 by Monty Taylor
Fixed the warnings in ha_innodb.
7978
  innodb_status_variables_export,/* status variables             */
1 by brian
clean slate
7979
  innobase_system_variables, /* system variables */
7980
  NULL /* reserved */
7981
}
7982
mysql_declare_plugin_end;
7983
7984
/****************************************************************************
7985
 * DS-MRR implementation 
7986
 ***************************************************************************/
7987
7988
/**
7989
 * Multi Range Read interface, DS-MRR calls
7990
 */
7991
7992
int ha_innobase::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
482 by Brian Aker
Remove uint.
7993
                          uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
1 by brian
clean slate
7994
{
7995
  return ds_mrr.dsmrr_init(this, &table->key_info[active_index], 
7996
                           seq, seq_init_param, n_ranges, mode, buf);
7997
}
7998
7999
int ha_innobase::multi_range_read_next(char **range_info)
8000
{
8001
  return ds_mrr.dsmrr_next(this, range_info);
8002
}
8003
482 by Brian Aker
Remove uint.
8004
ha_rows ha_innobase::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
1 by brian
clean slate
8005
                                                 void *seq_init_param,  
482 by Brian Aker
Remove uint.
8006
                                                 uint32_t n_ranges, uint32_t *bufsz,
8007
                                                 uint32_t *flags, 
1 by brian
clean slate
8008
                                                 COST_VECT *cost)
8009
{
8010
  /* See comments in ha_myisam::multi_range_read_info_const */
8011
  ds_mrr.init(this, table);
8012
  return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
8013
                                 flags, cost);
8014
}
8015
482 by Brian Aker
Remove uint.
8016
int ha_innobase::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t keys,
8017
                          uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1 by brian
clean slate
8018
{
8019
  ds_mrr.init(this, table);
8020
  return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
8021
}
8022
8023
8024
8025
/**
8026
 * Index Condition Pushdown interface implementation
8027
 */
8028
398.1.9 by Monty Taylor
Cleaned up stuff out of global.h.
8029
#ifdef __cplusplus
8030
extern "C" {
8031
#endif
1 by brian
clean slate
8032
8033
/* Index condition check function to be called from within Innobase */
8034
286 by Brian Aker
Fix for Innodb bool issue.
8035
static int64_t index_cond_func_innodb(void *arg)
1 by brian
clean slate
8036
{
8037
  ha_innobase *h= (ha_innobase*)arg;
8038
  if (h->end_range) //was: h->in_range_read
8039
  {
8040
    if (h->compare_key2(h->end_range) > 0)
8041
      return 2; /* caller should return HA_ERR_END_OF_FILE already */
8042
  }
286 by Brian Aker
Fix for Innodb bool issue.
8043
  return h->pushed_idx_cond->val_int();
1 by brian
clean slate
8044
}
8045
398.1.9 by Monty Taylor
Cleaned up stuff out of global.h.
8046
#ifdef __cplusplus
8047
}
8048
#endif
8049
1 by brian
clean slate
8050
8051
482 by Brian Aker
Remove uint.
8052
Item *ha_innobase::idx_cond_push(uint32_t keyno_arg, Item* idx_cond_arg)
1 by brian
clean slate
8053
{
8054
  if (keyno_arg != primary_key)
8055
  {
8056
    pushed_idx_cond_keyno= keyno_arg;
8057
    pushed_idx_cond= idx_cond_arg;
8058
    in_range_check_pushed_down= TRUE;
8059
    return NULL; /* Table handler will check the entire condition */
8060
  }
8061
  return idx_cond_arg; /* Table handler will not make any checks */
8062
}
8063
8064
8065
int ha_innobase::read_range_first(const key_range *start_key,
8066
		 	        const key_range *end_key,
8067
			        bool eq_range_arg,
8068
                                bool sorted /* ignored */)
8069
{
8070
  int res;
8071
  //if (!eq_range_arg)
8072
    //in_range_read= TRUE;
8073
  res= handler::read_range_first(start_key, end_key, eq_range_arg, sorted);
8074
  //if (res)
8075
  //  in_range_read= FALSE;
8076
  return res;
8077
}
8078
8079
8080
int ha_innobase::read_range_next()
8081
{
8082
  int res= handler::read_range_next();
8083
  //if (res)
8084
  //  in_range_read= FALSE;
8085
  return res;
8086
}
8087