Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
9a91d46f
Commit
9a91d46f
authored
Jan 12, 2001
by
monty@donna.mysql.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updates for innobase
parent
9c80d5cb
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
398 additions
and
201 deletions
+398
-201
sql/ha_innobase.cc
sql/ha_innobase.cc
+388
-183
sql/ha_innobase.h
sql/ha_innobase.h
+10
-18
No files found.
sql/ha_innobase.cc
View file @
9a91d46f
...
...
@@ -22,102 +22,27 @@ Innobase */
/* TODO list for the Innobase handler:
- How to check for deadlocks if Innobase tables are used alongside
other MySQL table types? Should MySQL communicate the locking
information also to Innobase of any object it locks, or should
we use a timeout to detect a deadlock? Solution: there is no problem,
because MySQL requires that all table-level locks are reserved
at transaction startup (conservative locking). Deadlocks cannot
occur because of these locks.
- Innobase cmp function should call MySQL cmp for most datatypes?
Except currently for binary strings and 32-bit integers?
Solution: MySQL has conversion functions which currently convert
any datatype to a binary string which can be compared as binary
strings, except for character strings where we must identify
lower case with upper case.
other MySQL table types? Solution: we will use a timeout.
- MySQL parser should know SELECT FOR UPDATE and SELECT WITH SHARED LOCKS
for Innobase interface. We probably will make the non-locking
consistent read the default in Innobase like in Oracle.
- Does function next_same require matching of the whole last field,
or it is enough that the common prefix of the last field matches?
Answer: it is enough that the common prefix matches.
- Is the 'ref' field in handle pre-allocated to be big enough? Primary key
values can be very long! Answer: we can reallocate it to be long enough.
- DELETE FROM TABLE must not drop the table like it does now, because
consistent read will not work then! Answer: there is probably a flag
in MySQL which we can use to prevent dropping of a table in this case.
-------Oct 24, 2000
- Update trx pointers in 'prebuilt' when the transaction object of
the handle changes. Answer: in 'external_lock' we always set the pointers
to point to the trx of the current user. Note that if a user has
disconnected, then another thd at exactly the same machine address may
be created: just comparing the thd pointers does not really tell if it
actually is the same user using the handle!
- ANSI SQL specifies that if an SQL statement fails because of
an error (like duplicate key, division by zero), the whole statement
must be rolled back. Currently an error like this only rolls
back a single insert of a row, or a single row update.
-------Oct 25, 2000
- There are some autonomous threads within Innobase, like purge (= gc),
ibuf merge, and recovery threads, which may have to open tables.
Then they need type information for the table columns from MySQL.
Could they call 'openfrm' in MySQL? Then they should be properly
initialized pthreads, I presume.
-------Oct 30, 2000
- Dropping of table in Innobase fails if there is a lock set on it:
Innobase then gives an error number to MySQL but MySQL seems to drop
the table from its own data dictionary anyway, causing incoherence
between the two databases.
-------Oct 31, 2000
- In sql_table.cpp in quick_rm_table, the path has to be 'unpacked'
also after the latter sprintf to change / to \ in the path name.
between the two databases. Solution: sleep until locks have been
released.
- Innobase currently includes the path to a table name: the path should
actually be dropped off, because we may move a whole database to a new
directory.
-------Nov 1, 2000
- Ask from Monty what error codes 'record not found' and 'end of table'
exactly mean and when read and fetch operations should return them.
-------Nov 2, 2000
- Find out why in 'test-ATIS' in 'bench' directory, the client does
not seem to receive rows sent by the server: maybe Innobase does not
handle 'decimal' type correctly. Answer: Innobase did not return
'record not found' and 'end of table' with right meanings.
-------Nov 3, 2000
- 'pack' adds field length in front of string type fields: fields of
different length are not correctly alphabetically ordered.
- 'pack' removes leading (or was it, trailing) spaces from string type
fields: maybe it would be better to store them as they are, if the
field is not declared as varchar.
- MySQL 'read_last_with_key' does not allow Innobase to return
HA_ERR_KEY_NOT_FOUND, even when we try to read from an empty
table.
-------Nov 4, 2000
- MySQL should know when row id is added as uniquefier to a table for
update and delete to work.
- Innobase does not really support MySQL varchar type yet.
-------Nov 16, 2000
- We use memcpy to store float and double types to Innobase: this
makes database files not portable between big-endian and little-endian
machines.
-------Nov 17, 2000
- We added call of innobase_close_connection to THD::~THD in sql_class.cpp.
-------Nov 21, 2000
- In mysql_delete, in sql_delete.cpp, we must be able to prevent
MySQL from using generate_table to do a delete: consistent read does
not allow this. Currently, MySQL uses generate_table in DELETE FROM ...
if autocommit is on.
-------Nov 24, 2000
- Make the SELECT in an update a locking read.
- Add a deadlock error message to MySQL.
- Add 'cannot drop locked table' error message to MySQL.
-------Nov 26, 2000
- Find out why MySQL sometimes prints error message about read locks and
write locks associated with a handle.
- Find out why MySQL at shutdown prints error message 'Error on delete of
......pid (Errcode : 2).
-------Nov 30, 2000
- MySQL calls innobase_end (shutdown) before it knows that all handles
have been closed. It declares MySQL shutdown complete before Innobase
shutdown is complete.
*/
#ifdef __GNUC__
...
...
@@ -131,43 +56,50 @@ Innobase */
#include <hash.h>
#include <myisampack.h>
#include "ha_innobase.h"
/* We use the following define in univ.i to remove a conflicting definition
of type 'byte' in univ.i, different from MySQL definition */
#define INSIDE_HA_INNOBASE_CC
/* NOTE! When we include univ.i below, bool will be defined in the Innobase
way as an unsigned long int! In MySQL source code bool may be char. */
/* Include necessary Innobase headers */
extern
"C"
{
#include
<univmysql.i>
#include
<srv0start.h>
#include
<srv0srv.h>
#include
<trx0roll.h>
#include
<trx0trx.h>
#include
<row0ins.h>
#include
<row0mysql.h>
#include
<row0sel.h>
#include
<row0upd.h>
#include
<log0log.h>
#include
<dict0crea.h>
#include
<btr0cur.h>
#include
<btr0btr.h>
#include
"../innobase/include/univ.i"
#include
"../innobase/include/srv0start.h"
#include
"../innobase/include/srv0srv.h"
#include
"../innobase/include/trx0roll.h"
#include
"../innobase/include/trx0trx.h"
#include
"../innobase/include/row0ins.h"
#include
"../innobase/include/row0mysql.h"
#include
"../innobase/include/row0sel.h"
#include
"../innobase/include/row0upd.h"
#include
"../innobase/include/log0log.h"
#include
"../innobase/include/dict0crea.h"
#include
"../innobase/include/btr0cur.h"
#include
"../innobase/include/btr0btr.h"
}
#include "ha_innobase.h"
#define HA_INNOBASE_ROWS_IN_TABLE 10000
/* to get optimization right */
#define HA_INNOBASE_RANGE_COUNT 100
const
char
*
ha_innobase_ext
=
".ib"
;
bool
innobase_skip
=
0
;
mysql_bool
innobase_skip
=
0
;
uint
innobase_init_flags
=
0
;
ulong
innobase_cache_size
=
0
;
long
innobase_mirrored_log_groups
,
innobase_
mirrored_log_groups
,
long
innobase_mirrored_log_groups
,
innobase_
log_files_in_group
,
innobase_log_file_size
,
innobase_log_buffer_size
,
innobase_buffer_pool_size
,
innobase_additional_mem_pool_size
,
innobase_file_io_threads
;
char
*
innobase_data_home_dir
,
*
innobase_data_file_path
;
char
*
innobase_log_group_home_dir
,
*
innobase_log_arch_dir
;
bool
innobase_flush_log_at_trx_commit
,
innobase_log_archive
;
mysql_bool
innobase_flush_log_at_trx_commit
,
innobase_log_archive
,
innobase_use_native_aio
;
/* innobase_data_file_path=ibdata:15,idata2:1,... */
...
...
@@ -182,9 +114,9 @@ ulong innobase_select_counter = 0;
char
*
innobase_home
=
NULL
;
pthread_mutex_t
inn
b
_mutex
;
pthread_mutex_t
inn
obase
_mutex
;
static
HASH
inn
b
_open_tables
;
static
HASH
inn
obase
_open_tables
;
static
byte
*
innobase_get_key
(
INNOBASE_SHARE
*
share
,
uint
*
length
,
my_bool
not_used
__attribute__
((
unused
)));
...
...
@@ -261,12 +193,20 @@ check_trx_exists(
assert
(
thd
!=
NULL
);
trx
=
(
trx_t
*
)
thd
->
transaction
.
innobase_trx_handle
;
trx
=
(
trx_t
*
)
thd
->
transaction
.
all
.
innobase_tid
;
if
(
trx
==
NULL
)
{
trx
=
trx_allocate_for_mysql
();
thd
->
transaction
.
innobase_trx_handle
=
trx
;
thd
->
transaction
.
all
.
innobase_tid
=
trx
;
/* The execution of a single SQL statement is denoted by
a 'transaction' handle which is a NULL pointer: Innobase
remembers internally where the latest SQL statement
started, and if error handling requires rolling back the
latest statement, Innobase does a rollback to a savepoint. */
thd
->
transaction
.
stmt
.
innobase_tid
=
NULL
;
}
return
(
trx
);
...
...
@@ -298,25 +238,226 @@ ha_innobase::update_thd(
return
(
0
);
}
/*************************************************************************
Reads the data files and their sizes from a character string given in
the .cnf file. */
static
mysql_bool
innobase_parse_data_file_paths_and_sizes
(
void
)
/*==========================================*/
/* out: ((mysql_bool)TRUE) if ok,
((mysql_bool)FALSE) if parsing
error */
{
char
*
str
;
char
*
endp
;
char
*
path
;
ulint
size
;
ulint
i
=
0
;
str
=
innobase_data_file_path
;
/* First calculate the number of data files and check syntax:
path:size[M];path:size[M]... */
while
(
*
str
!=
'\0'
)
{
path
=
str
;
while
(
*
str
!=
':'
&&
*
str
!=
'\0'
)
{
str
++
;
}
if
(
*
str
==
'\0'
)
{
return
(((
mysql_bool
)
FALSE
));
}
str
++
;
size
=
strtoul
(
str
,
&
endp
,
10
);
str
=
endp
;
if
(
*
str
!=
'M'
)
{
size
=
size
/
(
1024
*
1024
);
}
else
{
str
++
;
}
if
(
size
==
0
)
{
return
(((
mysql_bool
)
FALSE
));
}
i
++
;
if
(
*
str
==
';'
)
{
str
++
;
}
else
if
(
*
str
!=
'\0'
)
{
return
(((
mysql_bool
)
FALSE
));
}
}
srv_data_file_names
=
(
char
**
)
ut_malloc
(
i
*
sizeof
(
void
*
));
srv_data_file_sizes
=
(
ulint
*
)
ut_malloc
(
i
*
sizeof
(
ulint
));
srv_n_data_files
=
i
;
/* Then store the actual values to our arrays */
str
=
innobase_data_file_path
;
i
=
0
;
while
(
*
str
!=
'\0'
)
{
path
=
str
;
while
(
*
str
!=
':'
&&
*
str
!=
'\0'
)
{
str
++
;
}
if
(
*
str
==
':'
)
{
/* Make path a null-terminated string */
*
str
=
'\0'
;
str
++
;
}
size
=
strtoul
(
str
,
&
endp
,
10
);
str
=
endp
;
if
(
*
str
!=
'M'
)
{
size
=
size
/
(
1024
*
1024
);
}
else
{
str
++
;
}
srv_data_file_names
[
i
]
=
path
;
srv_data_file_sizes
[
i
]
=
size
;
i
++
;
if
(
*
str
==
';'
)
{
str
++
;
}
}
return
(((
mysql_bool
)
TRUE
));
}
/*************************************************************************
Reads log group home directories from a character string given in
the .cnf file. */
static
mysql_bool
innobase_parse_log_group_home_dirs
(
void
)
/*====================================*/
/* out: ((mysql_bool)TRUE) if ok,
((mysql_bool)FALSE) if parsing
error */
{
char
*
str
;
char
*
path
;
ulint
i
=
0
;
str
=
innobase_log_group_home_dir
;
/* First calculate the number of directories and check syntax:
path;path;... */
while
(
*
str
!=
'\0'
)
{
path
=
str
;
while
(
*
str
!=
';'
&&
*
str
!=
'\0'
)
{
str
++
;
}
i
++
;
if
(
*
str
==
';'
)
{
str
++
;
}
else
if
(
*
str
!=
'\0'
)
{
return
(((
mysql_bool
)
FALSE
));
}
}
if
(
i
!=
(
ulint
)
innobase_mirrored_log_groups
)
{
return
(((
mysql_bool
)
FALSE
));
}
srv_log_group_home_dirs
=
(
char
**
)
ut_malloc
(
i
*
sizeof
(
void
*
));
/* Then store the actual values to our array */
str
=
innobase_log_group_home_dir
;
i
=
0
;
while
(
*
str
!=
'\0'
)
{
path
=
str
;
while
(
*
str
!=
';'
&&
*
str
!=
'\0'
)
{
str
++
;
}
if
(
*
str
==
';'
)
{
*
str
=
'\0'
;
str
++
;
}
srv_log_group_home_dirs
[
i
]
=
path
;
i
++
;
}
return
(((
mysql_bool
)
TRUE
));
}
/*************************************************************************
Opens an Innobase database. */
bool
mysql_
bool
innobase_init
(
void
)
/*===============*/
/* out:
TRUE
if error */
/* out:
((mysql_bool)TRUE)
if error */
{
int
err
;
mysql_bool
ret
;
DBUG_ENTER
(
"innobase_init"
);
if
(
!
innobase_home
)
{
innobase_home
=
mysql_real_data_home
;
/* Set Innobase initialization parameters according to the values
read from MySQL .cnf file */
printf
(
"Innobase home is %s
\n
"
,
innobase_home
);
}
srv_data_home
=
innobase_data_home_dir
;
srv_logs_home
=
""
;
srv_arch_dir
=
innobase_log_arch_dir
;
ret
=
innobase_parse_data_file_paths_and_sizes
();
if
(
ret
==
((
mysql_bool
)
FALSE
))
{
return
(((
mysql_bool
)
TRUE
));
}
ret
=
innobase_parse_log_group_home_dirs
();
if
(
ret
==
((
mysql_bool
)
FALSE
))
{
return
(((
mysql_bool
)
TRUE
));
}
srv_n_log_groups
=
(
ulint
)
innobase_mirrored_log_groups
;
srv_n_log_files
=
(
ulint
)
innobase_log_files_in_group
;
srv_log_file_size
=
(
ulint
)
innobase_log_file_size
;
srv_log_archive_on
=
(
ulint
)
innobase_log_archive
;
srv_log_buffer_size
=
(
ulint
)
innobase_log_buffer_size
;
srv_flush_log_at_trx_commit
=
(
ulint
)
innobase_flush_log_at_trx_commit
;
err
=
innobase_start_or_create_for_mysql
(
innobase_home
);
srv_use_native_aio
=
(
ulint
)
innobase_use_native_aio
;
srv_pool_size
=
(
ulint
)
innobase_buffer_pool_size
;
srv_mem_pool_size
=
(
ulint
)
innobase_additional_mem_pool_size
;
srv_n_file_io_threads
=
(
ulint
)
innobase_file_io_threads
;
err
=
innobase_start_or_create_for_mysql
();
if
(
err
!=
DB_SUCCESS
)
{
...
...
@@ -331,10 +472,10 @@ innobase_init(void)
/***********************************************************************
Closes an Innobase database. */
bool
mysql_
bool
innobase_end
(
void
)
/*==============*/
/* out:
TRUE
if error */
/* out:
((mysql_bool)TRUE)
if error */
{
int
err
;
...
...
@@ -354,12 +495,12 @@ innobase_end(void)
Flushes Innobase logs to disk and makes a checkpoint. Really, a commit
flushes logs, and the name of this function should be innobase_checkpoint. */
bool
mysql_
bool
innobase_flush_logs
(
void
)
/*=====================*/
/* out:
TRUE
if error */
/* out:
((mysql_bool)TRUE)
if error */
{
bool
result
=
0
;
mysql_
bool
result
=
0
;
DBUG_ENTER
(
"innobase_flush_logs"
);
...
...
@@ -375,8 +516,11 @@ int
innobase_commit
(
/*============*/
/* out: 0 or error number */
THD
*
thd
)
/* in: MySQL thread handle of the user for whom
THD
*
thd
,
/* in: MySQL thread handle of the user for whom
the transaction should be committed */
void
*
trx_handle
)
/* in: Innobase trx handle or NULL: NULL means
that the current SQL statement ended, and we should
mark the start of a new statement with a savepoint */
{
int
error
=
0
;
...
...
@@ -385,7 +529,13 @@ innobase_commit(
check_trx_exists
(
thd
);
trx_commit_for_mysql
((
trx_t
*
)(
thd
->
transaction
.
innobase_trx_handle
));
if
(
trx_handle
)
{
trx_commit_for_mysql
(
(
trx_t
*
)
(
thd
->
transaction
.
all
.
innobase_tid
));
}
else
{
trx_mark_sql_stat_end
(
(
trx_t
*
)
(
thd
->
transaction
.
all
.
innobase_tid
));
}
#ifndef DBUG_OFF
if
(
error
)
{
...
...
@@ -407,8 +557,11 @@ int
innobase_rollback
(
/*==============*/
/* out: 0 or error number */
THD
*
thd
)
/* in: handle to the MySQL thread of the user
THD
*
thd
,
/* in: handle to the MySQL thread of the user
whose transaction should be rolled back */
void
*
trx_handle
)
/* in: Innobase trx handle or NULL: NULL means
that the current SQL statement should be rolled
back */
{
int
error
=
0
;
...
...
@@ -417,8 +570,13 @@ innobase_rollback(
check_trx_exists
(
thd
);
error
=
trx_rollback_for_mysql
((
trx_t
*
)
(
thd
->
transaction
.
innobase_trx_handle
));
if
(
trx_handle
)
{
error
=
trx_rollback_for_mysql
(
(
trx_t
*
)
(
thd
->
transaction
.
all
.
innobase_tid
));
}
else
{
error
=
trx_rollback_last_sql_stat_for_mysql
(
(
trx_t
*
)
(
thd
->
transaction
.
all
.
innobase_tid
));
}
DBUG_RETURN
(
convert_error_code_to_mysql
(
error
));
}
...
...
@@ -434,10 +592,10 @@ innobase_close_connection(
THD
*
thd
)
/* in: handle to the MySQL thread of the user
whose transaction should be rolled back */
{
if
(
NULL
!=
thd
->
transaction
.
innobase_trx_handle
)
{
if
(
NULL
!=
thd
->
transaction
.
all
.
innobase_tid
)
{
trx_free_for_mysql
((
trx_t
*
)
(
thd
->
transaction
.
innobase_trx_handle
));
(
thd
->
transaction
.
all
.
innobase_tid
));
}
return
(
0
);
...
...
@@ -482,7 +640,7 @@ ha_innobase::open(
/* out: 1 if error, 0 if success */
const
char
*
name
,
/* in: table name */
int
mode
,
/* in: not used */
int
test_if_locked
)
/* in: not used */
u
int
test_if_locked
)
/* in: not used */
{
int
error
=
0
;
uint
buff_len
;
...
...
@@ -1042,12 +1200,14 @@ ha_innobase::store_key_val_for_row(
/******************************************************************
Convert a row in MySQL format to a row in Innobase format. Uses rec_buff
of the handle. */
static
void
ha_innobase
::
convert_row_to_innobase
(
/*====================
=============
*/
convert_row_to_innobase
(
/*====================*/
dtuple_t
*
row
,
/* in/out: row in Innobase format */
char
*
record
)
/* in: row in MySQL format */
char
*
record
,
/* in: row in MySQL format */
byte
*
rec_buff
,
/* in: record buffer */
struct
st_table
*
table
)
/* in: table in MySQL data dictionary */
{
Field
*
field
;
dfield_t
*
dfield
;
...
...
@@ -1083,12 +1243,13 @@ ha_innobase::convert_row_to_innobase(
/******************************************************************
Convert a row in Innobase format to a row in MySQL format. */
static
void
ha_innobase
::
convert_row_to_mysql
(
/*=================
=============
*/
convert_row_to_mysql
(
/*=================*/
char
*
record
,
/* in/out: row in MySQL format */
dtuple_t
*
row
)
/* in: row in Innobase format */
dtuple_t
*
row
,
/* in: row in Innobase format */
struct
st_table
*
table
)
/* in: table in MySQL data dictionary */
{
Field
*
field
;
dfield_t
*
dfield
;
...
...
@@ -1124,10 +1285,10 @@ ha_innobase::convert_row_to_mysql(
Converts a key value stored in MySQL format to an Innobase dtuple.
The last field of the key value may be just a prefix of a fixed length
field: hence the parameter key_len. */
static
dtuple_t
*
ha_innobase
::
convert_key_to_innobase
(
/*====================
=============
*/
convert_key_to_innobase
(
/*====================*/
dtuple_t
*
tuple
,
/* in/out: an Innobase dtuple which
must contain enough fields to be
able to store the key value */
...
...
@@ -1231,7 +1392,7 @@ ha_innobase::write_row(
update_auto_increment
();
}
assert
(
user_thd
->
transaction
.
innobase_trx_handle
);
assert
(
user_thd
->
transaction
.
all
.
innobase_tid
);
trx
=
check_trx_exists
(
user_thd
);
/* Convert the MySQL row into an Innobase dtuple format */
...
...
@@ -1240,7 +1401,7 @@ ha_innobase::write_row(
(
row_prebuilt_t
*
)
innobase_prebuilt
,
(
dict_table_t
*
)
innobase_table_handle
,
trx
);
convert_row_to_innobase
(
row
,
(
char
*
)
record
);
convert_row_to_innobase
(
row
,
(
char
*
)
record
,
rec_buff
,
table
);
error
=
row_insert_for_mysql
((
row_prebuilt_t
*
)
innobase_prebuilt
,
trx
);
...
...
@@ -1257,16 +1418,19 @@ ha_innobase::write_row(
/**************************************************************************
Checks which fields have changed in a row and stores information
of them to an update vector. */
static
int
ha_innobase
::
calc_row_difference
(
/*================
=============
*/
calc_row_difference
(
/*================*/
/* out: error number or 0 */
upd_t
*
uvect
,
/* in/out: update vector */
byte
*
old_row
,
/* in: old row in MySQL format */
byte
*
new_row
)
/* in: new row in MySQL format */
byte
*
new_row
,
/* in: new row in MySQL format */
struct
st_table
*
table
,
/* in: table in MySQL data dictionary */
byte
*
upd_buff
,
/* in: buffer to use */
row_prebuilt_t
*
prebuilt
,
/* in: Innobase prebuilt struct */
void
*
innobase_table_handle
)
/* in: Innobase table handle */
{
row_prebuilt_t
*
prebuilt
=
(
row_prebuilt_t
*
)
innobase_prebuilt
;
Field
*
field
;
uint
n_fields
;
ulint
o_len
;
...
...
@@ -1353,7 +1517,7 @@ ha_innobase::update_row(
DBUG_ENTER
(
"update_row"
);
assert
(
user_thd
->
transaction
.
innobase_trx_handle
);
assert
(
user_thd
->
transaction
.
all
.
innobase_tid
);
trx
=
check_trx_exists
(
user_thd
);
uvect
=
row_get_prebuilt_update_vector
(
...
...
@@ -1363,13 +1527,14 @@ ha_innobase::update_row(
/* Build old row in the Innobase format (uses rec_buff of the
handle) */
convert_row_to_innobase
(
prebuilt
->
row_tuple
,
(
char
*
)
old_row
);
convert_row_to_innobase
(
prebuilt
->
row_tuple
,
(
char
*
)
old_row
,
rec_buff
,
table
);
/* Build an update vector from the modified fields in the rows
(uses upd_buff of the handle) */
calc_row_difference
(
uvect
,
(
byte
*
)
old_row
,
new_row
);
calc_row_difference
(
uvect
,
(
byte
*
)
old_row
,
new_row
,
table
,
upd_buff
,
prebuilt
,
innobase_table_handle
);
/* This is not a delete */
prebuilt
->
upd_node
->
is_delete
=
FALSE
;
...
...
@@ -1402,7 +1567,7 @@ ha_innobase::delete_row(
DBUG_ENTER
(
"update_row"
);
assert
(
user_thd
->
transaction
.
innobase_trx_handle
);
assert
(
user_thd
->
transaction
.
all
.
innobase_tid
);
trx
=
check_trx_exists
(
user_thd
);
uvect
=
row_get_prebuilt_update_vector
(
...
...
@@ -1412,8 +1577,8 @@ ha_innobase::delete_row(
/* Build old row in the Innobase format (uses rec_buff of the
handle) */
convert_row_to_innobase
(
prebuilt
->
row_tuple
,
(
char
*
)
record
);
convert_row_to_innobase
(
prebuilt
->
row_tuple
,
(
char
*
)
record
,
rec_buff
,
table
);
/* This is a delete */
prebuilt
->
upd_node
->
is_delete
=
TRUE
;
...
...
@@ -1527,7 +1692,7 @@ ha_innobase::index_read(
/* TODO: currently we assume all reads perform consistent read! */
/* prebuilt->consistent_read = TRUE; */
assert
(
user_thd
->
transaction
.
innobase_trx_handle
);
assert
(
user_thd
->
transaction
.
all
.
innobase_tid
);
trx
=
check_trx_exists
(
user_thd
);
pcur
=
prebuilt
->
pcur
;
...
...
@@ -1538,7 +1703,7 @@ ha_innobase::index_read(
if
(
key_ptr
)
{
convert_key_to_innobase
(
prebuilt
->
search_tuple
,
key_val_buff
,
index
,
key
,
(
unsigned
char
*
)
key_ptr
,
index
,
key
,
(
byte
*
)
key_ptr
,
(
int
)
key_len
);
}
else
{
/* We position the cursor to the last or the first entry
...
...
@@ -1571,7 +1736,7 @@ ha_innobase::index_read(
trx
,
&
mtr
,
0
);
if
(
ret
==
DB_SUCCESS
)
{
convert_row_to_mysql
((
char
*
)
buf
,
prebuilt
->
row_tuple
);
convert_row_to_mysql
((
char
*
)
buf
,
prebuilt
->
row_tuple
,
table
);
error
=
0
;
table
->
status
=
0
;
...
...
@@ -1687,7 +1852,7 @@ ha_innobase::general_fetch(
ret
=
row_search_for_mysql
(
prebuilt
->
row_tuple
,
0
,
prebuilt
,
match_mode
,
trx
,
&
mtr
,
direction
);
if
(
ret
==
DB_SUCCESS
)
{
convert_row_to_mysql
((
char
*
)
buf
,
prebuilt
->
row_tuple
);
convert_row_to_mysql
((
char
*
)
buf
,
prebuilt
->
row_tuple
,
table
);
error
=
0
;
table
->
status
=
0
;
...
...
@@ -1814,7 +1979,7 @@ int
ha_innobase
::
rnd_init
(
/*==================*/
/* out: 0 or error number */
bool
scan
)
/* in: ???????? */
mysql_
bool
scan
)
/* in: ???????? */
{
row_prebuilt_t
*
prebuilt
=
(
row_prebuilt_t
*
)
innobase_prebuilt
;
...
...
@@ -1931,7 +2096,8 @@ ha_innobase::info(
}
else
if
(
flag
&
HA_STATUS_ERRKEY
)
{
errkey
=
-
1
;
/* TODO: get the key number from Innobase */
errkey
=
(
unsigned
int
)
-
1
;
/* TODO: get the key number from
Innobase */
}
DBUG_VOID_RETURN
;
...
...
@@ -1948,9 +2114,12 @@ int ha_innobase::reset(void)
}
/**********************************************************************
As MySQL will execute an external lock for every new table it uses
we can use this to store the pointer to the THD in the handle. We use this
also in explicit locking of tables by request of the user. */
As MySQL will execute an external lock for every new table it uses when it
starts to process an SQL statement, we can use this function to store the
pointer to the THD in the handle. We will also use this function to communicate
to Innobase that a new SQL statement has started and that we must store a
savepoint to our transaction handle, so that we are able to roll back
the SQL statement in case of an error. */
int
ha_innobase
::
external_lock
(
...
...
@@ -1958,30 +2127,65 @@ ha_innobase::external_lock(
THD
*
thd
,
/* in: handle to the user thread */
int
lock_type
)
/* in: lock type */
{
int
error
=
0
;
row_prebuilt_t
*
prebuilt
=
(
row_prebuilt_t
*
)
innobase_prebuilt
;
int
error
=
0
;
trx_t
*
trx
;
DBUG_ENTER
(
"ha_innobase::external_lock"
);
update_thd
(
thd
);
prebuilt
->
sql_stat_start
=
TRUE
;
trx
=
check_trx_exists
(
thd
);
if
(
lock_type
!=
F_UNLCK
)
{
if
(
trx
->
n_mysql_tables_in_use
==
0
)
{
trx_mark_sql_stat_end
(
trx
);
}
trx
->
n_mysql_tables_in_use
++
;
}
else
{
trx
->
n_mysql_tables_in_use
--
;
}
DBUG_RETURN
(
error
);
}
/* Currently, the following does nothing in Innobase: */
THR_LOCK_DATA
**
ha_innobase
::
store_lock
(
THD
*
thd
,
THR_LOCK_DATA
**
to
,
enum
thr_lock_type
lock_type
)
{
if
(
lock_type
!=
TL_IGNORE
&&
lock
.
type
==
TL_UNLOCK
)
{
/* If we are not doing a LOCK TABLE, then allow multiple writers */
if
((
lock_type
>=
TL_WRITE_CONCURRENT_INSERT
&&
lock_type
<=
TL_WRITE
)
&&
!
thd
->
in_lock_tables
)
lock_type
=
TL_WRITE_ALLOW_WRITE
;
lock
.
type
=
lock_type
;
}
*
to
++=
&
lock
;
return
(
to
);
/*********************************************************************
Stores a MySQL lock into a 'lock' field in a handle. */
THR_LOCK_DATA
**
ha_innobase
::
store_lock
(
/*====================*/
/* out: pointer to the next
element in the 'to' array */
THD
*
thd
,
/* in: user thread handle */
THR_LOCK_DATA
**
to
,
/* in: pointer to an array
of pointers to lock structs;
pointer to the 'lock' field
of current handle is stored
next to this array */
enum
thr_lock_type
lock_type
)
/* in: lock type to store in
'lock' */
{
if
(
lock_type
!=
TL_IGNORE
&&
lock
.
type
==
TL_UNLOCK
)
{
/* If we are not doing a LOCK TABLE, then allow multiple
writers */
if
((
lock_type
>=
TL_WRITE_CONCURRENT_INSERT
&&
lock_type
<=
TL_WRITE
)
&&
!
thd
->
in_lock_tables
)
{
lock_type
=
TL_WRITE_ALLOW_WRITE
;
}
lock
.
type
=
lock_type
;
}
*
to
++=
&
lock
;
return
(
to
);
}
/*********************************************************************
...
...
@@ -2206,15 +2410,17 @@ ha_innobase::create(
}
/*********************************************************************
Drops a table from an Innobase database. No one is allowed to have
locks on the table, not even the calling user when the table is
dropped. */
Drops a table from an Innobase database. Before calling this function,
MySQL calls innobase_commit to commit the transaction of the current user.
Then the current user cannot have locks set on the table. Drop table
operation inside Innobase will wait sleeping in a loop until no other
user has locks on the table. */
int
ha_innobase
::
delete_table
(
/*======================*/
/* out: error number */
const
char
*
name
)
/* in: table name */
/* out: error number */
const
char
*
name
)
/* in: table name */
{
ulint
name_len
;
int
error
;
...
...
@@ -2340,10 +2546,10 @@ ha_innobase::records_in_range(
byte
*
key_val_buff2
=
(
byte
*
)
my_malloc
(
table
->
reclength
,
MYF
(
MY_WME
));
dtuple_t
*
range_end
;
mem_heap_t
*
heap
;
ulint
n_rows
;
ulint
mode1
;
ulint
mode2
;
void
*
heap
;
DBUG_ENTER
(
"records_in_range"
);
...
...
@@ -2363,9 +2569,7 @@ ha_innobase::records_in_range(
/* For the second key value we have to use allocated buffers: */
heap
=
mem_heap_create
(
100
);
range_end
=
dtuple_create
(
heap
,
key
->
key_parts
);
range_end
=
dtuple_create_for_mysql
(
&
heap
,
key
->
key_parts
);
convert_key_to_innobase
(
range_end
,
key_val_buff2
,
index
,
key
,
(
byte
*
)
end_key
,
(
int
)
end_key_len
);
...
...
@@ -2375,7 +2579,7 @@ ha_innobase::records_in_range(
n_rows
=
btr_estimate_n_rows_in_range
(
index
,
prebuilt
->
search_tuple
,
mode1
,
range_end
,
mode2
);
mem_heap_free
(
heap
);
dtuple_free_for_mysql
(
heap
);
my_free
((
char
*
)
key_val_buff2
,
MYF
(
0
));
DBUG_RETURN
((
ha_rows
)
n_rows
);
...
...
@@ -2398,7 +2602,8 @@ static INNOBASE_SHARE *get_share(const char *table_name)
INNOBASE_SHARE
*
share
;
pthread_mutex_lock
(
&
innobase_mutex
);
uint
length
=
(
uint
)
strlen
(
table_name
);
if
(
!
(
share
=
(
INNOBASE_SHARE
*
)
hash_search
(
&
innobase_open_tables
,
table_name
,
if
(
!
(
share
=
(
INNOBASE_SHARE
*
)
hash_search
(
&
innobase_open_tables
,
(
byte
*
)
table_name
,
length
)))
{
if
((
share
=
(
INNOBASE_SHARE
*
)
my_malloc
(
sizeof
(
*
share
)
+
length
+
1
,
...
...
@@ -2407,7 +2612,7 @@ static INNOBASE_SHARE *get_share(const char *table_name)
share
->
table_name_length
=
length
;
share
->
table_name
=
(
char
*
)
(
share
+
1
);
strmov
(
share
->
table_name
,
table_name
);
if
(
hash_insert
(
&
innobase_open_tables
,
(
char
*
)
share
))
if
(
hash_insert
(
&
innobase_open_tables
,
(
byte
*
)
share
))
{
pthread_mutex_unlock
(
&
innobase_mutex
);
my_free
((
gptr
)
share
,
0
);
...
...
@@ -2427,7 +2632,7 @@ static void free_share(INNOBASE_SHARE *share)
pthread_mutex_lock
(
&
innobase_mutex
);
if
(
!--
share
->
use_count
)
{
hash_delete
(
&
innobase_open_tables
,
(
gptr
)
share
);
hash_delete
(
&
innobase_open_tables
,
(
byte
*
)
share
);
thr_lock_delete
(
&
share
->
lock
);
pthread_mutex_destroy
(
&
share
->
mutex
);
my_free
((
gptr
)
share
,
MYF
(
0
));
...
...
sql/ha_innobase.h
View file @
9a91d46f
...
...
@@ -21,15 +21,13 @@
#pragma interface
/* gcc class implementation */
#endif
/* Store the MySQL bool type definition to this defined type:
inside ha_innobase we use the Innobase definition of the bool type! */
typedef
bool
mysql_bool
;
/* This file defines the Innobase handler: the interface between MySQL and
Innobase */
extern
"C"
{
#include <data0types.h>
#include <dict0types.h>
#include <row0types.h>
}
typedef
struct
st_innobase_share
{
THR_LOCK
lock
;
pthread_mutex_t
mutex
;
...
...
@@ -73,12 +71,6 @@ class ha_innobase: public handler
ulong
max_row_length
(
const
byte
*
buf
);
uint
store_key_val_for_row
(
uint
keynr
,
char
*
buff
,
const
byte
*
record
);
void
convert_row_to_innobase
(
dtuple_t
*
row
,
char
*
record
);
void
convert_row_to_mysql
(
char
*
record
,
dtuple_t
*
row
);
dtuple_t
*
convert_key_to_innobase
(
dtuple_t
*
tuple
,
byte
*
buf
,
dict_index_t
*
index
,
KEY
*
key
,
byte
*
key_ptr
,
int
key_len
);
int
calc_row_difference
(
upd_t
*
uvect
,
byte
*
old_row
,
byte
*
new_row
);
int
update_thd
(
THD
*
thd
);
int
change_active_index
(
uint
keynr
);
int
general_fetch
(
byte
*
buf
,
uint
direction
,
uint
match_mode
);
...
...
@@ -110,7 +102,7 @@ class ha_innobase: public handler
bool
fast_key_read
()
{
return
1
;}
bool
has_transactions
()
{
return
1
;}
int
open
(
const
char
*
name
,
int
mode
,
int
test_if_locked
);
int
open
(
const
char
*
name
,
int
mode
,
u
int
test_if_locked
);
void
initialize
(
void
);
int
close
(
void
);
double
scan_time
();
...
...
@@ -162,13 +154,14 @@ extern uint innobase_init_flags, innobase_lock_type;
extern
ulong
innobase_cache_size
;
extern
char
*
innobase_home
,
*
innobase_tmpdir
,
*
innobase_logdir
;
extern
long
innobase_lock_scan_time
;
extern
long
innobase_mirrored_log_groups
,
innobase_
mirrored_log_groups
;
extern
long
innobase_mirrored_log_groups
,
innobase_
log_files_in_group
;
extern
long
innobase_log_file_size
,
innobase_log_buffer_size
;
extern
long
innobase_buffer_pool_size
,
innobase_additional_mem_pool_size
;
extern
long
innobase_file_io_threads
;
extern
char
*
innobase_data_home_dir
,
*
innobase_data_file_path
;
extern
char
*
innobase_log_group_home_dir
,
*
innobase_log_arch_dir
;
extern
bool
innobase_flush_log_at_trx_commit
,
innobase_log_archive
;
extern
bool
innobase_flush_log_at_trx_commit
,
innobase_log_archive
,
innobase_use_native_aio
;
extern
TYPELIB
innobase_lock_typelib
;
...
...
@@ -176,7 +169,6 @@ bool innobase_init(void);
bool
innobase_end
(
void
);
bool
innobase_flush_logs
(
void
);
int
innobase_commit
(
THD
*
thd
);
int
innobase_rollback
(
THD
*
thd
);
int
innobase_commit
(
THD
*
thd
,
void
*
trx_handle
);
int
innobase_rollback
(
THD
*
thd
,
void
*
trx_handle
);
int
innobase_close_connection
(
THD
*
thd
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment