550
676
{"buffer_pool_read_requests",
551
677
(char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG},
552
678
{"buffer_pool_reads",
553
(char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG},
679
(char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG},
554
680
{"buffer_pool_wait_free",
555
(char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG},
681
(char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG},
556
682
{"buffer_pool_write_requests",
557
683
(char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
559
(char*) &export_vars.innodb_data_fsyncs, SHOW_LONG},
685
(char*) &export_vars.innodb_data_fsyncs, SHOW_LONG},
560
686
{"data_pending_fsyncs",
561
(char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG},
687
(char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG},
562
688
{"data_pending_reads",
563
(char*) &export_vars.innodb_data_pending_reads, SHOW_LONG},
689
(char*) &export_vars.innodb_data_pending_reads, SHOW_LONG},
564
690
{"data_pending_writes",
565
(char*) &export_vars.innodb_data_pending_writes, SHOW_LONG},
691
(char*) &export_vars.innodb_data_pending_writes, SHOW_LONG},
567
(char*) &export_vars.innodb_data_read, SHOW_LONG},
693
(char*) &export_vars.innodb_data_read, SHOW_LONG},
569
(char*) &export_vars.innodb_data_reads, SHOW_LONG},
695
(char*) &export_vars.innodb_data_reads, SHOW_LONG},
571
(char*) &export_vars.innodb_data_writes, SHOW_LONG},
697
(char*) &export_vars.innodb_data_writes, SHOW_LONG},
573
(char*) &export_vars.innodb_data_written, SHOW_LONG},
699
(char*) &export_vars.innodb_data_written, SHOW_LONG},
574
700
{"dblwr_pages_written",
575
(char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
701
(char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
577
(char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
703
(char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
578
704
{"have_atomic_builtins",
579
(char*) &export_vars.innodb_have_atomic_builtins, SHOW_BOOL},
705
(char*) &export_vars.innodb_have_atomic_builtins, SHOW_BOOL},
581
(char*) &export_vars.innodb_log_waits, SHOW_LONG},
707
(char*) &export_vars.innodb_log_waits, SHOW_LONG},
582
708
{"log_write_requests",
583
(char*) &export_vars.innodb_log_write_requests, SHOW_LONG},
709
(char*) &export_vars.innodb_log_write_requests, SHOW_LONG},
585
(char*) &export_vars.innodb_log_writes, SHOW_LONG},
711
(char*) &export_vars.innodb_log_writes, SHOW_LONG},
586
712
{"os_log_fsyncs",
587
(char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG},
713
(char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG},
588
714
{"os_log_pending_fsyncs",
589
(char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG},
715
(char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG},
590
716
{"os_log_pending_writes",
591
(char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG},
717
(char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG},
592
718
{"os_log_written",
593
(char*) &export_vars.innodb_os_log_written, SHOW_LONG},
719
(char*) &export_vars.innodb_os_log_written, SHOW_LONG},
595
(char*) &export_vars.innodb_page_size, SHOW_LONG},
721
(char*) &export_vars.innodb_page_size, SHOW_LONG},
596
722
{"pages_created",
597
(char*) &export_vars.innodb_pages_created, SHOW_LONG},
723
(char*) &export_vars.innodb_pages_created, SHOW_LONG},
599
(char*) &export_vars.innodb_pages_read, SHOW_LONG},
725
(char*) &export_vars.innodb_pages_read, SHOW_LONG},
600
726
{"pages_written",
601
(char*) &export_vars.innodb_pages_written, SHOW_LONG},
727
(char*) &export_vars.innodb_pages_written, SHOW_LONG},
602
728
{"row_lock_current_waits",
603
(char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG},
729
(char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG},
604
730
{"row_lock_time",
605
(char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG},
731
(char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG},
606
732
{"row_lock_time_avg",
607
(char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG},
733
(char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG},
608
734
{"row_lock_time_max",
609
(char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG},
735
(char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG},
610
736
{"row_lock_waits",
611
(char*) &export_vars.innodb_row_lock_waits, SHOW_LONG},
737
(char*) &export_vars.innodb_row_lock_waits, SHOW_LONG},
613
(char*) &export_vars.innodb_rows_deleted, SHOW_LONG},
739
(char*) &export_vars.innodb_rows_deleted, SHOW_LONG},
614
740
{"rows_inserted",
615
(char*) &export_vars.innodb_rows_inserted, SHOW_LONG},
741
(char*) &export_vars.innodb_rows_inserted, SHOW_LONG},
617
(char*) &export_vars.innodb_rows_read, SHOW_LONG},
743
(char*) &export_vars.innodb_rows_read, SHOW_LONG},
619
(char*) &export_vars.innodb_rows_updated, SHOW_LONG},
745
(char*) &export_vars.innodb_rows_updated, SHOW_LONG},
620
746
{NULL, NULL, SHOW_LONG}
853
979
innobase_active_small(void)
854
980
/*=======================*/
856
innobase_active_counter++;
982
innobase_active_counter++;
858
if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
859
srv_active_wake_master_thread();
984
if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
985
srv_active_wake_master_thread();
863
989
/********************************************************************//**
864
990
Converts an InnoDB error code to a MySQL error code and also tells to MySQL
865
991
about a possible transaction rollback inside InnoDB caused by a lock wait
866
992
timeout or a deadlock.
867
@return MySQL error code */
993
@return MySQL error code */
868
994
extern "C" UNIV_INTERN
870
996
convert_error_code_to_mysql(
871
997
/*========================*/
872
int error, /*!< in: InnoDB error code */
873
ulint flags, /*!< in: InnoDB table flags, or 0 */
874
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 */
882
return(-1); /* unspecified error */
884
case DB_DUPLICATE_KEY:
885
return(HA_ERR_FOUND_DUPP_KEY);
887
case DB_FOREIGN_DUPLICATE_KEY:
888
return(HA_ERR_FOREIGN_DUPLICATE_KEY);
890
case DB_MISSING_HISTORY:
891
return(HA_ERR_TABLE_DEF_CHANGED);
893
case DB_RECORD_NOT_FOUND:
894
return(HA_ERR_NO_ACTIVE_RECORD);
897
/* Since we rolled back the whole transaction, we must
898
tell it also to MySQL so that MySQL knows to empty the
899
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 */
901
1027
session_mark_transaction_to_rollback(session, TRUE);
903
return(HA_ERR_LOCK_DEADLOCK);
1029
return(HA_ERR_LOCK_DEADLOCK);
905
case DB_LOCK_WAIT_TIMEOUT:
906
/* Starting from 5.0.13, we let MySQL just roll back the
907
latest SQL statement in a lock wait timeout. Previously, we
908
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. */
910
1036
session_mark_transaction_to_rollback(session,
911
1037
(bool)row_rollback_on_timeout);
913
return(HA_ERR_LOCK_WAIT_TIMEOUT);
915
case DB_NO_REFERENCED_ROW:
916
return(HA_ERR_NO_REFERENCED_ROW);
918
case DB_ROW_IS_REFERENCED:
919
return(HA_ERR_ROW_IS_REFERENCED);
921
case DB_CANNOT_ADD_CONSTRAINT:
922
return(HA_ERR_CANNOT_ADD_FOREIGN);
924
case DB_CANNOT_DROP_CONSTRAINT:
926
return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
927
misleading, a new MySQL error
928
code should be introduced */
930
case DB_COL_APPEARS_TWICE_IN_INDEX:
932
return(HA_ERR_CRASHED);
934
case DB_OUT_OF_FILE_SPACE:
935
return(HA_ERR_RECORD_FILE_FULL);
937
case DB_TABLE_IS_BEING_USED:
938
return(HA_ERR_WRONG_COMMAND);
940
case DB_TABLE_NOT_FOUND:
941
return(HA_ERR_NO_SUCH_TABLE);
943
case DB_TOO_BIG_RECORD:
944
my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
945
page_get_free_space_of_empty(flags
946
& DICT_TF_COMPACT) / 2);
947
return(HA_ERR_TO_BIG_ROW);
949
case DB_NO_SAVEPOINT:
950
return(HA_ERR_NO_SAVEPOINT);
952
case DB_LOCK_TABLE_FULL:
953
/* Since we rolled back the whole transaction, we must
954
tell it also to MySQL so that MySQL knows to empty the
955
cached binlog for this transaction */
957
session_mark_transaction_to_rollback(session, TRUE);
959
return(HA_ERR_LOCK_TABLE_FULL);
961
case DB_PRIMARY_KEY_IS_NULL:
962
return(ER_PRIMARY_CANT_HAVE_NULL);
964
case DB_TOO_MANY_CONCURRENT_TRXS:
966
/* Once MySQL add the appropriate code to errmsg.txt then
967
we can get rid of this #ifdef. NOTE: The code checked by
968
the #ifdef is the suggested name for the error condition
969
and the actual error code name could very well be different.
970
This will require some monitoring, ie. the status
971
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.*/
972
1098
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
973
return(ER_TOO_MANY_CONCURRENT_TRXS);
1099
return(ER_TOO_MANY_CONCURRENT_TRXS);
975
return(HA_ERR_RECORD_FILE_FULL);
1101
return(HA_ERR_RECORD_FILE_FULL);
978
return(HA_ERR_UNSUPPORTED);
1103
case DB_UNSUPPORTED:
1104
return(HA_ERR_UNSUPPORTED);
982
1108
/*************************************************************//**
1159
unsigned long); /*!< in: OS error value */
1285
unsigned long); /*!< in: OS error value */
1161
1287
/*********************************************************************//**
1162
1288
Creates a temporary file.
1163
@return temporary file descriptor, or < 0 on error */
1289
@return temporary file descriptor, or < 0 on error */
1164
1290
extern "C" UNIV_INTERN
1166
1292
innobase_mysql_tmpfile(void)
1167
1293
/*========================*/
1169
int fd; /* handle of opened file */
1170
HANDLE osfh; /* OS handle of opened file */
1171
char* tmpdir; /* point to the directory
1172
where to create file */
1173
TCHAR path_buf[MAX_PATH - 14]; /* buffer for tmp file path.
1174
The length cannot be longer
1175
than MAX_PATH - 14, or
1176
GetTempFileName will fail. */
1177
char filename[MAX_PATH]; /* name of the tmpfile */
1178
DWORD fileaccess = GENERIC_READ /* OS file access */
1181
DWORD fileshare = FILE_SHARE_READ /* OS file sharing mode */
1183
| FILE_SHARE_DELETE;
1184
DWORD filecreate = CREATE_ALWAYS; /* OS method of open/create */
1185
DWORD fileattrib = /* OS file attribute flags */
1186
FILE_ATTRIBUTE_NORMAL
1187
| FILE_FLAG_DELETE_ON_CLOSE
1188
| FILE_ATTRIBUTE_TEMPORARY
1189
| FILE_FLAG_SEQUENTIAL_SCAN;
1191
tmpdir = my_tmpdir(&mysql_tmpdir_list);
1193
/* The tmpdir parameter can not be NULL for GetTempFileName. */
1197
/* Use GetTempPath to determine path for temporary files. */
1198
ret = GetTempPath(sizeof(path_buf), path_buf);
1199
if (ret > sizeof(path_buf) || (ret == 0)) {
1201
_dosmaperr(GetLastError()); /* map error */
1208
/* Use GetTempFileName to generate a unique filename. */
1209
if (!GetTempFileName(tmpdir, "ib", 0, filename)) {
1211
_dosmaperr(GetLastError()); /* map error */
1215
/* Open/Create the file. */
1216
osfh = CreateFile(filename, fileaccess, fileshare, NULL,
1217
filecreate, fileattrib, NULL);
1218
if (osfh == INVALID_HANDLE_VALUE) {
1220
/* open/create file failed! */
1221
_dosmaperr(GetLastError()); /* map error */
1226
/* Associates a CRT file descriptor with the OS file handle. */
1227
fd = _open_osfhandle((intptr_t) osfh, 0);
1228
} while (fd == -1 && errno == EINTR);
1231
/* Open failed, close the file handle. */
1233
_dosmaperr(GetLastError()); /* map error */
1234
CloseHandle(osfh); /* no need to check if
1235
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 */
1241
1367
/*********************************************************************//**
1242
1368
Creates a temporary file.
1243
@return temporary file descriptor, or < 0 on error */
1369
@return temporary file descriptor, or < 0 on error */
1244
1370
extern "C" UNIV_INTERN
1246
1372
innobase_mysql_tmpfile(void)
1247
1373
/*========================*/
1250
int fd = mysql_tmpfile("ib");
1252
/* Copy the file descriptor, so that the additional resources
1253
allocated by create_temp_file() can be freed by invoking
1254
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().
1256
Because the file descriptor returned by this function
1257
will be passed to fdopen(), it will be closed by invoking
1258
fclose(), which in turn will invoke close() instead of
1259
internal::my_close(). */
1263
my_error(EE_OUT_OF_FILERESOURCES,
1264
MYF(ME_BELL+ME_WAITTANG),
1267
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));
1271
1397
#endif /* defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) */
1502
1628
ha_innobase::update_session()
1503
1629
/*=====================*/
1505
Session* session = ha_session();
1506
ut_ad(EQ_CURRENT_SESSION(session));
1507
update_session(session);
1631
Session* session = ha_session();
1632
ut_ad(EQ_CURRENT_SESSION(session));
1633
update_session(session);
1510
1636
/*****************************************************************//**
1511
1637
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
1512
1638
and quote it if needed.
1513
@return pointer to the end of buf */
1639
@return pointer to the end of buf */
1516
1642
innobase_convert_identifier(
1517
1643
/*========================*/
1518
char* buf, /*!< out: buffer for converted identifier */
1519
ulint buflen, /*!< in: length of buf, in bytes */
1520
const char* id, /*!< in: identifier to convert */
1521
ulint idlen, /*!< in: length of id, in bytes */
1522
void* session,/*!< in: MySQL connection thread, or NULL */
1523
ibool file_id)/*!< in: TRUE=id is a table or database name;
1524
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 */
1526
char nz[NAME_LEN + 1];
1527
char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
1533
/* Decode the table name. The filename_to_tablename()
1534
function expects a NUL-terminated string. The input and
1535
output strings buffers must not be shared. */
1537
if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
1538
idlen = (sizeof nz) - 1;
1541
memcpy(nz, id, idlen);
1545
idlen = filename_to_tablename(nz, nz2, sizeof nz2);
1548
/* See if the identifier needs to be quoted. */
1549
if (UNIV_UNLIKELY(!session)) {
1552
q = get_quote_char_for_identifier();
1556
if (UNIV_UNLIKELY(idlen > buflen)) {
1559
memcpy(buf, s, idlen);
1560
return(buf + idlen);
1563
/* Quote the identifier. */
1571
for (; idlen; idlen--) {
1573
if (UNIV_UNLIKELY(c == q)) {
1574
if (UNIV_UNLIKELY(buflen < 3)) {
1582
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)) {
1595
1721
/*****************************************************************//**
1596
1722
Convert a table or index name to the MySQL system_charset_info (UTF-8)
1597
1723
and quote it if needed.
1598
@return pointer to the end of buf */
1724
@return pointer to the end of buf */
1599
1725
extern "C" UNIV_INTERN
1601
1727
innobase_convert_name(
1602
1728
/*==================*/
1603
char* buf, /*!< out: buffer for converted identifier */
1604
ulint buflen, /*!< in: length of buf, in bytes */
1605
const char* id, /*!< in: identifier to convert */
1606
ulint idlen, /*!< in: length of id, in bytes */
1607
void* session,/*!< in: MySQL connection thread, or NULL */
1608
ibool table_id)/*!< in: TRUE=id is a table or database name;
1609
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 */
1612
const char* bufend = buf + buflen;
1615
const char* slash = (const char*) memchr(id, '/', idlen);
1621
/* Print the database name and table name separately. */
1622
s = innobase_convert_identifier(s, bufend - s, id, slash - id,
1624
if (UNIV_LIKELY(s < bufend)) {
1626
s = innobase_convert_identifier(s, bufend - s,
1631
} else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
1632
/* Temporary index name (smart ALTER TABLE) */
1633
const char temp_index_suffix[]= "--temporary--";
1635
s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
1637
if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
1638
memcpy(s, temp_index_suffix,
1639
sizeof temp_index_suffix - 1);
1640
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;
1644
s = innobase_convert_identifier(buf, buflen, id, idlen,
1770
s = innobase_convert_identifier(buf, buflen, id, idlen,
1652
1778
/**********************************************************************//**
1653
1779
Determines if the currently running transaction has been interrupted.
1654
@return TRUE if interrupted */
1780
@return TRUE if interrupted */
1655
1781
extern "C" UNIV_INTERN
1657
1783
trx_is_interrupted(
1658
1784
/*===============*/
1659
trx_t* trx) /*!< in: transaction */
1785
trx_t* trx) /*!< in: transaction */
1661
return(trx && trx->mysql_thd && session_killed((Session*) trx->mysql_thd));
1787
return(trx && trx->mysql_thd && session_killed((Session*) trx->mysql_thd));
1664
1790
/**************************************************************//**
1669
1795
reset_template(
1670
1796
/*===========*/
1671
row_prebuilt_t* prebuilt) /*!< in/out: prebuilt struct */
1797
row_prebuilt_t* prebuilt) /*!< in/out: prebuilt struct */
1673
prebuilt->keep_other_fields_on_keyread = 0;
1674
prebuilt->read_just_key = 0;
1799
prebuilt->keep_other_fields_on_keyread = 0;
1800
prebuilt->read_just_key = 0;
1677
1803
/*********************************************************************//**
1678
1804
Opens an InnoDB database.
1679
@return 0 on success, error code on failure */
1805
@return 0 on success, error code on failure */
1684
plugin::Registry ®istry) /*!< in: Drizzle Plugin Registry */
1810
plugin::Context &context) /*!< in: Drizzle Plugin Context */
1686
static char current_dir[3]; /*!< Set if using current lib */
1692
innodb_engine_ptr= new InnobaseEngine(innobase_engine_name);
1695
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);
1697
1822
#ifdef UNIV_DEBUG
1698
static const char test_filename[] = "-@";
1699
char test_tablename[sizeof test_filename
1700
+ sizeof srv_mysql50_table_name_prefix];
1701
if ((sizeof test_tablename) - 1
1702
!= filename_to_tablename(test_filename, test_tablename,
1703
sizeof test_tablename)
1704
|| strncmp(test_tablename,
1705
srv_mysql50_table_name_prefix,
1706
sizeof srv_mysql50_table_name_prefix)
1707
|| strcmp(test_tablename
1708
+ sizeof srv_mysql50_table_name_prefix,
1710
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");
1713
1838
#endif /* UNIV_DEBUG */
1715
/* Check that values don't overflow on 32-bit systems. */
1716
if (sizeof(ulint) == 4) {
1717
if (innobase_buffer_pool_size > UINT32_MAX) {
1718
errmsg_printf(ERRMSG_LVL_ERROR,
1719
"innobase_buffer_pool_size can't be over 4GB"
1720
" on 32-bit systems");
1725
if (innobase_log_file_size > UINT32_MAX) {
1726
errmsg_printf(ERRMSG_LVL_ERROR,
1727
"innobase_log_file_size can't be over 4GB"
1728
" on 32-bit systems");
1734
os_innodb_umask = (ulint)internal::my_umask;
1736
/* First calculate the default path for innodb_data_home_dir etc.,
1737
in case the user has not given any value.
1739
Note that when using the embedded server, the datadirectory is not
1740
necessarily the current directory of this program. */
1742
/* It's better to use current lib, to keep paths short */
1743
current_dir[0] = FN_CURLIB;
1744
current_dir[1] = FN_LIBCHAR;
1746
default_path = current_dir;
1750
srv_set_thread_priorities = TRUE;
1751
srv_query_thread_priority = QUERY_PRIOR;
1753
/* Set InnoDB initialization parameters according to the values
1754
read from MySQL .cnf file */
1756
/*--------------- Data files -------------------------*/
1758
/* The default dir for data files is the datadir of MySQL */
1760
srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
1763
/* Set default InnoDB data file size to 10 MB and let it be
1764
auto-extending. Thus users can use InnoDB in >= 4.0 without having
1765
to specify any startup options. */
1767
if (!innobase_data_file_path) {
1768
innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
1771
/* Since InnoDB edits the argument in the next call, we make another
1774
internal_innobase_data_file_path = strdup(innobase_data_file_path);
1776
ret = (bool) srv_parse_data_file_paths_and_sizes(
1777
internal_innobase_data_file_path);
1779
errmsg_printf(ERRMSG_LVL_ERROR,
1780
"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");
1781
1906
mem_free_and_error:
1782
srv_free_paths_and_sizes();
1783
if (internal_innobase_data_file_path)
1784
free(internal_innobase_data_file_path);
1788
/* -------------- Log files ---------------------------*/
1790
/* The default dir for log files is the datadir of MySQL */
1792
if (!innobase_log_group_home_dir) {
1793
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;
1796
1921
#ifdef UNIV_LOG_ARCHIVE
1797
/* Since innodb_log_arch_dir has no relevance under MySQL,
1798
starting from 4.0.6 we always set it the same as
1799
innodb_log_group_home_dir: */
1801
innobase_log_arch_dir = innobase_log_group_home_dir;
1803
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;
1804
1929
#endif /* UNIG_LOG_ARCHIVE */
1807
srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
1809
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
1810
errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
1811
"wrong number of mirrored log groups");
1813
goto mem_free_and_error;
1816
/* Validate the file format by animal name */
1817
if (innobase_file_format_name != NULL) {
1819
format_id = innobase_file_format_name_lookup(
1820
innobase_file_format_name);
1822
if (format_id > DICT_TF_FORMAT_MAX) {
1824
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
1826
goto mem_free_and_error;
1829
/* Set it to the default file format id. Though this
1830
should never happen. */
1834
srv_file_format = format_id;
1836
/* Given the type of innobase_file_format_name we have little
1837
choice but to cast away the constness from the returned name.
1838
innobase_file_format_name is used in the MySQL set variable
1839
interface and so can't be const. */
1841
innobase_file_format_name =
1842
(char*) trx_sys_file_format_id_to_name(format_id);
1844
/* Process innobase_file_format_check variable */
1845
ut_a(innobase_file_format_check != NULL);
1847
/* As a side effect it will set srv_check_file_format_at_startup
1848
on valid input. First we check for "on"/"off". */
1849
if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
1851
/* Did the user specify a format name that we support ?
1852
As a side effect it will update the variable
1853
srv_check_file_format_at_startup */
1854
if (!innobase_file_format_check_validate(
1855
innobase_file_format_check)) {
1857
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
1858
"innodb_file_format_check value: "
1859
"should be either 'on' or 'off' or "
1860
"any value up to %s or its "
1861
"equivalent numeric id",
1862
trx_sys_file_format_id_to_name(
1863
DICT_TF_FORMAT_MAX));
1865
goto mem_free_and_error;
1869
if (innobase_change_buffering) {
1873
use < UT_ARR_SIZE(innobase_change_buffering_values);
1875
if (!innobase_strcasecmp(
1876
innobase_change_buffering,
1877
innobase_change_buffering_values[use])) {
1878
ibuf_use = (ibuf_use_t) use;
1879
goto innobase_change_buffering_inited_ok;
1883
errmsg_printf(ERRMSG_LVL_ERROR,
1884
"InnoDB: invalid value "
1885
"innodb_file_format_check=%s",
1886
innobase_change_buffering);
1887
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;
1890
2015
innobase_change_buffering_inited_ok:
1891
ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
1892
innobase_change_buffering = (char*)
1893
innobase_change_buffering_values[ibuf_use];
1895
/* --------------------------------------------------*/
1897
srv_file_flush_method_str = innobase_unix_file_flush_method;
1899
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
1900
srv_n_log_files = (ulint) innobase_log_files_in_group;
1901
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;
1903
2028
#ifdef UNIV_LOG_ARCHIVE
1904
srv_log_archive_on = (ulint) innobase_log_archive;
2029
srv_log_archive_on = (ulint) innobase_log_archive;
1905
2030
#endif /* UNIV_LOG_ARCHIVE */
1906
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
1908
srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
1910
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
1912
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
1913
srv_n_read_io_threads = (ulint) innobase_read_io_threads;
1914
srv_n_write_io_threads = (ulint) innobase_write_io_threads;
1916
srv_force_recovery = (ulint) innobase_force_recovery;
1918
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
1919
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;
1921
2046
#ifdef HAVE_LARGE_PAGES
1922
2047
if ((os_use_large_pages = (ibool) my_use_large_pages))
1923
os_large_page_size = (ulint) opt_large_page_size;
2048
os_large_page_size = (ulint) opt_large_page_size;
1926
row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
1928
srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
1930
srv_max_n_open_files = (ulint) innobase_open_files;
1931
srv_innodb_status = (ibool) innobase_create_status_file;
1933
srv_print_verbose_log = true;
1935
/* Store the default charset-collation number of this MySQL
1938
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
1941
innobase_commit_concurrency_init_default();
1943
/* Since we in this module access directly the fields of a trx
1944
struct, and due to different headers and flags it might happen that
1945
mutex_t has a different size in this module and in InnoDB
1946
modules, we check at run time that the size is the same in
1947
these compilation modules. */
1949
err = innobase_start_or_create_for_mysql();
1951
if (err != DB_SUCCESS) {
1952
goto mem_free_and_error;
1955
innobase_open_tables = hash_create(200);
1956
pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
1957
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
1958
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
1959
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
1960
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);
1963
2088
status_table_function_ptr= new InnodbStatusTool;
1965
registry.add(innodb_engine_ptr);
1967
registry.add(status_table_function_ptr);
1969
cmp_tool= new(std::nothrow)CmpTool(false);
1970
registry.add(cmp_tool);
1972
cmp_reset_tool= new(std::nothrow)CmpTool(true);
1973
registry.add(cmp_reset_tool);
1975
cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
1976
registry.add(cmp_mem_tool);
1978
cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
1979
registry.add(cmp_mem_reset_tool);
1981
innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
1982
registry.add(innodb_trx_tool);
1984
innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
1985
registry.add(innodb_locks_tool);
1987
innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
1988
registry.add(innodb_lock_waits_tool);
1990
/* Get the current high water mark format. */
1991
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();
1998
/*******************************************************************//**
1999
Closes an InnoDB database.
2000
@return TRUE if error */
2003
innobase_deinit(plugin::Registry ®istry)
2007
registry.remove(status_table_function_ptr);
2008
delete status_table_function_ptr;
2010
registry.remove(cmp_tool);
2013
registry.remove(cmp_reset_tool);
2014
delete cmp_reset_tool;
2016
registry.remove(cmp_mem_tool);
2017
delete cmp_mem_tool;
2019
registry.remove(cmp_mem_reset_tool);
2020
delete cmp_mem_reset_tool;
2022
registry.remove(innodb_trx_tool);
2023
delete innodb_trx_tool;
2025
registry.remove(innodb_locks_tool);
2026
delete innodb_locks_tool;
2028
registry.remove(innodb_lock_waits_tool);
2029
delete innodb_lock_waits_tool;
2031
registry.remove(innodb_engine_ptr);
2032
delete innodb_engine_ptr;
2034
if (innodb_inited) {
2036
srv_fast_shutdown = (ulint) innobase_fast_shutdown;
2038
hash_table_free(innobase_open_tables);
2039
innobase_open_tables = NULL;
2040
if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
2043
srv_free_paths_and_sizes();
2044
if (internal_innobase_data_file_path)
2045
free(internal_innobase_data_file_path);
2046
pthread_mutex_destroy(&innobase_share_mutex);
2047
pthread_mutex_destroy(&prepare_commit_mutex);
2048
pthread_mutex_destroy(&commit_threads_m);
2049
pthread_mutex_destroy(&commit_cond_m);
2050
pthread_cond_destroy(&commit_cond);
2056
2124
/****************************************************************//**
2057
2125
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
2058
2126
the logs, and the name of this function should be innobase_checkpoint.
2059
@return TRUE if error */
2127
@return TRUE if error */
2061
2129
InnobaseEngine::flush_logs()
2062
2130
/*=====================*/
2066
assert(this == innodb_engine_ptr);
2068
log_buffer_flush_to_disk();
2134
assert(this == innodb_engine_ptr);
2136
log_buffer_flush_to_disk();
2073
2141
/*****************************************************************//**
2091
2159
Starts a new InnoDB transaction if a transaction is not yet started. And
2092
2160
assigns a new snapshot for a consistent read if the transaction does not yet
2096
2164
InnobaseEngine::doStartTransaction(
2097
2165
/*====================================*/
2098
Session* session, /*!< in: MySQL thread handle of the user for whom
2099
the transaction should be committed */
2166
Session* session, /*!< in: MySQL thread handle of the user for whom
2167
the transaction should be committed */
2100
2168
start_transaction_option_t options)
2102
assert(this == innodb_engine_ptr);
2104
/* Create a new trx struct for session, if it does not yet have one */
2105
trx_t *trx = check_trx_exists(session);
2107
/* This is just to play safe: release a possible FIFO ticket and
2108
search latch. Since we will reserve the kernel mutex, we have to
2109
release the search system latch first to obey the latching order. */
2110
innobase_release_stat_resources(trx);
2112
/* If the transaction is not started yet, start it */
2113
trx_start_if_not_started(trx);
2115
/* 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 */
2116
2184
if (options == START_TRANS_OPT_WITH_CONS_SNAPSHOT)
2117
trx_assign_read_view(trx);
2185
trx_assign_read_view(trx);
2122
2190
/*****************************************************************//**
2123
2191
Commits a transaction in an InnoDB database or marks an SQL statement
2127
2195
InnobaseEngine::doCommit(
2128
2196
/*============*/
2129
Session* session, /*!< in: MySQL thread handle of the user for whom
2130
the transaction should be committed */
2131
bool all) /*!< in: TRUE - commit transaction
2132
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 */
2136
assert(this == innodb_engine_ptr);
2138
trx = check_trx_exists(session);
2140
/* Since we will reserve the kernel mutex, we have to release
2141
the search system latch first to obey the latching order. */
2143
if (trx->has_search_latch) {
2144
trx_search_latch_release_if_reserved(trx);
2148
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2150
/* We were instructed to commit the whole transaction, or
2151
this is an SQL statement end and autocommit is on */
2153
/* We need current binlog position for ibbackup to work.
2154
Note, the position is current because of
2155
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 */
2157
if (innobase_commit_concurrency > 0) {
2158
pthread_mutex_lock(&commit_cond_m);
2225
if (innobase_commit_concurrency > 0) {
2226
pthread_mutex_lock(&commit_cond_m);
2161
if (commit_threads > innobase_commit_concurrency) {
2163
pthread_cond_wait(&commit_cond,
2165
pthread_mutex_unlock(&commit_cond_m);
2169
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);
2173
2241
/* Store transaction point for binlog
2174
Later logic tests that this is set to _something_. We need
2175
that logic to fire, even though we do not have a real name. */
2176
trx->mysql_log_file_name = "UNUSED";
2177
trx->mysql_log_offset = 0;
2179
/* Don't do write + flush right now. For group commit
2180
to work we want to do the flush after releasing the
2181
prepare_commit_mutex. */
2182
trx->flush_log_later = TRUE;
2183
innobase_commit_low(trx);
2184
trx->flush_log_later = FALSE;
2186
if (innobase_commit_concurrency > 0) {
2187
pthread_mutex_lock(&commit_cond_m);
2189
pthread_cond_signal(&commit_cond);
2190
pthread_mutex_unlock(&commit_cond_m);
2193
if (trx->conc_state == TRX_PREPARED) {
2195
pthread_mutex_unlock(&prepare_commit_mutex);
2198
/* Now do a write + flush of logs. */
2199
trx_commit_complete_for_mysql(trx);
2202
/* We just mark the SQL statement ended and do not do a
2203
transaction commit */
2205
/* If we had reserved the auto-inc lock for some
2206
table in this SQL statement we release it now */
2208
row_unlock_table_autoinc_for_mysql(trx);
2210
/* Store the current undo_no of the transaction so that we
2211
know where to roll back if we have to roll back the next
2214
trx_mark_sql_stat_end(trx);
2217
trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2219
if (trx->declared_to_be_inside_innodb) {
2220
/* Release our possible ticket in the FIFO */
2222
srv_conc_force_exit_innodb(trx);
2225
/* Tell the InnoDB server that there might be work for utility
2227
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();
2232
2295
/*****************************************************************//**
2233
2296
Rolls back a transaction or the latest SQL statement.
2234
@return 0 or error number */
2297
@return 0 or error number */
2236
2299
InnobaseEngine::doRollback(
2237
2300
/*==============*/
2238
Session* session,/*!< in: handle to the MySQL thread of the user
2239
whose transaction should be rolled back */
2240
bool all) /*!< in: TRUE - commit transaction
2241
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 */
2246
assert(this == innodb_engine_ptr);
2248
trx = check_trx_exists(session);
2250
/* Release a possible FIFO ticket and search latch. Since we will
2251
reserve the kernel mutex, we have to release the search system latch
2252
first to obey the latching order. */
2254
innobase_release_stat_resources(trx);
2256
/* If we had reserved the auto-inc lock for some table (if
2257
we come here to roll back the latest SQL statement) we
2258
release it now before a possibly lengthy rollback */
2260
row_unlock_table_autoinc_for_mysql(trx);
2263
|| !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2265
error = trx_rollback_for_mysql(trx);
2267
error = trx_rollback_last_sql_stat_for_mysql(trx);
2270
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));
2273
2336
/*****************************************************************//**
2274
2337
Rolls back a transaction
2275
@return 0 or error number */
2338
@return 0 or error number */
2278
2341
innobase_rollback_trx(
2279
2342
/*==================*/
2280
trx_t* trx) /*!< in: transaction */
2343
trx_t* trx) /*!< in: transaction */
2284
/* Release a possible FIFO ticket and search latch. Since we will
2285
reserve the kernel mutex, we have to release the search system latch
2286
first to obey the latching order. */
2288
innobase_release_stat_resources(trx);
2290
/* If we had reserved the auto-inc lock for some table (if
2291
we come here to roll back the latest SQL statement) we
2292
release it now before a possibly lengthy rollback */
2294
row_unlock_table_autoinc_for_mysql(trx);
2296
error = trx_rollback_for_mysql(trx);
2298
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));
2301
2364
/*****************************************************************//**
2539
2602
normalize_table_name(
2540
2603
/*=================*/
2541
char* norm_name, /*!< out: normalized name as a
2542
null-terminated string */
2543
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 */
2545
const char* name_ptr;
2549
/* Scan name from the end */
2551
ptr = strchr(name, '\0')-1;
2553
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2563
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2569
memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2571
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] = '/';
2574
innobase_casedn_str(norm_name);
2637
innobase_casedn_str(norm_name);
2578
2641
/********************************************************************//**
2579
2642
Set the autoinc column max value. This should only be called once from
2580
2643
ha_innobase::open(). Therefore there's no need for a covering lock.
2581
@return DB_SUCCESS or error code */
2644
@return DB_SUCCESS or error code */
2584
2647
ha_innobase::innobase_initialize_autoinc()
2585
2648
/*======================================*/
2587
dict_index_t* index;
2589
const char* col_name;
2592
col_name = table->found_next_number_field->field_name;
2593
index = innobase_get_index(table->s->next_number_index);
2595
/* Execute SELECT MAX(col_name) FROM TABLE; */
2596
error = row_search_max_autoinc(index, col_name, &auto_inc);
2601
/* At the this stage we don't know the increment
2602
or the offset, so use default inrement of 1. */
2606
case DB_RECORD_NOT_FOUND:
2607
ut_print_timestamp(stderr);
2608
fprintf(stderr, " InnoDB: MySQL and InnoDB data "
2609
"dictionaries are out of sync.\n"
2610
"InnoDB: Unable to find the AUTOINC column %s in the "
2611
"InnoDB table %s.\n"
2612
"InnoDB: We set the next AUTOINC column value to the "
2613
"maximum possible value,\n"
2614
"InnoDB: in effect disabling the AUTOINC next value "
2616
"InnoDB: You can either set the next AUTOINC value "
2617
"explicitly using ALTER TABLE\n"
2618
"InnoDB: or fix the data dictionary by recreating "
2620
col_name, index->table->name);
2622
auto_inc = 0xFFFFFFFFFFFFFFFFULL;
2629
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);
2634
2697
/*****************************************************************//**
2635
2698
Creates and opens a handle to a table which already exists in an InnoDB
2637
@return 1 if error, 0 if success */
2700
@return 1 if error, 0 if success */
2640
2703
ha_innobase::open(
2641
2704
/*==============*/
2642
const char* name, /*!< in: table name */
2643
int mode, /*!< in: not used */
2644
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 */
2646
dict_table_t* ib_table;
2647
char norm_name[1000];
2650
char* is_part = NULL;
2653
UT_NOT_USED(test_if_locked);
2655
session = ha_session();
2657
/* Under some cases Drizzle seems to call this function while
2658
holding btr_search_latch. This breaks the latching order as
2659
we acquire dict_sys->mutex below and leads to a deadlock. */
2660
if (session != NULL) {
2661
getTransactionalEngine()->releaseTemporaryLatches(session);
2664
normalize_table_name(norm_name, name);
2666
user_session = NULL;
2668
if (!(share=get_share(name))) {
2673
/* Create buffers for packing the fields of a record. Why
2674
table->stored_rec_length did not work here? Obviously, because char
2675
fields when packed actually became 1 byte longer, when we also
2676
stored the string length as the first byte. */
2678
upd_and_key_val_buff_len =
2679
table->s->stored_rec_length
2680
+ table->s->max_key_length
2681
+ MAX_REF_PARTS * 3;
2682
if (!(unsigned char*) memory::multi_malloc(false,
2683
&upd_buff, upd_and_key_val_buff_len,
2684
&key_val_buff, upd_and_key_val_buff_len,
2691
/* We look for pattern #P# to see if the table is partitioned
2692
MySQL table. The retry logic for partitioned tables is a
2693
workaround for http://bugs.mysql.com/bug.php?id=33349. Look
2694
at support issue https://support.mysql.com/view.php?id=21080
2695
for more details. */
2696
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#");
2698
/* Get pointer to a table object in InnoDB dictionary cache */
2699
ib_table = dict_table_get(norm_name, TRUE);
2701
if (NULL == ib_table) {
2702
if (is_part && retries < 10) {
2704
os_thread_sleep(100000);
2709
errmsg_printf(ERRMSG_LVL_ERROR, "Failed to open table %s after "
2710
"%lu attemtps.\n", norm_name,
2714
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
2715
"the internal data dictionary of InnoDB "
2716
"though the .frm file for the\n"
2717
"table exists. Maybe you have deleted and "
2718
"recreated InnoDB data\n"
2719
"files but have forgotten to delete the "
2720
"corresponding .frm files\n"
2721
"of InnoDB tables, or you have moved .frm "
2722
"files to another database?\n"
2723
"or, the table contains indexes that this "
2724
"version of the engine\n"
2725
"doesn't support.\n"
2726
"See " REFMAN "innodb-troubleshooting.html\n"
2727
"how you can resolve the problem.\n",
2733
return(HA_ERR_NO_SUCH_TABLE);
2736
if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
2737
errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
2738
"the .ibd file for\ntable %s does not exist.\n"
2739
"Have you deleted the .ibd file from the "
2740
"database directory under\nthe MySQL datadir, "
2741
"or have you used DISCARD TABLESPACE?\n"
2742
"See " REFMAN "innodb-troubleshooting.html\n"
2743
"how you can resolve the problem.\n",
2749
dict_table_decrement_handle_count(ib_table, FALSE);
2750
return(HA_ERR_NO_SUCH_TABLE);
2753
prebuilt = row_create_prebuilt(ib_table);
2755
prebuilt->mysql_row_len = table->s->stored_rec_length;
2756
prebuilt->default_rec = table->s->default_values;
2757
ut_ad(prebuilt->default_rec);
2759
/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
2761
primary_key = table->s->primary_key;
2762
key_used_on_scan = primary_key;
2764
/* Allocate a buffer for a 'row reference'. A row reference is
2765
a string of bytes of length ref_length which uniquely specifies
2766
a row in our table. Note that MySQL may also compare two row
2767
references for equality by doing a simple memcmp on the strings
2768
of length ref_length! */
2770
if (!row_table_got_default_clust_index(ib_table)) {
2771
if (primary_key >= MAX_KEY) {
2772
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in InnoDB data "
2773
"dictionary, but not in MySQL!", name);
2776
prebuilt->clust_index_was_generated = FALSE;
2778
/* MySQL allocates the buffer for ref. key_info->key_length
2779
includes space for all key columns + one byte for each column
2780
that may be NULL. ref_length must be as exact as possible to
2781
save space, because all row reference buffers are allocated
2782
based on ref_length. */
2784
ref_length = table->key_info[primary_key].key_length;
2786
if (primary_key != MAX_KEY) {
2787
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has no primary key in InnoDB data "
2788
"dictionary, but has one in MySQL! If you "
2789
"created the table with a MySQL version < "
2790
"3.23.54 and did not define a primary key, "
2791
"but defined a unique key with all non-NULL "
2792
"columns, then MySQL internally treats that "
2793
"key as the primary key. You can fix this "
2794
"error by dump + DROP + CREATE + reimport "
2795
"of the table.", name);
2798
prebuilt->clust_index_was_generated = TRUE;
2800
ref_length = DATA_ROW_ID_LEN;
2802
/* If we automatically created the clustered index, then
2803
MySQL does not know about it, and MySQL must NOT be aware
2804
of the index used on scan, to make it avoid checking if we
2805
update the column of the index. That is why we assert below
2806
that key_used_on_scan is the undefined value MAX_KEY.
2807
The column is the row id in the automatical generation case,
2808
and it will never be updated anyway. */
2810
if (key_used_on_scan != MAX_KEY) {
2811
errmsg_printf(ERRMSG_LVL_WARN,
2812
"Table %s key_used_on_scan is %lu even "
2813
"though there is no primary key inside "
2814
"InnoDB.", name, (ulong) key_used_on_scan);
2818
/* Index block size in InnoDB: used by MySQL in query optimization */
2819
stats.block_size = 16 * 1024;
2821
/* Init table lock structure */
2822
thr_lock_data_init(&share->lock,&lock,(void*) 0);
2824
if (prebuilt->table) {
2825
/* We update the highest file format in the system table
2826
space, if this table has higher file format setting. */
2828
trx_sys_file_format_max_upgrade(
2829
(const char**) &innobase_file_format_check,
2830
dict_table_get_format(prebuilt->table));
2833
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
2835
/* Only if the table has an AUTOINC column. */
2836
if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
2839
dict_table_autoinc_lock(prebuilt->table);
2841
/* Since a table can already be "open" in InnoDB's internal
2842
data dictionary, we only init the autoinc counter once, the
2843
first time the table is loaded. We can safely reuse the
2844
autoinc value from a previous Drizzle open. */
2845
if (dict_table_autoinc_read(prebuilt->table) == 0) {
2847
error = innobase_initialize_autoinc();
2848
ut_a(error == DB_SUCCESS);
2851
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);
2859
2922
InnobaseEngine::max_supported_key_part_length() const
2861
return(DICT_MAX_INDEX_COL_LEN - 1);
2924
return(DICT_MAX_INDEX_COL_LEN - 1);
2864
2927
/******************************************************************//**
2865
2928
Closes a handle to an InnoDB table.
2869
2932
ha_innobase::close(void)
2870
2933
/*====================*/
2874
session = ha_session();
2875
if (session != NULL) {
2876
getTransactionalEngine()->releaseTemporaryLatches(session);
2879
row_prebuilt_free(prebuilt, FALSE);
2884
/* Tell InnoDB server that there might be work for
2887
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();
2892
2955
/* The following accessor functions should really be inside MySQL code! */
2894
2957
/**************************************************************//**
2895
2958
Gets field offset for a field in a table.
2899
2962
get_field_offset(
2900
2963
/*=============*/
2901
Table* table, /*!< in: MySQL table object */
2902
Field* field) /*!< in: MySQL field object */
2964
Table* table, /*!< in: MySQL table object */
2965
Field* field) /*!< in: MySQL field object */
2904
return((uint) (field->ptr - table->record[0]));
2967
return((uint) (field->ptr - table->record[0]));
2907
2970
/**************************************************************//**
2908
2971
Checks if a field in a record is SQL NULL. Uses the record format
2909
2972
information in table to track the null bit in record.
2910
@return 1 if NULL, 0 otherwise */
2973
@return 1 if NULL, 0 otherwise */
2913
2976
field_in_record_is_null(
2914
2977
/*====================*/
2915
Table* table, /*!< in: MySQL table object */
2916
Field* field, /*!< in: MySQL field object */
2917
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 */
2921
if (!field->null_ptr) {
2926
null_offset = (uint) ((char*) field->null_ptr
2927
- (char*) table->record[0]);
2929
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) {
2937
3000
/**************************************************************//**
2958
3021
is such that we must use MySQL code to compare them. NOTE that the prototype
2959
3022
of this function is in rem0cmp.c in InnoDB source code! If you change this
2960
3023
function, remember to update the prototype there!
2961
@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 */
2962
3025
extern "C" UNIV_INTERN
2964
3027
innobase_mysql_cmp(
2965
3028
/*===============*/
2966
int mysql_type, /*!< in: MySQL type */
2967
uint charset_number, /*!< in: number of the charset */
2968
const unsigned char* a, /*!< in: data field */
2969
unsigned int a_length, /*!< in: data field length,
2970
not UNIV_SQL_NULL */
2971
const unsigned char* b, /* in: data field */
2972
unsigned int b_length); /* in: data field length,
2973
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 */
2976
3039
innobase_mysql_cmp(
2977
3040
/*===============*/
2978
/* out: 1, 0, -1, if a is greater,
2979
equal, less than b, respectively */
2980
int mysql_type, /* in: MySQL type */
2981
uint charset_number, /* in: number of the charset */
2982
const unsigned char* a, /* in: data field */
2983
unsigned int a_length, /* in: data field length,
2984
not UNIV_SQL_NULL */
2985
const unsigned char* b, /* in: data field */
2986
unsigned int b_length) /* in: data field length,
2987
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 */
2989
const CHARSET_INFO* charset;
2990
enum_field_types mysql_tp;
2993
assert(a_length != UNIV_SQL_NULL);
2994
assert(b_length != UNIV_SQL_NULL);
2996
mysql_tp = (enum_field_types) mysql_type;
3000
case DRIZZLE_TYPE_BLOB:
3001
case DRIZZLE_TYPE_VARCHAR:
3002
/* Use the charset number to pick the right charset struct for
3003
the comparison. Since the MySQL function get_charset may be
3004
slow before Bar removes the mutex operation there, we first
3005
look at 2 common charsets directly. */
3007
if (charset_number == default_charset_info->number) {
3008
charset = default_charset_info;
3010
charset = get_charset(charset_number);
3012
if (charset == NULL) {
3013
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
3014
"a comparison, but MySQL cannot "
3015
"find that charset.",
3016
(ulong) charset_number);
3021
/* Starting from 4.1.3, we use strnncollsp() in comparisons of
3022
non-latin1_swedish_ci strings. NOTE that the collation order
3023
changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users
3024
having indexes on such data need to rebuild their tables! */
3026
ret = charset->coll->strnncollsp(charset,
3031
} 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) {
3043
3106
/**************************************************************//**
3044
3107
Converts a MySQL type to an InnoDB type. Note that this function returns
3045
3108
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
3046
3109
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'.
3047
@return DATA_BINARY, DATA_VARCHAR, ... */
3110
@return DATA_BINARY, DATA_VARCHAR, ... */
3048
3111
extern "C" UNIV_INTERN
3050
3113
get_innobase_type_from_mysql_type(
3051
3114
/*==============================*/
3052
ulint* unsigned_flag, /*!< out: DATA_UNSIGNED if an
3054
at least ENUM and SET,
3055
and unsigned integer
3056
types are 'unsigned types' */
3057
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 */
3059
const class Field* field = reinterpret_cast<const class Field*>(f);
3061
/* The following asserts try to check that the MySQL type code fits in
3062
8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
3065
assert((ulint)DRIZZLE_TYPE_DOUBLE < 256);
3067
if (field->flags & UNSIGNED_FLAG) {
3069
*unsigned_flag = DATA_UNSIGNED;
3074
if (field->real_type() == DRIZZLE_TYPE_ENUM)
3076
/* MySQL has field->type() a string type for these, but the
3077
data is actually internally stored as an unsigned integer
3080
*unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
3081
flag set to zero, even though
3082
internally this is an unsigned
3087
switch (field->type()) {
3088
/* NOTE that we only allow string types in DATA_DRIZZLE and
3090
case DRIZZLE_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */
3091
if (field->binary()) {
3092
return(DATA_BINARY);
3094
return(DATA_VARMYSQL);
3096
case DRIZZLE_TYPE_DECIMAL:
3097
return(DATA_FIXBINARY);
3098
case DRIZZLE_TYPE_LONG:
3099
case DRIZZLE_TYPE_LONGLONG:
3100
case DRIZZLE_TYPE_DATETIME:
3101
case DRIZZLE_TYPE_DATE:
3102
case DRIZZLE_TYPE_TIMESTAMP:
3104
case DRIZZLE_TYPE_DOUBLE:
3105
return(DATA_DOUBLE);
3106
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:
3107
3170
return(DATA_BLOB);
3115
3178
/*******************************************************************//**
3120
3183
innobase_write_to_2_little_endian(
3121
3184
/*==============================*/
3122
byte* buf, /*!< in: where to store */
3123
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 */
3125
ut_a(val < 256 * 256);
3188
ut_a(val < 256 * 256);
3127
buf[0] = (byte)(val & 0xFF);
3128
buf[1] = (byte)(val / 256);
3190
buf[0] = (byte)(val & 0xFF);
3191
buf[1] = (byte)(val / 256);
3131
3194
/*******************************************************************//**
3132
3195
Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
3133
3196
storage format.
3137
3200
innobase_read_from_2_little_endian(
3138
3201
/*===============================*/
3139
const unsigned char* buf) /*!< in: from where to read */
3202
const unsigned char* buf) /*!< in: from where to read */
3141
return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
3204
return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
3144
3207
/*******************************************************************//**
3145
3208
Stores a key value for a row to a buffer.
3146
@return key value length as stored in buff */
3209
@return key value length as stored in buff */
3149
3212
ha_innobase::store_key_val_for_row(
3150
3213
/*===============================*/
3151
uint keynr, /*!< in: key number */
3152
char* buff, /*!< in/out: buffer for the key value (in MySQL
3154
uint buff_len,/*!< in: buffer length */
3155
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 */
3157
KEY* key_info = table->key_info + keynr;
3158
KEY_PART_INFO* key_part = key_info->key_part;
3159
KEY_PART_INFO* end = key_part + key_info->key_parts;
3160
char* buff_start = buff;
3161
enum_field_types mysql_type;
3165
/* The format for storing a key field in MySQL is the following:
3167
1. If the column can be NULL, then in the first byte we put 1 if the
3168
field value is NULL, 0 otherwise.
3170
2. If the column is of a BLOB type (it must be a column prefix field
3171
in this case), then we put the length of the data in the field to the
3172
next 2 bytes, in the little-endian format. If the field is SQL NULL,
3173
then these 2 bytes are set to 0. Note that the length of data in the
3174
field is <= column prefix length.
3176
3. In a column prefix field, prefix_len next bytes are reserved for
3177
data. In a normal field the max field length next bytes are reserved
3178
for data. For a VARCHAR(n) the max field length is n. If the stored
3179
value is the SQL NULL then these data bytes are set to 0.
3181
4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
3182
in the MySQL row format, the length is stored in 1 or 2 bytes,
3183
depending on the maximum allowed length. But in the MySQL key value
3184
format, the length always takes 2 bytes.
3186
We have to zero-fill the buffer so that MySQL is able to use a
3187
simple memcmp to compare two key values to determine if they are
3188
equal. MySQL does this to compare contents of two 'ref' values. */
3190
bzero(buff, buff_len);
3192
for (; key_part != end; key_part++) {
3195
if (key_part->null_bit) {
3196
if (record[key_part->null_offset]
3197
& key_part->null_bit) {
3206
field = key_part->field;
3207
mysql_type = field->type();
3209
if (mysql_type == DRIZZLE_TYPE_VARCHAR) {
3210
/* >= 5.0.3 true VARCHAR */
3216
const CHARSET_INFO* cs;
3219
key_len = key_part->length;
3222
buff += key_len + 2;
3226
cs = field->charset();
3229
(((Field_varstring*)field)->length_bytes);
3231
data = row_mysql_read_true_varchar(&len,
3233
+ (ulint)get_field_offset(table, field)),
3238
/* For multi byte character sets we need to calculate
3239
the true length of the key */
3241
if (len > 0 && cs->mbmaxlen > 1) {
3242
true_len = (ulint) cs->cset->well_formed_len(cs,
3243
(const char *) data,
3244
(const char *) data + len,
3250
/* In a column prefix index, we may need to truncate
3251
the stored value: */
3253
if (true_len > key_len) {
3257
/* The length in a key value is always stored in 2
3260
row_mysql_store_true_var_len((byte*)buff, true_len, 2);
3263
memcpy(buff, data, true_len);
3265
/* Note that we always reserve the maximum possible
3266
length of the true VARCHAR in the key value, though
3267
only len first bytes after the 2 length bytes contain
3268
actual data. The rest of the space was reset to zero
3269
in the bzero() call above. */
3273
} else if (mysql_type == DRIZZLE_TYPE_BLOB) {
3275
const CHARSET_INFO* cs;
3280
const byte* blob_data;
3282
ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
3284
key_len = key_part->length;
3287
buff += key_len + 2;
3292
cs = field->charset();
3294
blob_data = row_mysql_read_blob_ref(&blob_len,
3296
+ (ulint)get_field_offset(table, field)),
3297
(ulint) field->pack_length());
3299
true_len = blob_len;
3301
ut_a(get_field_offset(table, field)
3302
== key_part->offset);
3304
/* For multi byte character sets we need to calculate
3305
the true length of the key */
3307
if (blob_len > 0 && cs->mbmaxlen > 1) {
3308
true_len = (ulint) cs->cset->well_formed_len(cs,
3309
(const char *) blob_data,
3310
(const char *) blob_data
3317
/* All indexes on BLOB and TEXT are column prefix
3318
indexes, and we may need to truncate the data to be
3319
stored in the key value: */
3321
if (true_len > key_len) {
3325
/* MySQL reserves 2 bytes for the length and the
3326
storage of the number is little-endian */
3328
innobase_write_to_2_little_endian(
3329
(byte*)buff, true_len);
3332
memcpy(buff, blob_data, true_len);
3334
/* Note that we always reserve the maximum possible
3335
length of the BLOB prefix in the key value. */
3339
/* Here we handle all other data types except the
3340
true VARCHAR, BLOB and TEXT. Note that the column
3341
value we store may be also in a column prefix
3346
const unsigned char* src_start;
3347
enum_field_types real_type;
3349
key_len = key_part->length;
3357
src_start = record + key_part->offset;
3358
real_type = field->real_type();
3361
/* Character set for the field is defined only
3362
to fields whose type is string and real field
3363
type is not enum or set. For these fields check
3364
if character set is multi byte. */
3366
memcpy(buff, src_start, true_len);
3369
/* Pad the unused space with spaces. Note that no
3370
padding is ever needed for UCS-2 because in MySQL,
3371
all UCS2 characters are 2 bytes, as MySQL does not
3372
support surrogate pairs, which are needed to represent
3373
characters in the range U+10000 to U+10FFFF. */
3375
if (true_len < key_len) {
3376
ulint pad_len = key_len - true_len;
3377
memset(buff, ' ', pad_len);
3383
ut_a(buff <= buff_start + buff_len);
3385
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));
3388
3451
/**************************************************************//**
3393
3456
build_template(
3394
3457
/*===========*/
3395
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */
3396
Session* , /*!< in: current user thread, used
3397
only if templ_type is
3398
ROW_DRIZZLE_REC_FIELDS */
3399
Table* table, /*!< in: MySQL table */
3400
uint templ_type) /*!< in: ROW_MYSQL_WHOLE_ROW or
3401
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 */
3403
dict_index_t* index;
3404
dict_index_t* clust_index;
3405
mysql_row_templ_t* templ;
3408
ulint n_requested_fields = 0;
3409
ibool fetch_all_in_key = FALSE;
3410
ibool fetch_primary_key_cols = FALSE;
3412
/* byte offset of the end of last requested column */
3413
ulint mysql_prefix_len = 0;
3415
if (prebuilt->select_lock_type == LOCK_X) {
3416
/* We always retrieve the whole clustered index record if we
3417
use exclusive row level locks, for example, if the read is
3418
done in an UPDATE statement. */
3420
templ_type = ROW_MYSQL_WHOLE_ROW;
3423
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3424
if (prebuilt->hint_need_to_fetch_extra_cols
3425
== ROW_RETRIEVE_ALL_COLS) {
3427
/* We know we must at least fetch all columns in the
3428
key, or all columns in the table */
3430
if (prebuilt->read_just_key) {
3431
/* MySQL has instructed us that it is enough
3432
to fetch the columns in the key; looks like
3433
MySQL can set this flag also when there is
3434
only a prefix of the column in the key: in
3435
that case we retrieve the whole column from
3436
the clustered index */
3438
fetch_all_in_key = TRUE;
3440
templ_type = ROW_MYSQL_WHOLE_ROW;
3442
} else if (prebuilt->hint_need_to_fetch_extra_cols
3443
== ROW_RETRIEVE_PRIMARY_KEY) {
3444
/* We must at least fetch all primary key cols. Note
3445
that if the clustered index was internally generated
3446
by InnoDB on the row id (no primary key was
3447
defined), then row_search_for_mysql() will always
3448
retrieve the row id to a special buffer in the
3451
fetch_primary_key_cols = TRUE;
3455
clust_index = dict_table_get_first_index(prebuilt->table);
3457
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3458
index = prebuilt->index;
3460
index = clust_index;
3463
if (index == clust_index) {
3464
prebuilt->need_to_access_clustered = TRUE;
3466
prebuilt->need_to_access_clustered = FALSE;
3467
/* Below we check column by column if we need to access
3468
the clustered index */
3471
n_fields = (ulint)table->s->fields; /* number of columns */
3473
if (!prebuilt->mysql_template) {
3474
prebuilt->mysql_template = (mysql_row_templ_t*)
3475
mem_alloc(n_fields * sizeof(mysql_row_templ_t));
3478
prebuilt->template_type = templ_type;
3479
prebuilt->null_bitmap_len = table->s->null_bytes;
3481
prebuilt->templ_contains_blob = FALSE;
3483
/* Note that in InnoDB, i is the column number. MySQL calls columns
3485
for (i = 0; i < n_fields; i++) {
3486
templ = prebuilt->mysql_template + n_requested_fields;
3487
field = table->field[i];
3489
if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
3490
/* Decide which columns we should fetch
3491
and which we can skip. */
3492
register const ibool index_contains_field =
3493
dict_index_contains_col_or_prefix(index, i);
3495
if (!index_contains_field && prebuilt->read_just_key) {
3496
/* If this is a 'key read', we do not need
3497
columns that are not in the key */
3502
if (index_contains_field && fetch_all_in_key) {
3503
/* 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 */
3508
3571
if (field->isReadSet() || field->isWriteSet())
3509
/* This field is needed in the query */
3572
/* This field is needed in the query */
3512
3575
assert(table->isReadSet(i) == field->isReadSet());
3513
3576
assert(table->isWriteSet(i) == field->isWriteSet());
3515
if (fetch_primary_key_cols
3516
&& dict_table_col_in_clustered_key(
3518
/* This field is needed in the query */
3523
/* 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 */
3528
n_requested_fields++;
3532
if (index == clust_index) {
3533
templ->rec_field_no = dict_col_get_clust_pos(
3534
&index->table->cols[i], index);
3536
templ->rec_field_no = dict_index_get_nth_col_pos(
3540
if (templ->rec_field_no == ULINT_UNDEFINED) {
3541
prebuilt->need_to_access_clustered = TRUE;
3544
if (field->null_ptr) {
3545
templ->mysql_null_byte_offset =
3546
(ulint) ((char*) field->null_ptr
3547
- (char*) table->record[0]);
3549
templ->mysql_null_bit_mask = (ulint) field->null_bit;
3551
templ->mysql_null_bit_mask = 0;
3554
templ->mysql_col_offset = (ulint)
3555
get_field_offset(table, field);
3557
templ->mysql_col_len = (ulint) field->pack_length();
3558
if (mysql_prefix_len < templ->mysql_col_offset
3559
+ templ->mysql_col_len) {
3560
mysql_prefix_len = templ->mysql_col_offset
3561
+ templ->mysql_col_len;
3563
templ->type = index->table->cols[i].mtype;
3564
templ->mysql_type = (ulint)field->type();
3566
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
3567
templ->mysql_length_bytes = (ulint)
3568
(((Field_varstring*)field)->length_bytes);
3571
templ->charset = dtype_get_charset_coll(
3572
index->table->cols[i].prtype);
3573
templ->mbminlen = index->table->cols[i].mbminlen;
3574
templ->mbmaxlen = index->table->cols[i].mbmaxlen;
3575
templ->is_unsigned = index->table->cols[i].prtype
3577
if (templ->type == DATA_BLOB) {
3578
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;
3584
prebuilt->n_template = n_requested_fields;
3585
prebuilt->mysql_prefix_len = mysql_prefix_len;
3587
if (index != clust_index && prebuilt->need_to_access_clustered) {
3588
/* Change rec_field_no's to correspond to the clustered index
3590
for (i = 0; i < n_requested_fields; i++) {
3591
templ = prebuilt->mysql_template + i;
3593
templ->rec_field_no = dict_col_get_clust_pos(
3594
&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],
3600
3663
/********************************************************************//**
3647
3710
INSERT ... SELECT type of statements, since MySQL binlog only stores the
3648
3711
min value of the autoinc interval. Once that is fixed we can get rid of
3649
3712
the special lock handling.
3650
@return DB_SUCCESS if all OK else error code */
3713
@return DB_SUCCESS if all OK else error code */
3653
3716
ha_innobase::innobase_lock_autoinc(void)
3654
3717
/*====================================*/
3656
ulint error = DB_SUCCESS;
3658
switch (innobase_autoinc_lock_mode) {
3659
case AUTOINC_NO_LOCKING:
3660
/* Acquire only the AUTOINC mutex. */
3661
dict_table_autoinc_lock(prebuilt->table);
3664
case AUTOINC_NEW_STYLE_LOCKING:
3665
/* For simple (single/multi) row INSERTs, we fallback to the
3666
old style only if another transaction has already acquired
3667
the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
3668
etc. type of statement. */
3669
if (session_sql_command(user_session) == SQLCOM_INSERT
3670
|| session_sql_command(user_session) == SQLCOM_REPLACE) {
3671
dict_table_t* d_table = prebuilt->table;
3673
/* Acquire the AUTOINC mutex. */
3674
dict_table_autoinc_lock(d_table);
3676
/* We need to check that another transaction isn't
3677
already holding the AUTOINC lock on the table. */
3678
if (d_table->n_waiting_or_granted_auto_inc_locks) {
3679
/* Release the mutex to avoid deadlocks. */
3680
dict_table_autoinc_unlock(d_table);
3685
/* Fall through to old style locking. */
3687
case AUTOINC_OLD_STYLE_LOCKING:
3688
error = row_lock_table_autoinc_for_mysql(prebuilt);
3690
if (error == DB_SUCCESS) {
3692
/* Acquire the AUTOINC mutex. */
3693
dict_table_autoinc_lock(prebuilt->table);
3701
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));
3704
3767
/********************************************************************//**
3705
3768
Reset the autoinc value in the table.
3706
@return DB_SUCCESS if all went well else error code */
3769
@return DB_SUCCESS if all went well else error code */
3709
3772
ha_innobase::innobase_reset_autoinc(
3710
3773
/*================================*/
3711
uint64_t autoinc) /*!< in: value to store */
3774
uint64_t autoinc) /*!< in: value to store */
3715
error = innobase_lock_autoinc();
3717
if (error == DB_SUCCESS) {
3719
dict_table_autoinc_initialize(prebuilt->table, autoinc);
3721
dict_table_autoinc_unlock(prebuilt->table);
3724
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));
3727
3790
/********************************************************************//**
3728
3791
Store the autoinc value in the table. The autoinc value is only set if
3729
3792
it's greater than the existing autoinc value in the table.
3730
@return DB_SUCCESS if all went well else error code */
3793
@return DB_SUCCESS if all went well else error code */
3733
3796
ha_innobase::innobase_set_max_autoinc(
3734
3797
/*==================================*/
3735
uint64_t auto_inc) /*!< in: value to store */
3798
uint64_t auto_inc) /*!< in: value to store */
3739
error = innobase_lock_autoinc();
3741
if (error == DB_SUCCESS) {
3743
dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
3745
dict_table_autoinc_unlock(prebuilt->table);
3748
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));
3751
3814
/********************************************************************//**
3752
3815
Stores a row in an InnoDB database, to the table specified in this
3754
@return error code */
3817
@return error code */
3757
3820
ha_innobase::write_row(
3758
3821
/*===================*/
3759
unsigned char* record) /*!< in: a row in MySQL format */
3822
unsigned char* record) /*!< in: a row in MySQL format */
3762
3825
int error_result= 0;
3763
ibool auto_inc_used= FALSE;
3765
trx_t* trx = session_to_trx(user_session);
3767
if (prebuilt->trx != trx) {
3768
errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
3769
"%p, but for the current thread it is at %p",
3770
(const void*) prebuilt->trx, (const void*) trx);
3772
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
3773
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
3775
"InnoDB: Dump of 200 bytes around ha_data: ",
3777
ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
3782
ha_statistic_increment(&system_status_var::ha_write_count);
3784
sql_command = session_sql_command(user_session);
3786
if ((sql_command == SQLCOM_ALTER_TABLE
3787
|| sql_command == SQLCOM_CREATE_INDEX
3788
|| sql_command == SQLCOM_DROP_INDEX)
3789
&& num_write_row >= 10000) {
3790
/* ALTER TABLE is COMMITted at every 10000 copied rows.
3791
The IX table lock for the original table has to be re-issued.
3792
As this method will be called on a temporary table where the
3793
contents of the original table is being copied to, it is
3794
a bit tricky to determine the source table. The cursor
3795
position in the source table need not be adjusted after the
3796
intermediate COMMIT, since writes by other transactions are
3797
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
3799
dict_table_t* src_table;
3800
enum lock_mode mode;
3804
/* Commit the transaction. This will release the table
3805
locks, so they have to be acquired again. */
3807
/* Altering an InnoDB table */
3808
/* Get the source table. */
3809
src_table = lock_get_src_table(
3810
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);
3813
/* Unknown situation: do not commit */
3815
ut_print_timestamp(stderr);
3817
" InnoDB: ALTER TABLE is holding lock"
3818
" on %lu tables!\n",
3819
prebuilt->trx->mysql_n_tables_locked);
3822
} else if (src_table == prebuilt->table) {
3823
/* Source table is not in InnoDB format:
3824
no need to re-acquire locks on it. */
3826
/* Altering to InnoDB format */
3827
getTransactionalEngine()->commit(user_session, 1);
3828
/* We will need an IX lock on the destination table. */
3829
prebuilt->sql_stat_start = TRUE;
3831
/* Ensure that there are no other table locks than
3832
LOCK_IX and LOCK_AUTO_INC on the destination table. */
3834
if (!lock_is_table_exclusive(prebuilt->table,
3839
/* Commit the transaction. This will release the table
3840
locks, so they have to be acquired again. */
3841
getTransactionalEngine()->commit(user_session, 1);
3842
/* Re-acquire the table lock on the source table. */
3843
row_lock_table_for_mysql(prebuilt, src_table, mode);
3844
/* We will need an IX lock on the destination table. */
3845
prebuilt->sql_stat_start = TRUE;
3851
/* This is the case where the table has an auto-increment column */
3852
if (table->next_number_field && record == table->record[0]) {
3854
/* Reset the error code before calling
3855
innobase_get_auto_increment(). */
3856
prebuilt->autoinc_error = DB_SUCCESS;
3858
if ((error = update_auto_increment())) {
3860
/* We don't want to mask autoinc overflow errors. */
3861
if (prebuilt->autoinc_error != DB_SUCCESS) {
3862
error = (int) prebuilt->autoinc_error;
3867
/* MySQL errors are passed straight back. */
3868
error_result = (int) error;
3872
auto_inc_used = TRUE;
3875
if (prebuilt->mysql_template == NULL
3876
|| prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
3878
/* Build the template used in converting quickly between
3879
the two database formats */
3881
build_template(prebuilt, NULL, table,
3882
ROW_MYSQL_WHOLE_ROW);
3885
innodb_srv_conc_enter_innodb(prebuilt->trx);
3887
error = row_insert_for_mysql((byte*) record, prebuilt);
3889
/* Handle duplicate key errors */
3890
if (auto_inc_used) {
3893
uint64_t col_max_value;
3895
/* Note the number of rows processed for this statement, used
3896
by get_auto_increment() to determine the number of AUTO-INC
3897
values to reserve. This is only useful for a mult-value INSERT
3898
and is a statement level counter.*/
3899
if (trx->n_autoinc_rows > 0) {
3900
--trx->n_autoinc_rows;
3903
/* We need the upper limit of the col type to check for
3904
whether we update the table autoinc counter or not. */
3905
col_max_value = innobase_get_int_col_max_value(
3906
table->next_number_field);
3908
/* Get the value that MySQL attempted to store in the table.*/
3909
auto_inc = table->next_number_field->val_int();
3912
case DB_DUPLICATE_KEY:
3914
/* A REPLACE command and LOAD DATA INFILE REPLACE
3915
handle a duplicate key error themselves, but we
3916
must update the autoinc counter if we are performing
3917
those statements. */
3919
switch (sql_command) {
3921
if ((trx->duplicates
3922
& (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
3924
goto set_max_autoinc;
3928
case SQLCOM_REPLACE:
3929
case SQLCOM_INSERT_SELECT:
3930
case SQLCOM_REPLACE_SELECT:
3931
goto set_max_autoinc;
3940
/* If the actual value inserted is greater than
3941
the upper limit of the interval, then we try and
3942
update the table upper limit. Note: last_value
3943
will be 0 if get_auto_increment() was not called.*/
3945
if (auto_inc <= col_max_value
3946
&& 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) {
3947
4010
set_max_autoinc:
3948
ut_a(prebuilt->autoinc_increment > 0);
3953
offset = prebuilt->autoinc_offset;
3954
need = prebuilt->autoinc_increment;
3956
auto_inc = innobase_next_autoinc(
3957
auto_inc, need, offset, col_max_value);
3959
err = innobase_set_max_autoinc(auto_inc);
3961
if (err != DB_SUCCESS) {
3969
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);
3972
error_result = convert_error_code_to_mysql((int) error,
3973
prebuilt->table->flags,
4035
error_result = convert_error_code_to_mysql((int) error,
4036
prebuilt->table->flags,
3977
innobase_active_small();
4040
innobase_active_small();
3979
return(error_result);
4042
return(error_result);
3982
4045
/**********************************************************************//**
3983
4046
Checks which fields have changed in a row and stores information
3984
4047
of them to an update vector.
3985
@return error number or 0 */
4048
@return error number or 0 */
3988
4051
calc_row_difference(
3989
4052
/*================*/
3990
upd_t* uvect, /*!< in/out: update vector */
3991
unsigned char* old_row, /*!< in: old row in MySQL format */
3992
unsigned char* new_row, /*!< in: new row in MySQL format */
3993
Table* table, /*!< in: table in MySQL data
3995
unsigned char* upd_buff, /*!< in: buffer to use */
3996
ulint buff_len, /*!< in: buffer length */
3997
row_prebuilt_t* prebuilt, /*!< in: InnoDB prebuilt struct */
3998
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 */
4000
unsigned char* original_upd_buff = upd_buff;
4002
enum_field_types field_mysql_type;
4007
const byte* new_mysql_row_col;
4011
upd_field_t* ufield;
4013
ulint n_changed = 0;
4015
dict_index_t* clust_index;
4018
n_fields = table->s->fields;
4019
clust_index = dict_table_get_first_index(prebuilt->table);
4021
/* We use upd_buff to convert changed fields */
4022
buf = (byte*) upd_buff;
4024
for (i = 0; i < n_fields; i++) {
4025
field = table->field[i];
4027
o_ptr = (const byte*) old_row + get_field_offset(table, field);
4028
n_ptr = (const byte*) new_row + get_field_offset(table, field);
4030
/* Use new_mysql_row_col and col_pack_len save the values */
4032
new_mysql_row_col = n_ptr;
4033
col_pack_len = field->pack_length();
4035
o_len = col_pack_len;
4036
n_len = col_pack_len;
4038
/* We use o_ptr and n_ptr to dig up the actual data for
4041
field_mysql_type = field->type();
4043
col_type = prebuilt->table->cols[i].mtype;
4048
o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
4049
n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
4056
if (field_mysql_type == DRIZZLE_TYPE_VARCHAR) {
4057
/* This is a >= 5.0.3 type true VARCHAR where
4058
the real payload data length is stored in
4061
o_ptr = row_mysql_read_true_varchar(
4064
(((Field_varstring*)field)->length_bytes));
4066
n_ptr = row_mysql_read_true_varchar(
4069
(((Field_varstring*)field)->length_bytes));
4077
if (field->null_ptr) {
4078
if (field_in_record_is_null(table, field,
4080
o_len = UNIV_SQL_NULL;
4083
if (field_in_record_is_null(table, field,
4085
n_len = UNIV_SQL_NULL;
4089
if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
4090
0 != memcmp(o_ptr, n_ptr, o_len))) {
4091
/* The field has changed */
4093
ufield = uvect->fields + n_changed;
4095
/* Let us use a dummy dfield to make the conversion
4096
from the MySQL column format to the InnoDB format */
4098
dict_col_copy_type(prebuilt->table->cols + i,
4101
if (n_len != UNIV_SQL_NULL) {
4102
buf = row_mysql_store_col_in_innobase_format(
4108
dict_table_is_comp(prebuilt->table));
4109
dfield_copy_data(&ufield->new_val, &dfield);
4111
dfield_set_null(&ufield->new_val);
4115
ufield->orig_len = 0;
4116
ufield->field_no = dict_col_get_clust_pos(
4117
&prebuilt->table->cols[i], clust_index);
4122
uvect->n_fields = n_changed;
4123
uvect->info_bits = 0;
4125
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);
4130
4193
/**********************************************************************//**
4134
4197
TODO: currently InnoDB does not prevent the 'Halloween problem':
4135
4198
in a searched update a single row can get updated several times
4136
4199
if its index columns are updated!
4137
@return error number or 0 */
4200
@return error number or 0 */
4140
4203
ha_innobase::update_row(
4141
4204
/*====================*/
4142
const unsigned char* old_row,/*!< in: old row in MySQL format */
4143
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 */
4147
trx_t* trx = session_to_trx(user_session);
4149
ut_a(prebuilt->trx == trx);
4151
ha_statistic_increment(&system_status_var::ha_update_count);
4153
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
4154
table->timestamp_field->set_time();
4156
if (prebuilt->upd_node) {
4157
uvect = prebuilt->upd_node->update;
4159
uvect = row_get_prebuilt_update_vector(prebuilt);
4162
/* Build an update vector from the modified fields in the rows
4163
(uses upd_buff of the handle) */
4165
calc_row_difference(uvect, (unsigned char*) old_row, new_row, table,
4166
upd_buff, (ulint)upd_and_key_val_buff_len,
4167
prebuilt, user_session);
4169
/* This is not a delete */
4170
prebuilt->upd_node->is_delete = FALSE;
4172
ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
4174
innodb_srv_conc_enter_innodb(trx);
4176
error = row_update_for_mysql((byte*) old_row, prebuilt);
4178
/* We need to do some special AUTOINC handling for the following case:
4180
INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
4182
We need to use the AUTOINC counter that was actually used by
4183
MySQL in the UPDATE statement, which can be different from the
4184
value used in the INSERT statement.*/
4186
if (error == DB_SUCCESS
4187
&& table->next_number_field
4188
&& new_row == table->record[0]
4189
&& session_sql_command(user_session) == SQLCOM_INSERT
4190
&& (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4191
== TRX_DUP_IGNORE) {
4194
uint64_t col_max_value;
4196
auto_inc = table->next_number_field->val_int();
4198
/* We need the upper limit of the col type to check for
4199
whether we update the table autoinc counter or not. */
4200
col_max_value = innobase_get_int_col_max_value(
4201
table->next_number_field);
4203
if (auto_inc <= col_max_value && auto_inc != 0) {
4208
offset = prebuilt->autoinc_offset;
4209
need = prebuilt->autoinc_increment;
4211
auto_inc = innobase_next_autoinc(
4212
auto_inc, need, offset, col_max_value);
4214
error = innobase_set_max_autoinc(auto_inc);
4218
innodb_srv_conc_exit_innodb(trx);
4220
error = convert_error_code_to_mysql(error,
4221
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,
4224
if (error == 0 /* success */
4225
&& uvect->n_fields == 0 /* no columns were updated */) {
4227
/* This is the same as success, but instructs
4228
MySQL that the row is not really updated and it
4229
should not increase the count of updated rows.
4230
This is fix for http://bugs.mysql.com/29157 */
4231
error = HA_ERR_RECORD_IS_THE_SAME;
4234
/* Tell InnoDB server that there might be work for
4237
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();
4242
4305
/**********************************************************************//**
4243
4306
Deletes a row given as the parameter.
4244
@return error number or 0 */
4307
@return error number or 0 */
4247
4310
ha_innobase::delete_row(
4248
4311
/*====================*/
4249
const unsigned char* record) /*!< in: a row in MySQL format */
4312
const unsigned char* record) /*!< in: a row in MySQL format */
4252
trx_t* trx = session_to_trx(user_session);
4254
ut_a(prebuilt->trx == trx);
4256
ha_statistic_increment(&system_status_var::ha_delete_count);
4258
if (!prebuilt->upd_node) {
4259
row_get_prebuilt_update_vector(prebuilt);
4262
/* This is a delete */
4264
prebuilt->upd_node->is_delete = TRUE;
4266
innodb_srv_conc_enter_innodb(trx);
4268
error = row_update_for_mysql((byte*) record, prebuilt);
4270
innodb_srv_conc_exit_innodb(trx);
4272
error = convert_error_code_to_mysql(
4273
error, prebuilt->table->flags, user_session);
4275
/* Tell the InnoDB server that there might be work for
4278
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();
4283
4346
/**********************************************************************//**
4489
4552
/**********************************************************************//**
4490
4553
Positions an index cursor to the index specified in the handle. Fetches the
4492
@return 0, HA_ERR_KEY_NOT_FOUND, or error number */
4555
@return 0, HA_ERR_KEY_NOT_FOUND, or error number */
4495
4558
ha_innobase::index_read(
4496
4559
/*====================*/
4497
unsigned char* buf, /*!< in/out: buffer for the returned
4499
const unsigned char* key_ptr,/*!< in: key value; if this is NULL
4500
we position the cursor at the
4501
start or end of index; this can
4502
also contain an InnoDB row id, in
4503
which case key_len is the InnoDB
4504
row id length; the key value can
4505
also be a prefix of a full key value,
4506
and the last column can be a prefix
4508
uint key_len,/*!< in: key value length */
4509
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 */
4512
dict_index_t* index;
4513
ulint match_mode = 0;
4517
ut_a(prebuilt->trx == session_to_trx(user_session));
4519
ha_statistic_increment(&system_status_var::ha_read_key_count);
4521
index = prebuilt->index;
4523
/* Note that if the index for which the search template is built is not
4524
necessarily prebuilt->index, but can also be the clustered index */
4526
if (prebuilt->sql_stat_start) {
4527
build_template(prebuilt, user_session, table,
4528
ROW_MYSQL_REC_FIELDS);
4532
/* Convert the search key value to InnoDB format into
4533
prebuilt->search_tuple */
4535
row_sel_convert_mysql_key_to_innobase(
4536
prebuilt->search_tuple,
4537
(byte*) key_val_buff,
4538
(ulint)upd_and_key_val_buff_len,
4544
/* We position the cursor to the last or the first entry
4547
dtuple_set_n_fields(prebuilt->search_tuple, 0);
4550
mode = convert_search_mode_to_innobase(find_flag);
4554
if (find_flag == HA_READ_KEY_EXACT) {
4556
match_mode = ROW_SEL_EXACT;
4558
} else if (find_flag == HA_READ_PREFIX
4559
|| find_flag == HA_READ_PREFIX_LAST) {
4561
match_mode = ROW_SEL_EXACT_PREFIX;
4564
last_match_mode = (uint) match_mode;
4566
if (mode != PAGE_CUR_UNSUPP) {
4568
innodb_srv_conc_enter_innodb(prebuilt->trx);
4570
ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
4573
innodb_srv_conc_exit_innodb(prebuilt->trx);
4576
ret = DB_UNSUPPORTED;
4584
case DB_RECORD_NOT_FOUND:
4585
error = HA_ERR_KEY_NOT_FOUND;
4586
table->status = STATUS_NOT_FOUND;
4588
case DB_END_OF_INDEX:
4589
error = HA_ERR_KEY_NOT_FOUND;
4590
table->status = STATUS_NOT_FOUND;
4593
error = convert_error_code_to_mysql((int) ret,
4594
prebuilt->table->flags,
4596
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;
4603
4666
/*******************************************************************//**
4604
4667
The following functions works like index_read, but it find the last
4605
4668
row with the current key value or prefix.
4606
@return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
4669
@return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
4609
4672
ha_innobase::index_read_last(
4610
4673
/*=========================*/
4611
unsigned char* buf, /*!< out: fetched row */
4612
const unsigned char* key_ptr,/*!< in: key value, or a prefix of a full
4614
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
4617
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));
4620
4683
/********************************************************************//**
4621
4684
Get the index for a handle. Does not change active index.
4622
@return NULL or index instance. */
4685
@return NULL or index instance. */
4625
4688
ha_innobase::innobase_get_index(
4626
4689
/*============================*/
4627
uint keynr) /*!< in: use this index; MAX_KEY means always
4628
clustered index, even if it was internally
4629
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 */
4632
dict_index_t* index = 0;
4634
ha_statistic_increment(&system_status_var::ha_read_key_count);
4636
ut_ad(user_session == ha_session());
4637
ut_a(prebuilt->trx == session_to_trx(user_session));
4639
if (keynr != MAX_KEY && table->s->keys > 0) {
4640
key = table->key_info + keynr;
4642
index = dict_table_get_index_on_name(prebuilt->table,
4645
index = dict_table_get_first_index(prebuilt->table);
4649
errmsg_printf(ERRMSG_LVL_ERROR,
4650
"Innodb could not find key n:o %u with name %s "
4651
"from dict cache for table %s",
4652
keynr, key ? key->name : "NULL",
4653
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);
4659
4722
/********************************************************************//**
4660
4723
Changes the active index of a handle.
4661
@return 0 or error code */
4724
@return 0 or error code */
4664
4727
ha_innobase::change_active_index(
4665
4728
/*=============================*/
4666
uint keynr) /*!< in: use this index; MAX_KEY means always clustered
4667
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
4670
ut_ad(user_session == ha_session());
4671
ut_a(prebuilt->trx == session_to_trx(user_session));
4673
active_index = keynr;
4675
prebuilt->index = innobase_get_index(keynr);
4677
if (UNIV_UNLIKELY(!prebuilt->index)) {
4678
errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
4683
prebuilt->index_usable = row_merge_is_index_usable(prebuilt->trx,
4686
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
4687
errmsg_printf(ERRMSG_LVL_WARN,
4688
"InnoDB: insufficient history for index %u",
4690
/* The caller seems to ignore this. Thus, we must check
4691
this again in row_search_for_mysql(). */
4695
ut_a(prebuilt->search_tuple != 0);
4697
dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
4699
dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
4700
prebuilt->index->n_fields);
4702
/* MySQL changes the active index for a handle also during some
4703
queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
4704
and then calculates the sum. Previously we played safe and used
4705
the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
4706
copying. Starting from MySQL-4.1 we use a more efficient flag here. */
4708
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);
4713
4776
/**********************************************************************//**
4714
4777
Positions an index cursor to the index specified in keynr. Fetches the
4716
4779
??? This is only used to read whole keys ???
4717
@return error number or 0 */
4780
@return error number or 0 */
4720
4783
ha_innobase::index_read_idx(
4721
4784
/*========================*/
4722
unsigned char* buf, /*!< in/out: buffer for the returned
4724
uint keynr, /*!< in: use this index */
4725
const unsigned char* key, /*!< in: key value; if this is NULL
4726
we position the cursor at the
4727
start or end of index */
4728
uint key_len, /*!< in: key value length */
4729
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 */
4731
if (change_active_index(keynr)) {
4736
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));
4739
4802
/***********************************************************************//**
4740
4803
Reads the next or previous row from a cursor, which must have previously been
4741
4804
positioned using index_read.
4742
@return 0, HA_ERR_END_OF_FILE, or error number */
4805
@return 0, HA_ERR_END_OF_FILE, or error number */
4745
4808
ha_innobase::general_fetch(
4746
4809
/*=======================*/
4747
unsigned char* buf, /*!< in/out: buffer for next row in MySQL
4749
uint direction, /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */
4750
uint match_mode) /*!< in: 0, ROW_SEL_EXACT, or
4751
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 */
4756
ut_a(prebuilt->trx == session_to_trx(user_session));
4758
innodb_srv_conc_enter_innodb(prebuilt->trx);
4760
ret = row_search_for_mysql(
4761
(byte*)buf, 0, prebuilt, match_mode, direction);
4763
innodb_srv_conc_exit_innodb(prebuilt->trx);
4770
case DB_RECORD_NOT_FOUND:
4771
error = HA_ERR_END_OF_FILE;
4772
table->status = STATUS_NOT_FOUND;
4774
case DB_END_OF_INDEX:
4775
error = HA_ERR_END_OF_FILE;
4776
table->status = STATUS_NOT_FOUND;
4779
error = convert_error_code_to_mysql(
4780
(int) ret, prebuilt->table->flags, user_session);
4781
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;
4788
4851
/***********************************************************************//**
4789
4852
Reads the next row from a cursor, which must have previously been
4790
4853
positioned using index_read.
4791
@return 0, HA_ERR_END_OF_FILE, or error number */
4854
@return 0, HA_ERR_END_OF_FILE, or error number */
4794
4857
ha_innobase::index_next(
4795
4858
/*====================*/
4796
unsigned char* buf) /*!< in/out: buffer for next row in MySQL
4859
unsigned char* buf) /*!< in/out: buffer for next row in MySQL
4799
ha_statistic_increment(&system_status_var::ha_read_next_count);
4862
ha_statistic_increment(&system_status_var::ha_read_next_count);
4801
return(general_fetch(buf, ROW_SEL_NEXT, 0));
4864
return(general_fetch(buf, ROW_SEL_NEXT, 0));
4804
4867
/*******************************************************************//**
4805
4868
Reads the next row matching to the key value given as the parameter.
4806
@return 0, HA_ERR_END_OF_FILE, or error number */
4869
@return 0, HA_ERR_END_OF_FILE, or error number */
4809
4872
ha_innobase::index_next_same(
4810
4873
/*=========================*/
4811
unsigned char* buf, /*!< in/out: buffer for the row */
4812
const unsigned char* , /*!< in: key value */
4813
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 */
4815
ha_statistic_increment(&system_status_var::ha_read_next_count);
4878
ha_statistic_increment(&system_status_var::ha_read_next_count);
4817
return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
4880
return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
4820
4883
/***********************************************************************//**
4821
4884
Reads the previous row from a cursor, which must have previously been
4822
4885
positioned using index_read.
4823
@return 0, HA_ERR_END_OF_FILE, or error number */
4886
@return 0, HA_ERR_END_OF_FILE, or error number */
4826
4889
ha_innobase::index_prev(
4827
4890
/*====================*/
4828
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 */
4830
ha_statistic_increment(&system_status_var::ha_read_prev_count);
4893
ha_statistic_increment(&system_status_var::ha_read_prev_count);
4832
return(general_fetch(buf, ROW_SEL_PREV, 0));
4895
return(general_fetch(buf, ROW_SEL_PREV, 0));
4835
4898
/********************************************************************//**
4836
4899
Positions a cursor on the first record in an index and reads the
4837
4900
corresponding row to buf.
4838
@return 0, HA_ERR_END_OF_FILE, or error code */
4901
@return 0, HA_ERR_END_OF_FILE, or error code */
4841
4904
ha_innobase::index_first(
4842
4905
/*=====================*/
4843
unsigned char* buf) /*!< in/out: buffer for the row */
4906
unsigned char* buf) /*!< in/out: buffer for the row */
4847
ha_statistic_increment(&system_status_var::ha_read_first_count);
4849
error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
4851
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4853
if (error == HA_ERR_KEY_NOT_FOUND) {
4854
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;
4860
4923
/********************************************************************//**
4861
4924
Positions a cursor on the last record in an index and reads the
4862
4925
corresponding row to buf.
4863
@return 0, HA_ERR_END_OF_FILE, or error code */
4926
@return 0, HA_ERR_END_OF_FILE, or error code */
4866
4929
ha_innobase::index_last(
4867
4930
/*====================*/
4868
unsigned char* buf) /*!< in/out: buffer for the row */
4931
unsigned char* buf) /*!< in/out: buffer for the row */
4872
ha_statistic_increment(&system_status_var::ha_read_last_count);
4874
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
4876
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4878
if (error == HA_ERR_KEY_NOT_FOUND) {
4879
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;
4885
4948
/****************************************************************//**
4886
4949
Initialize a table scan.
4887
@return 0 or error number */
4950
@return 0 or error number */
4890
4953
ha_innobase::rnd_init(
4891
4954
/*==================*/
4892
bool scan) /*!< in: TRUE if table/index scan FALSE otherwise */
4955
bool scan) /*!< in: TRUE if table/index scan FALSE otherwise */
4896
/* Store the active index value so that we can restore the original
4897
value after a scan */
4899
if (prebuilt->clust_index_was_generated) {
4900
err = change_active_index(MAX_KEY);
4902
err = change_active_index(primary_key);
4905
/* Don't use semi-consistent read in random row reads (by position).
4906
This means we must disable semi_consistent_read if scan is false */
4909
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);
4917
4980
/*****************************************************************//**
4918
4981
Ends a table scan.
4919
@return 0 or error number */
4982
@return 0 or error number */
4922
4985
ha_innobase::rnd_end(void)
4923
4986
/*======================*/
4925
return(index_end());
4988
return(index_end());
4928
4991
/*****************************************************************//**
4929
4992
Reads the next row in a table scan (also used to read the FIRST row
4930
4993
in a table scan).
4931
@return 0, HA_ERR_END_OF_FILE, or error number */
4994
@return 0, HA_ERR_END_OF_FILE, or error number */
4934
4997
ha_innobase::rnd_next(
4935
4998
/*==================*/
4936
unsigned char* buf) /*!< in/out: returns the row in this buffer,
4999
unsigned char* buf) /*!< in/out: returns the row in this buffer,
4941
ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
4943
if (start_of_scan) {
4944
error = index_first(buf);
4946
if (error == HA_ERR_KEY_NOT_FOUND) {
4947
error = HA_ERR_END_OF_FILE;
4952
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);
4958
5021
/**********************************************************************//**
4959
5022
Fetches a row from the table based on a row reference.
4960
@return 0, HA_ERR_KEY_NOT_FOUND, or error code */
5023
@return 0, HA_ERR_KEY_NOT_FOUND, or error code */
4963
5026
ha_innobase::rnd_pos(
4964
5027
/*=================*/
4965
unsigned char* buf, /*!< in/out: buffer for the row */
4966
unsigned char* pos) /*!< in: primary key value of the row in the
4967
MySQL format, or the row id if the clustered
4968
index was internally generated by InnoDB; the
4969
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 */
4972
uint keynr = active_index;
4974
ha_statistic_increment(&system_status_var::ha_read_rnd_count);
4976
ut_a(prebuilt->trx == session_to_trx(ha_session()));
4978
if (prebuilt->clust_index_was_generated) {
4979
/* No primary key was defined for the table and we
4980
generated the clustered index from the row id: the
4981
row reference is the row id, not any key value
4982
that MySQL knows of */
4984
error = change_active_index(MAX_KEY);
4986
error = change_active_index(primary_key);
4993
/* Note that we assume the length of the row reference is fixed
4994
for the table, and it is == ref_length */
4996
error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
5001
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);
5006
5069
/*********************************************************************//**
5052
5115
create_table_def(
5053
5116
/*=============*/
5054
trx_t* trx, /*!< in: InnoDB transaction handle */
5055
Table* form, /*!< in: information on table
5056
columns and indexes */
5057
const char* table_name, /*!< in: table name */
5058
const char* path_of_temp_table,/*!< in: if this is a table explicitly
5059
created by the user with the
5060
TEMPORARY keyword, then this
5061
parameter is the dir path where the
5062
table should be placed if we create
5063
an .ibd file for it (no .ibd extension
5064
in the path, though); otherwise this
5066
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 */
5069
dict_table_t* table;
5074
ulint nulls_allowed;
5075
ulint unsigned_type;
5077
ulint long_true_varchar;
5081
n_cols = form->s->fields;
5083
/* We pass 0 as the space id, and determine at a lower level the space
5084
id where to store the table */
5086
table = dict_mem_table_create(table_name, 0, n_cols, flags);
5088
if (path_of_temp_table) {
5089
table->dir_path_of_temp_table =
5090
mem_heap_strdup(table->heap, path_of_temp_table);
5093
for (i = 0; i < n_cols; i++) {
5094
field = form->field[i];
5096
col_type = get_innobase_type_from_mysql_type(&unsigned_type,
5098
if (field->null_ptr) {
5101
nulls_allowed = DATA_NOT_NULL;
5104
if (field->binary()) {
5105
binary_type = DATA_BINARY_TYPE;
5112
if (dtype_is_string_type(col_type)) {
5114
charset_no = (ulint)field->charset()->number;
5116
if (UNIV_UNLIKELY(charset_no >= 256)) {
5117
/* in data0type.h we assume that the
5118
number fits in one byte in prtype */
5119
push_warning_printf(
5120
(Session*) trx->mysql_thd,
5121
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5122
ER_CANT_CREATE_TABLE,
5123
"In InnoDB, charset-collation codes"
5124
" must be below 256."
5125
" Unsupported code %lu.",
5126
(ulong) charset_no);
5127
return(ER_CANT_CREATE_TABLE);
5131
ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
5132
that this fits in one byte */
5133
col_len = field->pack_length();
5135
/* The MySQL pack length contains 1 or 2 bytes length field
5136
for a true VARCHAR. Let us subtract that, so that the InnoDB
5137
column length in the InnoDB data dictionary is the real
5138
maximum byte length of the actual data. */
5140
long_true_varchar = 0;
5142
if (field->type() == DRIZZLE_TYPE_VARCHAR) {
5143
col_len -= ((Field_varstring*)field)->length_bytes;
5145
if (((Field_varstring*)field)->length_bytes == 2) {
5146
long_true_varchar = DATA_LONG_TRUE_VARCHAR;
5150
dict_mem_table_add_col(table, table->heap,
5151
(char*) field->field_name,
5154
(ulint)field->type()
5155
| nulls_allowed | unsigned_type
5156
| binary_type | long_true_varchar,
5161
error = row_create_table_for_mysql(table, trx);
5163
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);
5168
5231
/*****************************************************************//**
5174
trx_t* trx, /*!< in: InnoDB transaction handle */
5175
Table* form, /*!< in: information on table
5176
columns and indexes */
5177
ulint flags, /*!< in: InnoDB table flags */
5178
const char* table_name, /*!< in: table name */
5179
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 */
5182
dict_index_t* index;
5186
KEY_PART_INFO* key_part;
5193
ulint* field_lengths;
5195
key = form->key_info + key_num;
5197
n_fields = key->key_parts;
5201
if (key_num == form->s->primary_key) {
5202
ind_type = ind_type | DICT_CLUSTERED;
5205
if (key->flags & HA_NOSAME ) {
5206
ind_type = ind_type | DICT_UNIQUE;
5209
/* We pass 0 as the space id, and determine at a lower level the space
5210
id where to store the table */
5212
index = dict_mem_index_create(table_name, key->name, 0,
5213
ind_type, n_fields);
5215
field_lengths = (ulint*) malloc(sizeof(ulint) * n_fields);
5217
for (i = 0; i < n_fields; i++) {
5218
key_part = key->key_part + i;
5220
/* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
5221
field in an index: we only store a specified number of first
5222
bytes of the column to the index field.) The flag does not
5223
seem to be properly set by MySQL. Let us fall back on testing
5224
the length of the key part versus the column. */
5227
for (j = 0; j < form->s->fields; j++) {
5229
field = form->field[j];
5231
if (0 == innobase_strcasecmp(
5233
key_part->field->field_name)) {
5234
/* Found the corresponding column */
5240
ut_a(j < form->s->fields);
5242
col_type = get_innobase_type_from_mysql_type(
5243
&is_unsigned, key_part->field);
5245
if (DATA_BLOB == col_type
5246
|| (key_part->length < field->pack_length()
5247
&& field->type() != DRIZZLE_TYPE_VARCHAR)
5248
|| (field->type() == DRIZZLE_TYPE_VARCHAR
5249
&& key_part->length < field->pack_length()
5250
- ((Field_varstring*)field)->length_bytes)) {
5252
prefix_len = key_part->length;
5254
if (col_type == DATA_INT
5255
|| col_type == DATA_FLOAT
5256
|| col_type == DATA_DOUBLE
5257
|| col_type == DATA_DECIMAL) {
5258
errmsg_printf(ERRMSG_LVL_ERROR,
5259
"MySQL is trying to create a column "
5260
"prefix index field, on an "
5261
"inappropriate data type. Table "
5262
"name %s, column name %s.",
5264
key_part->field->field_name);
5272
field_lengths[i] = key_part->length;
5274
dict_mem_index_add_field(index,
5275
(char*) key_part->field->field_name, prefix_len);
5278
/* Even though we've defined max_supported_key_part_length, we
5279
still do our own checking using field_lengths to be absolutely
5280
sure we don't create too long indexes. */
5281
error = row_create_index_for_mysql(index, trx, field_lengths);
5283
error = convert_error_code_to_mysql(error, flags, NULL);
5285
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);
5290
5353
/*****************************************************************//**
5319
5382
in future. For now, it checks two specifiers:
5320
5383
KEY_BLOCK_SIZE and ROW_FORMAT
5321
5384
If innodb_strict_mode is not set then this function is a no-op
5322
@return TRUE if valid. */
5385
@return TRUE if valid. */
5325
5388
create_options_are_valid(
5326
5389
/*=====================*/
5327
Session* session, /*!< in: connection thread. */
5328
Table& form, /*!< in: information on table
5329
columns and indexes */
5390
Session* session, /*!< in: connection thread. */
5391
Table& form, /*!< in: information on table
5392
columns and indexes */
5330
5393
message::Table& create_proto)
5332
ibool kbs_specified = FALSE;
5336
ut_ad(session != NULL);
5338
/* If innodb_strict_mode is not set don't do any validation. */
5339
if (!(SessionVAR(session, strict_mode))) {
5343
/* First check if KEY_BLOCK_SIZE was specified. */
5344
if (create_proto.options().has_key_block_size()) {
5346
kbs_specified = TRUE;
5347
switch (create_proto.options().key_block_size()) {
5356
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5357
ER_ILLEGAL_HA_CREATE_OPTION,
5359
" KEY_BLOCK_SIZE = %lu."
5361
" [1, 2, 4, 8, 16]",
5362
create_proto.options().key_block_size());
5367
/* If KEY_BLOCK_SIZE was specified, check for its
5369
if (kbs_specified && !srv_file_per_table) {
5370
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5371
ER_ILLEGAL_HA_CREATE_OPTION,
5372
"InnoDB: KEY_BLOCK_SIZE"
5373
" requires innodb_file_per_table.");
5377
if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
5378
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5379
ER_ILLEGAL_HA_CREATE_OPTION,
5380
"InnoDB: KEY_BLOCK_SIZE"
5381
" requires innodb_file_format >"
5386
/* Now check for ROW_FORMAT specifier. */
5387
if (create_proto.options().has_row_type()) {
5388
switch (form.s->row_type) {
5389
const char* row_format_name;
5390
case ROW_TYPE_COMPRESSED:
5391
case ROW_TYPE_DYNAMIC:
5393
= form.s->row_type == ROW_TYPE_COMPRESSED
5397
/* These two ROW_FORMATs require
5398
srv_file_per_table and srv_file_format */
5399
if (!srv_file_per_table) {
5400
push_warning_printf(
5402
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5403
ER_ILLEGAL_HA_CREATE_OPTION,
5404
"InnoDB: ROW_FORMAT=%s"
5405
" requires innodb_file_per_table.",
5411
if (srv_file_format < DICT_TF_FORMAT_ZIP) {
5412
push_warning_printf(
5414
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5415
ER_ILLEGAL_HA_CREATE_OPTION,
5416
"InnoDB: ROW_FORMAT=%s"
5417
" requires innodb_file_format >"
5423
/* Cannot specify KEY_BLOCK_SIZE with
5424
ROW_FORMAT = DYNAMIC.
5425
However, we do allow COMPRESSED to be
5426
specified with KEY_BLOCK_SIZE. */
5428
&& form.s->row_type == ROW_TYPE_DYNAMIC) {
5429
push_warning_printf(
5431
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5432
ER_ILLEGAL_HA_CREATE_OPTION,
5433
"InnoDB: cannot specify"
5434
" ROW_FORMAT = DYNAMIC with"
5435
" KEY_BLOCK_SIZE.");
5441
case ROW_TYPE_REDUNDANT:
5442
case ROW_TYPE_COMPACT:
5443
case ROW_TYPE_DEFAULT:
5444
/* Default is COMPACT. */
5446
= form.s->row_type == ROW_TYPE_REDUNDANT
5450
/* Cannot specify KEY_BLOCK_SIZE with these
5451
format specifiers. */
5452
if (kbs_specified) {
5453
push_warning_printf(
5455
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5456
ER_ILLEGAL_HA_CREATE_OPTION,
5457
"InnoDB: cannot specify"
5458
" ROW_FORMAT = %s with"
5467
push_warning(session,
5468
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5469
ER_ILLEGAL_HA_CREATE_OPTION,
5470
"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.");
5479
5542
/*********************************************************************
5483
5546
InnobaseEngine::doCreateTable(
5484
5547
/*================*/
5485
Session* session, /*!< in: Session */
5486
const char* table_name, /*!< in: table name */
5487
Table& form, /*!< in: information on table
5488
columns and indexes */
5548
Session &session, /*!< in: Session */
5549
Table& form, /*!< in: information on table columns and indexes */
5550
drizzled::TableIdentifier &identifier,
5489
5551
message::Table& create_proto)
5492
dict_table_t* innobase_table;
5497
char name2[FN_REFLEN];
5498
char norm_name[FN_REFLEN];
5499
ib_int64_t auto_inc_value;
5501
/* Cache the value of innodb_file_format, in case it is
5502
modified by another thread while the table is being created. */
5503
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;
5504
5566
bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
5506
assert(session != NULL);
5568
const char *table_name= identifier.getPath().c_str();
5509
/* Names passed in from server are in two formats:
5510
1. <database_name>/<table_name>: for normal table creation
5511
2. full path: for temp table creation, or sym link
5513
When srv_file_per_table is on, check for full path pattern, i.e.
5514
X:\dir\..., X is a driver letter, or
5515
\\dir1\dir2\..., UNC path
5516
returns error if it is in full path format, but not creating a temp.
5517
table. Currently InnoDB does not support symbolic link on Windows. */
5519
if (srv_file_per_table
5520
&& (! lex_identified_temp_table)) {
5522
if ((table_name[1] == ':')
5523
|| (table_name[0] == '\\' && table_name[1] == '\\')) {
5524
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot create table %s\n", table_name);
5525
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);
5530
if (form.s->fields > 1000) {
5531
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
5532
but we play safe here */
5534
return(HA_ERR_TO_BIG_ROW);
5537
/* Get the transaction associated with the current session, or create one
5538
if not yet created */
5540
parent_trx = check_trx_exists(session);
5542
/* In case MySQL calls this in the middle of a SELECT query, release
5543
possible adaptive hash latch to avoid deadlocks of threads */
5545
trx_search_latch_release_if_reserved(parent_trx);
5547
trx = innobase_trx_allocate(session);
5549
srv_lower_case_table_names = TRUE;
5551
strcpy(name2, table_name);
5553
normalize_table_name(norm_name, name2);
5555
/* Latch the InnoDB data dictionary exclusively so that no deadlocks
5556
or lock waits can happen in it during a table create operation.
5557
Drop table etc. do this latching in row0mysql.c. */
5559
row_mysql_lock_data_dictionary(trx);
5561
/* Create the table definition in InnoDB */
5565
/* Validate create options if innodb_strict_mode is set. */
5566
if (! create_options_are_valid(session, form, create_proto)) {
5567
error = ER_ILLEGAL_HA_CREATE_OPTION;
5571
if (create_proto.options().has_key_block_size()) {
5572
/* Determine the page_zip.ssize corresponding to the
5573
requested page size (key_block_size) in kilobytes. */
5576
ulint key_block_size = create_proto.options().key_block_size();
5578
for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX;
5579
ssize++, ksize <<= 1) {
5580
if (key_block_size == ksize) {
5581
iflags = ssize << DICT_TF_ZSSIZE_SHIFT
5583
| DICT_TF_FORMAT_ZIP
5584
<< DICT_TF_FORMAT_SHIFT;
5589
if (!srv_file_per_table) {
5590
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5591
ER_ILLEGAL_HA_CREATE_OPTION,
5592
"InnoDB: KEY_BLOCK_SIZE"
5593
" requires innodb_file_per_table.");
5597
if (file_format < DICT_TF_FORMAT_ZIP) {
5598
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5599
ER_ILLEGAL_HA_CREATE_OPTION,
5600
"InnoDB: KEY_BLOCK_SIZE"
5601
" requires innodb_file_format >"
5607
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5608
ER_ILLEGAL_HA_CREATE_OPTION,
5610
" KEY_BLOCK_SIZE=%lu.",
5611
create_proto.options().key_block_size());
5615
if (create_proto.options().has_row_type()) {
5617
/* KEY_BLOCK_SIZE was specified. */
5618
if (form.s->row_type != ROW_TYPE_COMPRESSED) {
5619
/* ROW_FORMAT other than COMPRESSED
5620
ignores KEY_BLOCK_SIZE. It does not
5621
make sense to reject conflicting
5622
KEY_BLOCK_SIZE and ROW_FORMAT, because
5623
such combinations can be obtained
5624
with ALTER TABLE anyway. */
5625
push_warning_printf(
5627
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5628
ER_ILLEGAL_HA_CREATE_OPTION,
5629
"InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
5630
" unless ROW_FORMAT=COMPRESSED.",
5631
create_proto.options().key_block_size());
5635
/* No KEY_BLOCK_SIZE */
5636
if (form.s->row_type == ROW_TYPE_COMPRESSED) {
5637
/* ROW_FORMAT=COMPRESSED without
5638
KEY_BLOCK_SIZE implies half the
5639
maximum KEY_BLOCK_SIZE. */
5640
iflags = (DICT_TF_ZSSIZE_MAX - 1)
5641
<< DICT_TF_ZSSIZE_SHIFT
5643
| DICT_TF_FORMAT_ZIP
5644
<< 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;
5645
5707
#if DICT_TF_ZSSIZE_MAX < 1
5646
5708
# error "DICT_TF_ZSSIZE_MAX < 1"
5651
switch (form.s->row_type) {
5652
const char* row_format_name;
5653
case ROW_TYPE_REDUNDANT:
5655
case ROW_TYPE_COMPRESSED:
5656
case ROW_TYPE_DYNAMIC:
5658
= form.s->row_type == ROW_TYPE_COMPRESSED
5662
if (!srv_file_per_table) {
5663
push_warning_printf(
5665
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5666
ER_ILLEGAL_HA_CREATE_OPTION,
5667
"InnoDB: ROW_FORMAT=%s"
5668
" requires innodb_file_per_table.",
5670
} else if (file_format < DICT_TF_FORMAT_ZIP) {
5671
push_warning_printf(
5673
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5674
ER_ILLEGAL_HA_CREATE_OPTION,
5675
"InnoDB: ROW_FORMAT=%s"
5676
" requires innodb_file_format >"
5680
iflags |= DICT_TF_COMPACT
5681
| (DICT_TF_FORMAT_ZIP
5682
<< DICT_TF_FORMAT_SHIFT);
5687
case ROW_TYPE_NOT_USED:
5688
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:
5690
5752
error = ER_ILLEGAL_HA_CREATE_OPTION;
5692
case ROW_TYPE_DEFAULT:
5693
case ROW_TYPE_COMPACT:
5694
iflags = DICT_TF_COMPACT;
5697
} else if (!iflags) {
5698
/* No KEY_BLOCK_SIZE or ROW_FORMAT specified:
5699
use ROW_FORMAT=COMPACT by default. */
5700
iflags = DICT_TF_COMPACT;
5703
error = create_table_def(trx, &form, norm_name,
5704
lex_identified_temp_table ? name2 : NULL,
5711
/* Look for a primary key */
5713
primary_key_no= (form.s->primary_key != MAX_KEY ?
5714
(int) form.s->primary_key :
5717
/* Our function row_get_mysql_key_number_for_index assumes
5718
the primary key is always number 0, if it exists */
5720
assert(primary_key_no == -1 || primary_key_no == 0);
5722
/* Create the keys */
5724
if (form.s->keys == 0 || primary_key_no == -1) {
5725
/* Create an index which is used as the clustered index;
5726
order the rows by their row id which is internally generated
5729
error = create_clustered_index_when_no_primary(
5730
trx, iflags, norm_name);
5736
if (primary_key_no != -1) {
5737
/* In InnoDB the clustered index must always be created
5739
if ((error = create_index(trx, &form, iflags, norm_name,
5740
(uint) primary_key_no))) {
5745
for (i = 0; i < form.s->keys; i++) {
5747
if (i != (uint) primary_key_no) {
5749
if ((error = create_index(trx, &form, iflags, norm_name,
5756
if (trx->mysql_query_str) {
5757
error = row_table_add_foreign_constraints(trx,
5758
trx->mysql_query_str, norm_name,
5759
lex_identified_temp_table);
5761
error = convert_error_code_to_mysql(error, iflags, NULL);
5768
innobase_commit_low(trx);
5770
row_mysql_unlock_data_dictionary(trx);
5772
/* Flush the log to reduce probability that the .frm files and
5773
the InnoDB data dictionary get out-of-sync if the user runs
5774
with innodb_flush_log_at_trx_commit = 0 */
5776
log_buffer_flush_to_disk();
5778
innobase_table = dict_table_get(norm_name, FALSE);
5780
assert(innobase_table != 0);
5782
if (innobase_table) {
5783
/* We update the highest file format in the system table
5784
space, if this table has higher file format setting. */
5786
trx_sys_file_format_max_upgrade(
5787
(const char**) &innobase_file_format_check,
5788
dict_table_get_format(innobase_table));
5791
/* Note: We can't call update_session() as prebuilt will not be
5792
setup at this stage and so we use session. */
5794
/* We need to copy the AUTOINC value from the old table if
5795
this is an ALTER TABLE. */
5797
if ((create_proto.options().has_auto_increment_value()
5798
|| session_sql_command(session) == SQLCOM_ALTER_TABLE)
5799
&& create_proto.options().auto_increment_value() != 0) {
5801
/* Query was ALTER TABLE...AUTO_INCREMENT = x; or
5802
CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
5803
definition from the dictionary and get the current value
5804
of the auto increment field. Set a new value to the
5805
auto increment field if the value is greater than the
5806
maximum value in the column. */
5808
auto_inc_value = create_proto.options().auto_increment_value();
5810
dict_table_autoinc_lock(innobase_table);
5811
dict_table_autoinc_initialize(innobase_table, auto_inc_value);
5812
dict_table_autoinc_unlock(innobase_table);
5815
/* Tell the InnoDB server that there might be work for
5818
srv_active_wake_master_thread();
5820
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
StorageEngine::writeDefinitionFromPath(identifier, create_proto);
5825
innobase_commit_low(trx);
5827
row_mysql_unlock_data_dictionary(trx);
5829
trx_free_for_mysql(trx);
5889
innobase_commit_low(trx);
5891
row_mysql_unlock_data_dictionary(trx);
5893
trx_free_for_mysql(trx);
5834
5898
/*****************************************************************//**
5835
5899
Discards or imports an InnoDB tablespace.
5836
@return 0 == success, -1 == error */
5900
@return 0 == success, -1 == error */
5839
5903
ha_innobase::discard_or_import_tablespace(
5840
5904
/*======================================*/
5841
my_bool discard) /*!< in: TRUE if discard, else import */
5905
my_bool discard) /*!< in: TRUE if discard, else import */
5843
dict_table_t* dict_table;
5847
ut_a(prebuilt->trx);
5848
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
5849
ut_a(prebuilt->trx == session_to_trx(ha_session()));
5851
dict_table = prebuilt->table;
5852
trx = prebuilt->trx;
5855
err = row_discard_tablespace_for_mysql(dict_table->name, trx);
5857
err = row_import_tablespace_for_mysql(dict_table->name, trx);
5860
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);
5865
5929
/*****************************************************************//**
5866
5930
Deletes all rows of an InnoDB table.
5867
@return error number */
5931
@return error number */
5870
5934
ha_innobase::delete_all_rows(void)
5871
5935
/*==============================*/
5875
/* Get the transaction associated with the current session, or create one
5876
if not yet created, and update prebuilt->trx */
5878
update_session(ha_session());
5880
if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
5882
/* We only handle TRUNCATE TABLE t as a special case.
5883
DELETE FROM t will have to use ha_innobase::delete_row(),
5884
because DELETE is transactional while TRUNCATE is not. */
5885
return(errno=HA_ERR_WRONG_COMMAND);
5888
/* Truncate the table in InnoDB */
5890
error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
5891
if (error == DB_ERROR) {
5892
/* Cannot truncate; resort to ha_innobase::delete_row() */
5896
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,
5902
5966
/*****************************************************************//**
5971
6044
InnobaseEngine::doDropSchema(
5972
6045
/*===================*/
5973
const std::string &schema_name)
5974
/*!< in: database path; inside InnoDB the name
5975
of the last directory in the path is used as
5976
the database name: for example, in 'mysql/data/test'
5977
the database name is 'test' */
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' */
5981
string schema_path(schema_name);
5982
Session* session = current_session;
5984
/* Get the transaction associated with the current session, or create one
5985
if not yet created */
5987
assert(this == innodb_engine_ptr);
5989
/* In the Windows plugin, session = current_session is always NULL */
5991
trx_t* parent_trx = check_trx_exists(session);
5993
/* In case Drizzle calls this in the middle of a SELECT
5994
query, release possible adaptive hash latch to avoid
5995
deadlocks of threads */
5997
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);
6000
6073
schema_path.append("/");
6001
trx = innobase_trx_allocate(session);
6002
error = row_drop_database_for_mysql(schema_path.c_str(), trx);
6004
/* Flush the log to reduce probability that the .frm files and
6005
the InnoDB data dictionary get out-of-sync if the user runs
6006
with innodb_flush_log_at_trx_commit = 0 */
6008
log_buffer_flush_to_disk();
6010
/* Tell the InnoDB server that there might be work for
6013
srv_active_wake_master_thread();
6015
innobase_commit_low(trx);
6016
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);
6018
6091
return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement.
6020
6093
/*********************************************************************//**
6021
6094
Renames an InnoDB table.
6022
@return 0 or error code */
6095
@return 0 or error code */
6025
6098
innobase_rename_table(
6026
6099
/*==================*/
6027
trx_t* trx, /*!< in: transaction */
6028
const char* from, /*!< in: old name of the table */
6029
const char* to, /*!< in: new name of the table */
6030
ibool lock_and_commit)
6031
/*!< 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 */
6037
srv_lower_case_table_names = TRUE;
6039
// Magic number 64 arbitrary
6040
norm_to = (char*) malloc(strlen(to) + 64);
6041
norm_from = (char*) malloc(strlen(from) + 64);
6043
normalize_table_name(norm_to, to);
6044
normalize_table_name(norm_from, from);
6046
/* Serialize data dictionary operations with dictionary mutex:
6047
no deadlocks can occur then in these operations */
6049
if (lock_and_commit) {
6050
row_mysql_lock_data_dictionary(trx);
6053
error = row_rename_table_for_mysql(
6054
norm_from, norm_to, trx, lock_and_commit);
6056
if (error != DB_SUCCESS) {
6057
FILE* ef = dict_foreign_err_file;
6059
fputs("InnoDB: Renaming table ", ef);
6060
ut_print_name(ef, trx, TRUE, norm_from);
6062
ut_print_name(ef, trx, TRUE, norm_to);
6063
fputs(" failed!\n", ef);
6066
if (lock_and_commit) {
6067
row_mysql_unlock_data_dictionary(trx);
6069
/* Flush the log to reduce probability that the .frm
6070
files and the InnoDB data dictionary get out-of-sync
6071
if the user runs with innodb_flush_log_at_trx_commit = 0 */
6073
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();
6081
6154
/*********************************************************************//**
6082
6155
Renames an InnoDB table.
6083
@return 0 or error code */
6086
InnobaseEngine::doRenameTable(
6087
/*======================*/
6089
const char* from, /*!< in: old name of the table */
6090
const char* to) /*!< in: new name of the table */
6156
@return 0 or error code */
6157
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
6096
/* Get the transaction associated with the current session, or create one
6097
if not yet created */
6099
parent_trx = check_trx_exists(session);
6101
/* In case MySQL calls this in the middle of a SELECT query, release
6102
possible adaptive hash latch to avoid deadlocks of threads */
6104
trx_search_latch_release_if_reserved(parent_trx);
6106
trx = innobase_trx_allocate(session);
6108
error = innobase_rename_table(trx, from, to, TRUE);
6110
/* Tell the InnoDB server that there might be work for
6113
srv_active_wake_master_thread();
6115
innobase_commit_low(trx);
6116
trx_free_for_mysql(trx);
6118
error = convert_error_code_to_mysql(error, 0, NULL);
6159
// A temp table alter table/rename is a shallow rename and only the
6160
// definition needs to be updated.
6161
if (to.getType() == message::Table::TEMPORARY && from.getType() == message::Table::TEMPORARY)
6163
return plugin::StorageEngine::renameDefinitionFromPath(to, from);
6170
/* Get the transaction associated with the current session, or create one
6171
if not yet created */
6173
parent_trx = check_trx_exists(&session);
6175
/* In case MySQL calls this in the middle of a SELECT query, release
6176
possible adaptive hash latch to avoid deadlocks of threads */
6178
trx_search_latch_release_if_reserved(parent_trx);
6180
trx = innobase_trx_allocate(&session);
6182
error = innobase_rename_table(trx, from.getPath().c_str(), to.getPath().c_str(), TRUE);
6184
/* Tell the InnoDB server that there might be work for
6187
srv_active_wake_master_thread();
6189
innobase_commit_low(trx);
6190
trx_free_for_mysql(trx);
6192
error = convert_error_code_to_mysql(error, 0, NULL);
6196
// If this fails, we are in trouble
6197
plugin::StorageEngine::renameDefinitionFromPath(to, from);
6123
6203
/*********************************************************************//**
6124
6204
Estimates the number of index records in a range.
6125
@return estimated number of rows */
6205
@return estimated number of rows */
6128
6208
ha_innobase::records_in_range(
6129
6209
/*==========================*/
6130
uint keynr, /*!< in: index number */
6131
key_range *min_key, /*!< in: start key value of the
6132
range, may also be 0 */
6133
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
6137
dict_index_t* index;
6138
unsigned char* key_val_buff2 = (unsigned char*) malloc(
6139
table->s->stored_rec_length
6140
+ table->s->max_key_length + 100);
6141
ulint buff2_len = table->s->stored_rec_length
6142
+ table->s->max_key_length + 100;
6143
dtuple_t* range_start;
6144
dtuple_t* range_end;
6150
ut_a(prebuilt->trx == session_to_trx(ha_session()));
6152
prebuilt->trx->op_info = (char*)"estimating records in index range";
6154
/* In case MySQL calls this in the middle of a SELECT query, release
6155
possible adaptive hash latch to avoid deadlocks of threads */
6157
trx_search_latch_release_if_reserved(prebuilt->trx);
6159
active_index = keynr;
6161
key = table->key_info + active_index;
6163
index = dict_table_get_index_on_name(prebuilt->table, key->name);
6165
/* MySQL knows about this index and so we must be able to find it.*/
6168
heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6169
+ sizeof(dtuple_t)));
6171
range_start = dtuple_create(heap, key->key_parts);
6172
dict_index_copy_types(range_start, index, key->key_parts);
6174
range_end = dtuple_create(heap, key->key_parts);
6175
dict_index_copy_types(range_end, index, key->key_parts);
6177
row_sel_convert_mysql_key_to_innobase(
6178
range_start, (byte*) key_val_buff,
6179
(ulint)upd_and_key_val_buff_len,
6181
(byte*) (min_key ? min_key->key :
6182
(const unsigned char*) 0),
6183
(ulint) (min_key ? min_key->length : 0),
6186
row_sel_convert_mysql_key_to_innobase(
6187
range_end, (byte*) key_val_buff2,
6189
(byte*) (max_key ? max_key->key :
6190
(const unsigned char*) 0),
6191
(ulint) (max_key ? max_key->length : 0),
6194
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
6196
mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
6199
if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
6201
n_rows = btr_estimate_n_rows_in_range(index, range_start,
6206
n_rows = HA_POS_ERROR;
6209
mem_heap_free(heap);
6211
free(key_val_buff2);
6213
prebuilt->trx->op_info = (char*)"";
6215
/* The MySQL optimizer seems to believe an estimate of 0 rows is
6216
always accurate and may return the result 'Empty set' based on that.
6217
The accuracy is not guaranteed, and even if it were, for a locking
6218
read we should anyway perform the search to set the next-key lock.
6219
Add 1 to the value to make sure MySQL does not make the assumption! */
6225
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);
6228
6308
/*********************************************************************//**
6229
6309
Gives an UPPER BOUND to the number of rows in a table. This is used in
6231
@return upper bound of rows */
6311
@return upper bound of rows */
6234
6314
ha_innobase::estimate_rows_upper_bound(void)
6235
6315
/*======================================*/
6237
dict_index_t* index;
6239
uint64_t local_data_file_length;
6241
/* We do not know if MySQL can call this function before calling
6242
external_lock(). To be safe, update the session of the current table
6245
update_session(ha_session());
6247
prebuilt->trx->op_info = (char*)
6248
"calculating upper bound for table rows";
6250
/* In case MySQL calls this in the middle of a SELECT query, release
6251
possible adaptive hash latch to avoid deadlocks of threads */
6253
trx_search_latch_release_if_reserved(prebuilt->trx);
6255
index = dict_table_get_first_index(prebuilt->table);
6257
ut_a(index->stat_n_leaf_pages > 0);
6259
local_data_file_length =
6260
((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6263
/* Calculate a minimum length for a clustered index record and from
6264
that an upper bound for the number of rows. Since we only calculate
6265
new statistics in row0mysql.c when a table has grown by a threshold
6266
factor, we must add a safety factor 2 in front of the formula below. */
6268
estimate = 2 * local_data_file_length /
6269
dict_index_calc_min_rec_len(index);
6271
prebuilt->trx->op_info = (char*)"";
6273
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);
6276
6356
/*********************************************************************//**
6277
6357
How many seeks it will take to read through the table. This is to be
6278
6358
comparable to the number returned by records_in_range so that we can
6279
6359
decide if we should scan the table or use keys.
6280
@return estimated time measured in disk seeks */
6360
@return estimated time measured in disk seeks */
6283
6363
ha_innobase::scan_time()
6284
6364
/*====================*/
6286
/* Since MySQL seems to favor table scans too much over index
6287
searches, we pretend that a sequential read takes the same time
6288
as a random disk read, that is, we do not divide the following
6289
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. */
6291
return((double) (prebuilt->table->stat_clustered_index_size));
6371
return((double) (prebuilt->table->stat_clustered_index_size));
6294
6374
/******************************************************************//**
6295
6375
Calculate the time it takes to read a set of ranges through an index
6296
6376
This enables us to optimise reads for clustered indexes.
6297
@return estimated time measured in disk seeks */
6377
@return estimated time measured in disk seeks */
6300
6380
ha_innobase::read_time(
6301
6381
/*===================*/
6302
uint index, /*!< in: key number */
6303
uint ranges, /*!< in: how many ranges */
6304
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 */
6307
double time_for_scan;
6309
if (index != table->s->primary_key) {
6311
return(Cursor::read_time(index, ranges, rows));
6316
return((double) rows);
6319
/* Assume that the read time is proportional to the scan time for all
6320
rows + at most one seek per range. */
6322
time_for_scan = scan_time();
6324
if ((total_rows = estimate_rows_upper_bound()) < rows) {
6326
return(time_for_scan);
6329
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);
6332
6412
/*********************************************************************//**
6337
6417
ha_innobase::info(
6338
6418
/*==============*/
6339
uint flag) /*!< in: what information MySQL requests */
6419
uint flag) /*!< in: what information MySQL requests */
6341
dict_table_t* ib_table;
6342
dict_index_t* index;
6343
ha_rows rec_per_key;
6347
char path[FN_REFLEN];
6348
os_file_stat_t stat_info;
6350
/* If we are forcing recovery at a high level, we will suppress
6351
statistics calculation on tables, because that may crash the
6352
server if an index is badly corrupted. */
6354
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
6356
/* We return success (0) instead of HA_ERR_CRASHED,
6357
because we want MySQL to process this query and not
6358
stop, like it would do if it received the error code
6364
/* We do not know if MySQL can call this function before calling
6365
external_lock(). To be safe, update the session of the current table
6368
update_session(ha_session());
6370
/* In case MySQL calls this in the middle of a SELECT query, release
6371
possible adaptive hash latch to avoid deadlocks of threads */
6373
prebuilt->trx->op_info = (char*)"returning various info to MySQL";
6375
trx_search_latch_release_if_reserved(prebuilt->trx);
6377
ib_table = prebuilt->table;
6379
if (flag & HA_STATUS_TIME) {
6380
if (innobase_stats_on_metadata) {
6381
/* In sql_show we call with this flag: update
6382
then statistics so that they are up-to-date */
6384
prebuilt->trx->op_info = "updating table statistics";
6386
dict_update_statistics(ib_table);
6388
prebuilt->trx->op_info = "returning various info to MySQL";
6391
snprintf(path, sizeof(path), "%s/%s%s",
6392
drizzle_data_home, ib_table->name, ".dfe");
6394
internal::unpack_filename(path,path);
6396
/* Note that we do not know the access time of the table,
6397
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
6399
if (os_file_get_status(path,&stat_info)) {
6400
stats.create_time = (ulong) stat_info.ctime;
6404
if (flag & HA_STATUS_VARIABLE) {
6405
n_rows = ib_table->stat_n_rows;
6407
/* Because we do not protect stat_n_rows by any mutex in a
6408
delete, it is theoretically possible that the value can be
6409
smaller than zero! TODO: fix this race.
6411
The MySQL optimizer seems to assume in a left join that n_rows
6412
is an accurate estimate if it is zero. Of course, it is not,
6413
since we do not have any locks on the rows yet at this phase.
6414
Since SHOW TABLE STATUS seems to call this function with the
6415
HA_STATUS_TIME flag set, while the left join optimizer does not
6416
set that flag, we add one to a zero value if the flag is not
6417
set. That way SHOW TABLE STATUS will show the best estimate,
6418
while the optimizer never sees the table empty. */
6424
if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
6428
/* Fix bug#40386: Not flushing query cache after truncate.
6429
n_rows can not be 0 unless the table is empty, set to 1
6430
instead. The original problem of bug#29507 is actually
6431
fixed in the server code. */
6432
if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
6436
/* We need to reset the prebuilt value too, otherwise
6437
checks for values greater than the last value written
6438
to the table will fail and the autoinc counter will
6439
not be updated. This will force write_row() into
6440
attempting an update of the table's AUTOINC counter. */
6442
prebuilt->autoinc_last_value = 0;
6445
stats.records = (ha_rows)n_rows;
6447
stats.data_file_length = ((uint64_t)
6448
ib_table->stat_clustered_index_size)
6450
stats.index_file_length = ((uint64_t)
6451
ib_table->stat_sum_of_other_index_sizes)
6454
/* Since fsp_get_available_space_in_free_extents() is
6455
acquiring latches inside InnoDB, we do not call it if we
6456
are asked by MySQL to avoid locking. Another reason to
6457
avoid the call is that it uses quite a lot of CPU.
6459
We do not update delete_length if no locking is requested
6460
so the "old" value can remain. delete_length is initialized
6461
to 0 in the ha_statistics' constructor. */
6462
if (!(flag & HA_STATUS_NO_LOCK)) {
6464
/* lock the data dictionary to avoid races with
6465
ibd_file_missing and tablespace_discarded */
6466
row_mysql_lock_data_dictionary(prebuilt->trx);
6468
/* ib_table->space must be an existent tablespace */
6469
if (!ib_table->ibd_file_missing
6470
&& !ib_table->tablespace_discarded) {
6472
stats.delete_length =
6473
fsp_get_available_space_in_free_extents(
6474
ib_table->space) * 1024;
6479
session = ha_session();
6481
push_warning_printf(
6483
DRIZZLE_ERROR::WARN_LEVEL_WARN,
6485
"InnoDB: Trying to get the free "
6486
"space for table %s but its "
6487
"tablespace has been discarded or "
6488
"the .ibd file is missing. Setting "
6489
"the free space to zero.",
6492
stats.delete_length = 0;
6495
row_mysql_unlock_data_dictionary(prebuilt->trx);
6498
stats.check_time = 0;
6500
if (stats.records == 0) {
6501
stats.mean_rec_length = 0;
6503
stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
6507
if (flag & HA_STATUS_CONST) {
6508
index = dict_table_get_first_index(ib_table);
6510
if (prebuilt->clust_index_was_generated) {
6511
index = dict_table_get_next_index(index);
6514
for (i = 0; i < table->s->keys; i++) {
6515
if (index == NULL) {
6516
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
6517
"indexes inside InnoDB than "
6518
"are defined in the MySQL "
6519
".frm file. Have you mixed up "
6520
".frm files from different "
6521
"installations? See "
6523
"innodb-troubleshooting.html\n",
6528
for (j = 0; j < table->key_info[i].key_parts; j++) {
6530
if (j + 1 > index->n_uniq) {
6531
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,
6532
6612
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
6533
6613
"statistics for %lu columns. Have you mixed up .frm files from different "
6534
6614
"installations? "
6535
6615
"See " REFMAN "innodb-troubleshooting.html\n",
6539
index->n_uniq, j + 1);
6543
if (index->stat_n_diff_key_vals[j + 1] == 0) {
6545
rec_per_key = stats.records;
6547
rec_per_key = (ha_rows)(stats.records /
6548
index->stat_n_diff_key_vals[j + 1]);
6551
/* Since MySQL seems to favor table scans
6552
too much over index searches, we pretend
6553
index selectivity is 2 times better than
6556
rec_per_key = rec_per_key / 2;
6558
if (rec_per_key == 0) {
6562
table->key_info[i].rec_per_key[j]=
6563
rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
6564
(ulong) rec_per_key;
6567
index = dict_table_get_next_index(index);
6571
if (flag & HA_STATUS_ERRKEY) {
6572
const dict_index_t* err_index;
6574
ut_a(prebuilt->trx);
6575
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6577
err_index = trx_get_error_info(prebuilt->trx);
6580
errkey = (unsigned int)
6581
row_get_mysql_key_number_for_index(err_index);
6583
errkey = (unsigned int) prebuilt->trx->error_key_num;
6587
if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
6588
stats.auto_increment_value = innobase_peek_autoinc();
6591
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*)"";
6596
6676
/**********************************************************************//**
6597
6677
Updates index cardinalities of the table, based on 8 random dives into
6598
6678
each index tree. This does NOT calculate exact statistics on the table.
6599
@return returns always 0 (success) */
6679
@return returns always 0 (success) */
6602
6682
ha_innobase::analyze(
6603
6683
/*=================*/
6604
Session*) /*!< in: connection thread handle */
6684
Session*) /*!< in: connection thread handle */
6606
/* Simply call ::info() with all the flags */
6607
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);
6612
6692
/*******************************************************************//**
6613
6693
Tries to check that an InnoDB table is not corrupted. If corruption is
6614
6694
noticed, prints to stderr information about it. In case of corruption
6615
6695
may also assert a failure and crash the server.
6616
@return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
6696
@return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
6619
6699
ha_innobase::check(
6620
6700
/*===============*/
6621
Session* session) /*!< in: user thread handle */
6701
Session* session) /*!< in: user thread handle */
6625
assert(session == ha_session());
6626
ut_a(prebuilt->trx);
6627
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6628
ut_a(prebuilt->trx == session_to_trx(session));
6630
if (prebuilt->mysql_template == NULL) {
6631
/* Build the template; we will use a dummy template
6632
in index scans done in checking */
6634
build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
6637
ret = row_check_table_for_mysql(prebuilt);
6639
if (ret == DB_SUCCESS) {
6640
return(HA_ADMIN_OK);
6643
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);
6646
6726
/*************************************************************//**
6647
6727
Adds information about free space in the InnoDB tablespace to a table comment
6648
6728
which is printed out when a user calls SHOW TABLE STATUS. Adds also info on
6650
@return table comment + InnoDB free space + info on foreign keys */
6730
@return table comment + InnoDB free space + info on foreign keys */
6653
6733
ha_innobase::update_table_comment(
6654
6734
/*==============================*/
6655
const char* comment)/*!< in: table comment defined by user */
6735
const char* comment)/*!< in: table comment defined by user */
6657
uint length = (uint) strlen(comment);
6661
/* We do not know if MySQL can call this function before calling
6662
external_lock(). To be safe, update the session of the current table
6665
if (length > 64000 - 3) {
6666
return((char*)comment); /* string too long */
6669
update_session(ha_session());
6671
prebuilt->trx->op_info = (char*)"returning table comment";
6673
/* In case MySQL calls this in the middle of a SELECT query, release
6674
possible adaptive hash latch to avoid deadlocks of threads */
6676
trx_search_latch_release_if_reserved(prebuilt->trx);
6679
/* output the data to a temporary file */
6681
mutex_enter(&srv_dict_tmpfile_mutex);
6682
rewind(srv_dict_tmpfile);
6684
fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
6685
fsp_get_available_space_in_free_extents(
6686
prebuilt->table->space));
6688
dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
6689
prebuilt->trx, prebuilt->table);
6690
flen = ftell(srv_dict_tmpfile);
6693
} else if (length + flen + 3 > 64000) {
6694
flen = 64000 - 3 - length;
6697
/* allocate buffer for the full string, and
6698
read the contents of the temporary file */
6700
str = (char*) malloc(length + flen + 3);
6703
char* pos = str + length;
6705
memcpy(str, comment, length);
6709
rewind(srv_dict_tmpfile);
6710
flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
6714
mutex_exit(&srv_dict_tmpfile_mutex);
6716
prebuilt->trx->op_info = (char*)"";
6718
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);
6721
6801
/*******************************************************************//**
6959
7046
ha_innobase::free_foreign_key_create_info(
6960
7047
/*======================================*/
6961
char* str) /*!< in, own: create info string to free */
7048
char* str) /*!< in, own: create info string to free */
6968
7055
/*******************************************************************//**
6969
7056
Tells something additional to the Cursor about how to do things.
6970
@return 0 or error number */
7057
@return 0 or error number */
6973
7060
ha_innobase::extra(
6974
7061
/*===============*/
6975
enum ha_extra_function operation)
6976
/*!< in: HA_EXTRA_FLUSH or some other flag */
7062
enum ha_extra_function operation)
7063
/*!< in: HA_EXTRA_FLUSH or some other flag */
6978
/* Warning: since it is not sure that MySQL calls external_lock
6979
before calling this function, the trx field in prebuilt can be
6982
switch (operation) {
6983
case HA_EXTRA_FLUSH:
6984
if (prebuilt->blob_heap) {
6985
row_mysql_prebuilt_free_blob_heap(prebuilt);
6988
case HA_EXTRA_RESET_STATE:
6989
reset_template(prebuilt);
6991
case HA_EXTRA_NO_KEYREAD:
6992
prebuilt->read_just_key = 0;
6994
case HA_EXTRA_KEYREAD:
6995
prebuilt->read_just_key = 1;
6997
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
6998
prebuilt->keep_other_fields_on_keyread = 1;
7001
/* IMPORTANT: prebuilt->trx can be obsolete in
7002
this method, because it is not sure that MySQL
7003
calls external_lock before this method with the
7004
parameters below. We must not invoke update_session()
7005
either, because the calling threads may change.
7006
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7007
case HA_EXTRA_IGNORE_DUP_KEY:
7008
session_to_trx(ha_session())->duplicates |= TRX_DUP_IGNORE;
7010
case HA_EXTRA_WRITE_CAN_REPLACE:
7011
session_to_trx(ha_session())->duplicates |= TRX_DUP_REPLACE;
7013
case HA_EXTRA_WRITE_CANNOT_REPLACE:
7014
session_to_trx(ha_session())->duplicates &= ~TRX_DUP_REPLACE;
7016
case HA_EXTRA_NO_IGNORE_DUP_KEY:
7017
session_to_trx(ha_session())->duplicates &=
7018
~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7020
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 */
7029
7116
ha_innobase::reset()
7031
if (prebuilt->blob_heap) {
7032
row_mysql_prebuilt_free_blob_heap(prebuilt);
7035
reset_template(prebuilt);
7037
/* TODO: This should really be reset in reset_template() but for now
7038
it's safer to do it explicitly here. */
7040
/* This is a statement level counter. */
7041
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;
7046
7133
/******************************************************************//**
7047
7134
Maps a MySQL trx isolation level code to the InnoDB isolation level code
7048
@return InnoDB isolation level */
7135
@return InnoDB isolation level */
7051
7138
innobase_map_isolation_level(
7052
7139
/*=========================*/
7053
enum_tx_isolation iso) /*!< in: MySQL isolation level code */
7140
enum_tx_isolation iso) /*!< in: MySQL isolation level code */
7056
case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
7057
case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
7058
case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
7059
case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
7060
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);
7064
7151
/******************************************************************//**
7065
7152
As MySQL will execute an external lock for every new table it uses when it
7066
7153
starts to process an SQL statement. We can use this function to store the pointer to
7067
7154
the Session in the handle.
7071
7158
ha_innobase::external_lock(
7072
7159
/*=======================*/
7073
Session* session, /*!< in: handle to the user thread */
7074
int lock_type) /*!< in: lock type */
7160
Session* session, /*!< in: handle to the user thread */
7161
int lock_type) /*!< in: lock type */
7076
update_session(session);
7163
update_session(session);
7078
7165
trx_t *trx= prebuilt->trx;
7080
prebuilt->sql_stat_start = TRUE;
7081
prebuilt->hint_need_to_fetch_extra_cols = 0;
7083
reset_template(prebuilt);
7085
if (lock_type == F_WRLCK) {
7087
/* If this is a SELECT, then it is in UPDATE TABLE ...
7088
or SELECT ... FOR UPDATE */
7089
prebuilt->select_lock_type = LOCK_X;
7090
prebuilt->stored_select_lock_type = LOCK_X;
7093
if (lock_type != F_UNLCK) {
7094
/* MySQL is setting a new table lock */
7096
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
7097
&& prebuilt->select_lock_type == LOCK_NONE
7098
&& session_test_options(session,
7099
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7101
/* To get serializable execution, we let InnoDB
7102
conceptually add 'LOCK IN SHARE MODE' to all SELECTs
7103
which otherwise would have been consistent reads. An
7104
exception is consistent reads in the AUTOCOMMIT=1 mode:
7105
we know that they are read-only transactions, and they
7106
can be serialized also if performed as consistent
7109
prebuilt->select_lock_type = LOCK_S;
7110
prebuilt->stored_select_lock_type = LOCK_S;
7113
/* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
7114
TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
7115
an InnoDB table lock if it is released immediately at the end
7116
of LOCK TABLES, and InnoDB's table locks in that case cause
7117
VERY easily deadlocks.
7119
We do not set InnoDB table locks if user has not explicitly
7120
requested a table lock. Note that session_in_lock_tables(session)
7121
can hold in some cases, e.g., at the start of a stored
7122
procedure call (SQLCOM_CALL). */
7124
if (prebuilt->select_lock_type != LOCK_NONE) {
7125
trx->mysql_n_tables_locked++;
7128
prebuilt->mysql_has_locked = TRUE;
7133
/* MySQL is releasing a table lock */
7134
prebuilt->mysql_has_locked = FALSE;
7135
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;
7140
7227
/************************************************************************//**
7145
7232
innodb_show_status(
7146
7233
/*===============*/
7147
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7148
Session* session,/*!< in: the MySQL query thread of the caller */
7149
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)
7152
static const char truncated_msg[] = "... truncated...\n";
7153
const long MAX_STATUS_SIZE = 64000;
7154
ulint trx_list_start = ULINT_UNDEFINED;
7155
ulint trx_list_end = ULINT_UNDEFINED;
7157
assert(engine == innodb_engine_ptr);
7159
trx = check_trx_exists(session);
7161
innobase_release_stat_resources(trx);
7163
/* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
7166
long flen, usable_len;
7169
mutex_enter(&srv_monitor_file_mutex);
7170
rewind(srv_monitor_file);
7171
srv_printf_innodb_monitor(srv_monitor_file,
7172
&trx_list_start, &trx_list_end);
7173
flen = ftell(srv_monitor_file);
7174
os_file_set_eof(srv_monitor_file);
7180
if (flen > MAX_STATUS_SIZE) {
7181
usable_len = MAX_STATUS_SIZE;
7186
/* allocate buffer for the string, and
7187
read the contents of the temporary file */
7189
if (!(str = (char*) malloc(usable_len + 1))) {
7190
mutex_exit(&srv_monitor_file_mutex);
7194
rewind(srv_monitor_file);
7195
if (flen < MAX_STATUS_SIZE) {
7196
/* Display the entire output. */
7197
flen = (long) fread(str, 1, flen, srv_monitor_file);
7198
} else if (trx_list_end < (ulint) flen
7199
&& trx_list_start < trx_list_end
7200
&& trx_list_start + (flen - trx_list_end)
7201
< MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
7202
/* Omit the beginning of the list of active transactions. */
7203
long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
7204
memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
7205
len += sizeof truncated_msg - 1;
7206
usable_len = (MAX_STATUS_SIZE - 1) - len;
7207
fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
7208
len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
7211
/* Omit the end of the output. */
7212
flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
7215
mutex_exit(&srv_monitor_file_mutex);
7217
bool result = FALSE;
7219
if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
7220
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)) {
7228
7315
/************************************************************************//**
7232
7319
innodb_mutex_show_status(
7233
7320
/*=====================*/
7234
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7235
Session* session, /*!< in: the MySQL query thread of the
7237
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)
7239
char buf1[IO_SIZE], buf2[IO_SIZE];
7326
char buf1[IO_SIZE], buf2[IO_SIZE];
7242
7329
#ifdef UNIV_DEBUG
7243
ulint rw_lock_count= 0;
7244
ulint rw_lock_count_spin_loop= 0;
7245
ulint rw_lock_count_spin_rounds= 0;
7246
ulint rw_lock_count_os_wait= 0;
7247
ulint rw_lock_count_os_yield= 0;
7248
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;
7249
7336
#endif /* UNIV_DEBUG */
7250
uint engine_name_len= strlen(innobase_engine_name), buf1len, buf2len;
7251
assert(engine == innodb_engine_ptr);
7253
mutex_enter(&mutex_list_mutex);
7255
mutex = UT_LIST_GET_FIRST(mutex_list);
7257
while (mutex != NULL) {
7258
if (mutex->count_os_wait == 0
7259
|| 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)) {
7262
7349
#ifdef UNIV_DEBUG
7263
if (mutex->mutex_type != 1) {
7264
if (mutex->count_using > 0) {
7265
buf1len= my_snprintf(buf1, sizeof(buf1),
7267
mutex->cmutex_name, mutex->cfile_name);
7268
buf2len= my_snprintf(buf2, sizeof(buf2),
7269
"count=%lu, spin_waits=%lu,"
7270
" spin_rounds=%lu, "
7271
"os_waits=%lu, os_yields=%lu,"
7272
" os_wait_times=%lu",
7274
mutex->count_spin_loop,
7275
mutex->count_spin_rounds,
7276
mutex->count_os_wait,
7277
mutex->count_os_yield,
7278
(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));
7280
if (stat_print(session, innobase_engine_name,
7281
engine_name_len, buf1, buf1len,
7283
mutex_exit(&mutex_list_mutex);
7289
rw_lock_count += mutex->count_using;
7290
rw_lock_count_spin_loop += mutex->count_spin_loop;
7291
rw_lock_count_spin_rounds += mutex->count_spin_rounds;
7292
rw_lock_count_os_wait += mutex->count_os_wait;
7293
rw_lock_count_os_yield += mutex->count_os_yield;
7294
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;
7296
7383
#else /* UNIV_DEBUG */
7297
buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
7298
mutex->cfile_name, (ulong) mutex->cline);
7299
buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
7300
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);
7302
if (stat_print(session, innobase_engine_name,
7303
engine_name_len, buf1, buf1len,
7305
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);
7308
7395
#endif /* UNIV_DEBUG */
7311
mutex = UT_LIST_GET_NEXT(list, mutex);
7314
mutex_exit(&mutex_list_mutex);
7316
mutex_enter(&rw_lock_list_mutex);
7318
lock = UT_LIST_GET_FIRST(rw_lock_list);
7320
while (lock != NULL) {
7321
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
7322
7409
&& !buf_pool_is_block_lock(lock)) {
7323
buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
7410
buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
7324
7411
lock->cfile_name, (unsigned long) lock->cline);
7325
buf2len= snprintf(buf2, sizeof(buf2),
7412
buf2len= snprintf(buf2, sizeof(buf2),
7326
7413
"os_waits=%lu", lock->count_os_wait);
7328
if (stat_print(session, innobase_engine_name,
7329
engine_name_len, buf1, buf1len,
7331
mutex_exit(&rw_lock_list_mutex);
7335
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);
7338
mutex_exit(&rw_lock_list_mutex);
7425
mutex_exit(&rw_lock_list_mutex);
7340
7427
#ifdef UNIV_DEBUG
7341
buf2len= my_snprintf(buf2, sizeof(buf2),
7342
"count=%lu, spin_waits=%lu, spin_rounds=%lu, "
7343
"os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
7344
rw_lock_count, rw_lock_count_spin_loop,
7345
rw_lock_count_spin_rounds,
7346
rw_lock_count_os_wait, rw_lock_count_os_yield,
7347
(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));
7349
if (stat_print(session, innobase_engine_name, engine_name_len,
7350
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)) {
7353
7440
#endif /* UNIV_DEBUG */
7358
7445
bool InnobaseEngine::show_status(Session* session,
7359
7446
stat_print_fn* stat_print,
7360
7447
enum ha_stat_type stat_type)
7362
assert(this == innodb_engine_ptr);
7449
assert(this == innodb_engine_ptr);
7364
switch (stat_type) {
7365
case HA_ENGINE_STATUS:
7366
return innodb_show_status(this, session, stat_print);
7367
case HA_ENGINE_MUTEX:
7368
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);
7374
7461
/************************************************************************//**
7452
7539
SELECT the read lock is released early on the 'const' tables where we only
7453
7540
fetch one row. MySQL does not call this when it releases all locks at the
7454
7541
end of an SQL statement.
7455
@return pointer to the next element in the 'to' array */
7542
@return pointer to the next element in the 'to' array */
7457
7544
THR_LOCK_DATA**
7458
7545
ha_innobase::store_lock(
7459
7546
/*====================*/
7460
Session* session, /*!< in: user thread handle */
7461
THR_LOCK_DATA** to, /*!< in: pointer to an array
7462
of pointers to lock structs;
7463
pointer to the 'lock' field
7464
of current handle is stored
7465
next to this array */
7466
enum thr_lock_type lock_type) /*!< in: lock type to store in
7467
'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
7472
/* Note that trx in this function is NOT necessarily prebuilt->trx
7473
because we call update_session() later, in ::external_lock()! Failure to
7474
understand this caused a serious memory corruption bug in 5.1.11. */
7476
trx = check_trx_exists(session);
7478
assert(EQ_CURRENT_SESSION(session));
7479
const uint32_t sql_command = session_sql_command(session);
7481
if (sql_command == SQLCOM_DROP_TABLE) {
7483
/* MySQL calls this function in DROP Table though this table
7484
handle may belong to another session that is running a query.
7485
Let us in that case skip any changes to the prebuilt struct. */
7487
} else if (lock_type == TL_READ_WITH_SHARED_LOCKS
7488
|| lock_type == TL_READ_NO_INSERT
7489
|| (lock_type != TL_IGNORE
7490
&& sql_command != SQLCOM_SELECT)) {
7492
/* The OR cases above are in this order:
7493
1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
7494
are processing a stored procedure or function, or
7495
2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
7496
3) this is a SELECT ... IN SHARE MODE, or
7497
4) we are doing a complex SQL statement like
7498
INSERT INTO ... SELECT ... and the logical logging (MySQL
7499
binlog) requires the use of a locking read, or
7500
MySQL is doing LOCK TABLES ... READ.
7501
5) we let InnoDB do locking reads for all SQL statements that
7502
are not simple SELECTs; note that select_lock_type in this
7503
case may get strengthened in ::external_lock() to LOCK_X.
7504
Note that we MUST use a locking read in all data modifying
7505
SQL statements, because otherwise the execution would not be
7506
serializable, and also the results from the update could be
7507
unexpected if an obsolete consistent read view would be
7510
ulint isolation_level;
7512
isolation_level = trx->isolation_level;
7514
if ((srv_locks_unsafe_for_binlog
7515
|| isolation_level == TRX_ISO_READ_COMMITTED)
7516
&& isolation_level != TRX_ISO_SERIALIZABLE
7517
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
7518
&& (sql_command == SQLCOM_INSERT_SELECT
7519
|| sql_command == SQLCOM_UPDATE
7520
|| sql_command == SQLCOM_CREATE_TABLE)) {
7522
/* If we either have innobase_locks_unsafe_for_binlog
7523
option set or this session is using READ COMMITTED
7524
isolation level and isolation level of the transaction
7525
is not set to serializable and MySQL is doing
7526
INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
7527
CREATE ... SELECT... without FOR UPDATE or
7528
IN SHARE MODE in select, then we use consistent
7531
prebuilt->select_lock_type = LOCK_NONE;
7532
prebuilt->stored_select_lock_type = LOCK_NONE;
7533
} else if (sql_command == SQLCOM_CHECKSUM) {
7534
/* Use consistent read for checksum table */
7536
prebuilt->select_lock_type = LOCK_NONE;
7537
prebuilt->stored_select_lock_type = LOCK_NONE;
7539
prebuilt->select_lock_type = LOCK_S;
7540
prebuilt->stored_select_lock_type = LOCK_S;
7543
} else if (lock_type != TL_IGNORE) {
7545
/* We set possible LOCK_X value in external_lock, not yet
7546
here even if this would be SELECT ... FOR UPDATE */
7548
prebuilt->select_lock_type = LOCK_NONE;
7549
prebuilt->stored_select_lock_type = LOCK_NONE;
7552
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
7554
/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
7555
TABLESPACE or TRUNCATE TABLE then allow multiple
7556
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
7557
< TL_WRITE_CONCURRENT_INSERT.
7560
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
7561
&& lock_type <= TL_WRITE)
7562
&& !session_tablespace_op(session)
7563
&& sql_command != SQLCOM_TRUNCATE
7564
&& sql_command != SQLCOM_CREATE_TABLE) {
7566
lock_type = TL_WRITE_ALLOW_WRITE;
7569
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
7570
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
7571
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
7572
to t2. Convert the lock to a normal read lock to allow
7573
concurrent inserts to t2.
7576
if (lock_type == TL_READ_NO_INSERT) {
7578
lock_type = TL_READ;
7581
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;
7589
7676
/*********************************************************************//**
7590
7677
Read the next autoinc value. Acquire the relevant locks before reading
7591
7678
the AUTOINC value. If SUCCESS then the table AUTOINC mutex will be locked
7592
7679
on return and all relevant locks acquired.
7593
@return DB_SUCCESS or error code */
7680
@return DB_SUCCESS or error code */
7596
7683
ha_innobase::innobase_get_autoinc(
7597
7684
/*==============================*/
7598
uint64_t* value) /*!< out: autoinc value */
7685
uint64_t* value) /*!< out: autoinc value */
7602
prebuilt->autoinc_error = innobase_lock_autoinc();
7604
if (prebuilt->autoinc_error == DB_SUCCESS) {
7606
/* Determine the first value of the interval */
7607
*value = dict_table_autoinc_read(prebuilt->table);
7609
/* It should have been initialized during open. */
7613
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);
7616
7703
/*******************************************************************//**
7617
7704
This function reads the global auto-inc counter. It doesn't use the
7618
7705
AUTOINC lock even if the lock mode is set to TRADITIONAL.
7619
@return the autoinc value */
7706
@return the autoinc value */
7622
7709
ha_innobase::innobase_peek_autoinc(void)
7623
7710
/*====================================*/
7626
dict_table_t* innodb_table;
7628
ut_a(prebuilt != NULL);
7629
ut_a(prebuilt->table != NULL);
7631
innodb_table = prebuilt->table;
7633
dict_table_autoinc_lock(innodb_table);
7635
auto_inc = dict_table_autoinc_read(innodb_table);
7639
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);
7644
7731
/*********************************************************************//**
7653
7740
ha_innobase::get_auto_increment(
7654
7741
/*============================*/
7655
uint64_t offset, /*!< in: table autoinc offset */
7656
uint64_t increment, /*!< in: table autoinc increment */
7657
uint64_t nb_desired_values, /*!< in: number of values reqd */
7658
uint64_t *first_value, /*!< out: the autoinc value */
7659
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 */
7663
uint64_t autoinc = 0;
7665
/* Prepare prebuilt->trx in the table handle */
7666
update_session(ha_session());
7668
error = innobase_get_autoinc(&autoinc);
7670
if (error != DB_SUCCESS) {
7671
*first_value = (~(uint64_t) 0);
7675
/* This is a hack, since nb_desired_values seems to be accurate only
7676
for the first call to get_auto_increment() for multi-row INSERT and
7677
meaningless for other statements e.g, LOAD etc. Subsequent calls to
7678
this method for the same statement results in different values which
7679
don't make sense. Therefore we store the value the first time we are
7680
called and count down from that as rows are written (see write_row()).
7683
trx = prebuilt->trx;
7685
/* Note: We can't rely on *first_value since some MySQL engines,
7686
in particular the partition engine, don't initialize it to 0 when
7687
invoking this method. So we are not sure if it's guaranteed to
7690
/* Called for the first time ? */
7691
if (trx->n_autoinc_rows == 0) {
7693
trx->n_autoinc_rows = (ulint) nb_desired_values;
7695
/* It's possible for nb_desired_values to be 0:
7696
e.g., INSERT INTO T1(C) SELECT C FROM T2; */
7697
if (nb_desired_values == 0) {
7699
trx->n_autoinc_rows = 1;
7702
set_if_bigger(*first_value, autoinc);
7703
/* Not in the middle of a mult-row INSERT. */
7704
} else if (prebuilt->autoinc_last_value == 0) {
7705
set_if_bigger(*first_value, autoinc);
7708
*nb_reserved_values = trx->n_autoinc_rows;
7710
/* With old style AUTOINC locking we only update the table's
7711
AUTOINC counter after attempting to insert the row. */
7712
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
7714
uint64_t next_value;
7715
uint64_t col_max_value;
7717
/* We need the upper limit of the col type to check for
7718
whether we update the table autoinc counter or not. */
7719
col_max_value = innobase_get_int_col_max_value(
7720
table->next_number_field);
7722
need = *nb_reserved_values * increment;
7724
/* Compute the last value in the interval */
7725
next_value = innobase_next_autoinc(
7726
*first_value, need, offset, col_max_value);
7728
prebuilt->autoinc_last_value = next_value;
7730
if (prebuilt->autoinc_last_value < *first_value) {
7731
*first_value = (~(unsigned long long) 0);
7733
/* Update the table autoinc variable */
7734
dict_table_autoinc_update_if_greater(
7735
prebuilt->table, prebuilt->autoinc_last_value);
7738
/* This will force write_row() into attempting an update
7739
of the table's AUTOINC counter. */
7740
prebuilt->autoinc_last_value = 0;
7743
/* The increment to be used to increase the AUTOINC value, we use
7744
this in write_row() and update_row() to increase the autoinc counter
7745
for columns that are filled by the user. We need the offset and
7747
prebuilt->autoinc_offset = offset;
7748
prebuilt->autoinc_increment = increment;
7750
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);
7753
7840
/*******************************************************************//**
7872
7959
characters for prefix indexes using a multibyte character set. The function
7873
7960
finds charset information and returns length of prefix_len characters in the
7874
7961
index field in bytes.
7875
@return number of bytes occupied by the first n characters */
7962
@return number of bytes occupied by the first n characters */
7876
7963
extern "C" UNIV_INTERN
7878
7965
innobase_get_at_most_n_mbchars(
7879
7966
/*===========================*/
7880
ulint charset_id, /*!< in: character set id */
7881
ulint prefix_len, /*!< in: prefix length in bytes of the index
7882
(this has to be divided by mbmaxlen to get the
7883
number of CHARACTERS n in the prefix) */
7884
ulint data_len, /*!< in: length of the string in bytes */
7885
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 */
7888
7975
innobase_get_at_most_n_mbchars(
7889
7976
/*===========================*/
7890
ulint charset_id, /*!< in: character set id */
7891
ulint prefix_len, /*!< in: prefix length in bytes of the index
7892
(this has to be divided by mbmaxlen to get the
7893
number of CHARACTERS n in the prefix) */
7894
ulint data_len, /*!< in: length of the string in bytes */
7895
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 */
7897
ulint char_length; /*!< character length in bytes */
7898
ulint n_chars; /*!< number of characters in prefix */
7899
const CHARSET_INFO* charset; /*!< charset used in the field */
7901
charset = get_charset((uint) charset_id);
7904
ut_ad(charset->mbmaxlen);
7906
/* Calculate how many characters at most the prefix index contains */
7908
n_chars = prefix_len / charset->mbmaxlen;
7910
/* If the charset is multi-byte, then we must find the length of the
7911
first at most n chars in the string. If the string contains less
7912
characters than n, then we return the length to the end of the last
7915
if (charset->mbmaxlen > 1) {
7916
/* my_charpos() returns the byte length of the first n_chars
7917
characters, or a value bigger than the length of str, if
7918
there were not enough full characters in str.
7920
Why does the code below work:
7921
Suppose that we are looking for n UTF-8 characters.
7923
1) If the string is long enough, then the prefix contains at
7924
least n complete UTF-8 characters + maybe some extra
7925
characters + an incomplete UTF-8 character. No problem in
7926
this case. The function returns the pointer to the
7927
end of the nth character.
7929
2) If the string is not long enough, then the string contains
7930
the complete value of a column, that is, only complete UTF-8
7931
characters, and we can store in the column prefix index the
7934
char_length = my_charpos(charset, str,
7935
str + data_len, (int) n_chars);
7936
if (char_length > data_len) {
7937
char_length = data_len;
7940
if (data_len < prefix_len) {
7941
char_length = data_len;
7943
char_length = prefix_len;
7947
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);
7950
8037
* We will also use this function to communicate
8003
8090
/*******************************************************************//**
8004
8091
This function is used to prepare an X/Open XA distributed transaction.
8005
@return 0 or error number */
8092
@return 0 or error number */
8007
8094
InnobaseEngine::doXaPrepare(
8008
8095
/*================*/
8009
Session* session,/*!< in: handle to the MySQL thread of
8010
the user whose XA transaction should
8012
bool all) /*!< in: TRUE - commit transaction
8013
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
8017
trx_t* trx = check_trx_exists(session);
8019
assert(this == innodb_engine_ptr);
8021
/* we use support_xa value as it was seen at transaction start
8022
time, not the current session variable value. Any possible changes
8023
to the session variable take effect only in the next transaction */
8024
if (!trx->support_xa) {
8029
session_get_xid(session, reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
8031
/* Release a possible FIFO ticket and search latch. Since we will
8032
reserve the kernel mutex, we have to release the search system latch
8033
first to obey the latching order. */
8035
innobase_release_stat_resources(trx);
8038
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
8040
/* We were instructed to prepare the whole transaction, or
8041
this is an SQL statement end and autocommit is on */
8043
ut_ad(trx->conc_state != TRX_NOT_STARTED);
8045
error = (int) trx_prepare_for_mysql(trx);
8047
/* We just mark the SQL statement ended and do not do a
8048
transaction prepare */
8050
/* If we had reserved the auto-inc lock for some
8051
table in this SQL statement we release it now */
8053
row_unlock_table_autoinc_for_mysql(trx);
8055
/* Store the current undo_no of the transaction so that we
8056
know where to roll back if we have to roll back the next
8059
trx_mark_sql_stat_end(trx);
8062
/* Tell the InnoDB server that there might be work for utility
8065
srv_active_wake_master_thread();
8067
if (all || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
8070
/* For ibbackup to work the order of transactions in binlog
8071
and InnoDB must be the same. Consider the situation
8073
thread1> prepare; write to binlog; ...
8075
thread2> prepare; write to binlog; commit
8078
To ensure this will not happen we're taking the mutex on
8079
prepare, and releasing it on commit.
8081
Note: only do it for normal commits, done via ha_commit_trans.
8082
If 2pc protocol is executed by external transaction
8083
coordinator, it will be just a regular MySQL client
8084
executing XA PREPARE and XA COMMIT commands.
8085
In this case we cannot know how many minutes or hours
8086
will be between XA PREPARE and XA COMMIT, and we don't want
8087
to block for undefined period of time.
8089
pthread_mutex_lock(&prepare_commit_mutex);
8090
trx->conc_state = TRX_PREPARED;
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();
8095
8157
/*******************************************************************//**
8096
8158
This function is used to recover X/Open XA distributed transactions.
8097
@return number of prepared transactions stored in xid_list */
8159
@return number of prepared transactions stored in xid_list */
8099
8161
InnobaseEngine::doXaRecover(
8100
8162
/*================*/
8101
::drizzled::XID* xid_list,/*!< in/out: prepared transactions */
8102
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 */
8104
assert(this == innodb_engine_ptr);
8106
if (len == 0 || xid_list == NULL) {
8111
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));
8114
8176
/*******************************************************************//**
8115
8177
This function is used to commit one X/Open XA distributed transaction
8116
8178
which is in the prepared state
8117
@return 0 or error number */
8179
@return 0 or error number */
8119
8181
InnobaseEngine::doXaCommitXid(
8120
8182
/*===================*/
8121
::drizzled::XID* xid) /*!< in: X/Open XA transaction identification */
8183
::drizzled::XID* xid) /*!< in: X/Open XA transaction identification */
8125
assert(this == innodb_engine_ptr);
8127
trx = trx_get_trx_by_xid((::XID *)xid);
8130
innobase_commit_low(trx);
8187
assert(this == innodb_engine_ptr);
8189
trx = trx_get_trx_by_xid((::XID *)xid);
8192
innobase_commit_low(trx);
8138
8200
/*******************************************************************//**
8139
8201
This function is used to rollback one X/Open XA distributed transaction
8140
8202
which is in the prepared state
8141
@return 0 or error number */
8203
@return 0 or error number */
8143
8205
InnobaseEngine::doXaRollbackXid(
8144
8206
/*=====================*/
8145
::drizzled::XID* xid) /*!< in: X/Open XA transaction
8207
::drizzled::XID* xid) /*!< in: X/Open XA transaction
8150
assert(this == innodb_engine_ptr);
8152
trx = trx_get_trx_by_xid((::XID *)xid);
8155
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));
8162
8224
/************************************************************//**
8163
8225
Validate the file format name and return its corresponding id.
8164
@return valid file format id */
8226
@return valid file format id */
8167
8229
innobase_file_format_name_lookup(
8168
8230
/*=============================*/
8169
const char* format_name) /*!< in: pointer to file format name */
8231
const char* format_name) /*!< in: pointer to file format name */
8174
ut_a(format_name != NULL);
8176
/* The format name can contain the format id itself instead of
8177
the name and we check for that. */
8178
format_id = (uint) strtoul(format_name, &endp, 10);
8180
/* Check for valid parse. */
8181
if (*endp == '\0' && *format_name != '\0') {
8183
if (format_id <= DICT_TF_FORMAT_MAX) {
8189
for (format_id = 0; format_id <= DICT_TF_FORMAT_MAX;
8193
name = trx_sys_file_format_id_to_name(format_id);
8195
if (!innobase_strcasecmp(format_name, name)) {
8202
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);
8205
8267
/************************************************************//**
8206
8268
Validate the file format check value, is it one of "on" or "off",
8207
8269
as a side effect it sets the srv_check_file_format_at_startup variable.
8208
@return true if config value one of "on" or "off" */
8270
@return true if config value one of "on" or "off" */
8211
8273
innobase_file_format_check_on_off(
8212
8274
/*==============================*/
8213
const char* format_check) /*!< in: parameter value */
8275
const char* format_check) /*!< in: parameter value */
8217
if (!innobase_strcasecmp(format_check, "off")) {
8219
/* Set the value to disable checking. */
8220
srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
8222
} else if (!innobase_strcasecmp(format_check, "on")) {
8224
/* Set the value to the lowest supported format. */
8225
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;
8233
8295
/************************************************************//**
8234
8296
Validate the file format check config parameters, as a side effect it
8235
8297
sets the srv_check_file_format_at_startup variable.
8236
@return true if valid config value */
8298
@return true if valid config value */
8239
8301
innobase_file_format_check_validate(
8240
8302
/*================================*/
8241
const char* format_check) /*!< in: parameter value */
8303
const char* format_check) /*!< in: parameter value */
8246
format_id = innobase_file_format_name_lookup(format_check);
8248
if (format_id < DICT_TF_FORMAT_MAX + 1) {
8249
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;
8257
8319
/*************************************************************//**
8258
8320
Check if it is a valid file format. This function is registered as
8259
8321
a callback with MySQL.
8260
@return 0 for valid file format */
8322
@return 0 for valid file format */
8263
8325
innodb_file_format_name_validate(
8264
8326
/*=============================*/
8265
Session* , /*!< in: thread handle */
8266
drizzle_sys_var* , /*!< in: pointer to system
8268
void* save, /*!< out: immediate result
8269
for update function */
8270
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 */
8272
const char* file_format_input;
8273
char buff[STRING_BUFFER_USUAL_SIZE];
8274
int len = sizeof(buff);
8277
ut_a(value != NULL);
8279
file_format_input = value->val_str(value, buff, &len);
8281
if (file_format_input != NULL) {
8284
format_id = innobase_file_format_name_lookup(
8287
if (format_id <= DICT_TF_FORMAT_MAX) {
8289
*static_cast<const char**>(save) = file_format_input;
8294
*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;
8298
8360
/****************************************************************//**
8888
8943
innobase_commit_concurrency_init_default(void)
8889
8944
/*==========================================*/
8891
DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
8892
= innobase_commit_concurrency;
8946
DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
8947
= innobase_commit_concurrency;
8895
8950
#ifdef UNIV_COMPILE_TEST_FUNCS
8897
8952
typedef struct innobase_convert_name_test_struct {
8905
const char* expected;
8960
const char* expected;
8906
8961
} innobase_convert_name_test_t;
8909
8964
test_innobase_convert_name()
8914
innobase_convert_name_test_t test_input[] = {
8915
{buf, sizeof(buf), "abcd", 4, NULL, TRUE, "\"abcd\""},
8916
{buf, 7, "abcd", 4, NULL, TRUE, "\"abcd\""},
8917
{buf, 6, "abcd", 4, NULL, TRUE, "\"abcd\""},
8918
{buf, 5, "abcd", 4, NULL, TRUE, "\"abc\""},
8919
{buf, 4, "abcd", 4, NULL, TRUE, "\"ab\""},
8921
{buf, sizeof(buf), "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8922
{buf, 9, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8923
{buf, 8, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8924
{buf, 7, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8925
{buf, 6, "ab@0060cd", 9, NULL, TRUE, "\"ab`c\""},
8926
{buf, 5, "ab@0060cd", 9, NULL, TRUE, "\"ab`\""},
8927
{buf, 4, "ab@0060cd", 9, NULL, TRUE, "\"ab\""},
8929
{buf, sizeof(buf), "ab\"cd", 5, NULL, TRUE,
8930
"\"#mysql50#ab\"\"cd\""},
8931
{buf, 17, "ab\"cd", 5, NULL, TRUE,
8932
"\"#mysql50#ab\"\"cd\""},
8933
{buf, 16, "ab\"cd", 5, NULL, TRUE,
8934
"\"#mysql50#ab\"\"c\""},
8935
{buf, 15, "ab\"cd", 5, NULL, TRUE,
8936
"\"#mysql50#ab\"\"\""},
8937
{buf, 14, "ab\"cd", 5, NULL, TRUE,
8939
{buf, 13, "ab\"cd", 5, NULL, TRUE,
8941
{buf, 12, "ab\"cd", 5, NULL, TRUE,
8943
{buf, 11, "ab\"cd", 5, NULL, TRUE,
8945
{buf, 10, "ab\"cd", 5, NULL, TRUE,
8948
{buf, sizeof(buf), "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
8949
{buf, 9, "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
8950
{buf, 8, "ab/cd", 5, NULL, TRUE, "\"ab\".\"c\""},
8951
{buf, 7, "ab/cd", 5, NULL, TRUE, "\"ab\".\"\""},
8952
{buf, 6, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
8953
{buf, 5, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
8954
{buf, 4, "ab/cd", 5, NULL, TRUE, "\"ab\""},
8955
{buf, 3, "ab/cd", 5, NULL, TRUE, "\"a\""},
8956
{buf, 2, "ab/cd", 5, NULL, TRUE, "\"\""},
8957
/* XXX probably "" is a better result in this case
8958
{buf, 1, "ab/cd", 5, NULL, TRUE, "."},
8960
{buf, 0, "ab/cd", 5, NULL, TRUE, ""},
8963
for (i = 0; i < sizeof(test_input) / sizeof(test_input[0]); i++) {
8969
fprintf(stderr, "TESTING %lu, %s, %lu, %s\n",
8970
test_input[i].buflen,
8972
test_input[i].idlen,
8973
test_input[i].expected);
8975
end = innobase_convert_name(
8977
test_input[i].buflen,
8979
test_input[i].idlen,
8980
test_input[i].session,
8981
test_input[i].file_id);
8983
res_len = (size_t) (end - test_input[i].buf);
8985
if (res_len != strlen(test_input[i].expected)) {
8987
fprintf(stderr, "unexpected len of the result: %u, "
8988
"expected: %u\n", (unsigned) res_len,
8989
(unsigned) strlen(test_input[i].expected));
8993
if (memcmp(test_input[i].buf,
8994
test_input[i].expected,
8995
strlen(test_input[i].expected)) != 0
8998
fprintf(stderr, "unexpected result: %.*s, "
8999
"expected: %s\n", (int) res_len,
9001
test_input[i].expected);
9006
fprintf(stderr, "OK: res: %.*s\n\n", (int) res_len,
9009
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");
9015
9070
#endif /* UNIV_COMPILE_TEST_FUNCS */