676
676
{"buffer_pool_read_requests",
677
677
(char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG},
678
678
{"buffer_pool_reads",
679
(char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG},
679
(char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG},
680
680
{"buffer_pool_wait_free",
681
(char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG},
681
(char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG},
682
682
{"buffer_pool_write_requests",
683
683
(char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
685
(char*) &export_vars.innodb_data_fsyncs, SHOW_LONG},
685
(char*) &export_vars.innodb_data_fsyncs, SHOW_LONG},
686
686
{"data_pending_fsyncs",
687
(char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG},
687
(char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG},
688
688
{"data_pending_reads",
689
(char*) &export_vars.innodb_data_pending_reads, SHOW_LONG},
689
(char*) &export_vars.innodb_data_pending_reads, SHOW_LONG},
690
690
{"data_pending_writes",
691
(char*) &export_vars.innodb_data_pending_writes, SHOW_LONG},
691
(char*) &export_vars.innodb_data_pending_writes, SHOW_LONG},
693
(char*) &export_vars.innodb_data_read, SHOW_LONG},
693
(char*) &export_vars.innodb_data_read, SHOW_LONG},
695
(char*) &export_vars.innodb_data_reads, SHOW_LONG},
695
(char*) &export_vars.innodb_data_reads, SHOW_LONG},
697
(char*) &export_vars.innodb_data_writes, SHOW_LONG},
697
(char*) &export_vars.innodb_data_writes, SHOW_LONG},
699
(char*) &export_vars.innodb_data_written, SHOW_LONG},
699
(char*) &export_vars.innodb_data_written, SHOW_LONG},
700
700
{"dblwr_pages_written",
701
(char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
701
(char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
703
(char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
703
(char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
704
704
{"have_atomic_builtins",
705
(char*) &export_vars.innodb_have_atomic_builtins, SHOW_BOOL},
705
(char*) &export_vars.innodb_have_atomic_builtins, SHOW_BOOL},
707
(char*) &export_vars.innodb_log_waits, SHOW_LONG},
707
(char*) &export_vars.innodb_log_waits, SHOW_LONG},
708
708
{"log_write_requests",
709
(char*) &export_vars.innodb_log_write_requests, SHOW_LONG},
709
(char*) &export_vars.innodb_log_write_requests, SHOW_LONG},
711
(char*) &export_vars.innodb_log_writes, SHOW_LONG},
711
(char*) &export_vars.innodb_log_writes, SHOW_LONG},
712
712
{"os_log_fsyncs",
713
(char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG},
713
(char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG},
714
714
{"os_log_pending_fsyncs",
715
(char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG},
715
(char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG},
716
716
{"os_log_pending_writes",
717
(char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG},
717
(char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG},
718
718
{"os_log_written",
719
(char*) &export_vars.innodb_os_log_written, SHOW_LONG},
719
(char*) &export_vars.innodb_os_log_written, SHOW_LONG},
721
(char*) &export_vars.innodb_page_size, SHOW_LONG},
721
(char*) &export_vars.innodb_page_size, SHOW_LONG},
722
722
{"pages_created",
723
(char*) &export_vars.innodb_pages_created, SHOW_LONG},
723
(char*) &export_vars.innodb_pages_created, SHOW_LONG},
725
(char*) &export_vars.innodb_pages_read, SHOW_LONG},
725
(char*) &export_vars.innodb_pages_read, SHOW_LONG},
726
726
{"pages_written",
727
(char*) &export_vars.innodb_pages_written, SHOW_LONG},
727
(char*) &export_vars.innodb_pages_written, SHOW_LONG},
728
728
{"row_lock_current_waits",
729
(char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG},
729
(char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG},
730
730
{"row_lock_time",
731
(char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG},
731
(char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG},
732
732
{"row_lock_time_avg",
733
(char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG},
733
(char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG},
734
734
{"row_lock_time_max",
735
(char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG},
735
(char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG},
736
736
{"row_lock_waits",
737
(char*) &export_vars.innodb_row_lock_waits, SHOW_LONG},
737
(char*) &export_vars.innodb_row_lock_waits, SHOW_LONG},
739
(char*) &export_vars.innodb_rows_deleted, SHOW_LONG},
739
(char*) &export_vars.innodb_rows_deleted, SHOW_LONG},
740
740
{"rows_inserted",
741
(char*) &export_vars.innodb_rows_inserted, SHOW_LONG},
741
(char*) &export_vars.innodb_rows_inserted, SHOW_LONG},
743
(char*) &export_vars.innodb_rows_read, SHOW_LONG},
743
(char*) &export_vars.innodb_rows_read, SHOW_LONG},
745
(char*) &export_vars.innodb_rows_updated, SHOW_LONG},
745
(char*) &export_vars.innodb_rows_updated, SHOW_LONG},
746
746
{NULL, NULL, SHOW_LONG}
979
979
innobase_active_small(void)
980
980
/*=======================*/
982
innobase_active_counter++;
982
innobase_active_counter++;
984
if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
985
srv_active_wake_master_thread();
984
if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
985
srv_active_wake_master_thread();
989
989
/********************************************************************//**
990
990
Converts an InnoDB error code to a MySQL error code and also tells to MySQL
991
991
about a possible transaction rollback inside InnoDB caused by a lock wait
992
992
timeout or a deadlock.
993
@return MySQL error code */
993
@return MySQL error code */
994
994
extern "C" UNIV_INTERN
996
996
convert_error_code_to_mysql(
997
997
/*========================*/
998
int error, /*!< in: InnoDB error code */
999
ulint flags, /*!< in: InnoDB table flags, or 0 */
1000
Session* session)/*!< in: user thread handle or NULL */
998
int error, /*!< in: InnoDB error code */
999
ulint flags, /*!< in: InnoDB table flags, or 0 */
1000
Session* session)/*!< in: user thread handle or NULL */
1008
return(-1); /* unspecified error */
1010
case DB_DUPLICATE_KEY:
1011
return(HA_ERR_FOUND_DUPP_KEY);
1013
case DB_FOREIGN_DUPLICATE_KEY:
1014
return(HA_ERR_FOREIGN_DUPLICATE_KEY);
1016
case DB_MISSING_HISTORY:
1017
return(HA_ERR_TABLE_DEF_CHANGED);
1019
case DB_RECORD_NOT_FOUND:
1020
return(HA_ERR_NO_ACTIVE_RECORD);
1023
/* Since we rolled back the whole transaction, we must
1024
tell it also to MySQL so that MySQL knows to empty the
1025
cached binlog for this transaction */
1008
return(-1); /* unspecified error */
1010
case DB_DUPLICATE_KEY:
1011
return(HA_ERR_FOUND_DUPP_KEY);
1013
case DB_FOREIGN_DUPLICATE_KEY:
1014
return(HA_ERR_FOREIGN_DUPLICATE_KEY);
1016
case DB_MISSING_HISTORY:
1017
return(HA_ERR_TABLE_DEF_CHANGED);
1019
case DB_RECORD_NOT_FOUND:
1020
return(HA_ERR_NO_ACTIVE_RECORD);
1023
/* Since we rolled back the whole transaction, we must
1024
tell it also to MySQL so that MySQL knows to empty the
1025
cached binlog for this transaction */
1027
1027
session_mark_transaction_to_rollback(session, TRUE);
1029
return(HA_ERR_LOCK_DEADLOCK);
1029
return(HA_ERR_LOCK_DEADLOCK);
1031
case DB_LOCK_WAIT_TIMEOUT:
1032
/* Starting from 5.0.13, we let MySQL just roll back the
1033
latest SQL statement in a lock wait timeout. Previously, we
1034
rolled back the whole transaction. */
1031
case DB_LOCK_WAIT_TIMEOUT:
1032
/* Starting from 5.0.13, we let MySQL just roll back the
1033
latest SQL statement in a lock wait timeout. Previously, we
1034
rolled back the whole transaction. */
1036
1036
session_mark_transaction_to_rollback(session,
1037
1037
(bool)row_rollback_on_timeout);
1039
return(HA_ERR_LOCK_WAIT_TIMEOUT);
1041
case DB_NO_REFERENCED_ROW:
1042
return(HA_ERR_NO_REFERENCED_ROW);
1044
case DB_ROW_IS_REFERENCED:
1045
return(HA_ERR_ROW_IS_REFERENCED);
1047
case DB_CANNOT_ADD_CONSTRAINT:
1048
return(HA_ERR_CANNOT_ADD_FOREIGN);
1050
case DB_CANNOT_DROP_CONSTRAINT:
1052
return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
1053
misleading, a new MySQL error
1054
code should be introduced */
1056
case DB_COL_APPEARS_TWICE_IN_INDEX:
1058
return(HA_ERR_CRASHED);
1060
case DB_OUT_OF_FILE_SPACE:
1061
return(HA_ERR_RECORD_FILE_FULL);
1063
case DB_TABLE_IS_BEING_USED:
1064
return(HA_ERR_WRONG_COMMAND);
1066
case DB_TABLE_NOT_FOUND:
1067
return(HA_ERR_NO_SUCH_TABLE);
1069
case DB_TOO_BIG_RECORD:
1070
my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
1071
page_get_free_space_of_empty(flags
1072
& DICT_TF_COMPACT) / 2);
1073
return(HA_ERR_TO_BIG_ROW);
1075
case DB_NO_SAVEPOINT:
1076
return(HA_ERR_NO_SAVEPOINT);
1078
case DB_LOCK_TABLE_FULL:
1079
/* Since we rolled back the whole transaction, we must
1080
tell it also to MySQL so that MySQL knows to empty the
1081
cached binlog for this transaction */
1083
session_mark_transaction_to_rollback(session, TRUE);
1085
return(HA_ERR_LOCK_TABLE_FULL);
1087
case DB_PRIMARY_KEY_IS_NULL:
1088
return(ER_PRIMARY_CANT_HAVE_NULL);
1090
case DB_TOO_MANY_CONCURRENT_TRXS:
1092
/* Once MySQL add the appropriate code to errmsg.txt then
1093
we can get rid of this #ifdef. NOTE: The code checked by
1094
the #ifdef is the suggested name for the error condition
1095
and the actual error code name could very well be different.
1096
This will require some monitoring, ie. the status
1097
of this request on our part.*/
1039
return(HA_ERR_LOCK_WAIT_TIMEOUT);
1041
case DB_NO_REFERENCED_ROW:
1042
return(HA_ERR_NO_REFERENCED_ROW);
1044
case DB_ROW_IS_REFERENCED:
1045
return(HA_ERR_ROW_IS_REFERENCED);
1047
case DB_CANNOT_ADD_CONSTRAINT:
1048
return(HA_ERR_CANNOT_ADD_FOREIGN);
1050
case DB_CANNOT_DROP_CONSTRAINT:
1052
return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
1053
misleading, a new MySQL error
1054
code should be introduced */
1056
case DB_COL_APPEARS_TWICE_IN_INDEX:
1058
return(HA_ERR_CRASHED);
1060
case DB_OUT_OF_FILE_SPACE:
1061
return(HA_ERR_RECORD_FILE_FULL);
1063
case DB_TABLE_IS_BEING_USED:
1064
return(HA_ERR_WRONG_COMMAND);
1066
case DB_TABLE_NOT_FOUND:
1067
return(HA_ERR_NO_SUCH_TABLE);
1069
case DB_TOO_BIG_RECORD:
1070
my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
1071
page_get_free_space_of_empty(flags
1072
& DICT_TF_COMPACT) / 2);
1073
return(HA_ERR_TO_BIG_ROW);
1075
case DB_NO_SAVEPOINT:
1076
return(HA_ERR_NO_SAVEPOINT);
1078
case DB_LOCK_TABLE_FULL:
1079
/* Since we rolled back the whole transaction, we must
1080
tell it also to MySQL so that MySQL knows to empty the
1081
cached binlog for this transaction */
1083
session_mark_transaction_to_rollback(session, TRUE);
1085
return(HA_ERR_LOCK_TABLE_FULL);
1087
case DB_PRIMARY_KEY_IS_NULL:
1088
return(ER_PRIMARY_CANT_HAVE_NULL);
1090
case DB_TOO_MANY_CONCURRENT_TRXS:
1092
/* Once MySQL add the appropriate code to errmsg.txt then
1093
we can get rid of this #ifdef. NOTE: The code checked by
1094
the #ifdef is the suggested name for the error condition
1095
and the actual error code name could very well be different.
1096
This will require some monitoring, ie. the status
1097
of this request on our part.*/
1098
1098
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
1099
return(ER_TOO_MANY_CONCURRENT_TRXS);
1099
return(ER_TOO_MANY_CONCURRENT_TRXS);
1101
return(HA_ERR_RECORD_FILE_FULL);
1101
return(HA_ERR_RECORD_FILE_FULL);
1103
case DB_UNSUPPORTED:
1104
return(HA_ERR_UNSUPPORTED);
1103
case DB_UNSUPPORTED:
1104
return(HA_ERR_UNSUPPORTED);
1108
1108
/*************************************************************//**
1285
unsigned long); /*!< in: OS error value */
1285
unsigned long); /*!< in: OS error value */
1287
1287
/*********************************************************************//**
1288
1288
Creates a temporary file.
1289
@return temporary file descriptor, or < 0 on error */
1289
@return temporary file descriptor, or < 0 on error */
1290
1290
extern "C" UNIV_INTERN
1292
1292
innobase_mysql_tmpfile(void)
1293
1293
/*========================*/
1295
int fd; /* handle of opened file */
1296
HANDLE osfh; /* OS handle of opened file */
1297
char* tmpdir; /* point to the directory
1298
where to create file */
1299
TCHAR path_buf[MAX_PATH - 14]; /* buffer for tmp file path.
1300
The length cannot be longer
1301
than MAX_PATH - 14, or
1302
GetTempFileName will fail. */
1303
char filename[MAX_PATH]; /* name of the tmpfile */
1304
DWORD fileaccess = GENERIC_READ /* OS file access */
1307
DWORD fileshare = FILE_SHARE_READ /* OS file sharing mode */
1309
| FILE_SHARE_DELETE;
1310
DWORD filecreate = CREATE_ALWAYS; /* OS method of open/create */
1311
DWORD fileattrib = /* OS file attribute flags */
1312
FILE_ATTRIBUTE_NORMAL
1313
| FILE_FLAG_DELETE_ON_CLOSE
1314
| FILE_ATTRIBUTE_TEMPORARY
1315
| FILE_FLAG_SEQUENTIAL_SCAN;
1317
tmpdir = my_tmpdir(&mysql_tmpdir_list);
1319
/* The tmpdir parameter can not be NULL for GetTempFileName. */
1323
/* Use GetTempPath to determine path for temporary files. */
1324
ret = GetTempPath(sizeof(path_buf), path_buf);
1325
if (ret > sizeof(path_buf) || (ret == 0)) {
1327
_dosmaperr(GetLastError()); /* map error */
1334
/* Use GetTempFileName to generate a unique filename. */
1335
if (!GetTempFileName(tmpdir, "ib", 0, filename)) {
1337
_dosmaperr(GetLastError()); /* map error */
1341
/* Open/Create the file. */
1342
osfh = CreateFile(filename, fileaccess, fileshare, NULL,
1343
filecreate, fileattrib, NULL);
1344
if (osfh == INVALID_HANDLE_VALUE) {
1346
/* open/create file failed! */
1347
_dosmaperr(GetLastError()); /* map error */
1352
/* Associates a CRT file descriptor with the OS file handle. */
1353
fd = _open_osfhandle((intptr_t) osfh, 0);
1354
} while (fd == -1 && errno == EINTR);
1357
/* Open failed, close the file handle. */
1359
_dosmaperr(GetLastError()); /* map error */
1360
CloseHandle(osfh); /* no need to check if
1361
CloseHandle fails */
1295
int fd; /* handle of opened file */
1296
HANDLE osfh; /* OS handle of opened file */
1297
char* tmpdir; /* point to the directory
1298
where to create file */
1299
TCHAR path_buf[MAX_PATH - 14]; /* buffer for tmp file path.
1300
The length cannot be longer
1301
than MAX_PATH - 14, or
1302
GetTempFileName will fail. */
1303
char filename[MAX_PATH]; /* name of the tmpfile */
1304
DWORD fileaccess = GENERIC_READ /* OS file access */
1307
DWORD fileshare = FILE_SHARE_READ /* OS file sharing mode */
1309
| FILE_SHARE_DELETE;
1310
DWORD filecreate = CREATE_ALWAYS; /* OS method of open/create */
1311
DWORD fileattrib = /* OS file attribute flags */
1312
FILE_ATTRIBUTE_NORMAL
1313
| FILE_FLAG_DELETE_ON_CLOSE
1314
| FILE_ATTRIBUTE_TEMPORARY
1315
| FILE_FLAG_SEQUENTIAL_SCAN;
1317
tmpdir = my_tmpdir(&mysql_tmpdir_list);
1319
/* The tmpdir parameter can not be NULL for GetTempFileName. */
1323
/* Use GetTempPath to determine path for temporary files. */
1324
ret = GetTempPath(sizeof(path_buf), path_buf);
1325
if (ret > sizeof(path_buf) || (ret == 0)) {
1327
_dosmaperr(GetLastError()); /* map error */
1334
/* Use GetTempFileName to generate a unique filename. */
1335
if (!GetTempFileName(tmpdir, "ib", 0, filename)) {
1337
_dosmaperr(GetLastError()); /* map error */
1341
/* Open/Create the file. */
1342
osfh = CreateFile(filename, fileaccess, fileshare, NULL,
1343
filecreate, fileattrib, NULL);
1344
if (osfh == INVALID_HANDLE_VALUE) {
1346
/* open/create file failed! */
1347
_dosmaperr(GetLastError()); /* map error */
1352
/* Associates a CRT file descriptor with the OS file handle. */
1353
fd = _open_osfhandle((intptr_t) osfh, 0);
1354
} while (fd == -1 && errno == EINTR);
1357
/* Open failed, close the file handle. */
1359
_dosmaperr(GetLastError()); /* map error */
1360
CloseHandle(osfh); /* no need to check if
1361
CloseHandle fails */
1367
1367
/*********************************************************************//**
1368
1368
Creates a temporary file.
1369
@return temporary file descriptor, or < 0 on error */
1369
@return temporary file descriptor, or < 0 on error */
1370
1370
extern "C" UNIV_INTERN
1372
1372
innobase_mysql_tmpfile(void)
1373
1373
/*========================*/
1376
int fd = mysql_tmpfile("ib");
1378
/* Copy the file descriptor, so that the additional resources
1379
allocated by create_temp_file() can be freed by invoking
1380
internal::my_close().
1376
int fd = mysql_tmpfile("ib");
1378
/* Copy the file descriptor, so that the additional resources
1379
allocated by create_temp_file() can be freed by invoking
1380
internal::my_close().
1382
Because the file descriptor returned by this function
1383
will be passed to fdopen(), it will be closed by invoking
1384
fclose(), which in turn will invoke close() instead of
1385
internal::my_close(). */
1389
my_error(EE_OUT_OF_FILERESOURCES,
1390
MYF(ME_BELL+ME_WAITTANG),
1393
internal::my_close(fd, MYF(MY_WME));
1382
Because the file descriptor returned by this function
1383
will be passed to fdopen(), it will be closed by invoking
1384
fclose(), which in turn will invoke close() instead of
1385
internal::my_close(). */
1389
my_error(EE_OUT_OF_FILERESOURCES,
1390
MYF(ME_BELL+ME_WAITTANG),
1393
internal::my_close(fd, MYF(MY_WME));
1397
1397
#endif /* defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) */
1628
1628
ha_innobase::update_session()
1629
1629
/*=====================*/
1631
Session* session = ha_session();
1632
ut_ad(EQ_CURRENT_SESSION(session));
1633
update_session(session);
1631
Session* session = ha_session();
1632
ut_ad(EQ_CURRENT_SESSION(session));
1633
update_session(session);
1636
1636
/*****************************************************************//**
1637
1637
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
1638
1638
and quote it if needed.
1639
@return pointer to the end of buf */
1639
@return pointer to the end of buf */
1642
1642
innobase_convert_identifier(
1643
1643
/*========================*/
1644
char* buf, /*!< out: buffer for converted identifier */
1645
ulint buflen, /*!< in: length of buf, in bytes */
1646
const char* id, /*!< in: identifier to convert */
1647
ulint idlen, /*!< in: length of id, in bytes */
1648
void* session,/*!< in: MySQL connection thread, or NULL */
1649
ibool file_id)/*!< in: TRUE=id is a table or database name;
1650
FALSE=id is an UTF-8 string */
1644
char* buf, /*!< out: buffer for converted identifier */
1645
ulint buflen, /*!< in: length of buf, in bytes */
1646
const char* id, /*!< in: identifier to convert */
1647
ulint idlen, /*!< in: length of id, in bytes */
1648
void* session,/*!< in: MySQL connection thread, or NULL */
1649
ibool file_id)/*!< in: TRUE=id is a table or database name;
1650
FALSE=id is an UTF-8 string */
1652
char nz[NAME_LEN + 1];
1653
char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
1659
/* Decode the table name. The filename_to_tablename()
1660
function expects a NUL-terminated string. The input and
1661
output strings buffers must not be shared. */
1663
if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
1664
idlen = (sizeof nz) - 1;
1667
memcpy(nz, id, idlen);
1671
idlen = filename_to_tablename(nz, nz2, sizeof nz2);
1674
/* See if the identifier needs to be quoted. */
1675
if (UNIV_UNLIKELY(!session)) {
1678
q = get_quote_char_for_identifier();
1682
if (UNIV_UNLIKELY(idlen > buflen)) {
1685
memcpy(buf, s, idlen);
1686
return(buf + idlen);
1689
/* Quote the identifier. */
1697
for (; idlen; idlen--) {
1699
if (UNIV_UNLIKELY(c == q)) {
1700
if (UNIV_UNLIKELY(buflen < 3)) {
1708
if (UNIV_UNLIKELY(buflen < 2)) {
1652
char nz[NAME_LEN + 1];
1653
char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
1659
/* Decode the table name. The filename_to_tablename()
1660
function expects a NUL-terminated string. The input and
1661
output strings buffers must not be shared. */
1663
if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
1664
idlen = (sizeof nz) - 1;
1667
memcpy(nz, id, idlen);
1671
idlen = filename_to_tablename(nz, nz2, sizeof nz2);
1674
/* See if the identifier needs to be quoted. */
1675
if (UNIV_UNLIKELY(!session)) {
1678
q = get_quote_char_for_identifier();
1682
if (UNIV_UNLIKELY(idlen > buflen)) {
1685
memcpy(buf, s, idlen);
1686
return(buf + idlen);
1689
/* Quote the identifier. */
1697
for (; idlen; idlen--) {
1699
if (UNIV_UNLIKELY(c == q)) {
1700
if (UNIV_UNLIKELY(buflen < 3)) {
1708
if (UNIV_UNLIKELY(buflen < 2)) {
1721
1721
/*****************************************************************//**
1722
1722
Convert a table or index name to the MySQL system_charset_info (UTF-8)
1723
1723
and quote it if needed.
1724
@return pointer to the end of buf */
1724
@return pointer to the end of buf */
1725
1725
extern "C" UNIV_INTERN
1727
1727
innobase_convert_name(
1728
1728
/*==================*/
1729
char* buf, /*!< out: buffer for converted identifier */
1730
ulint buflen, /*!< in: length of buf, in bytes */
1731
const char* id, /*!< in: identifier to convert */
1732
ulint idlen, /*!< in: length of id, in bytes */
1733
void* session,/*!< in: MySQL connection thread, or NULL */
1734
ibool table_id)/*!< in: TRUE=id is a table or database name;
1735
FALSE=id is an index name */
1729
char* buf, /*!< out: buffer for converted identifier */
1730
ulint buflen, /*!< in: length of buf, in bytes */
1731
const char* id, /*!< in: identifier to convert */
1732
ulint idlen, /*!< in: length of id, in bytes */
1733
void* session,/*!< in: MySQL connection thread, or NULL */
1734
ibool table_id)/*!< in: TRUE=id is a table or database name;
1735
FALSE=id is an index name */
1738
const char* bufend = buf + buflen;
1741
const char* slash = (const char*) memchr(id, '/', idlen);
1747
/* Print the database name and table name separately. */
1748
s = innobase_convert_identifier(s, bufend - s, id, slash - id,
1750
if (UNIV_LIKELY(s < bufend)) {
1752
s = innobase_convert_identifier(s, bufend - s,
1757
} else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
1758
/* Temporary index name (smart ALTER TABLE) */
1759
const char temp_index_suffix[]= "--temporary--";
1761
s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
1763
if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
1764
memcpy(s, temp_index_suffix,
1765
sizeof temp_index_suffix - 1);
1766
s += sizeof temp_index_suffix - 1;
1738
const char* bufend = buf + buflen;
1741
const char* slash = (const char*) memchr(id, '/', idlen);
1747
/* Print the database name and table name separately. */
1748
s = innobase_convert_identifier(s, bufend - s, id, slash - id,
1750
if (UNIV_LIKELY(s < bufend)) {
1752
s = innobase_convert_identifier(s, bufend - s,
1757
} else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
1758
/* Temporary index name (smart ALTER TABLE) */
1759
const char temp_index_suffix[]= "--temporary--";
1761
s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
1763
if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
1764
memcpy(s, temp_index_suffix,
1765
sizeof temp_index_suffix - 1);
1766
s += sizeof temp_index_suffix - 1;
1770
s = innobase_convert_identifier(buf, buflen, id, idlen,
1770
s = innobase_convert_identifier(buf, buflen, id, idlen,
1778
1778
/**********************************************************************//**
1779
1779
Determines if the currently running transaction has been interrupted.
1780
@return TRUE if interrupted */
1780
@return TRUE if interrupted */
1781
1781
extern "C" UNIV_INTERN
1783
1783
trx_is_interrupted(
1784
1784
/*===============*/
1785
trx_t* trx) /*!< in: transaction */
1785
trx_t* trx) /*!< in: transaction */
1787
return(trx && trx->mysql_thd && session_killed((Session*) trx->mysql_thd));
1787
return(trx && trx->mysql_thd && session_killed((Session*) trx->mysql_thd));
1790
1790
/**************************************************************//**
1795
1795
reset_template(
1796
1796
/*===========*/
1797
row_prebuilt_t* prebuilt) /*!< in/out: prebuilt struct */
1797
row_prebuilt_t* prebuilt) /*!< in/out: prebuilt struct */
1799
prebuilt->keep_other_fields_on_keyread = 0;
1800
prebuilt->read_just_key = 0;
1799
prebuilt->keep_other_fields_on_keyread = 0;
1800
prebuilt->read_just_key = 0;
1803
1803
/*********************************************************************//**
1804
1804
Opens an InnoDB database.
1805
@return 0 on success, error code on failure */
1805
@return 0 on success, error code on failure */
1810
plugin::Context &context) /*!< in: Drizzle Plugin Context */
1810
plugin::Context &context) /*!< in: Drizzle Plugin Context */
1812
static char current_dir[3]; /*!< Set if using current lib */
1818
innodb_engine_ptr= new InnobaseEngine(innobase_engine_name);
1820
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)DRIZZLE_TYPE_VARCHAR);
1812
static char current_dir[3]; /*!< Set if using current lib */
1818
innodb_engine_ptr= new InnobaseEngine(innobase_engine_name);
1820
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)DRIZZLE_TYPE_VARCHAR);
1822
1822
#ifdef UNIV_DEBUG
1823
static const char test_filename[] = "-@";
1824
char test_tablename[sizeof test_filename
1825
+ sizeof srv_mysql50_table_name_prefix];
1826
if ((sizeof test_tablename) - 1
1827
!= filename_to_tablename(test_filename, test_tablename,
1828
sizeof test_tablename)
1829
|| strncmp(test_tablename,
1830
srv_mysql50_table_name_prefix,
1831
sizeof srv_mysql50_table_name_prefix)
1832
|| strcmp(test_tablename
1833
+ sizeof srv_mysql50_table_name_prefix,
1835
errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
1823
static const char test_filename[] = "-@";
1824
char test_tablename[sizeof test_filename
1825
+ sizeof srv_mysql50_table_name_prefix];
1826
if ((sizeof test_tablename) - 1
1827
!= filename_to_tablename(test_filename, test_tablename,
1828
sizeof test_tablename)
1829
|| strncmp(test_tablename,
1830
srv_mysql50_table_name_prefix,
1831
sizeof srv_mysql50_table_name_prefix)
1832
|| strcmp(test_tablename
1833
+ sizeof srv_mysql50_table_name_prefix,
1835
errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
1838
1838
#endif /* UNIV_DEBUG */
1840
/* Check that values don't overflow on 32-bit systems. */
1841
if (sizeof(ulint) == 4) {
1842
if (innobase_buffer_pool_size > UINT32_MAX) {
1843
errmsg_printf(ERRMSG_LVL_ERROR,
1844
"innobase_buffer_pool_size can't be over 4GB"
1845
" on 32-bit systems");
1850
if (innobase_log_file_size > UINT32_MAX) {
1851
errmsg_printf(ERRMSG_LVL_ERROR,
1852
"innobase_log_file_size can't be over 4GB"
1853
" on 32-bit systems");
1859
os_innodb_umask = (ulint)internal::my_umask;
1861
/* First calculate the default path for innodb_data_home_dir etc.,
1862
in case the user has not given any value.
1864
Note that when using the embedded server, the datadirectory is not
1865
necessarily the current directory of this program. */
1867
/* It's better to use current lib, to keep paths short */
1868
current_dir[0] = FN_CURLIB;
1869
current_dir[1] = FN_LIBCHAR;
1871
default_path = current_dir;
1875
srv_set_thread_priorities = TRUE;
1876
srv_query_thread_priority = QUERY_PRIOR;
1878
/* Set InnoDB initialization parameters according to the values
1879
read from MySQL .cnf file */
1881
/*--------------- Data files -------------------------*/
1883
/* The default dir for data files is the datadir of MySQL */
1885
srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
1888
/* Set default InnoDB data file size to 10 MB and let it be
1889
auto-extending. Thus users can use InnoDB in >= 4.0 without having
1890
to specify any startup options. */
1892
if (!innobase_data_file_path) {
1893
innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
1896
/* Since InnoDB edits the argument in the next call, we make another
1899
internal_innobase_data_file_path = strdup(innobase_data_file_path);
1901
ret = (bool) srv_parse_data_file_paths_and_sizes(
1902
internal_innobase_data_file_path);
1904
errmsg_printf(ERRMSG_LVL_ERROR,
1905
"InnoDB: syntax error in innodb_data_file_path");
1840
/* Check that values don't overflow on 32-bit systems. */
1841
if (sizeof(ulint) == 4) {
1842
if (innobase_buffer_pool_size > UINT32_MAX) {
1843
errmsg_printf(ERRMSG_LVL_ERROR,
1844
"innobase_buffer_pool_size can't be over 4GB"
1845
" on 32-bit systems");
1850
if (innobase_log_file_size > UINT32_MAX) {
1851
errmsg_printf(ERRMSG_LVL_ERROR,
1852
"innobase_log_file_size can't be over 4GB"
1853
" on 32-bit systems");
1859
os_innodb_umask = (ulint)internal::my_umask;
1861
/* First calculate the default path for innodb_data_home_dir etc.,
1862
in case the user has not given any value.
1864
Note that when using the embedded server, the datadirectory is not
1865
necessarily the current directory of this program. */
1867
/* It's better to use current lib, to keep paths short */
1868
current_dir[0] = FN_CURLIB;
1869
current_dir[1] = FN_LIBCHAR;
1871
default_path = current_dir;
1875
srv_set_thread_priorities = TRUE;
1876
srv_query_thread_priority = QUERY_PRIOR;
1878
/* Set InnoDB initialization parameters according to the values
1879
read from MySQL .cnf file */
1881
/*--------------- Data files -------------------------*/
1883
/* The default dir for data files is the datadir of MySQL */
1885
srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
1888
/* Set default InnoDB data file size to 10 MB and let it be
1889
auto-extending. Thus users can use InnoDB in >= 4.0 without having
1890
to specify any startup options. */
1892
if (!innobase_data_file_path) {
1893
innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
1896
/* Since InnoDB edits the argument in the next call, we make another
1899
internal_innobase_data_file_path = strdup(innobase_data_file_path);
1901
ret = (bool) srv_parse_data_file_paths_and_sizes(
1902
internal_innobase_data_file_path);
1904
errmsg_printf(ERRMSG_LVL_ERROR,
1905
"InnoDB: syntax error in innodb_data_file_path");
1906
1906
mem_free_and_error:
1907
srv_free_paths_and_sizes();
1908
if (internal_innobase_data_file_path)
1909
free(internal_innobase_data_file_path);
1913
/* -------------- Log files ---------------------------*/
1915
/* The default dir for log files is the datadir of MySQL */
1917
if (!innobase_log_group_home_dir) {
1918
innobase_log_group_home_dir = default_path;
1907
srv_free_paths_and_sizes();
1908
if (internal_innobase_data_file_path)
1909
free(internal_innobase_data_file_path);
1913
/* -------------- Log files ---------------------------*/
1915
/* The default dir for log files is the datadir of MySQL */
1917
if (!innobase_log_group_home_dir) {
1918
innobase_log_group_home_dir = default_path;
1921
1921
#ifdef UNIV_LOG_ARCHIVE
1922
/* Since innodb_log_arch_dir has no relevance under MySQL,
1923
starting from 4.0.6 we always set it the same as
1924
innodb_log_group_home_dir: */
1926
innobase_log_arch_dir = innobase_log_group_home_dir;
1928
srv_arch_dir = innobase_log_arch_dir;
1922
/* Since innodb_log_arch_dir has no relevance under MySQL,
1923
starting from 4.0.6 we always set it the same as
1924
innodb_log_group_home_dir: */
1926
innobase_log_arch_dir = innobase_log_group_home_dir;
1928
srv_arch_dir = innobase_log_arch_dir;
1929
1929
#endif /* UNIG_LOG_ARCHIVE */
1932
srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
1934
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
1935
errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
1936
"wrong number of mirrored log groups");
1938
goto mem_free_and_error;
1941
/* Validate the file format by animal name */
1942
if (innobase_file_format_name != NULL) {
1944
format_id = innobase_file_format_name_lookup(
1945
innobase_file_format_name);
1947
if (format_id > DICT_TF_FORMAT_MAX) {
1949
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
1951
goto mem_free_and_error;
1954
/* Set it to the default file format id. Though this
1955
should never happen. */
1959
srv_file_format = format_id;
1961
/* Given the type of innobase_file_format_name we have little
1962
choice but to cast away the constness from the returned name.
1963
innobase_file_format_name is used in the MySQL set variable
1964
interface and so can't be const. */
1966
innobase_file_format_name =
1967
(char*) trx_sys_file_format_id_to_name(format_id);
1969
/* Process innobase_file_format_check variable */
1970
ut_a(innobase_file_format_check != NULL);
1972
/* As a side effect it will set srv_check_file_format_at_startup
1973
on valid input. First we check for "on"/"off". */
1974
if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
1976
/* Did the user specify a format name that we support ?
1977
As a side effect it will update the variable
1978
srv_check_file_format_at_startup */
1979
if (!innobase_file_format_check_validate(
1980
innobase_file_format_check)) {
1982
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
1983
"innodb_file_format_check value: "
1984
"should be either 'on' or 'off' or "
1985
"any value up to %s or its "
1986
"equivalent numeric id",
1987
trx_sys_file_format_id_to_name(
1988
DICT_TF_FORMAT_MAX));
1990
goto mem_free_and_error;
1994
if (innobase_change_buffering) {
1998
use < UT_ARR_SIZE(innobase_change_buffering_values);
2000
if (!innobase_strcasecmp(
2001
innobase_change_buffering,
2002
innobase_change_buffering_values[use])) {
2003
ibuf_use = (ibuf_use_t) use;
2004
goto innobase_change_buffering_inited_ok;
2008
errmsg_printf(ERRMSG_LVL_ERROR,
2009
"InnoDB: invalid value "
2010
"innodb_file_format_check=%s",
2011
innobase_change_buffering);
2012
goto mem_free_and_error;
1932
srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
1934
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
1935
errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
1936
"wrong number of mirrored log groups");
1938
goto mem_free_and_error;
1941
/* Validate the file format by animal name */
1942
if (innobase_file_format_name != NULL) {
1944
format_id = innobase_file_format_name_lookup(
1945
innobase_file_format_name);
1947
if (format_id > DICT_TF_FORMAT_MAX) {
1949
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
1951
goto mem_free_and_error;
1954
/* Set it to the default file format id. Though this
1955
should never happen. */
1959
srv_file_format = format_id;
1961
/* Given the type of innobase_file_format_name we have little
1962
choice but to cast away the constness from the returned name.
1963
innobase_file_format_name is used in the MySQL set variable
1964
interface and so can't be const. */
1966
innobase_file_format_name =
1967
(char*) trx_sys_file_format_id_to_name(format_id);
1969
/* Process innobase_file_format_check variable */
1970
ut_a(innobase_file_format_check != NULL);
1972
/* As a side effect it will set srv_check_file_format_at_startup
1973
on valid input. First we check for "on"/"off". */
1974
if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
1976
/* Did the user specify a format name that we support ?
1977
As a side effect it will update the variable
1978
srv_check_file_format_at_startup */
1979
if (!innobase_file_format_check_validate(
1980
innobase_file_format_check)) {
1982
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
1983
"innodb_file_format_check value: "
1984
"should be either 'on' or 'off' or "
1985
"any value up to %s or its "
1986
"equivalent numeric id",
1987
trx_sys_file_format_id_to_name(
1988
DICT_TF_FORMAT_MAX));
1990
goto mem_free_and_error;
1994
if (innobase_change_buffering) {
1998
use < UT_ARR_SIZE(innobase_change_buffering_values);
2000
if (!innobase_strcasecmp(
2001
innobase_change_buffering,
2002
innobase_change_buffering_values[use])) {
2003
ibuf_use = (ibuf_use_t) use;
2004
goto innobase_change_buffering_inited_ok;
2008
errmsg_printf(ERRMSG_LVL_ERROR,
2009
"InnoDB: invalid value "
2010
"innodb_file_format_check=%s",
2011
innobase_change_buffering);
2012
goto mem_free_and_error;
2015
2015
innobase_change_buffering_inited_ok:
2016
ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
2017
innobase_change_buffering = (char*)
2018
innobase_change_buffering_values[ibuf_use];
2020
/* --------------------------------------------------*/
2022
srv_file_flush_method_str = innobase_unix_file_flush_method;
2024
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
2025
srv_n_log_files = (ulint) innobase_log_files_in_group;
2026
srv_log_file_size = (ulint) innobase_log_file_size;
2016
ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
2017
innobase_change_buffering = (char*)
2018
innobase_change_buffering_values[ibuf_use];
2020
/* --------------------------------------------------*/
2022
srv_file_flush_method_str = innobase_unix_file_flush_method;
2024
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
2025
srv_n_log_files = (ulint) innobase_log_files_in_group;
2026
srv_log_file_size = (ulint) innobase_log_file_size;
2028
2028
#ifdef UNIV_LOG_ARCHIVE
2029
srv_log_archive_on = (ulint) innobase_log_archive;
2029
srv_log_archive_on = (ulint) innobase_log_archive;
2030
2030
#endif /* UNIV_LOG_ARCHIVE */
2031
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
2033
srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
2035
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
2037
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
2038
srv_n_read_io_threads = (ulint) innobase_read_io_threads;
2039
srv_n_write_io_threads = (ulint) innobase_write_io_threads;
2041
srv_force_recovery = (ulint) innobase_force_recovery;
2043
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
2044
srv_use_checksums = (ibool) innobase_use_checksums;
2031
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
2033
srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
2035
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
2037
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
2038
srv_n_read_io_threads = (ulint) innobase_read_io_threads;
2039
srv_n_write_io_threads = (ulint) innobase_write_io_threads;
2041
srv_force_recovery = (ulint) innobase_force_recovery;
2043
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
2044
srv_use_checksums = (ibool) innobase_use_checksums;
2046
2046
#ifdef HAVE_LARGE_PAGES
2047
2047
if ((os_use_large_pages = (ibool) my_use_large_pages))
2048
os_large_page_size = (ulint) opt_large_page_size;
2048
os_large_page_size = (ulint) opt_large_page_size;
2051
row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
2053
srv_locks_unsafe_for_binlog = (ibool) TRUE;
2055
srv_max_n_open_files = (ulint) innobase_open_files;
2056
srv_innodb_status = (ibool) innobase_create_status_file;
2058
srv_print_verbose_log = true;
2060
/* Store the default charset-collation number of this MySQL
2063
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
2066
innobase_commit_concurrency_init_default();
2068
/* Since we in this module access directly the fields of a trx
2069
struct, and due to different headers and flags it might happen that
2070
mutex_t has a different size in this module and in InnoDB
2071
modules, we check at run time that the size is the same in
2072
these compilation modules. */
2074
err = innobase_start_or_create_for_mysql();
2076
if (err != DB_SUCCESS) {
2077
goto mem_free_and_error;
2080
innobase_open_tables = hash_create(200);
2081
pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
2082
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
2083
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
2084
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
2085
pthread_cond_init(&commit_cond, NULL);
2051
row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
2053
srv_locks_unsafe_for_binlog = (ibool) TRUE;
2055
srv_max_n_open_files = (ulint) innobase_open_files;
2056
srv_innodb_status = (ibool) innobase_create_status_file;
2058
srv_print_verbose_log = true;
2060
/* Store the default charset-collation number of this MySQL
2063
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
2066
innobase_commit_concurrency_init_default();
2068
/* Since we in this module access directly the fields of a trx
2069
struct, and due to different headers and flags it might happen that
2070
mutex_t has a different size in this module and in InnoDB
2071
modules, we check at run time that the size is the same in
2072
these compilation modules. */
2074
err = innobase_start_or_create_for_mysql();
2076
if (err != DB_SUCCESS) {
2077
goto mem_free_and_error;
2080
innobase_open_tables = hash_create(200);
2081
pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
2082
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
2083
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
2084
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
2085
pthread_cond_init(&commit_cond, NULL);
2088
2088
status_table_function_ptr= new InnodbStatusTool;
2090
context.add(innodb_engine_ptr);
2092
context.add(status_table_function_ptr);
2094
cmp_tool= new(std::nothrow)CmpTool(false);
2095
context.add(cmp_tool);
2097
cmp_reset_tool= new(std::nothrow)CmpTool(true);
2098
context.add(cmp_reset_tool);
2100
cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
2101
context.add(cmp_mem_tool);
2103
cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
2104
context.add(cmp_mem_reset_tool);
2106
innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
2107
context.add(innodb_trx_tool);
2109
innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
2110
context.add(innodb_locks_tool);
2112
innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
2113
context.add(innodb_lock_waits_tool);
2115
/* Get the current high water mark format. */
2116
innobase_file_format_check = (char*) trx_sys_file_format_max_get();
2090
context.add(innodb_engine_ptr);
2092
context.add(status_table_function_ptr);
2094
cmp_tool= new(std::nothrow)CmpTool(false);
2095
context.add(cmp_tool);
2097
cmp_reset_tool= new(std::nothrow)CmpTool(true);
2098
context.add(cmp_reset_tool);
2100
cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
2101
context.add(cmp_mem_tool);
2103
cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
2104
context.add(cmp_mem_reset_tool);
2106
innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
2107
context.add(innodb_trx_tool);
2109
innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
2110
context.add(innodb_locks_tool);
2112
innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
2113
context.add(innodb_lock_waits_tool);
2115
/* Get the current high water mark format. */
2116
innobase_file_format_check = (char*) trx_sys_file_format_max_get();
2124
2124
/****************************************************************//**
2125
2125
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
2126
2126
the logs, and the name of this function should be innobase_checkpoint.
2127
@return TRUE if error */
2127
@return TRUE if error */
2129
2129
InnobaseEngine::flush_logs()
2130
2130
/*=====================*/
2134
assert(this == innodb_engine_ptr);
2136
log_buffer_flush_to_disk();
2134
assert(this == innodb_engine_ptr);
2136
log_buffer_flush_to_disk();
2141
2141
/*****************************************************************//**
2159
2159
Starts a new InnoDB transaction if a transaction is not yet started. And
2160
2160
assigns a new snapshot for a consistent read if the transaction does not yet
2164
2164
InnobaseEngine::doStartTransaction(
2165
2165
/*====================================*/
2166
Session* session, /*!< in: MySQL thread handle of the user for whom
2167
the transaction should be committed */
2166
Session* session, /*!< in: MySQL thread handle of the user for whom
2167
the transaction should be committed */
2168
2168
start_transaction_option_t options)
2170
assert(this == innodb_engine_ptr);
2172
/* Create a new trx struct for session, if it does not yet have one */
2173
trx_t *trx = check_trx_exists(session);
2175
/* This is just to play safe: release a possible FIFO ticket and
2176
search latch. Since we will reserve the kernel mutex, we have to
2177
release the search system latch first to obey the latching order. */
2178
innobase_release_stat_resources(trx);
2180
/* If the transaction is not started yet, start it */
2181
trx_start_if_not_started(trx);
2183
/* Assign a read view if the transaction does not have it yet */
2170
assert(this == innodb_engine_ptr);
2172
/* Create a new trx struct for session, if it does not yet have one */
2173
trx_t *trx = check_trx_exists(session);
2175
/* This is just to play safe: release a possible FIFO ticket and
2176
search latch. Since we will reserve the kernel mutex, we have to
2177
release the search system latch first to obey the latching order. */
2178
innobase_release_stat_resources(trx);
2180
/* If the transaction is not started yet, start it */
2181
trx_start_if_not_started(trx);
2183
/* Assign a read view if the transaction does not have it yet */
2184
2184
if (options == START_TRANS_OPT_WITH_CONS_SNAPSHOT)
2185
trx_assign_read_view(trx);
2185
trx_assign_read_view(trx);
2190
2190
/*****************************************************************//**
2191
2191
Commits a transaction in an InnoDB database or marks an SQL statement
2195
2195
InnobaseEngine::doCommit(
2196
2196
/*============*/
2197
Session* session, /*!< in: MySQL thread handle of the user for whom
2198
the transaction should be committed */
2199
bool all) /*!< in: TRUE - commit transaction
2200
FALSE - the current SQL statement ended */
2197
Session* session, /*!< in: MySQL thread handle of the user for whom
2198
the transaction should be committed */
2199
bool all) /*!< in: TRUE - commit transaction
2200
FALSE - the current SQL statement ended */
2204
assert(this == innodb_engine_ptr);
2206
trx = check_trx_exists(session);
2208
/* Since we will reserve the kernel mutex, we have to release
2209
the search system latch first to obey the latching order. */
2211
if (trx->has_search_latch) {
2212
trx_search_latch_release_if_reserved(trx);
2216
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2218
/* We were instructed to commit the whole transaction, or
2219
this is an SQL statement end and autocommit is on */
2221
/* We need current binlog position for ibbackup to work.
2222
Note, the position is current because of
2223
prepare_commit_mutex */
2204
assert(this == innodb_engine_ptr);
2206
trx = check_trx_exists(session);
2208
/* Since we will reserve the kernel mutex, we have to release
2209
the search system latch first to obey the latching order. */
2211
if (trx->has_search_latch) {
2212
trx_search_latch_release_if_reserved(trx);
2216
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2218
/* We were instructed to commit the whole transaction, or
2219
this is an SQL statement end and autocommit is on */
2221
/* We need current binlog position for ibbackup to work.
2222
Note, the position is current because of
2223
prepare_commit_mutex */
2225
if (innobase_commit_concurrency > 0) {
2226
pthread_mutex_lock(&commit_cond_m);
2225
if (innobase_commit_concurrency > 0) {
2226
pthread_mutex_lock(&commit_cond_m);
2229
if (commit_threads > innobase_commit_concurrency) {
2231
pthread_cond_wait(&commit_cond,
2233
pthread_mutex_unlock(&commit_cond_m);
2237
pthread_mutex_unlock(&commit_cond_m);
2229
if (commit_threads > innobase_commit_concurrency) {
2231
pthread_cond_wait(&commit_cond,
2233
pthread_mutex_unlock(&commit_cond_m);
2237
pthread_mutex_unlock(&commit_cond_m);
2241
2241
/* Store transaction point for binlog
2242
Later logic tests that this is set to _something_. We need
2243
that logic to fire, even though we do not have a real name. */
2244
trx->mysql_log_file_name = "UNUSED";
2245
trx->mysql_log_offset = 0;
2247
/* Don't do write + flush right now. For group commit
2248
to work we want to do the flush after releasing the
2249
prepare_commit_mutex. */
2250
trx->flush_log_later = TRUE;
2251
innobase_commit_low(trx);
2252
trx->flush_log_later = FALSE;
2254
if (innobase_commit_concurrency > 0) {
2255
pthread_mutex_lock(&commit_cond_m);
2257
pthread_cond_signal(&commit_cond);
2258
pthread_mutex_unlock(&commit_cond_m);
2261
/* Now do a write + flush of logs. */
2262
trx_commit_complete_for_mysql(trx);
2265
/* We just mark the SQL statement ended and do not do a
2266
transaction commit */
2268
/* If we had reserved the auto-inc lock for some
2269
table in this SQL statement we release it now */
2271
row_unlock_table_autoinc_for_mysql(trx);
2273
/* Store the current undo_no of the transaction so that we
2274
know where to roll back if we have to roll back the next
2277
trx_mark_sql_stat_end(trx);
2280
trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2282
if (trx->declared_to_be_inside_innodb) {
2283
/* Release our possible ticket in the FIFO */
2285
srv_conc_force_exit_innodb(trx);
2288
/* Tell the InnoDB server that there might be work for utility
2290
srv_active_wake_master_thread();
2242
Later logic tests that this is set to _something_. We need
2243
that logic to fire, even though we do not have a real name. */
2244
trx->mysql_log_file_name = "UNUSED";
2245
trx->mysql_log_offset = 0;
2247
/* Don't do write + flush right now. For group commit
2248
to work we want to do the flush after releasing the
2249
prepare_commit_mutex. */
2250
trx->flush_log_later = TRUE;
2251
innobase_commit_low(trx);
2252
trx->flush_log_later = FALSE;
2254
if (innobase_commit_concurrency > 0) {
2255
pthread_mutex_lock(&commit_cond_m);
2257
pthread_cond_signal(&commit_cond);
2258
pthread_mutex_unlock(&commit_cond_m);
2261
/* Now do a write + flush of logs. */
2262
trx_commit_complete_for_mysql(trx);
2265
/* We just mark the SQL statement ended and do not do a
2266
transaction commit */
2268
/* If we had reserved the auto-inc lock for some
2269
table in this SQL statement we release it now */
2271
row_unlock_table_autoinc_for_mysql(trx);
2273
/* Store the current undo_no of the transaction so that we
2274
know where to roll back if we have to roll back the next
2277
trx_mark_sql_stat_end(trx);
2280
trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2282
if (trx->declared_to_be_inside_innodb) {
2283
/* Release our possible ticket in the FIFO */
2285
srv_conc_force_exit_innodb(trx);
2288
/* Tell the InnoDB server that there might be work for utility
2290
srv_active_wake_master_thread();
2295
2295
/*****************************************************************//**
2296
2296
Rolls back a transaction or the latest SQL statement.
2297
@return 0 or error number */
2297
@return 0 or error number */
2299
2299
InnobaseEngine::doRollback(
2300
2300
/*==============*/
2301
Session* session,/*!< in: handle to the MySQL thread of the user
2302
whose transaction should be rolled back */
2303
bool all) /*!< in: TRUE - commit transaction
2304
FALSE - the current SQL statement ended */
2301
Session* session,/*!< in: handle to the MySQL thread of the user
2302
whose transaction should be rolled back */
2303
bool all) /*!< in: TRUE - commit transaction
2304
FALSE - the current SQL statement ended */
2309
assert(this == innodb_engine_ptr);
2311
trx = check_trx_exists(session);
2313
/* Release a possible FIFO ticket and search latch. Since we will
2314
reserve the kernel mutex, we have to release the search system latch
2315
first to obey the latching order. */
2317
innobase_release_stat_resources(trx);
2319
/* If we had reserved the auto-inc lock for some table (if
2320
we come here to roll back the latest SQL statement) we
2321
release it now before a possibly lengthy rollback */
2323
row_unlock_table_autoinc_for_mysql(trx);
2326
|| !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2328
error = trx_rollback_for_mysql(trx);
2330
error = trx_rollback_last_sql_stat_for_mysql(trx);
2333
return(convert_error_code_to_mysql(error, 0, NULL));
2309
assert(this == innodb_engine_ptr);
2311
trx = check_trx_exists(session);
2313
/* Release a possible FIFO ticket and search latch. Since we will
2314
reserve the kernel mutex, we have to release the search system latch
2315
first to obey the latching order. */
2317
innobase_release_stat_resources(trx);
2319
/* If we had reserved the auto-inc lock for some table (if
2320
we come here to roll back the latest SQL statement) we
2321
release it now before a possibly lengthy rollback */
2323
row_unlock_table_autoinc_for_mysql(trx);
2326
|| !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2328
error = trx_rollback_for_mysql(trx);
2330
error = trx_rollback_last_sql_stat_for_mysql(trx);
2333
return(convert_error_code_to_mysql(error, 0, NULL));
2336
2336
/*****************************************************************//**
2337
2337
Rolls back a transaction
2338
@return 0 or error number */
2338
@return 0 or error number */
2341
2341
innobase_rollback_trx(
2342
2342
/*==================*/
2343
trx_t* trx) /*!< in: transaction */
2343
trx_t* trx) /*!< in: transaction */
2347
/* Release a possible FIFO ticket and search latch. Since we will
2348
reserve the kernel mutex, we have to release the search system latch
2349
first to obey the latching order. */
2351
innobase_release_stat_resources(trx);
2353
/* If we had reserved the auto-inc lock for some table (if
2354
we come here to roll back the latest SQL statement) we
2355
release it now before a possibly lengthy rollback */
2357
row_unlock_table_autoinc_for_mysql(trx);
2359
error = trx_rollback_for_mysql(trx);
2361
return(convert_error_code_to_mysql(error, 0, NULL));
2347
/* Release a possible FIFO ticket and search latch. Since we will
2348
reserve the kernel mutex, we have to release the search system latch
2349
first to obey the latching order. */
2351
innobase_release_stat_resources(trx);
2353
/* If we had reserved the auto-inc lock for some table (if
2354
we come here to roll back the latest SQL statement) we
2355
release it now before a possibly lengthy rollback */
2357
row_unlock_table_autoinc_for_mysql(trx);
2359
error = trx_rollback_for_mysql(trx);
2361
return(convert_error_code_to_mysql(error, 0, NULL));
2364
2364
/*****************************************************************//**
2602
2602
normalize_table_name(
2603
2603
/*=================*/
2604
char* norm_name, /*!< out: normalized name as a
2605
null-terminated string */
2606
const char* name) /*!< in: table name string */
2604
char* norm_name, /*!< out: normalized name as a
2605
null-terminated string */
2606
const char* name) /*!< in: table name string */
2608
const char* name_ptr;
2612
/* Scan name from the end */
2614
ptr = strchr(name, '\0')-1;
2616
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2626
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2632
memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2634
norm_name[name_ptr - db_ptr - 1] = '/';
2608
const char* name_ptr;
2612
/* Scan name from the end */
2614
ptr = strchr(name, '\0')-1;
2616
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2626
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2632
memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2634
norm_name[name_ptr - db_ptr - 1] = '/';
2637
innobase_casedn_str(norm_name);
2637
innobase_casedn_str(norm_name);
2641
2641
/********************************************************************//**
2642
2642
Set the autoinc column max value. This should only be called once from
2643
2643
ha_innobase::open(). Therefore there's no need for a covering lock.
2644
@return DB_SUCCESS or error code */
2644
@return DB_SUCCESS or error code */
2647
2647
ha_innobase::innobase_initialize_autoinc()
2648
2648
/*======================================*/
2650
dict_index_t* index;
2652
const char* col_name;
2655
col_name = table->found_next_number_field->field_name;
2656
index = innobase_get_index(table->s->next_number_index);
2658
/* Execute SELECT MAX(col_name) FROM TABLE; */
2659
error = row_search_max_autoinc(index, col_name, &auto_inc);
2664
/* At the this stage we don't know the increment
2665
or the offset, so use default inrement of 1. */
2669
case DB_RECORD_NOT_FOUND:
2670
ut_print_timestamp(stderr);
2671
fprintf(stderr, " InnoDB: MySQL and InnoDB data "
2672
"dictionaries are out of sync.\n"
2673
"InnoDB: Unable to find the AUTOINC column %s in the "
2674
"InnoDB table %s.\n"
2675
"InnoDB: We set the next AUTOINC column value to the "
2676
"maximum possible value,\n"
2677
"InnoDB: in effect disabling the AUTOINC next value "
2679
"InnoDB: You can either set the next AUTOINC value "
2680
"explicitly using ALTER TABLE\n"
2681
"InnoDB: or fix the data dictionary by recreating "
2683
col_name, index->table->name);
2685
auto_inc = 0xFFFFFFFFFFFFFFFFULL;
2692
dict_table_autoinc_initialize(prebuilt->table, auto_inc);
2650
dict_index_t* index;
2652
const char* col_name;
2655
col_name = table->found_next_number_field->field_name;
2656
index = innobase_get_index(table->s->next_number_index);
2658
/* Execute SELECT MAX(col_name) FROM TABLE; */
2659
error = row_search_max_autoinc(index, col_name, &auto_inc);
2664
/* At the this stage we don't know the increment
2665
or the offset, so use default inrement of 1. */
2669
case DB_RECORD_NOT_FOUND:
2670
ut_print_timestamp(stderr);
2671
fprintf(stderr, " InnoDB: MySQL and InnoDB data "
2672
"dictionaries are out of sync.\n"
2673
"InnoDB: Unable to find the AUTOINC column %s in the "
2674
"InnoDB table %s.\n"
2675
"InnoDB: We set the next AUTOINC column value to the "
2676
"maximum possible value,\n"
2677
"InnoDB: in effect disabling the AUTOINC next value "
2679
"InnoDB: You can either set the next AUTOINC value "
2680
"explicitly using ALTER TABLE\n"
2681
"InnoDB: or fix the data dictionary by recreating "
2683
col_name, index->table->name);
2685
auto_inc = 0xFFFFFFFFFFFFFFFFULL;
2692
dict_table_autoinc_initialize(prebuilt->table, auto_inc);
2697
2697
/*****************************************************************//**
2698
2698
Creates and opens a handle to a table which already exists in an InnoDB
2700
@return 1 if error, 0 if success */
2700
@return 1 if error, 0 if success */
2703
2703
ha_innobase::open(
2704
2704
/*==============*/
2705
const char* name, /*!< in: table name */
2706
int mode, /*!< in: not used */
2707
uint test_if_locked) /*!< in: not used */
2705
const char* name, /*!< in: table name */
2706
int mode, /*!< in: not used */
2707
uint test_if_locked) /*!< in: not used */
2709
dict_table_t* ib_table;
2710
char norm_name[1000];
2713
char* is_part = NULL;
2716
UT_NOT_USED(test_if_locked);
2718
session = ha_session();
2720
/* Under some cases Drizzle seems to call this function while
2721
holding btr_search_latch. This breaks the latching order as
2722
we acquire dict_sys->mutex below and leads to a deadlock. */
2723
if (session != NULL) {
2724
getTransactionalEngine()->releaseTemporaryLatches(session);
2727
normalize_table_name(norm_name, name);
2729
user_session = NULL;
2731
if (!(share=get_share(name))) {
2736
/* Create buffers for packing the fields of a record. Why
2737
table->stored_rec_length did not work here? Obviously, because char
2738
fields when packed actually became 1 byte longer, when we also
2739
stored the string length as the first byte. */
2741
upd_and_key_val_buff_len =
2742
table->s->stored_rec_length
2743
+ table->s->max_key_length
2744
+ MAX_REF_PARTS * 3;
2745
if (!(unsigned char*) memory::multi_malloc(false,
2746
&upd_buff, upd_and_key_val_buff_len,
2747
&key_val_buff, upd_and_key_val_buff_len,
2754
/* We look for pattern #P# to see if the table is partitioned
2755
MySQL table. The retry logic for partitioned tables is a
2756
workaround for http://bugs.mysql.com/bug.php?id=33349. Look
2757
at support issue https://support.mysql.com/view.php?id=21080
2758
for more details. */
2759
is_part = strstr(norm_name, "#P#");
2709
dict_table_t* ib_table;
2710
char norm_name[1000];
2713
char* is_part = NULL;
2716
UT_NOT_USED(test_if_locked);
2718
session = ha_session();
2720
/* Under some cases Drizzle seems to call this function while
2721
holding btr_search_latch. This breaks the latching order as
2722
we acquire dict_sys->mutex below and leads to a deadlock. */
2723
if (session != NULL) {
2724
getTransactionalEngine()->releaseTemporaryLatches(session);
2727
normalize_table_name(norm_name, name);
2729
user_session = NULL;
2731
if (!(share=get_share(name))) {
2736
/* Create buffers for packing the fields of a record. Why
2737
table->stored_rec_length did not work here? Obviously, because char
2738
fields when packed actually became 1 byte longer, when we also
2739
stored the string length as the first byte. */
2741
upd_and_key_val_buff_len =
2742
table->s->stored_rec_length
2743
+ table->s->max_key_length
2744
+ MAX_REF_PARTS * 3;
2745
if (!(unsigned char*) memory::multi_malloc(false,
2746
&upd_buff, upd_and_key_val_buff_len,
2747
&key_val_buff, upd_and_key_val_buff_len,
2754
/* We look for pattern #P# to see if the table is partitioned
2755
MySQL table. The retry logic for partitioned tables is a
2756
workaround for http://bugs.mysql.com/bug.php?id=33349. Look
2757
at support issue https://support.mysql.com/view.php?id=21080
2758
for more details. */
2759
is_part = strstr(norm_name, "#P#");
2761
/* Get pointer to a table object in InnoDB dictionary cache */
2762
ib_table = dict_table_get(norm_name, TRUE);
2764
if (NULL == ib_table) {
2765
if (is_part && retries < 10) {
2767
os_thread_sleep(100000);
2772
errmsg_printf(ERRMSG_LVL_ERROR, "Failed to open table %s after "
2773
"%lu attemtps.\n", norm_name,
2777
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
2778
"the internal data dictionary of InnoDB "
2779
"though the .frm file for the\n"
2780
"table exists. Maybe you have deleted and "
2781
"recreated InnoDB data\n"
2782
"files but have forgotten to delete the "
2783
"corresponding .frm files\n"
2784
"of InnoDB tables, or you have moved .frm "
2785
"files to another database?\n"
2786
"or, the table contains indexes that this "
2787
"version of the engine\n"
2788
"doesn't support.\n"
2789
"See " REFMAN "innodb-troubleshooting.html\n"
2790
"how you can resolve the problem.\n",
2796
return(HA_ERR_NO_SUCH_TABLE);
2799
if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
2800
errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
2801
"the .ibd file for\ntable %s does not exist.\n"
2802
"Have you deleted the .ibd file from the "
2803
"database directory under\nthe MySQL datadir, "
2804
"or have you used DISCARD TABLESPACE?\n"
2805
"See " REFMAN "innodb-troubleshooting.html\n"
2806
"how you can resolve the problem.\n",
2812
dict_table_decrement_handle_count(ib_table, FALSE);
2813
return(HA_ERR_NO_SUCH_TABLE);
2816
prebuilt = row_create_prebuilt(ib_table);
2818
prebuilt->mysql_row_len = table->s->stored_rec_length;
2819
prebuilt->default_rec = table->s->default_values;
2820
ut_ad(prebuilt->default_rec);
2822
/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
2824
primary_key = table->s->primary_key;
2825
key_used_on_scan = primary_key;
2827
/* Allocate a buffer for a 'row reference'. A row reference is
2828
a string of bytes of length ref_length which uniquely specifies
2829
a row in our table. Note that MySQL may also compare two row
2830
references for equality by doing a simple memcmp on the strings
2831
of length ref_length! */
2833
if (!row_table_got_default_clust_index(ib_table)) {
2834
if (primary_key >= MAX_KEY) {
2835
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in InnoDB data "
2836
"dictionary, but not in MySQL!", name);
2839
prebuilt->clust_index_was_generated = FALSE;
2841
/* MySQL allocates the buffer for ref. key_info->key_length
2842
includes space for all key columns + one byte for each column
2843
that may be NULL. ref_length must be as exact as possible to
2844
save space, because all row reference buffers are allocated
2845
based on ref_length. */
2847
ref_length = table->key_info[primary_key].key_length;
2849
if (primary_key != MAX_KEY) {
2850
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has no primary key in InnoDB data "
2851
"dictionary, but has one in MySQL! If you "
2852
"created the table with a MySQL version < "
2853
"3.23.54 and did not define a primary key, "
2854
"but defined a unique key with all non-NULL "
2855
"columns, then MySQL internally treats that "
2856
"key as the primary key. You can fix this "
2857
"error by dump + DROP + CREATE + reimport "
2858
"of the table.", name);
2861
prebuilt->clust_index_was_generated = TRUE;
2863
ref_length = DATA_ROW_ID_LEN;
2865
/* If we automatically created the clustered index, then
2866
MySQL does not know about it, and MySQL must NOT be aware
2867
of the index used on scan, to make it avoid checking if we
2868
update the column of the index. That is why we assert below
2869
that key_used_on_scan is the undefined value MAX_KEY.
2870
The column is the row id in the automatical generation case,
2871
and it will never be updated anyway. */
2873
if (key_used_on_scan != MAX_KEY) {
2874
errmsg_printf(ERRMSG_LVL_WARN,
2875
"Table %s key_used_on_scan is %lu even "
2876
"though there is no primary key inside "
2877
"InnoDB.", name, (ulong) key_used_on_scan);
2881
/* Index block size in InnoDB: used by MySQL in query optimization */
2882
stats.block_size = 16 * 1024;
2884
/* Init table lock structure */
2885
thr_lock_data_init(&share->lock,&lock,(void*) 0);
2887
if (prebuilt->table) {
2888
/* We update the highest file format in the system table
2889
space, if this table has higher file format setting. */
2891
trx_sys_file_format_max_upgrade(
2892
(const char**) &innobase_file_format_check,
2893
dict_table_get_format(prebuilt->table));
2896
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
2898
/* Only if the table has an AUTOINC column. */
2899
if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
2902
dict_table_autoinc_lock(prebuilt->table);
2904
/* Since a table can already be "open" in InnoDB's internal
2905
data dictionary, we only init the autoinc counter once, the
2906
first time the table is loaded. We can safely reuse the
2907
autoinc value from a previous Drizzle open. */
2908
if (dict_table_autoinc_read(prebuilt->table) == 0) {
2910
error = innobase_initialize_autoinc();
2911
ut_a(error == DB_SUCCESS);
2914
dict_table_autoinc_unlock(prebuilt->table);
2761
/* Get pointer to a table object in InnoDB dictionary cache */
2762
ib_table = dict_table_get(norm_name, TRUE);
2764
if (NULL == ib_table) {
2765
if (is_part && retries < 10) {
2767
os_thread_sleep(100000);
2772
errmsg_printf(ERRMSG_LVL_ERROR, "Failed to open table %s after "
2773
"%lu attemtps.\n", norm_name,
2777
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
2778
"the internal data dictionary of InnoDB "
2779
"though the .frm file for the\n"
2780
"table exists. Maybe you have deleted and "
2781
"recreated InnoDB data\n"
2782
"files but have forgotten to delete the "
2783
"corresponding .frm files\n"
2784
"of InnoDB tables, or you have moved .frm "
2785
"files to another database?\n"
2786
"or, the table contains indexes that this "
2787
"version of the engine\n"
2788
"doesn't support.\n"
2789
"See " REFMAN "innodb-troubleshooting.html\n"
2790
"how you can resolve the problem.\n",
2796
return(HA_ERR_NO_SUCH_TABLE);
2799
if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
2800
errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
2801
"the .ibd file for\ntable %s does not exist.\n"
2802
"Have you deleted the .ibd file from the "
2803
"database directory under\nthe MySQL datadir, "
2804
"or have you used DISCARD TABLESPACE?\n"
2805
"See " REFMAN "innodb-troubleshooting.html\n"
2806
"how you can resolve the problem.\n",
2812
dict_table_decrement_handle_count(ib_table, FALSE);
2813
return(HA_ERR_NO_SUCH_TABLE);
2816
prebuilt = row_create_prebuilt(ib_table);
2818
prebuilt->mysql_row_len = table->s->stored_rec_length;
2819
prebuilt->default_rec = table->s->default_values;
2820
ut_ad(prebuilt->default_rec);
2822
/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
2824
primary_key = table->s->primary_key;
2825
key_used_on_scan = primary_key;
2827
/* Allocate a buffer for a 'row reference'. A row reference is
2828
a string of bytes of length ref_length which uniquely specifies
2829
a row in our table. Note that MySQL may also compare two row
2830
references for equality by doing a simple memcmp on the strings
2831
of length ref_length! */
2833
if (!row_table_got_default_clust_index(ib_table)) {
2834
if (primary_key >= MAX_KEY) {
2835
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in InnoDB data "
2836
"dictionary, but not in MySQL!", name);
2839
prebuilt->clust_index_was_generated = FALSE;
2841
/* MySQL allocates the buffer for ref. key_info->key_length
2842
includes space for all key columns + one byte for each column
2843
that may be NULL. ref_length must be as exact as possible to
2844
save space, because all row reference buffers are allocated
2845
based on ref_length. */
2847
ref_length = table->key_info[primary_key].key_length;
2849
if (primary_key != MAX_KEY) {
2850
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has no primary key in InnoDB data "
2851
"dictionary, but has one in MySQL! If you "
2852
"created the table with a MySQL version < "
2853
"3.23.54 and did not define a primary key, "
2854
"but defined a unique key with all non-NULL "
2855
"columns, then MySQL internally treats that "
2856
"key as the primary key. You can fix this "
2857
"error by dump + DROP + CREATE + reimport "
2858
"of the table.", name);
2861
prebuilt->clust_index_was_generated = TRUE;
2863
ref_length = DATA_ROW_ID_LEN;
2865
/* If we automatically created the clustered index, then
2866
MySQL does not know about it, and MySQL must NOT be aware
2867
of the index used on scan, to make it avoid checking if we
2868
update the column of the index. That is why we assert below
2869
that key_used_on_scan is the undefined value MAX_KEY.
2870
The column is the row id in the automatical generation case,
2871
and it will never be updated anyway. */
2873
if (key_used_on_scan != MAX_KEY) {
2874
errmsg_printf(ERRMSG_LVL_WARN,
2875
"Table %s key_used_on_scan is %lu even "
2876
"though there is no primary key inside "
2877
"InnoDB.", name, (ulong) key_used_on_scan);
2881
/* Index block size in InnoDB: used by MySQL in query optimization */
2882
stats.block_size = 16 * 1024;
2884
/* Init table lock structure */
2885
thr_lock_data_init(&share->lock,&lock,(void*) 0);
2887
if (prebuilt->table) {
2888
/* We update the highest file format in the system table
2889
space, if this table has higher file format setting. */
2891
trx_sys_file_format_max_upgrade(
2892
(const char**) &innobase_file_format_check,
2893
dict_table_get_format(prebuilt->table));
2896
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
2898
/* Only if the table has an AUTOINC column. */
2899
if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
2902
dict_table_autoinc_lock(prebuilt->table);
2904
/* Since a table can already be "open" in InnoDB's internal
2905
data dictionary, we only init the autoinc counter once, the
2906
first time the table is loaded. We can safely reuse the
2907
autoinc value from a previous Drizzle open. */
2908
if (dict_table_autoinc_read(prebuilt->table) == 0) {
2910
error = innobase_initialize_autoinc();
2911
ut_a(error == DB_SUCCESS);
2914
dict_table_autoinc_unlock(prebuilt->table);
2922
2922
InnobaseEngine::max_supported_key_part_length() const
2924
return(DICT_MAX_INDEX_COL_LEN - 1);
2924
return(DICT_MAX_INDEX_COL_LEN - 1);
2927
2927
/******************************************************************//**
2928
2928
Closes a handle to an InnoDB table.
2932
2932
ha_innobase::close(void)
2933
2933
/*====================*/
2937
session = ha_session();
2938
if (session != NULL) {
2939
getTransactionalEngine()->releaseTemporaryLatches(session);
2942
row_prebuilt_free(prebuilt, FALSE);
2947
/* Tell InnoDB server that there might be work for
2950
srv_active_wake_master_thread();
2937
session = ha_session();
2938
if (session != NULL) {
2939
getTransactionalEngine()->releaseTemporaryLatches(session);
2942
row_prebuilt_free(prebuilt, FALSE);
2947
/* Tell InnoDB server that there might be work for
2950
srv_active_wake_master_thread();
2955
2955
/* The following accessor functions should really be inside MySQL code! */
2957
2957
/**************************************************************//**
2958
2958
Gets field offset for a field in a table.
2962
2962
get_field_offset(
2963
2963
/*=============*/
2964
Table* table, /*!< in: MySQL table object */
2965
Field* field) /*!< in: MySQL field object */
2964
Table* table, /*!< in: MySQL table object */
2965
Field* field) /*!< in: MySQL field object */
2967
return((uint) (field->ptr - table->record[0]));
2967
return((uint) (field->ptr - table->record[0]));
2970
2970
/**************************************************************//**
2971
2971
Checks if a field in a record is SQL NULL. Uses the record format
2972
2972
information in table to track the null bit in record.
2973
@return 1 if NULL, 0 otherwise */
2973
@return 1 if NULL, 0 otherwise */
2976
2976
field_in_record_is_null(
2977
2977
/*====================*/
2978
Table* table, /*!< in: MySQL table object */
2979
Field* field, /*!< in: MySQL field object */
2980
char* record) /*!< in: a row in MySQL format */
2978
Table* table, /*!< in: MySQL table object */
2979
Field* field, /*!< in: MySQL field object */
2980
char* record) /*!< in: a row in MySQL format */
2984
if (!field->null_ptr) {
2989
null_offset = (uint) ((char*) field->null_ptr
2990
- (char*) table->record[0]);
2992
if (record[null_offset] & field->null_bit) {
2984
if (!field->null_ptr) {
2989
null_offset = (uint) ((char*) field->null_ptr
2990
- (char*) table->record[0]);
2992
if (record[null_offset] & field->null_bit) {
3000
3000
/**************************************************************//**
3021
3021
is such that we must use MySQL code to compare them. NOTE that the prototype
3022
3022
of this function is in rem0cmp.c in InnoDB source code! If you change this
3023
3023
function, remember to update the prototype there!
3024
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
3024
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
3025
3025
extern "C" UNIV_INTERN
3027
3027
innobase_mysql_cmp(
3028
3028
/*===============*/
3029
int mysql_type, /*!< in: MySQL type */
3030
uint charset_number, /*!< in: number of the charset */
3031
const unsigned char* a, /*!< in: data field */
3032
unsigned int a_length, /*!< in: data field length,
3033
not UNIV_SQL_NULL */
3034
const unsigned char* b, /* in: data field */
3035
unsigned int b_length); /* in: data field length,
3036
not UNIV_SQL_NULL */
3029
int mysql_type, /*!< in: MySQL type */
3030
uint charset_number, /*!< in: number of the charset */
3031
const unsigned char* a, /*!< in: data field */
3032
unsigned int a_length, /*!< in: data field length,
3033
not UNIV_SQL_NULL */
3034
const unsigned char* b, /* in: data field */
3035
unsigned int b_length); /* in: data field length,
3036
not UNIV_SQL_NULL */
3039
3039
innobase_mysql_cmp(
3040
3040
/*===============*/
3041
/* out: 1, 0, -1, if a is greater,
3042
equal, less than b, respectively */
3043
int mysql_type, /* in: MySQL type */
3044
uint charset_number, /* in: number of the charset */
3045
const unsigned char* a, /* in: data field */
3046
unsigned int a_length, /* in: data field length,
3047
not UNIV_SQL_NULL */
3048
const unsigned char* b, /* in: data field */
3049
unsigned int b_length) /* in: data field length,
3050
not UNIV_SQL_NULL */
3041
/* out: 1, 0, -1, if a is greater,
3042
equal, less than b, respectively */
3043
int mysql_type, /* in: MySQL type */
3044
uint charset_number, /* in: number of the charset */
3045
const unsigned char* a, /* in: data field */
3046
unsigned int a_length, /* in: data field length,
3047
not UNIV_SQL_NULL */
3048
const unsigned char* b, /* in: data field */
3049
unsigned int b_length) /* in: data field length,
3050
not UNIV_SQL_NULL */
3052
const CHARSET_INFO* charset;
3053
enum_field_types mysql_tp;
3056
assert(a_length != UNIV_SQL_NULL);
3057
assert(b_length != UNIV_SQL_NULL);
3059
mysql_tp = (enum_field_types) mysql_type;
3063
case DRIZZLE_TYPE_BLOB:
3064
case DRIZZLE_TYPE_VARCHAR:
3065
/* Use the charset number to pick the right charset struct for
3066
the comparison. Since the MySQL function get_charset may be
3067
slow before Bar removes the mutex operation there, we first
3068
look at 2 common charsets directly. */
3070
if (charset_number == default_charset_info->number) {
3071
charset = default_charset_info;
3073
charset = get_charset(charset_number);
3075
if (charset == NULL) {
3076
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
3077
"a comparison, but MySQL cannot "
3078
"find that charset.",
3079
(ulong) charset_number);
3084
/* Starting from 4.1.3, we use strnncollsp() in comparisons of
3085
non-latin1_swedish_ci strings. NOTE that the collation order
3086
changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users
3087
having indexes on such data need to rebuild their tables! */
3089
ret = charset->coll->strnncollsp(charset,
3094
} else if (ret > 0) {
3052
const CHARSET_INFO* charset;
3053
enum_field_types mysql_tp;
3056
assert(a_length != UNIV_SQL_NULL);
3057
assert(b_length != UNIV_SQL_NULL);
3059
mysql_tp = (enum_field_types) mysql_type;
3063
case DRIZZLE_TYPE_BLOB:
3064
case DRIZZLE_TYPE_VARCHAR:
3065
/* Use the charset number to pick the right charset struct for
3066
the comparison. Since the MySQL function get_charset may be
3067
slow before Bar removes the mutex operation there, we first
3068
look at 2 common charsets directly. */
3070
if (charset_number == default_charset_info->number) {
3071
charset = default_charset_info;
3073
charset = get_charset(charset_number);
3075
if (charset == NULL) {
3076
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
3077
"a comparison, but MySQL cannot "
3078
"find that charset.",
3079
(ulong) charset_number);
3084
/* Starting from 4.1.3, we use strnncollsp() in comparisons of
3085
non-latin1_swedish_ci strings. NOTE that the collation order
3086
changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users
3087
having indexes on such data need to rebuild their tables! */
3089
ret = charset->coll->strnncollsp(charset,
3094
} else if (ret > 0) {
3106
3106
/**************************************************************//**
3107
3107
Converts a MySQL type to an InnoDB type. Note that this function returns
3108
3108
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
3109
3109
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'.
3110
@return DATA_BINARY, DATA_VARCHAR, ... */
3110
@return DATA_BINARY, DATA_VARCHAR, ... */
3111
3111
extern "C" UNIV_INTERN
3113
3113
get_innobase_type_from_mysql_type(
3114
3114
/*==============================*/
3115
ulint* unsigned_flag, /*!< out: DATA_UNSIGNED if an
3117
at least ENUM and SET,
3118
and unsigned integer
3119
types are 'unsigned types' */
3120
const void* f) /*!< in: MySQL Field */
3115
ulint* unsigned_flag, /*!< out: DATA_UNSIGNED if an
3117
at least ENUM and SET,
3118
and unsigned integer
3119
types are 'unsigned types' */
3120
const void* f) /*!< in: MySQL Field */
3122
const class Field* field = reinterpret_cast<const class Field*>(f);
3124
/* The following asserts try to check that the MySQL type code fits in
3125
8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
3128
assert((ulint)DRIZZLE_TYPE_DOUBLE < 256);
3130
if (field->flags & UNSIGNED_FLAG) {
3132
*unsigned_flag = DATA_UNSIGNED;
3137
if (field->real_type() == DRIZZLE_TYPE_ENUM)
3139
/* MySQL has field->type() a string type for these, but the
3140
data is actually internally stored as an unsigned integer
3143
*unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
3144
flag set to zero, even though
3145
internally this is an unsigned
3150
switch (field->type()) {
3151
/* NOTE that we only allow string types in DATA_DRIZZLE and
3153
case DRIZZLE_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */
3154
if (field->binary()) {
3155
return(DATA_BINARY);
3157
return(DATA_VARMYSQL);
3159
case DRIZZLE_TYPE_DECIMAL:
3160
return(DATA_FIXBINARY);
3161
case DRIZZLE_TYPE_LONG:
3162
case DRIZZLE_TYPE_LONGLONG:
3163
case DRIZZLE_TYPE_DATETIME:
3164
case DRIZZLE_TYPE_DATE:
3165
case DRIZZLE_TYPE_TIMESTAMP:
3167
case DRIZZLE_TYPE_DOUBLE:
3168
return(DATA_DOUBLE);
3169
case DRIZZLE_TYPE_BLOB:
3122
const class Field* field = reinterpret_cast<const class Field*>(f);
3124
/* The following asserts try to check that the MySQL type code fits in
3125
8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
3128
assert((ulint)DRIZZLE_TYPE_DOUBLE < 256);
3130
if (field->flags & UNSIGNED_FLAG) {
3132
*unsigned_flag = DATA_UNSIGNED;
3137
if (field->real_type() == DRIZZLE_TYPE_ENUM)
3139
/* MySQL has field->type() a string type for these, but the
3140
data is actually internally stored as an unsigned integer
3143
*unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
3144
flag set to zero, even though
3145
internally this is an unsigned
3150
switch (field->type()) {
3151
/* NOTE that we only allow string types in DATA_DRIZZLE and
3153
case DRIZZLE_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */
3154
if (field->binary()) {
3155
return(DATA_BINARY);
3157
return(DATA_VARMYSQL);
3159
case DRIZZLE_TYPE_DECIMAL:
3160
return(DATA_FIXBINARY);
3161
case DRIZZLE_TYPE_LONG:
3162
case DRIZZLE_TYPE_LONGLONG:
3163
case DRIZZLE_TYPE_DATETIME:
3164
case DRIZZLE_TYPE_DATE:
3165
case DRIZZLE_TYPE_TIMESTAMP:
3167
case DRIZZLE_TYPE_DOUBLE:
3168
return(DATA_DOUBLE);
3169
case DRIZZLE_TYPE_BLOB:
3170
3170
return(DATA_BLOB);
3178
3178
/*******************************************************************//**
3183
3183
innobase_write_to_2_little_endian(
3184
3184
/*==============================*/
3185
byte* buf, /*!< in: where to store */
3186
ulint val) /*!< in: value to write, must be < 64k */
3185
byte* buf, /*!< in: where to store */
3186
ulint val) /*!< in: value to write, must be < 64k */
3188
ut_a(val < 256 * 256);
3188
ut_a(val < 256 * 256);
3190
buf[0] = (byte)(val & 0xFF);
3191
buf[1] = (byte)(val / 256);
3190
buf[0] = (byte)(val & 0xFF);
3191
buf[1] = (byte)(val / 256);
3194
3194
/*******************************************************************//**
3195
3195
Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
3196
3196
storage format.
3200
3200
innobase_read_from_2_little_endian(
3201
3201
/*===============================*/
3202
const unsigned char* buf) /*!< in: from where to read */
3202
const unsigned char* buf) /*!< in: from where to read */
3204
return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
3204
return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
3207
3207
/*******************************************************************//**
3208
3208
Stores a key value for a row to a buffer.
3209
@return key value length as stored in buff */
3209
@return key value length as stored in buff */
3212
3212
ha_innobase::store_key_val_for_row(
3213
3213
/*===============================*/
3214
uint keynr, /*!< in: key number */
3215
char* buff, /*!< in/out: buffer for the key value (in MySQL
3217
uint buff_len,/*!< in: buffer length */
3218
const unsigned char* record)/*!< in: row in MySQL format */
3214
uint keynr, /*!< in: key number */
3215
char* buff, /*!< in/out: buffer for the key value (in MySQL
3217
uint buff_len,/*!< in: buffer length */
3218
const unsigned char* record)/*!< in: row in MySQL format */
3220
KEY* key_info = table->key_info + keynr;
3221
KEY_PART_INFO* key_part = key_info->key_part;
3222
KEY_PART_INFO* end = key_part + key_info->key_parts;
3223
char* buff_start = buff;
3224
enum_field_types mysql_type;
3228
/* The format for storing a key field in MySQL is the following:
3230
1. If the column can be NULL, then in the first byte we put 1 if the
3231
field value is NULL, 0 otherwise.
3233
2. If the column is of a BLOB type (it must be a column prefix field
3234
in this case), then we put the length of the data in the field to the
3235
next 2 bytes, in the little-endian format. If the field is SQL NULL,
3236
then these 2 bytes are set to 0. Note that the length of data in the
3237
field is <= column prefix length.
3239
3. In a column prefix field, prefix_len next bytes are reserved for
3240
data. In a normal field the max field length next bytes are reserved
3241
for data. For a VARCHAR(n) the max field length is n. If the stored
3242
value is the SQL NULL then these data bytes are set to 0.
3244
4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
3245
in the MySQL row format, the length is stored in 1 or 2 bytes,
3246
depending on the maximum allowed length. But in the MySQL key value
3247
format, the length always takes 2 bytes.
3249
We have to zero-fill the buffer so that MySQL is able to use a
3250
simple memcmp to compare two key values to determine if they are
3251
equal. MySQL does this to compare contents of two 'ref' values. */
3253
bzero(buff, buff_len);
3255
for (; key_part != end; key_part++) {
3258
if (key_part->null_bit) {
3259
if (record[key_part->null_offset]
3260
& key_part->null_bit) {
3269
field = key_part->field;
3270
mysql_type = field->type();
3272
if (mysql_type == DRIZZLE_TYPE_VARCHAR) {
3273
/* >= 5.0.3 true VARCHAR */
3279
const CHARSET_INFO* cs;
3282
key_len = key_part->length;
3285
buff += key_len + 2;
3289
cs = field->charset();
3292
(((Field_varstring*)field)->length_bytes);
3294
data = row_mysql_read_true_varchar(&len,
3296
+ (ulint)get_field_offset(table, field)),
3301
/* For multi byte character sets we need to calculate
3302
the true length of the key */
3304
if (len > 0 && cs->mbmaxlen > 1) {
3305
true_len = (ulint) cs->cset->well_formed_len(cs,
3306
(const char *) data,
3307
(const char *) data + len,
3313
/* In a column prefix index, we may need to truncate
3314
the stored value: */
3316
if (true_len > key_len) {
3320
/* The length in a key value is always stored in 2
3323
row_mysql_store_true_var_len((byte*)buff, true_len, 2);
3326
memcpy(buff, data, true_len);
3328
/* Note that we always reserve the maximum possible
3329
length of the true VARCHAR in the key value, though
3330
only len first bytes after the 2 length bytes contain
3331
actual data. The rest of the space was reset to zero
3332
in the bzero() call above. */
3336
} else if (mysql_type == DRIZZLE_TYPE_BLOB) {
3338
const CHARSET_INFO* cs;
3343
const byte* blob_data;
3345
ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
3347
key_len = key_part->length;
3350
buff += key_len + 2;
3355
cs = field->charset();
3357
blob_data = row_mysql_read_blob_ref(&blob_len,
3359
+ (ulint)get_field_offset(table, field)),
3360
(ulint) field->pack_length());
3362
true_len = blob_len;
3364
ut_a(get_field_offset(table, field)
3365
== key_part->offset);
3367
/* For multi byte character sets we need to calculate
3368
the true length of the key */
3370
if (blob_len > 0 && cs->mbmaxlen > 1) {
3371
true_len = (ulint) cs->cset->well_formed_len(cs,
3372
(const char *) blob_data,
3373
(const char *) blob_data
3380
/* All indexes on BLOB and TEXT are column prefix
3381
indexes, and we may need to truncate the data to be
3382
stored in the key value: */
3384
if (true_len > key_len) {
3388
/* MySQL reserves 2 bytes for the length and the
3389
storage of the number is little-endian */
3391
innobase_write_to_2_little_endian(
3392
(byte*)buff, true_len);
3395
memcpy(buff, blob_data, true_len);
3397
/* Note that we always reserve the maximum possible
3398
length of the BLOB prefix in the key value. */
3402
/* Here we handle all other data types except the
3403
true VARCHAR, BLOB and TEXT. Note that the column
3404
value we store may be also in a column prefix
3409
const unsigned char* src_start;
3410
enum_field_types real_type;
3412
key_len = key_part->length;
3420
src_start = record + key_part->offset;
3421
real_type = field->real_type();
3424
/* Character set for the field is defined only
3425
to fields whose type is string and real field
3426
type is not enum or set. For these fields check
3427
if character set is multi byte. */
3429
memcpy(buff, src_start, true_len);
3432
/* Pad the unused space with spaces. Note that no
3433
padding is ever needed for UCS-2 because in MySQL,
3434
all UCS2 characters are 2 bytes, as MySQL does not
3435
support surrogate pairs, which are needed to represent
3436
characters in the range U+10000 to U+10FFFF. */
3438
if (true_len < key_len) {
3439
ulint pad_len = key_len - true_len;
3440
memset(buff, ' ', pad_len);
3446
ut_a(buff <= buff_start + buff_len);
3448
return((uint)(buff - buff_start));
3220
KEY* key_info = table->key_info + keynr;
3221
KEY_PART_INFO* key_part = key_info->key_part;
3222
KEY_PART_INFO* end = key_part + key_info->key_parts;
3223
char* buff_start = buff;
3224
enum_field_types mysql_type;
3228
/* The format for storing a key field in MySQL is the following:
3230
1. If the column can be NULL, then in the first byte we put 1 if the
3231
field value is NULL, 0 otherwise.
3233
2. If the column is of a BLOB type (it must be a column prefix field
3234
in this case), then we put the length of the data in the field to the
3235
next 2 bytes, in the little-endian format. If the field is SQL NULL,
3236
then these 2 bytes are set to 0. Note that the length of data in the
3237
field is <= column prefix length.
3239
3. In a column prefix field, prefix_len next bytes are reserved for
3240
data. In a normal field the max field length next bytes are reserved
3241
for data. For a VARCHAR(n) the max field length is n. If the stored
3242
value is the SQL NULL then these data bytes are set to 0.
3244
4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
3245
in the MySQL row format, the length is stored in 1 or 2 bytes,
3246
depending on the maximum allowed length. But in the MySQL key value
3247
format, the length always takes 2 bytes.
3249
We have to zero-fill the buffer so that MySQL is able to use a
3250
simple memcmp to compare two key values to determine if they are
3251
equal. MySQL does this to compare contents of two 'ref' values. */
3253
bzero(buff, buff_len);
3255
for (; key_part != end; key_part++) {
3258
if (key_part->null_bit) {
3259
if (record[key_part->null_offset]
3260
& key_part->null_bit) {
3269
field = key_part->field;
3270
mysql_type = field->type();
3272
if (mysql_type == DRIZZLE_TYPE_VARCHAR) {
3273
/* >= 5.0.3 true VARCHAR */
3279
const CHARSET_INFO* cs;
3282
key_len = key_part->length;
3285
buff += key_len + 2;
3289
cs = field->charset();
3292
(((Field_varstring*)field)->length_bytes);
3294
data = row_mysql_read_true_varchar(&len,
3296
+ (ulint)get_field_offset(table, field)),
3301
/* For multi byte character sets we need to calculate
3302
the true length of the key */
3304
if (len > 0 && cs->mbmaxlen > 1) {
3305
true_len = (ulint) cs->cset->well_formed_len(cs,
3306
(const char *) data,
3307
(const char *) data + len,
3313
/* In a column prefix index, we may need to truncate
3314
the stored value: */
3316
if (true_len > key_len) {
3320
/* The length in a key value is always stored in 2
3323
row_mysql_store_true_var_len((byte*)buff, true_len, 2);
3326
memcpy(buff, data, true_len);
3328
/* Note that we always reserve the maximum possible
3329
length of the true VARCHAR in the key value, though
3330
only len first bytes after the 2 length bytes contain
3331
actual data. The rest of the space was reset to zero
3332
in the bzero() call above. */
3336
} else if (mysql_type == DRIZZLE_TYPE_BLOB) {
3338
const CHARSET_INFO* cs;
3343
const byte* blob_data;
3345
ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
3347
key_len = key_part->length;
3350
buff += key_len + 2;
3355
cs = field->charset();
3357
blob_data = row_mysql_read_blob_ref(&blob_len,
3359
+ (ulint)get_field_offset(table, field)),
3360
(ulint) field->pack_length());
3362
true_len = blob_len;
3364
ut_a(get_field_offset(table, field)
3365
== key_part->offset);
3367
/* For multi byte character sets we need to calculate
3368
the true length of the key */
3370
if (blob_len > 0 && cs->mbmaxlen > 1) {
3371
true_len = (ulint) cs->cset->well_formed_len(cs,
3372
(const char *) blob_data,
3373
(const char *) blob_data
3380
/* All indexes on BLOB and TEXT are column prefix
3381
indexes, and we may need to truncate the data to be
3382
stored in the key value: */
3384
if (true_len > key_len) {
3388
/* MySQL reserves 2 bytes for the length and the
3389
storage of the number is little-endian */
3391
innobase_write_to_2_little_endian(
3392
(byte*)buff, true_len);
3395
memcpy(buff, blob_data, true_len);
3397
/* Note that we always reserve the maximum possible
3398
length of the BLOB prefix in the key value. */
3402
/* Here we handle all other data types except the
3403
true VARCHAR, BLOB and TEXT. Note that the column
3404
value we store may be also in a column prefix
3409
const unsigned char* src_start;
3410
enum_field_types real_type;
3412
key_len = key_part->length;
3420
src_start = record + key_part->offset;
3421
real_type = field->real_type();
3424
/* Character set for the field is defined only
3425
to fields whose type is string and real field
3426
type is not enum or set. For these fields check
3427
if character set is multi byte. */
3429
memcpy(buff, src_start, true_len);
3432
/* Pad the unused space with spaces. Note that no
3433
padding is ever needed for UCS-2 because in MySQL,
3434
all UCS2 characters are 2 bytes, as MySQL does not
3435
support surrogate pairs, which are needed to represent
3436
characters in the range U+10000 to U+10FFFF. */
3438
if (true_len < key_len) {
3439
ulint pad_len = key_len - true_len;
3440
memset(buff, ' ', pad_len);
3446
ut_a(buff <= buff_start + buff_len);
3448
return((uint)(buff - buff_start));
3451
3451
/**************************************************************//**
3456
3456
build_template(
3457
3457
/*===========*/
3458
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */
3459
Session* , /*!< in: current user thread, used
3460
only if templ_type is
3461
ROW_DRIZZLE_REC_FIELDS */
3462
Table* table, /*!< in: MySQL table */
3463
uint templ_type) /*!< in: ROW_MYSQL_WHOLE_ROW or
3464
ROW_DRIZZLE_REC_FIELDS */
3458
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */
3459
Session* , /*!< in: current user thread, used
3460
only if templ_type is
3461
ROW_DRIZZLE_REC_FIELDS */
3462
Table* table, /*!< in: MySQL table */
3463
uint templ_type) /*!< in: ROW_MYSQL_WHOLE_ROW or
3464
ROW_DRIZZLE_REC_FIELDS */
3466
dict_index_t* index;
3467
dict_index_t* clust_index;
3468
mysql_row_templ_t* templ;
3471
ulint n_requested_fields = 0;
3472
ibool fetch_all_in_key = FALSE;
3473
ibool fetch_primary_key_cols = FALSE;
3475
/* byte offset of the end of last requested column */
3476
ulint mysql_prefix_len = 0;
3478
if (prebuilt->select_lock_type == LOCK_X) {
3479
/* We always retrieve the whole clustered index record if we
3480
use exclusive row level locks, for example, if the read is
3481
done in an UPDATE statement. */
3483
templ_type = ROW_MYSQL_WHOLE_ROW;
3486
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3487
if (prebuilt->hint_need_to_fetch_extra_cols
3488
== ROW_RETRIEVE_ALL_COLS) {
3490
/* We know we must at least fetch all columns in the
3491
key, or all columns in the table */
3493
if (prebuilt->read_just_key) {
3494
/* MySQL has instructed us that it is enough
3495
to fetch the columns in the key; looks like
3496
MySQL can set this flag also when there is
3497
only a prefix of the column in the key: in
3498
that case we retrieve the whole column from
3499
the clustered index */
3501
fetch_all_in_key = TRUE;
3503
templ_type = ROW_MYSQL_WHOLE_ROW;
3505
} else if (prebuilt->hint_need_to_fetch_extra_cols
3506
== ROW_RETRIEVE_PRIMARY_KEY) {
3507
/* We must at least fetch all primary key cols. Note
3508
that if the clustered index was internally generated
3509
by InnoDB on the row id (no primary key was
3510
defined), then row_search_for_mysql() will always
3511
retrieve the row id to a special buffer in the
3514
fetch_primary_key_cols = TRUE;
3518
clust_index = dict_table_get_first_index(prebuilt->table);
3520
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3521
index = prebuilt->index;
3523
index = clust_index;
3526
if (index == clust_index) {
3527
prebuilt->need_to_access_clustered = TRUE;
3529
prebuilt->need_to_access_clustered = FALSE;
3530
/* Below we check column by column if we need to access
3531
the clustered index */
3534
n_fields = (ulint)table->s->fields; /* number of columns */
3536
if (!prebuilt->mysql_template) {
3537
prebuilt->mysql_template = (mysql_row_templ_t*)
3538
mem_alloc(n_fields * sizeof(mysql_row_templ_t));
3541
prebuilt->template_type = templ_type;
3542
prebuilt->null_bitmap_len = table->s->null_bytes;
3544
prebuilt->templ_contains_blob = FALSE;
3546
/* Note that in InnoDB, i is the column number. MySQL calls columns
3548
for (i = 0; i < n_fields; i++) {
3549
templ = prebuilt->mysql_template + n_requested_fields;
3550
field = table->field[i];
3552
if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
3553
/* Decide which columns we should fetch
3554
and which we can skip. */
3555
register const ibool index_contains_field =
3556
dict_index_contains_col_or_prefix(index, i);
3558
if (!index_contains_field && prebuilt->read_just_key) {
3559
/* If this is a 'key read', we do not need
3560
columns that are not in the key */
3565
if (index_contains_field && fetch_all_in_key) {
3566
/* This field is needed in the query */
3466
dict_index_t* index;
3467
dict_index_t* clust_index;
3468
mysql_row_templ_t* templ;
3471
ulint n_requested_fields = 0;
3472
ibool fetch_all_in_key = FALSE;
3473
ibool fetch_primary_key_cols = FALSE;
3475
/* byte offset of the end of last requested column */
3476
ulint mysql_prefix_len = 0;
3478
if (prebuilt->select_lock_type == LOCK_X) {
3479
/* We always retrieve the whole clustered index record if we
3480
use exclusive row level locks, for example, if the read is
3481
done in an UPDATE statement. */
3483
templ_type = ROW_MYSQL_WHOLE_ROW;
3486
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3487
if (prebuilt->hint_need_to_fetch_extra_cols
3488
== ROW_RETRIEVE_ALL_COLS) {
3490
/* We know we must at least fetch all columns in the
3491
key, or all columns in the table */
3493
if (prebuilt->read_just_key) {
3494
/* MySQL has instructed us that it is enough
3495
to fetch the columns in the key; looks like
3496
MySQL can set this flag also when there is
3497
only a prefix of the column in the key: in
3498
that case we retrieve the whole column from
3499
the clustered index */
3501
fetch_all_in_key = TRUE;
3503
templ_type = ROW_MYSQL_WHOLE_ROW;
3505
} else if (prebuilt->hint_need_to_fetch_extra_cols
3506
== ROW_RETRIEVE_PRIMARY_KEY) {
3507
/* We must at least fetch all primary key cols. Note
3508
that if the clustered index was internally generated
3509
by InnoDB on the row id (no primary key was
3510
defined), then row_search_for_mysql() will always
3511
retrieve the row id to a special buffer in the
3514
fetch_primary_key_cols = TRUE;
3518
clust_index = dict_table_get_first_index(prebuilt->table);
3520
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3521
index = prebuilt->index;
3523
index = clust_index;
3526
if (index == clust_index) {
3527
prebuilt->need_to_access_clustered = TRUE;
3529
prebuilt->need_to_access_clustered = FALSE;
3530
/* Below we check column by column if we need to access
3531
the clustered index */
3534
n_fields = (ulint)table->s->fields; /* number of columns */
3536
if (!prebuilt->mysql_template) {
3537
prebuilt->mysql_template = (mysql_row_templ_t*)
3538
mem_alloc(n_fields * sizeof(mysql_row_templ_t));
3541
prebuilt->template_type = templ_type;
3542
prebuilt->null_bitmap_len = table->s->null_bytes;
3544
prebuilt->templ_contains_blob = FALSE;
3546
/* Note that in InnoDB, i is the column number. MySQL calls columns
3548
for (i = 0; i < n_fields; i++) {
3549
templ = prebuilt->mysql_template + n_requested_fields;
3550
field = table->field[i];
3552
if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
3553
/* Decide which columns we should fetch
3554
and which we can skip. */
3555
register const ibool index_contains_field =
3556
dict_index_contains_col_or_prefix(index, i);
3558
if (!index_contains_field && prebuilt->read_just_key) {
3559
/* If this is a 'key read', we do not need
3560
columns that are not in the key */
3565
if (index_contains_field && fetch_all_in_key) {
3566
/* This field is needed in the query */
3571
3571
if (field->isReadSet() || field->isWriteSet())
3572
/* This field is needed in the query */
3572
/* This field is needed in the query */
3575
3575
assert(table->isReadSet(i) == field->isReadSet());
3576
3576
assert(table->isWriteSet(i) == field->isWriteSet());
3578
if (fetch_primary_key_cols
3579
&& dict_table_col_in_clustered_key(
3581
/* This field is needed in the query */
3586
/* This field is not needed in the query, skip it */
3578
if (fetch_primary_key_cols
3579
&& dict_table_col_in_clustered_key(
3581
/* This field is needed in the query */
3586
/* This field is not needed in the query, skip it */
3591
n_requested_fields++;
3595
if (index == clust_index) {
3596
templ->rec_field_no = dict_col_get_clust_pos(
3597
&index->table->cols[i], index);
3599
templ->rec_field_no = dict_index_get_nth_col_pos(
3603
if (templ->rec_field_no == ULINT_UNDEFINED) {
3604
prebuilt->need_to_access_clustered = TRUE;
3607
if (field->null_ptr) {
3608
templ->mysql_null_byte_offset =
3609
(ulint) ((char*) field->null_ptr
3610
- (char*) table->record[0]);
3612
templ->mysql_null_bit_mask = (ulint) field->null_bit;
3614
templ->mysql_null_bit_mask = 0;
3617
templ->mysql_col_offset = (ulint)
3618
get_field_offset(table, field);
3620
templ->mysql_col_len = (ulint) field->pack_length();
3621
if (mysql_prefix_len < templ->mysql_col_offset
3622
+ templ->mysql_col_len) {
3623
mysql_prefix_len = templ->mysql_col_offset
3624
+ templ->mysql_col_len;
3626
templ->type = index->table->cols[i].mtype;
3627
templ->mysql_type = (ulint)field->type();
3629
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
3630
templ->mysql_length_bytes = (ulint)
3631
(((Field_varstring*)field)->length_bytes);
3634
templ->charset = dtype_get_charset_coll(
3635
index->table->cols[i].prtype);
3636
templ->mbminlen = index->table->cols[i].mbminlen;
3637
templ->mbmaxlen = index->table->cols[i].mbmaxlen;
3638
templ->is_unsigned = index->table->cols[i].prtype
3640
if (templ->type == DATA_BLOB) {
3641
prebuilt->templ_contains_blob = TRUE;
3591
n_requested_fields++;
3595
if (index == clust_index) {
3596
templ->rec_field_no = dict_col_get_clust_pos(
3597
&index->table->cols[i], index);
3599
templ->rec_field_no = dict_index_get_nth_col_pos(
3603
if (templ->rec_field_no == ULINT_UNDEFINED) {
3604
prebuilt->need_to_access_clustered = TRUE;
3607
if (field->null_ptr) {
3608
templ->mysql_null_byte_offset =
3609
(ulint) ((char*) field->null_ptr
3610
- (char*) table->record[0]);
3612
templ->mysql_null_bit_mask = (ulint) field->null_bit;
3614
templ->mysql_null_bit_mask = 0;
3617
templ->mysql_col_offset = (ulint)
3618
get_field_offset(table, field);
3620
templ->mysql_col_len = (ulint) field->pack_length();
3621
if (mysql_prefix_len < templ->mysql_col_offset
3622
+ templ->mysql_col_len) {
3623
mysql_prefix_len = templ->mysql_col_offset
3624
+ templ->mysql_col_len;
3626
templ->type = index->table->cols[i].mtype;
3627
templ->mysql_type = (ulint)field->type();
3629
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
3630
templ->mysql_length_bytes = (ulint)
3631
(((Field_varstring*)field)->length_bytes);
3634
templ->charset = dtype_get_charset_coll(
3635
index->table->cols[i].prtype);
3636
templ->mbminlen = index->table->cols[i].mbminlen;
3637
templ->mbmaxlen = index->table->cols[i].mbmaxlen;
3638
templ->is_unsigned = index->table->cols[i].prtype
3640
if (templ->type == DATA_BLOB) {
3641
prebuilt->templ_contains_blob = TRUE;
3647
prebuilt->n_template = n_requested_fields;
3648
prebuilt->mysql_prefix_len = mysql_prefix_len;
3650
if (index != clust_index && prebuilt->need_to_access_clustered) {
3651
/* Change rec_field_no's to correspond to the clustered index
3653
for (i = 0; i < n_requested_fields; i++) {
3654
templ = prebuilt->mysql_template + i;
3656
templ->rec_field_no = dict_col_get_clust_pos(
3657
&index->table->cols[templ->col_no],
3647
prebuilt->n_template = n_requested_fields;
3648
prebuilt->mysql_prefix_len = mysql_prefix_len;
3650
if (index != clust_index && prebuilt->need_to_access_clustered) {
3651
/* Change rec_field_no's to correspond to the clustered index
3653
for (i = 0; i < n_requested_fields; i++) {
3654
templ = prebuilt->mysql_template + i;
3656
templ->rec_field_no = dict_col_get_clust_pos(
3657
&index->table->cols[templ->col_no],
3663
3663
/********************************************************************//**
3710
3710
INSERT ... SELECT type of statements, since MySQL binlog only stores the
3711
3711
min value of the autoinc interval. Once that is fixed we can get rid of
3712
3712
the special lock handling.
3713
@return DB_SUCCESS if all OK else error code */
3713
@return DB_SUCCESS if all OK else error code */
3716
3716
ha_innobase::innobase_lock_autoinc(void)
3717
3717
/*====================================*/
3719
ulint error = DB_SUCCESS;
3721
switch (innobase_autoinc_lock_mode) {
3722
case AUTOINC_NO_LOCKING:
3723
/* Acquire only the AUTOINC mutex. */
3724
dict_table_autoinc_lock(prebuilt->table);
3727
case AUTOINC_NEW_STYLE_LOCKING:
3728
/* For simple (single/multi) row INSERTs, we fallback to the
3729
old style only if another transaction has already acquired
3730
the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
3731
etc. type of statement. */
3732
if (session_sql_command(user_session) == SQLCOM_INSERT
3733
|| session_sql_command(user_session) == SQLCOM_REPLACE) {
3734
dict_table_t* d_table = prebuilt->table;
3736
/* Acquire the AUTOINC mutex. */
3737
dict_table_autoinc_lock(d_table);
3739
/* We need to check that another transaction isn't
3740
already holding the AUTOINC lock on the table. */
3741
if (d_table->n_waiting_or_granted_auto_inc_locks) {
3742
/* Release the mutex to avoid deadlocks. */
3743
dict_table_autoinc_unlock(d_table);
3748
/* Fall through to old style locking. */
3750
case AUTOINC_OLD_STYLE_LOCKING:
3751
error = row_lock_table_autoinc_for_mysql(prebuilt);
3753
if (error == DB_SUCCESS) {
3755
/* Acquire the AUTOINC mutex. */
3756
dict_table_autoinc_lock(prebuilt->table);
3764
return(ulong(error));
3719
ulint error = DB_SUCCESS;
3721
switch (innobase_autoinc_lock_mode) {
3722
case AUTOINC_NO_LOCKING:
3723
/* Acquire only the AUTOINC mutex. */
3724
dict_table_autoinc_lock(prebuilt->table);
3727
case AUTOINC_NEW_STYLE_LOCKING:
3728
/* For simple (single/multi) row INSERTs, we fallback to the
3729
old style only if another transaction has already acquired
3730
the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
3731
etc. type of statement. */
3732
if (session_sql_command(user_session) == SQLCOM_INSERT
3733
|| session_sql_command(user_session) == SQLCOM_REPLACE) {
3734
dict_table_t* d_table = prebuilt->table;
3736
/* Acquire the AUTOINC mutex. */
3737
dict_table_autoinc_lock(d_table);
3739
/* We need to check that another transaction isn't
3740
already holding the AUTOINC lock on the table. */
3741
if (d_table->n_waiting_or_granted_auto_inc_locks) {
3742
/* Release the mutex to avoid deadlocks. */
3743
dict_table_autoinc_unlock(d_table);
3748
/* Fall through to old style locking. */
3750
case AUTOINC_OLD_STYLE_LOCKING:
3751
error = row_lock_table_autoinc_for_mysql(prebuilt);
3753
if (error == DB_SUCCESS) {
3755
/* Acquire the AUTOINC mutex. */
3756
dict_table_autoinc_lock(prebuilt->table);
3764
return(ulong(error));
3767
3767
/********************************************************************//**
3768
3768
Reset the autoinc value in the table.
3769
@return DB_SUCCESS if all went well else error code */
3769
@return DB_SUCCESS if all went well else error code */
3772
3772
ha_innobase::innobase_reset_autoinc(
3773
3773
/*================================*/
3774
uint64_t autoinc) /*!< in: value to store */
3774
uint64_t autoinc) /*!< in: value to store */
3778
error = innobase_lock_autoinc();
3780
if (error == DB_SUCCESS) {
3782
dict_table_autoinc_initialize(prebuilt->table, autoinc);
3784
dict_table_autoinc_unlock(prebuilt->table);
3787
return(ulong(error));
3778
error = innobase_lock_autoinc();
3780
if (error == DB_SUCCESS) {
3782
dict_table_autoinc_initialize(prebuilt->table, autoinc);
3784
dict_table_autoinc_unlock(prebuilt->table);
3787
return(ulong(error));
3790
3790
/********************************************************************//**
3791
3791
Store the autoinc value in the table. The autoinc value is only set if
3792
3792
it's greater than the existing autoinc value in the table.
3793
@return DB_SUCCESS if all went well else error code */
3793
@return DB_SUCCESS if all went well else error code */
3796
3796
ha_innobase::innobase_set_max_autoinc(
3797
3797
/*==================================*/
3798
uint64_t auto_inc) /*!< in: value to store */
3798
uint64_t auto_inc) /*!< in: value to store */
3802
error = innobase_lock_autoinc();
3804
if (error == DB_SUCCESS) {
3806
dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
3808
dict_table_autoinc_unlock(prebuilt->table);
3811
return(ulong(error));
3802
error = innobase_lock_autoinc();
3804
if (error == DB_SUCCESS) {
3806
dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
3808
dict_table_autoinc_unlock(prebuilt->table);
3811
return(ulong(error));
3814
3814
/********************************************************************//**
3815
3815
Stores a row in an InnoDB database, to the table specified in this
3817
@return error code */
3817
@return error code */
3820
3820
ha_innobase::write_row(
3821
3821
/*===================*/
3822
unsigned char* record) /*!< in: a row in MySQL format */
3822
unsigned char* record) /*!< in: a row in MySQL format */
3825
3825
int error_result= 0;
3826
ibool auto_inc_used= FALSE;
3828
trx_t* trx = session_to_trx(user_session);
3830
if (prebuilt->trx != trx) {
3831
errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
3832
"%p, but for the current thread it is at %p",
3833
(const void*) prebuilt->trx, (const void*) trx);
3835
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
3836
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
3838
"InnoDB: Dump of 200 bytes around ha_data: ",
3840
ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
3845
ha_statistic_increment(&system_status_var::ha_write_count);
3847
sql_command = session_sql_command(user_session);
3849
if ((sql_command == SQLCOM_ALTER_TABLE
3850
|| sql_command == SQLCOM_CREATE_INDEX
3851
|| sql_command == SQLCOM_DROP_INDEX)
3852
&& num_write_row >= 10000) {
3853
/* ALTER TABLE is COMMITted at every 10000 copied rows.
3854
The IX table lock for the original table has to be re-issued.
3855
As this method will be called on a temporary table where the
3856
contents of the original table is being copied to, it is
3857
a bit tricky to determine the source table. The cursor
3858
position in the source table need not be adjusted after the
3859
intermediate COMMIT, since writes by other transactions are
3860
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
3862
dict_table_t* src_table;
3863
enum lock_mode mode;
3867
/* Commit the transaction. This will release the table
3868
locks, so they have to be acquired again. */
3870
/* Altering an InnoDB table */
3871
/* Get the source table. */
3872
src_table = lock_get_src_table(
3873
prebuilt->trx, prebuilt->table, &mode);
3826
ibool auto_inc_used= FALSE;
3828
trx_t* trx = session_to_trx(user_session);
3830
if (prebuilt->trx != trx) {
3831
errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
3832
"%p, but for the current thread it is at %p",
3833
(const void*) prebuilt->trx, (const void*) trx);
3835
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
3836
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
3838
"InnoDB: Dump of 200 bytes around ha_data: ",
3840
ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
3845
ha_statistic_increment(&system_status_var::ha_write_count);
3847
sql_command = session_sql_command(user_session);
3849
if ((sql_command == SQLCOM_ALTER_TABLE
3850
|| sql_command == SQLCOM_CREATE_INDEX
3851
|| sql_command == SQLCOM_DROP_INDEX)
3852
&& num_write_row >= 10000) {
3853
/* ALTER TABLE is COMMITted at every 10000 copied rows.
3854
The IX table lock for the original table has to be re-issued.
3855
As this method will be called on a temporary table where the
3856
contents of the original table is being copied to, it is
3857
a bit tricky to determine the source table. The cursor
3858
position in the source table need not be adjusted after the
3859
intermediate COMMIT, since writes by other transactions are
3860
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
3862
dict_table_t* src_table;
3863
enum lock_mode mode;
3867
/* Commit the transaction. This will release the table
3868
locks, so they have to be acquired again. */
3870
/* Altering an InnoDB table */
3871
/* Get the source table. */
3872
src_table = lock_get_src_table(
3873
prebuilt->trx, prebuilt->table, &mode);
3876
/* Unknown situation: do not commit */
3878
ut_print_timestamp(stderr);
3880
" InnoDB: ALTER TABLE is holding lock"
3881
" on %lu tables!\n",
3882
prebuilt->trx->mysql_n_tables_locked);
3885
} else if (src_table == prebuilt->table) {
3886
/* Source table is not in InnoDB format:
3887
no need to re-acquire locks on it. */
3889
/* Altering to InnoDB format */
3890
getTransactionalEngine()->commit(user_session, 1);
3891
/* We will need an IX lock on the destination table. */
3892
prebuilt->sql_stat_start = TRUE;
3894
/* Ensure that there are no other table locks than
3895
LOCK_IX and LOCK_AUTO_INC on the destination table. */
3897
if (!lock_is_table_exclusive(prebuilt->table,
3902
/* Commit the transaction. This will release the table
3903
locks, so they have to be acquired again. */
3904
getTransactionalEngine()->commit(user_session, 1);
3905
/* Re-acquire the table lock on the source table. */
3906
row_lock_table_for_mysql(prebuilt, src_table, mode);
3907
/* We will need an IX lock on the destination table. */
3908
prebuilt->sql_stat_start = TRUE;
3914
/* This is the case where the table has an auto-increment column */
3915
if (table->next_number_field && record == table->record[0]) {
3917
/* Reset the error code before calling
3918
innobase_get_auto_increment(). */
3919
prebuilt->autoinc_error = DB_SUCCESS;
3921
if ((error = update_auto_increment())) {
3923
/* We don't want to mask autoinc overflow errors. */
3924
if (prebuilt->autoinc_error != DB_SUCCESS) {
3925
error = (int) prebuilt->autoinc_error;
3930
/* MySQL errors are passed straight back. */
3931
error_result = (int) error;
3935
auto_inc_used = TRUE;
3938
if (prebuilt->mysql_template == NULL
3939
|| prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
3941
/* Build the template used in converting quickly between
3942
the two database formats */
3944
build_template(prebuilt, NULL, table,
3945
ROW_MYSQL_WHOLE_ROW);
3948
innodb_srv_conc_enter_innodb(prebuilt->trx);
3950
error = row_insert_for_mysql((byte*) record, prebuilt);
3952
/* Handle duplicate key errors */
3953
if (auto_inc_used) {
3956
uint64_t col_max_value;
3958
/* Note the number of rows processed for this statement, used
3959
by get_auto_increment() to determine the number of AUTO-INC
3960
values to reserve. This is only useful for a mult-value INSERT
3961
and is a statement level counter.*/
3962
if (trx->n_autoinc_rows > 0) {
3963
--trx->n_autoinc_rows;
3966
/* We need the upper limit of the col type to check for
3967
whether we update the table autoinc counter or not. */
3968
col_max_value = innobase_get_int_col_max_value(
3969
table->next_number_field);
3971
/* Get the value that MySQL attempted to store in the table.*/
3972
auto_inc = table->next_number_field->val_int();
3975
case DB_DUPLICATE_KEY:
3977
/* A REPLACE command and LOAD DATA INFILE REPLACE
3978
handle a duplicate key error themselves, but we
3979
must update the autoinc counter if we are performing
3980
those statements. */
3982
switch (sql_command) {
3984
if ((trx->duplicates
3985
& (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
3987
goto set_max_autoinc;
3991
case SQLCOM_REPLACE:
3992
case SQLCOM_INSERT_SELECT:
3993
case SQLCOM_REPLACE_SELECT:
3994
goto set_max_autoinc;
4003
/* If the actual value inserted is greater than
4004
the upper limit of the interval, then we try and
4005
update the table upper limit. Note: last_value
4006
will be 0 if get_auto_increment() was not called.*/
4008
if (auto_inc <= col_max_value
4009
&& auto_inc >= prebuilt->autoinc_last_value) {
3876
/* Unknown situation: do not commit */
3878
ut_print_timestamp(stderr);
3880
" InnoDB: ALTER TABLE is holding lock"
3881
" on %lu tables!\n",
3882
prebuilt->trx->mysql_n_tables_locked);
3885
} else if (src_table == prebuilt->table) {
3886
/* Source table is not in InnoDB format:
3887
no need to re-acquire locks on it. */
3889
/* Altering to InnoDB format */
3890
getTransactionalEngine()->commit(user_session, 1);
3891
/* We will need an IX lock on the destination table. */
3892
prebuilt->sql_stat_start = TRUE;
3894
/* Ensure that there are no other table locks than
3895
LOCK_IX and LOCK_AUTO_INC on the destination table. */
3897
if (!lock_is_table_exclusive(prebuilt->table,
3902
/* Commit the transaction. This will release the table
3903
locks, so they have to be acquired again. */
3904
getTransactionalEngine()->commit(user_session, 1);
3905
/* Re-acquire the table lock on the source table. */
3906
row_lock_table_for_mysql(prebuilt, src_table, mode);
3907
/* We will need an IX lock on the destination table. */
3908
prebuilt->sql_stat_start = TRUE;
3914
/* This is the case where the table has an auto-increment column */
3915
if (table->next_number_field && record == table->record[0]) {
3917
/* Reset the error code before calling
3918
innobase_get_auto_increment(). */
3919
prebuilt->autoinc_error = DB_SUCCESS;
3921
if ((error = update_auto_increment())) {
3923
/* We don't want to mask autoinc overflow errors. */
3924
if (prebuilt->autoinc_error != DB_SUCCESS) {
3925
error = (int) prebuilt->autoinc_error;
3930
/* MySQL errors are passed straight back. */
3931
error_result = (int) error;
3935
auto_inc_used = TRUE;
3938
if (prebuilt->mysql_template == NULL
3939
|| prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
3941
/* Build the template used in converting quickly between
3942
the two database formats */
3944
build_template(prebuilt, NULL, table,
3945
ROW_MYSQL_WHOLE_ROW);
3948
innodb_srv_conc_enter_innodb(prebuilt->trx);
3950
error = row_insert_for_mysql((byte*) record, prebuilt);
3952
/* Handle duplicate key errors */
3953
if (auto_inc_used) {
3956
uint64_t col_max_value;
3958
/* Note the number of rows processed for this statement, used
3959
by get_auto_increment() to determine the number of AUTO-INC
3960
values to reserve. This is only useful for a mult-value INSERT
3961
and is a statement level counter.*/
3962
if (trx->n_autoinc_rows > 0) {
3963
--trx->n_autoinc_rows;
3966
/* We need the upper limit of the col type to check for
3967
whether we update the table autoinc counter or not. */
3968
col_max_value = innobase_get_int_col_max_value(
3969
table->next_number_field);
3971
/* Get the value that MySQL attempted to store in the table.*/
3972
auto_inc = table->next_number_field->val_int();
3975
case DB_DUPLICATE_KEY:
3977
/* A REPLACE command and LOAD DATA INFILE REPLACE
3978
handle a duplicate key error themselves, but we
3979
must update the autoinc counter if we are performing
3980
those statements. */
3982
switch (sql_command) {
3984
if ((trx->duplicates
3985
& (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
3987
goto set_max_autoinc;
3991
case SQLCOM_REPLACE:
3992
case SQLCOM_INSERT_SELECT:
3993
case SQLCOM_REPLACE_SELECT:
3994
goto set_max_autoinc;
4003
/* If the actual value inserted is greater than
4004
the upper limit of the interval, then we try and
4005
update the table upper limit. Note: last_value
4006
will be 0 if get_auto_increment() was not called.*/
4008
if (auto_inc <= col_max_value
4009
&& auto_inc >= prebuilt->autoinc_last_value) {
4010
4010
set_max_autoinc:
4011
ut_a(prebuilt->autoinc_increment > 0);
4016
offset = prebuilt->autoinc_offset;
4017
need = prebuilt->autoinc_increment;
4019
auto_inc = innobase_next_autoinc(
4020
auto_inc, need, offset, col_max_value);
4022
err = innobase_set_max_autoinc(auto_inc);
4024
if (err != DB_SUCCESS) {
4032
innodb_srv_conc_exit_innodb(prebuilt->trx);
4011
ut_a(prebuilt->autoinc_increment > 0);
4016
offset = prebuilt->autoinc_offset;
4017
need = prebuilt->autoinc_increment;
4019
auto_inc = innobase_next_autoinc(
4020
auto_inc, need, offset, col_max_value);
4022
err = innobase_set_max_autoinc(auto_inc);
4024
if (err != DB_SUCCESS) {
4032
innodb_srv_conc_exit_innodb(prebuilt->trx);
4035
error_result = convert_error_code_to_mysql((int) error,
4036
prebuilt->table->flags,
4035
error_result = convert_error_code_to_mysql((int) error,
4036
prebuilt->table->flags,
4040
innobase_active_small();
4040
innobase_active_small();
4042
return(error_result);
4042
return(error_result);
4045
4045
/**********************************************************************//**
4046
4046
Checks which fields have changed in a row and stores information
4047
4047
of them to an update vector.
4048
@return error number or 0 */
4048
@return error number or 0 */
4051
4051
calc_row_difference(
4052
4052
/*================*/
4053
upd_t* uvect, /*!< in/out: update vector */
4054
unsigned char* old_row, /*!< in: old row in MySQL format */
4055
unsigned char* new_row, /*!< in: new row in MySQL format */
4056
Table* table, /*!< in: table in MySQL data
4058
unsigned char* upd_buff, /*!< in: buffer to use */
4059
ulint buff_len, /*!< in: buffer length */
4060
row_prebuilt_t* prebuilt, /*!< in: InnoDB prebuilt struct */
4061
Session* ) /*!< in: user thread */
4053
upd_t* uvect, /*!< in/out: update vector */
4054
unsigned char* old_row, /*!< in: old row in MySQL format */
4055
unsigned char* new_row, /*!< in: new row in MySQL format */
4056
Table* table, /*!< in: table in MySQL data
4058
unsigned char* upd_buff, /*!< in: buffer to use */
4059
ulint buff_len, /*!< in: buffer length */
4060
row_prebuilt_t* prebuilt, /*!< in: InnoDB prebuilt struct */
4061
Session* ) /*!< in: user thread */
4063
unsigned char* original_upd_buff = upd_buff;
4065
enum_field_types field_mysql_type;
4070
const byte* new_mysql_row_col;
4074
upd_field_t* ufield;
4076
ulint n_changed = 0;
4078
dict_index_t* clust_index;
4081
n_fields = table->s->fields;
4082
clust_index = dict_table_get_first_index(prebuilt->table);
4084
/* We use upd_buff to convert changed fields */
4085
buf = (byte*) upd_buff;
4087
for (i = 0; i < n_fields; i++) {
4088
field = table->field[i];
4090
o_ptr = (const byte*) old_row + get_field_offset(table, field);
4091
n_ptr = (const byte*) new_row + get_field_offset(table, field);
4093
/* Use new_mysql_row_col and col_pack_len save the values */
4095
new_mysql_row_col = n_ptr;
4096
col_pack_len = field->pack_length();
4098
o_len = col_pack_len;
4099
n_len = col_pack_len;
4101
/* We use o_ptr and n_ptr to dig up the actual data for
4104
field_mysql_type = field->type();
4106
col_type = prebuilt->table->cols[i].mtype;
4111
o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
4112
n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
4119
if (field_mysql_type == DRIZZLE_TYPE_VARCHAR) {
4120
/* This is a >= 5.0.3 type true VARCHAR where
4121
the real payload data length is stored in
4124
o_ptr = row_mysql_read_true_varchar(
4127
(((Field_varstring*)field)->length_bytes));
4129
n_ptr = row_mysql_read_true_varchar(
4132
(((Field_varstring*)field)->length_bytes));
4140
if (field->null_ptr) {
4141
if (field_in_record_is_null(table, field,
4143
o_len = UNIV_SQL_NULL;
4146
if (field_in_record_is_null(table, field,
4148
n_len = UNIV_SQL_NULL;
4152
if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
4153
0 != memcmp(o_ptr, n_ptr, o_len))) {
4154
/* The field has changed */
4156
ufield = uvect->fields + n_changed;
4158
/* Let us use a dummy dfield to make the conversion
4159
from the MySQL column format to the InnoDB format */
4161
dict_col_copy_type(prebuilt->table->cols + i,
4164
if (n_len != UNIV_SQL_NULL) {
4165
buf = row_mysql_store_col_in_innobase_format(
4171
dict_table_is_comp(prebuilt->table));
4172
dfield_copy_data(&ufield->new_val, &dfield);
4174
dfield_set_null(&ufield->new_val);
4178
ufield->orig_len = 0;
4179
ufield->field_no = dict_col_get_clust_pos(
4180
&prebuilt->table->cols[i], clust_index);
4185
uvect->n_fields = n_changed;
4186
uvect->info_bits = 0;
4188
ut_a(buf <= (byte*)original_upd_buff + buff_len);
4063
unsigned char* original_upd_buff = upd_buff;
4065
enum_field_types field_mysql_type;
4070
const byte* new_mysql_row_col;
4074
upd_field_t* ufield;
4076
ulint n_changed = 0;
4078
dict_index_t* clust_index;
4081
n_fields = table->s->fields;
4082
clust_index = dict_table_get_first_index(prebuilt->table);
4084
/* We use upd_buff to convert changed fields */
4085
buf = (byte*) upd_buff;
4087
for (i = 0; i < n_fields; i++) {
4088
field = table->field[i];
4090
o_ptr = (const byte*) old_row + get_field_offset(table, field);
4091
n_ptr = (const byte*) new_row + get_field_offset(table, field);
4093
/* Use new_mysql_row_col and col_pack_len save the values */
4095
new_mysql_row_col = n_ptr;
4096
col_pack_len = field->pack_length();
4098
o_len = col_pack_len;
4099
n_len = col_pack_len;
4101
/* We use o_ptr and n_ptr to dig up the actual data for
4104
field_mysql_type = field->type();
4106
col_type = prebuilt->table->cols[i].mtype;
4111
o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
4112
n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
4119
if (field_mysql_type == DRIZZLE_TYPE_VARCHAR) {
4120
/* This is a >= 5.0.3 type true VARCHAR where
4121
the real payload data length is stored in
4124
o_ptr = row_mysql_read_true_varchar(
4127
(((Field_varstring*)field)->length_bytes));
4129
n_ptr = row_mysql_read_true_varchar(
4132
(((Field_varstring*)field)->length_bytes));
4140
if (field->null_ptr) {
4141
if (field_in_record_is_null(table, field,
4143
o_len = UNIV_SQL_NULL;
4146
if (field_in_record_is_null(table, field,
4148
n_len = UNIV_SQL_NULL;
4152
if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
4153
0 != memcmp(o_ptr, n_ptr, o_len))) {
4154
/* The field has changed */
4156
ufield = uvect->fields + n_changed;
4158
/* Let us use a dummy dfield to make the conversion
4159
from the MySQL column format to the InnoDB format */
4161
dict_col_copy_type(prebuilt->table->cols + i,
4164
if (n_len != UNIV_SQL_NULL) {
4165
buf = row_mysql_store_col_in_innobase_format(
4171
dict_table_is_comp(prebuilt->table));
4172
dfield_copy_data(&ufield->new_val, &dfield);
4174
dfield_set_null(&ufield->new_val);
4178
ufield->orig_len = 0;
4179
ufield->field_no = dict_col_get_clust_pos(
4180
&prebuilt->table->cols[i], clust_index);
4185
uvect->n_fields = n_changed;
4186
uvect->info_bits = 0;
4188
ut_a(buf <= (byte*)original_upd_buff + buff_len);
4193
4193
/**********************************************************************//**
4197
4197
TODO: currently InnoDB does not prevent the 'Halloween problem':
4198
4198
in a searched update a single row can get updated several times
4199
4199
if its index columns are updated!
4200
@return error number or 0 */
4200
@return error number or 0 */
4203
4203
ha_innobase::update_row(
4204
4204
/*====================*/
4205
const unsigned char* old_row,/*!< in: old row in MySQL format */
4206
unsigned char* new_row)/*!< in: new row in MySQL format */
4205
const unsigned char* old_row,/*!< in: old row in MySQL format */
4206
unsigned char* new_row)/*!< in: new row in MySQL format */
4210
trx_t* trx = session_to_trx(user_session);
4212
ut_a(prebuilt->trx == trx);
4214
ha_statistic_increment(&system_status_var::ha_update_count);
4216
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
4217
table->timestamp_field->set_time();
4219
if (prebuilt->upd_node) {
4220
uvect = prebuilt->upd_node->update;
4222
uvect = row_get_prebuilt_update_vector(prebuilt);
4225
/* Build an update vector from the modified fields in the rows
4226
(uses upd_buff of the handle) */
4228
calc_row_difference(uvect, (unsigned char*) old_row, new_row, table,
4229
upd_buff, (ulint)upd_and_key_val_buff_len,
4230
prebuilt, user_session);
4232
/* This is not a delete */
4233
prebuilt->upd_node->is_delete = FALSE;
4235
ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
4237
innodb_srv_conc_enter_innodb(trx);
4239
error = row_update_for_mysql((byte*) old_row, prebuilt);
4241
/* We need to do some special AUTOINC handling for the following case:
4243
INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
4245
We need to use the AUTOINC counter that was actually used by
4246
MySQL in the UPDATE statement, which can be different from the
4247
value used in the INSERT statement.*/
4249
if (error == DB_SUCCESS
4250
&& table->next_number_field
4251
&& new_row == table->record[0]
4252
&& session_sql_command(user_session) == SQLCOM_INSERT
4253
&& (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4254
== TRX_DUP_IGNORE) {
4257
uint64_t col_max_value;
4259
auto_inc = table->next_number_field->val_int();
4261
/* We need the upper limit of the col type to check for
4262
whether we update the table autoinc counter or not. */
4263
col_max_value = innobase_get_int_col_max_value(
4264
table->next_number_field);
4266
if (auto_inc <= col_max_value && auto_inc != 0) {
4271
offset = prebuilt->autoinc_offset;
4272
need = prebuilt->autoinc_increment;
4274
auto_inc = innobase_next_autoinc(
4275
auto_inc, need, offset, col_max_value);
4277
error = innobase_set_max_autoinc(auto_inc);
4281
innodb_srv_conc_exit_innodb(trx);
4283
error = convert_error_code_to_mysql(error,
4284
prebuilt->table->flags,
4210
trx_t* trx = session_to_trx(user_session);
4212
ut_a(prebuilt->trx == trx);
4214
ha_statistic_increment(&system_status_var::ha_update_count);
4216
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
4217
table->timestamp_field->set_time();
4219
if (prebuilt->upd_node) {
4220
uvect = prebuilt->upd_node->update;
4222
uvect = row_get_prebuilt_update_vector(prebuilt);
4225
/* Build an update vector from the modified fields in the rows
4226
(uses upd_buff of the handle) */
4228
calc_row_difference(uvect, (unsigned char*) old_row, new_row, table,
4229
upd_buff, (ulint)upd_and_key_val_buff_len,
4230
prebuilt, user_session);
4232
/* This is not a delete */
4233
prebuilt->upd_node->is_delete = FALSE;
4235
ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
4237
innodb_srv_conc_enter_innodb(trx);
4239
error = row_update_for_mysql((byte*) old_row, prebuilt);
4241
/* We need to do some special AUTOINC handling for the following case:
4243
INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
4245
We need to use the AUTOINC counter that was actually used by
4246
MySQL in the UPDATE statement, which can be different from the
4247
value used in the INSERT statement.*/
4249
if (error == DB_SUCCESS
4250
&& table->next_number_field
4251
&& new_row == table->record[0]
4252
&& session_sql_command(user_session) == SQLCOM_INSERT
4253
&& (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4254
== TRX_DUP_IGNORE) {
4257
uint64_t col_max_value;
4259
auto_inc = table->next_number_field->val_int();
4261
/* We need the upper limit of the col type to check for
4262
whether we update the table autoinc counter or not. */
4263
col_max_value = innobase_get_int_col_max_value(
4264
table->next_number_field);
4266
if (auto_inc <= col_max_value && auto_inc != 0) {
4271
offset = prebuilt->autoinc_offset;
4272
need = prebuilt->autoinc_increment;
4274
auto_inc = innobase_next_autoinc(
4275
auto_inc, need, offset, col_max_value);
4277
error = innobase_set_max_autoinc(auto_inc);
4281
innodb_srv_conc_exit_innodb(trx);
4283
error = convert_error_code_to_mysql(error,
4284
prebuilt->table->flags,
4287
if (error == 0 /* success */
4288
&& uvect->n_fields == 0 /* no columns were updated */) {
4290
/* This is the same as success, but instructs
4291
MySQL that the row is not really updated and it
4292
should not increase the count of updated rows.
4293
This is fix for http://bugs.mysql.com/29157 */
4294
error = HA_ERR_RECORD_IS_THE_SAME;
4297
/* Tell InnoDB server that there might be work for
4300
innobase_active_small();
4287
if (error == 0 /* success */
4288
&& uvect->n_fields == 0 /* no columns were updated */) {
4290
/* This is the same as success, but instructs
4291
MySQL that the row is not really updated and it
4292
should not increase the count of updated rows.
4293
This is fix for http://bugs.mysql.com/29157 */
4294
error = HA_ERR_RECORD_IS_THE_SAME;
4297
/* Tell InnoDB server that there might be work for
4300
innobase_active_small();
4305
4305
/**********************************************************************//**
4306
4306
Deletes a row given as the parameter.
4307
@return error number or 0 */
4307
@return error number or 0 */
4310
4310
ha_innobase::delete_row(
4311
4311
/*====================*/
4312
const unsigned char* record) /*!< in: a row in MySQL format */
4312
const unsigned char* record) /*!< in: a row in MySQL format */
4315
trx_t* trx = session_to_trx(user_session);
4317
ut_a(prebuilt->trx == trx);
4319
ha_statistic_increment(&system_status_var::ha_delete_count);
4321
if (!prebuilt->upd_node) {
4322
row_get_prebuilt_update_vector(prebuilt);
4325
/* This is a delete */
4327
prebuilt->upd_node->is_delete = TRUE;
4329
innodb_srv_conc_enter_innodb(trx);
4331
error = row_update_for_mysql((byte*) record, prebuilt);
4333
innodb_srv_conc_exit_innodb(trx);
4335
error = convert_error_code_to_mysql(
4336
error, prebuilt->table->flags, user_session);
4338
/* Tell the InnoDB server that there might be work for
4341
innobase_active_small();
4315
trx_t* trx = session_to_trx(user_session);
4317
ut_a(prebuilt->trx == trx);
4319
ha_statistic_increment(&system_status_var::ha_delete_count);
4321
if (!prebuilt->upd_node) {
4322
row_get_prebuilt_update_vector(prebuilt);
4325
/* This is a delete */
4327
prebuilt->upd_node->is_delete = TRUE;
4329
innodb_srv_conc_enter_innodb(trx);
4331
error = row_update_for_mysql((byte*) record, prebuilt);
4333
innodb_srv_conc_exit_innodb(trx);
4335
error = convert_error_code_to_mysql(
4336
error, prebuilt->table->flags, user_session);
4338
/* Tell the InnoDB server that there might be work for
4341
innobase_active_small();
4346
4346
/**********************************************************************//**
4552
4552
/**********************************************************************//**
4553
4553
Positions an index cursor to the index specified in the handle. Fetches the
4555
@return 0, HA_ERR_KEY_NOT_FOUND, or error number */
4555
@return 0, HA_ERR_KEY_NOT_FOUND, or error number */
4558
4558
ha_innobase::index_read(
4559
4559
/*====================*/
4560
unsigned char* buf, /*!< in/out: buffer for the returned
4562
const unsigned char* key_ptr,/*!< in: key value; if this is NULL
4563
we position the cursor at the
4564
start or end of index; this can
4565
also contain an InnoDB row id, in
4566
which case key_len is the InnoDB
4567
row id length; the key value can
4568
also be a prefix of a full key value,
4569
and the last column can be a prefix
4571
uint key_len,/*!< in: key value length */
4572
enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
4560
unsigned char* buf, /*!< in/out: buffer for the returned
4562
const unsigned char* key_ptr,/*!< in: key value; if this is NULL
4563
we position the cursor at the
4564
start or end of index; this can
4565
also contain an InnoDB row id, in
4566
which case key_len is the InnoDB
4567
row id length; the key value can
4568
also be a prefix of a full key value,
4569
and the last column can be a prefix
4571
uint key_len,/*!< in: key value length */
4572
enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
4575
dict_index_t* index;
4576
ulint match_mode = 0;
4580
ut_a(prebuilt->trx == session_to_trx(user_session));
4582
ha_statistic_increment(&system_status_var::ha_read_key_count);
4584
index = prebuilt->index;
4586
/* Note that if the index for which the search template is built is not
4587
necessarily prebuilt->index, but can also be the clustered index */
4589
if (prebuilt->sql_stat_start) {
4590
build_template(prebuilt, user_session, table,
4591
ROW_MYSQL_REC_FIELDS);
4595
/* Convert the search key value to InnoDB format into
4596
prebuilt->search_tuple */
4598
row_sel_convert_mysql_key_to_innobase(
4599
prebuilt->search_tuple,
4600
(byte*) key_val_buff,
4601
(ulint)upd_and_key_val_buff_len,
4607
/* We position the cursor to the last or the first entry
4610
dtuple_set_n_fields(prebuilt->search_tuple, 0);
4613
mode = convert_search_mode_to_innobase(find_flag);
4617
if (find_flag == HA_READ_KEY_EXACT) {
4619
match_mode = ROW_SEL_EXACT;
4621
} else if (find_flag == HA_READ_PREFIX
4622
|| find_flag == HA_READ_PREFIX_LAST) {
4624
match_mode = ROW_SEL_EXACT_PREFIX;
4627
last_match_mode = (uint) match_mode;
4629
if (mode != PAGE_CUR_UNSUPP) {
4631
innodb_srv_conc_enter_innodb(prebuilt->trx);
4633
ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
4636
innodb_srv_conc_exit_innodb(prebuilt->trx);
4639
ret = DB_UNSUPPORTED;
4647
case DB_RECORD_NOT_FOUND:
4648
error = HA_ERR_KEY_NOT_FOUND;
4649
table->status = STATUS_NOT_FOUND;
4651
case DB_END_OF_INDEX:
4652
error = HA_ERR_KEY_NOT_FOUND;
4653
table->status = STATUS_NOT_FOUND;
4656
error = convert_error_code_to_mysql((int) ret,
4657
prebuilt->table->flags,
4659
table->status = STATUS_NOT_FOUND;
4575
dict_index_t* index;
4576
ulint match_mode = 0;
4580
ut_a(prebuilt->trx == session_to_trx(user_session));
4582
ha_statistic_increment(&system_status_var::ha_read_key_count);
4584
index = prebuilt->index;
4586
/* Note that if the index for which the search template is built is not
4587
necessarily prebuilt->index, but can also be the clustered index */
4589
if (prebuilt->sql_stat_start) {
4590
build_template(prebuilt, user_session, table,
4591
ROW_MYSQL_REC_FIELDS);
4595
/* Convert the search key value to InnoDB format into
4596
prebuilt->search_tuple */
4598
row_sel_convert_mysql_key_to_innobase(
4599
prebuilt->search_tuple,
4600
(byte*) key_val_buff,
4601
(ulint)upd_and_key_val_buff_len,
4607
/* We position the cursor to the last or the first entry
4610
dtuple_set_n_fields(prebuilt->search_tuple, 0);
4613
mode = convert_search_mode_to_innobase(find_flag);
4617
if (find_flag == HA_READ_KEY_EXACT) {
4619
match_mode = ROW_SEL_EXACT;
4621
} else if (find_flag == HA_READ_PREFIX
4622
|| find_flag == HA_READ_PREFIX_LAST) {
4624
match_mode = ROW_SEL_EXACT_PREFIX;
4627
last_match_mode = (uint) match_mode;
4629
if (mode != PAGE_CUR_UNSUPP) {
4631
innodb_srv_conc_enter_innodb(prebuilt->trx);
4633
ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
4636
innodb_srv_conc_exit_innodb(prebuilt->trx);
4639
ret = DB_UNSUPPORTED;
4647
case DB_RECORD_NOT_FOUND:
4648
error = HA_ERR_KEY_NOT_FOUND;
4649
table->status = STATUS_NOT_FOUND;
4651
case DB_END_OF_INDEX:
4652
error = HA_ERR_KEY_NOT_FOUND;
4653
table->status = STATUS_NOT_FOUND;
4656
error = convert_error_code_to_mysql((int) ret,
4657
prebuilt->table->flags,
4659
table->status = STATUS_NOT_FOUND;
4666
4666
/*******************************************************************//**
4667
4667
The following functions works like index_read, but it find the last
4668
4668
row with the current key value or prefix.
4669
@return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
4669
@return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
4672
4672
ha_innobase::index_read_last(
4673
4673
/*=========================*/
4674
unsigned char* buf, /*!< out: fetched row */
4675
const unsigned char* key_ptr,/*!< in: key value, or a prefix of a full
4677
uint key_len)/*!< in: length of the key val or prefix
4674
unsigned char* buf, /*!< out: fetched row */
4675
const unsigned char* key_ptr,/*!< in: key value, or a prefix of a full
4677
uint key_len)/*!< in: length of the key val or prefix
4680
return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
4680
return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
4683
4683
/********************************************************************//**
4684
4684
Get the index for a handle. Does not change active index.
4685
@return NULL or index instance. */
4685
@return NULL or index instance. */
4688
4688
ha_innobase::innobase_get_index(
4689
4689
/*============================*/
4690
uint keynr) /*!< in: use this index; MAX_KEY means always
4691
clustered index, even if it was internally
4692
generated by InnoDB */
4690
uint keynr) /*!< in: use this index; MAX_KEY means always
4691
clustered index, even if it was internally
4692
generated by InnoDB */
4695
dict_index_t* index = 0;
4697
ha_statistic_increment(&system_status_var::ha_read_key_count);
4699
ut_ad(user_session == ha_session());
4700
ut_a(prebuilt->trx == session_to_trx(user_session));
4702
if (keynr != MAX_KEY && table->s->keys > 0) {
4703
key = table->key_info + keynr;
4705
index = dict_table_get_index_on_name(prebuilt->table,
4708
index = dict_table_get_first_index(prebuilt->table);
4712
errmsg_printf(ERRMSG_LVL_ERROR,
4713
"Innodb could not find key n:o %u with name %s "
4714
"from dict cache for table %s",
4715
keynr, key ? key->name : "NULL",
4716
prebuilt->table->name);
4695
dict_index_t* index = 0;
4697
ha_statistic_increment(&system_status_var::ha_read_key_count);
4699
ut_ad(user_session == ha_session());
4700
ut_a(prebuilt->trx == session_to_trx(user_session));
4702
if (keynr != MAX_KEY && table->s->keys > 0) {
4703
key = table->key_info + keynr;
4705
index = dict_table_get_index_on_name(prebuilt->table,
4708
index = dict_table_get_first_index(prebuilt->table);
4712
errmsg_printf(ERRMSG_LVL_ERROR,
4713
"Innodb could not find key n:o %u with name %s "
4714
"from dict cache for table %s",
4715
keynr, key ? key->name : "NULL",
4716
prebuilt->table->name);
4722
4722
/********************************************************************//**
4723
4723
Changes the active index of a handle.
4724
@return 0 or error code */
4724
@return 0 or error code */
4727
4727
ha_innobase::change_active_index(
4728
4728
/*=============================*/
4729
uint keynr) /*!< in: use this index; MAX_KEY means always clustered
4730
index, even if it was internally generated by
4729
uint keynr) /*!< in: use this index; MAX_KEY means always clustered
4730
index, even if it was internally generated by
4733
ut_ad(user_session == ha_session());
4734
ut_a(prebuilt->trx == session_to_trx(user_session));
4736
active_index = keynr;
4738
prebuilt->index = innobase_get_index(keynr);
4740
if (UNIV_UNLIKELY(!prebuilt->index)) {
4741
errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
4746
prebuilt->index_usable = row_merge_is_index_usable(prebuilt->trx,
4749
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
4750
errmsg_printf(ERRMSG_LVL_WARN,
4751
"InnoDB: insufficient history for index %u",
4753
/* The caller seems to ignore this. Thus, we must check
4754
this again in row_search_for_mysql(). */
4758
ut_a(prebuilt->search_tuple != 0);
4760
dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
4762
dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
4763
prebuilt->index->n_fields);
4765
/* MySQL changes the active index for a handle also during some
4766
queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
4767
and then calculates the sum. Previously we played safe and used
4768
the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
4769
copying. Starting from MySQL-4.1 we use a more efficient flag here. */
4771
build_template(prebuilt, user_session, table, ROW_MYSQL_REC_FIELDS);
4733
ut_ad(user_session == ha_session());
4734
ut_a(prebuilt->trx == session_to_trx(user_session));
4736
active_index = keynr;
4738
prebuilt->index = innobase_get_index(keynr);
4740
if (UNIV_UNLIKELY(!prebuilt->index)) {
4741
errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
4746
prebuilt->index_usable = row_merge_is_index_usable(prebuilt->trx,
4749
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
4750
errmsg_printf(ERRMSG_LVL_WARN,
4751
"InnoDB: insufficient history for index %u",
4753
/* The caller seems to ignore this. Thus, we must check
4754
this again in row_search_for_mysql(). */
4758
ut_a(prebuilt->search_tuple != 0);
4760
dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
4762
dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
4763
prebuilt->index->n_fields);
4765
/* MySQL changes the active index for a handle also during some
4766
queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
4767
and then calculates the sum. Previously we played safe and used
4768
the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
4769
copying. Starting from MySQL-4.1 we use a more efficient flag here. */
4771
build_template(prebuilt, user_session, table, ROW_MYSQL_REC_FIELDS);
4776
4776
/**********************************************************************//**
4777
4777
Positions an index cursor to the index specified in keynr. Fetches the
4779
4779
??? This is only used to read whole keys ???
4780
@return error number or 0 */
4780
@return error number or 0 */
4783
4783
ha_innobase::index_read_idx(
4784
4784
/*========================*/
4785
unsigned char* buf, /*!< in/out: buffer for the returned
4787
uint keynr, /*!< in: use this index */
4788
const unsigned char* key, /*!< in: key value; if this is NULL
4789
we position the cursor at the
4790
start or end of index */
4791
uint key_len, /*!< in: key value length */
4792
enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
4785
unsigned char* buf, /*!< in/out: buffer for the returned
4787
uint keynr, /*!< in: use this index */
4788
const unsigned char* key, /*!< in: key value; if this is NULL
4789
we position the cursor at the
4790
start or end of index */
4791
uint key_len, /*!< in: key value length */
4792
enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
4794
if (change_active_index(keynr)) {
4799
return(index_read(buf, key, key_len, find_flag));
4794
if (change_active_index(keynr)) {
4799
return(index_read(buf, key, key_len, find_flag));
4802
4802
/***********************************************************************//**
4803
4803
Reads the next or previous row from a cursor, which must have previously been
4804
4804
positioned using index_read.
4805
@return 0, HA_ERR_END_OF_FILE, or error number */
4805
@return 0, HA_ERR_END_OF_FILE, or error number */
4808
4808
ha_innobase::general_fetch(
4809
4809
/*=======================*/
4810
unsigned char* buf, /*!< in/out: buffer for next row in MySQL
4812
uint direction, /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */
4813
uint match_mode) /*!< in: 0, ROW_SEL_EXACT, or
4814
ROW_SEL_EXACT_PREFIX */
4810
unsigned char* buf, /*!< in/out: buffer for next row in MySQL
4812
uint direction, /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */
4813
uint match_mode) /*!< in: 0, ROW_SEL_EXACT, or
4814
ROW_SEL_EXACT_PREFIX */
4819
ut_a(prebuilt->trx == session_to_trx(user_session));
4821
innodb_srv_conc_enter_innodb(prebuilt->trx);
4823
ret = row_search_for_mysql(
4824
(byte*)buf, 0, prebuilt, match_mode, direction);
4826
innodb_srv_conc_exit_innodb(prebuilt->trx);
4833
case DB_RECORD_NOT_FOUND:
4834
error = HA_ERR_END_OF_FILE;
4835
table->status = STATUS_NOT_FOUND;
4837
case DB_END_OF_INDEX:
4838
error = HA_ERR_END_OF_FILE;
4839
table->status = STATUS_NOT_FOUND;
4842
error = convert_error_code_to_mysql(
4843
(int) ret, prebuilt->table->flags, user_session);
4844
table->status = STATUS_NOT_FOUND;
4819
ut_a(prebuilt->trx == session_to_trx(user_session));
4821
innodb_srv_conc_enter_innodb(prebuilt->trx);
4823
ret = row_search_for_mysql(
4824
(byte*)buf, 0, prebuilt, match_mode, direction);
4826
innodb_srv_conc_exit_innodb(prebuilt->trx);
4833
case DB_RECORD_NOT_FOUND:
4834
error = HA_ERR_END_OF_FILE;
4835
table->status = STATUS_NOT_FOUND;
4837
case DB_END_OF_INDEX:
4838
error = HA_ERR_END_OF_FILE;
4839
table->status = STATUS_NOT_FOUND;
4842
error = convert_error_code_to_mysql(
4843
(int) ret, prebuilt->table->flags, user_session);
4844
table->status = STATUS_NOT_FOUND;
4851
4851
/***********************************************************************//**
4852
4852
Reads the next row from a cursor, which must have previously been
4853
4853
positioned using index_read.
4854
@return 0, HA_ERR_END_OF_FILE, or error number */
4854
@return 0, HA_ERR_END_OF_FILE, or error number */
4857
4857
ha_innobase::index_next(
4858
4858
/*====================*/
4859
unsigned char* buf) /*!< in/out: buffer for next row in MySQL
4859
unsigned char* buf) /*!< in/out: buffer for next row in MySQL
4862
ha_statistic_increment(&system_status_var::ha_read_next_count);
4862
ha_statistic_increment(&system_status_var::ha_read_next_count);
4864
return(general_fetch(buf, ROW_SEL_NEXT, 0));
4864
return(general_fetch(buf, ROW_SEL_NEXT, 0));
4867
4867
/*******************************************************************//**
4868
4868
Reads the next row matching to the key value given as the parameter.
4869
@return 0, HA_ERR_END_OF_FILE, or error number */
4869
@return 0, HA_ERR_END_OF_FILE, or error number */
4872
4872
ha_innobase::index_next_same(
4873
4873
/*=========================*/
4874
unsigned char* buf, /*!< in/out: buffer for the row */
4875
const unsigned char* , /*!< in: key value */
4876
uint ) /*!< in: key value length */
4874
unsigned char* buf, /*!< in/out: buffer for the row */
4875
const unsigned char* , /*!< in: key value */
4876
uint ) /*!< in: key value length */
4878
ha_statistic_increment(&system_status_var::ha_read_next_count);
4878
ha_statistic_increment(&system_status_var::ha_read_next_count);
4880
return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
4880
return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
4883
4883
/***********************************************************************//**
4884
4884
Reads the previous row from a cursor, which must have previously been
4885
4885
positioned using index_read.
4886
@return 0, HA_ERR_END_OF_FILE, or error number */
4886
@return 0, HA_ERR_END_OF_FILE, or error number */
4889
4889
ha_innobase::index_prev(
4890
4890
/*====================*/
4891
unsigned char* buf) /*!< in/out: buffer for previous row in MySQL format */
4891
unsigned char* buf) /*!< in/out: buffer for previous row in MySQL format */
4893
ha_statistic_increment(&system_status_var::ha_read_prev_count);
4893
ha_statistic_increment(&system_status_var::ha_read_prev_count);
4895
return(general_fetch(buf, ROW_SEL_PREV, 0));
4895
return(general_fetch(buf, ROW_SEL_PREV, 0));
4898
4898
/********************************************************************//**
4899
4899
Positions a cursor on the first record in an index and reads the
4900
4900
corresponding row to buf.
4901
@return 0, HA_ERR_END_OF_FILE, or error code */
4901
@return 0, HA_ERR_END_OF_FILE, or error code */
4904
4904
ha_innobase::index_first(
4905
4905
/*=====================*/
4906
unsigned char* buf) /*!< in/out: buffer for the row */
4906
unsigned char* buf) /*!< in/out: buffer for the row */
4910
ha_statistic_increment(&system_status_var::ha_read_first_count);
4912
error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
4914
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4916
if (error == HA_ERR_KEY_NOT_FOUND) {
4917
error = HA_ERR_END_OF_FILE;
4910
ha_statistic_increment(&system_status_var::ha_read_first_count);
4912
error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
4914
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4916
if (error == HA_ERR_KEY_NOT_FOUND) {
4917
error = HA_ERR_END_OF_FILE;
4923
4923
/********************************************************************//**
4924
4924
Positions a cursor on the last record in an index and reads the
4925
4925
corresponding row to buf.
4926
@return 0, HA_ERR_END_OF_FILE, or error code */
4926
@return 0, HA_ERR_END_OF_FILE, or error code */
4929
4929
ha_innobase::index_last(
4930
4930
/*====================*/
4931
unsigned char* buf) /*!< in/out: buffer for the row */
4931
unsigned char* buf) /*!< in/out: buffer for the row */
4935
ha_statistic_increment(&system_status_var::ha_read_last_count);
4937
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
4939
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4941
if (error == HA_ERR_KEY_NOT_FOUND) {
4942
error = HA_ERR_END_OF_FILE;
4935
ha_statistic_increment(&system_status_var::ha_read_last_count);
4937
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
4939
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4941
if (error == HA_ERR_KEY_NOT_FOUND) {
4942
error = HA_ERR_END_OF_FILE;
4948
4948
/****************************************************************//**
4949
4949
Initialize a table scan.
4950
@return 0 or error number */
4950
@return 0 or error number */
4953
4953
ha_innobase::rnd_init(
4954
4954
/*==================*/
4955
bool scan) /*!< in: TRUE if table/index scan FALSE otherwise */
4955
bool scan) /*!< in: TRUE if table/index scan FALSE otherwise */
4959
/* Store the active index value so that we can restore the original
4960
value after a scan */
4962
if (prebuilt->clust_index_was_generated) {
4963
err = change_active_index(MAX_KEY);
4965
err = change_active_index(primary_key);
4968
/* Don't use semi-consistent read in random row reads (by position).
4969
This means we must disable semi_consistent_read if scan is false */
4972
try_semi_consistent_read(0);
4959
/* Store the active index value so that we can restore the original
4960
value after a scan */
4962
if (prebuilt->clust_index_was_generated) {
4963
err = change_active_index(MAX_KEY);
4965
err = change_active_index(primary_key);
4968
/* Don't use semi-consistent read in random row reads (by position).
4969
This means we must disable semi_consistent_read if scan is false */
4972
try_semi_consistent_read(0);
4980
4980
/*****************************************************************//**
4981
4981
Ends a table scan.
4982
@return 0 or error number */
4982
@return 0 or error number */
4985
4985
ha_innobase::rnd_end(void)
4986
4986
/*======================*/
4988
return(index_end());
4988
return(index_end());
4991
4991
/*****************************************************************//**
4992
4992
Reads the next row in a table scan (also used to read the FIRST row
4993
4993
in a table scan).
4994
@return 0, HA_ERR_END_OF_FILE, or error number */
4994
@return 0, HA_ERR_END_OF_FILE, or error number */
4997
4997
ha_innobase::rnd_next(
4998
4998
/*==================*/
4999
unsigned char* buf) /*!< in/out: returns the row in this buffer,
4999
unsigned char* buf) /*!< in/out: returns the row in this buffer,
5004
ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
5006
if (start_of_scan) {
5007
error = index_first(buf);
5009
if (error == HA_ERR_KEY_NOT_FOUND) {
5010
error = HA_ERR_END_OF_FILE;
5015
error = general_fetch(buf, ROW_SEL_NEXT, 0);
5004
ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
5006
if (start_of_scan) {
5007
error = index_first(buf);
5009
if (error == HA_ERR_KEY_NOT_FOUND) {
5010
error = HA_ERR_END_OF_FILE;
5015
error = general_fetch(buf, ROW_SEL_NEXT, 0);
5021
5021
/**********************************************************************//**
5022
5022
Fetches a row from the table based on a row reference.
5023
@return 0, HA_ERR_KEY_NOT_FOUND, or error code */
5023
@return 0, HA_ERR_KEY_NOT_FOUND, or error code */
5026
5026
ha_innobase::rnd_pos(
5027
5027
/*=================*/
5028
unsigned char* buf, /*!< in/out: buffer for the row */
5029
unsigned char* pos) /*!< in: primary key value of the row in the
5030
MySQL format, or the row id if the clustered
5031
index was internally generated by InnoDB; the
5032
length of data in pos has to be ref_length */
5028
unsigned char* buf, /*!< in/out: buffer for the row */
5029
unsigned char* pos) /*!< in: primary key value of the row in the
5030
MySQL format, or the row id if the clustered
5031
index was internally generated by InnoDB; the
5032
length of data in pos has to be ref_length */
5035
uint keynr = active_index;
5037
ha_statistic_increment(&system_status_var::ha_read_rnd_count);
5039
ut_a(prebuilt->trx == session_to_trx(ha_session()));
5041
if (prebuilt->clust_index_was_generated) {
5042
/* No primary key was defined for the table and we
5043
generated the clustered index from the row id: the
5044
row reference is the row id, not any key value
5045
that MySQL knows of */
5047
error = change_active_index(MAX_KEY);
5049
error = change_active_index(primary_key);
5056
/* Note that we assume the length of the row reference is fixed
5057
for the table, and it is == ref_length */
5059
error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
5064
change_active_index(keynr);
5035
uint keynr = active_index;
5037
ha_statistic_increment(&system_status_var::ha_read_rnd_count);
5039
ut_a(prebuilt->trx == session_to_trx(ha_session()));
5041
if (prebuilt->clust_index_was_generated) {
5042
/* No primary key was defined for the table and we
5043
generated the clustered index from the row id: the
5044
row reference is the row id, not any key value
5045
that MySQL knows of */
5047
error = change_active_index(MAX_KEY);
5049
error = change_active_index(primary_key);
5056
/* Note that we assume the length of the row reference is fixed
5057
for the table, and it is == ref_length */
5059
error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
5064
change_active_index(keynr);
5069
5069
/*********************************************************************//**
5115
5115
create_table_def(
5116
5116
/*=============*/
5117
trx_t* trx, /*!< in: InnoDB transaction handle */
5118
Table* form, /*!< in: information on table
5119
columns and indexes */
5120
const char* table_name, /*!< in: table name */
5121
const char* path_of_temp_table,/*!< in: if this is a table explicitly
5122
created by the user with the
5123
TEMPORARY keyword, then this
5124
parameter is the dir path where the
5125
table should be placed if we create
5126
an .ibd file for it (no .ibd extension
5127
in the path, though); otherwise this
5129
ulint flags) /*!< in: table flags */
5117
trx_t* trx, /*!< in: InnoDB transaction handle */
5118
Table* form, /*!< in: information on table
5119
columns and indexes */
5120
const char* table_name, /*!< in: table name */
5121
const char* path_of_temp_table,/*!< in: if this is a table explicitly
5122
created by the user with the
5123
TEMPORARY keyword, then this
5124
parameter is the dir path where the
5125
table should be placed if we create
5126
an .ibd file for it (no .ibd extension
5127
in the path, though); otherwise this
5129
ulint flags) /*!< in: table flags */
5132
dict_table_t* table;
5137
ulint nulls_allowed;
5138
ulint unsigned_type;
5140
ulint long_true_varchar;
5144
n_cols = form->s->fields;
5146
/* We pass 0 as the space id, and determine at a lower level the space
5147
id where to store the table */
5149
table = dict_mem_table_create(table_name, 0, n_cols, flags);
5151
if (path_of_temp_table) {
5152
table->dir_path_of_temp_table =
5153
mem_heap_strdup(table->heap, path_of_temp_table);
5156
for (i = 0; i < n_cols; i++) {
5157
field = form->field[i];
5159
col_type = get_innobase_type_from_mysql_type(&unsigned_type,
5161
if (field->null_ptr) {
5164
nulls_allowed = DATA_NOT_NULL;
5167
if (field->binary()) {
5168
binary_type = DATA_BINARY_TYPE;
5175
if (dtype_is_string_type(col_type)) {
5177
charset_no = (ulint)field->charset()->number;
5179
if (UNIV_UNLIKELY(charset_no >= 256)) {
5180
/* in data0type.h we assume that the
5181
number fits in one byte in prtype */
5182
push_warning_printf(
5183
(Session*) trx->mysql_thd,
5184
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5185
ER_CANT_CREATE_TABLE,
5186
"In InnoDB, charset-collation codes"
5187
" must be below 256."
5188
" Unsupported code %lu.",
5189
(ulong) charset_no);
5190
return(ER_CANT_CREATE_TABLE);
5194
ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
5195
that this fits in one byte */
5196
col_len = field->pack_length();
5198
/* The MySQL pack length contains 1 or 2 bytes length field
5199
for a true VARCHAR. Let us subtract that, so that the InnoDB
5200
column length in the InnoDB data dictionary is the real
5201
maximum byte length of the actual data. */
5203
long_true_varchar = 0;
5205
if (field->type() == DRIZZLE_TYPE_VARCHAR) {
5206
col_len -= ((Field_varstring*)field)->length_bytes;
5208
if (((Field_varstring*)field)->length_bytes == 2) {
5209
long_true_varchar = DATA_LONG_TRUE_VARCHAR;
5213
dict_mem_table_add_col(table, table->heap,
5214
(char*) field->field_name,
5217
(ulint)field->type()
5218
| nulls_allowed | unsigned_type
5219
| binary_type | long_true_varchar,
5224
error = row_create_table_for_mysql(table, trx);
5226
error = convert_error_code_to_mysql(error, flags, NULL);
5132
dict_table_t* table;
5137
ulint nulls_allowed;
5138
ulint unsigned_type;
5140
ulint long_true_varchar;
5144
n_cols = form->s->fields;
5146
/* We pass 0 as the space id, and determine at a lower level the space
5147
id where to store the table */
5149
table = dict_mem_table_create(table_name, 0, n_cols, flags);
5151
if (path_of_temp_table) {
5152
table->dir_path_of_temp_table =
5153
mem_heap_strdup(table->heap, path_of_temp_table);
5156
for (i = 0; i < n_cols; i++) {
5157
field = form->field[i];
5159
col_type = get_innobase_type_from_mysql_type(&unsigned_type,
5161
if (field->null_ptr) {
5164
nulls_allowed = DATA_NOT_NULL;
5167
if (field->binary()) {
5168
binary_type = DATA_BINARY_TYPE;
5175
if (dtype_is_string_type(col_type)) {
5177
charset_no = (ulint)field->charset()->number;
5179
if (UNIV_UNLIKELY(charset_no >= 256)) {
5180
/* in data0type.h we assume that the
5181
number fits in one byte in prtype */
5182
push_warning_printf(
5183
(Session*) trx->mysql_thd,
5184
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5185
ER_CANT_CREATE_TABLE,
5186
"In InnoDB, charset-collation codes"
5187
" must be below 256."
5188
" Unsupported code %lu.",
5189
(ulong) charset_no);
5190
return(ER_CANT_CREATE_TABLE);
5194
ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
5195
that this fits in one byte */
5196
col_len = field->pack_length();
5198
/* The MySQL pack length contains 1 or 2 bytes length field
5199
for a true VARCHAR. Let us subtract that, so that the InnoDB
5200
column length in the InnoDB data dictionary is the real
5201
maximum byte length of the actual data. */
5203
long_true_varchar = 0;
5205
if (field->type() == DRIZZLE_TYPE_VARCHAR) {
5206
col_len -= ((Field_varstring*)field)->length_bytes;
5208
if (((Field_varstring*)field)->length_bytes == 2) {
5209
long_true_varchar = DATA_LONG_TRUE_VARCHAR;
5213
dict_mem_table_add_col(table, table->heap,
5214
(char*) field->field_name,
5217
(ulint)field->type()
5218
| nulls_allowed | unsigned_type
5219
| binary_type | long_true_varchar,
5224
error = row_create_table_for_mysql(table, trx);
5226
error = convert_error_code_to_mysql(error, flags, NULL);
5231
5231
/*****************************************************************//**
5237
trx_t* trx, /*!< in: InnoDB transaction handle */
5238
Table* form, /*!< in: information on table
5239
columns and indexes */
5240
ulint flags, /*!< in: InnoDB table flags */
5241
const char* table_name, /*!< in: table name */
5242
uint key_num) /*!< in: index number */
5237
trx_t* trx, /*!< in: InnoDB transaction handle */
5238
Table* form, /*!< in: information on table
5239
columns and indexes */
5240
ulint flags, /*!< in: InnoDB table flags */
5241
const char* table_name, /*!< in: table name */
5242
uint key_num) /*!< in: index number */
5245
dict_index_t* index;
5249
KEY_PART_INFO* key_part;
5256
ulint* field_lengths;
5258
key = form->key_info + key_num;
5260
n_fields = key->key_parts;
5264
if (key_num == form->s->primary_key) {
5265
ind_type = ind_type | DICT_CLUSTERED;
5268
if (key->flags & HA_NOSAME ) {
5269
ind_type = ind_type | DICT_UNIQUE;
5272
/* We pass 0 as the space id, and determine at a lower level the space
5273
id where to store the table */
5275
index = dict_mem_index_create(table_name, key->name, 0,
5276
ind_type, n_fields);
5278
field_lengths = (ulint*) malloc(sizeof(ulint) * n_fields);
5280
for (i = 0; i < n_fields; i++) {
5281
key_part = key->key_part + i;
5283
/* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
5284
field in an index: we only store a specified number of first
5285
bytes of the column to the index field.) The flag does not
5286
seem to be properly set by MySQL. Let us fall back on testing
5287
the length of the key part versus the column. */
5290
for (j = 0; j < form->s->fields; j++) {
5292
field = form->field[j];
5294
if (0 == innobase_strcasecmp(
5296
key_part->field->field_name)) {
5297
/* Found the corresponding column */
5303
ut_a(j < form->s->fields);
5305
col_type = get_innobase_type_from_mysql_type(
5306
&is_unsigned, key_part->field);
5308
if (DATA_BLOB == col_type
5309
|| (key_part->length < field->pack_length()
5310
&& field->type() != DRIZZLE_TYPE_VARCHAR)
5311
|| (field->type() == DRIZZLE_TYPE_VARCHAR
5312
&& key_part->length < field->pack_length()
5313
- ((Field_varstring*)field)->length_bytes)) {
5315
prefix_len = key_part->length;
5317
if (col_type == DATA_INT
5318
|| col_type == DATA_FLOAT
5319
|| col_type == DATA_DOUBLE
5320
|| col_type == DATA_DECIMAL) {
5321
errmsg_printf(ERRMSG_LVL_ERROR,
5322
"MySQL is trying to create a column "
5323
"prefix index field, on an "
5324
"inappropriate data type. Table "
5325
"name %s, column name %s.",
5327
key_part->field->field_name);
5335
field_lengths[i] = key_part->length;
5337
dict_mem_index_add_field(index,
5338
(char*) key_part->field->field_name, prefix_len);
5341
/* Even though we've defined max_supported_key_part_length, we
5342
still do our own checking using field_lengths to be absolutely
5343
sure we don't create too long indexes. */
5344
error = row_create_index_for_mysql(index, trx, field_lengths);
5346
error = convert_error_code_to_mysql(error, flags, NULL);
5348
free(field_lengths);
5245
dict_index_t* index;
5249
KEY_PART_INFO* key_part;
5256
ulint* field_lengths;
5258
key = form->key_info + key_num;
5260
n_fields = key->key_parts;
5264
if (key_num == form->s->primary_key) {
5265
ind_type = ind_type | DICT_CLUSTERED;
5268
if (key->flags & HA_NOSAME ) {
5269
ind_type = ind_type | DICT_UNIQUE;
5272
/* We pass 0 as the space id, and determine at a lower level the space
5273
id where to store the table */
5275
index = dict_mem_index_create(table_name, key->name, 0,
5276
ind_type, n_fields);
5278
field_lengths = (ulint*) malloc(sizeof(ulint) * n_fields);
5280
for (i = 0; i < n_fields; i++) {
5281
key_part = key->key_part + i;
5283
/* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
5284
field in an index: we only store a specified number of first
5285
bytes of the column to the index field.) The flag does not
5286
seem to be properly set by MySQL. Let us fall back on testing
5287
the length of the key part versus the column. */
5290
for (j = 0; j < form->s->fields; j++) {
5292
field = form->field[j];
5294
if (0 == innobase_strcasecmp(
5296
key_part->field->field_name)) {
5297
/* Found the corresponding column */
5303
ut_a(j < form->s->fields);
5305
col_type = get_innobase_type_from_mysql_type(
5306
&is_unsigned, key_part->field);
5308
if (DATA_BLOB == col_type
5309
|| (key_part->length < field->pack_length()
5310
&& field->type() != DRIZZLE_TYPE_VARCHAR)
5311
|| (field->type() == DRIZZLE_TYPE_VARCHAR
5312
&& key_part->length < field->pack_length()
5313
- ((Field_varstring*)field)->length_bytes)) {
5315
prefix_len = key_part->length;
5317
if (col_type == DATA_INT
5318
|| col_type == DATA_FLOAT
5319
|| col_type == DATA_DOUBLE
5320
|| col_type == DATA_DECIMAL) {
5321
errmsg_printf(ERRMSG_LVL_ERROR,
5322
"MySQL is trying to create a column "
5323
"prefix index field, on an "
5324
"inappropriate data type. Table "
5325
"name %s, column name %s.",
5327
key_part->field->field_name);
5335
field_lengths[i] = key_part->length;
5337
dict_mem_index_add_field(index,
5338
(char*) key_part->field->field_name, prefix_len);
5341
/* Even though we've defined max_supported_key_part_length, we
5342
still do our own checking using field_lengths to be absolutely
5343
sure we don't create too long indexes. */
5344
error = row_create_index_for_mysql(index, trx, field_lengths);
5346
error = convert_error_code_to_mysql(error, flags, NULL);
5348
free(field_lengths);
5353
5353
/*****************************************************************//**
5382
5382
in future. For now, it checks two specifiers:
5383
5383
KEY_BLOCK_SIZE and ROW_FORMAT
5384
5384
If innodb_strict_mode is not set then this function is a no-op
5385
@return TRUE if valid. */
5385
@return TRUE if valid. */
5388
5388
create_options_are_valid(
5389
5389
/*=====================*/
5390
Session* session, /*!< in: connection thread. */
5391
Table& form, /*!< in: information on table
5392
columns and indexes */
5390
Session* session, /*!< in: connection thread. */
5391
Table& form, /*!< in: information on table
5392
columns and indexes */
5393
5393
message::Table& create_proto)
5395
ibool kbs_specified = FALSE;
5399
ut_ad(session != NULL);
5401
/* If innodb_strict_mode is not set don't do any validation. */
5402
if (!(SessionVAR(session, strict_mode))) {
5406
/* First check if KEY_BLOCK_SIZE was specified. */
5407
if (create_proto.options().has_key_block_size()) {
5409
kbs_specified = TRUE;
5410
switch (create_proto.options().key_block_size()) {
5419
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5420
ER_ILLEGAL_HA_CREATE_OPTION,
5422
" KEY_BLOCK_SIZE = %lu."
5424
" [1, 2, 4, 8, 16]",
5425
create_proto.options().key_block_size());
5430
/* If KEY_BLOCK_SIZE was specified, check for its
5432
if (kbs_specified && !srv_file_per_table) {
5433
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5434
ER_ILLEGAL_HA_CREATE_OPTION,
5435
"InnoDB: KEY_BLOCK_SIZE"
5436
" requires innodb_file_per_table.");
5440
if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
5441
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5442
ER_ILLEGAL_HA_CREATE_OPTION,
5443
"InnoDB: KEY_BLOCK_SIZE"
5444
" requires innodb_file_format >"
5449
/* Now check for ROW_FORMAT specifier. */
5450
if (create_proto.options().has_row_type()) {
5451
switch (form.s->row_type) {
5452
const char* row_format_name;
5453
case ROW_TYPE_COMPRESSED:
5454
case ROW_TYPE_DYNAMIC:
5456
= form.s->row_type == ROW_TYPE_COMPRESSED
5460
/* These two ROW_FORMATs require
5461
srv_file_per_table and srv_file_format */
5462
if (!srv_file_per_table) {
5463
push_warning_printf(
5465
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5466
ER_ILLEGAL_HA_CREATE_OPTION,
5467
"InnoDB: ROW_FORMAT=%s"
5468
" requires innodb_file_per_table.",
5474
if (srv_file_format < DICT_TF_FORMAT_ZIP) {
5475
push_warning_printf(
5477
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5478
ER_ILLEGAL_HA_CREATE_OPTION,
5479
"InnoDB: ROW_FORMAT=%s"
5480
" requires innodb_file_format >"
5486
/* Cannot specify KEY_BLOCK_SIZE with
5487
ROW_FORMAT = DYNAMIC.
5488
However, we do allow COMPRESSED to be
5489
specified with KEY_BLOCK_SIZE. */
5491
&& form.s->row_type == ROW_TYPE_DYNAMIC) {
5492
push_warning_printf(
5494
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5495
ER_ILLEGAL_HA_CREATE_OPTION,
5496
"InnoDB: cannot specify"
5497
" ROW_FORMAT = DYNAMIC with"
5498
" KEY_BLOCK_SIZE.");
5504
case ROW_TYPE_REDUNDANT:
5505
case ROW_TYPE_COMPACT:
5506
case ROW_TYPE_DEFAULT:
5507
/* Default is COMPACT. */
5509
= form.s->row_type == ROW_TYPE_REDUNDANT
5513
/* Cannot specify KEY_BLOCK_SIZE with these
5514
format specifiers. */
5515
if (kbs_specified) {
5516
push_warning_printf(
5518
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5519
ER_ILLEGAL_HA_CREATE_OPTION,
5520
"InnoDB: cannot specify"
5521
" ROW_FORMAT = %s with"
5530
push_warning(session,
5531
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5532
ER_ILLEGAL_HA_CREATE_OPTION,
5533
"InnoDB: invalid ROW_FORMAT specifier.");
5395
ibool kbs_specified = FALSE;
5399
ut_ad(session != NULL);
5401
/* If innodb_strict_mode is not set don't do any validation. */
5402
if (!(SessionVAR(session, strict_mode))) {
5406
/* First check if KEY_BLOCK_SIZE was specified. */
5407
if (create_proto.options().has_key_block_size()) {
5409
kbs_specified = TRUE;
5410
switch (create_proto.options().key_block_size()) {
5419
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5420
ER_ILLEGAL_HA_CREATE_OPTION,
5422
" KEY_BLOCK_SIZE = %lu."
5424
" [1, 2, 4, 8, 16]",
5425
create_proto.options().key_block_size());
5430
/* If KEY_BLOCK_SIZE was specified, check for its
5432
if (kbs_specified && !srv_file_per_table) {
5433
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5434
ER_ILLEGAL_HA_CREATE_OPTION,
5435
"InnoDB: KEY_BLOCK_SIZE"
5436
" requires innodb_file_per_table.");
5440
if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
5441
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5442
ER_ILLEGAL_HA_CREATE_OPTION,
5443
"InnoDB: KEY_BLOCK_SIZE"
5444
" requires innodb_file_format >"
5449
/* Now check for ROW_FORMAT specifier. */
5450
if (create_proto.options().has_row_type()) {
5451
switch (form.s->row_type) {
5452
const char* row_format_name;
5453
case ROW_TYPE_COMPRESSED:
5454
case ROW_TYPE_DYNAMIC:
5456
= form.s->row_type == ROW_TYPE_COMPRESSED
5460
/* These two ROW_FORMATs require
5461
srv_file_per_table and srv_file_format */
5462
if (!srv_file_per_table) {
5463
push_warning_printf(
5465
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5466
ER_ILLEGAL_HA_CREATE_OPTION,
5467
"InnoDB: ROW_FORMAT=%s"
5468
" requires innodb_file_per_table.",
5474
if (srv_file_format < DICT_TF_FORMAT_ZIP) {
5475
push_warning_printf(
5477
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5478
ER_ILLEGAL_HA_CREATE_OPTION,
5479
"InnoDB: ROW_FORMAT=%s"
5480
" requires innodb_file_format >"
5486
/* Cannot specify KEY_BLOCK_SIZE with
5487
ROW_FORMAT = DYNAMIC.
5488
However, we do allow COMPRESSED to be
5489
specified with KEY_BLOCK_SIZE. */
5491
&& form.s->row_type == ROW_TYPE_DYNAMIC) {
5492
push_warning_printf(
5494
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5495
ER_ILLEGAL_HA_CREATE_OPTION,
5496
"InnoDB: cannot specify"
5497
" ROW_FORMAT = DYNAMIC with"
5498
" KEY_BLOCK_SIZE.");
5504
case ROW_TYPE_REDUNDANT:
5505
case ROW_TYPE_COMPACT:
5506
case ROW_TYPE_DEFAULT:
5507
/* Default is COMPACT. */
5509
= form.s->row_type == ROW_TYPE_REDUNDANT
5513
/* Cannot specify KEY_BLOCK_SIZE with these
5514
format specifiers. */
5515
if (kbs_specified) {
5516
push_warning_printf(
5518
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5519
ER_ILLEGAL_HA_CREATE_OPTION,
5520
"InnoDB: cannot specify"
5521
" ROW_FORMAT = %s with"
5530
push_warning(session,
5531
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5532
ER_ILLEGAL_HA_CREATE_OPTION,
5533
"InnoDB: invalid ROW_FORMAT specifier.");
5542
5542
/*********************************************************************
5546
5546
InnobaseEngine::doCreateTable(
5547
5547
/*================*/
5548
Session &session, /*!< in: Session */
5549
Table& form, /*!< in: information on table columns and indexes */
5548
Session &session, /*!< in: Session */
5549
Table& form, /*!< in: information on table columns and indexes */
5550
5550
drizzled::TableIdentifier &identifier,
5551
5551
message::Table& create_proto)
5554
dict_table_t* innobase_table;
5559
char name2[FN_REFLEN];
5560
char norm_name[FN_REFLEN];
5561
ib_int64_t auto_inc_value;
5563
/* Cache the value of innodb_file_format, in case it is
5564
modified by another thread while the table is being created. */
5565
const ulint file_format = srv_file_format;
5554
dict_table_t* innobase_table;
5559
char name2[FN_REFLEN];
5560
char norm_name[FN_REFLEN];
5561
ib_int64_t auto_inc_value;
5563
/* Cache the value of innodb_file_format, in case it is
5564
modified by another thread while the table is being created. */
5565
const ulint file_format = srv_file_format;
5566
5566
bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
5568
const char *table_name= identifier.getPath().c_str();
5568
const char *table_name= identifier.getPath().c_str();
5571
/* Names passed in from server are in two formats:
5572
1. <database_name>/<table_name>: for normal table creation
5573
2. full path: for temp table creation, or sym link
5575
When srv_file_per_table is on, check for full path pattern, i.e.
5576
X:\dir\..., X is a driver letter, or
5577
\\dir1\dir2\..., UNC path
5578
returns error if it is in full path format, but not creating a temp.
5579
table. Currently InnoDB does not support symbolic link on Windows. */
5581
if (srv_file_per_table
5582
&& (! lex_identified_temp_table)) {
5584
if ((table_name[1] == ':')
5585
|| (table_name[0] == '\\' && table_name[1] == '\\')) {
5586
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot create table %s\n", table_name);
5587
return(HA_ERR_GENERIC);
5571
/* Names passed in from server are in two formats:
5572
1. <database_name>/<table_name>: for normal table creation
5573
2. full path: for temp table creation, or sym link
5575
When srv_file_per_table is on, check for full path pattern, i.e.
5576
X:\dir\..., X is a driver letter, or
5577
\\dir1\dir2\..., UNC path
5578
returns error if it is in full path format, but not creating a temp.
5579
table. Currently InnoDB does not support symbolic link on Windows. */
5581
if (srv_file_per_table
5582
&& (! lex_identified_temp_table)) {
5584
if ((table_name[1] == ':')
5585
|| (table_name[0] == '\\' && table_name[1] == '\\')) {
5586
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot create table %s\n", table_name);
5587
return(HA_ERR_GENERIC);
5592
if (form.s->fields > 1000) {
5593
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
5594
but we play safe here */
5596
return(HA_ERR_TO_BIG_ROW);
5599
/* Get the transaction associated with the current session, or create one
5600
if not yet created */
5602
parent_trx = check_trx_exists(&session);
5604
/* In case MySQL calls this in the middle of a SELECT query, release
5605
possible adaptive hash latch to avoid deadlocks of threads */
5607
trx_search_latch_release_if_reserved(parent_trx);
5609
trx = innobase_trx_allocate(&session);
5611
srv_lower_case_table_names = TRUE;
5613
strcpy(name2, table_name);
5615
normalize_table_name(norm_name, name2);
5617
/* Latch the InnoDB data dictionary exclusively so that no deadlocks
5618
or lock waits can happen in it during a table create operation.
5619
Drop table etc. do this latching in row0mysql.c. */
5621
row_mysql_lock_data_dictionary(trx);
5623
/* Create the table definition in InnoDB */
5627
/* Validate create options if innodb_strict_mode is set. */
5628
if (! create_options_are_valid(&session, form, create_proto)) {
5629
error = ER_ILLEGAL_HA_CREATE_OPTION;
5633
if (create_proto.options().has_key_block_size()) {
5634
/* Determine the page_zip.ssize corresponding to the
5635
requested page size (key_block_size) in kilobytes. */
5638
ulint key_block_size = create_proto.options().key_block_size();
5640
for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX;
5641
ssize++, ksize <<= 1) {
5642
if (key_block_size == ksize) {
5643
iflags = ssize << DICT_TF_ZSSIZE_SHIFT
5645
| DICT_TF_FORMAT_ZIP
5646
<< DICT_TF_FORMAT_SHIFT;
5651
if (!srv_file_per_table) {
5652
push_warning(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5653
ER_ILLEGAL_HA_CREATE_OPTION,
5654
"InnoDB: KEY_BLOCK_SIZE"
5655
" requires innodb_file_per_table.");
5659
if (file_format < DICT_TF_FORMAT_ZIP) {
5660
push_warning(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5661
ER_ILLEGAL_HA_CREATE_OPTION,
5662
"InnoDB: KEY_BLOCK_SIZE"
5663
" requires innodb_file_format >"
5669
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5670
ER_ILLEGAL_HA_CREATE_OPTION,
5672
" KEY_BLOCK_SIZE=%lu.",
5673
create_proto.options().key_block_size());
5677
if (create_proto.options().has_row_type()) {
5679
/* KEY_BLOCK_SIZE was specified. */
5680
if (form.s->row_type != ROW_TYPE_COMPRESSED) {
5681
/* ROW_FORMAT other than COMPRESSED
5682
ignores KEY_BLOCK_SIZE. It does not
5683
make sense to reject conflicting
5684
KEY_BLOCK_SIZE and ROW_FORMAT, because
5685
such combinations can be obtained
5686
with ALTER TABLE anyway. */
5687
push_warning_printf(
5689
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5690
ER_ILLEGAL_HA_CREATE_OPTION,
5691
"InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
5692
" unless ROW_FORMAT=COMPRESSED.",
5693
create_proto.options().key_block_size());
5697
/* No KEY_BLOCK_SIZE */
5698
if (form.s->row_type == ROW_TYPE_COMPRESSED) {
5699
/* ROW_FORMAT=COMPRESSED without
5700
KEY_BLOCK_SIZE implies half the
5701
maximum KEY_BLOCK_SIZE. */
5702
iflags = (DICT_TF_ZSSIZE_MAX - 1)
5703
<< DICT_TF_ZSSIZE_SHIFT
5705
| DICT_TF_FORMAT_ZIP
5706
<< DICT_TF_FORMAT_SHIFT;
5592
if (form.s->fields > 1000) {
5593
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
5594
but we play safe here */
5596
return(HA_ERR_TO_BIG_ROW);
5599
/* Get the transaction associated with the current session, or create one
5600
if not yet created */
5602
parent_trx = check_trx_exists(&session);
5604
/* In case MySQL calls this in the middle of a SELECT query, release
5605
possible adaptive hash latch to avoid deadlocks of threads */
5607
trx_search_latch_release_if_reserved(parent_trx);
5609
trx = innobase_trx_allocate(&session);
5611
srv_lower_case_table_names = TRUE;
5613
strcpy(name2, table_name);
5615
normalize_table_name(norm_name, name2);
5617
/* Latch the InnoDB data dictionary exclusively so that no deadlocks
5618
or lock waits can happen in it during a table create operation.
5619
Drop table etc. do this latching in row0mysql.c. */
5621
row_mysql_lock_data_dictionary(trx);
5623
/* Create the table definition in InnoDB */
5627
/* Validate create options if innodb_strict_mode is set. */
5628
if (! create_options_are_valid(&session, form, create_proto)) {
5629
error = ER_ILLEGAL_HA_CREATE_OPTION;
5633
if (create_proto.options().has_key_block_size()) {
5634
/* Determine the page_zip.ssize corresponding to the
5635
requested page size (key_block_size) in kilobytes. */
5638
ulint key_block_size = create_proto.options().key_block_size();
5640
for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX;
5641
ssize++, ksize <<= 1) {
5642
if (key_block_size == ksize) {
5643
iflags = ssize << DICT_TF_ZSSIZE_SHIFT
5645
| DICT_TF_FORMAT_ZIP
5646
<< DICT_TF_FORMAT_SHIFT;
5651
if (!srv_file_per_table) {
5652
push_warning(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5653
ER_ILLEGAL_HA_CREATE_OPTION,
5654
"InnoDB: KEY_BLOCK_SIZE"
5655
" requires innodb_file_per_table.");
5659
if (file_format < DICT_TF_FORMAT_ZIP) {
5660
push_warning(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5661
ER_ILLEGAL_HA_CREATE_OPTION,
5662
"InnoDB: KEY_BLOCK_SIZE"
5663
" requires innodb_file_format >"
5669
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5670
ER_ILLEGAL_HA_CREATE_OPTION,
5672
" KEY_BLOCK_SIZE=%lu.",
5673
create_proto.options().key_block_size());
5677
if (create_proto.options().has_row_type()) {
5679
/* KEY_BLOCK_SIZE was specified. */
5680
if (form.s->row_type != ROW_TYPE_COMPRESSED) {
5681
/* ROW_FORMAT other than COMPRESSED
5682
ignores KEY_BLOCK_SIZE. It does not
5683
make sense to reject conflicting
5684
KEY_BLOCK_SIZE and ROW_FORMAT, because
5685
such combinations can be obtained
5686
with ALTER TABLE anyway. */
5687
push_warning_printf(
5689
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5690
ER_ILLEGAL_HA_CREATE_OPTION,
5691
"InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
5692
" unless ROW_FORMAT=COMPRESSED.",
5693
create_proto.options().key_block_size());
5697
/* No KEY_BLOCK_SIZE */
5698
if (form.s->row_type == ROW_TYPE_COMPRESSED) {
5699
/* ROW_FORMAT=COMPRESSED without
5700
KEY_BLOCK_SIZE implies half the
5701
maximum KEY_BLOCK_SIZE. */
5702
iflags = (DICT_TF_ZSSIZE_MAX - 1)
5703
<< DICT_TF_ZSSIZE_SHIFT
5705
| DICT_TF_FORMAT_ZIP
5706
<< DICT_TF_FORMAT_SHIFT;
5707
5707
#if DICT_TF_ZSSIZE_MAX < 1
5708
5708
# error "DICT_TF_ZSSIZE_MAX < 1"
5713
switch (form.s->row_type) {
5714
const char* row_format_name;
5715
case ROW_TYPE_REDUNDANT:
5717
case ROW_TYPE_COMPRESSED:
5718
case ROW_TYPE_DYNAMIC:
5720
= form.s->row_type == ROW_TYPE_COMPRESSED
5724
if (!srv_file_per_table) {
5725
push_warning_printf(
5727
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5728
ER_ILLEGAL_HA_CREATE_OPTION,
5729
"InnoDB: ROW_FORMAT=%s"
5730
" requires innodb_file_per_table.",
5732
} else if (file_format < DICT_TF_FORMAT_ZIP) {
5733
push_warning_printf(
5735
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5736
ER_ILLEGAL_HA_CREATE_OPTION,
5737
"InnoDB: ROW_FORMAT=%s"
5738
" requires innodb_file_format >"
5742
iflags |= DICT_TF_COMPACT
5743
| (DICT_TF_FORMAT_ZIP
5744
<< DICT_TF_FORMAT_SHIFT);
5749
case ROW_TYPE_NOT_USED:
5750
case ROW_TYPE_FIXED:
5713
switch (form.s->row_type) {
5714
const char* row_format_name;
5715
case ROW_TYPE_REDUNDANT:
5717
case ROW_TYPE_COMPRESSED:
5718
case ROW_TYPE_DYNAMIC:
5720
= form.s->row_type == ROW_TYPE_COMPRESSED
5724
if (!srv_file_per_table) {
5725
push_warning_printf(
5727
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5728
ER_ILLEGAL_HA_CREATE_OPTION,
5729
"InnoDB: ROW_FORMAT=%s"
5730
" requires innodb_file_per_table.",
5732
} else if (file_format < DICT_TF_FORMAT_ZIP) {
5733
push_warning_printf(
5735
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5736
ER_ILLEGAL_HA_CREATE_OPTION,
5737
"InnoDB: ROW_FORMAT=%s"
5738
" requires innodb_file_format >"
5742
iflags |= DICT_TF_COMPACT
5743
| (DICT_TF_FORMAT_ZIP
5744
<< DICT_TF_FORMAT_SHIFT);
5749
case ROW_TYPE_NOT_USED:
5750
case ROW_TYPE_FIXED:
5752
5752
error = ER_ILLEGAL_HA_CREATE_OPTION;
5754
case ROW_TYPE_DEFAULT:
5755
case ROW_TYPE_COMPACT:
5756
iflags = DICT_TF_COMPACT;
5759
} else if (!iflags) {
5760
/* No KEY_BLOCK_SIZE or ROW_FORMAT specified:
5761
use ROW_FORMAT=COMPACT by default. */
5762
iflags = DICT_TF_COMPACT;
5765
error = create_table_def(trx, &form, norm_name,
5766
lex_identified_temp_table ? name2 : NULL,
5773
/* Look for a primary key */
5775
primary_key_no= (form.s->primary_key != MAX_KEY ?
5776
(int) form.s->primary_key :
5779
/* Our function row_get_mysql_key_number_for_index assumes
5780
the primary key is always number 0, if it exists */
5782
assert(primary_key_no == -1 || primary_key_no == 0);
5784
/* Create the keys */
5786
if (form.s->keys == 0 || primary_key_no == -1) {
5787
/* Create an index which is used as the clustered index;
5788
order the rows by their row id which is internally generated
5791
error = create_clustered_index_when_no_primary(
5792
trx, iflags, norm_name);
5798
if (primary_key_no != -1) {
5799
/* In InnoDB the clustered index must always be created
5801
if ((error = create_index(trx, &form, iflags, norm_name,
5802
(uint) primary_key_no))) {
5807
for (i = 0; i < form.s->keys; i++) {
5809
if (i != (uint) primary_key_no) {
5811
if ((error = create_index(trx, &form, iflags, norm_name,
5818
if (trx->mysql_query_str) {
5819
error = row_table_add_foreign_constraints(trx,
5820
trx->mysql_query_str, norm_name,
5821
lex_identified_temp_table);
5823
error = convert_error_code_to_mysql(error, iflags, NULL);
5830
innobase_commit_low(trx);
5832
row_mysql_unlock_data_dictionary(trx);
5834
/* Flush the log to reduce probability that the .frm files and
5835
the InnoDB data dictionary get out-of-sync if the user runs
5836
with innodb_flush_log_at_trx_commit = 0 */
5838
log_buffer_flush_to_disk();
5840
innobase_table = dict_table_get(norm_name, FALSE);
5842
assert(innobase_table != 0);
5844
if (innobase_table) {
5845
/* We update the highest file format in the system table
5846
space, if this table has higher file format setting. */
5848
trx_sys_file_format_max_upgrade(
5849
(const char**) &innobase_file_format_check,
5850
dict_table_get_format(innobase_table));
5853
/* Note: We can't call update_session() as prebuilt will not be
5854
setup at this stage and so we use session. */
5856
/* We need to copy the AUTOINC value from the old table if
5857
this is an ALTER TABLE. */
5859
if ((create_proto.options().has_auto_increment_value()
5860
|| session_sql_command(&session) == SQLCOM_ALTER_TABLE)
5861
&& create_proto.options().auto_increment_value() != 0) {
5863
/* Query was ALTER TABLE...AUTO_INCREMENT = x; or
5864
CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
5865
definition from the dictionary and get the current value
5866
of the auto increment field. Set a new value to the
5867
auto increment field if the value is greater than the
5868
maximum value in the column. */
5870
auto_inc_value = create_proto.options().auto_increment_value();
5872
dict_table_autoinc_lock(innobase_table);
5873
dict_table_autoinc_initialize(innobase_table, auto_inc_value);
5874
dict_table_autoinc_unlock(innobase_table);
5877
/* Tell the InnoDB server that there might be work for
5880
srv_active_wake_master_thread();
5882
trx_free_for_mysql(trx);
5754
case ROW_TYPE_DEFAULT:
5755
case ROW_TYPE_COMPACT:
5756
iflags = DICT_TF_COMPACT;
5759
} else if (!iflags) {
5760
/* No KEY_BLOCK_SIZE or ROW_FORMAT specified:
5761
use ROW_FORMAT=COMPACT by default. */
5762
iflags = DICT_TF_COMPACT;
5765
error = create_table_def(trx, &form, norm_name,
5766
lex_identified_temp_table ? name2 : NULL,
5773
/* Look for a primary key */
5775
primary_key_no= (form.s->primary_key != MAX_KEY ?
5776
(int) form.s->primary_key :
5779
/* Our function row_get_mysql_key_number_for_index assumes
5780
the primary key is always number 0, if it exists */
5782
assert(primary_key_no == -1 || primary_key_no == 0);
5784
/* Create the keys */
5786
if (form.s->keys == 0 || primary_key_no == -1) {
5787
/* Create an index which is used as the clustered index;
5788
order the rows by their row id which is internally generated
5791
error = create_clustered_index_when_no_primary(
5792
trx, iflags, norm_name);
5798
if (primary_key_no != -1) {
5799
/* In InnoDB the clustered index must always be created
5801
if ((error = create_index(trx, &form, iflags, norm_name,
5802
(uint) primary_key_no))) {
5807
for (i = 0; i < form.s->keys; i++) {
5809
if (i != (uint) primary_key_no) {
5811
if ((error = create_index(trx, &form, iflags, norm_name,
5818
if (trx->mysql_query_str) {
5819
error = row_table_add_foreign_constraints(trx,
5820
trx->mysql_query_str, norm_name,
5821
lex_identified_temp_table);
5823
error = convert_error_code_to_mysql(error, iflags, NULL);
5830
innobase_commit_low(trx);
5832
row_mysql_unlock_data_dictionary(trx);
5834
/* Flush the log to reduce probability that the .frm files and
5835
the InnoDB data dictionary get out-of-sync if the user runs
5836
with innodb_flush_log_at_trx_commit = 0 */
5838
log_buffer_flush_to_disk();
5840
innobase_table = dict_table_get(norm_name, FALSE);
5842
assert(innobase_table != 0);
5844
if (innobase_table) {
5845
/* We update the highest file format in the system table
5846
space, if this table has higher file format setting. */
5848
trx_sys_file_format_max_upgrade(
5849
(const char**) &innobase_file_format_check,
5850
dict_table_get_format(innobase_table));
5853
/* Note: We can't call update_session() as prebuilt will not be
5854
setup at this stage and so we use session. */
5856
/* We need to copy the AUTOINC value from the old table if
5857
this is an ALTER TABLE. */
5859
if ((create_proto.options().has_auto_increment_value()
5860
|| session_sql_command(&session) == SQLCOM_ALTER_TABLE)
5861
&& create_proto.options().auto_increment_value() != 0) {
5863
/* Query was ALTER TABLE...AUTO_INCREMENT = x; or
5864
CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
5865
definition from the dictionary and get the current value
5866
of the auto increment field. Set a new value to the
5867
auto increment field if the value is greater than the
5868
maximum value in the column. */
5870
auto_inc_value = create_proto.options().auto_increment_value();
5872
dict_table_autoinc_lock(innobase_table);
5873
dict_table_autoinc_initialize(innobase_table, auto_inc_value);
5874
dict_table_autoinc_unlock(innobase_table);
5877
/* Tell the InnoDB server that there might be work for
5880
srv_active_wake_master_thread();
5882
trx_free_for_mysql(trx);
5884
5884
StorageEngine::writeDefinitionFromPath(identifier, create_proto);
5889
innobase_commit_low(trx);
5891
row_mysql_unlock_data_dictionary(trx);
5893
trx_free_for_mysql(trx);
5889
innobase_commit_low(trx);
5891
row_mysql_unlock_data_dictionary(trx);
5893
trx_free_for_mysql(trx);
5898
5898
/*****************************************************************//**
5899
5899
Discards or imports an InnoDB tablespace.
5900
@return 0 == success, -1 == error */
5900
@return 0 == success, -1 == error */
5903
5903
ha_innobase::discard_or_import_tablespace(
5904
5904
/*======================================*/
5905
my_bool discard) /*!< in: TRUE if discard, else import */
5905
my_bool discard) /*!< in: TRUE if discard, else import */
5907
dict_table_t* dict_table;
5911
ut_a(prebuilt->trx);
5912
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
5913
ut_a(prebuilt->trx == session_to_trx(ha_session()));
5915
dict_table = prebuilt->table;
5916
trx = prebuilt->trx;
5919
err = row_discard_tablespace_for_mysql(dict_table->name, trx);
5921
err = row_import_tablespace_for_mysql(dict_table->name, trx);
5924
err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
5907
dict_table_t* dict_table;
5911
ut_a(prebuilt->trx);
5912
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
5913
ut_a(prebuilt->trx == session_to_trx(ha_session()));
5915
dict_table = prebuilt->table;
5916
trx = prebuilt->trx;
5919
err = row_discard_tablespace_for_mysql(dict_table->name, trx);
5921
err = row_import_tablespace_for_mysql(dict_table->name, trx);
5924
err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
5929
5929
/*****************************************************************//**
5930
5930
Deletes all rows of an InnoDB table.
5931
@return error number */
5931
@return error number */
5934
5934
ha_innobase::delete_all_rows(void)
5935
5935
/*==============================*/
5939
/* Get the transaction associated with the current session, or create one
5940
if not yet created, and update prebuilt->trx */
5942
update_session(ha_session());
5944
if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
5946
/* We only handle TRUNCATE TABLE t as a special case.
5947
DELETE FROM t will have to use ha_innobase::delete_row(),
5948
because DELETE is transactional while TRUNCATE is not. */
5949
return(errno=HA_ERR_WRONG_COMMAND);
5952
/* Truncate the table in InnoDB */
5954
error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
5955
if (error == DB_ERROR) {
5956
/* Cannot truncate; resort to ha_innobase::delete_row() */
5960
error = convert_error_code_to_mysql(error, prebuilt->table->flags,
5939
/* Get the transaction associated with the current session, or create one
5940
if not yet created, and update prebuilt->trx */
5942
update_session(ha_session());
5944
if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
5946
/* We only handle TRUNCATE TABLE t as a special case.
5947
DELETE FROM t will have to use ha_innobase::delete_row(),
5948
because DELETE is transactional while TRUNCATE is not. */
5949
return(errno=HA_ERR_WRONG_COMMAND);
5952
/* Truncate the table in InnoDB */
5954
error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
5955
if (error == DB_ERROR) {
5956
/* Cannot truncate; resort to ha_innobase::delete_row() */
5960
error = convert_error_code_to_mysql(error, prebuilt->table->flags,
5966
5966
/*****************************************************************//**
6044
6044
InnobaseEngine::doDropSchema(
6045
6045
/*===================*/
6046
6046
SchemaIdentifier &identifier)
6047
/*!< in: database path; inside InnoDB the name
6048
of the last directory in the path is used as
6049
the database name: for example, in 'mysql/data/test'
6050
the database name is 'test' */
6047
/*!< in: database path; inside InnoDB the name
6048
of the last directory in the path is used as
6049
the database name: for example, in 'mysql/data/test'
6050
the database name is 'test' */
6054
string schema_path(identifier.getPath());
6055
Session* session = current_session;
6057
/* Get the transaction associated with the current session, or create one
6058
if not yet created */
6060
assert(this == innodb_engine_ptr);
6062
/* In the Windows plugin, session = current_session is always NULL */
6064
trx_t* parent_trx = check_trx_exists(session);
6066
/* In case Drizzle calls this in the middle of a SELECT
6067
query, release possible adaptive hash latch to avoid
6068
deadlocks of threads */
6070
trx_search_latch_release_if_reserved(parent_trx);
6054
string schema_path(identifier.getPath());
6055
Session* session = current_session;
6057
/* Get the transaction associated with the current session, or create one
6058
if not yet created */
6060
assert(this == innodb_engine_ptr);
6062
/* In the Windows plugin, session = current_session is always NULL */
6064
trx_t* parent_trx = check_trx_exists(session);
6066
/* In case Drizzle calls this in the middle of a SELECT
6067
query, release possible adaptive hash latch to avoid
6068
deadlocks of threads */
6070
trx_search_latch_release_if_reserved(parent_trx);
6073
6073
schema_path.append("/");
6074
trx = innobase_trx_allocate(session);
6075
error = row_drop_database_for_mysql(schema_path.c_str(), trx);
6077
/* Flush the log to reduce probability that the .frm files and
6078
the InnoDB data dictionary get out-of-sync if the user runs
6079
with innodb_flush_log_at_trx_commit = 0 */
6081
log_buffer_flush_to_disk();
6083
/* Tell the InnoDB server that there might be work for
6086
srv_active_wake_master_thread();
6088
innobase_commit_low(trx);
6089
trx_free_for_mysql(trx);
6074
trx = innobase_trx_allocate(session);
6075
error = row_drop_database_for_mysql(schema_path.c_str(), trx);
6077
/* Flush the log to reduce probability that the .frm files and
6078
the InnoDB data dictionary get out-of-sync if the user runs
6079
with innodb_flush_log_at_trx_commit = 0 */
6081
log_buffer_flush_to_disk();
6083
/* Tell the InnoDB server that there might be work for
6086
srv_active_wake_master_thread();
6088
innobase_commit_low(trx);
6089
trx_free_for_mysql(trx);
6091
6091
return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement.
6093
6093
/*********************************************************************//**
6094
6094
Renames an InnoDB table.
6095
@return 0 or error code */
6095
@return 0 or error code */
6098
6098
innobase_rename_table(
6099
6099
/*==================*/
6100
trx_t* trx, /*!< in: transaction */
6101
const char* from, /*!< in: old name of the table */
6102
const char* to, /*!< in: new name of the table */
6103
ibool lock_and_commit)
6104
/*!< in: TRUE=lock data dictionary and commit */
6100
trx_t* trx, /*!< in: transaction */
6101
const char* from, /*!< in: old name of the table */
6102
const char* to, /*!< in: new name of the table */
6103
ibool lock_and_commit)
6104
/*!< in: TRUE=lock data dictionary and commit */
6110
srv_lower_case_table_names = TRUE;
6112
// Magic number 64 arbitrary
6113
norm_to = (char*) malloc(strlen(to) + 64);
6114
norm_from = (char*) malloc(strlen(from) + 64);
6116
normalize_table_name(norm_to, to);
6117
normalize_table_name(norm_from, from);
6119
/* Serialize data dictionary operations with dictionary mutex:
6120
no deadlocks can occur then in these operations */
6122
if (lock_and_commit) {
6123
row_mysql_lock_data_dictionary(trx);
6126
error = row_rename_table_for_mysql(
6127
norm_from, norm_to, trx, lock_and_commit);
6129
if (error != DB_SUCCESS) {
6130
FILE* ef = dict_foreign_err_file;
6132
fputs("InnoDB: Renaming table ", ef);
6133
ut_print_name(ef, trx, TRUE, norm_from);
6135
ut_print_name(ef, trx, TRUE, norm_to);
6136
fputs(" failed!\n", ef);
6139
if (lock_and_commit) {
6140
row_mysql_unlock_data_dictionary(trx);
6142
/* Flush the log to reduce probability that the .frm
6143
files and the InnoDB data dictionary get out-of-sync
6144
if the user runs with innodb_flush_log_at_trx_commit = 0 */
6146
log_buffer_flush_to_disk();
6110
srv_lower_case_table_names = TRUE;
6112
// Magic number 64 arbitrary
6113
norm_to = (char*) malloc(strlen(to) + 64);
6114
norm_from = (char*) malloc(strlen(from) + 64);
6116
normalize_table_name(norm_to, to);
6117
normalize_table_name(norm_from, from);
6119
/* Serialize data dictionary operations with dictionary mutex:
6120
no deadlocks can occur then in these operations */
6122
if (lock_and_commit) {
6123
row_mysql_lock_data_dictionary(trx);
6126
error = row_rename_table_for_mysql(
6127
norm_from, norm_to, trx, lock_and_commit);
6129
if (error != DB_SUCCESS) {
6130
FILE* ef = dict_foreign_err_file;
6132
fputs("InnoDB: Renaming table ", ef);
6133
ut_print_name(ef, trx, TRUE, norm_from);
6135
ut_print_name(ef, trx, TRUE, norm_to);
6136
fputs(" failed!\n", ef);
6139
if (lock_and_commit) {
6140
row_mysql_unlock_data_dictionary(trx);
6142
/* Flush the log to reduce probability that the .frm
6143
files and the InnoDB data dictionary get out-of-sync
6144
if the user runs with innodb_flush_log_at_trx_commit = 0 */
6146
log_buffer_flush_to_disk();
6154
6154
/*********************************************************************//**
6155
6155
Renames an InnoDB table.
6156
@return 0 or error code */
6156
@return 0 or error code */
6157
6157
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
6159
6159
// A temp table alter table/rename is a shallow rename and only the
6197
6197
plugin::StorageEngine::renameDefinitionFromPath(to, from);
6203
6203
/*********************************************************************//**
6204
6204
Estimates the number of index records in a range.
6205
@return estimated number of rows */
6205
@return estimated number of rows */
6208
6208
ha_innobase::records_in_range(
6209
6209
/*==========================*/
6210
uint keynr, /*!< in: index number */
6211
key_range *min_key, /*!< in: start key value of the
6212
range, may also be 0 */
6213
key_range *max_key) /*!< in: range end key val, may
6210
uint keynr, /*!< in: index number */
6211
key_range *min_key, /*!< in: start key value of the
6212
range, may also be 0 */
6213
key_range *max_key) /*!< in: range end key val, may
6217
dict_index_t* index;
6218
unsigned char* key_val_buff2 = (unsigned char*) malloc(
6219
table->s->stored_rec_length
6220
+ table->s->max_key_length + 100);
6221
ulint buff2_len = table->s->stored_rec_length
6222
+ table->s->max_key_length + 100;
6223
dtuple_t* range_start;
6224
dtuple_t* range_end;
6230
ut_a(prebuilt->trx == session_to_trx(ha_session()));
6232
prebuilt->trx->op_info = (char*)"estimating records in index range";
6234
/* In case MySQL calls this in the middle of a SELECT query, release
6235
possible adaptive hash latch to avoid deadlocks of threads */
6237
trx_search_latch_release_if_reserved(prebuilt->trx);
6239
active_index = keynr;
6241
key = table->key_info + active_index;
6243
index = dict_table_get_index_on_name(prebuilt->table, key->name);
6245
/* MySQL knows about this index and so we must be able to find it.*/
6248
heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6249
+ sizeof(dtuple_t)));
6251
range_start = dtuple_create(heap, key->key_parts);
6252
dict_index_copy_types(range_start, index, key->key_parts);
6254
range_end = dtuple_create(heap, key->key_parts);
6255
dict_index_copy_types(range_end, index, key->key_parts);
6257
row_sel_convert_mysql_key_to_innobase(
6258
range_start, (byte*) key_val_buff,
6259
(ulint)upd_and_key_val_buff_len,
6261
(byte*) (min_key ? min_key->key :
6262
(const unsigned char*) 0),
6263
(ulint) (min_key ? min_key->length : 0),
6266
row_sel_convert_mysql_key_to_innobase(
6267
range_end, (byte*) key_val_buff2,
6269
(byte*) (max_key ? max_key->key :
6270
(const unsigned char*) 0),
6271
(ulint) (max_key ? max_key->length : 0),
6274
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
6276
mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
6279
if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
6281
n_rows = btr_estimate_n_rows_in_range(index, range_start,
6286
n_rows = HA_POS_ERROR;
6289
mem_heap_free(heap);
6291
free(key_val_buff2);
6293
prebuilt->trx->op_info = (char*)"";
6295
/* The MySQL optimizer seems to believe an estimate of 0 rows is
6296
always accurate and may return the result 'Empty set' based on that.
6297
The accuracy is not guaranteed, and even if it were, for a locking
6298
read we should anyway perform the search to set the next-key lock.
6299
Add 1 to the value to make sure MySQL does not make the assumption! */
6305
return((ha_rows) n_rows);
6217
dict_index_t* index;
6218
unsigned char* key_val_buff2 = (unsigned char*) malloc(
6219
table->s->stored_rec_length
6220
+ table->s->max_key_length + 100);
6221
ulint buff2_len = table->s->stored_rec_length
6222
+ table->s->max_key_length + 100;
6223
dtuple_t* range_start;
6224
dtuple_t* range_end;
6230
ut_a(prebuilt->trx == session_to_trx(ha_session()));
6232
prebuilt->trx->op_info = (char*)"estimating records in index range";
6234
/* In case MySQL calls this in the middle of a SELECT query, release
6235
possible adaptive hash latch to avoid deadlocks of threads */
6237
trx_search_latch_release_if_reserved(prebuilt->trx);
6239
active_index = keynr;
6241
key = table->key_info + active_index;
6243
index = dict_table_get_index_on_name(prebuilt->table, key->name);
6245
/* MySQL knows about this index and so we must be able to find it.*/
6248
heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6249
+ sizeof(dtuple_t)));
6251
range_start = dtuple_create(heap, key->key_parts);
6252
dict_index_copy_types(range_start, index, key->key_parts);
6254
range_end = dtuple_create(heap, key->key_parts);
6255
dict_index_copy_types(range_end, index, key->key_parts);
6257
row_sel_convert_mysql_key_to_innobase(
6258
range_start, (byte*) key_val_buff,
6259
(ulint)upd_and_key_val_buff_len,
6261
(byte*) (min_key ? min_key->key :
6262
(const unsigned char*) 0),
6263
(ulint) (min_key ? min_key->length : 0),
6266
row_sel_convert_mysql_key_to_innobase(
6267
range_end, (byte*) key_val_buff2,
6269
(byte*) (max_key ? max_key->key :
6270
(const unsigned char*) 0),
6271
(ulint) (max_key ? max_key->length : 0),
6274
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
6276
mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
6279
if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
6281
n_rows = btr_estimate_n_rows_in_range(index, range_start,
6286
n_rows = HA_POS_ERROR;
6289
mem_heap_free(heap);
6291
free(key_val_buff2);
6293
prebuilt->trx->op_info = (char*)"";
6295
/* The MySQL optimizer seems to believe an estimate of 0 rows is
6296
always accurate and may return the result 'Empty set' based on that.
6297
The accuracy is not guaranteed, and even if it were, for a locking
6298
read we should anyway perform the search to set the next-key lock.
6299
Add 1 to the value to make sure MySQL does not make the assumption! */
6305
return((ha_rows) n_rows);
6308
6308
/*********************************************************************//**
6309
6309
Gives an UPPER BOUND to the number of rows in a table. This is used in
6311
@return upper bound of rows */
6311
@return upper bound of rows */
6314
6314
ha_innobase::estimate_rows_upper_bound(void)
6315
6315
/*======================================*/
6317
dict_index_t* index;
6319
uint64_t local_data_file_length;
6321
/* We do not know if MySQL can call this function before calling
6322
external_lock(). To be safe, update the session of the current table
6325
update_session(ha_session());
6327
prebuilt->trx->op_info = (char*)
6328
"calculating upper bound for table rows";
6330
/* In case MySQL calls this in the middle of a SELECT query, release
6331
possible adaptive hash latch to avoid deadlocks of threads */
6333
trx_search_latch_release_if_reserved(prebuilt->trx);
6335
index = dict_table_get_first_index(prebuilt->table);
6337
ut_a(index->stat_n_leaf_pages > 0);
6339
local_data_file_length =
6340
((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6343
/* Calculate a minimum length for a clustered index record and from
6344
that an upper bound for the number of rows. Since we only calculate
6345
new statistics in row0mysql.c when a table has grown by a threshold
6346
factor, we must add a safety factor 2 in front of the formula below. */
6348
estimate = 2 * local_data_file_length /
6349
dict_index_calc_min_rec_len(index);
6351
prebuilt->trx->op_info = (char*)"";
6353
return((ha_rows) estimate);
6317
dict_index_t* index;
6319
uint64_t local_data_file_length;
6321
/* We do not know if MySQL can call this function before calling
6322
external_lock(). To be safe, update the session of the current table
6325
update_session(ha_session());
6327
prebuilt->trx->op_info = (char*)
6328
"calculating upper bound for table rows";
6330
/* In case MySQL calls this in the middle of a SELECT query, release
6331
possible adaptive hash latch to avoid deadlocks of threads */
6333
trx_search_latch_release_if_reserved(prebuilt->trx);
6335
index = dict_table_get_first_index(prebuilt->table);
6337
ut_a(index->stat_n_leaf_pages > 0);
6339
local_data_file_length =
6340
((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6343
/* Calculate a minimum length for a clustered index record and from
6344
that an upper bound for the number of rows. Since we only calculate
6345
new statistics in row0mysql.c when a table has grown by a threshold
6346
factor, we must add a safety factor 2 in front of the formula below. */
6348
estimate = 2 * local_data_file_length /
6349
dict_index_calc_min_rec_len(index);
6351
prebuilt->trx->op_info = (char*)"";
6353
return((ha_rows) estimate);
6356
6356
/*********************************************************************//**
6357
6357
How many seeks it will take to read through the table. This is to be
6358
6358
comparable to the number returned by records_in_range so that we can
6359
6359
decide if we should scan the table or use keys.
6360
@return estimated time measured in disk seeks */
6360
@return estimated time measured in disk seeks */
6363
6363
ha_innobase::scan_time()
6364
6364
/*====================*/
6366
/* Since MySQL seems to favor table scans too much over index
6367
searches, we pretend that a sequential read takes the same time
6368
as a random disk read, that is, we do not divide the following
6369
by 10, which would be physically realistic. */
6366
/* Since MySQL seems to favor table scans too much over index
6367
searches, we pretend that a sequential read takes the same time
6368
as a random disk read, that is, we do not divide the following
6369
by 10, which would be physically realistic. */
6371
return((double) (prebuilt->table->stat_clustered_index_size));
6371
return((double) (prebuilt->table->stat_clustered_index_size));
6374
6374
/******************************************************************//**
6375
6375
Calculate the time it takes to read a set of ranges through an index
6376
6376
This enables us to optimise reads for clustered indexes.
6377
@return estimated time measured in disk seeks */
6377
@return estimated time measured in disk seeks */
6380
6380
ha_innobase::read_time(
6381
6381
/*===================*/
6382
uint index, /*!< in: key number */
6383
uint ranges, /*!< in: how many ranges */
6384
ha_rows rows) /*!< in: estimated number of rows in the ranges */
6382
uint index, /*!< in: key number */
6383
uint ranges, /*!< in: how many ranges */
6384
ha_rows rows) /*!< in: estimated number of rows in the ranges */
6387
double time_for_scan;
6389
if (index != table->s->primary_key) {
6391
return(Cursor::read_time(index, ranges, rows));
6396
return((double) rows);
6399
/* Assume that the read time is proportional to the scan time for all
6400
rows + at most one seek per range. */
6402
time_for_scan = scan_time();
6404
if ((total_rows = estimate_rows_upper_bound()) < rows) {
6406
return(time_for_scan);
6409
return(ranges + (double) rows / (double) total_rows * time_for_scan);
6387
double time_for_scan;
6389
if (index != table->s->primary_key) {
6391
return(Cursor::read_time(index, ranges, rows));
6396
return((double) rows);
6399
/* Assume that the read time is proportional to the scan time for all
6400
rows + at most one seek per range. */
6402
time_for_scan = scan_time();
6404
if ((total_rows = estimate_rows_upper_bound()) < rows) {
6406
return(time_for_scan);
6409
return(ranges + (double) rows / (double) total_rows * time_for_scan);
6412
6412
/*********************************************************************//**
6417
6417
ha_innobase::info(
6418
6418
/*==============*/
6419
uint flag) /*!< in: what information MySQL requests */
6419
uint flag) /*!< in: what information MySQL requests */
6421
dict_table_t* ib_table;
6422
dict_index_t* index;
6423
ha_rows rec_per_key;
6427
char path[FN_REFLEN];
6428
os_file_stat_t stat_info;
6430
/* If we are forcing recovery at a high level, we will suppress
6431
statistics calculation on tables, because that may crash the
6432
server if an index is badly corrupted. */
6434
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
6436
/* We return success (0) instead of HA_ERR_CRASHED,
6437
because we want MySQL to process this query and not
6438
stop, like it would do if it received the error code
6444
/* We do not know if MySQL can call this function before calling
6445
external_lock(). To be safe, update the session of the current table
6448
update_session(ha_session());
6450
/* In case MySQL calls this in the middle of a SELECT query, release
6451
possible adaptive hash latch to avoid deadlocks of threads */
6453
prebuilt->trx->op_info = (char*)"returning various info to MySQL";
6455
trx_search_latch_release_if_reserved(prebuilt->trx);
6457
ib_table = prebuilt->table;
6459
if (flag & HA_STATUS_TIME) {
6460
if (innobase_stats_on_metadata) {
6461
/* In sql_show we call with this flag: update
6462
then statistics so that they are up-to-date */
6464
prebuilt->trx->op_info = "updating table statistics";
6466
dict_update_statistics(ib_table);
6468
prebuilt->trx->op_info = "returning various info to MySQL";
6471
snprintf(path, sizeof(path), "%s/%s%s",
6472
drizzle_data_home, ib_table->name, ".dfe");
6474
internal::unpack_filename(path,path);
6476
/* Note that we do not know the access time of the table,
6477
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
6479
if (os_file_get_status(path,&stat_info)) {
6480
stats.create_time = (ulong) stat_info.ctime;
6484
if (flag & HA_STATUS_VARIABLE) {
6485
n_rows = ib_table->stat_n_rows;
6487
/* Because we do not protect stat_n_rows by any mutex in a
6488
delete, it is theoretically possible that the value can be
6489
smaller than zero! TODO: fix this race.
6491
The MySQL optimizer seems to assume in a left join that n_rows
6492
is an accurate estimate if it is zero. Of course, it is not,
6493
since we do not have any locks on the rows yet at this phase.
6494
Since SHOW TABLE STATUS seems to call this function with the
6495
HA_STATUS_TIME flag set, while the left join optimizer does not
6496
set that flag, we add one to a zero value if the flag is not
6497
set. That way SHOW TABLE STATUS will show the best estimate,
6498
while the optimizer never sees the table empty. */
6504
if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
6508
/* Fix bug#40386: Not flushing query cache after truncate.
6509
n_rows can not be 0 unless the table is empty, set to 1
6510
instead. The original problem of bug#29507 is actually
6511
fixed in the server code. */
6512
if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
6516
/* We need to reset the prebuilt value too, otherwise
6517
checks for values greater than the last value written
6518
to the table will fail and the autoinc counter will
6519
not be updated. This will force write_row() into
6520
attempting an update of the table's AUTOINC counter. */
6522
prebuilt->autoinc_last_value = 0;
6525
stats.records = (ha_rows)n_rows;
6527
stats.data_file_length = ((uint64_t)
6528
ib_table->stat_clustered_index_size)
6530
stats.index_file_length = ((uint64_t)
6531
ib_table->stat_sum_of_other_index_sizes)
6534
/* Since fsp_get_available_space_in_free_extents() is
6535
acquiring latches inside InnoDB, we do not call it if we
6536
are asked by MySQL to avoid locking. Another reason to
6537
avoid the call is that it uses quite a lot of CPU.
6539
We do not update delete_length if no locking is requested
6540
so the "old" value can remain. delete_length is initialized
6541
to 0 in the ha_statistics' constructor. */
6542
if (!(flag & HA_STATUS_NO_LOCK)) {
6544
/* lock the data dictionary to avoid races with
6545
ibd_file_missing and tablespace_discarded */
6546
row_mysql_lock_data_dictionary(prebuilt->trx);
6548
/* ib_table->space must be an existent tablespace */
6549
if (!ib_table->ibd_file_missing
6550
&& !ib_table->tablespace_discarded) {
6552
stats.delete_length =
6553
fsp_get_available_space_in_free_extents(
6554
ib_table->space) * 1024;
6559
session = ha_session();
6561
push_warning_printf(
6563
DRIZZLE_ERROR::WARN_LEVEL_WARN,
6565
"InnoDB: Trying to get the free "
6566
"space for table %s but its "
6567
"tablespace has been discarded or "
6568
"the .ibd file is missing. Setting "
6569
"the free space to zero.",
6572
stats.delete_length = 0;
6575
row_mysql_unlock_data_dictionary(prebuilt->trx);
6578
stats.check_time = 0;
6580
if (stats.records == 0) {
6581
stats.mean_rec_length = 0;
6583
stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
6587
if (flag & HA_STATUS_CONST) {
6588
index = dict_table_get_first_index(ib_table);
6590
if (prebuilt->clust_index_was_generated) {
6591
index = dict_table_get_next_index(index);
6594
for (i = 0; i < table->s->keys; i++) {
6595
if (index == NULL) {
6596
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
6597
"indexes inside InnoDB than "
6598
"are defined in the MySQL "
6599
".frm file. Have you mixed up "
6600
".frm files from different "
6601
"installations? See "
6603
"innodb-troubleshooting.html\n",
6608
for (j = 0; j < table->key_info[i].key_parts; j++) {
6610
if (j + 1 > index->n_uniq) {
6611
errmsg_printf(ERRMSG_LVL_ERROR,
6421
dict_table_t* ib_table;
6422
dict_index_t* index;
6423
ha_rows rec_per_key;
6427
char path[FN_REFLEN];
6428
os_file_stat_t stat_info;
6430
/* If we are forcing recovery at a high level, we will suppress
6431
statistics calculation on tables, because that may crash the
6432
server if an index is badly corrupted. */
6434
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
6436
/* We return success (0) instead of HA_ERR_CRASHED,
6437
because we want MySQL to process this query and not
6438
stop, like it would do if it received the error code
6444
/* We do not know if MySQL can call this function before calling
6445
external_lock(). To be safe, update the session of the current table
6448
update_session(ha_session());
6450
/* In case MySQL calls this in the middle of a SELECT query, release
6451
possible adaptive hash latch to avoid deadlocks of threads */
6453
prebuilt->trx->op_info = (char*)"returning various info to MySQL";
6455
trx_search_latch_release_if_reserved(prebuilt->trx);
6457
ib_table = prebuilt->table;
6459
if (flag & HA_STATUS_TIME) {
6460
if (innobase_stats_on_metadata) {
6461
/* In sql_show we call with this flag: update
6462
then statistics so that they are up-to-date */
6464
prebuilt->trx->op_info = "updating table statistics";
6466
dict_update_statistics(ib_table);
6468
prebuilt->trx->op_info = "returning various info to MySQL";
6471
snprintf(path, sizeof(path), "%s/%s%s",
6472
drizzle_data_home, ib_table->name, ".dfe");
6474
internal::unpack_filename(path,path);
6476
/* Note that we do not know the access time of the table,
6477
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
6479
if (os_file_get_status(path,&stat_info)) {
6480
stats.create_time = (ulong) stat_info.ctime;
6484
if (flag & HA_STATUS_VARIABLE) {
6485
n_rows = ib_table->stat_n_rows;
6487
/* Because we do not protect stat_n_rows by any mutex in a
6488
delete, it is theoretically possible that the value can be
6489
smaller than zero! TODO: fix this race.
6491
The MySQL optimizer seems to assume in a left join that n_rows
6492
is an accurate estimate if it is zero. Of course, it is not,
6493
since we do not have any locks on the rows yet at this phase.
6494
Since SHOW TABLE STATUS seems to call this function with the
6495
HA_STATUS_TIME flag set, while the left join optimizer does not
6496
set that flag, we add one to a zero value if the flag is not
6497
set. That way SHOW TABLE STATUS will show the best estimate,
6498
while the optimizer never sees the table empty. */
6504
if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
6508
/* Fix bug#40386: Not flushing query cache after truncate.
6509
n_rows can not be 0 unless the table is empty, set to 1
6510
instead. The original problem of bug#29507 is actually
6511
fixed in the server code. */
6512
if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
6516
/* We need to reset the prebuilt value too, otherwise
6517
checks for values greater than the last value written
6518
to the table will fail and the autoinc counter will
6519
not be updated. This will force write_row() into
6520
attempting an update of the table's AUTOINC counter. */
6522
prebuilt->autoinc_last_value = 0;
6525
stats.records = (ha_rows)n_rows;
6527
stats.data_file_length = ((uint64_t)
6528
ib_table->stat_clustered_index_size)
6530
stats.index_file_length = ((uint64_t)
6531
ib_table->stat_sum_of_other_index_sizes)
6534
/* Since fsp_get_available_space_in_free_extents() is
6535
acquiring latches inside InnoDB, we do not call it if we
6536
are asked by MySQL to avoid locking. Another reason to
6537
avoid the call is that it uses quite a lot of CPU.
6539
We do not update delete_length if no locking is requested
6540
so the "old" value can remain. delete_length is initialized
6541
to 0 in the ha_statistics' constructor. */
6542
if (!(flag & HA_STATUS_NO_LOCK)) {
6544
/* lock the data dictionary to avoid races with
6545
ibd_file_missing and tablespace_discarded */
6546
row_mysql_lock_data_dictionary(prebuilt->trx);
6548
/* ib_table->space must be an existent tablespace */
6549
if (!ib_table->ibd_file_missing
6550
&& !ib_table->tablespace_discarded) {
6552
stats.delete_length =
6553
fsp_get_available_space_in_free_extents(
6554
ib_table->space) * 1024;
6559
session = ha_session();
6561
push_warning_printf(
6563
DRIZZLE_ERROR::WARN_LEVEL_WARN,
6565
"InnoDB: Trying to get the free "
6566
"space for table %s but its "
6567
"tablespace has been discarded or "
6568
"the .ibd file is missing. Setting "
6569
"the free space to zero.",
6572
stats.delete_length = 0;
6575
row_mysql_unlock_data_dictionary(prebuilt->trx);
6578
stats.check_time = 0;
6580
if (stats.records == 0) {
6581
stats.mean_rec_length = 0;
6583
stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
6587
if (flag & HA_STATUS_CONST) {
6588
index = dict_table_get_first_index(ib_table);
6590
if (prebuilt->clust_index_was_generated) {
6591
index = dict_table_get_next_index(index);
6594
for (i = 0; i < table->s->keys; i++) {
6595
if (index == NULL) {
6596
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
6597
"indexes inside InnoDB than "
6598
"are defined in the MySQL "
6599
".frm file. Have you mixed up "
6600
".frm files from different "
6601
"installations? See "
6603
"innodb-troubleshooting.html\n",
6608
for (j = 0; j < table->key_info[i].key_parts; j++) {
6610
if (j + 1 > index->n_uniq) {
6611
errmsg_printf(ERRMSG_LVL_ERROR,
6612
6612
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
6613
6613
"statistics for %lu columns. Have you mixed up .frm files from different "
6614
6614
"installations? "
6615
6615
"See " REFMAN "innodb-troubleshooting.html\n",
6619
index->n_uniq, j + 1);
6623
if (index->stat_n_diff_key_vals[j + 1] == 0) {
6625
rec_per_key = stats.records;
6627
rec_per_key = (ha_rows)(stats.records /
6628
index->stat_n_diff_key_vals[j + 1]);
6631
/* Since MySQL seems to favor table scans
6632
too much over index searches, we pretend
6633
index selectivity is 2 times better than
6636
rec_per_key = rec_per_key / 2;
6638
if (rec_per_key == 0) {
6642
table->key_info[i].rec_per_key[j]=
6643
rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
6644
(ulong) rec_per_key;
6647
index = dict_table_get_next_index(index);
6651
if (flag & HA_STATUS_ERRKEY) {
6652
const dict_index_t* err_index;
6654
ut_a(prebuilt->trx);
6655
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6657
err_index = trx_get_error_info(prebuilt->trx);
6660
errkey = (unsigned int)
6661
row_get_mysql_key_number_for_index(err_index);
6663
errkey = (unsigned int) prebuilt->trx->error_key_num;
6667
if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
6668
stats.auto_increment_value = innobase_peek_autoinc();
6671
prebuilt->trx->op_info = (char*)"";
6619
index->n_uniq, j + 1);
6623
if (index->stat_n_diff_key_vals[j + 1] == 0) {
6625
rec_per_key = stats.records;
6627
rec_per_key = (ha_rows)(stats.records /
6628
index->stat_n_diff_key_vals[j + 1]);
6631
/* Since MySQL seems to favor table scans
6632
too much over index searches, we pretend
6633
index selectivity is 2 times better than
6636
rec_per_key = rec_per_key / 2;
6638
if (rec_per_key == 0) {
6642
table->key_info[i].rec_per_key[j]=
6643
rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
6644
(ulong) rec_per_key;
6647
index = dict_table_get_next_index(index);
6651
if (flag & HA_STATUS_ERRKEY) {
6652
const dict_index_t* err_index;
6654
ut_a(prebuilt->trx);
6655
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6657
err_index = trx_get_error_info(prebuilt->trx);
6660
errkey = (unsigned int)
6661
row_get_mysql_key_number_for_index(err_index);
6663
errkey = (unsigned int) prebuilt->trx->error_key_num;
6667
if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
6668
stats.auto_increment_value = innobase_peek_autoinc();
6671
prebuilt->trx->op_info = (char*)"";
6676
6676
/**********************************************************************//**
6677
6677
Updates index cardinalities of the table, based on 8 random dives into
6678
6678
each index tree. This does NOT calculate exact statistics on the table.
6679
@return returns always 0 (success) */
6679
@return returns always 0 (success) */
6682
6682
ha_innobase::analyze(
6683
6683
/*=================*/
6684
Session*) /*!< in: connection thread handle */
6684
Session*) /*!< in: connection thread handle */
6686
/* Simply call ::info() with all the flags */
6687
info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
6686
/* Simply call ::info() with all the flags */
6687
info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
6692
6692
/*******************************************************************//**
6693
6693
Tries to check that an InnoDB table is not corrupted. If corruption is
6694
6694
noticed, prints to stderr information about it. In case of corruption
6695
6695
may also assert a failure and crash the server.
6696
@return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
6696
@return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
6699
6699
ha_innobase::check(
6700
6700
/*===============*/
6701
Session* session) /*!< in: user thread handle */
6701
Session* session) /*!< in: user thread handle */
6705
assert(session == ha_session());
6706
ut_a(prebuilt->trx);
6707
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6708
ut_a(prebuilt->trx == session_to_trx(session));
6710
if (prebuilt->mysql_template == NULL) {
6711
/* Build the template; we will use a dummy template
6712
in index scans done in checking */
6714
build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
6717
ret = row_check_table_for_mysql(prebuilt);
6719
if (ret == DB_SUCCESS) {
6720
return(HA_ADMIN_OK);
6723
return(HA_ADMIN_CORRUPT);
6705
assert(session == ha_session());
6706
ut_a(prebuilt->trx);
6707
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6708
ut_a(prebuilt->trx == session_to_trx(session));
6710
if (prebuilt->mysql_template == NULL) {
6711
/* Build the template; we will use a dummy template
6712
in index scans done in checking */
6714
build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
6717
ret = row_check_table_for_mysql(prebuilt);
6719
if (ret == DB_SUCCESS) {
6720
return(HA_ADMIN_OK);
6723
return(HA_ADMIN_CORRUPT);
6726
6726
/*************************************************************//**
6727
6727
Adds information about free space in the InnoDB tablespace to a table comment
6728
6728
which is printed out when a user calls SHOW TABLE STATUS. Adds also info on
6730
@return table comment + InnoDB free space + info on foreign keys */
6730
@return table comment + InnoDB free space + info on foreign keys */
6733
6733
ha_innobase::update_table_comment(
6734
6734
/*==============================*/
6735
const char* comment)/*!< in: table comment defined by user */
6735
const char* comment)/*!< in: table comment defined by user */
6737
uint length = (uint) strlen(comment);
6741
/* We do not know if MySQL can call this function before calling
6742
external_lock(). To be safe, update the session of the current table
6745
if (length > 64000 - 3) {
6746
return((char*)comment); /* string too long */
6749
update_session(ha_session());
6751
prebuilt->trx->op_info = (char*)"returning table comment";
6753
/* In case MySQL calls this in the middle of a SELECT query, release
6754
possible adaptive hash latch to avoid deadlocks of threads */
6756
trx_search_latch_release_if_reserved(prebuilt->trx);
6759
/* output the data to a temporary file */
6761
mutex_enter(&srv_dict_tmpfile_mutex);
6762
rewind(srv_dict_tmpfile);
6764
fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
6765
fsp_get_available_space_in_free_extents(
6766
prebuilt->table->space));
6768
dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
6769
prebuilt->trx, prebuilt->table);
6770
flen = ftell(srv_dict_tmpfile);
6773
} else if (length + flen + 3 > 64000) {
6774
flen = 64000 - 3 - length;
6777
/* allocate buffer for the full string, and
6778
read the contents of the temporary file */
6780
str = (char*) malloc(length + flen + 3);
6783
char* pos = str + length;
6785
memcpy(str, comment, length);
6789
rewind(srv_dict_tmpfile);
6790
flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
6794
mutex_exit(&srv_dict_tmpfile_mutex);
6796
prebuilt->trx->op_info = (char*)"";
6798
return(str ? str : (char*) comment);
6737
uint length = (uint) strlen(comment);
6741
/* We do not know if MySQL can call this function before calling
6742
external_lock(). To be safe, update the session of the current table
6745
if (length > 64000 - 3) {
6746
return((char*)comment); /* string too long */
6749
update_session(ha_session());
6751
prebuilt->trx->op_info = (char*)"returning table comment";
6753
/* In case MySQL calls this in the middle of a SELECT query, release
6754
possible adaptive hash latch to avoid deadlocks of threads */
6756
trx_search_latch_release_if_reserved(prebuilt->trx);
6759
/* output the data to a temporary file */
6761
mutex_enter(&srv_dict_tmpfile_mutex);
6762
rewind(srv_dict_tmpfile);
6764
fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
6765
fsp_get_available_space_in_free_extents(
6766
prebuilt->table->space));
6768
dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
6769
prebuilt->trx, prebuilt->table);
6770
flen = ftell(srv_dict_tmpfile);
6773
} else if (length + flen + 3 > 64000) {
6774
flen = 64000 - 3 - length;
6777
/* allocate buffer for the full string, and
6778
read the contents of the temporary file */
6780
str = (char*) malloc(length + flen + 3);
6783
char* pos = str + length;
6785
memcpy(str, comment, length);
6789
rewind(srv_dict_tmpfile);
6790
flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
6794
mutex_exit(&srv_dict_tmpfile_mutex);
6796
prebuilt->trx->op_info = (char*)"";
6798
return(str ? str : (char*) comment);
6801
6801
/*******************************************************************//**
7039
7046
ha_innobase::free_foreign_key_create_info(
7040
7047
/*======================================*/
7041
char* str) /*!< in, own: create info string to free */
7048
char* str) /*!< in, own: create info string to free */
7048
7055
/*******************************************************************//**
7049
7056
Tells something additional to the Cursor about how to do things.
7050
@return 0 or error number */
7057
@return 0 or error number */
7053
7060
ha_innobase::extra(
7054
7061
/*===============*/
7055
enum ha_extra_function operation)
7056
/*!< in: HA_EXTRA_FLUSH or some other flag */
7062
enum ha_extra_function operation)
7063
/*!< in: HA_EXTRA_FLUSH or some other flag */
7058
/* Warning: since it is not sure that MySQL calls external_lock
7059
before calling this function, the trx field in prebuilt can be
7062
switch (operation) {
7063
case HA_EXTRA_FLUSH:
7064
if (prebuilt->blob_heap) {
7065
row_mysql_prebuilt_free_blob_heap(prebuilt);
7068
case HA_EXTRA_RESET_STATE:
7069
reset_template(prebuilt);
7071
case HA_EXTRA_NO_KEYREAD:
7072
prebuilt->read_just_key = 0;
7074
case HA_EXTRA_KEYREAD:
7075
prebuilt->read_just_key = 1;
7077
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
7078
prebuilt->keep_other_fields_on_keyread = 1;
7081
/* IMPORTANT: prebuilt->trx can be obsolete in
7082
this method, because it is not sure that MySQL
7083
calls external_lock before this method with the
7084
parameters below. We must not invoke update_session()
7085
either, because the calling threads may change.
7086
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7087
case HA_EXTRA_IGNORE_DUP_KEY:
7088
session_to_trx(ha_session())->duplicates |= TRX_DUP_IGNORE;
7090
case HA_EXTRA_WRITE_CAN_REPLACE:
7091
session_to_trx(ha_session())->duplicates |= TRX_DUP_REPLACE;
7093
case HA_EXTRA_WRITE_CANNOT_REPLACE:
7094
session_to_trx(ha_session())->duplicates &= ~TRX_DUP_REPLACE;
7096
case HA_EXTRA_NO_IGNORE_DUP_KEY:
7097
session_to_trx(ha_session())->duplicates &=
7098
~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7100
default:/* Do nothing */
7065
/* Warning: since it is not sure that MySQL calls external_lock
7066
before calling this function, the trx field in prebuilt can be
7069
switch (operation) {
7070
case HA_EXTRA_FLUSH:
7071
if (prebuilt->blob_heap) {
7072
row_mysql_prebuilt_free_blob_heap(prebuilt);
7075
case HA_EXTRA_RESET_STATE:
7076
reset_template(prebuilt);
7078
case HA_EXTRA_NO_KEYREAD:
7079
prebuilt->read_just_key = 0;
7081
case HA_EXTRA_KEYREAD:
7082
prebuilt->read_just_key = 1;
7084
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
7085
prebuilt->keep_other_fields_on_keyread = 1;
7088
/* IMPORTANT: prebuilt->trx can be obsolete in
7089
this method, because it is not sure that MySQL
7090
calls external_lock before this method with the
7091
parameters below. We must not invoke update_session()
7092
either, because the calling threads may change.
7093
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7094
case HA_EXTRA_IGNORE_DUP_KEY:
7095
session_to_trx(ha_session())->duplicates |= TRX_DUP_IGNORE;
7097
case HA_EXTRA_WRITE_CAN_REPLACE:
7098
session_to_trx(ha_session())->duplicates |= TRX_DUP_REPLACE;
7100
case HA_EXTRA_WRITE_CANNOT_REPLACE:
7101
session_to_trx(ha_session())->duplicates &= ~TRX_DUP_REPLACE;
7103
case HA_EXTRA_NO_IGNORE_DUP_KEY:
7104
session_to_trx(ha_session())->duplicates &=
7105
~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7107
default:/* Do nothing */
7109
7116
ha_innobase::reset()
7111
if (prebuilt->blob_heap) {
7112
row_mysql_prebuilt_free_blob_heap(prebuilt);
7115
reset_template(prebuilt);
7117
/* TODO: This should really be reset in reset_template() but for now
7118
it's safer to do it explicitly here. */
7120
/* This is a statement level counter. */
7121
prebuilt->autoinc_last_value = 0;
7118
if (prebuilt->blob_heap) {
7119
row_mysql_prebuilt_free_blob_heap(prebuilt);
7122
reset_template(prebuilt);
7124
/* TODO: This should really be reset in reset_template() but for now
7125
it's safer to do it explicitly here. */
7127
/* This is a statement level counter. */
7128
prebuilt->autoinc_last_value = 0;
7126
7133
/******************************************************************//**
7127
7134
Maps a MySQL trx isolation level code to the InnoDB isolation level code
7128
@return InnoDB isolation level */
7135
@return InnoDB isolation level */
7131
7138
innobase_map_isolation_level(
7132
7139
/*=========================*/
7133
enum_tx_isolation iso) /*!< in: MySQL isolation level code */
7140
enum_tx_isolation iso) /*!< in: MySQL isolation level code */
7136
case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
7137
case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
7138
case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
7139
case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
7140
default: ut_a(0); return(0);
7143
case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
7144
case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
7145
case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
7146
case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
7147
default: ut_a(0); return(0);
7144
7151
/******************************************************************//**
7145
7152
As MySQL will execute an external lock for every new table it uses when it
7146
7153
starts to process an SQL statement. We can use this function to store the pointer to
7147
7154
the Session in the handle.
7151
7158
ha_innobase::external_lock(
7152
7159
/*=======================*/
7153
Session* session, /*!< in: handle to the user thread */
7154
int lock_type) /*!< in: lock type */
7160
Session* session, /*!< in: handle to the user thread */
7161
int lock_type) /*!< in: lock type */
7156
update_session(session);
7163
update_session(session);
7158
7165
trx_t *trx= prebuilt->trx;
7160
prebuilt->sql_stat_start = TRUE;
7161
prebuilt->hint_need_to_fetch_extra_cols = 0;
7163
reset_template(prebuilt);
7165
if (lock_type == F_WRLCK) {
7167
/* If this is a SELECT, then it is in UPDATE TABLE ...
7168
or SELECT ... FOR UPDATE */
7169
prebuilt->select_lock_type = LOCK_X;
7170
prebuilt->stored_select_lock_type = LOCK_X;
7173
if (lock_type != F_UNLCK) {
7174
/* MySQL is setting a new table lock */
7176
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
7177
&& prebuilt->select_lock_type == LOCK_NONE
7178
&& session_test_options(session,
7179
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7181
/* To get serializable execution, we let InnoDB
7182
conceptually add 'LOCK IN SHARE MODE' to all SELECTs
7183
which otherwise would have been consistent reads. An
7184
exception is consistent reads in the AUTOCOMMIT=1 mode:
7185
we know that they are read-only transactions, and they
7186
can be serialized also if performed as consistent
7189
prebuilt->select_lock_type = LOCK_S;
7190
prebuilt->stored_select_lock_type = LOCK_S;
7193
/* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
7194
TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
7195
an InnoDB table lock if it is released immediately at the end
7196
of LOCK TABLES, and InnoDB's table locks in that case cause
7197
VERY easily deadlocks.
7199
We do not set InnoDB table locks if user has not explicitly
7200
requested a table lock. Note that session_in_lock_tables(session)
7201
can hold in some cases, e.g., at the start of a stored
7202
procedure call (SQLCOM_CALL). */
7204
if (prebuilt->select_lock_type != LOCK_NONE) {
7205
trx->mysql_n_tables_locked++;
7208
prebuilt->mysql_has_locked = TRUE;
7213
/* MySQL is releasing a table lock */
7214
prebuilt->mysql_has_locked = FALSE;
7215
trx->mysql_n_tables_locked= 0;
7167
prebuilt->sql_stat_start = TRUE;
7168
prebuilt->hint_need_to_fetch_extra_cols = 0;
7170
reset_template(prebuilt);
7172
if (lock_type == F_WRLCK) {
7174
/* If this is a SELECT, then it is in UPDATE TABLE ...
7175
or SELECT ... FOR UPDATE */
7176
prebuilt->select_lock_type = LOCK_X;
7177
prebuilt->stored_select_lock_type = LOCK_X;
7180
if (lock_type != F_UNLCK) {
7181
/* MySQL is setting a new table lock */
7183
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
7184
&& prebuilt->select_lock_type == LOCK_NONE
7185
&& session_test_options(session,
7186
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7188
/* To get serializable execution, we let InnoDB
7189
conceptually add 'LOCK IN SHARE MODE' to all SELECTs
7190
which otherwise would have been consistent reads. An
7191
exception is consistent reads in the AUTOCOMMIT=1 mode:
7192
we know that they are read-only transactions, and they
7193
can be serialized also if performed as consistent
7196
prebuilt->select_lock_type = LOCK_S;
7197
prebuilt->stored_select_lock_type = LOCK_S;
7200
/* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
7201
TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
7202
an InnoDB table lock if it is released immediately at the end
7203
of LOCK TABLES, and InnoDB's table locks in that case cause
7204
VERY easily deadlocks.
7206
We do not set InnoDB table locks if user has not explicitly
7207
requested a table lock. Note that session_in_lock_tables(session)
7208
can hold in some cases, e.g., at the start of a stored
7209
procedure call (SQLCOM_CALL). */
7211
if (prebuilt->select_lock_type != LOCK_NONE) {
7212
trx->mysql_n_tables_locked++;
7215
prebuilt->mysql_has_locked = TRUE;
7220
/* MySQL is releasing a table lock */
7221
prebuilt->mysql_has_locked = FALSE;
7222
trx->mysql_n_tables_locked= 0;
7220
7227
/************************************************************************//**
7225
7232
innodb_show_status(
7226
7233
/*===============*/
7227
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7228
Session* session,/*!< in: the MySQL query thread of the caller */
7229
stat_print_fn *stat_print)
7234
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7235
Session* session,/*!< in: the MySQL query thread of the caller */
7236
stat_print_fn *stat_print)
7232
static const char truncated_msg[] = "... truncated...\n";
7233
const long MAX_STATUS_SIZE = 64000;
7234
ulint trx_list_start = ULINT_UNDEFINED;
7235
ulint trx_list_end = ULINT_UNDEFINED;
7237
assert(engine == innodb_engine_ptr);
7239
trx = check_trx_exists(session);
7241
innobase_release_stat_resources(trx);
7243
/* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
7246
long flen, usable_len;
7249
mutex_enter(&srv_monitor_file_mutex);
7250
rewind(srv_monitor_file);
7251
srv_printf_innodb_monitor(srv_monitor_file,
7252
&trx_list_start, &trx_list_end);
7253
flen = ftell(srv_monitor_file);
7254
os_file_set_eof(srv_monitor_file);
7260
if (flen > MAX_STATUS_SIZE) {
7261
usable_len = MAX_STATUS_SIZE;
7266
/* allocate buffer for the string, and
7267
read the contents of the temporary file */
7269
if (!(str = (char*) malloc(usable_len + 1))) {
7270
mutex_exit(&srv_monitor_file_mutex);
7274
rewind(srv_monitor_file);
7275
if (flen < MAX_STATUS_SIZE) {
7276
/* Display the entire output. */
7277
flen = (long) fread(str, 1, flen, srv_monitor_file);
7278
} else if (trx_list_end < (ulint) flen
7279
&& trx_list_start < trx_list_end
7280
&& trx_list_start + (flen - trx_list_end)
7281
< MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
7282
/* Omit the beginning of the list of active transactions. */
7283
long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
7284
memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
7285
len += sizeof truncated_msg - 1;
7286
usable_len = (MAX_STATUS_SIZE - 1) - len;
7287
fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
7288
len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
7291
/* Omit the end of the output. */
7292
flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
7295
mutex_exit(&srv_monitor_file_mutex);
7297
bool result = FALSE;
7299
if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
7300
STRING_WITH_LEN(""), str, flen)) {
7239
static const char truncated_msg[] = "... truncated...\n";
7240
const long MAX_STATUS_SIZE = 64000;
7241
ulint trx_list_start = ULINT_UNDEFINED;
7242
ulint trx_list_end = ULINT_UNDEFINED;
7244
assert(engine == innodb_engine_ptr);
7246
trx = check_trx_exists(session);
7248
innobase_release_stat_resources(trx);
7250
/* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
7253
long flen, usable_len;
7256
mutex_enter(&srv_monitor_file_mutex);
7257
rewind(srv_monitor_file);
7258
srv_printf_innodb_monitor(srv_monitor_file,
7259
&trx_list_start, &trx_list_end);
7260
flen = ftell(srv_monitor_file);
7261
os_file_set_eof(srv_monitor_file);
7267
if (flen > MAX_STATUS_SIZE) {
7268
usable_len = MAX_STATUS_SIZE;
7273
/* allocate buffer for the string, and
7274
read the contents of the temporary file */
7276
if (!(str = (char*) malloc(usable_len + 1))) {
7277
mutex_exit(&srv_monitor_file_mutex);
7281
rewind(srv_monitor_file);
7282
if (flen < MAX_STATUS_SIZE) {
7283
/* Display the entire output. */
7284
flen = (long) fread(str, 1, flen, srv_monitor_file);
7285
} else if (trx_list_end < (ulint) flen
7286
&& trx_list_start < trx_list_end
7287
&& trx_list_start + (flen - trx_list_end)
7288
< MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
7289
/* Omit the beginning of the list of active transactions. */
7290
long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
7291
memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
7292
len += sizeof truncated_msg - 1;
7293
usable_len = (MAX_STATUS_SIZE - 1) - len;
7294
fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
7295
len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
7298
/* Omit the end of the output. */
7299
flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
7302
mutex_exit(&srv_monitor_file_mutex);
7304
bool result = FALSE;
7306
if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
7307
STRING_WITH_LEN(""), str, flen)) {
7308
7315
/************************************************************************//**
7312
7319
innodb_mutex_show_status(
7313
7320
/*=====================*/
7314
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7315
Session* session, /*!< in: the MySQL query thread of the
7317
stat_print_fn* stat_print)
7321
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7322
Session* session, /*!< in: the MySQL query thread of the
7324
stat_print_fn* stat_print)
7319
char buf1[IO_SIZE], buf2[IO_SIZE];
7326
char buf1[IO_SIZE], buf2[IO_SIZE];
7322
7329
#ifdef UNIV_DEBUG
7323
ulint rw_lock_count= 0;
7324
ulint rw_lock_count_spin_loop= 0;
7325
ulint rw_lock_count_spin_rounds= 0;
7326
ulint rw_lock_count_os_wait= 0;
7327
ulint rw_lock_count_os_yield= 0;
7328
uint64_t rw_lock_wait_time= 0;
7330
ulint rw_lock_count= 0;
7331
ulint rw_lock_count_spin_loop= 0;
7332
ulint rw_lock_count_spin_rounds= 0;
7333
ulint rw_lock_count_os_wait= 0;
7334
ulint rw_lock_count_os_yield= 0;
7335
uint64_t rw_lock_wait_time= 0;
7329
7336
#endif /* UNIV_DEBUG */
7330
uint engine_name_len= strlen(innobase_engine_name), buf1len, buf2len;
7331
assert(engine == innodb_engine_ptr);
7333
mutex_enter(&mutex_list_mutex);
7335
mutex = UT_LIST_GET_FIRST(mutex_list);
7337
while (mutex != NULL) {
7338
if (mutex->count_os_wait == 0
7339
|| buf_pool_is_block_mutex(mutex)) {
7337
uint engine_name_len= strlen(innobase_engine_name), buf1len, buf2len;
7338
assert(engine == innodb_engine_ptr);
7340
mutex_enter(&mutex_list_mutex);
7342
mutex = UT_LIST_GET_FIRST(mutex_list);
7344
while (mutex != NULL) {
7345
if (mutex->count_os_wait == 0
7346
|| buf_pool_is_block_mutex(mutex)) {
7342
7349
#ifdef UNIV_DEBUG
7343
if (mutex->mutex_type != 1) {
7344
if (mutex->count_using > 0) {
7345
buf1len= my_snprintf(buf1, sizeof(buf1),
7347
mutex->cmutex_name, mutex->cfile_name);
7348
buf2len= my_snprintf(buf2, sizeof(buf2),
7349
"count=%lu, spin_waits=%lu,"
7350
" spin_rounds=%lu, "
7351
"os_waits=%lu, os_yields=%lu,"
7352
" os_wait_times=%lu",
7354
mutex->count_spin_loop,
7355
mutex->count_spin_rounds,
7356
mutex->count_os_wait,
7357
mutex->count_os_yield,
7358
(ulong) (mutex->lspent_time/1000));
7350
if (mutex->mutex_type != 1) {
7351
if (mutex->count_using > 0) {
7352
buf1len= my_snprintf(buf1, sizeof(buf1),
7354
mutex->cmutex_name, mutex->cfile_name);
7355
buf2len= my_snprintf(buf2, sizeof(buf2),
7356
"count=%lu, spin_waits=%lu,"
7357
" spin_rounds=%lu, "
7358
"os_waits=%lu, os_yields=%lu,"
7359
" os_wait_times=%lu",
7361
mutex->count_spin_loop,
7362
mutex->count_spin_rounds,
7363
mutex->count_os_wait,
7364
mutex->count_os_yield,
7365
(ulong) (mutex->lspent_time/1000));
7360
if (stat_print(session, innobase_engine_name,
7361
engine_name_len, buf1, buf1len,
7363
mutex_exit(&mutex_list_mutex);
7369
rw_lock_count += mutex->count_using;
7370
rw_lock_count_spin_loop += mutex->count_spin_loop;
7371
rw_lock_count_spin_rounds += mutex->count_spin_rounds;
7372
rw_lock_count_os_wait += mutex->count_os_wait;
7373
rw_lock_count_os_yield += mutex->count_os_yield;
7374
rw_lock_wait_time += mutex->lspent_time;
7367
if (stat_print(session, innobase_engine_name,
7368
engine_name_len, buf1, buf1len,
7370
mutex_exit(&mutex_list_mutex);
7376
rw_lock_count += mutex->count_using;
7377
rw_lock_count_spin_loop += mutex->count_spin_loop;
7378
rw_lock_count_spin_rounds += mutex->count_spin_rounds;
7379
rw_lock_count_os_wait += mutex->count_os_wait;
7380
rw_lock_count_os_yield += mutex->count_os_yield;
7381
rw_lock_wait_time += mutex->lspent_time;
7376
7383
#else /* UNIV_DEBUG */
7377
buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
7378
mutex->cfile_name, (ulong) mutex->cline);
7379
buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
7380
mutex->count_os_wait);
7384
buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
7385
mutex->cfile_name, (ulong) mutex->cline);
7386
buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
7387
mutex->count_os_wait);
7382
if (stat_print(session, innobase_engine_name,
7383
engine_name_len, buf1, buf1len,
7385
mutex_exit(&mutex_list_mutex);
7389
if (stat_print(session, innobase_engine_name,
7390
engine_name_len, buf1, buf1len,
7392
mutex_exit(&mutex_list_mutex);
7388
7395
#endif /* UNIV_DEBUG */
7391
mutex = UT_LIST_GET_NEXT(list, mutex);
7394
mutex_exit(&mutex_list_mutex);
7396
mutex_enter(&rw_lock_list_mutex);
7398
lock = UT_LIST_GET_FIRST(rw_lock_list);
7400
while (lock != NULL) {
7401
if (lock->count_os_wait
7398
mutex = UT_LIST_GET_NEXT(list, mutex);
7401
mutex_exit(&mutex_list_mutex);
7403
mutex_enter(&rw_lock_list_mutex);
7405
lock = UT_LIST_GET_FIRST(rw_lock_list);
7407
while (lock != NULL) {
7408
if (lock->count_os_wait
7402
7409
&& !buf_pool_is_block_lock(lock)) {
7403
buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
7410
buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
7404
7411
lock->cfile_name, (unsigned long) lock->cline);
7405
buf2len= snprintf(buf2, sizeof(buf2),
7412
buf2len= snprintf(buf2, sizeof(buf2),
7406
7413
"os_waits=%lu", lock->count_os_wait);
7408
if (stat_print(session, innobase_engine_name,
7409
engine_name_len, buf1, buf1len,
7411
mutex_exit(&rw_lock_list_mutex);
7415
lock = UT_LIST_GET_NEXT(list, lock);
7415
if (stat_print(session, innobase_engine_name,
7416
engine_name_len, buf1, buf1len,
7418
mutex_exit(&rw_lock_list_mutex);
7422
lock = UT_LIST_GET_NEXT(list, lock);
7418
mutex_exit(&rw_lock_list_mutex);
7425
mutex_exit(&rw_lock_list_mutex);
7420
7427
#ifdef UNIV_DEBUG
7421
buf2len= my_snprintf(buf2, sizeof(buf2),
7422
"count=%lu, spin_waits=%lu, spin_rounds=%lu, "
7423
"os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
7424
rw_lock_count, rw_lock_count_spin_loop,
7425
rw_lock_count_spin_rounds,
7426
rw_lock_count_os_wait, rw_lock_count_os_yield,
7427
(ulong) (rw_lock_wait_time/1000));
7428
buf2len= my_snprintf(buf2, sizeof(buf2),
7429
"count=%lu, spin_waits=%lu, spin_rounds=%lu, "
7430
"os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
7431
rw_lock_count, rw_lock_count_spin_loop,
7432
rw_lock_count_spin_rounds,
7433
rw_lock_count_os_wait, rw_lock_count_os_yield,
7434
(ulong) (rw_lock_wait_time/1000));
7429
if (stat_print(session, innobase_engine_name, engine_name_len,
7430
STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
7436
if (stat_print(session, innobase_engine_name, engine_name_len,
7437
STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
7433
7440
#endif /* UNIV_DEBUG */
7438
7445
bool InnobaseEngine::show_status(Session* session,
7439
7446
stat_print_fn* stat_print,
7440
7447
enum ha_stat_type stat_type)
7442
assert(this == innodb_engine_ptr);
7449
assert(this == innodb_engine_ptr);
7444
switch (stat_type) {
7445
case HA_ENGINE_STATUS:
7446
return innodb_show_status(this, session, stat_print);
7447
case HA_ENGINE_MUTEX:
7448
return innodb_mutex_show_status(this, session, stat_print);
7451
switch (stat_type) {
7452
case HA_ENGINE_STATUS:
7453
return innodb_show_status(this, session, stat_print);
7454
case HA_ENGINE_MUTEX:
7455
return innodb_mutex_show_status(this, session, stat_print);
7454
7461
/************************************************************************//**
7532
7539
SELECT the read lock is released early on the 'const' tables where we only
7533
7540
fetch one row. MySQL does not call this when it releases all locks at the
7534
7541
end of an SQL statement.
7535
@return pointer to the next element in the 'to' array */
7542
@return pointer to the next element in the 'to' array */
7537
7544
THR_LOCK_DATA**
7538
7545
ha_innobase::store_lock(
7539
7546
/*====================*/
7540
Session* session, /*!< in: user thread handle */
7541
THR_LOCK_DATA** to, /*!< in: pointer to an array
7542
of pointers to lock structs;
7543
pointer to the 'lock' field
7544
of current handle is stored
7545
next to this array */
7546
enum thr_lock_type lock_type) /*!< in: lock type to store in
7547
'lock'; this may also be
7547
Session* session, /*!< in: user thread handle */
7548
THR_LOCK_DATA** to, /*!< in: pointer to an array
7549
of pointers to lock structs;
7550
pointer to the 'lock' field
7551
of current handle is stored
7552
next to this array */
7553
enum thr_lock_type lock_type) /*!< in: lock type to store in
7554
'lock'; this may also be
7552
/* Note that trx in this function is NOT necessarily prebuilt->trx
7553
because we call update_session() later, in ::external_lock()! Failure to
7554
understand this caused a serious memory corruption bug in 5.1.11. */
7556
trx = check_trx_exists(session);
7558
assert(EQ_CURRENT_SESSION(session));
7559
const uint32_t sql_command = session_sql_command(session);
7561
if (sql_command == SQLCOM_DROP_TABLE) {
7563
/* MySQL calls this function in DROP Table though this table
7564
handle may belong to another session that is running a query.
7565
Let us in that case skip any changes to the prebuilt struct. */
7567
} else if (lock_type == TL_READ_WITH_SHARED_LOCKS
7568
|| lock_type == TL_READ_NO_INSERT
7569
|| (lock_type != TL_IGNORE
7570
&& sql_command != SQLCOM_SELECT)) {
7572
/* The OR cases above are in this order:
7573
1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
7574
are processing a stored procedure or function, or
7575
2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
7576
3) this is a SELECT ... IN SHARE MODE, or
7577
4) we are doing a complex SQL statement like
7578
INSERT INTO ... SELECT ... and the logical logging (MySQL
7579
binlog) requires the use of a locking read, or
7580
MySQL is doing LOCK TABLES ... READ.
7581
5) we let InnoDB do locking reads for all SQL statements that
7582
are not simple SELECTs; note that select_lock_type in this
7583
case may get strengthened in ::external_lock() to LOCK_X.
7584
Note that we MUST use a locking read in all data modifying
7585
SQL statements, because otherwise the execution would not be
7586
serializable, and also the results from the update could be
7587
unexpected if an obsolete consistent read view would be
7590
ulint isolation_level;
7592
isolation_level = trx->isolation_level;
7594
if ((srv_locks_unsafe_for_binlog
7595
|| isolation_level == TRX_ISO_READ_COMMITTED)
7596
&& isolation_level != TRX_ISO_SERIALIZABLE
7597
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
7598
&& (sql_command == SQLCOM_INSERT_SELECT
7599
|| sql_command == SQLCOM_UPDATE
7600
|| sql_command == SQLCOM_CREATE_TABLE)) {
7602
/* If we either have innobase_locks_unsafe_for_binlog
7603
option set or this session is using READ COMMITTED
7604
isolation level and isolation level of the transaction
7605
is not set to serializable and MySQL is doing
7606
INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
7607
CREATE ... SELECT... without FOR UPDATE or
7608
IN SHARE MODE in select, then we use consistent
7611
prebuilt->select_lock_type = LOCK_NONE;
7612
prebuilt->stored_select_lock_type = LOCK_NONE;
7613
} else if (sql_command == SQLCOM_CHECKSUM) {
7614
/* Use consistent read for checksum table */
7616
prebuilt->select_lock_type = LOCK_NONE;
7617
prebuilt->stored_select_lock_type = LOCK_NONE;
7619
prebuilt->select_lock_type = LOCK_S;
7620
prebuilt->stored_select_lock_type = LOCK_S;
7623
} else if (lock_type != TL_IGNORE) {
7625
/* We set possible LOCK_X value in external_lock, not yet
7626
here even if this would be SELECT ... FOR UPDATE */
7628
prebuilt->select_lock_type = LOCK_NONE;
7629
prebuilt->stored_select_lock_type = LOCK_NONE;
7632
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
7634
/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
7635
TABLESPACE or TRUNCATE TABLE then allow multiple
7636
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
7637
< TL_WRITE_CONCURRENT_INSERT.
7640
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
7641
&& lock_type <= TL_WRITE)
7642
&& !session_tablespace_op(session)
7643
&& sql_command != SQLCOM_TRUNCATE
7644
&& sql_command != SQLCOM_CREATE_TABLE) {
7646
lock_type = TL_WRITE_ALLOW_WRITE;
7649
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
7650
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
7651
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
7652
to t2. Convert the lock to a normal read lock to allow
7653
concurrent inserts to t2.
7656
if (lock_type == TL_READ_NO_INSERT) {
7658
lock_type = TL_READ;
7661
lock.type = lock_type;
7559
/* Note that trx in this function is NOT necessarily prebuilt->trx
7560
because we call update_session() later, in ::external_lock()! Failure to
7561
understand this caused a serious memory corruption bug in 5.1.11. */
7563
trx = check_trx_exists(session);
7565
assert(EQ_CURRENT_SESSION(session));
7566
const uint32_t sql_command = session_sql_command(session);
7568
if (sql_command == SQLCOM_DROP_TABLE) {
7570
/* MySQL calls this function in DROP Table though this table
7571
handle may belong to another session that is running a query.
7572
Let us in that case skip any changes to the prebuilt struct. */
7574
} else if (lock_type == TL_READ_WITH_SHARED_LOCKS
7575
|| lock_type == TL_READ_NO_INSERT
7576
|| (lock_type != TL_IGNORE
7577
&& sql_command != SQLCOM_SELECT)) {
7579
/* The OR cases above are in this order:
7580
1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
7581
are processing a stored procedure or function, or
7582
2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
7583
3) this is a SELECT ... IN SHARE MODE, or
7584
4) we are doing a complex SQL statement like
7585
INSERT INTO ... SELECT ... and the logical logging (MySQL
7586
binlog) requires the use of a locking read, or
7587
MySQL is doing LOCK TABLES ... READ.
7588
5) we let InnoDB do locking reads for all SQL statements that
7589
are not simple SELECTs; note that select_lock_type in this
7590
case may get strengthened in ::external_lock() to LOCK_X.
7591
Note that we MUST use a locking read in all data modifying
7592
SQL statements, because otherwise the execution would not be
7593
serializable, and also the results from the update could be
7594
unexpected if an obsolete consistent read view would be
7597
ulint isolation_level;
7599
isolation_level = trx->isolation_level;
7601
if ((srv_locks_unsafe_for_binlog
7602
|| isolation_level == TRX_ISO_READ_COMMITTED)
7603
&& isolation_level != TRX_ISO_SERIALIZABLE
7604
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
7605
&& (sql_command == SQLCOM_INSERT_SELECT
7606
|| sql_command == SQLCOM_UPDATE
7607
|| sql_command == SQLCOM_CREATE_TABLE)) {
7609
/* If we either have innobase_locks_unsafe_for_binlog
7610
option set or this session is using READ COMMITTED
7611
isolation level and isolation level of the transaction
7612
is not set to serializable and MySQL is doing
7613
INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
7614
CREATE ... SELECT... without FOR UPDATE or
7615
IN SHARE MODE in select, then we use consistent
7618
prebuilt->select_lock_type = LOCK_NONE;
7619
prebuilt->stored_select_lock_type = LOCK_NONE;
7620
} else if (sql_command == SQLCOM_CHECKSUM) {
7621
/* Use consistent read for checksum table */
7623
prebuilt->select_lock_type = LOCK_NONE;
7624
prebuilt->stored_select_lock_type = LOCK_NONE;
7626
prebuilt->select_lock_type = LOCK_S;
7627
prebuilt->stored_select_lock_type = LOCK_S;
7630
} else if (lock_type != TL_IGNORE) {
7632
/* We set possible LOCK_X value in external_lock, not yet
7633
here even if this would be SELECT ... FOR UPDATE */
7635
prebuilt->select_lock_type = LOCK_NONE;
7636
prebuilt->stored_select_lock_type = LOCK_NONE;
7639
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
7641
/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
7642
TABLESPACE or TRUNCATE TABLE then allow multiple
7643
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
7644
< TL_WRITE_CONCURRENT_INSERT.
7647
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
7648
&& lock_type <= TL_WRITE)
7649
&& !session_tablespace_op(session)
7650
&& sql_command != SQLCOM_TRUNCATE
7651
&& sql_command != SQLCOM_CREATE_TABLE) {
7653
lock_type = TL_WRITE_ALLOW_WRITE;
7656
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
7657
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
7658
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
7659
to t2. Convert the lock to a normal read lock to allow
7660
concurrent inserts to t2.
7663
if (lock_type == TL_READ_NO_INSERT) {
7665
lock_type = TL_READ;
7668
lock.type = lock_type;
7669
7676
/*********************************************************************//**
7670
7677
Read the next autoinc value. Acquire the relevant locks before reading
7671
7678
the AUTOINC value. If SUCCESS then the table AUTOINC mutex will be locked
7672
7679
on return and all relevant locks acquired.
7673
@return DB_SUCCESS or error code */
7680
@return DB_SUCCESS or error code */
7676
7683
ha_innobase::innobase_get_autoinc(
7677
7684
/*==============================*/
7678
uint64_t* value) /*!< out: autoinc value */
7685
uint64_t* value) /*!< out: autoinc value */
7682
prebuilt->autoinc_error = innobase_lock_autoinc();
7684
if (prebuilt->autoinc_error == DB_SUCCESS) {
7686
/* Determine the first value of the interval */
7687
*value = dict_table_autoinc_read(prebuilt->table);
7689
/* It should have been initialized during open. */
7693
return(prebuilt->autoinc_error);
7689
prebuilt->autoinc_error = innobase_lock_autoinc();
7691
if (prebuilt->autoinc_error == DB_SUCCESS) {
7693
/* Determine the first value of the interval */
7694
*value = dict_table_autoinc_read(prebuilt->table);
7696
/* It should have been initialized during open. */
7700
return(prebuilt->autoinc_error);
7696
7703
/*******************************************************************//**
7697
7704
This function reads the global auto-inc counter. It doesn't use the
7698
7705
AUTOINC lock even if the lock mode is set to TRADITIONAL.
7699
@return the autoinc value */
7706
@return the autoinc value */
7702
7709
ha_innobase::innobase_peek_autoinc(void)
7703
7710
/*====================================*/
7706
dict_table_t* innodb_table;
7708
ut_a(prebuilt != NULL);
7709
ut_a(prebuilt->table != NULL);
7711
innodb_table = prebuilt->table;
7713
dict_table_autoinc_lock(innodb_table);
7715
auto_inc = dict_table_autoinc_read(innodb_table);
7719
dict_table_autoinc_unlock(innodb_table);
7713
dict_table_t* innodb_table;
7715
ut_a(prebuilt != NULL);
7716
ut_a(prebuilt->table != NULL);
7718
innodb_table = prebuilt->table;
7720
dict_table_autoinc_lock(innodb_table);
7722
auto_inc = dict_table_autoinc_read(innodb_table);
7726
dict_table_autoinc_unlock(innodb_table);
7724
7731
/*********************************************************************//**
7733
7740
ha_innobase::get_auto_increment(
7734
7741
/*============================*/
7735
uint64_t offset, /*!< in: table autoinc offset */
7736
uint64_t increment, /*!< in: table autoinc increment */
7737
uint64_t nb_desired_values, /*!< in: number of values reqd */
7738
uint64_t *first_value, /*!< out: the autoinc value */
7739
uint64_t *nb_reserved_values) /*!< out: count of reserved values */
7742
uint64_t offset, /*!< in: table autoinc offset */
7743
uint64_t increment, /*!< in: table autoinc increment */
7744
uint64_t nb_desired_values, /*!< in: number of values reqd */
7745
uint64_t *first_value, /*!< out: the autoinc value */
7746
uint64_t *nb_reserved_values) /*!< out: count of reserved values */
7743
uint64_t autoinc = 0;
7745
/* Prepare prebuilt->trx in the table handle */
7746
update_session(ha_session());
7748
error = innobase_get_autoinc(&autoinc);
7750
if (error != DB_SUCCESS) {
7751
*first_value = (~(uint64_t) 0);
7755
/* This is a hack, since nb_desired_values seems to be accurate only
7756
for the first call to get_auto_increment() for multi-row INSERT and
7757
meaningless for other statements e.g, LOAD etc. Subsequent calls to
7758
this method for the same statement results in different values which
7759
don't make sense. Therefore we store the value the first time we are
7760
called and count down from that as rows are written (see write_row()).
7763
trx = prebuilt->trx;
7765
/* Note: We can't rely on *first_value since some MySQL engines,
7766
in particular the partition engine, don't initialize it to 0 when
7767
invoking this method. So we are not sure if it's guaranteed to
7770
/* Called for the first time ? */
7771
if (trx->n_autoinc_rows == 0) {
7773
trx->n_autoinc_rows = (ulint) nb_desired_values;
7775
/* It's possible for nb_desired_values to be 0:
7776
e.g., INSERT INTO T1(C) SELECT C FROM T2; */
7777
if (nb_desired_values == 0) {
7779
trx->n_autoinc_rows = 1;
7782
set_if_bigger(*first_value, autoinc);
7783
/* Not in the middle of a mult-row INSERT. */
7784
} else if (prebuilt->autoinc_last_value == 0) {
7785
set_if_bigger(*first_value, autoinc);
7788
*nb_reserved_values = trx->n_autoinc_rows;
7790
/* With old style AUTOINC locking we only update the table's
7791
AUTOINC counter after attempting to insert the row. */
7792
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
7794
uint64_t next_value;
7795
uint64_t col_max_value;
7797
/* We need the upper limit of the col type to check for
7798
whether we update the table autoinc counter or not. */
7799
col_max_value = innobase_get_int_col_max_value(
7800
table->next_number_field);
7802
need = *nb_reserved_values * increment;
7804
/* Compute the last value in the interval */
7805
next_value = innobase_next_autoinc(
7806
*first_value, need, offset, col_max_value);
7808
prebuilt->autoinc_last_value = next_value;
7810
if (prebuilt->autoinc_last_value < *first_value) {
7811
*first_value = (~(unsigned long long) 0);
7813
/* Update the table autoinc variable */
7814
dict_table_autoinc_update_if_greater(
7815
prebuilt->table, prebuilt->autoinc_last_value);
7818
/* This will force write_row() into attempting an update
7819
of the table's AUTOINC counter. */
7820
prebuilt->autoinc_last_value = 0;
7823
/* The increment to be used to increase the AUTOINC value, we use
7824
this in write_row() and update_row() to increase the autoinc counter
7825
for columns that are filled by the user. We need the offset and
7827
prebuilt->autoinc_offset = offset;
7828
prebuilt->autoinc_increment = increment;
7830
dict_table_autoinc_unlock(prebuilt->table);
7750
uint64_t autoinc = 0;
7752
/* Prepare prebuilt->trx in the table handle */
7753
update_session(ha_session());
7755
error = innobase_get_autoinc(&autoinc);
7757
if (error != DB_SUCCESS) {
7758
*first_value = (~(uint64_t) 0);
7762
/* This is a hack, since nb_desired_values seems to be accurate only
7763
for the first call to get_auto_increment() for multi-row INSERT and
7764
meaningless for other statements e.g, LOAD etc. Subsequent calls to
7765
this method for the same statement results in different values which
7766
don't make sense. Therefore we store the value the first time we are
7767
called and count down from that as rows are written (see write_row()).
7770
trx = prebuilt->trx;
7772
/* Note: We can't rely on *first_value since some MySQL engines,
7773
in particular the partition engine, don't initialize it to 0 when
7774
invoking this method. So we are not sure if it's guaranteed to
7777
/* Called for the first time ? */
7778
if (trx->n_autoinc_rows == 0) {
7780
trx->n_autoinc_rows = (ulint) nb_desired_values;
7782
/* It's possible for nb_desired_values to be 0:
7783
e.g., INSERT INTO T1(C) SELECT C FROM T2; */
7784
if (nb_desired_values == 0) {
7786
trx->n_autoinc_rows = 1;
7789
set_if_bigger(*first_value, autoinc);
7790
/* Not in the middle of a mult-row INSERT. */
7791
} else if (prebuilt->autoinc_last_value == 0) {
7792
set_if_bigger(*first_value, autoinc);
7795
*nb_reserved_values = trx->n_autoinc_rows;
7797
/* With old style AUTOINC locking we only update the table's
7798
AUTOINC counter after attempting to insert the row. */
7799
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
7801
uint64_t next_value;
7802
uint64_t col_max_value;
7804
/* We need the upper limit of the col type to check for
7805
whether we update the table autoinc counter or not. */
7806
col_max_value = innobase_get_int_col_max_value(
7807
table->next_number_field);
7809
need = *nb_reserved_values * increment;
7811
/* Compute the last value in the interval */
7812
next_value = innobase_next_autoinc(
7813
*first_value, need, offset, col_max_value);
7815
prebuilt->autoinc_last_value = next_value;
7817
if (prebuilt->autoinc_last_value < *first_value) {
7818
*first_value = (~(unsigned long long) 0);
7820
/* Update the table autoinc variable */
7821
dict_table_autoinc_update_if_greater(
7822
prebuilt->table, prebuilt->autoinc_last_value);
7825
/* This will force write_row() into attempting an update
7826
of the table's AUTOINC counter. */
7827
prebuilt->autoinc_last_value = 0;
7830
/* The increment to be used to increase the AUTOINC value, we use
7831
this in write_row() and update_row() to increase the autoinc counter
7832
for columns that are filled by the user. We need the offset and
7834
prebuilt->autoinc_offset = offset;
7835
prebuilt->autoinc_increment = increment;
7837
dict_table_autoinc_unlock(prebuilt->table);
7833
7840
/*******************************************************************//**
7952
7959
characters for prefix indexes using a multibyte character set. The function
7953
7960
finds charset information and returns length of prefix_len characters in the
7954
7961
index field in bytes.
7955
@return number of bytes occupied by the first n characters */
7962
@return number of bytes occupied by the first n characters */
7956
7963
extern "C" UNIV_INTERN
7958
7965
innobase_get_at_most_n_mbchars(
7959
7966
/*===========================*/
7960
ulint charset_id, /*!< in: character set id */
7961
ulint prefix_len, /*!< in: prefix length in bytes of the index
7962
(this has to be divided by mbmaxlen to get the
7963
number of CHARACTERS n in the prefix) */
7964
ulint data_len, /*!< in: length of the string in bytes */
7965
const char* str); /*!< in: character string */
7967
ulint charset_id, /*!< in: character set id */
7968
ulint prefix_len, /*!< in: prefix length in bytes of the index
7969
(this has to be divided by mbmaxlen to get the
7970
number of CHARACTERS n in the prefix) */
7971
ulint data_len, /*!< in: length of the string in bytes */
7972
const char* str); /*!< in: character string */
7968
7975
innobase_get_at_most_n_mbchars(
7969
7976
/*===========================*/
7970
ulint charset_id, /*!< in: character set id */
7971
ulint prefix_len, /*!< in: prefix length in bytes of the index
7972
(this has to be divided by mbmaxlen to get the
7973
number of CHARACTERS n in the prefix) */
7974
ulint data_len, /*!< in: length of the string in bytes */
7975
const char* str) /*!< in: character string */
7977
ulint charset_id, /*!< in: character set id */
7978
ulint prefix_len, /*!< in: prefix length in bytes of the index
7979
(this has to be divided by mbmaxlen to get the
7980
number of CHARACTERS n in the prefix) */
7981
ulint data_len, /*!< in: length of the string in bytes */
7982
const char* str) /*!< in: character string */
7977
ulint char_length; /*!< character length in bytes */
7978
ulint n_chars; /*!< number of characters in prefix */
7979
const CHARSET_INFO* charset; /*!< charset used in the field */
7981
charset = get_charset((uint) charset_id);
7984
ut_ad(charset->mbmaxlen);
7986
/* Calculate how many characters at most the prefix index contains */
7988
n_chars = prefix_len / charset->mbmaxlen;
7990
/* If the charset is multi-byte, then we must find the length of the
7991
first at most n chars in the string. If the string contains less
7992
characters than n, then we return the length to the end of the last
7995
if (charset->mbmaxlen > 1) {
7996
/* my_charpos() returns the byte length of the first n_chars
7997
characters, or a value bigger than the length of str, if
7998
there were not enough full characters in str.
8000
Why does the code below work:
8001
Suppose that we are looking for n UTF-8 characters.
8003
1) If the string is long enough, then the prefix contains at
8004
least n complete UTF-8 characters + maybe some extra
8005
characters + an incomplete UTF-8 character. No problem in
8006
this case. The function returns the pointer to the
8007
end of the nth character.
8009
2) If the string is not long enough, then the string contains
8010
the complete value of a column, that is, only complete UTF-8
8011
characters, and we can store in the column prefix index the
8014
char_length = my_charpos(charset, str,
8015
str + data_len, (int) n_chars);
8016
if (char_length > data_len) {
8017
char_length = data_len;
8020
if (data_len < prefix_len) {
8021
char_length = data_len;
8023
char_length = prefix_len;
8027
return(char_length);
7984
ulint char_length; /*!< character length in bytes */
7985
ulint n_chars; /*!< number of characters in prefix */
7986
const CHARSET_INFO* charset; /*!< charset used in the field */
7988
charset = get_charset((uint) charset_id);
7991
ut_ad(charset->mbmaxlen);
7993
/* Calculate how many characters at most the prefix index contains */
7995
n_chars = prefix_len / charset->mbmaxlen;
7997
/* If the charset is multi-byte, then we must find the length of the
7998
first at most n chars in the string. If the string contains less
7999
characters than n, then we return the length to the end of the last
8002
if (charset->mbmaxlen > 1) {
8003
/* my_charpos() returns the byte length of the first n_chars
8004
characters, or a value bigger than the length of str, if
8005
there were not enough full characters in str.
8007
Why does the code below work:
8008
Suppose that we are looking for n UTF-8 characters.
8010
1) If the string is long enough, then the prefix contains at
8011
least n complete UTF-8 characters + maybe some extra
8012
characters + an incomplete UTF-8 character. No problem in
8013
this case. The function returns the pointer to the
8014
end of the nth character.
8016
2) If the string is not long enough, then the string contains
8017
the complete value of a column, that is, only complete UTF-8
8018
characters, and we can store in the column prefix index the
8021
char_length = my_charpos(charset, str,
8022
str + data_len, (int) n_chars);
8023
if (char_length > data_len) {
8024
char_length = data_len;
8027
if (data_len < prefix_len) {
8028
char_length = data_len;
8030
char_length = prefix_len;
8034
return(char_length);
8030
8037
* We will also use this function to communicate
8083
8090
/*******************************************************************//**
8084
8091
This function is used to prepare an X/Open XA distributed transaction.
8085
@return 0 or error number */
8092
@return 0 or error number */
8087
8094
InnobaseEngine::doXaPrepare(
8088
8095
/*================*/
8089
Session* session,/*!< in: handle to the MySQL thread of
8090
the user whose XA transaction should
8092
bool all) /*!< in: TRUE - commit transaction
8093
FALSE - the current SQL statement
8096
Session* session,/*!< in: handle to the MySQL thread of
8097
the user whose XA transaction should
8099
bool all) /*!< in: TRUE - commit transaction
8100
FALSE - the current SQL statement
8097
trx_t* trx = check_trx_exists(session);
8099
assert(this == innodb_engine_ptr);
8101
/* we use support_xa value as it was seen at transaction start
8102
time, not the current session variable value. Any possible changes
8103
to the session variable take effect only in the next transaction */
8104
if (!trx->support_xa) {
8109
session_get_xid(session, reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
8111
/* Release a possible FIFO ticket and search latch. Since we will
8112
reserve the kernel mutex, we have to release the search system latch
8113
first to obey the latching order. */
8115
innobase_release_stat_resources(trx);
8118
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
8120
/* We were instructed to prepare the whole transaction, or
8121
this is an SQL statement end and autocommit is on */
8123
ut_ad(trx->conc_state != TRX_NOT_STARTED);
8125
error = (int) trx_prepare_for_mysql(trx);
8127
/* We just mark the SQL statement ended and do not do a
8128
transaction prepare */
8130
/* If we had reserved the auto-inc lock for some
8131
table in this SQL statement we release it now */
8133
row_unlock_table_autoinc_for_mysql(trx);
8135
/* Store the current undo_no of the transaction so that we
8136
know where to roll back if we have to roll back the next
8139
trx_mark_sql_stat_end(trx);
8142
/* Tell the InnoDB server that there might be work for utility
8145
srv_active_wake_master_thread();
8104
trx_t* trx = check_trx_exists(session);
8106
assert(this == innodb_engine_ptr);
8108
/* we use support_xa value as it was seen at transaction start
8109
time, not the current session variable value. Any possible changes
8110
to the session variable take effect only in the next transaction */
8111
if (!trx->support_xa) {
8116
session_get_xid(session, reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
8118
/* Release a possible FIFO ticket and search latch. Since we will
8119
reserve the kernel mutex, we have to release the search system latch
8120
first to obey the latching order. */
8122
innobase_release_stat_resources(trx);
8125
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
8127
/* We were instructed to prepare the whole transaction, or
8128
this is an SQL statement end and autocommit is on */
8130
ut_ad(trx->conc_state != TRX_NOT_STARTED);
8132
error = (int) trx_prepare_for_mysql(trx);
8134
/* We just mark the SQL statement ended and do not do a
8135
transaction prepare */
8137
/* If we had reserved the auto-inc lock for some
8138
table in this SQL statement we release it now */
8140
row_unlock_table_autoinc_for_mysql(trx);
8142
/* Store the current undo_no of the transaction so that we
8143
know where to roll back if we have to roll back the next
8146
trx_mark_sql_stat_end(trx);
8149
/* Tell the InnoDB server that there might be work for utility
8152
srv_active_wake_master_thread();
8150
8157
/*******************************************************************//**
8151
8158
This function is used to recover X/Open XA distributed transactions.
8152
@return number of prepared transactions stored in xid_list */
8159
@return number of prepared transactions stored in xid_list */
8154
8161
InnobaseEngine::doXaRecover(
8155
8162
/*================*/
8156
::drizzled::XID* xid_list,/*!< in/out: prepared transactions */
8157
size_t len) /*!< in: number of slots in xid_list */
8163
::drizzled::XID* xid_list,/*!< in/out: prepared transactions */
8164
size_t len) /*!< in: number of slots in xid_list */
8159
assert(this == innodb_engine_ptr);
8161
if (len == 0 || xid_list == NULL) {
8166
return(trx_recover_for_mysql((::XID *)xid_list, len));
8166
assert(this == innodb_engine_ptr);
8168
if (len == 0 || xid_list == NULL) {
8173
return(trx_recover_for_mysql((::XID *)xid_list, len));
8169
8176
/*******************************************************************//**
8170
8177
This function is used to commit one X/Open XA distributed transaction
8171
8178
which is in the prepared state
8172
@return 0 or error number */
8179
@return 0 or error number */
8174
8181
InnobaseEngine::doXaCommitXid(
8175
8182
/*===================*/
8176
::drizzled::XID* xid) /*!< in: X/Open XA transaction identification */
8183
::drizzled::XID* xid) /*!< in: X/Open XA transaction identification */
8180
assert(this == innodb_engine_ptr);
8182
trx = trx_get_trx_by_xid((::XID *)xid);
8185
innobase_commit_low(trx);
8187
assert(this == innodb_engine_ptr);
8189
trx = trx_get_trx_by_xid((::XID *)xid);
8192
innobase_commit_low(trx);
8193
8200
/*******************************************************************//**
8194
8201
This function is used to rollback one X/Open XA distributed transaction
8195
8202
which is in the prepared state
8196
@return 0 or error number */
8203
@return 0 or error number */
8198
8205
InnobaseEngine::doXaRollbackXid(
8199
8206
/*=====================*/
8200
::drizzled::XID* xid) /*!< in: X/Open XA transaction
8207
::drizzled::XID* xid) /*!< in: X/Open XA transaction
8205
assert(this == innodb_engine_ptr);
8207
trx = trx_get_trx_by_xid((::XID *)xid);
8210
return(innobase_rollback_trx(trx));
8212
assert(this == innodb_engine_ptr);
8214
trx = trx_get_trx_by_xid((::XID *)xid);
8217
return(innobase_rollback_trx(trx));
8217
8224
/************************************************************//**
8218
8225
Validate the file format name and return its corresponding id.
8219
@return valid file format id */
8226
@return valid file format id */
8222
8229
innobase_file_format_name_lookup(
8223
8230
/*=============================*/
8224
const char* format_name) /*!< in: pointer to file format name */
8231
const char* format_name) /*!< in: pointer to file format name */
8229
ut_a(format_name != NULL);
8231
/* The format name can contain the format id itself instead of
8232
the name and we check for that. */
8233
format_id = (uint) strtoul(format_name, &endp, 10);
8235
/* Check for valid parse. */
8236
if (*endp == '\0' && *format_name != '\0') {
8238
if (format_id <= DICT_TF_FORMAT_MAX) {
8244
for (format_id = 0; format_id <= DICT_TF_FORMAT_MAX;
8248
name = trx_sys_file_format_id_to_name(format_id);
8250
if (!innobase_strcasecmp(format_name, name)) {
8257
return(DICT_TF_FORMAT_MAX + 1);
8236
ut_a(format_name != NULL);
8238
/* The format name can contain the format id itself instead of
8239
the name and we check for that. */
8240
format_id = (uint) strtoul(format_name, &endp, 10);
8242
/* Check for valid parse. */
8243
if (*endp == '\0' && *format_name != '\0') {
8245
if (format_id <= DICT_TF_FORMAT_MAX) {
8251
for (format_id = 0; format_id <= DICT_TF_FORMAT_MAX;
8255
name = trx_sys_file_format_id_to_name(format_id);
8257
if (!innobase_strcasecmp(format_name, name)) {
8264
return(DICT_TF_FORMAT_MAX + 1);
8260
8267
/************************************************************//**
8261
8268
Validate the file format check value, is it one of "on" or "off",
8262
8269
as a side effect it sets the srv_check_file_format_at_startup variable.
8263
@return true if config value one of "on" or "off" */
8270
@return true if config value one of "on" or "off" */
8266
8273
innobase_file_format_check_on_off(
8267
8274
/*==============================*/
8268
const char* format_check) /*!< in: parameter value */
8275
const char* format_check) /*!< in: parameter value */
8272
if (!innobase_strcasecmp(format_check, "off")) {
8274
/* Set the value to disable checking. */
8275
srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
8277
} else if (!innobase_strcasecmp(format_check, "on")) {
8279
/* Set the value to the lowest supported format. */
8280
srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
8279
if (!innobase_strcasecmp(format_check, "off")) {
8281
/* Set the value to disable checking. */
8282
srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
8284
} else if (!innobase_strcasecmp(format_check, "on")) {
8286
/* Set the value to the lowest supported format. */
8287
srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
8288
8295
/************************************************************//**
8289
8296
Validate the file format check config parameters, as a side effect it
8290
8297
sets the srv_check_file_format_at_startup variable.
8291
@return true if valid config value */
8298
@return true if valid config value */
8294
8301
innobase_file_format_check_validate(
8295
8302
/*================================*/
8296
const char* format_check) /*!< in: parameter value */
8303
const char* format_check) /*!< in: parameter value */
8301
format_id = innobase_file_format_name_lookup(format_check);
8303
if (format_id < DICT_TF_FORMAT_MAX + 1) {
8304
srv_check_file_format_at_startup = format_id;
8308
format_id = innobase_file_format_name_lookup(format_check);
8310
if (format_id < DICT_TF_FORMAT_MAX + 1) {
8311
srv_check_file_format_at_startup = format_id;
8312
8319
/*************************************************************//**
8313
8320
Check if it is a valid file format. This function is registered as
8314
8321
a callback with MySQL.
8315
@return 0 for valid file format */
8322
@return 0 for valid file format */
8318
8325
innodb_file_format_name_validate(
8319
8326
/*=============================*/
8320
Session* , /*!< in: thread handle */
8321
drizzle_sys_var* , /*!< in: pointer to system
8323
void* save, /*!< out: immediate result
8324
for update function */
8325
drizzle_value* value) /*!< in: incoming string */
8327
Session* , /*!< in: thread handle */
8328
drizzle_sys_var* , /*!< in: pointer to system
8330
void* save, /*!< out: immediate result
8331
for update function */
8332
drizzle_value* value) /*!< in: incoming string */
8327
const char* file_format_input;
8328
char buff[STRING_BUFFER_USUAL_SIZE];
8329
int len = sizeof(buff);
8332
ut_a(value != NULL);
8334
file_format_input = value->val_str(value, buff, &len);
8336
if (file_format_input != NULL) {
8339
format_id = innobase_file_format_name_lookup(
8342
if (format_id <= DICT_TF_FORMAT_MAX) {
8344
*static_cast<const char**>(save) = file_format_input;
8349
*static_cast<const char**>(save) = NULL;
8334
const char* file_format_input;
8335
char buff[STRING_BUFFER_USUAL_SIZE];
8336
int len = sizeof(buff);
8339
ut_a(value != NULL);
8341
file_format_input = value->val_str(value, buff, &len);
8343
if (file_format_input != NULL) {
8346
format_id = innobase_file_format_name_lookup(
8349
if (format_id <= DICT_TF_FORMAT_MAX) {
8351
*static_cast<const char**>(save) = file_format_input;
8356
*static_cast<const char**>(save) = NULL;
8353
8360
/****************************************************************//**
8936
8943
innobase_commit_concurrency_init_default(void)
8937
8944
/*==========================================*/
8939
DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
8940
= innobase_commit_concurrency;
8946
DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
8947
= innobase_commit_concurrency;
8943
8950
#ifdef UNIV_COMPILE_TEST_FUNCS
8945
8952
typedef struct innobase_convert_name_test_struct {
8953
const char* expected;
8960
const char* expected;
8954
8961
} innobase_convert_name_test_t;
8957
8964
test_innobase_convert_name()
8962
innobase_convert_name_test_t test_input[] = {
8963
{buf, sizeof(buf), "abcd", 4, NULL, TRUE, "\"abcd\""},
8964
{buf, 7, "abcd", 4, NULL, TRUE, "\"abcd\""},
8965
{buf, 6, "abcd", 4, NULL, TRUE, "\"abcd\""},
8966
{buf, 5, "abcd", 4, NULL, TRUE, "\"abc\""},
8967
{buf, 4, "abcd", 4, NULL, TRUE, "\"ab\""},
8969
{buf, sizeof(buf), "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8970
{buf, 9, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8971
{buf, 8, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8972
{buf, 7, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8973
{buf, 6, "ab@0060cd", 9, NULL, TRUE, "\"ab`c\""},
8974
{buf, 5, "ab@0060cd", 9, NULL, TRUE, "\"ab`\""},
8975
{buf, 4, "ab@0060cd", 9, NULL, TRUE, "\"ab\""},
8977
{buf, sizeof(buf), "ab\"cd", 5, NULL, TRUE,
8978
"\"#mysql50#ab\"\"cd\""},
8979
{buf, 17, "ab\"cd", 5, NULL, TRUE,
8980
"\"#mysql50#ab\"\"cd\""},
8981
{buf, 16, "ab\"cd", 5, NULL, TRUE,
8982
"\"#mysql50#ab\"\"c\""},
8983
{buf, 15, "ab\"cd", 5, NULL, TRUE,
8984
"\"#mysql50#ab\"\"\""},
8985
{buf, 14, "ab\"cd", 5, NULL, TRUE,
8987
{buf, 13, "ab\"cd", 5, NULL, TRUE,
8989
{buf, 12, "ab\"cd", 5, NULL, TRUE,
8991
{buf, 11, "ab\"cd", 5, NULL, TRUE,
8993
{buf, 10, "ab\"cd", 5, NULL, TRUE,
8996
{buf, sizeof(buf), "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
8997
{buf, 9, "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
8998
{buf, 8, "ab/cd", 5, NULL, TRUE, "\"ab\".\"c\""},
8999
{buf, 7, "ab/cd", 5, NULL, TRUE, "\"ab\".\"\""},
9000
{buf, 6, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
9001
{buf, 5, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
9002
{buf, 4, "ab/cd", 5, NULL, TRUE, "\"ab\""},
9003
{buf, 3, "ab/cd", 5, NULL, TRUE, "\"a\""},
9004
{buf, 2, "ab/cd", 5, NULL, TRUE, "\"\""},
9005
/* XXX probably "" is a better result in this case
9006
{buf, 1, "ab/cd", 5, NULL, TRUE, "."},
9008
{buf, 0, "ab/cd", 5, NULL, TRUE, ""},
9011
for (i = 0; i < sizeof(test_input) / sizeof(test_input[0]); i++) {
9017
fprintf(stderr, "TESTING %lu, %s, %lu, %s\n",
9018
test_input[i].buflen,
9020
test_input[i].idlen,
9021
test_input[i].expected);
9023
end = innobase_convert_name(
9025
test_input[i].buflen,
9027
test_input[i].idlen,
9028
test_input[i].session,
9029
test_input[i].file_id);
9031
res_len = (size_t) (end - test_input[i].buf);
9033
if (res_len != strlen(test_input[i].expected)) {
9035
fprintf(stderr, "unexpected len of the result: %u, "
9036
"expected: %u\n", (unsigned) res_len,
9037
(unsigned) strlen(test_input[i].expected));
9041
if (memcmp(test_input[i].buf,
9042
test_input[i].expected,
9043
strlen(test_input[i].expected)) != 0
9046
fprintf(stderr, "unexpected result: %.*s, "
9047
"expected: %s\n", (int) res_len,
9049
test_input[i].expected);
9054
fprintf(stderr, "OK: res: %.*s\n\n", (int) res_len,
9057
fprintf(stderr, "FAILED\n\n");
8969
innobase_convert_name_test_t test_input[] = {
8970
{buf, sizeof(buf), "abcd", 4, NULL, TRUE, "\"abcd\""},
8971
{buf, 7, "abcd", 4, NULL, TRUE, "\"abcd\""},
8972
{buf, 6, "abcd", 4, NULL, TRUE, "\"abcd\""},
8973
{buf, 5, "abcd", 4, NULL, TRUE, "\"abc\""},
8974
{buf, 4, "abcd", 4, NULL, TRUE, "\"ab\""},
8976
{buf, sizeof(buf), "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8977
{buf, 9, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8978
{buf, 8, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8979
{buf, 7, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8980
{buf, 6, "ab@0060cd", 9, NULL, TRUE, "\"ab`c\""},
8981
{buf, 5, "ab@0060cd", 9, NULL, TRUE, "\"ab`\""},
8982
{buf, 4, "ab@0060cd", 9, NULL, TRUE, "\"ab\""},
8984
{buf, sizeof(buf), "ab\"cd", 5, NULL, TRUE,
8985
"\"#mysql50#ab\"\"cd\""},
8986
{buf, 17, "ab\"cd", 5, NULL, TRUE,
8987
"\"#mysql50#ab\"\"cd\""},
8988
{buf, 16, "ab\"cd", 5, NULL, TRUE,
8989
"\"#mysql50#ab\"\"c\""},
8990
{buf, 15, "ab\"cd", 5, NULL, TRUE,
8991
"\"#mysql50#ab\"\"\""},
8992
{buf, 14, "ab\"cd", 5, NULL, TRUE,
8994
{buf, 13, "ab\"cd", 5, NULL, TRUE,
8996
{buf, 12, "ab\"cd", 5, NULL, TRUE,
8998
{buf, 11, "ab\"cd", 5, NULL, TRUE,
9000
{buf, 10, "ab\"cd", 5, NULL, TRUE,
9003
{buf, sizeof(buf), "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
9004
{buf, 9, "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
9005
{buf, 8, "ab/cd", 5, NULL, TRUE, "\"ab\".\"c\""},
9006
{buf, 7, "ab/cd", 5, NULL, TRUE, "\"ab\".\"\""},
9007
{buf, 6, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
9008
{buf, 5, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
9009
{buf, 4, "ab/cd", 5, NULL, TRUE, "\"ab\""},
9010
{buf, 3, "ab/cd", 5, NULL, TRUE, "\"a\""},
9011
{buf, 2, "ab/cd", 5, NULL, TRUE, "\"\""},
9012
/* XXX probably "" is a better result in this case
9013
{buf, 1, "ab/cd", 5, NULL, TRUE, "."},
9015
{buf, 0, "ab/cd", 5, NULL, TRUE, ""},
9018
for (i = 0; i < sizeof(test_input) / sizeof(test_input[0]); i++) {
9024
fprintf(stderr, "TESTING %lu, %s, %lu, %s\n",
9025
test_input[i].buflen,
9027
test_input[i].idlen,
9028
test_input[i].expected);
9030
end = innobase_convert_name(
9032
test_input[i].buflen,
9034
test_input[i].idlen,
9035
test_input[i].session,
9036
test_input[i].file_id);
9038
res_len = (size_t) (end - test_input[i].buf);
9040
if (res_len != strlen(test_input[i].expected)) {
9042
fprintf(stderr, "unexpected len of the result: %u, "
9043
"expected: %u\n", (unsigned) res_len,
9044
(unsigned) strlen(test_input[i].expected));
9048
if (memcmp(test_input[i].buf,
9049
test_input[i].expected,
9050
strlen(test_input[i].expected)) != 0
9053
fprintf(stderr, "unexpected result: %.*s, "
9054
"expected: %s\n", (int) res_len,
9056
test_input[i].expected);
9061
fprintf(stderr, "OK: res: %.*s\n\n", (int) res_len,
9064
fprintf(stderr, "FAILED\n\n");
9063
9070
#endif /* UNIV_COMPILE_TEST_FUNCS */