643
505
NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
508
/***********************************************************************
509
Closes an InnoDB database. */
512
innobase_deinit(plugin::Registry ®istry);
646
514
/*****************************************************************//**
647
515
Commits a transaction in an InnoDB database. */
650
518
innobase_commit_low(
651
519
/*================*/
652
trx_t* trx); /*!< in: transaction handle */
520
trx_t* trx); /*!< in: transaction handle */
654
522
static drizzle_show_var innodb_status_variables[]= {
655
523
{"buffer_pool_pages_data",
656
(char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG},
524
(char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG},
657
525
{"buffer_pool_pages_dirty",
658
(char*) &export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG},
526
(char*) &export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG},
659
527
{"buffer_pool_pages_flushed",
660
528
(char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG},
661
529
{"buffer_pool_pages_free",
662
(char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG},
530
(char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG},
663
531
#ifdef UNIV_DEBUG
664
532
{"buffer_pool_pages_latched",
665
533
(char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG},
666
534
#endif /* UNIV_DEBUG */
667
535
{"buffer_pool_pages_misc",
668
(char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
536
(char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
669
537
{"buffer_pool_pages_total",
670
(char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG},
671
{"buffer_pool_read_ahead",
672
(char*) &export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG},
673
{"buffer_pool_read_ahead_evicted",
674
(char*) &export_vars.innodb_buffer_pool_read_ahead_evicted, SHOW_LONG},
538
(char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG},
539
{"buffer_pool_read_ahead_rnd",
540
(char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
541
{"buffer_pool_read_ahead_seq",
542
(char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
675
543
{"buffer_pool_read_requests",
676
544
(char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG},
677
545
{"buffer_pool_reads",
678
(char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG},
546
(char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG},
679
547
{"buffer_pool_wait_free",
680
(char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG},
548
(char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG},
681
549
{"buffer_pool_write_requests",
682
550
(char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
684
(char*) &export_vars.innodb_data_fsyncs, SHOW_LONG},
552
(char*) &export_vars.innodb_data_fsyncs, SHOW_LONG},
685
553
{"data_pending_fsyncs",
686
(char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG},
554
(char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG},
687
555
{"data_pending_reads",
688
(char*) &export_vars.innodb_data_pending_reads, SHOW_LONG},
556
(char*) &export_vars.innodb_data_pending_reads, SHOW_LONG},
689
557
{"data_pending_writes",
690
(char*) &export_vars.innodb_data_pending_writes, SHOW_LONG},
558
(char*) &export_vars.innodb_data_pending_writes, SHOW_LONG},
692
(char*) &export_vars.innodb_data_read, SHOW_LONG},
560
(char*) &export_vars.innodb_data_read, SHOW_LONG},
694
(char*) &export_vars.innodb_data_reads, SHOW_LONG},
562
(char*) &export_vars.innodb_data_reads, SHOW_LONG},
696
(char*) &export_vars.innodb_data_writes, SHOW_LONG},
564
(char*) &export_vars.innodb_data_writes, SHOW_LONG},
698
(char*) &export_vars.innodb_data_written, SHOW_LONG},
566
(char*) &export_vars.innodb_data_written, SHOW_LONG},
699
567
{"dblwr_pages_written",
700
(char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
568
(char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
702
(char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
570
(char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
703
571
{"have_atomic_builtins",
704
(char*) &export_vars.innodb_have_atomic_builtins, SHOW_BOOL},
572
(char*) &export_vars.innodb_have_atomic_builtins, SHOW_BOOL},
706
(char*) &export_vars.innodb_log_waits, SHOW_LONG},
574
(char*) &export_vars.innodb_log_waits, SHOW_LONG},
707
575
{"log_write_requests",
708
(char*) &export_vars.innodb_log_write_requests, SHOW_LONG},
576
(char*) &export_vars.innodb_log_write_requests, SHOW_LONG},
710
(char*) &export_vars.innodb_log_writes, SHOW_LONG},
578
(char*) &export_vars.innodb_log_writes, SHOW_LONG},
711
579
{"os_log_fsyncs",
712
(char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG},
580
(char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG},
713
581
{"os_log_pending_fsyncs",
714
(char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG},
582
(char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG},
715
583
{"os_log_pending_writes",
716
(char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG},
584
(char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG},
717
585
{"os_log_written",
718
(char*) &export_vars.innodb_os_log_written, SHOW_LONG},
586
(char*) &export_vars.innodb_os_log_written, SHOW_LONG},
720
(char*) &export_vars.innodb_page_size, SHOW_LONG},
588
(char*) &export_vars.innodb_page_size, SHOW_LONG},
721
589
{"pages_created",
722
(char*) &export_vars.innodb_pages_created, SHOW_LONG},
590
(char*) &export_vars.innodb_pages_created, SHOW_LONG},
724
(char*) &export_vars.innodb_pages_read, SHOW_LONG},
592
(char*) &export_vars.innodb_pages_read, SHOW_LONG},
725
593
{"pages_written",
726
(char*) &export_vars.innodb_pages_written, SHOW_LONG},
594
(char*) &export_vars.innodb_pages_written, SHOW_LONG},
727
595
{"row_lock_current_waits",
728
(char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG},
596
(char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG},
729
597
{"row_lock_time",
730
(char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG},
598
(char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG},
731
599
{"row_lock_time_avg",
732
(char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG},
600
(char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG},
733
601
{"row_lock_time_max",
734
(char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG},
602
(char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG},
735
603
{"row_lock_waits",
736
(char*) &export_vars.innodb_row_lock_waits, SHOW_LONG},
604
(char*) &export_vars.innodb_row_lock_waits, SHOW_LONG},
738
(char*) &export_vars.innodb_rows_deleted, SHOW_LONG},
606
(char*) &export_vars.innodb_rows_deleted, SHOW_LONG},
739
607
{"rows_inserted",
740
(char*) &export_vars.innodb_rows_inserted, SHOW_LONG},
608
(char*) &export_vars.innodb_rows_inserted, SHOW_LONG},
742
(char*) &export_vars.innodb_rows_read, SHOW_LONG},
610
(char*) &export_vars.innodb_rows_read, SHOW_LONG},
744
(char*) &export_vars.innodb_rows_updated, SHOW_LONG},
612
(char*) &export_vars.innodb_rows_updated, SHOW_LONG},
745
613
{NULL, NULL, SHOW_LONG}
978
846
innobase_active_small(void)
979
847
/*=======================*/
981
innobase_active_counter++;
849
innobase_active_counter++;
983
if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
984
srv_active_wake_master_thread();
851
if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
852
srv_active_wake_master_thread();
988
856
/********************************************************************//**
989
857
Converts an InnoDB error code to a MySQL error code and also tells to MySQL
990
858
about a possible transaction rollback inside InnoDB caused by a lock wait
991
859
timeout or a deadlock.
992
@return MySQL error code */
860
@return MySQL error code */
993
861
extern "C" UNIV_INTERN
995
863
convert_error_code_to_mysql(
996
864
/*========================*/
997
int error, /*!< in: InnoDB error code */
998
ulint flags, /*!< in: InnoDB table flags, or 0 */
999
Session* session)/*!< in: user thread handle or NULL */
1005
case DB_INTERRUPTED:
1006
my_error(ER_QUERY_INTERRUPTED, MYF(0));
1010
return(-1); /* unspecified error */
1012
case DB_DUPLICATE_KEY:
1013
/* Be cautious with returning this error, since
1014
mysql could re-enter the storage layer to get
1015
duplicated key info, the operation requires a
1016
valid table handle and/or transaction information,
1017
which might not always be available in the error
1019
return(HA_ERR_FOUND_DUPP_KEY);
1021
case DB_FOREIGN_DUPLICATE_KEY:
1022
return(HA_ERR_FOREIGN_DUPLICATE_KEY);
1024
case DB_MISSING_HISTORY:
1025
return(HA_ERR_TABLE_DEF_CHANGED);
1027
case DB_RECORD_NOT_FOUND:
1028
return(HA_ERR_NO_ACTIVE_RECORD);
1031
/* Since we rolled back the whole transaction, we must
1032
tell it also to MySQL so that MySQL knows to empty the
1033
cached binlog for this transaction */
1035
mark_transaction_to_rollback(session, TRUE);
1037
return(HA_ERR_LOCK_DEADLOCK);
1039
case DB_LOCK_WAIT_TIMEOUT:
1040
/* Starting from 5.0.13, we let MySQL just roll back the
1041
latest SQL statement in a lock wait timeout. Previously, we
1042
rolled back the whole transaction. */
1044
mark_transaction_to_rollback(session, (bool)row_rollback_on_timeout);
1046
return(HA_ERR_LOCK_WAIT_TIMEOUT);
1048
case DB_NO_REFERENCED_ROW:
1049
return(HA_ERR_NO_REFERENCED_ROW);
1051
case DB_ROW_IS_REFERENCED:
1052
return(HA_ERR_ROW_IS_REFERENCED);
1054
case DB_CANNOT_ADD_CONSTRAINT:
1055
return(HA_ERR_CANNOT_ADD_FOREIGN);
1057
case DB_CANNOT_DROP_CONSTRAINT:
1059
return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
1060
misleading, a new MySQL error
1061
code should be introduced */
1063
case DB_COL_APPEARS_TWICE_IN_INDEX:
1065
return(HA_ERR_CRASHED);
1067
case DB_OUT_OF_FILE_SPACE:
1068
return(HA_ERR_RECORD_FILE_FULL);
1070
case DB_TABLE_IS_BEING_USED:
1071
return(HA_ERR_WRONG_COMMAND);
1073
case DB_TABLE_NOT_FOUND:
1074
return(HA_ERR_NO_SUCH_TABLE);
1076
case DB_TOO_BIG_RECORD:
1077
my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
1078
page_get_free_space_of_empty(flags
1079
& DICT_TF_COMPACT) / 2);
1080
return(HA_ERR_TO_BIG_ROW);
1082
case DB_NO_SAVEPOINT:
1083
return(HA_ERR_NO_SAVEPOINT);
1085
case DB_LOCK_TABLE_FULL:
1086
/* Since we rolled back the whole transaction, we must
1087
tell it also to MySQL so that MySQL knows to empty the
1088
cached binlog for this transaction */
1090
mark_transaction_to_rollback(session, TRUE);
1092
return(HA_ERR_LOCK_TABLE_FULL);
1094
case DB_PRIMARY_KEY_IS_NULL:
1095
return(ER_PRIMARY_CANT_HAVE_NULL);
1097
case DB_TOO_MANY_CONCURRENT_TRXS:
1099
/* Once MySQL add the appropriate code to errmsg.txt then
1100
we can get rid of this #ifdef. NOTE: The code checked by
1101
the #ifdef is the suggested name for the error condition
1102
and the actual error code name could very well be different.
1103
This will require some monitoring, ie. the status
1104
of this request on our part.*/
1106
/* New error code HA_ERR_TOO_MANY_CONCURRENT_TRXS is only
1107
available in 5.1.38 and later, but the plugin should still
1108
work with previous versions of MySQL.
1109
In Drizzle we seem to not have this yet.
1111
#ifdef HA_ERR_TOO_MANY_CONCURRENT_TRXS
1112
return(HA_ERR_TOO_MANY_CONCURRENT_TRXS);
1113
#else /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
1114
return(HA_ERR_RECORD_FILE_FULL);
1115
#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
1116
case DB_UNSUPPORTED:
1117
return(HA_ERR_UNSUPPORTED);
865
int error, /*!< in: InnoDB error code */
866
ulint flags, /*!< in: InnoDB table flags, or 0 */
867
Session* session)/*!< in: user thread handle or NULL */
875
return(-1); /* unspecified error */
877
case DB_DUPLICATE_KEY:
878
return(HA_ERR_FOUND_DUPP_KEY);
880
case DB_FOREIGN_DUPLICATE_KEY:
881
return(HA_ERR_FOREIGN_DUPLICATE_KEY);
883
case DB_MISSING_HISTORY:
884
return(HA_ERR_TABLE_DEF_CHANGED);
886
case DB_RECORD_NOT_FOUND:
887
return(HA_ERR_NO_ACTIVE_RECORD);
890
/* Since we rolled back the whole transaction, we must
891
tell it also to MySQL so that MySQL knows to empty the
892
cached binlog for this transaction */
894
session_mark_transaction_to_rollback(session, TRUE);
896
return(HA_ERR_LOCK_DEADLOCK);
898
case DB_LOCK_WAIT_TIMEOUT:
899
/* Starting from 5.0.13, we let MySQL just roll back the
900
latest SQL statement in a lock wait timeout. Previously, we
901
rolled back the whole transaction. */
903
session_mark_transaction_to_rollback(session,
904
(bool)row_rollback_on_timeout);
906
return(HA_ERR_LOCK_WAIT_TIMEOUT);
908
case DB_NO_REFERENCED_ROW:
909
return(HA_ERR_NO_REFERENCED_ROW);
911
case DB_ROW_IS_REFERENCED:
912
return(HA_ERR_ROW_IS_REFERENCED);
914
case DB_CANNOT_ADD_CONSTRAINT:
915
return(HA_ERR_CANNOT_ADD_FOREIGN);
917
case DB_CANNOT_DROP_CONSTRAINT:
919
return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
920
misleading, a new MySQL error
921
code should be introduced */
923
case DB_COL_APPEARS_TWICE_IN_INDEX:
925
return(HA_ERR_CRASHED);
927
case DB_OUT_OF_FILE_SPACE:
928
return(HA_ERR_RECORD_FILE_FULL);
930
case DB_TABLE_IS_BEING_USED:
931
return(HA_ERR_WRONG_COMMAND);
933
case DB_TABLE_NOT_FOUND:
934
return(HA_ERR_NO_SUCH_TABLE);
936
case DB_TOO_BIG_RECORD:
937
my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
938
page_get_free_space_of_empty(flags
939
& DICT_TF_COMPACT) / 2);
940
return(HA_ERR_TO_BIG_ROW);
942
case DB_NO_SAVEPOINT:
943
return(HA_ERR_NO_SAVEPOINT);
945
case DB_LOCK_TABLE_FULL:
946
/* Since we rolled back the whole transaction, we must
947
tell it also to MySQL so that MySQL knows to empty the
948
cached binlog for this transaction */
950
session_mark_transaction_to_rollback(session, TRUE);
952
return(HA_ERR_LOCK_TABLE_FULL);
954
case DB_PRIMARY_KEY_IS_NULL:
955
return(ER_PRIMARY_CANT_HAVE_NULL);
957
case DB_TOO_MANY_CONCURRENT_TRXS:
959
/* Once MySQL add the appropriate code to errmsg.txt then
960
we can get rid of this #ifdef. NOTE: The code checked by
961
the #ifdef is the suggested name for the error condition
962
and the actual error code name could very well be different.
963
This will require some monitoring, ie. the status
964
of this request on our part.*/
965
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
966
return(ER_TOO_MANY_CONCURRENT_TRXS);
968
return(HA_ERR_RECORD_FILE_FULL);
971
return(HA_ERR_UNSUPPORTED);
975
/*************************************************************//**
976
If you want to print a session that is not associated with the current thread,
977
you must call this function before reserving the InnoDB kernel_mutex, to
978
protect Drizzle from setting session->query NULL. If you print a session of the
979
current thread, we know that Drizzle cannot modify sesion->query, and it is
980
not necessary to call this. Call innobase_mysql_end_print_arbitrary_thd()
981
after you release the kernel_mutex.
983
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking
986
extern "C" UNIV_INTERN
988
innobase_mysql_prepare_print_arbitrary_thd(void)
989
/*============================================*/
991
ut_ad(!mutex_own(&kernel_mutex));
992
pthread_mutex_lock(&LOCK_thread_count);
995
/*************************************************************//**
996
Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
997
In the InnoDB latching order, the mutex sits right above the
998
kernel_mutex. In debug builds, we assert that the kernel_mutex is
999
released before this function is invoked.
1001
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking
1004
extern "C" UNIV_INTERN
1006
innobase_mysql_end_print_arbitrary_thd(void)
1007
/*========================================*/
1009
ut_ad(!mutex_own(&kernel_mutex));
1010
pthread_mutex_unlock(&LOCK_thread_count);
1122
1013
/*************************************************************//**
1123
1014
Prints info of a Session object (== user session thread) to the given file. */
1272
unsigned long); /*!< in: OS error value */
1152
unsigned long); /*!< in: OS error value */
1274
1154
/*********************************************************************//**
1275
1155
Creates a temporary file.
1276
@return temporary file descriptor, or < 0 on error */
1156
@return temporary file descriptor, or < 0 on error */
1277
1157
extern "C" UNIV_INTERN
1279
1159
innobase_mysql_tmpfile(void)
1280
1160
/*========================*/
1282
int fd; /* handle of opened file */
1283
HANDLE osfh; /* OS handle of opened file */
1284
char* tmpdir; /* point to the directory
1285
where to create file */
1286
TCHAR path_buf[MAX_PATH - 14]; /* buffer for tmp file path.
1287
The length cannot be longer
1288
than MAX_PATH - 14, or
1289
GetTempFileName will fail. */
1290
char filename[MAX_PATH]; /* name of the tmpfile */
1291
DWORD fileaccess = GENERIC_READ /* OS file access */
1294
DWORD fileshare = FILE_SHARE_READ /* OS file sharing mode */
1296
| FILE_SHARE_DELETE;
1297
DWORD filecreate = CREATE_ALWAYS; /* OS method of open/create */
1298
DWORD fileattrib = /* OS file attribute flags */
1299
FILE_ATTRIBUTE_NORMAL
1300
| FILE_FLAG_DELETE_ON_CLOSE
1301
| FILE_ATTRIBUTE_TEMPORARY
1302
| FILE_FLAG_SEQUENTIAL_SCAN;
1304
tmpdir = my_tmpdir(&mysql_tmpdir_list);
1306
/* The tmpdir parameter can not be NULL for GetTempFileName. */
1310
/* Use GetTempPath to determine path for temporary files. */
1311
ret = GetTempPath(sizeof(path_buf), path_buf);
1312
if (ret > sizeof(path_buf) || (ret == 0)) {
1314
_dosmaperr(GetLastError()); /* map error */
1321
/* Use GetTempFileName to generate a unique filename. */
1322
if (!GetTempFileName(tmpdir, "ib", 0, filename)) {
1324
_dosmaperr(GetLastError()); /* map error */
1328
/* Open/Create the file. */
1329
osfh = CreateFile(filename, fileaccess, fileshare, NULL,
1330
filecreate, fileattrib, NULL);
1331
if (osfh == INVALID_HANDLE_VALUE) {
1333
/* open/create file failed! */
1334
_dosmaperr(GetLastError()); /* map error */
1339
/* Associates a CRT file descriptor with the OS file handle. */
1340
fd = _open_osfhandle((intptr_t) osfh, 0);
1341
} while (fd == -1 && errno == EINTR);
1344
/* Open failed, close the file handle. */
1346
_dosmaperr(GetLastError()); /* map error */
1347
CloseHandle(osfh); /* no need to check if
1348
CloseHandle fails */
1162
int fd; /* handle of opened file */
1163
HANDLE osfh; /* OS handle of opened file */
1164
char* tmpdir; /* point to the directory
1165
where to create file */
1166
TCHAR path_buf[MAX_PATH - 14]; /* buffer for tmp file path.
1167
The length cannot be longer
1168
than MAX_PATH - 14, or
1169
GetTempFileName will fail. */
1170
char filename[MAX_PATH]; /* name of the tmpfile */
1171
DWORD fileaccess = GENERIC_READ /* OS file access */
1174
DWORD fileshare = FILE_SHARE_READ /* OS file sharing mode */
1176
| FILE_SHARE_DELETE;
1177
DWORD filecreate = CREATE_ALWAYS; /* OS method of open/create */
1178
DWORD fileattrib = /* OS file attribute flags */
1179
FILE_ATTRIBUTE_NORMAL
1180
| FILE_FLAG_DELETE_ON_CLOSE
1181
| FILE_ATTRIBUTE_TEMPORARY
1182
| FILE_FLAG_SEQUENTIAL_SCAN;
1184
tmpdir = my_tmpdir(&mysql_tmpdir_list);
1186
/* The tmpdir parameter can not be NULL for GetTempFileName. */
1190
/* Use GetTempPath to determine path for temporary files. */
1191
ret = GetTempPath(sizeof(path_buf), path_buf);
1192
if (ret > sizeof(path_buf) || (ret == 0)) {
1194
_dosmaperr(GetLastError()); /* map error */
1201
/* Use GetTempFileName to generate a unique filename. */
1202
if (!GetTempFileName(tmpdir, "ib", 0, filename)) {
1204
_dosmaperr(GetLastError()); /* map error */
1208
/* Open/Create the file. */
1209
osfh = CreateFile(filename, fileaccess, fileshare, NULL,
1210
filecreate, fileattrib, NULL);
1211
if (osfh == INVALID_HANDLE_VALUE) {
1213
/* open/create file failed! */
1214
_dosmaperr(GetLastError()); /* map error */
1219
/* Associates a CRT file descriptor with the OS file handle. */
1220
fd = _open_osfhandle((intptr_t) osfh, 0);
1221
} while (fd == -1 && errno == EINTR);
1224
/* Open failed, close the file handle. */
1226
_dosmaperr(GetLastError()); /* map error */
1227
CloseHandle(osfh); /* no need to check if
1228
CloseHandle fails */
1354
1234
/*********************************************************************//**
1355
1235
Creates a temporary file.
1356
@return temporary file descriptor, or < 0 on error */
1236
@return temporary file descriptor, or < 0 on error */
1357
1237
extern "C" UNIV_INTERN
1359
1239
innobase_mysql_tmpfile(void)
1360
1240
/*========================*/
1363
int fd = mysql_tmpfile("ib");
1365
/* Copy the file descriptor, so that the additional resources
1366
allocated by create_temp_file() can be freed by invoking
1367
internal::my_close().
1243
int fd = mysql_tmpfile("ib");
1245
/* Copy the file descriptor, so that the additional resources
1246
allocated by create_temp_file() can be freed by invoking
1247
internal::my_close().
1369
Because the file descriptor returned by this function
1370
will be passed to fdopen(), it will be closed by invoking
1371
fclose(), which in turn will invoke close() instead of
1372
internal::my_close(). */
1376
my_error(EE_OUT_OF_FILERESOURCES,
1377
MYF(ME_BELL+ME_WAITTANG),
1380
internal::my_close(fd, MYF(MY_WME));
1249
Because the file descriptor returned by this function
1250
will be passed to fdopen(), it will be closed by invoking
1251
fclose(), which in turn will invoke close() instead of
1252
internal::my_close(). */
1256
my_error(EE_OUT_OF_FILERESOURCES,
1257
MYF(ME_BELL+ME_WAITTANG),
1260
internal::my_close(fd, MYF(MY_WME));
1384
1264
#endif /* defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) */
1591
1473
ha_innobase::update_session(
1592
1474
/*====================*/
1593
Session* session) /*!< in: thd to use the handle */
1598
trx = check_trx_exists(session);
1600
if (prebuilt->trx != trx) {
1602
row_update_prebuilt_trx(prebuilt, trx);
1605
user_session = session;
1475
Session* session) /*!< in: thd to use the handle */
1479
trx = check_trx_exists(session);
1481
if (prebuilt->trx != trx) {
1483
row_update_prebuilt_trx(prebuilt, trx);
1486
user_session = session;
1489
/*********************************************************************//**
1490
Updates the user_thd field in a handle and also allocates a new InnoDB
1491
transaction handle if needed, and updates the transaction fields in the
1495
ha_innobase::update_session()
1496
/*=====================*/
1498
Session* session = ha_session();
1499
ut_ad(EQ_CURRENT_SESSION(session));
1500
update_session(session);
1608
1503
/*****************************************************************//**
1609
1504
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
1610
1505
and quote it if needed.
1611
@return pointer to the end of buf */
1506
@return pointer to the end of buf */
1614
1509
innobase_convert_identifier(
1615
1510
/*========================*/
1616
char* buf, /*!< out: buffer for converted identifier */
1617
ulint buflen, /*!< in: length of buf, in bytes */
1618
const char* id, /*!< in: identifier to convert */
1619
ulint idlen, /*!< in: length of id, in bytes */
1620
void* session,/*!< in: MySQL connection thread, or NULL */
1621
ibool file_id)/*!< in: TRUE=id is a table or database name;
1622
FALSE=id is an UTF-8 string */
1511
char* buf, /*!< out: buffer for converted identifier */
1512
ulint buflen, /*!< in: length of buf, in bytes */
1513
const char* id, /*!< in: identifier to convert */
1514
ulint idlen, /*!< in: length of id, in bytes */
1515
void* session,/*!< in: MySQL connection thread, or NULL */
1516
ibool file_id)/*!< in: TRUE=id is a table or database name;
1517
FALSE=id is an UTF-8 string */
1624
char nz[NAME_LEN + 1];
1625
char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
1631
/* Decode the table name. The filename_to_tablename()
1632
function expects a NUL-terminated string. The input and
1633
output strings buffers must not be shared. */
1635
if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
1636
idlen = (sizeof nz) - 1;
1639
memcpy(nz, id, idlen);
1643
idlen = TableIdentifier::filename_to_tablename(nz, nz2, sizeof nz2);
1646
/* See if the identifier needs to be quoted. */
1647
if (UNIV_UNLIKELY(!session)) {
1650
q = get_quote_char_for_identifier();
1654
if (UNIV_UNLIKELY(idlen > buflen)) {
1657
memcpy(buf, s, idlen);
1658
return(buf + idlen);
1661
/* Quote the identifier. */
1669
for (; idlen; idlen--) {
1671
if (UNIV_UNLIKELY(c == q)) {
1672
if (UNIV_UNLIKELY(buflen < 3)) {
1680
if (UNIV_UNLIKELY(buflen < 2)) {
1519
char nz[NAME_LEN + 1];
1520
char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
1526
/* Decode the table name. The filename_to_tablename()
1527
function expects a NUL-terminated string. The input and
1528
output strings buffers must not be shared. */
1530
if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
1531
idlen = (sizeof nz) - 1;
1534
memcpy(nz, id, idlen);
1538
idlen = filename_to_tablename(nz, nz2, sizeof nz2);
1541
/* See if the identifier needs to be quoted. */
1542
if (UNIV_UNLIKELY(!session)) {
1545
q = get_quote_char_for_identifier();
1549
if (UNIV_UNLIKELY(idlen > buflen)) {
1552
memcpy(buf, s, idlen);
1553
return(buf + idlen);
1556
/* Quote the identifier. */
1564
for (; idlen; idlen--) {
1566
if (UNIV_UNLIKELY(c == q)) {
1567
if (UNIV_UNLIKELY(buflen < 3)) {
1575
if (UNIV_UNLIKELY(buflen < 2)) {
1693
1588
/*****************************************************************//**
1694
1589
Convert a table or index name to the MySQL system_charset_info (UTF-8)
1695
1590
and quote it if needed.
1696
@return pointer to the end of buf */
1591
@return pointer to the end of buf */
1697
1592
extern "C" UNIV_INTERN
1699
1594
innobase_convert_name(
1700
1595
/*==================*/
1701
char* buf, /*!< out: buffer for converted identifier */
1702
ulint buflen, /*!< in: length of buf, in bytes */
1703
const char* id, /*!< in: identifier to convert */
1704
ulint idlen, /*!< in: length of id, in bytes */
1705
void* session,/*!< in: MySQL connection thread, or NULL */
1706
ibool table_id)/*!< in: TRUE=id is a table or database name;
1707
FALSE=id is an index name */
1596
char* buf, /*!< out: buffer for converted identifier */
1597
ulint buflen, /*!< in: length of buf, in bytes */
1598
const char* id, /*!< in: identifier to convert */
1599
ulint idlen, /*!< in: length of id, in bytes */
1600
void* session,/*!< in: MySQL connection thread, or NULL */
1601
ibool table_id)/*!< in: TRUE=id is a table or database name;
1602
FALSE=id is an index name */
1710
const char* bufend = buf + buflen;
1713
const char* slash = (const char*) memchr(id, '/', idlen);
1719
/* Print the database name and table name separately. */
1720
s = innobase_convert_identifier(s, bufend - s, id, slash - id,
1722
if (UNIV_LIKELY(s < bufend)) {
1724
s = innobase_convert_identifier(s, bufend - s,
1729
} else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
1730
/* Temporary index name (smart ALTER TABLE) */
1731
const char temp_index_suffix[]= "--temporary--";
1733
s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
1735
if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
1736
memcpy(s, temp_index_suffix,
1737
sizeof temp_index_suffix - 1);
1738
s += sizeof temp_index_suffix - 1;
1605
const char* bufend = buf + buflen;
1608
const char* slash = (const char*) memchr(id, '/', idlen);
1614
/* Print the database name and table name separately. */
1615
s = innobase_convert_identifier(s, bufend - s, id, slash - id,
1617
if (UNIV_LIKELY(s < bufend)) {
1619
s = innobase_convert_identifier(s, bufend - s,
1624
} else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
1625
/* Temporary index name (smart ALTER TABLE) */
1626
const char temp_index_suffix[]= "--temporary--";
1628
s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
1630
if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
1631
memcpy(s, temp_index_suffix,
1632
sizeof temp_index_suffix - 1);
1633
s += sizeof temp_index_suffix - 1;
1742
s = innobase_convert_identifier(buf, buflen, id, idlen,
1637
s = innobase_convert_identifier(buf, buflen, id, idlen,
1750
1645
/**********************************************************************//**
1751
1646
Determines if the currently running transaction has been interrupted.
1752
@return TRUE if interrupted */
1647
@return TRUE if interrupted */
1753
1648
extern "C" UNIV_INTERN
1755
1650
trx_is_interrupted(
1756
1651
/*===============*/
1757
trx_t* trx) /*!< in: transaction */
1759
return(trx && trx->mysql_thd && static_cast<Session*>(trx->mysql_thd)->getKilled());
1762
/**********************************************************************//**
1763
Determines if the currently running transaction is in strict mode.
1764
@return TRUE if strict */
1765
extern "C" UNIV_INTERN
1769
1652
trx_t* trx) /*!< in: transaction */
1771
return(trx && trx->mysql_thd && true);
1654
return(trx && trx->mysql_thd && session_killed((Session*) trx->mysql_thd));
1774
1657
/**************************************************************//**
1779
1662
reset_template(
1780
1663
/*===========*/
1781
row_prebuilt_t* prebuilt) /*!< in/out: prebuilt struct */
1783
prebuilt->keep_other_fields_on_keyread = 0;
1784
prebuilt->read_just_key = 0;
1788
void align_value(T& value, size_t align_val= 1024)
1790
value= value - (value % align_val);
1664
row_prebuilt_t* prebuilt) /*!< in/out: prebuilt struct */
1666
prebuilt->keep_other_fields_on_keyread = 0;
1667
prebuilt->read_just_key = 0;
1793
1670
/*********************************************************************//**
1794
1671
Opens an InnoDB database.
1795
@return 0 on success, error code on failure */
1672
@return 0 on success, error code on failure */
1800
module::Context &context) /*!< in: Drizzle Plugin Context */
1677
plugin::Registry ®istry) /*!< in: Drizzle Plugin Registry */
1805
InnobaseEngine *actuall_engine_ptr;
1806
const module::option_map &vm= context.getOptions();
1808
/* Inverted Booleans */
1810
innobase_use_checksums= (vm.count("disable-checksums")) ? false : true;
1811
innobase_use_doublewrite= (vm.count("disable-doublewrite")) ? false : true;
1812
srv_adaptive_flushing= (vm.count("disable-adaptive-flushing")) ? false : true;
1813
srv_use_sys_malloc= (vm.count("use-internal-malloc")) ? false : true;
1814
(SessionVAR(NULL,support_xa))= (vm.count("disable-xa")) ? false : true;
1815
(SessionVAR(NULL,table_locks))= (vm.count("disable-table-locks")) ? false : true;
1817
if (vm.count("io-capacity"))
1819
if (srv_io_capacity < 100)
1821
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for io-capacity\n"));
1826
if (vm.count("data-home-dir"))
1828
innobase_data_home_dir= strdup(vm["data-home-dir"].as<string>().c_str());
1832
innobase_data_home_dir= strdup(getDataHome().file_string().c_str());
1835
if (vm.count("fast-shutdown"))
1837
if (innobase_fast_shutdown > 2)
1839
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for fast-shutdown\n"));
1844
if (vm.count("file-format-check"))
1846
innobase_file_format_check= const_cast<char *>(vm["file-format-check"].as<string>().c_str());
1849
if (vm.count("flush-log-at-trx-commit"))
1851
if (srv_flush_log_at_trx_commit > 2)
1853
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for flush-log-at-trx-commit\n"));
1858
if (vm.count("flush-method"))
1860
innobase_file_flush_method= const_cast<char *>(vm["flush-method"].as<string>().c_str());
1864
innobase_file_flush_method= NULL;
1867
#ifdef UNIV_LOG_ARCHIVE
1868
if (vm.count("log-arch-dir"))
1870
innobase_log_arch_dir= const_cast<char *>(vm["log-arch-dir"].as<string>().c_str());
1875
innobase_log_arch_dir= NULL;
1877
#endif /* UNIV_LOG_ARCHIVE */
1879
if (vm.count("max-dirty-pages-pct"))
1881
if (srv_max_buf_pool_modified_pct > 99)
1883
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for max-dirty-pages-pct\n"));
1888
if (vm.count("stats-sample-pages"))
1890
if (srv_stats_sample_pages < 8)
1892
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for stats-sample-pages\n"));
1897
if (vm.count("additional-mem-pool-size"))
1899
align_value(innobase_additional_mem_pool_size);
1901
if (innobase_additional_mem_pool_size < 512*1024L)
1903
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for additional-mem-pool-size\n"));
1909
if (vm.count("autoextend-increment"))
1911
if (srv_auto_extend_increment < 1 || srv_auto_extend_increment > 1000)
1913
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for autoextend-increment\n"));
1918
if (vm.count("buffer-pool-size"))
1920
align_value(innobase_buffer_pool_size, 1024*1024);
1921
if (innobase_buffer_pool_size < 5*1024*1024)
1923
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for buffer-pool-size\n"));
1929
if (vm.count("commit-concurrency"))
1931
if (srv_replication_delay > 1000)
1933
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for commit-concurrency\n"));
1938
if (vm.count("concurrency-tickets"))
1940
if (srv_n_free_tickets_to_enter < 1)
1942
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for concurrency-tickets\n"));
1947
if (vm.count("read-io-threads"))
1949
if (innobase_read_io_threads < 1 || innobase_read_io_threads > 64)
1951
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for read-io-threads\n"));
1956
if (vm.count("write-io-threads"))
1958
if (innobase_write_io_threads < 1 || innobase_write_io_threads > 64)
1960
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for write-io-threads\n"));
1965
if (vm.count("force-recovery"))
1967
if (innobase_force_recovery > 6)
1969
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for force-recovery\n"));
1974
if (vm.count("log-buffer-size"))
1976
align_value(innobase_log_buffer_size);
1977
if (innobase_log_buffer_size < 256*1024L)
1979
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for log-file-size\n"));
1984
if (vm.count("log-file-size"))
1986
align_value(innobase_log_file_size, 1024*1024);
1987
if (innobase_log_file_size < 1*1024*1024L)
1989
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for log-file-size\n"));
1994
if (vm.count("log-files-in-group"))
1996
if (innobase_log_files_in_group < 2 || innobase_log_files_in_group > 100)
1998
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for log-files-in-group\n"));
2003
if (vm.count("mirrored-log-groups"))
2005
if (innobase_mirrored_log_groups < 1 || innobase_mirrored_log_groups > 10)
2007
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for mirrored-log-groups\n"));
2012
if (vm.count("open-files"))
2014
if (innobase_open_files < 10)
2016
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for open-files\n"));
2021
if (vm.count("thread-concurrency"))
2023
if (srv_thread_concurrency > 1000)
2025
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for thread-concurrency\n"));
2030
if (vm.count("data-file-path"))
2032
innobase_data_file_path= const_cast<char *>(vm["data-file-path"].as<string>().c_str());
2036
innobase_data_file_path= NULL;
2039
if (vm.count("version"))
2041
innodb_version_str= const_cast<char *>(vm["version"].as<string>().c_str());
2044
if (vm.count("read-ahead-threshold"))
2046
if (srv_read_ahead_threshold > 64)
2048
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for read-ahead-threshold\n"));
2053
if (vm.count("strict-mode"))
2055
(SessionVAR(NULL,strict_mode))= vm["strict-mode"].as<bool>();
2058
if (vm.count("lock-wait-timeout"))
2060
if (vm["lock-wait-timeout"].as<unsigned long>() < 1 || vm["lock-wait-timeout"].as<unsigned long>() > 1024*1024*1024)
2062
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for lock-wait-timeout\n"));
2066
(SessionVAR(NULL,lock_wait_timeout))= vm["lock-wait-timeout"].as<unsigned long>();
2069
innodb_engine_ptr= actuall_engine_ptr= new InnobaseEngine(innobase_engine_name);
2071
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)DRIZZLE_TYPE_VARCHAR);
1679
static char current_dir[3]; /*!< Set if using current lib */
1685
innodb_engine_ptr= new InnobaseEngine(innobase_engine_name);
1688
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)DRIZZLE_TYPE_VARCHAR);
2073
1690
#ifdef UNIV_DEBUG
2074
static const char test_filename[] = "-@";
2075
char test_tablename[sizeof test_filename
2076
+ sizeof srv_mysql50_table_name_prefix];
2077
if ((sizeof test_tablename) - 1
2078
!= filename_to_tablename(test_filename, test_tablename,
2079
sizeof test_tablename)
2080
|| strncmp(test_tablename,
2081
srv_mysql50_table_name_prefix,
2082
sizeof srv_mysql50_table_name_prefix)
2083
|| strcmp(test_tablename
2084
+ sizeof srv_mysql50_table_name_prefix,
2086
errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
1691
static const char test_filename[] = "-@";
1692
char test_tablename[sizeof test_filename
1693
+ sizeof srv_mysql50_table_name_prefix];
1694
if ((sizeof test_tablename) - 1
1695
!= filename_to_tablename(test_filename, test_tablename,
1696
sizeof test_tablename)
1697
|| strncmp(test_tablename,
1698
srv_mysql50_table_name_prefix,
1699
sizeof srv_mysql50_table_name_prefix)
1700
|| strcmp(test_tablename
1701
+ sizeof srv_mysql50_table_name_prefix,
1703
errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
2089
1706
#endif /* UNIV_DEBUG */
2091
/* Check that values don't overflow on 32-bit systems. */
2092
if (sizeof(ulint) == 4) {
2093
if (innobase_buffer_pool_size > UINT32_MAX) {
2094
errmsg_printf(ERRMSG_LVL_ERROR,
2095
"innobase_buffer_pool_size can't be over 4GB"
2096
" on 32-bit systems");
2101
if (innobase_log_file_size > UINT32_MAX) {
2102
errmsg_printf(ERRMSG_LVL_ERROR,
2103
"innobase_log_file_size can't be over 4GB"
2104
" on 32-bit systems");
2110
os_innodb_umask = (ulint)internal::my_umask;
2113
/* Set InnoDB initialization parameters according to the values
2114
read from MySQL .cnf file */
2116
/*--------------- Data files -------------------------*/
2118
/* The default dir for data files is the datadir of MySQL */
2120
srv_data_home = (char *)innobase_data_home_dir;
2122
/* Set default InnoDB data file size to 10 MB and let it be
2123
auto-extending. Thus users can use InnoDB in >= 4.0 without having
2124
to specify any startup options. */
2126
if (!innobase_data_file_path) {
2127
innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
2130
/* Since InnoDB edits the argument in the next call, we make another
2133
internal_innobase_data_file_path = strdup(innobase_data_file_path);
2135
ret = (bool) srv_parse_data_file_paths_and_sizes(
2136
internal_innobase_data_file_path);
2138
errmsg_printf(ERRMSG_LVL_ERROR,
2139
"InnoDB: syntax error in innodb_data_file_path");
1708
/* Check that values don't overflow on 32-bit systems. */
1709
if (sizeof(ulint) == 4) {
1710
if (innobase_buffer_pool_size > UINT32_MAX) {
1711
errmsg_printf(ERRMSG_LVL_ERROR,
1712
"innobase_buffer_pool_size can't be over 4GB"
1713
" on 32-bit systems");
1718
if (innobase_log_file_size > UINT32_MAX) {
1719
errmsg_printf(ERRMSG_LVL_ERROR,
1720
"innobase_log_file_size can't be over 4GB"
1721
" on 32-bit systems");
1727
os_innodb_umask = (ulint)internal::my_umask;
1729
/* First calculate the default path for innodb_data_home_dir etc.,
1730
in case the user has not given any value.
1732
Note that when using the embedded server, the datadirectory is not
1733
necessarily the current directory of this program. */
1735
/* It's better to use current lib, to keep paths short */
1736
current_dir[0] = FN_CURLIB;
1737
current_dir[1] = FN_LIBCHAR;
1739
default_path = current_dir;
1743
srv_set_thread_priorities = TRUE;
1744
srv_query_thread_priority = QUERY_PRIOR;
1746
/* Set InnoDB initialization parameters according to the values
1747
read from MySQL .cnf file */
1749
/*--------------- Data files -------------------------*/
1751
/* The default dir for data files is the datadir of MySQL */
1753
srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
1756
/* Set default InnoDB data file size to 10 MB and let it be
1757
auto-extending. Thus users can use InnoDB in >= 4.0 without having
1758
to specify any startup options. */
1760
if (!innobase_data_file_path) {
1761
innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
1764
/* Since InnoDB edits the argument in the next call, we make another
1767
internal_innobase_data_file_path = strdup(innobase_data_file_path);
1769
ret = (bool) srv_parse_data_file_paths_and_sizes(
1770
internal_innobase_data_file_path);
1772
errmsg_printf(ERRMSG_LVL_ERROR,
1773
"InnoDB: syntax error in innodb_data_file_path");
2140
1774
mem_free_and_error:
2141
srv_free_paths_and_sizes();
2142
if (internal_innobase_data_file_path)
2143
free(internal_innobase_data_file_path);
2147
/* -------------- Log files ---------------------------*/
2149
/* The default dir for log files is the datadir of MySQL */
2151
if (vm.count("log-group-home-dir"))
2153
innobase_log_group_home_dir= strdup(vm["log-group-home-dir"].as<string>().c_str());
2157
innobase_log_group_home_dir = strdup(getDataHome().file_string().c_str());
1775
srv_free_paths_and_sizes();
1776
if (internal_innobase_data_file_path)
1777
free(internal_innobase_data_file_path);
1781
/* -------------- Log files ---------------------------*/
1783
/* The default dir for log files is the datadir of MySQL */
1785
if (!innobase_log_group_home_dir) {
1786
innobase_log_group_home_dir = default_path;
2160
1789
#ifdef UNIV_LOG_ARCHIVE
2161
/* Since innodb_log_arch_dir has no relevance under MySQL,
2162
starting from 4.0.6 we always set it the same as
2163
innodb_log_group_home_dir: */
2165
innobase_log_arch_dir = innobase_log_group_home_dir;
2167
srv_arch_dir = innobase_log_arch_dir;
1790
/* Since innodb_log_arch_dir has no relevance under MySQL,
1791
starting from 4.0.6 we always set it the same as
1792
innodb_log_group_home_dir: */
1794
innobase_log_arch_dir = innobase_log_group_home_dir;
1796
srv_arch_dir = innobase_log_arch_dir;
2168
1797
#endif /* UNIG_LOG_ARCHIVE */
2171
srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
2173
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
2174
errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
2175
"wrong number of mirrored log groups");
2177
goto mem_free_and_error;
2181
/* Validate the file format by animal name */
2182
if (vm.count("file-format"))
2184
format_id = innobase_file_format_name_lookup(
2185
vm["file-format"].as<string>().c_str());
2187
if (format_id > DICT_TF_FORMAT_MAX) {
2189
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
2191
goto mem_free_and_error;
2194
/* Set it to the default file format id.*/
2198
srv_file_format = format_id;
2200
/* Given the type of innobase_file_format_name we have little
2201
choice but to cast away the constness from the returned name.
2202
innobase_file_format_name is used in the MySQL set variable
2203
interface and so can't be const. */
2205
innobase_file_format_name =
2206
(char*) trx_sys_file_format_id_to_name(format_id);
2208
/* Process innobase_file_format_check variable */
2209
ut_a(innobase_file_format_check != NULL);
2211
/* As a side effect it will set srv_check_file_format_at_startup
2212
on valid input. First we check for "on"/"off". */
2213
if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
2215
/* Did the user specify a format name that we support ?
2216
As a side effect it will update the variable
2217
srv_check_file_format_at_startup */
2218
if (innobase_file_format_validate_and_set(
2219
innobase_file_format_check) < 0) {
2220
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
2221
"innodb_file_format_check value: "
2222
"should be either 'on' or 'off' or "
2223
"any value up to %s or its "
2224
"equivalent numeric id",
2225
trx_sys_file_format_id_to_name(
2226
DICT_TF_FORMAT_MAX));
2228
goto mem_free_and_error;
2232
if (vm.count("change-buffering"))
2237
use < UT_ARR_SIZE(innobase_change_buffering_values);
2239
if (!innobase_strcasecmp(
2240
vm["change-buffering"].as<string>().c_str(),
2241
innobase_change_buffering_values[use])) {
2242
ibuf_use = (ibuf_use_t) use;
2243
goto innobase_change_buffering_inited_ok;
2247
errmsg_printf(ERRMSG_LVL_ERROR,
2248
"InnoDB: invalid value "
2249
"innodb_file_format_check=%s",
2250
vm["change-buffering"].as<string>().c_str());
2251
goto mem_free_and_error;
1800
srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
1802
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
1803
errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
1804
"wrong number of mirrored log groups");
1806
goto mem_free_and_error;
1809
/* Validate the file format by animal name */
1810
if (innobase_file_format_name != NULL) {
1812
format_id = innobase_file_format_name_lookup(
1813
innobase_file_format_name);
1815
if (format_id > DICT_TF_FORMAT_MAX) {
1817
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
1819
goto mem_free_and_error;
1822
/* Set it to the default file format id. Though this
1823
should never happen. */
1827
srv_file_format = format_id;
1829
/* Given the type of innobase_file_format_name we have little
1830
choice but to cast away the constness from the returned name.
1831
innobase_file_format_name is used in the MySQL set variable
1832
interface and so can't be const. */
1834
innobase_file_format_name =
1835
(char*) trx_sys_file_format_id_to_name(format_id);
1837
/* Process innobase_file_format_check variable */
1838
ut_a(innobase_file_format_check != NULL);
1840
/* As a side effect it will set srv_check_file_format_at_startup
1841
on valid input. First we check for "on"/"off". */
1842
if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
1844
/* Did the user specify a format name that we support ?
1845
As a side effect it will update the variable
1846
srv_check_file_format_at_startup */
1847
if (!innobase_file_format_check_validate(
1848
innobase_file_format_check)) {
1850
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
1851
"innodb_file_format_check value: "
1852
"should be either 'on' or 'off' or "
1853
"any value up to %s or its "
1854
"equivalent numeric id",
1855
trx_sys_file_format_id_to_name(
1856
DICT_TF_FORMAT_MAX));
1858
goto mem_free_and_error;
1862
if (innobase_change_buffering) {
1866
use < UT_ARR_SIZE(innobase_change_buffering_values);
1868
if (!innobase_strcasecmp(
1869
innobase_change_buffering,
1870
innobase_change_buffering_values[use])) {
1871
ibuf_use = (ibuf_use_t) use;
1872
goto innobase_change_buffering_inited_ok;
1876
errmsg_printf(ERRMSG_LVL_ERROR,
1877
"InnoDB: invalid value "
1878
"innodb_file_format_check=%s",
1879
innobase_change_buffering);
1880
goto mem_free_and_error;
2254
1883
innobase_change_buffering_inited_ok:
2255
ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
2256
innobase_change_buffering = (char*)
2257
innobase_change_buffering_values[ibuf_use];
2259
/* --------------------------------------------------*/
2261
srv_file_flush_method_str = innobase_file_flush_method;
2263
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
2264
srv_n_log_files = (ulint) innobase_log_files_in_group;
2265
srv_log_file_size = (ulint) innobase_log_file_size;
1884
ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
1885
innobase_change_buffering = (char*)
1886
innobase_change_buffering_values[ibuf_use];
1888
/* --------------------------------------------------*/
1890
srv_file_flush_method_str = innobase_unix_file_flush_method;
1892
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
1893
srv_n_log_files = (ulint) innobase_log_files_in_group;
1894
srv_log_file_size = (ulint) innobase_log_file_size;
2267
1896
#ifdef UNIV_LOG_ARCHIVE
2268
srv_log_archive_on = (ulint) innobase_log_archive;
1897
srv_log_archive_on = (ulint) innobase_log_archive;
2269
1898
#endif /* UNIV_LOG_ARCHIVE */
2270
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
2272
srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
2274
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
2276
srv_n_read_io_threads = (ulint) innobase_read_io_threads;
2277
srv_n_write_io_threads = (ulint) innobase_write_io_threads;
2279
srv_force_recovery = (ulint) innobase_force_recovery;
2281
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
2282
srv_use_checksums = (ibool) innobase_use_checksums;
1899
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
1901
srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
1903
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
1905
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
1906
srv_n_read_io_threads = (ulint) innobase_read_io_threads;
1907
srv_n_write_io_threads = (ulint) innobase_write_io_threads;
1909
srv_force_recovery = (ulint) innobase_force_recovery;
1911
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
1912
srv_use_checksums = (ibool) innobase_use_checksums;
2284
1914
#ifdef HAVE_LARGE_PAGES
2285
if ((os_use_large_pages = (ibool) my_use_large_pages))
2286
os_large_page_size = (ulint) opt_large_page_size;
1915
if ((os_use_large_pages = (ibool) my_use_large_pages))
1916
os_large_page_size = (ulint) opt_large_page_size;
2289
row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
2291
srv_locks_unsafe_for_binlog = (ibool) TRUE;
2293
srv_max_n_open_files = (ulint) innobase_open_files;
2294
srv_innodb_status = (ibool) innobase_create_status_file;
2296
srv_print_verbose_log = true;
2298
/* Store the default charset-collation number of this MySQL
2301
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
2303
innobase_old_blocks_pct = buf_LRU_old_ratio_update(innobase_old_blocks_pct,
2306
innobase_commit_concurrency_init_default();
2308
/* Since we in this module access directly the fields of a trx
2309
struct, and due to different headers and flags it might happen that
2310
mutex_t has a different size in this module and in InnoDB
2311
modules, we check at run time that the size is the same in
2312
these compilation modules. */
2314
err = innobase_start_or_create_for_mysql();
2316
if (err != DB_SUCCESS) {
2317
goto mem_free_and_error;
2320
innobase_open_tables = hash_create(200);
2321
pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
2322
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
2323
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
2324
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
2325
pthread_cond_init(&commit_cond, NULL);
2328
actuall_engine_ptr->dropTemporarySchema();
2330
status_table_function_ptr= new InnodbStatusTool;
2332
context.add(innodb_engine_ptr);
2334
context.add(status_table_function_ptr);
2336
cmp_tool= new(std::nothrow)CmpTool(false);
2337
context.add(cmp_tool);
2339
cmp_reset_tool= new(std::nothrow)CmpTool(true);
2340
context.add(cmp_reset_tool);
2342
cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
2343
context.add(cmp_mem_tool);
2345
cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
2346
context.add(cmp_mem_reset_tool);
2348
innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
2349
context.add(innodb_trx_tool);
2351
innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
2352
context.add(innodb_locks_tool);
2354
innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
2355
context.add(innodb_lock_waits_tool);
2357
context.add(new(std::nothrow)InnodbInternalTables());
2359
/* Get the current high water mark format. */
2360
innobase_file_format_check = (char*) trx_sys_file_format_max_get();
1919
row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
1921
srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
1923
srv_max_n_open_files = (ulint) innobase_open_files;
1924
srv_innodb_status = (ibool) innobase_create_status_file;
1926
srv_print_verbose_log = true;
1928
/* Store the default charset-collation number of this MySQL
1931
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
1934
innobase_commit_concurrency_init_default();
1936
/* Since we in this module access directly the fields of a trx
1937
struct, and due to different headers and flags it might happen that
1938
mutex_t has a different size in this module and in InnoDB
1939
modules, we check at run time that the size is the same in
1940
these compilation modules. */
1942
err = innobase_start_or_create_for_mysql();
1944
if (err != DB_SUCCESS) {
1945
goto mem_free_and_error;
1948
innobase_open_tables = hash_create(200);
1949
pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
1950
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
1951
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
1952
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
1953
pthread_cond_init(&commit_cond, NULL);
1956
status_table_function_ptr= new InnodbStatusTool;
1958
registry.add(innodb_engine_ptr);
1960
registry.add(status_table_function_ptr);
1962
cmp_tool= new(std::nothrow)CmpTool(false);
1963
registry.add(cmp_tool);
1965
cmp_reset_tool= new(std::nothrow)CmpTool(true);
1966
registry.add(cmp_reset_tool);
1968
cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
1969
registry.add(cmp_mem_tool);
1971
cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
1972
registry.add(cmp_mem_reset_tool);
1974
innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
1975
registry.add(innodb_trx_tool);
1977
innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
1978
registry.add(innodb_locks_tool);
1980
innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
1981
registry.add(innodb_lock_waits_tool);
1983
/* Get the current high water mark format. */
1984
innobase_file_format_check = (char*) trx_sys_file_format_max_get();
1991
/*******************************************************************//**
1992
Closes an InnoDB database.
1993
@return TRUE if error */
1996
innobase_deinit(plugin::Registry ®istry)
2000
registry.remove(status_table_function_ptr);
2001
delete status_table_function_ptr;
2003
registry.remove(cmp_tool);
2006
registry.remove(cmp_reset_tool);
2007
delete cmp_reset_tool;
2009
registry.remove(cmp_mem_tool);
2010
delete cmp_mem_tool;
2012
registry.remove(cmp_mem_reset_tool);
2013
delete cmp_mem_reset_tool;
2015
registry.remove(innodb_trx_tool);
2016
delete innodb_trx_tool;
2018
registry.remove(innodb_locks_tool);
2019
delete innodb_locks_tool;
2021
registry.remove(innodb_lock_waits_tool);
2022
delete innodb_lock_waits_tool;
2024
registry.remove(innodb_engine_ptr);
2025
delete innodb_engine_ptr;
2027
if (innodb_inited) {
2029
srv_fast_shutdown = (ulint) innobase_fast_shutdown;
2031
hash_table_free(innobase_open_tables);
2032
innobase_open_tables = NULL;
2033
if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
2036
srv_free_paths_and_sizes();
2037
if (internal_innobase_data_file_path)
2038
free(internal_innobase_data_file_path);
2039
pthread_mutex_destroy(&innobase_share_mutex);
2040
pthread_mutex_destroy(&prepare_commit_mutex);
2041
pthread_mutex_destroy(&commit_threads_m);
2042
pthread_mutex_destroy(&commit_cond_m);
2043
pthread_cond_destroy(&commit_cond);
2368
2049
/****************************************************************//**
2369
2050
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
2370
2051
the logs, and the name of this function should be innobase_checkpoint.
2371
@return TRUE if error */
2052
@return TRUE if error */
2373
2054
InnobaseEngine::flush_logs()
2374
2055
/*=====================*/
2378
assert(this == innodb_engine_ptr);
2380
log_buffer_flush_to_disk();
2059
assert(this == innodb_engine_ptr);
2061
log_buffer_flush_to_disk();
2385
2066
/*****************************************************************//**
2403
2084
Starts a new InnoDB transaction if a transaction is not yet started. And
2404
2085
assigns a new snapshot for a consistent read if the transaction does not yet
2408
2089
InnobaseEngine::doStartTransaction(
2409
2090
/*====================================*/
2410
Session* session, /*!< in: MySQL thread handle of the user for whom
2411
the transaction should be committed */
2091
Session* session, /*!< in: MySQL thread handle of the user for whom
2092
the transaction should be committed */
2412
2093
start_transaction_option_t options)
2414
assert(this == innodb_engine_ptr);
2416
/* Create a new trx struct for session, if it does not yet have one */
2417
trx_t *trx = check_trx_exists(session);
2419
/* This is just to play safe: release a possible FIFO ticket and
2420
search latch. Since we will reserve the kernel mutex, we have to
2421
release the search system latch first to obey the latching order. */
2422
innobase_release_stat_resources(trx);
2424
/* If the transaction is not started yet, start it */
2425
trx_start_if_not_started(trx);
2427
/* Assign a read view if the transaction does not have it yet */
2095
assert(this == innodb_engine_ptr);
2097
/* Create a new trx struct for session, if it does not yet have one */
2098
trx_t *trx = check_trx_exists(session);
2100
/* This is just to play safe: release a possible FIFO ticket and
2101
search latch. Since we will reserve the kernel mutex, we have to
2102
release the search system latch first to obey the latching order. */
2103
innobase_release_stat_resources(trx);
2105
/* If the transaction is not started yet, start it */
2106
trx_start_if_not_started(trx);
2108
/* Assign a read view if the transaction does not have it yet */
2428
2109
if (options == START_TRANS_OPT_WITH_CONS_SNAPSHOT)
2429
trx_assign_read_view(trx);
2110
trx_assign_read_view(trx);
2112
/* Set the Drizzle flag to mark that there is an active transaction */
2113
if (trx->active_trans == 0) {
2114
trx->active_trans= 1;
2434
2120
/*****************************************************************//**
2435
2121
Commits a transaction in an InnoDB database or marks an SQL statement
2439
2125
InnobaseEngine::doCommit(
2440
2126
/*============*/
2441
Session* session, /*!< in: MySQL thread handle of the user for whom
2442
the transaction should be committed */
2443
bool all) /*!< in: TRUE - commit transaction
2444
FALSE - the current SQL statement ended */
2127
Session* session, /*!< in: MySQL thread handle of the user for whom
2128
the transaction should be committed */
2129
bool all) /*!< in: TRUE - commit transaction
2130
FALSE - the current SQL statement ended */
2448
assert(this == innodb_engine_ptr);
2450
trx = check_trx_exists(session);
2452
/* Since we will reserve the kernel mutex, we have to release
2453
the search system latch first to obey the latching order. */
2455
if (trx->has_search_latch) {
2456
trx_search_latch_release_if_reserved(trx);
2460
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2462
/* We were instructed to commit the whole transaction, or
2463
this is an SQL statement end and autocommit is on */
2465
/* We need current binlog position for ibbackup to work.
2466
Note, the position is current because of
2467
prepare_commit_mutex */
2134
assert(this == innodb_engine_ptr);
2136
trx = check_trx_exists(session);
2138
/* Since we will reserve the kernel mutex, we have to release
2139
the search system latch first to obey the latching order. */
2141
if (trx->has_search_latch) {
2142
trx_search_latch_release_if_reserved(trx);
2145
/* The flag trx->active_trans is set to 1 in
2147
1. ::external_lock()
2148
2 InnobaseEngine::doStartStatement()
2149
3. InnobaseEngine::setSavepoint()
2150
4. InnobaseEngine::doStartTransaction()
2152
and it is only set to 0 in a commit or a rollback. If it is 0 we know
2153
there cannot be resources to be freed and we could return immediately.
2154
For the time being, we play safe and do the cleanup though there should
2155
be nothing to clean up. */
2157
if (trx->active_trans == 0
2158
&& trx->conc_state != TRX_NOT_STARTED) {
2160
errmsg_printf(ERRMSG_LVL_ERROR, "trx->active_trans == 0, but"
2161
" trx->conc_state != TRX_NOT_STARTED");
2164
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2166
/* We were instructed to commit the whole transaction, or
2167
this is an SQL statement end and autocommit is on */
2169
/* We need current binlog position for ibbackup to work.
2170
Note, the position is current because of
2171
prepare_commit_mutex */
2469
if (innobase_commit_concurrency > 0) {
2470
pthread_mutex_lock(&commit_cond_m);
2173
if (innobase_commit_concurrency > 0) {
2174
pthread_mutex_lock(&commit_cond_m);
2473
if (commit_threads > innobase_commit_concurrency) {
2475
pthread_cond_wait(&commit_cond,
2477
pthread_mutex_unlock(&commit_cond_m);
2481
pthread_mutex_unlock(&commit_cond_m);
2177
if (commit_threads > innobase_commit_concurrency) {
2179
pthread_cond_wait(&commit_cond,
2181
pthread_mutex_unlock(&commit_cond_m);
2185
pthread_mutex_unlock(&commit_cond_m);
2485
2189
/* Store transaction point for binlog
2486
Later logic tests that this is set to _something_. We need
2487
that logic to fire, even though we do not have a real name. */
2488
trx->mysql_log_file_name = "UNUSED";
2489
trx->mysql_log_offset = 0;
2491
/* Don't do write + flush right now. For group commit
2492
to work we want to do the flush after releasing the
2493
prepare_commit_mutex. */
2494
trx->flush_log_later = TRUE;
2495
innobase_commit_low(trx);
2496
trx->flush_log_later = FALSE;
2498
if (innobase_commit_concurrency > 0) {
2499
pthread_mutex_lock(&commit_cond_m);
2501
pthread_cond_signal(&commit_cond);
2502
pthread_mutex_unlock(&commit_cond_m);
2505
/* Now do a write + flush of logs. */
2506
trx_commit_complete_for_mysql(trx);
2509
/* We just mark the SQL statement ended and do not do a
2510
transaction commit */
2512
/* If we had reserved the auto-inc lock for some
2513
table in this SQL statement we release it now */
2515
row_unlock_table_autoinc_for_mysql(trx);
2517
/* Store the current undo_no of the transaction so that we
2518
know where to roll back if we have to roll back the next
2521
trx_mark_sql_stat_end(trx);
2523
if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
2525
if (trx->conc_state != TRX_NOT_STARTED)
2527
commit(session, TRUE);
2532
trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2534
if (trx->declared_to_be_inside_innodb) {
2535
/* Release our possible ticket in the FIFO */
2537
srv_conc_force_exit_innodb(trx);
2540
/* Tell the InnoDB server that there might be work for utility
2542
srv_active_wake_master_thread();
2544
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
2545
trx->global_read_view)
2547
/* At low transaction isolation levels we let
2548
each consistent read set its own snapshot */
2549
read_view_close_for_mysql(trx);
2190
Later logic tests that this is set to _something_. We need
2191
that logic to fire, even though we do not have a real name. */
2192
trx->mysql_log_file_name = "UNUSED";
2193
trx->mysql_log_offset = 0;
2195
/* Don't do write + flush right now. For group commit
2196
to work we want to do the flush after releasing the
2197
prepare_commit_mutex. */
2198
trx->flush_log_later = TRUE;
2199
innobase_commit_low(trx);
2200
trx->flush_log_later = FALSE;
2202
if (innobase_commit_concurrency > 0) {
2203
pthread_mutex_lock(&commit_cond_m);
2205
pthread_cond_signal(&commit_cond);
2206
pthread_mutex_unlock(&commit_cond_m);
2209
if (trx->active_trans == 2) {
2211
pthread_mutex_unlock(&prepare_commit_mutex);
2214
/* Now do a write + flush of logs. */
2215
trx_commit_complete_for_mysql(trx);
2216
trx->active_trans = 0;
2219
/* We just mark the SQL statement ended and do not do a
2220
transaction commit */
2222
/* If we had reserved the auto-inc lock for some
2223
table in this SQL statement we release it now */
2225
row_unlock_table_autoinc_for_mysql(trx);
2227
/* Store the current undo_no of the transaction so that we
2228
know where to roll back if we have to roll back the next
2231
trx_mark_sql_stat_end(trx);
2234
trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2236
if (trx->declared_to_be_inside_innodb) {
2237
/* Release our possible ticket in the FIFO */
2239
srv_conc_force_exit_innodb(trx);
2242
/* Tell the InnoDB server that there might be work for utility
2244
srv_active_wake_master_thread();
2555
2249
/*****************************************************************//**
2556
2250
Rolls back a transaction or the latest SQL statement.
2557
@return 0 or error number */
2251
@return 0 or error number */
2559
2253
InnobaseEngine::doRollback(
2560
2254
/*==============*/
2561
Session* session,/*!< in: handle to the MySQL thread of the user
2562
whose transaction should be rolled back */
2563
bool all) /*!< in: TRUE - commit transaction
2564
FALSE - the current SQL statement ended */
2255
Session* session,/*!< in: handle to the MySQL thread of the user
2256
whose transaction should be rolled back */
2257
bool all) /*!< in: TRUE - commit transaction
2258
FALSE - the current SQL statement ended */
2569
assert(this == innodb_engine_ptr);
2571
trx = check_trx_exists(session);
2573
/* Release a possible FIFO ticket and search latch. Since we will
2574
reserve the kernel mutex, we have to release the search system latch
2575
first to obey the latching order. */
2577
innobase_release_stat_resources(trx);
2579
trx->n_autoinc_rows = 0;
2581
/* If we had reserved the auto-inc lock for some table (if
2582
we come here to roll back the latest SQL statement) we
2583
release it now before a possibly lengthy rollback */
2585
row_unlock_table_autoinc_for_mysql(trx);
2588
|| !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2590
error = trx_rollback_for_mysql(trx);
2592
error = trx_rollback_last_sql_stat_for_mysql(trx);
2595
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
2596
trx->global_read_view)
2598
/* At low transaction isolation levels we let
2599
each consistent read set its own snapshot */
2600
read_view_close_for_mysql(trx);
2603
return(convert_error_code_to_mysql(error, 0, NULL));
2263
assert(this == innodb_engine_ptr);
2265
trx = check_trx_exists(session);
2267
/* Release a possible FIFO ticket and search latch. Since we will
2268
reserve the kernel mutex, we have to release the search system latch
2269
first to obey the latching order. */
2271
innobase_release_stat_resources(trx);
2273
/* If we had reserved the auto-inc lock for some table (if
2274
we come here to roll back the latest SQL statement) we
2275
release it now before a possibly lengthy rollback */
2277
row_unlock_table_autoinc_for_mysql(trx);
2280
|| !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2282
error = trx_rollback_for_mysql(trx);
2283
trx->active_trans = 0;
2285
error = trx_rollback_last_sql_stat_for_mysql(trx);
2288
return(convert_error_code_to_mysql(error, 0, NULL));
2606
2291
/*****************************************************************//**
2607
2292
Rolls back a transaction
2608
@return 0 or error number */
2293
@return 0 or error number */
2611
2296
innobase_rollback_trx(
2612
2297
/*==================*/
2613
trx_t* trx) /*!< in: transaction */
2298
trx_t* trx) /*!< in: transaction */
2617
/* Release a possible FIFO ticket and search latch. Since we will
2618
reserve the kernel mutex, we have to release the search system latch
2619
first to obey the latching order. */
2621
innobase_release_stat_resources(trx);
2623
/* If we had reserved the auto-inc lock for some table (if
2624
we come here to roll back the latest SQL statement) we
2625
release it now before a possibly lengthy rollback */
2627
row_unlock_table_autoinc_for_mysql(trx);
2629
error = trx_rollback_for_mysql(trx);
2631
return(convert_error_code_to_mysql(error, 0, NULL));
2302
/* Release a possible FIFO ticket and search latch. Since we will
2303
reserve the kernel mutex, we have to release the search system latch
2304
first to obey the latching order. */
2306
innobase_release_stat_resources(trx);
2308
/* If we had reserved the auto-inc lock for some table (if
2309
we come here to roll back the latest SQL statement) we
2310
release it now before a possibly lengthy rollback */
2312
row_unlock_table_autoinc_for_mysql(trx);
2314
error = trx_rollback_for_mysql(trx);
2316
return(convert_error_code_to_mysql(error, 0, NULL));
2634
2319
/*****************************************************************//**
2835
2561
normalize_table_name(
2836
2562
/*=================*/
2837
char* norm_name, /*!< out: normalized name as a
2838
null-terminated string */
2839
const char* name) /*!< in: table name string */
2563
char* norm_name, /*!< out: normalized name as a
2564
null-terminated string */
2565
const char* name) /*!< in: table name string */
2841
const char* name_ptr;
2845
/* Scan name from the end */
2847
ptr = strchr(name, '\0')-1;
2849
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2859
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2865
memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2867
norm_name[name_ptr - db_ptr - 1] = '/';
2567
const char* name_ptr;
2571
/* Scan name from the end */
2573
ptr = strchr(name, '\0')-1;
2575
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2585
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2591
memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2593
norm_name[name_ptr - db_ptr - 1] = '/';
2870
innobase_casedn_str(norm_name);
2596
innobase_casedn_str(norm_name);
2874
2600
/********************************************************************//**
2875
Get the upper limit of the MySQL integral and floating-point type.
2876
@return maximum allowed value for the field */
2879
innobase_get_int_col_max_value(
2880
/*===========================*/
2881
const Field* field) /*!< in: MySQL field */
2883
uint64_t max_value = 0;
2885
switch(field->key_type()) {
2887
case HA_KEYTYPE_BINARY:
2888
max_value = 0xFFULL;
2891
case HA_KEYTYPE_ULONG_INT:
2892
max_value = 0xFFFFFFFFULL;
2894
case HA_KEYTYPE_LONG_INT:
2895
max_value = 0x7FFFFFFFULL;
2898
case HA_KEYTYPE_ULONGLONG:
2899
max_value = 0xFFFFFFFFFFFFFFFFULL;
2901
case HA_KEYTYPE_LONGLONG:
2902
max_value = 0x7FFFFFFFFFFFFFFFULL;
2904
case HA_KEYTYPE_DOUBLE:
2905
/* We use the maximum as per IEEE754-2008 standard, 2^53 */
2906
max_value = 0x20000000000000ULL;
2915
/*******************************************************************//**
2916
This function checks whether the index column information
2917
is consistent between KEY info from mysql and that from innodb index.
2918
@return TRUE if all column types match. */
2921
innobase_match_index_columns(
2922
/*=========================*/
2923
const KeyInfo* key_info, /*!< in: Index info
2925
const dict_index_t* index_info) /*!< in: Index info
2928
const KeyPartInfo* key_part;
2929
const KeyPartInfo* key_end;
2930
const dict_field_t* innodb_idx_fld;
2931
const dict_field_t* innodb_idx_fld_end;
2933
/* Check whether user defined index column count matches */
2934
if (key_info->key_parts != index_info->n_user_defined_cols) {
2938
key_part = key_info->key_part;
2939
key_end = key_part + key_info->key_parts;
2940
innodb_idx_fld = index_info->fields;
2941
innodb_idx_fld_end = index_info->fields + index_info->n_fields;
2943
/* Check each index column's datatype. We do not check
2944
column name because there exists case that index
2945
column name got modified in mysql but such change does not
2946
propagate to InnoDB.
2947
One hidden assumption here is that the index column sequences
2948
are matched up between those in mysql and Innodb. */
2949
for (; key_part != key_end; ++key_part) {
2952
ulint mtype = innodb_idx_fld->col->mtype;
2954
/* Need to translate to InnoDB column type before
2956
col_type = get_innobase_type_from_mysql_type(&is_unsigned,
2959
/* Ignore Innodb specific system columns. */
2960
while (mtype == DATA_SYS) {
2963
if (innodb_idx_fld >= innodb_idx_fld_end) {
2968
if (col_type != mtype) {
2969
/* Column Type mismatches */
2979
/*******************************************************************//**
2980
This function builds a translation table in INNOBASE_SHARE
2981
structure for fast index location with mysql array number from its
2982
table->key_info structure. This also provides the necessary translation
2983
between the key order in mysql key_info and Innodb ib_table->indexes if
2984
they are not fully matched with each other.
2985
Note we do not have any mutex protecting the translation table
2986
building based on the assumption that there is no concurrent
2987
index creation/drop and DMLs that requires index lookup. All table
2988
handle will be closed before the index creation/drop.
2989
@return TRUE if index translation table built successfully */
2992
innobase_build_index_translation(
2993
/*=============================*/
2994
const Table* table, /*!< in: table in MySQL data
2996
dict_table_t* ib_table, /*!< in: table in Innodb data
2998
INNOBASE_SHARE* share) /*!< in/out: share structure
2999
where index translation table
3000
will be constructed in. */
3002
ulint mysql_num_index;
3004
dict_index_t** index_mapping;
3007
mysql_num_index = table->getShare()->keys;
3008
ib_num_index = UT_LIST_GET_LEN(ib_table->indexes);
3010
index_mapping = share->idx_trans_tbl.index_mapping;
3012
/* If there exists inconsistency between MySQL and InnoDB dictionary
3013
(metadata) information, the number of index defined in MySQL
3014
could exceed that in InnoDB, do not build index translation
3015
table in such case */
3016
if (UNIV_UNLIKELY(ib_num_index < mysql_num_index)) {
3021
/* If index entry count is non-zero, nothing has
3022
changed since last update, directly return TRUE */
3023
if (share->idx_trans_tbl.index_count) {
3024
/* Index entry count should still match mysql_num_index */
3025
ut_a(share->idx_trans_tbl.index_count == mysql_num_index);
3029
/* The number of index increased, rebuild the mapping table */
3030
if (mysql_num_index > share->idx_trans_tbl.array_size) {
3031
index_mapping = (dict_index_t**) realloc(index_mapping,
3033
sizeof(*index_mapping));
3035
if (!index_mapping) {
3040
share->idx_trans_tbl.array_size = mysql_num_index;
3044
/* For each index in the mysql key_info array, fetch its
3045
corresponding InnoDB index pointer into index_mapping
3047
for (ulint count = 0; count < mysql_num_index; count++) {
3049
/* Fetch index pointers into index_mapping according to mysql
3051
index_mapping[count] = dict_table_get_index_on_name(
3052
ib_table, table->key_info[count].name);
3054
if (!index_mapping[count]) {
3055
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find index %s in InnoDB "
3056
"index dictionary.",
3057
table->key_info[count].name);
3062
/* Double check fetched index has the same
3063
column info as those in mysql key_info. */
3064
if (!innobase_match_index_columns(&table->key_info[count],
3065
index_mapping[count])) {
3066
errmsg_printf(ERRMSG_LVL_ERROR, "Found index %s whose column info "
3067
"does not match that of MySQL.",
3068
table->key_info[count].name);
3074
/* Successfully built the translation table */
3075
share->idx_trans_tbl.index_count = mysql_num_index;
3079
/* Build translation table failed. */
3080
free(index_mapping);
3082
share->idx_trans_tbl.array_size = 0;
3083
share->idx_trans_tbl.index_count = 0;
3084
index_mapping = NULL;
3087
share->idx_trans_tbl.index_mapping = index_mapping;
3092
/*******************************************************************//**
3093
This function uses index translation table to quickly locate the
3094
requested index structure.
3095
Note we do not have mutex protection for the index translatoin table
3096
access, it is based on the assumption that there is no concurrent
3097
translation table rebuild (fter create/drop index) and DMLs that
3098
require index lookup.
3099
@return dict_index_t structure for requested index. NULL if
3100
fail to locate the index structure. */
3103
innobase_index_lookup(
3104
/*==================*/
3105
INNOBASE_SHARE* share, /*!< in: share structure for index
3106
translation table. */
3107
uint keynr) /*!< in: index number for the requested
3110
if (!share->idx_trans_tbl.index_mapping
3111
|| keynr >= share->idx_trans_tbl.index_count) {
3115
return(share->idx_trans_tbl.index_mapping[keynr]);
3118
/********************************************************************//**
3119
2601
Set the autoinc column max value. This should only be called once from
3120
ha_innobase::open(). Therefore there's no need for a covering lock. */
2602
ha_innobase::open(). Therefore there's no need for a covering lock.
2603
@return DB_SUCCESS or error code */
3123
2606
ha_innobase::innobase_initialize_autoinc()
3124
2607
/*======================================*/
3127
const Field* field = getTable()->found_next_number_field;
3129
if (field != NULL) {
3130
auto_inc = innobase_get_int_col_max_value(field);
3132
/* We have no idea what's been passed in to us as the
3133
autoinc column. We set it to the 0, effectively disabling
3134
updates to the table. */
3137
ut_print_timestamp(stderr);
3138
fprintf(stderr, " InnoDB: Unable to determine the AUTOINC "
3142
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
3143
/* If the recovery level is set so high that writes
3144
are disabled we force the AUTOINC counter to 0
3145
value effectively disabling writes to the table.
3146
Secondly, we avoid reading the table in case the read
3147
results in failure due to a corrupted table/index.
3149
We will not return an error to the client, so that the
3150
tables can be dumped with minimal hassle. If an error
3151
were returned in this case, the first attempt to read
3152
the table would fail and subsequent SELECTs would succeed. */
3154
} else if (field == NULL) {
3155
/* This is a far more serious error, best to avoid
3156
opening the table and return failure. */
3157
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
3159
dict_index_t* index;
3160
const char* col_name;
3161
uint64_t read_auto_inc;
3164
update_session(getTable()->in_use);
3165
col_name = field->field_name;
3167
ut_a(prebuilt->trx == session_to_trx(user_session));
3169
index = innobase_get_index(getTable()->getShare()->next_number_index);
3171
/* Execute SELECT MAX(col_name) FROM TABLE; */
3172
err = row_search_max_autoinc(index, col_name, &read_auto_inc);
3176
/* At the this stage we do not know the increment
3177
or the offset, so use a default increment of 1. */
3178
auto_inc = read_auto_inc + 1;
3181
case DB_RECORD_NOT_FOUND:
3182
ut_print_timestamp(stderr);
3183
fprintf(stderr, " InnoDB: MySQL and InnoDB data "
3184
"dictionaries are out of sync.\n"
3185
"InnoDB: Unable to find the AUTOINC column "
3186
"%s in the InnoDB table %s.\n"
3187
"InnoDB: We set the next AUTOINC column "
3189
"InnoDB: in effect disabling the AUTOINC "
3190
"next value generation.\n"
3191
"InnoDB: You can either set the next "
3192
"AUTOINC value explicitly using ALTER TABLE\n"
3193
"InnoDB: or fix the data dictionary by "
3194
"recreating the table.\n",
3195
col_name, index->table->name);
3197
/* This will disable the AUTOINC generation. */
3200
/* We want the open to succeed, so that the user can
3201
take corrective action. ie. reads should succeed but
3202
updates should fail. */
3206
/* row_search_max_autoinc() should only return
3207
one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */
3212
dict_table_autoinc_initialize(prebuilt->table, auto_inc);
2609
dict_index_t* index;
2611
const char* col_name;
2614
col_name = table->found_next_number_field->field_name;
2615
index = innobase_get_index(table->s->next_number_index);
2617
/* Execute SELECT MAX(col_name) FROM TABLE; */
2618
error = row_search_max_autoinc(index, col_name, &auto_inc);
2623
/* At the this stage we don't know the increment
2624
or the offset, so use default inrement of 1. */
2628
case DB_RECORD_NOT_FOUND:
2629
ut_print_timestamp(stderr);
2630
fprintf(stderr, " InnoDB: MySQL and InnoDB data "
2631
"dictionaries are out of sync.\n"
2632
"InnoDB: Unable to find the AUTOINC column %s in the "
2633
"InnoDB table %s.\n"
2634
"InnoDB: We set the next AUTOINC column value to the "
2635
"maximum possible value,\n"
2636
"InnoDB: in effect disabling the AUTOINC next value "
2638
"InnoDB: You can either set the next AUTOINC value "
2639
"explicitly using ALTER TABLE\n"
2640
"InnoDB: or fix the data dictionary by recreating "
2642
col_name, index->table->name);
2644
auto_inc = 0xFFFFFFFFFFFFFFFFULL;
2651
dict_table_autoinc_initialize(prebuilt->table, auto_inc);
3215
2656
/*****************************************************************//**
3216
2657
Creates and opens a handle to a table which already exists in an InnoDB
3218
@return 1 if error, 0 if success */
2659
@return 1 if error, 0 if success */
3221
ha_innobase::doOpen(const TableIdentifier &identifier,
3222
int mode, /*!< in: not used */
3223
uint test_if_locked) /*!< in: not used */
2664
const char* name, /*!< in: table name */
2665
int mode, /*!< in: not used */
2666
uint test_if_locked) /*!< in: not used */
3225
dict_table_t* ib_table;
3226
char norm_name[FN_REFLEN];
3230
UT_NOT_USED(test_if_locked);
3232
session= getTable()->in_use;
3234
/* Under some cases Drizzle seems to call this function while
3235
holding btr_search_latch. This breaks the latching order as
3236
we acquire dict_sys->mutex below and leads to a deadlock. */
3237
if (session != NULL) {
3238
getTransactionalEngine()->releaseTemporaryLatches(session);
3241
normalize_table_name(norm_name, identifier.getPath().c_str());
3243
user_session = NULL;
3245
if (!(share=get_share(identifier.getPath().c_str()))) {
3250
/* Create buffers for packing the fields of a record. Why
3251
table->stored_rec_length did not work here? Obviously, because char
3252
fields when packed actually became 1 byte longer, when we also
3253
stored the string length as the first byte. */
3255
upd_and_key_val_buff_len =
3256
getTable()->getShare()->stored_rec_length
3257
+ getTable()->getShare()->max_key_length
3258
+ MAX_REF_PARTS * 3;
3260
upd_buff.resize(upd_and_key_val_buff_len);
3262
if (upd_buff.size() < upd_and_key_val_buff_len)
3267
key_val_buff.resize(upd_and_key_val_buff_len);
3268
if (key_val_buff.size() < upd_and_key_val_buff_len)
3273
/* Get pointer to a table object in InnoDB dictionary cache */
3274
ib_table = dict_table_get(norm_name, TRUE);
3276
if (NULL == ib_table) {
3277
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
3278
"the internal data dictionary of InnoDB "
3279
"though the .frm file for the\n"
3280
"table exists. Maybe you have deleted and "
3281
"recreated InnoDB data\n"
3282
"files but have forgotten to delete the "
3283
"corresponding .frm files\n"
3284
"of InnoDB tables, or you have moved .frm "
3285
"files to another database?\n"
3286
"or, the table contains indexes that this "
3287
"version of the engine\n"
3288
"doesn't support.\n"
3289
"See " REFMAN "innodb-troubleshooting.html\n"
3290
"how you can resolve the problem.\n",
3294
key_val_buff.resize(0);
3297
return(HA_ERR_NO_SUCH_TABLE);
3300
if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
3301
errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
3302
"the .ibd file for\ntable %s does not exist.\n"
3303
"Have you deleted the .ibd file from the "
3304
"database directory under\nthe MySQL datadir, "
3305
"or have you used DISCARD TABLESPACE?\n"
3306
"See " REFMAN "innodb-troubleshooting.html\n"
3307
"how you can resolve the problem.\n",
3311
key_val_buff.resize(0);
3314
dict_table_decrement_handle_count(ib_table, FALSE);
3315
return(HA_ERR_NO_SUCH_TABLE);
3318
prebuilt = row_create_prebuilt(ib_table);
3320
prebuilt->mysql_row_len = getTable()->getShare()->stored_rec_length;
3321
prebuilt->default_rec = getTable()->getDefaultValues();
3322
ut_ad(prebuilt->default_rec);
3324
/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
3326
primary_key = getTable()->getShare()->getPrimaryKey();
3327
key_used_on_scan = primary_key;
3329
if (!innobase_build_index_translation(getTable(), ib_table, share)) {
3330
errmsg_printf(ERRMSG_LVL_ERROR, "Build InnoDB index translation table for"
3331
" Table %s failed", identifier.getPath().c_str());
3334
/* Allocate a buffer for a 'row reference'. A row reference is
3335
a string of bytes of length ref_length which uniquely specifies
3336
a row in our table. Note that MySQL may also compare two row
3337
references for equality by doing a simple memcmp on the strings
3338
of length ref_length! */
3340
if (!row_table_got_default_clust_index(ib_table)) {
3342
prebuilt->clust_index_was_generated = FALSE;
3344
if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
3345
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in "
3346
"InnoDB data dictionary, but not "
3347
"in MySQL!", identifier.getTableName().c_str());
3349
/* This mismatch could cause further problems
3350
if not attended, bring this to the user's attention
3351
by printing a warning in addition to log a message
3353
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
3355
"InnoDB: Table %s has a "
3356
"primary key in InnoDB data "
3357
"dictionary, but not in "
3358
"MySQL!", identifier.getTableName().c_str());
3360
/* If primary_key >= MAX_KEY, its (primary_key)
3361
value could be out of bound if continue to index
3362
into key_info[] array. Find InnoDB primary index,
3363
and assign its key_length to ref_length.
3364
In addition, since MySQL indexes are sorted starting
3365
with primary index, unique index etc., initialize
3366
ref_length to the first index key length in
3367
case we fail to find InnoDB cluster index.
3369
Please note, this will not resolve the primary
3370
index mismatch problem, other side effects are
3371
possible if users continue to use the table.
3372
However, we allow this table to be opened so
3373
that user can adopt necessary measures for the
3374
mismatch while still being accessible to the table
3376
ref_length = getTable()->key_info[0].key_length;
3378
/* Find correspoinding cluster index
3379
key length in MySQL's key_info[] array */
3380
for (ulint i = 0; i < getTable()->getShare()->keys; i++) {
3381
dict_index_t* index;
3382
index = innobase_get_index(i);
3383
if (dict_index_is_clust(index)) {
3385
getTable()->key_info[i].key_length;
3389
/* MySQL allocates the buffer for ref.
3390
key_info->key_length includes space for all key
3391
columns + one byte for each column that may be
3392
NULL. ref_length must be as exact as possible to
3393
save space, because all row reference buffers are
3394
allocated based on ref_length. */
3396
ref_length = getTable()->key_info[primary_key].key_length;
3399
if (primary_key != MAX_KEY) {
3400
errmsg_printf(ERRMSG_LVL_ERROR,
3401
"Table %s has no primary key in InnoDB data "
3402
"dictionary, but has one in MySQL! If you "
3403
"created the table with a MySQL version < "
3404
"3.23.54 and did not define a primary key, "
3405
"but defined a unique key with all non-NULL "
3406
"columns, then MySQL internally treats that "
3407
"key as the primary key. You can fix this "
3408
"error by dump + DROP + CREATE + reimport "
3409
"of the table.", identifier.getTableName().c_str());
3411
/* This mismatch could cause further problems
3412
if not attended, bring this to the user attention
3413
by printing a warning in addition to log a message
3415
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
3417
"InnoDB: Table %s has no "
3418
"primary key in InnoDB data "
3419
"dictionary, but has one in "
3420
"MySQL!", identifier.getTableName().c_str());
3423
prebuilt->clust_index_was_generated = TRUE;
3425
ref_length = DATA_ROW_ID_LEN;
3427
/* If we automatically created the clustered index, then
3428
MySQL does not know about it, and MySQL must NOT be aware
3429
of the index used on scan, to make it avoid checking if we
3430
update the column of the index. That is why we assert below
3431
that key_used_on_scan is the undefined value MAX_KEY.
3432
The column is the row id in the automatical generation case,
3433
and it will never be updated anyway. */
3435
if (key_used_on_scan != MAX_KEY) {
3436
errmsg_printf(ERRMSG_LVL_WARN,
3437
"Table %s key_used_on_scan is %lu even "
3438
"though there is no primary key inside "
3439
"InnoDB.", identifier.getTableName().c_str(), (ulong) key_used_on_scan);
3443
/* Index block size in InnoDB: used by MySQL in query optimization */
3444
stats.block_size = 16 * 1024;
3446
/* Init table lock structure */
3447
lock.init(&share->lock);
3449
if (prebuilt->table) {
3450
/* We update the highest file format in the system table
3451
space, if this table has higher file format setting. */
3453
trx_sys_file_format_max_upgrade(
3454
(const char**) &innobase_file_format_check,
3455
dict_table_get_format(prebuilt->table));
3458
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
3460
/* Only if the table has an AUTOINC column. */
3461
if (prebuilt->table != NULL && getTable()->found_next_number_field != NULL) {
3463
dict_table_autoinc_lock(prebuilt->table);
3465
/* Since a table can already be "open" in InnoDB's internal
3466
data dictionary, we only init the autoinc counter once, the
3467
first time the table is loaded. We can safely reuse the
3468
autoinc value from a previous Drizzle open. */
3469
if (dict_table_autoinc_read(prebuilt->table) == 0) {
3471
innobase_initialize_autoinc();
3474
dict_table_autoinc_unlock(prebuilt->table);
2668
dict_table_t* ib_table;
2669
char norm_name[1000];
2672
char* is_part = NULL;
2675
UT_NOT_USED(test_if_locked);
2677
session = ha_session();
2679
/* Under some cases Drizzle seems to call this function while
2680
holding btr_search_latch. This breaks the latching order as
2681
we acquire dict_sys->mutex below and leads to a deadlock. */
2682
if (session != NULL) {
2683
getTransactionalEngine()->releaseTemporaryLatches(session);
2686
normalize_table_name(norm_name, name);
2688
user_session = NULL;
2690
if (!(share=get_share(name))) {
2695
/* Create buffers for packing the fields of a record. Why
2696
table->stored_rec_length did not work here? Obviously, because char
2697
fields when packed actually became 1 byte longer, when we also
2698
stored the string length as the first byte. */
2700
upd_and_key_val_buff_len =
2701
table->s->stored_rec_length
2702
+ table->s->max_key_length
2703
+ MAX_REF_PARTS * 3;
2704
if (!(unsigned char*) memory::multi_malloc(false,
2705
&upd_buff, upd_and_key_val_buff_len,
2706
&key_val_buff, upd_and_key_val_buff_len,
2713
/* We look for pattern #P# to see if the table is partitioned
2714
MySQL table. The retry logic for partitioned tables is a
2715
workaround for http://bugs.mysql.com/bug.php?id=33349. Look
2716
at support issue https://support.mysql.com/view.php?id=21080
2717
for more details. */
2718
is_part = strstr(norm_name, "#P#");
2720
/* Get pointer to a table object in InnoDB dictionary cache */
2721
ib_table = dict_table_get(norm_name, TRUE);
2723
if (NULL == ib_table) {
2724
if (is_part && retries < 10) {
2726
os_thread_sleep(100000);
2731
errmsg_printf(ERRMSG_LVL_ERROR, "Failed to open table %s after "
2732
"%lu attemtps.\n", norm_name,
2736
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
2737
"the internal data dictionary of InnoDB "
2738
"though the .frm file for the\n"
2739
"table exists. Maybe you have deleted and "
2740
"recreated InnoDB data\n"
2741
"files but have forgotten to delete the "
2742
"corresponding .frm files\n"
2743
"of InnoDB tables, or you have moved .frm "
2744
"files to another database?\n"
2745
"or, the table contains indexes that this "
2746
"version of the engine\n"
2747
"doesn't support.\n"
2748
"See " REFMAN "innodb-troubleshooting.html\n"
2749
"how you can resolve the problem.\n",
2755
return(HA_ERR_NO_SUCH_TABLE);
2758
if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
2759
errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
2760
"the .ibd file for\ntable %s does not exist.\n"
2761
"Have you deleted the .ibd file from the "
2762
"database directory under\nthe MySQL datadir, "
2763
"or have you used DISCARD TABLESPACE?\n"
2764
"See " REFMAN "innodb-troubleshooting.html\n"
2765
"how you can resolve the problem.\n",
2771
dict_table_decrement_handle_count(ib_table, FALSE);
2772
return(HA_ERR_NO_SUCH_TABLE);
2775
prebuilt = row_create_prebuilt(ib_table);
2777
prebuilt->mysql_row_len = table->s->stored_rec_length;
2778
prebuilt->default_rec = table->s->default_values;
2779
ut_ad(prebuilt->default_rec);
2781
/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
2783
primary_key = table->s->primary_key;
2784
key_used_on_scan = primary_key;
2786
/* Allocate a buffer for a 'row reference'. A row reference is
2787
a string of bytes of length ref_length which uniquely specifies
2788
a row in our table. Note that MySQL may also compare two row
2789
references for equality by doing a simple memcmp on the strings
2790
of length ref_length! */
2792
if (!row_table_got_default_clust_index(ib_table)) {
2793
if (primary_key >= MAX_KEY) {
2794
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in InnoDB data "
2795
"dictionary, but not in MySQL!", name);
2798
prebuilt->clust_index_was_generated = FALSE;
2800
/* MySQL allocates the buffer for ref. key_info->key_length
2801
includes space for all key columns + one byte for each column
2802
that may be NULL. ref_length must be as exact as possible to
2803
save space, because all row reference buffers are allocated
2804
based on ref_length. */
2806
ref_length = table->key_info[primary_key].key_length;
2808
if (primary_key != MAX_KEY) {
2809
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has no primary key in InnoDB data "
2810
"dictionary, but has one in MySQL! If you "
2811
"created the table with a MySQL version < "
2812
"3.23.54 and did not define a primary key, "
2813
"but defined a unique key with all non-NULL "
2814
"columns, then MySQL internally treats that "
2815
"key as the primary key. You can fix this "
2816
"error by dump + DROP + CREATE + reimport "
2817
"of the table.", name);
2820
prebuilt->clust_index_was_generated = TRUE;
2822
ref_length = DATA_ROW_ID_LEN;
2824
/* If we automatically created the clustered index, then
2825
MySQL does not know about it, and MySQL must NOT be aware
2826
of the index used on scan, to make it avoid checking if we
2827
update the column of the index. That is why we assert below
2828
that key_used_on_scan is the undefined value MAX_KEY.
2829
The column is the row id in the automatical generation case,
2830
and it will never be updated anyway. */
2832
if (key_used_on_scan != MAX_KEY) {
2833
errmsg_printf(ERRMSG_LVL_WARN,
2834
"Table %s key_used_on_scan is %lu even "
2835
"though there is no primary key inside "
2836
"InnoDB.", name, (ulong) key_used_on_scan);
2840
/* Index block size in InnoDB: used by MySQL in query optimization */
2841
stats.block_size = 16 * 1024;
2843
/* Init table lock structure */
2844
thr_lock_data_init(&share->lock,&lock,(void*) 0);
2846
if (prebuilt->table) {
2847
/* We update the highest file format in the system table
2848
space, if this table has higher file format setting. */
2850
trx_sys_file_format_max_upgrade(
2851
(const char**) &innobase_file_format_check,
2852
dict_table_get_format(prebuilt->table));
2855
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
2857
/* Only if the table has an AUTOINC column. */
2858
if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
2861
dict_table_autoinc_lock(prebuilt->table);
2863
/* Since a table can already be "open" in InnoDB's internal
2864
data dictionary, we only init the autoinc counter once, the
2865
first time the table is loaded. We can safely reuse the
2866
autoinc value from a previous Drizzle open. */
2867
if (dict_table_autoinc_read(prebuilt->table) == 0) {
2869
error = innobase_initialize_autoinc();
2870
ut_a(error == DB_SUCCESS);
2873
dict_table_autoinc_unlock(prebuilt->table);
3482
2881
InnobaseEngine::max_supported_key_part_length() const
3484
return(DICT_MAX_INDEX_COL_LEN - 1);
2883
return(DICT_MAX_INDEX_COL_LEN - 1);
3487
2886
/******************************************************************//**
3488
2887
Closes a handle to an InnoDB table.
3492
2891
ha_innobase::close(void)
3493
2892
/*====================*/
3497
session= getTable()->in_use;
3498
if (session != NULL) {
3499
getTransactionalEngine()->releaseTemporaryLatches(session);
3502
row_prebuilt_free(prebuilt, FALSE);
3505
key_val_buff.clear();
3508
/* Tell InnoDB server that there might be work for
3511
srv_active_wake_master_thread();
2896
session = ha_session();
2897
if (session != NULL) {
2898
getTransactionalEngine()->releaseTemporaryLatches(session);
2901
row_prebuilt_free(prebuilt, FALSE);
2906
/* Tell InnoDB server that there might be work for
2909
srv_active_wake_master_thread();
3516
2914
/* The following accessor functions should really be inside MySQL code! */
3518
2916
/**************************************************************//**
3519
2917
Gets field offset for a field in a table.
3523
2921
get_field_offset(
3524
2922
/*=============*/
3525
Table* table, /*!< in: MySQL table object */
3526
Field* field) /*!< in: MySQL field object */
2923
Table* table, /*!< in: MySQL table object */
2924
Field* field) /*!< in: MySQL field object */
3528
return((uint) (field->ptr - table->getInsertRecord()));
2926
return((uint) (field->ptr - table->record[0]));
3531
2929
/**************************************************************//**
3532
2930
Checks if a field in a record is SQL NULL. Uses the record format
3533
2931
information in table to track the null bit in record.
3534
@return 1 if NULL, 0 otherwise */
2932
@return 1 if NULL, 0 otherwise */
3537
2935
field_in_record_is_null(
3538
2936
/*====================*/
3539
Table* table, /*!< in: MySQL table object */
3540
Field* field, /*!< in: MySQL field object */
3541
char* record) /*!< in: a row in MySQL format */
2937
Table* table, /*!< in: MySQL table object */
2938
Field* field, /*!< in: MySQL field object */
2939
char* record) /*!< in: a row in MySQL format */
3545
if (!field->null_ptr) {
3550
null_offset = (uint) ((char*) field->null_ptr
3551
- (char*) table->getInsertRecord());
3553
if (record[null_offset] & field->null_bit) {
2943
if (!field->null_ptr) {
2948
null_offset = (uint) ((char*) field->null_ptr
2949
- (char*) table->record[0]);
2951
if (record[null_offset] & field->null_bit) {
3561
2959
/**************************************************************//**
3582
2980
is such that we must use MySQL code to compare them. NOTE that the prototype
3583
2981
of this function is in rem0cmp.c in InnoDB source code! If you change this
3584
2982
function, remember to update the prototype there!
3585
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
2983
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
3586
2984
extern "C" UNIV_INTERN
3588
2986
innobase_mysql_cmp(
3589
2987
/*===============*/
3590
int mysql_type, /*!< in: MySQL type */
3591
uint charset_number, /*!< in: number of the charset */
3592
const unsigned char* a, /*!< in: data field */
3593
unsigned int a_length, /*!< in: data field length,
3594
not UNIV_SQL_NULL */
3595
const unsigned char* b, /* in: data field */
3596
unsigned int b_length); /* in: data field length,
3597
not UNIV_SQL_NULL */
2988
int mysql_type, /*!< in: MySQL type */
2989
uint charset_number, /*!< in: number of the charset */
2990
const unsigned char* a, /*!< in: data field */
2991
unsigned int a_length, /*!< in: data field length,
2992
not UNIV_SQL_NULL */
2993
const unsigned char* b, /* in: data field */
2994
unsigned int b_length); /* in: data field length,
2995
not UNIV_SQL_NULL */
3600
2998
innobase_mysql_cmp(
3601
2999
/*===============*/
3602
/* out: 1, 0, -1, if a is greater, equal, less than b, respectively */
3603
int mysql_type, /* in: MySQL type */
3604
uint charset_number, /* in: number of the charset */
3605
const unsigned char* a, /* in: data field */
3606
unsigned int a_length, /* in: data field length, not UNIV_SQL_NULL */
3607
const unsigned char* b, /* in: data field */
3608
unsigned int b_length) /* in: data field length, not UNIV_SQL_NULL */
3000
/* out: 1, 0, -1, if a is greater,
3001
equal, less than b, respectively */
3002
int mysql_type, /* in: MySQL type */
3003
uint charset_number, /* in: number of the charset */
3004
const unsigned char* a, /* in: data field */
3005
unsigned int a_length, /* in: data field length,
3006
not UNIV_SQL_NULL */
3007
const unsigned char* b, /* in: data field */
3008
unsigned int b_length) /* in: data field length,
3009
not UNIV_SQL_NULL */
3610
const CHARSET_INFO* charset;
3611
enum_field_types mysql_tp;
3614
assert(a_length != UNIV_SQL_NULL);
3615
assert(b_length != UNIV_SQL_NULL);
3617
mysql_tp = (enum_field_types) mysql_type;
3621
case DRIZZLE_TYPE_BLOB:
3622
case DRIZZLE_TYPE_VARCHAR:
3623
/* Use the charset number to pick the right charset struct for
3624
the comparison. Since the MySQL function get_charset may be
3625
slow before Bar removes the mutex operation there, we first
3626
look at 2 common charsets directly. */
3628
if (charset_number == default_charset_info->number) {
3629
charset = default_charset_info;
3631
charset = get_charset(charset_number);
3633
if (charset == NULL) {
3634
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
3635
"a comparison, but MySQL cannot "
3636
"find that charset.",
3637
(ulong) charset_number);
3642
/* Starting from 4.1.3, we use strnncollsp() in comparisons of
3643
non-latin1_swedish_ci strings. NOTE that the collation order
3644
changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users
3645
having indexes on such data need to rebuild their tables! */
3647
ret = charset->coll->strnncollsp(charset,
3652
} else if (ret > 0) {
3011
const CHARSET_INFO* charset;
3012
enum_field_types mysql_tp;
3015
assert(a_length != UNIV_SQL_NULL);
3016
assert(b_length != UNIV_SQL_NULL);
3018
mysql_tp = (enum_field_types) mysql_type;
3022
case DRIZZLE_TYPE_BLOB:
3023
case DRIZZLE_TYPE_VARCHAR:
3024
/* Use the charset number to pick the right charset struct for
3025
the comparison. Since the MySQL function get_charset may be
3026
slow before Bar removes the mutex operation there, we first
3027
look at 2 common charsets directly. */
3029
if (charset_number == default_charset_info->number) {
3030
charset = default_charset_info;
3032
charset = get_charset(charset_number);
3034
if (charset == NULL) {
3035
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
3036
"a comparison, but MySQL cannot "
3037
"find that charset.",
3038
(ulong) charset_number);
3043
/* Starting from 4.1.3, we use strnncollsp() in comparisons of
3044
non-latin1_swedish_ci strings. NOTE that the collation order
3045
changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users
3046
having indexes on such data need to rebuild their tables! */
3048
ret = charset->coll->strnncollsp(charset,
3053
} else if (ret > 0) {
3664
3065
/**************************************************************//**
3665
3066
Converts a MySQL type to an InnoDB type. Note that this function returns
3666
3067
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
3667
3068
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'.
3668
@return DATA_BINARY, DATA_VARCHAR, ... */
3069
@return DATA_BINARY, DATA_VARCHAR, ... */
3669
3070
extern "C" UNIV_INTERN
3671
3072
get_innobase_type_from_mysql_type(
3672
3073
/*==============================*/
3673
ulint* unsigned_flag, /*!< out: DATA_UNSIGNED if an
3675
at least ENUM and SET,
3676
and unsigned integer
3677
types are 'unsigned types' */
3678
const void* f) /*!< in: MySQL Field */
3074
ulint* unsigned_flag, /*!< out: DATA_UNSIGNED if an
3076
at least ENUM and SET,
3077
and unsigned integer
3078
types are 'unsigned types' */
3079
const void* f) /*!< in: MySQL Field */
3680
const class Field* field = reinterpret_cast<const class Field*>(f);
3682
/* The following asserts try to check that the MySQL type code fits in
3683
8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
3686
assert((ulint)DRIZZLE_TYPE_DOUBLE < 256);
3688
if (field->flags & UNSIGNED_FLAG) {
3690
*unsigned_flag = DATA_UNSIGNED;
3695
if (field->real_type() == DRIZZLE_TYPE_ENUM)
3697
/* MySQL has field->type() a string type for these, but the
3698
data is actually internally stored as an unsigned integer
3701
*unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
3702
flag set to zero, even though
3703
internally this is an unsigned
3708
switch (field->type()) {
3709
/* NOTE that we only allow string types in DATA_DRIZZLE and
3711
case DRIZZLE_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */
3712
if (field->binary()) {
3713
return(DATA_BINARY);
3715
return(DATA_VARMYSQL);
3717
case DRIZZLE_TYPE_DECIMAL:
3718
return(DATA_FIXBINARY);
3719
case DRIZZLE_TYPE_LONG:
3720
case DRIZZLE_TYPE_LONGLONG:
3721
case DRIZZLE_TYPE_DATETIME:
3722
case DRIZZLE_TYPE_DATE:
3723
case DRIZZLE_TYPE_TIMESTAMP:
3725
case DRIZZLE_TYPE_DOUBLE:
3726
return(DATA_DOUBLE);
3727
case DRIZZLE_TYPE_BLOB:
3081
const class Field* field = reinterpret_cast<const class Field*>(f);
3083
/* The following asserts try to check that the MySQL type code fits in
3084
8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
3087
assert((ulint)DRIZZLE_TYPE_DOUBLE < 256);
3089
if (field->flags & UNSIGNED_FLAG) {
3091
*unsigned_flag = DATA_UNSIGNED;
3096
if (field->real_type() == DRIZZLE_TYPE_ENUM)
3098
/* MySQL has field->type() a string type for these, but the
3099
data is actually internally stored as an unsigned integer
3102
*unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
3103
flag set to zero, even though
3104
internally this is an unsigned
3109
switch (field->type()) {
3110
/* NOTE that we only allow string types in DATA_DRIZZLE and
3112
case DRIZZLE_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */
3113
if (field->binary()) {
3114
return(DATA_BINARY);
3116
return(DATA_VARMYSQL);
3118
case DRIZZLE_TYPE_DECIMAL:
3119
return(DATA_FIXBINARY);
3120
case DRIZZLE_TYPE_LONG:
3121
case DRIZZLE_TYPE_LONGLONG:
3122
case DRIZZLE_TYPE_DATETIME:
3123
case DRIZZLE_TYPE_DATE:
3124
case DRIZZLE_TYPE_TIMESTAMP:
3126
case DRIZZLE_TYPE_DOUBLE:
3127
return(DATA_DOUBLE);
3128
case DRIZZLE_TYPE_BLOB:
3728
3129
return(DATA_BLOB);
3736
3137
/*******************************************************************//**
3741
3142
innobase_write_to_2_little_endian(
3742
3143
/*==============================*/
3743
byte* buf, /*!< in: where to store */
3744
ulint val) /*!< in: value to write, must be < 64k */
3144
byte* buf, /*!< in: where to store */
3145
ulint val) /*!< in: value to write, must be < 64k */
3746
ut_a(val < 256 * 256);
3147
ut_a(val < 256 * 256);
3748
buf[0] = (byte)(val & 0xFF);
3749
buf[1] = (byte)(val / 256);
3149
buf[0] = (byte)(val & 0xFF);
3150
buf[1] = (byte)(val / 256);
3752
3153
/*******************************************************************//**
3753
3154
Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
3754
3155
storage format.
3758
3159
innobase_read_from_2_little_endian(
3759
3160
/*===============================*/
3760
const unsigned char* buf) /*!< in: from where to read */
3161
const unsigned char* buf) /*!< in: from where to read */
3762
return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
3163
return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
3765
3166
/*******************************************************************//**
3766
3167
Stores a key value for a row to a buffer.
3767
@return key value length as stored in buff */
3168
@return key value length as stored in buff */
3770
3171
ha_innobase::store_key_val_for_row(
3771
3172
/*===============================*/
3772
uint keynr, /*!< in: key number */
3773
char* buff, /*!< in/out: buffer for the key value (in MySQL
3775
uint buff_len,/*!< in: buffer length */
3776
const unsigned char* record)/*!< in: row in MySQL format */
3173
uint keynr, /*!< in: key number */
3174
char* buff, /*!< in/out: buffer for the key value (in MySQL
3176
uint buff_len,/*!< in: buffer length */
3177
const unsigned char* record)/*!< in: row in MySQL format */
3778
KeyInfo* key_info = &getTable()->key_info[keynr];
3779
KeyPartInfo* key_part = key_info->key_part;
3780
KeyPartInfo* end = key_part + key_info->key_parts;
3781
char* buff_start = buff;
3782
enum_field_types mysql_type;
3786
/* The format for storing a key field in MySQL is the following:
3788
1. If the column can be NULL, then in the first byte we put 1 if the
3789
field value is NULL, 0 otherwise.
3791
2. If the column is of a BLOB type (it must be a column prefix field
3792
in this case), then we put the length of the data in the field to the
3793
next 2 bytes, in the little-endian format. If the field is SQL NULL,
3794
then these 2 bytes are set to 0. Note that the length of data in the
3795
field is <= column prefix length.
3797
3. In a column prefix field, prefix_len next bytes are reserved for
3798
data. In a normal field the max field length next bytes are reserved
3799
for data. For a VARCHAR(n) the max field length is n. If the stored
3800
value is the SQL NULL then these data bytes are set to 0.
3802
4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
3803
in the MySQL row format, the length is stored in 1 or 2 bytes,
3804
depending on the maximum allowed length. But in the MySQL key value
3805
format, the length always takes 2 bytes.
3807
We have to zero-fill the buffer so that MySQL is able to use a
3808
simple memcmp to compare two key values to determine if they are
3809
equal. MySQL does this to compare contents of two 'ref' values. */
3811
bzero(buff, buff_len);
3813
for (; key_part != end; key_part++) {
3816
if (key_part->null_bit) {
3817
if (record[key_part->null_offset]
3818
& key_part->null_bit) {
3827
field = key_part->field;
3828
mysql_type = field->type();
3830
if (mysql_type == DRIZZLE_TYPE_VARCHAR) {
3831
/* >= 5.0.3 true VARCHAR */
3837
const CHARSET_INFO* cs;
3840
key_len = key_part->length;
3843
buff += key_len + 2;
3847
cs = field->charset();
3850
(((Field_varstring*)field)->pack_length_no_ptr());
3852
data = row_mysql_read_true_varchar(&len,
3854
+ (ulint)get_field_offset(getTable(), field)),
3859
/* For multi byte character sets we need to calculate
3860
the true length of the key */
3862
if (len > 0 && cs->mbmaxlen > 1) {
3863
true_len = (ulint) cs->cset->well_formed_len(cs,
3864
(const char *) data,
3865
(const char *) data + len,
3871
/* In a column prefix index, we may need to truncate
3872
the stored value: */
3874
if (true_len > key_len) {
3878
/* The length in a key value is always stored in 2
3881
row_mysql_store_true_var_len((byte*)buff, true_len, 2);
3884
memcpy(buff, data, true_len);
3886
/* Note that we always reserve the maximum possible
3887
length of the true VARCHAR in the key value, though
3888
only len first bytes after the 2 length bytes contain
3889
actual data. The rest of the space was reset to zero
3890
in the bzero() call above. */
3894
} else if (mysql_type == DRIZZLE_TYPE_BLOB) {
3896
const CHARSET_INFO* cs;
3901
const byte* blob_data;
3903
ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
3905
key_len = key_part->length;
3908
buff += key_len + 2;
3913
cs = field->charset();
3915
blob_data = row_mysql_read_blob_ref(&blob_len,
3917
+ (ulint)get_field_offset(getTable(), field)),
3918
(ulint) field->pack_length());
3920
true_len = blob_len;
3922
ut_a(get_field_offset(getTable(), field)
3923
== key_part->offset);
3925
/* For multi byte character sets we need to calculate
3926
the true length of the key */
3928
if (blob_len > 0 && cs->mbmaxlen > 1) {
3929
true_len = (ulint) cs->cset->well_formed_len(cs,
3930
(const char *) blob_data,
3931
(const char *) blob_data
3938
/* All indexes on BLOB and TEXT are column prefix
3939
indexes, and we may need to truncate the data to be
3940
stored in the key value: */
3942
if (true_len > key_len) {
3946
/* MySQL reserves 2 bytes for the length and the
3947
storage of the number is little-endian */
3949
innobase_write_to_2_little_endian(
3950
(byte*)buff, true_len);
3953
memcpy(buff, blob_data, true_len);
3955
/* Note that we always reserve the maximum possible
3956
length of the BLOB prefix in the key value. */
3960
/* Here we handle all other data types except the
3961
true VARCHAR, BLOB and TEXT. Note that the column
3962
value we store may be also in a column prefix
3967
const unsigned char* src_start;
3968
enum_field_types real_type;
3970
key_len = key_part->length;
3978
src_start = record + key_part->offset;
3979
real_type = field->real_type();
3982
/* Character set for the field is defined only
3983
to fields whose type is string and real field
3984
type is not enum or set. For these fields check
3985
if character set is multi byte. */
3987
memcpy(buff, src_start, true_len);
3990
/* Pad the unused space with spaces. Note that no
3991
padding is ever needed for UCS-2 because in MySQL,
3992
all UCS2 characters are 2 bytes, as MySQL does not
3993
support surrogate pairs, which are needed to represent
3994
characters in the range U+10000 to U+10FFFF. */
3996
if (true_len < key_len) {
3997
ulint pad_len = key_len - true_len;
3998
memset(buff, ' ', pad_len);
4004
ut_a(buff <= buff_start + buff_len);
4006
return((uint)(buff - buff_start));
3179
KEY* key_info = table->key_info + keynr;
3180
KEY_PART_INFO* key_part = key_info->key_part;
3181
KEY_PART_INFO* end = key_part + key_info->key_parts;
3182
char* buff_start = buff;
3183
enum_field_types mysql_type;
3187
/* The format for storing a key field in MySQL is the following:
3189
1. If the column can be NULL, then in the first byte we put 1 if the
3190
field value is NULL, 0 otherwise.
3192
2. If the column is of a BLOB type (it must be a column prefix field
3193
in this case), then we put the length of the data in the field to the
3194
next 2 bytes, in the little-endian format. If the field is SQL NULL,
3195
then these 2 bytes are set to 0. Note that the length of data in the
3196
field is <= column prefix length.
3198
3. In a column prefix field, prefix_len next bytes are reserved for
3199
data. In a normal field the max field length next bytes are reserved
3200
for data. For a VARCHAR(n) the max field length is n. If the stored
3201
value is the SQL NULL then these data bytes are set to 0.
3203
4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
3204
in the MySQL row format, the length is stored in 1 or 2 bytes,
3205
depending on the maximum allowed length. But in the MySQL key value
3206
format, the length always takes 2 bytes.
3208
We have to zero-fill the buffer so that MySQL is able to use a
3209
simple memcmp to compare two key values to determine if they are
3210
equal. MySQL does this to compare contents of two 'ref' values. */
3212
bzero(buff, buff_len);
3214
for (; key_part != end; key_part++) {
3217
if (key_part->null_bit) {
3218
if (record[key_part->null_offset]
3219
& key_part->null_bit) {
3228
field = key_part->field;
3229
mysql_type = field->type();
3231
if (mysql_type == DRIZZLE_TYPE_VARCHAR) {
3232
/* >= 5.0.3 true VARCHAR */
3238
const CHARSET_INFO* cs;
3241
key_len = key_part->length;
3244
buff += key_len + 2;
3248
cs = field->charset();
3251
(((Field_varstring*)field)->length_bytes);
3253
data = row_mysql_read_true_varchar(&len,
3255
+ (ulint)get_field_offset(table, field)),
3260
/* For multi byte character sets we need to calculate
3261
the true length of the key */
3263
if (len > 0 && cs->mbmaxlen > 1) {
3264
true_len = (ulint) cs->cset->well_formed_len(cs,
3265
(const char *) data,
3266
(const char *) data + len,
3272
/* In a column prefix index, we may need to truncate
3273
the stored value: */
3275
if (true_len > key_len) {
3279
/* The length in a key value is always stored in 2
3282
row_mysql_store_true_var_len((byte*)buff, true_len, 2);
3285
memcpy(buff, data, true_len);
3287
/* Note that we always reserve the maximum possible
3288
length of the true VARCHAR in the key value, though
3289
only len first bytes after the 2 length bytes contain
3290
actual data. The rest of the space was reset to zero
3291
in the bzero() call above. */
3295
} else if (mysql_type == DRIZZLE_TYPE_BLOB) {
3297
const CHARSET_INFO* cs;
3302
const byte* blob_data;
3304
ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
3306
key_len = key_part->length;
3309
buff += key_len + 2;
3314
cs = field->charset();
3316
blob_data = row_mysql_read_blob_ref(&blob_len,
3318
+ (ulint)get_field_offset(table, field)),
3319
(ulint) field->pack_length());
3321
true_len = blob_len;
3323
ut_a(get_field_offset(table, field)
3324
== key_part->offset);
3326
/* For multi byte character sets we need to calculate
3327
the true length of the key */
3329
if (blob_len > 0 && cs->mbmaxlen > 1) {
3330
true_len = (ulint) cs->cset->well_formed_len(cs,
3331
(const char *) blob_data,
3332
(const char *) blob_data
3339
/* All indexes on BLOB and TEXT are column prefix
3340
indexes, and we may need to truncate the data to be
3341
stored in the key value: */
3343
if (true_len > key_len) {
3347
/* MySQL reserves 2 bytes for the length and the
3348
storage of the number is little-endian */
3350
innobase_write_to_2_little_endian(
3351
(byte*)buff, true_len);
3354
memcpy(buff, blob_data, true_len);
3356
/* Note that we always reserve the maximum possible
3357
length of the BLOB prefix in the key value. */
3361
/* Here we handle all other data types except the
3362
true VARCHAR, BLOB and TEXT. Note that the column
3363
value we store may be also in a column prefix
3368
const unsigned char* src_start;
3369
enum_field_types real_type;
3371
key_len = key_part->length;
3379
src_start = record + key_part->offset;
3380
real_type = field->real_type();
3383
/* Character set for the field is defined only
3384
to fields whose type is string and real field
3385
type is not enum or set. For these fields check
3386
if character set is multi byte. */
3388
memcpy(buff, src_start, true_len);
3391
/* Pad the unused space with spaces. Note that no
3392
padding is ever needed for UCS-2 because in MySQL,
3393
all UCS2 characters are 2 bytes, as MySQL does not
3394
support surrogate pairs, which are needed to represent
3395
characters in the range U+10000 to U+10FFFF. */
3397
if (true_len < key_len) {
3398
ulint pad_len = key_len - true_len;
3399
memset(buff, ' ', pad_len);
3405
ut_a(buff <= buff_start + buff_len);
3407
return((uint)(buff - buff_start));
4009
3410
/**************************************************************//**
4014
3415
build_template(
4015
3416
/*===========*/
4016
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */
4017
Session* , /*!< in: current user thread, used
4018
only if templ_type is
4019
ROW_DRIZZLE_REC_FIELDS */
4020
Table* table, /*!< in: MySQL table */
4021
uint templ_type) /*!< in: ROW_MYSQL_WHOLE_ROW or
4022
ROW_DRIZZLE_REC_FIELDS */
3417
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */
3418
Session* , /*!< in: current user thread, used
3419
only if templ_type is
3420
ROW_DRIZZLE_REC_FIELDS */
3421
Table* table, /*!< in: MySQL table */
3422
uint templ_type) /*!< in: ROW_MYSQL_WHOLE_ROW or
3423
ROW_DRIZZLE_REC_FIELDS */
4024
dict_index_t* index;
4025
dict_index_t* clust_index;
4026
mysql_row_templ_t* templ;
4029
ulint n_requested_fields = 0;
4030
ibool fetch_all_in_key = FALSE;
4031
ibool fetch_primary_key_cols = FALSE;
4033
/* byte offset of the end of last requested column */
4034
ulint mysql_prefix_len = 0;
4036
if (prebuilt->select_lock_type == LOCK_X) {
4037
/* We always retrieve the whole clustered index record if we
4038
use exclusive row level locks, for example, if the read is
4039
done in an UPDATE statement. */
4041
templ_type = ROW_MYSQL_WHOLE_ROW;
4044
if (templ_type == ROW_MYSQL_REC_FIELDS) {
4045
if (prebuilt->hint_need_to_fetch_extra_cols
4046
== ROW_RETRIEVE_ALL_COLS) {
4048
/* We know we must at least fetch all columns in the
4049
key, or all columns in the table */
4051
if (prebuilt->read_just_key) {
4052
/* MySQL has instructed us that it is enough
4053
to fetch the columns in the key; looks like
4054
MySQL can set this flag also when there is
4055
only a prefix of the column in the key: in
4056
that case we retrieve the whole column from
4057
the clustered index */
4059
fetch_all_in_key = TRUE;
4061
templ_type = ROW_MYSQL_WHOLE_ROW;
4063
} else if (prebuilt->hint_need_to_fetch_extra_cols
4064
== ROW_RETRIEVE_PRIMARY_KEY) {
4065
/* We must at least fetch all primary key cols. Note
4066
that if the clustered index was internally generated
4067
by InnoDB on the row id (no primary key was
4068
defined), then row_search_for_mysql() will always
4069
retrieve the row id to a special buffer in the
4072
fetch_primary_key_cols = TRUE;
4076
clust_index = dict_table_get_first_index(prebuilt->table);
4078
if (templ_type == ROW_MYSQL_REC_FIELDS) {
4079
index = prebuilt->index;
4081
index = clust_index;
4084
if (index == clust_index) {
4085
prebuilt->need_to_access_clustered = TRUE;
4087
prebuilt->need_to_access_clustered = FALSE;
4088
/* Below we check column by column if we need to access
4089
the clustered index */
4092
n_fields = (ulint)table->getShare()->sizeFields(); /* number of columns */
4094
if (!prebuilt->mysql_template) {
4095
prebuilt->mysql_template = (mysql_row_templ_t*)
4096
mem_alloc(n_fields * sizeof(mysql_row_templ_t));
4099
prebuilt->template_type = templ_type;
4100
prebuilt->null_bitmap_len = table->getShare()->null_bytes;
4102
prebuilt->templ_contains_blob = FALSE;
4104
/* Note that in InnoDB, i is the column number. MySQL calls columns
4106
for (i = 0; i < n_fields; i++)
4108
templ = prebuilt->mysql_template + n_requested_fields;
4109
field = table->getField(i);
4111
if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
4112
/* Decide which columns we should fetch
4113
and which we can skip. */
4114
register const ibool index_contains_field =
4115
dict_index_contains_col_or_prefix(index, i);
4117
if (!index_contains_field && prebuilt->read_just_key) {
4118
/* If this is a 'key read', we do not need
4119
columns that are not in the key */
4124
if (index_contains_field && fetch_all_in_key) {
4125
/* This field is needed in the query */
3425
dict_index_t* index;
3426
dict_index_t* clust_index;
3427
mysql_row_templ_t* templ;
3430
ulint n_requested_fields = 0;
3431
ibool fetch_all_in_key = FALSE;
3432
ibool fetch_primary_key_cols = FALSE;
3434
/* byte offset of the end of last requested column */
3435
ulint mysql_prefix_len = 0;
3437
if (prebuilt->select_lock_type == LOCK_X) {
3438
/* We always retrieve the whole clustered index record if we
3439
use exclusive row level locks, for example, if the read is
3440
done in an UPDATE statement. */
3442
templ_type = ROW_MYSQL_WHOLE_ROW;
3445
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3446
if (prebuilt->hint_need_to_fetch_extra_cols
3447
== ROW_RETRIEVE_ALL_COLS) {
3449
/* We know we must at least fetch all columns in the
3450
key, or all columns in the table */
3452
if (prebuilt->read_just_key) {
3453
/* MySQL has instructed us that it is enough
3454
to fetch the columns in the key; looks like
3455
MySQL can set this flag also when there is
3456
only a prefix of the column in the key: in
3457
that case we retrieve the whole column from
3458
the clustered index */
3460
fetch_all_in_key = TRUE;
3462
templ_type = ROW_MYSQL_WHOLE_ROW;
3464
} else if (prebuilt->hint_need_to_fetch_extra_cols
3465
== ROW_RETRIEVE_PRIMARY_KEY) {
3466
/* We must at least fetch all primary key cols. Note
3467
that if the clustered index was internally generated
3468
by InnoDB on the row id (no primary key was
3469
defined), then row_search_for_mysql() will always
3470
retrieve the row id to a special buffer in the
3473
fetch_primary_key_cols = TRUE;
3477
clust_index = dict_table_get_first_index(prebuilt->table);
3479
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3480
index = prebuilt->index;
3482
index = clust_index;
3485
if (index == clust_index) {
3486
prebuilt->need_to_access_clustered = TRUE;
3488
prebuilt->need_to_access_clustered = FALSE;
3489
/* Below we check column by column if we need to access
3490
the clustered index */
3493
n_fields = (ulint)table->s->fields; /* number of columns */
3495
if (!prebuilt->mysql_template) {
3496
prebuilt->mysql_template = (mysql_row_templ_t*)
3497
mem_alloc(n_fields * sizeof(mysql_row_templ_t));
3500
prebuilt->template_type = templ_type;
3501
prebuilt->null_bitmap_len = table->s->null_bytes;
3503
prebuilt->templ_contains_blob = FALSE;
3505
/* Note that in InnoDB, i is the column number. MySQL calls columns
3507
for (i = 0; i < n_fields; i++) {
3508
templ = prebuilt->mysql_template + n_requested_fields;
3509
field = table->field[i];
3511
if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
3512
/* Decide which columns we should fetch
3513
and which we can skip. */
3514
register const ibool index_contains_field =
3515
dict_index_contains_col_or_prefix(index, i);
3517
if (!index_contains_field && prebuilt->read_just_key) {
3518
/* If this is a 'key read', we do not need
3519
columns that are not in the key */
3524
if (index_contains_field && fetch_all_in_key) {
3525
/* This field is needed in the query */
4130
3530
if (field->isReadSet() || field->isWriteSet())
4131
/* This field is needed in the query */
3531
/* This field is needed in the query */
4134
3534
assert(table->isReadSet(i) == field->isReadSet());
4135
3535
assert(table->isWriteSet(i) == field->isWriteSet());
4137
if (fetch_primary_key_cols
4138
&& dict_table_col_in_clustered_key(
4140
/* This field is needed in the query */
4145
/* This field is not needed in the query, skip it */
3537
if (fetch_primary_key_cols
3538
&& dict_table_col_in_clustered_key(
3540
/* This field is needed in the query */
3545
/* This field is not needed in the query, skip it */
4150
n_requested_fields++;
4154
if (index == clust_index) {
4155
templ->rec_field_no = dict_col_get_clust_pos(
4156
&index->table->cols[i], index);
4158
templ->rec_field_no = dict_index_get_nth_col_pos(
4162
if (templ->rec_field_no == ULINT_UNDEFINED) {
4163
prebuilt->need_to_access_clustered = TRUE;
4166
if (field->null_ptr) {
4167
templ->mysql_null_byte_offset =
4168
(ulint) ((char*) field->null_ptr
4169
- (char*) table->getInsertRecord());
4171
templ->mysql_null_bit_mask = (ulint) field->null_bit;
4173
templ->mysql_null_bit_mask = 0;
4176
templ->mysql_col_offset = (ulint)
4177
get_field_offset(table, field);
4179
templ->mysql_col_len = (ulint) field->pack_length();
4180
if (mysql_prefix_len < templ->mysql_col_offset
4181
+ templ->mysql_col_len) {
4182
mysql_prefix_len = templ->mysql_col_offset
4183
+ templ->mysql_col_len;
4185
templ->type = index->table->cols[i].mtype;
4186
templ->mysql_type = (ulint)field->type();
4188
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
4189
templ->mysql_length_bytes = (ulint)
4190
(((Field_varstring*)field)->pack_length_no_ptr());
4193
templ->charset = dtype_get_charset_coll(
4194
index->table->cols[i].prtype);
4195
templ->mbminlen = index->table->cols[i].mbminlen;
4196
templ->mbmaxlen = index->table->cols[i].mbmaxlen;
4197
templ->is_unsigned = index->table->cols[i].prtype
4199
if (templ->type == DATA_BLOB) {
4200
prebuilt->templ_contains_blob = TRUE;
3550
n_requested_fields++;
3554
if (index == clust_index) {
3555
templ->rec_field_no = dict_col_get_clust_pos(
3556
&index->table->cols[i], index);
3558
templ->rec_field_no = dict_index_get_nth_col_pos(
3562
if (templ->rec_field_no == ULINT_UNDEFINED) {
3563
prebuilt->need_to_access_clustered = TRUE;
3566
if (field->null_ptr) {
3567
templ->mysql_null_byte_offset =
3568
(ulint) ((char*) field->null_ptr
3569
- (char*) table->record[0]);
3571
templ->mysql_null_bit_mask = (ulint) field->null_bit;
3573
templ->mysql_null_bit_mask = 0;
3576
templ->mysql_col_offset = (ulint)
3577
get_field_offset(table, field);
3579
templ->mysql_col_len = (ulint) field->pack_length();
3580
if (mysql_prefix_len < templ->mysql_col_offset
3581
+ templ->mysql_col_len) {
3582
mysql_prefix_len = templ->mysql_col_offset
3583
+ templ->mysql_col_len;
3585
templ->type = index->table->cols[i].mtype;
3586
templ->mysql_type = (ulint)field->type();
3588
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
3589
templ->mysql_length_bytes = (ulint)
3590
(((Field_varstring*)field)->length_bytes);
3593
templ->charset = dtype_get_charset_coll(
3594
index->table->cols[i].prtype);
3595
templ->mbminlen = index->table->cols[i].mbminlen;
3596
templ->mbmaxlen = index->table->cols[i].mbmaxlen;
3597
templ->is_unsigned = index->table->cols[i].prtype
3599
if (templ->type == DATA_BLOB) {
3600
prebuilt->templ_contains_blob = TRUE;
4206
prebuilt->n_template = n_requested_fields;
4207
prebuilt->mysql_prefix_len = mysql_prefix_len;
4209
if (index != clust_index && prebuilt->need_to_access_clustered) {
4210
/* Change rec_field_no's to correspond to the clustered index
4212
for (i = 0; i < n_requested_fields; i++) {
4213
templ = prebuilt->mysql_template + i;
4215
templ->rec_field_no = dict_col_get_clust_pos(
4216
&index->table->cols[templ->col_no],
3606
prebuilt->n_template = n_requested_fields;
3607
prebuilt->mysql_prefix_len = mysql_prefix_len;
3609
if (index != clust_index && prebuilt->need_to_access_clustered) {
3610
/* Change rec_field_no's to correspond to the clustered index
3612
for (i = 0; i < n_requested_fields; i++) {
3613
templ = prebuilt->mysql_template + i;
3615
templ->rec_field_no = dict_col_get_clust_pos(
3616
&index->table->cols[templ->col_no],
3622
/********************************************************************//**
3623
Get the upper limit of the MySQL integral and floating-point type. */
3626
ha_innobase::innobase_get_int_col_max_value(
3627
/*========================================*/
3630
uint64_t max_value = 0;
3632
switch(field->key_type()) {
3634
case HA_KEYTYPE_BINARY:
3635
max_value = 0xFFULL;
3638
case HA_KEYTYPE_UINT24:
3639
max_value = 0xFFFFFFULL;
3642
case HA_KEYTYPE_ULONG_INT:
3643
max_value = 0xFFFFFFFFULL;
3645
case HA_KEYTYPE_LONG_INT:
3646
max_value = 0x7FFFFFFFULL;
3649
case HA_KEYTYPE_ULONGLONG:
3650
max_value = 0xFFFFFFFFFFFFFFFFULL;
3652
case HA_KEYTYPE_LONGLONG:
3653
max_value = 0x7FFFFFFFFFFFFFFFULL;
3655
case HA_KEYTYPE_DOUBLE:
3656
/* We use the maximum as per IEEE754-2008 standard, 2^53 */
3657
max_value = 0x20000000000000ULL;
4222
3666
/********************************************************************//**
4225
3669
INSERT ... SELECT type of statements, since MySQL binlog only stores the
4226
3670
min value of the autoinc interval. Once that is fixed we can get rid of
4227
3671
the special lock handling.
4228
@return DB_SUCCESS if all OK else error code */
3672
@return DB_SUCCESS if all OK else error code */
4231
3675
ha_innobase::innobase_lock_autoinc(void)
4232
3676
/*====================================*/
4234
ulint error = DB_SUCCESS;
4236
dict_table_autoinc_lock(prebuilt->table);
4238
return(ulong(error));
3678
ulint error = DB_SUCCESS;
3680
switch (innobase_autoinc_lock_mode) {
3681
case AUTOINC_NO_LOCKING:
3682
/* Acquire only the AUTOINC mutex. */
3683
dict_table_autoinc_lock(prebuilt->table);
3686
case AUTOINC_NEW_STYLE_LOCKING:
3687
/* For simple (single/multi) row INSERTs, we fallback to the
3688
old style only if another transaction has already acquired
3689
the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
3690
etc. type of statement. */
3691
if (session_sql_command(user_session) == SQLCOM_INSERT
3692
|| session_sql_command(user_session) == SQLCOM_REPLACE) {
3693
dict_table_t* d_table = prebuilt->table;
3695
/* Acquire the AUTOINC mutex. */
3696
dict_table_autoinc_lock(d_table);
3698
/* We need to check that another transaction isn't
3699
already holding the AUTOINC lock on the table. */
3700
if (d_table->n_waiting_or_granted_auto_inc_locks) {
3701
/* Release the mutex to avoid deadlocks. */
3702
dict_table_autoinc_unlock(d_table);
3707
/* Fall through to old style locking. */
3709
case AUTOINC_OLD_STYLE_LOCKING:
3710
error = row_lock_table_autoinc_for_mysql(prebuilt);
3712
if (error == DB_SUCCESS) {
3714
/* Acquire the AUTOINC mutex. */
3715
dict_table_autoinc_lock(prebuilt->table);
3723
return(ulong(error));
4241
3726
/********************************************************************//**
4242
3727
Reset the autoinc value in the table.
4243
@return DB_SUCCESS if all went well else error code */
3728
@return DB_SUCCESS if all went well else error code */
4246
3731
ha_innobase::innobase_reset_autoinc(
4247
3732
/*================================*/
4248
uint64_t autoinc) /*!< in: value to store */
3733
uint64_t autoinc) /*!< in: value to store */
4250
dict_table_autoinc_lock(prebuilt->table);
4251
dict_table_autoinc_initialize(prebuilt->table, autoinc);
4252
dict_table_autoinc_unlock(prebuilt->table);
4254
return(ulong(DB_SUCCESS));
3737
error = innobase_lock_autoinc();
3739
if (error == DB_SUCCESS) {
3741
dict_table_autoinc_initialize(prebuilt->table, autoinc);
3743
dict_table_autoinc_unlock(prebuilt->table);
3746
return(ulong(error));
4257
3749
/********************************************************************//**
4258
3750
Store the autoinc value in the table. The autoinc value is only set if
4259
3751
it's greater than the existing autoinc value in the table.
4260
@return DB_SUCCESS if all went well else error code */
3752
@return DB_SUCCESS if all went well else error code */
4263
3755
ha_innobase::innobase_set_max_autoinc(
4264
3756
/*==================================*/
4265
uint64_t auto_inc) /*!< in: value to store */
3757
uint64_t auto_inc) /*!< in: value to store */
4267
dict_table_autoinc_lock(prebuilt->table);
4268
dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
4269
dict_table_autoinc_unlock(prebuilt->table);
4271
return(ulong(DB_SUCCESS));
3761
error = innobase_lock_autoinc();
3763
if (error == DB_SUCCESS) {
3765
dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
3767
dict_table_autoinc_unlock(prebuilt->table);
3770
return(ulong(error));
4274
3773
/********************************************************************//**
4275
3774
Stores a row in an InnoDB database, to the table specified in this
4277
@return error code */
3776
@return error code */
4280
ha_innobase::doInsertRecord(
3779
ha_innobase::write_row(
4281
3780
/*===================*/
4282
unsigned char* record) /*!< in: a row in MySQL format */
3781
unsigned char* record) /*!< in: a row in MySQL format */
4285
3784
int error_result= 0;
4286
ibool auto_inc_used= FALSE;
4288
trx_t* trx = session_to_trx(user_session);
4290
if (prebuilt->trx != trx) {
4291
errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
4292
"%p, but for the current thread it is at %p",
4293
(const void*) prebuilt->trx, (const void*) trx);
4295
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
4296
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
4298
"InnoDB: Dump of 200 bytes around ha_data: ",
4300
ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
4305
sql_command = session_sql_command(user_session);
4307
if ((sql_command == SQLCOM_ALTER_TABLE
4308
|| sql_command == SQLCOM_CREATE_INDEX
4309
|| sql_command == SQLCOM_DROP_INDEX)
4310
&& num_write_row >= 10000) {
4311
/* ALTER TABLE is COMMITted at every 10000 copied rows.
4312
The IX table lock for the original table has to be re-issued.
4313
As this method will be called on a temporary table where the
4314
contents of the original table is being copied to, it is
4315
a bit tricky to determine the source table. The cursor
4316
position in the source table need not be adjusted after the
4317
intermediate COMMIT, since writes by other transactions are
4318
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
4320
dict_table_t* src_table;
4321
enum lock_mode mode;
4325
/* Commit the transaction. This will release the table
4326
locks, so they have to be acquired again. */
4328
/* Altering an InnoDB table */
4329
/* Get the source table. */
4330
src_table = lock_get_src_table(
4331
prebuilt->trx, prebuilt->table, &mode);
3785
ibool auto_inc_used= FALSE;
3787
trx_t* trx = session_to_trx(user_session);
3789
if (prebuilt->trx != trx) {
3790
errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
3791
"%p, but for the current thread it is at %p",
3792
(const void*) prebuilt->trx, (const void*) trx);
3794
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
3795
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
3797
"InnoDB: Dump of 200 bytes around ha_data: ",
3799
ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
3804
ha_statistic_increment(&system_status_var::ha_write_count);
3806
sql_command = session_sql_command(user_session);
3808
if ((sql_command == SQLCOM_ALTER_TABLE
3809
|| sql_command == SQLCOM_CREATE_INDEX
3810
|| sql_command == SQLCOM_DROP_INDEX)
3811
&& num_write_row >= 10000) {
3812
/* ALTER TABLE is COMMITted at every 10000 copied rows.
3813
The IX table lock for the original table has to be re-issued.
3814
As this method will be called on a temporary table where the
3815
contents of the original table is being copied to, it is
3816
a bit tricky to determine the source table. The cursor
3817
position in the source table need not be adjusted after the
3818
intermediate COMMIT, since writes by other transactions are
3819
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
3821
dict_table_t* src_table;
3822
enum lock_mode mode;
3826
/* Commit the transaction. This will release the table
3827
locks, so they have to be acquired again. */
3829
/* Altering an InnoDB table */
3830
/* Get the source table. */
3831
src_table = lock_get_src_table(
3832
prebuilt->trx, prebuilt->table, &mode);
4334
/* Unknown situation: do not commit */
4336
ut_print_timestamp(stderr);
4338
" InnoDB: ALTER TABLE is holding lock"
4339
" on %lu tables!\n",
4340
prebuilt->trx->mysql_n_tables_locked);
4343
} else if (src_table == prebuilt->table) {
4344
/* Source table is not in InnoDB format:
4345
no need to re-acquire locks on it. */
4347
/* Altering to InnoDB format */
4348
getTransactionalEngine()->commit(user_session, 1);
4349
/* We will need an IX lock on the destination table. */
4350
prebuilt->sql_stat_start = TRUE;
4352
/* Ensure that there are no other table locks than
4353
LOCK_IX and LOCK_AUTO_INC on the destination table. */
4355
if (!lock_is_table_exclusive(prebuilt->table,
4360
/* Commit the transaction. This will release the table
4361
locks, so they have to be acquired again. */
4362
getTransactionalEngine()->commit(user_session, 1);
4363
/* Re-acquire the table lock on the source table. */
4364
row_lock_table_for_mysql(prebuilt, src_table, mode);
4365
/* We will need an IX lock on the destination table. */
4366
prebuilt->sql_stat_start = TRUE;
4372
/* This is the case where the table has an auto-increment column */
4373
if (getTable()->next_number_field && record == getTable()->getInsertRecord()) {
4375
/* Reset the error code before calling
4376
innobase_get_auto_increment(). */
4377
prebuilt->autoinc_error = DB_SUCCESS;
4379
if ((error = update_auto_increment())) {
4380
/* We don't want to mask autoinc overflow errors. */
4382
/* Handle the case where the AUTOINC sub-system
4383
failed during initialization. */
4384
if (prebuilt->autoinc_error == DB_UNSUPPORTED) {
4385
error_result = ER_AUTOINC_READ_FAILED;
4386
/* Set the error message to report too. */
4387
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
4389
} else if (prebuilt->autoinc_error != DB_SUCCESS) {
4390
error = (int) prebuilt->autoinc_error;
4395
/* MySQL errors are passed straight back. */
4396
error_result = (int) error;
4400
auto_inc_used = TRUE;
4403
if (prebuilt->mysql_template == NULL
4404
|| prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
4406
/* Build the template used in converting quickly between
4407
the two database formats */
4409
build_template(prebuilt, NULL, getTable(), ROW_MYSQL_WHOLE_ROW);
4412
innodb_srv_conc_enter_innodb(prebuilt->trx);
4414
error = row_insert_for_mysql((byte*) record, prebuilt);
4416
user_session->setXaId((ib_uint64_t) ut_conv_dulint_to_longlong(trx->id));
4418
/* Handle duplicate key errors */
4419
if (auto_inc_used) {
4422
uint64_t col_max_value;
4424
/* Note the number of rows processed for this statement, used
4425
by get_auto_increment() to determine the number of AUTO-INC
4426
values to reserve. This is only useful for a mult-value INSERT
4427
and is a statement level counter.*/
4428
if (trx->n_autoinc_rows > 0) {
4429
--trx->n_autoinc_rows;
4432
/* We need the upper limit of the col type to check for
4433
whether we update the table autoinc counter or not. */
4434
col_max_value = innobase_get_int_col_max_value(
4435
getTable()->next_number_field);
4436
/* Get the value that MySQL attempted to store in the table.*/
4437
auto_inc = getTable()->next_number_field->val_int();
4440
case DB_DUPLICATE_KEY:
4442
/* A REPLACE command and LOAD DATA INFILE REPLACE
4443
handle a duplicate key error themselves, but we
4444
must update the autoinc counter if we are performing
4445
those statements. */
4447
switch (sql_command) {
4449
if ((trx->duplicates
4450
& (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
4452
goto set_max_autoinc;
4456
case SQLCOM_REPLACE:
4457
case SQLCOM_INSERT_SELECT:
4458
case SQLCOM_REPLACE_SELECT:
4459
goto set_max_autoinc;
4468
/* If the actual value inserted is greater than
4469
the upper limit of the interval, then we try and
4470
update the table upper limit. Note: last_value
4471
will be 0 if get_auto_increment() was not called.*/
4473
if (auto_inc >= prebuilt->autoinc_last_value) {
3835
/* Unknown situation: do not commit */
3837
ut_print_timestamp(stderr);
3839
" InnoDB: ALTER TABLE is holding lock"
3840
" on %lu tables!\n",
3841
prebuilt->trx->mysql_n_tables_locked);
3844
} else if (src_table == prebuilt->table) {
3845
/* Source table is not in InnoDB format:
3846
no need to re-acquire locks on it. */
3848
/* Altering to InnoDB format */
3849
getTransactionalEngine()->commit(user_session, 1);
3850
/* Note that this transaction is still active. */
3851
prebuilt->trx->active_trans = 1;
3852
/* We will need an IX lock on the destination table. */
3853
prebuilt->sql_stat_start = TRUE;
3855
/* Ensure that there are no other table locks than
3856
LOCK_IX and LOCK_AUTO_INC on the destination table. */
3858
if (!lock_is_table_exclusive(prebuilt->table,
3863
/* Commit the transaction. This will release the table
3864
locks, so they have to be acquired again. */
3865
getTransactionalEngine()->commit(user_session, 1);
3866
/* Note that this transaction is still active. */
3867
prebuilt->trx->active_trans = 1;
3868
/* Re-acquire the table lock on the source table. */
3869
row_lock_table_for_mysql(prebuilt, src_table, mode);
3870
/* We will need an IX lock on the destination table. */
3871
prebuilt->sql_stat_start = TRUE;
3877
/* This is the case where the table has an auto-increment column */
3878
if (table->next_number_field && record == table->record[0]) {
3880
/* Reset the error code before calling
3881
innobase_get_auto_increment(). */
3882
prebuilt->autoinc_error = DB_SUCCESS;
3884
if ((error = update_auto_increment())) {
3886
/* We don't want to mask autoinc overflow errors. */
3887
if (prebuilt->autoinc_error != DB_SUCCESS) {
3888
error = (int) prebuilt->autoinc_error;
3893
/* MySQL errors are passed straight back. */
3894
error_result = (int) error;
3898
auto_inc_used = TRUE;
3901
if (prebuilt->mysql_template == NULL
3902
|| prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
3904
/* Build the template used in converting quickly between
3905
the two database formats */
3907
build_template(prebuilt, NULL, table,
3908
ROW_MYSQL_WHOLE_ROW);
3911
innodb_srv_conc_enter_innodb(prebuilt->trx);
3913
error = row_insert_for_mysql((byte*) record, prebuilt);
3915
/* Handle duplicate key errors */
3916
if (auto_inc_used) {
3919
uint64_t col_max_value;
3921
/* Note the number of rows processed for this statement, used
3922
by get_auto_increment() to determine the number of AUTO-INC
3923
values to reserve. This is only useful for a mult-value INSERT
3924
and is a statement level counter.*/
3925
if (trx->n_autoinc_rows > 0) {
3926
--trx->n_autoinc_rows;
3929
/* We need the upper limit of the col type to check for
3930
whether we update the table autoinc counter or not. */
3931
col_max_value = innobase_get_int_col_max_value(
3932
table->next_number_field);
3934
/* Get the value that MySQL attempted to store in the table.*/
3935
auto_inc = table->next_number_field->val_int();
3938
case DB_DUPLICATE_KEY:
3940
/* A REPLACE command and LOAD DATA INFILE REPLACE
3941
handle a duplicate key error themselves, but we
3942
must update the autoinc counter if we are performing
3943
those statements. */
3945
switch (sql_command) {
3947
if ((trx->duplicates
3948
& (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
3950
goto set_max_autoinc;
3954
case SQLCOM_REPLACE:
3955
case SQLCOM_INSERT_SELECT:
3956
case SQLCOM_REPLACE_SELECT:
3957
goto set_max_autoinc;
3966
/* If the actual value inserted is greater than
3967
the upper limit of the interval, then we try and
3968
update the table upper limit. Note: last_value
3969
will be 0 if get_auto_increment() was not called.*/
3971
if (auto_inc <= col_max_value
3972
&& auto_inc >= prebuilt->autoinc_last_value) {
4474
3973
set_max_autoinc:
4475
/* This should filter out the negative
4476
values set explicitly by the user. */
4477
if (auto_inc <= col_max_value) {
4478
ut_a(prebuilt->autoinc_increment > 0);
4483
offset = prebuilt->autoinc_offset;
4484
need = prebuilt->autoinc_increment;
4486
auto_inc = innobase_next_autoinc(
4488
need, offset, col_max_value);
4490
err = innobase_set_max_autoinc(
4493
if (err != DB_SUCCESS) {
4502
innodb_srv_conc_exit_innodb(prebuilt->trx);
3974
ut_a(prebuilt->autoinc_increment > 0);
3979
offset = prebuilt->autoinc_offset;
3980
need = prebuilt->autoinc_increment;
3982
auto_inc = innobase_next_autoinc(
3983
auto_inc, need, offset, col_max_value);
3985
err = innobase_set_max_autoinc(auto_inc);
3987
if (err != DB_SUCCESS) {
3995
innodb_srv_conc_exit_innodb(prebuilt->trx);
4505
error_result = convert_error_code_to_mysql((int) error,
4506
prebuilt->table->flags,
3998
error_result = convert_error_code_to_mysql((int) error,
3999
prebuilt->table->flags,
4510
innobase_active_small();
4003
innobase_active_small();
4512
return(error_result);
4005
return(error_result);
4515
4008
/**********************************************************************//**
4516
4009
Checks which fields have changed in a row and stores information
4517
4010
of them to an update vector.
4518
@return error number or 0 */
4011
@return error number or 0 */
4521
4014
calc_row_difference(
4522
4015
/*================*/
4523
upd_t* uvect, /*!< in/out: update vector */
4524
unsigned char* old_row, /*!< in: old row in MySQL format */
4525
unsigned char* new_row, /*!< in: new row in MySQL format */
4526
Table* table, /*!< in: table in MySQL data
4528
unsigned char* upd_buff, /*!< in: buffer to use */
4529
ulint buff_len, /*!< in: buffer length */
4530
row_prebuilt_t* prebuilt, /*!< in: InnoDB prebuilt struct */
4531
Session* ) /*!< in: user thread */
4016
upd_t* uvect, /*!< in/out: update vector */
4017
unsigned char* old_row, /*!< in: old row in MySQL format */
4018
unsigned char* new_row, /*!< in: new row in MySQL format */
4019
Table* table, /*!< in: table in MySQL data
4021
unsigned char* upd_buff, /*!< in: buffer to use */
4022
ulint buff_len, /*!< in: buffer length */
4023
row_prebuilt_t* prebuilt, /*!< in: InnoDB prebuilt struct */
4024
Session* ) /*!< in: user thread */
4533
unsigned char* original_upd_buff = upd_buff;
4534
enum_field_types field_mysql_type;
4539
const byte* new_mysql_row_col;
4543
upd_field_t* ufield;
4545
ulint n_changed = 0;
4547
dict_index_t* clust_index;
4550
n_fields = table->getShare()->sizeFields();
4551
clust_index = dict_table_get_first_index(prebuilt->table);
4553
/* We use upd_buff to convert changed fields */
4554
buf = (byte*) upd_buff;
4556
for (i = 0; i < n_fields; i++) {
4557
Field *field= table->getField(i);
4559
o_ptr = (const byte*) old_row + get_field_offset(table, field);
4560
n_ptr = (const byte*) new_row + get_field_offset(table, field);
4562
/* Use new_mysql_row_col and col_pack_len save the values */
4564
new_mysql_row_col = n_ptr;
4565
col_pack_len = field->pack_length();
4567
o_len = col_pack_len;
4568
n_len = col_pack_len;
4570
/* We use o_ptr and n_ptr to dig up the actual data for
4573
field_mysql_type = field->type();
4575
col_type = prebuilt->table->cols[i].mtype;
4580
o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
4581
n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
4588
if (field_mysql_type == DRIZZLE_TYPE_VARCHAR) {
4589
/* This is a >= 5.0.3 type true VARCHAR where
4590
the real payload data length is stored in
4593
o_ptr = row_mysql_read_true_varchar(
4596
(((Field_varstring*)field)->pack_length_no_ptr()));
4598
n_ptr = row_mysql_read_true_varchar(
4601
(((Field_varstring*)field)->pack_length_no_ptr()));
4609
if (field->null_ptr) {
4610
if (field_in_record_is_null(table, field,
4612
o_len = UNIV_SQL_NULL;
4615
if (field_in_record_is_null(table, field,
4617
n_len = UNIV_SQL_NULL;
4621
if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
4622
0 != memcmp(o_ptr, n_ptr, o_len))) {
4623
/* The field has changed */
4625
ufield = uvect->fields + n_changed;
4627
/* Let us use a dummy dfield to make the conversion
4628
from the MySQL column format to the InnoDB format */
4630
dict_col_copy_type(prebuilt->table->cols + i,
4633
if (n_len != UNIV_SQL_NULL) {
4634
buf = row_mysql_store_col_in_innobase_format(
4640
dict_table_is_comp(prebuilt->table));
4641
dfield_copy_data(&ufield->new_val, &dfield);
4643
dfield_set_null(&ufield->new_val);
4647
ufield->orig_len = 0;
4648
ufield->field_no = dict_col_get_clust_pos(
4649
&prebuilt->table->cols[i], clust_index);
4654
uvect->n_fields = n_changed;
4655
uvect->info_bits = 0;
4657
ut_a(buf <= (byte*)original_upd_buff + buff_len);
4026
unsigned char* original_upd_buff = upd_buff;
4028
enum_field_types field_mysql_type;
4033
const byte* new_mysql_row_col;
4037
upd_field_t* ufield;
4039
ulint n_changed = 0;
4041
dict_index_t* clust_index;
4044
n_fields = table->s->fields;
4045
clust_index = dict_table_get_first_index(prebuilt->table);
4047
/* We use upd_buff to convert changed fields */
4048
buf = (byte*) upd_buff;
4050
for (i = 0; i < n_fields; i++) {
4051
field = table->field[i];
4053
o_ptr = (const byte*) old_row + get_field_offset(table, field);
4054
n_ptr = (const byte*) new_row + get_field_offset(table, field);
4056
/* Use new_mysql_row_col and col_pack_len save the values */
4058
new_mysql_row_col = n_ptr;
4059
col_pack_len = field->pack_length();
4061
o_len = col_pack_len;
4062
n_len = col_pack_len;
4064
/* We use o_ptr and n_ptr to dig up the actual data for
4067
field_mysql_type = field->type();
4069
col_type = prebuilt->table->cols[i].mtype;
4074
o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
4075
n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
4082
if (field_mysql_type == DRIZZLE_TYPE_VARCHAR) {
4083
/* This is a >= 5.0.3 type true VARCHAR where
4084
the real payload data length is stored in
4087
o_ptr = row_mysql_read_true_varchar(
4090
(((Field_varstring*)field)->length_bytes));
4092
n_ptr = row_mysql_read_true_varchar(
4095
(((Field_varstring*)field)->length_bytes));
4103
if (field->null_ptr) {
4104
if (field_in_record_is_null(table, field,
4106
o_len = UNIV_SQL_NULL;
4109
if (field_in_record_is_null(table, field,
4111
n_len = UNIV_SQL_NULL;
4115
if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
4116
0 != memcmp(o_ptr, n_ptr, o_len))) {
4117
/* The field has changed */
4119
ufield = uvect->fields + n_changed;
4121
/* Let us use a dummy dfield to make the conversion
4122
from the MySQL column format to the InnoDB format */
4124
dict_col_copy_type(prebuilt->table->cols + i,
4127
if (n_len != UNIV_SQL_NULL) {
4128
buf = row_mysql_store_col_in_innobase_format(
4134
dict_table_is_comp(prebuilt->table));
4135
dfield_copy_data(&ufield->new_val, &dfield);
4137
dfield_set_null(&ufield->new_val);
4141
ufield->orig_len = 0;
4142
ufield->field_no = dict_col_get_clust_pos(
4143
&prebuilt->table->cols[i], clust_index);
4148
uvect->n_fields = n_changed;
4149
uvect->info_bits = 0;
4151
ut_a(buf <= (byte*)original_upd_buff + buff_len);
4662
4156
/**********************************************************************//**
4666
4160
TODO: currently InnoDB does not prevent the 'Halloween problem':
4667
4161
in a searched update a single row can get updated several times
4668
4162
if its index columns are updated!
4669
@return error number or 0 */
4163
@return error number or 0 */
4672
ha_innobase::doUpdateRecord(
4166
ha_innobase::update_row(
4673
4167
/*====================*/
4674
const unsigned char* old_row,/*!< in: old row in MySQL format */
4675
unsigned char* new_row)/*!< in: new row in MySQL format */
4168
const unsigned char* old_row,/*!< in: old row in MySQL format */
4169
unsigned char* new_row)/*!< in: new row in MySQL format */
4679
trx_t* trx = session_to_trx(user_session);
4681
ut_a(prebuilt->trx == trx);
4683
if (prebuilt->upd_node) {
4684
uvect = prebuilt->upd_node->update;
4686
uvect = row_get_prebuilt_update_vector(prebuilt);
4689
/* Build an update vector from the modified fields in the rows
4690
(uses upd_buff of the handle) */
4692
calc_row_difference(uvect, (unsigned char*) old_row, new_row, getTable(),
4693
&upd_buff[0], (ulint)upd_and_key_val_buff_len,
4694
prebuilt, user_session);
4696
/* This is not a delete */
4697
prebuilt->upd_node->is_delete = FALSE;
4699
ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
4701
if (getTable()->found_next_number_field)
4704
uint64_t col_max_value;
4706
auto_inc = getTable()->found_next_number_field->val_int();
4708
/* We need the upper limit of the col type to check for
4709
whether we update the table autoinc counter or not. */
4710
col_max_value = innobase_get_int_col_max_value(
4711
getTable()->found_next_number_field);
4713
uint64_t current_autoinc;
4714
ulint autoinc_error= innobase_get_autoinc(¤t_autoinc);
4715
if (autoinc_error == DB_SUCCESS
4716
&& auto_inc <= col_max_value && auto_inc != 0
4717
&& auto_inc >= current_autoinc)
4723
offset = prebuilt->autoinc_offset;
4724
need = prebuilt->autoinc_increment;
4726
auto_inc = innobase_next_autoinc(
4727
auto_inc, need, offset, col_max_value);
4729
dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
4732
dict_table_autoinc_unlock(prebuilt->table);
4735
innodb_srv_conc_enter_innodb(trx);
4737
error = row_update_for_mysql((byte*) old_row, prebuilt);
4739
user_session->setXaId((ib_uint64_t) ut_conv_dulint_to_longlong(trx->id));
4741
/* We need to do some special AUTOINC handling for the following case:
4743
INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
4745
We need to use the AUTOINC counter that was actually used by
4746
MySQL in the UPDATE statement, which can be different from the
4747
value used in the INSERT statement.*/
4749
if (error == DB_SUCCESS
4750
&& getTable()->next_number_field
4751
&& new_row == getTable()->getInsertRecord()
4752
&& session_sql_command(user_session) == SQLCOM_INSERT
4753
&& (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4754
== TRX_DUP_IGNORE) {
4757
uint64_t col_max_value;
4759
auto_inc = getTable()->next_number_field->val_int();
4761
/* We need the upper limit of the col type to check for
4762
whether we update the table autoinc counter or not. */
4763
col_max_value = innobase_get_int_col_max_value(
4764
getTable()->next_number_field);
4766
if (auto_inc <= col_max_value && auto_inc != 0) {
4771
offset = prebuilt->autoinc_offset;
4772
need = prebuilt->autoinc_increment;
4774
auto_inc = innobase_next_autoinc(
4775
auto_inc, need, offset, col_max_value);
4777
error = innobase_set_max_autoinc(auto_inc);
4781
innodb_srv_conc_exit_innodb(trx);
4783
error = convert_error_code_to_mysql(error,
4784
prebuilt->table->flags,
4173
trx_t* trx = session_to_trx(user_session);
4175
ut_a(prebuilt->trx == trx);
4177
ha_statistic_increment(&system_status_var::ha_update_count);
4179
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
4180
table->timestamp_field->set_time();
4182
if (prebuilt->upd_node) {
4183
uvect = prebuilt->upd_node->update;
4185
uvect = row_get_prebuilt_update_vector(prebuilt);
4188
/* Build an update vector from the modified fields in the rows
4189
(uses upd_buff of the handle) */
4191
calc_row_difference(uvect, (unsigned char*) old_row, new_row, table,
4192
upd_buff, (ulint)upd_and_key_val_buff_len,
4193
prebuilt, user_session);
4195
/* This is not a delete */
4196
prebuilt->upd_node->is_delete = FALSE;
4198
ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
4200
innodb_srv_conc_enter_innodb(trx);
4202
error = row_update_for_mysql((byte*) old_row, prebuilt);
4204
/* We need to do some special AUTOINC handling for the following case:
4206
INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
4208
We need to use the AUTOINC counter that was actually used by
4209
MySQL in the UPDATE statement, which can be different from the
4210
value used in the INSERT statement.*/
4212
if (error == DB_SUCCESS
4213
&& table->next_number_field
4214
&& new_row == table->record[0]
4215
&& session_sql_command(user_session) == SQLCOM_INSERT
4216
&& (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4217
== TRX_DUP_IGNORE) {
4220
uint64_t col_max_value;
4222
auto_inc = table->next_number_field->val_int();
4224
/* We need the upper limit of the col type to check for
4225
whether we update the table autoinc counter or not. */
4226
col_max_value = innobase_get_int_col_max_value(
4227
table->next_number_field);
4229
if (auto_inc <= col_max_value && auto_inc != 0) {
4234
offset = prebuilt->autoinc_offset;
4235
need = prebuilt->autoinc_increment;
4237
auto_inc = innobase_next_autoinc(
4238
auto_inc, need, offset, col_max_value);
4240
error = innobase_set_max_autoinc(auto_inc);
4244
innodb_srv_conc_exit_innodb(trx);
4246
error = convert_error_code_to_mysql(error,
4247
prebuilt->table->flags,
4787
if (error == 0 /* success */
4788
&& uvect->n_fields == 0 /* no columns were updated */) {
4790
/* This is the same as success, but instructs
4791
MySQL that the row is not really updated and it
4792
should not increase the count of updated rows.
4793
This is fix for http://bugs.mysql.com/29157 */
4794
error = HA_ERR_RECORD_IS_THE_SAME;
4797
/* Tell InnoDB server that there might be work for
4800
innobase_active_small();
4250
if (error == 0 /* success */
4251
&& uvect->n_fields == 0 /* no columns were updated */) {
4253
/* This is the same as success, but instructs
4254
MySQL that the row is not really updated and it
4255
should not increase the count of updated rows.
4256
This is fix for http://bugs.mysql.com/29157 */
4257
error = HA_ERR_RECORD_IS_THE_SAME;
4260
/* Tell InnoDB server that there might be work for
4263
innobase_active_small();
4805
4268
/**********************************************************************//**
4806
4269
Deletes a row given as the parameter.
4807
@return error number or 0 */
4270
@return error number or 0 */
4810
ha_innobase::doDeleteRecord(
4273
ha_innobase::delete_row(
4811
4274
/*====================*/
4812
const unsigned char* record) /*!< in: a row in MySQL format */
4275
const unsigned char* record) /*!< in: a row in MySQL format */
4815
trx_t* trx = session_to_trx(user_session);
4817
ut_a(prebuilt->trx == trx);
4819
if (!prebuilt->upd_node) {
4820
row_get_prebuilt_update_vector(prebuilt);
4823
/* This is a delete */
4825
prebuilt->upd_node->is_delete = TRUE;
4827
innodb_srv_conc_enter_innodb(trx);
4829
error = row_update_for_mysql((byte*) record, prebuilt);
4831
user_session->setXaId((ib_uint64_t) ut_conv_dulint_to_longlong(trx->id));
4833
innodb_srv_conc_exit_innodb(trx);
4835
error = convert_error_code_to_mysql(
4836
error, prebuilt->table->flags, user_session);
4838
/* Tell the InnoDB server that there might be work for
4841
innobase_active_small();
4278
trx_t* trx = session_to_trx(user_session);
4280
ut_a(prebuilt->trx == trx);
4282
ha_statistic_increment(&system_status_var::ha_delete_count);
4284
if (!prebuilt->upd_node) {
4285
row_get_prebuilt_update_vector(prebuilt);
4288
/* This is a delete */
4290
prebuilt->upd_node->is_delete = TRUE;
4292
innodb_srv_conc_enter_innodb(trx);
4294
error = row_update_for_mysql((byte*) record, prebuilt);
4296
innodb_srv_conc_exit_innodb(trx);
4298
error = convert_error_code_to_mysql(
4299
error, prebuilt->table->flags, user_session);
4301
/* Tell the InnoDB server that there might be work for
4304
innobase_active_small();
4846
4309
/**********************************************************************//**
5052
4515
/**********************************************************************//**
5053
4516
Positions an index cursor to the index specified in the handle. Fetches the
5055
@return 0, HA_ERR_KEY_NOT_FOUND, or error number */
4518
@return 0, HA_ERR_KEY_NOT_FOUND, or error number */
5058
4521
ha_innobase::index_read(
5059
4522
/*====================*/
5060
unsigned char* buf, /*!< in/out: buffer for the returned
5062
const unsigned char* key_ptr,/*!< in: key value; if this is NULL
5063
we position the cursor at the
5064
start or end of index; this can
5065
also contain an InnoDB row id, in
5066
which case key_len is the InnoDB
5067
row id length; the key value can
5068
also be a prefix of a full key value,
5069
and the last column can be a prefix
5071
uint key_len,/*!< in: key value length */
5072
enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
4523
unsigned char* buf, /*!< in/out: buffer for the returned
4525
const unsigned char* key_ptr,/*!< in: key value; if this is NULL
4526
we position the cursor at the
4527
start or end of index; this can
4528
also contain an InnoDB row id, in
4529
which case key_len is the InnoDB
4530
row id length; the key value can
4531
also be a prefix of a full key value,
4532
and the last column can be a prefix
4534
uint key_len,/*!< in: key value length */
4535
enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
5075
dict_index_t* index;
5076
ulint match_mode = 0;
5080
ut_a(prebuilt->trx == session_to_trx(user_session));
5082
ha_statistic_increment(&system_status_var::ha_read_key_count);
5084
index = prebuilt->index;
5086
if (UNIV_UNLIKELY(index == NULL)) {
5087
prebuilt->index_usable = FALSE;
5088
return(HA_ERR_CRASHED);
5092
/* Note that if the index for which the search template is built is not
5093
necessarily prebuilt->index, but can also be the clustered index */
5095
if (prebuilt->sql_stat_start) {
5096
build_template(prebuilt, user_session, getTable(),
5097
ROW_MYSQL_REC_FIELDS);
5101
/* Convert the search key value to InnoDB format into
5102
prebuilt->search_tuple */
5104
row_sel_convert_mysql_key_to_innobase(
5105
prebuilt->search_tuple,
5106
(byte*) &key_val_buff[0],
5107
(ulint)upd_and_key_val_buff_len,
5113
/* We position the cursor to the last or the first entry
5116
dtuple_set_n_fields(prebuilt->search_tuple, 0);
5119
mode = convert_search_mode_to_innobase(find_flag);
5123
if (find_flag == HA_READ_KEY_EXACT) {
5125
match_mode = ROW_SEL_EXACT;
5127
} else if (find_flag == HA_READ_PREFIX
5128
|| find_flag == HA_READ_PREFIX_LAST) {
5130
match_mode = ROW_SEL_EXACT_PREFIX;
5133
last_match_mode = (uint) match_mode;
5135
if (mode != PAGE_CUR_UNSUPP) {
5137
innodb_srv_conc_enter_innodb(prebuilt->trx);
5139
ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
5142
innodb_srv_conc_exit_innodb(prebuilt->trx);
5145
ret = DB_UNSUPPORTED;
5151
getTable()->status = 0;
5153
case DB_RECORD_NOT_FOUND:
5154
error = HA_ERR_KEY_NOT_FOUND;
5155
getTable()->status = STATUS_NOT_FOUND;
5157
case DB_END_OF_INDEX:
5158
error = HA_ERR_KEY_NOT_FOUND;
5159
getTable()->status = STATUS_NOT_FOUND;
5162
error = convert_error_code_to_mysql((int) ret,
5163
prebuilt->table->flags,
5165
getTable()->status = STATUS_NOT_FOUND;
4538
dict_index_t* index;
4539
ulint match_mode = 0;
4543
ut_a(prebuilt->trx == session_to_trx(user_session));
4545
ha_statistic_increment(&system_status_var::ha_read_key_count);
4547
index = prebuilt->index;
4549
/* Note that if the index for which the search template is built is not
4550
necessarily prebuilt->index, but can also be the clustered index */
4552
if (prebuilt->sql_stat_start) {
4553
build_template(prebuilt, user_session, table,
4554
ROW_MYSQL_REC_FIELDS);
4558
/* Convert the search key value to InnoDB format into
4559
prebuilt->search_tuple */
4561
row_sel_convert_mysql_key_to_innobase(
4562
prebuilt->search_tuple,
4563
(byte*) key_val_buff,
4564
(ulint)upd_and_key_val_buff_len,
4570
/* We position the cursor to the last or the first entry
4573
dtuple_set_n_fields(prebuilt->search_tuple, 0);
4576
mode = convert_search_mode_to_innobase(find_flag);
4580
if (find_flag == HA_READ_KEY_EXACT) {
4582
match_mode = ROW_SEL_EXACT;
4584
} else if (find_flag == HA_READ_PREFIX
4585
|| find_flag == HA_READ_PREFIX_LAST) {
4587
match_mode = ROW_SEL_EXACT_PREFIX;
4590
last_match_mode = (uint) match_mode;
4592
if (mode != PAGE_CUR_UNSUPP) {
4594
innodb_srv_conc_enter_innodb(prebuilt->trx);
4596
ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
4599
innodb_srv_conc_exit_innodb(prebuilt->trx);
4602
ret = DB_UNSUPPORTED;
4610
case DB_RECORD_NOT_FOUND:
4611
error = HA_ERR_KEY_NOT_FOUND;
4612
table->status = STATUS_NOT_FOUND;
4614
case DB_END_OF_INDEX:
4615
error = HA_ERR_KEY_NOT_FOUND;
4616
table->status = STATUS_NOT_FOUND;
4619
error = convert_error_code_to_mysql((int) ret,
4620
prebuilt->table->flags,
4622
table->status = STATUS_NOT_FOUND;
5172
4629
/*******************************************************************//**
5173
4630
The following functions works like index_read, but it find the last
5174
4631
row with the current key value or prefix.
5175
@return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
4632
@return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
5178
4635
ha_innobase::index_read_last(
5179
4636
/*=========================*/
5180
unsigned char* buf, /*!< out: fetched row */
5181
const unsigned char* key_ptr,/*!< in: key value, or a prefix of a full
5183
uint key_len)/*!< in: length of the key val or prefix
4637
unsigned char* buf, /*!< out: fetched row */
4638
const unsigned char* key_ptr,/*!< in: key value, or a prefix of a full
4640
uint key_len)/*!< in: length of the key val or prefix
5186
return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
4643
return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
5189
4646
/********************************************************************//**
5190
4647
Get the index for a handle. Does not change active index.
5191
@return NULL or index instance. */
4648
@return NULL or index instance. */
5194
4651
ha_innobase::innobase_get_index(
5195
4652
/*============================*/
5196
uint keynr) /*!< in: use this index; MAX_KEY means always
5197
clustered index, even if it was internally
5198
generated by InnoDB */
4653
uint keynr) /*!< in: use this index; MAX_KEY means always
4654
clustered index, even if it was internally
4655
generated by InnoDB */
5200
dict_index_t* index = 0;
5202
ha_statistic_increment(&system_status_var::ha_read_key_count);
5204
if (keynr != MAX_KEY && getTable()->getShare()->sizeKeys() > 0)
5206
KeyInfo *key = getTable()->key_info + keynr;
5207
index = innobase_index_lookup(share, keynr);
5210
ut_a(ut_strcmp(index->name, key->name) == 0);
5212
/* Can't find index with keynr in the translation
5213
table. Only print message if the index translation
5215
if (share->idx_trans_tbl.index_mapping) {
5216
errmsg_printf(ERRMSG_LVL_ERROR,
5217
"InnoDB could not find "
5218
"index %s key no %u for "
5219
"table %s through its "
5220
"index translation table",
5221
key ? key->name : "NULL",
5223
prebuilt->table->name);
5226
index = dict_table_get_index_on_name(prebuilt->table,
5230
index = dict_table_get_first_index(prebuilt->table);
5234
errmsg_printf(ERRMSG_LVL_ERROR,
5235
"Innodb could not find key n:o %u with name %s "
5236
"from dict cache for table %s",
5237
keynr, getTable()->getShare()->getTableProto()->indexes(keynr).name().c_str(),
5238
prebuilt->table->name);
4658
dict_index_t* index = 0;
4660
ha_statistic_increment(&system_status_var::ha_read_key_count);
4662
ut_ad(user_session == ha_session());
4663
ut_a(prebuilt->trx == session_to_trx(user_session));
4665
if (keynr != MAX_KEY && table->s->keys > 0) {
4666
key = table->key_info + keynr;
4668
index = dict_table_get_index_on_name(prebuilt->table,
4671
index = dict_table_get_first_index(prebuilt->table);
4675
errmsg_printf(ERRMSG_LVL_ERROR,
4676
"Innodb could not find key n:o %u with name %s "
4677
"from dict cache for table %s",
4678
keynr, key ? key->name : "NULL",
4679
prebuilt->table->name);
5244
4685
/********************************************************************//**
5245
4686
Changes the active index of a handle.
5246
@return 0 or error code */
4687
@return 0 or error code */
5249
4690
ha_innobase::change_active_index(
5250
4691
/*=============================*/
5251
uint keynr) /*!< in: use this index; MAX_KEY means always clustered
5252
index, even if it was internally generated by
4692
uint keynr) /*!< in: use this index; MAX_KEY means always clustered
4693
index, even if it was internally generated by
5255
ut_ad(user_session == table->in_use);
5256
ut_a(prebuilt->trx == session_to_trx(user_session));
5258
active_index = keynr;
5260
prebuilt->index = innobase_get_index(keynr);
5262
if (UNIV_UNLIKELY(!prebuilt->index)) {
5263
errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
5265
prebuilt->index_usable = FALSE;
5269
prebuilt->index_usable = row_merge_is_index_usable(prebuilt->trx,
5272
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
5273
push_warning_printf(user_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5274
HA_ERR_TABLE_DEF_CHANGED,
5275
"InnoDB: insufficient history for index %u",
5277
/* The caller seems to ignore this. Thus, we must check
5278
this again in row_search_for_mysql(). */
5282
ut_a(prebuilt->search_tuple != 0);
5284
dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
5286
dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
5287
prebuilt->index->n_fields);
5289
/* MySQL changes the active index for a handle also during some
5290
queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
5291
and then calculates the sum. Previously we played safe and used
5292
the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
5293
copying. Starting from MySQL-4.1 we use a more efficient flag here. */
5295
build_template(prebuilt, user_session, getTable(), ROW_MYSQL_REC_FIELDS);
4696
ut_ad(user_session == ha_session());
4697
ut_a(prebuilt->trx == session_to_trx(user_session));
4699
active_index = keynr;
4701
prebuilt->index = innobase_get_index(keynr);
4703
if (UNIV_UNLIKELY(!prebuilt->index)) {
4704
errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
4709
prebuilt->index_usable = row_merge_is_index_usable(prebuilt->trx,
4712
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
4713
errmsg_printf(ERRMSG_LVL_WARN,
4714
"InnoDB: insufficient history for index %u",
4716
/* The caller seems to ignore this. Thus, we must check
4717
this again in row_search_for_mysql(). */
4721
ut_a(prebuilt->search_tuple != 0);
4723
dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
4725
dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
4726
prebuilt->index->n_fields);
4728
/* MySQL changes the active index for a handle also during some
4729
queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
4730
and then calculates the sum. Previously we played safe and used
4731
the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
4732
copying. Starting from MySQL-4.1 we use a more efficient flag here. */
4734
build_template(prebuilt, user_session, table, ROW_MYSQL_REC_FIELDS);
5300
4739
/**********************************************************************//**
5301
4740
Positions an index cursor to the index specified in keynr. Fetches the
5303
4742
??? This is only used to read whole keys ???
5304
@return error number or 0 */
4743
@return error number or 0 */
5307
4746
ha_innobase::index_read_idx(
5308
4747
/*========================*/
5309
unsigned char* buf, /*!< in/out: buffer for the returned
5311
uint keynr, /*!< in: use this index */
5312
const unsigned char* key, /*!< in: key value; if this is NULL
5313
we position the cursor at the
5314
start or end of index */
5315
uint key_len, /*!< in: key value length */
5316
enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
4748
unsigned char* buf, /*!< in/out: buffer for the returned
4750
uint keynr, /*!< in: use this index */
4751
const unsigned char* key, /*!< in: key value; if this is NULL
4752
we position the cursor at the
4753
start or end of index */
4754
uint key_len, /*!< in: key value length */
4755
enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
5318
if (change_active_index(keynr)) {
5323
return(index_read(buf, key, key_len, find_flag));
4757
if (change_active_index(keynr)) {
4762
return(index_read(buf, key, key_len, find_flag));
5326
4765
/***********************************************************************//**
5327
4766
Reads the next or previous row from a cursor, which must have previously been
5328
4767
positioned using index_read.
5329
@return 0, HA_ERR_END_OF_FILE, or error number */
4768
@return 0, HA_ERR_END_OF_FILE, or error number */
5332
4771
ha_innobase::general_fetch(
5333
4772
/*=======================*/
5334
unsigned char* buf, /*!< in/out: buffer for next row in MySQL
5336
uint direction, /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */
5337
uint match_mode) /*!< in: 0, ROW_SEL_EXACT, or
5338
ROW_SEL_EXACT_PREFIX */
4773
unsigned char* buf, /*!< in/out: buffer for next row in MySQL
4775
uint direction, /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */
4776
uint match_mode) /*!< in: 0, ROW_SEL_EXACT, or
4777
ROW_SEL_EXACT_PREFIX */
5343
ut_a(prebuilt->trx == session_to_trx(user_session));
5345
innodb_srv_conc_enter_innodb(prebuilt->trx);
5347
ret = row_search_for_mysql(
5348
(byte*)buf, 0, prebuilt, match_mode, direction);
5350
innodb_srv_conc_exit_innodb(prebuilt->trx);
5355
getTable()->status = 0;
5357
case DB_RECORD_NOT_FOUND:
5358
error = HA_ERR_END_OF_FILE;
5359
getTable()->status = STATUS_NOT_FOUND;
5361
case DB_END_OF_INDEX:
5362
error = HA_ERR_END_OF_FILE;
5363
getTable()->status = STATUS_NOT_FOUND;
5366
error = convert_error_code_to_mysql(
5367
(int) ret, prebuilt->table->flags, user_session);
5368
getTable()->status = STATUS_NOT_FOUND;
4782
ut_a(prebuilt->trx == session_to_trx(user_session));
4784
innodb_srv_conc_enter_innodb(prebuilt->trx);
4786
ret = row_search_for_mysql(
4787
(byte*)buf, 0, prebuilt, match_mode, direction);
4789
innodb_srv_conc_exit_innodb(prebuilt->trx);
4796
case DB_RECORD_NOT_FOUND:
4797
error = HA_ERR_END_OF_FILE;
4798
table->status = STATUS_NOT_FOUND;
4800
case DB_END_OF_INDEX:
4801
error = HA_ERR_END_OF_FILE;
4802
table->status = STATUS_NOT_FOUND;
4805
error = convert_error_code_to_mysql(
4806
(int) ret, prebuilt->table->flags, user_session);
4807
table->status = STATUS_NOT_FOUND;
5375
4814
/***********************************************************************//**
5376
4815
Reads the next row from a cursor, which must have previously been
5377
4816
positioned using index_read.
5378
@return 0, HA_ERR_END_OF_FILE, or error number */
4817
@return 0, HA_ERR_END_OF_FILE, or error number */
5381
4820
ha_innobase::index_next(
5382
4821
/*====================*/
5383
unsigned char* buf) /*!< in/out: buffer for next row in MySQL
4822
unsigned char* buf) /*!< in/out: buffer for next row in MySQL
5386
ha_statistic_increment(&system_status_var::ha_read_next_count);
4825
ha_statistic_increment(&system_status_var::ha_read_next_count);
5388
return(general_fetch(buf, ROW_SEL_NEXT, 0));
4827
return(general_fetch(buf, ROW_SEL_NEXT, 0));
5391
4830
/*******************************************************************//**
5392
4831
Reads the next row matching to the key value given as the parameter.
5393
@return 0, HA_ERR_END_OF_FILE, or error number */
4832
@return 0, HA_ERR_END_OF_FILE, or error number */
5396
4835
ha_innobase::index_next_same(
5397
4836
/*=========================*/
5398
unsigned char* buf, /*!< in/out: buffer for the row */
5399
const unsigned char* , /*!< in: key value */
5400
uint ) /*!< in: key value length */
4837
unsigned char* buf, /*!< in/out: buffer for the row */
4838
const unsigned char* , /*!< in: key value */
4839
uint ) /*!< in: key value length */
5402
ha_statistic_increment(&system_status_var::ha_read_next_count);
4841
ha_statistic_increment(&system_status_var::ha_read_next_count);
5404
return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
4843
return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
5407
4846
/***********************************************************************//**
5408
4847
Reads the previous row from a cursor, which must have previously been
5409
4848
positioned using index_read.
5410
@return 0, HA_ERR_END_OF_FILE, or error number */
4849
@return 0, HA_ERR_END_OF_FILE, or error number */
5413
4852
ha_innobase::index_prev(
5414
4853
/*====================*/
5415
unsigned char* buf) /*!< in/out: buffer for previous row in MySQL format */
4854
unsigned char* buf) /*!< in/out: buffer for previous row in MySQL format */
5417
ha_statistic_increment(&system_status_var::ha_read_prev_count);
4856
ha_statistic_increment(&system_status_var::ha_read_prev_count);
5419
return(general_fetch(buf, ROW_SEL_PREV, 0));
4858
return(general_fetch(buf, ROW_SEL_PREV, 0));
5422
4861
/********************************************************************//**
5423
4862
Positions a cursor on the first record in an index and reads the
5424
4863
corresponding row to buf.
5425
@return 0, HA_ERR_END_OF_FILE, or error code */
4864
@return 0, HA_ERR_END_OF_FILE, or error code */
5428
4867
ha_innobase::index_first(
5429
4868
/*=====================*/
5430
unsigned char* buf) /*!< in/out: buffer for the row */
4869
unsigned char* buf) /*!< in/out: buffer for the row */
5434
ha_statistic_increment(&system_status_var::ha_read_first_count);
5436
error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
5438
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
5440
if (error == HA_ERR_KEY_NOT_FOUND) {
5441
error = HA_ERR_END_OF_FILE;
4873
ha_statistic_increment(&system_status_var::ha_read_first_count);
4875
error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
4877
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4879
if (error == HA_ERR_KEY_NOT_FOUND) {
4880
error = HA_ERR_END_OF_FILE;
5447
4886
/********************************************************************//**
5448
4887
Positions a cursor on the last record in an index and reads the
5449
4888
corresponding row to buf.
5450
@return 0, HA_ERR_END_OF_FILE, or error code */
4889
@return 0, HA_ERR_END_OF_FILE, or error code */
5453
4892
ha_innobase::index_last(
5454
4893
/*====================*/
5455
unsigned char* buf) /*!< in/out: buffer for the row */
4894
unsigned char* buf) /*!< in/out: buffer for the row */
5459
ha_statistic_increment(&system_status_var::ha_read_last_count);
5461
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
5463
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
5465
if (error == HA_ERR_KEY_NOT_FOUND) {
5466
error = HA_ERR_END_OF_FILE;
4898
ha_statistic_increment(&system_status_var::ha_read_last_count);
4900
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
4902
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4904
if (error == HA_ERR_KEY_NOT_FOUND) {
4905
error = HA_ERR_END_OF_FILE;
5472
4911
/****************************************************************//**
5473
4912
Initialize a table scan.
5474
@return 0 or error number */
4913
@return 0 or error number */
5477
ha_innobase::doStartTableScan(
4916
ha_innobase::rnd_init(
5478
4917
/*==================*/
5479
bool scan) /*!< in: TRUE if table/index scan FALSE otherwise */
4918
bool scan) /*!< in: TRUE if table/index scan FALSE otherwise */
5483
/* Store the active index value so that we can restore the original
5484
value after a scan */
5486
if (prebuilt->clust_index_was_generated) {
5487
err = change_active_index(MAX_KEY);
5489
err = change_active_index(primary_key);
5492
/* Don't use semi-consistent read in random row reads (by position).
5493
This means we must disable semi_consistent_read if scan is false */
5496
try_semi_consistent_read(0);
4922
/* Store the active index value so that we can restore the original
4923
value after a scan */
4925
if (prebuilt->clust_index_was_generated) {
4926
err = change_active_index(MAX_KEY);
4928
err = change_active_index(primary_key);
4931
/* Don't use semi-consistent read in random row reads (by position).
4932
This means we must disable semi_consistent_read if scan is false */
4935
try_semi_consistent_read(0);
5504
4943
/*****************************************************************//**
5505
4944
Ends a table scan.
5506
@return 0 or error number */
4945
@return 0 or error number */
5509
ha_innobase::doEndTableScan(void)
4948
ha_innobase::rnd_end(void)
5510
4949
/*======================*/
5512
return(doEndIndexScan());
4951
return(index_end());
5515
4954
/*****************************************************************//**
5516
4955
Reads the next row in a table scan (also used to read the FIRST row
5517
4956
in a table scan).
5518
@return 0, HA_ERR_END_OF_FILE, or error number */
4957
@return 0, HA_ERR_END_OF_FILE, or error number */
5521
4960
ha_innobase::rnd_next(
5522
4961
/*==================*/
5523
unsigned char* buf) /*!< in/out: returns the row in this buffer,
4962
unsigned char* buf) /*!< in/out: returns the row in this buffer,
5528
ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
5530
if (start_of_scan) {
5531
error = index_first(buf);
5533
if (error == HA_ERR_KEY_NOT_FOUND) {
5534
error = HA_ERR_END_OF_FILE;
5539
error = general_fetch(buf, ROW_SEL_NEXT, 0);
4967
ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
4969
if (start_of_scan) {
4970
error = index_first(buf);
4972
if (error == HA_ERR_KEY_NOT_FOUND) {
4973
error = HA_ERR_END_OF_FILE;
4978
error = general_fetch(buf, ROW_SEL_NEXT, 0);
5545
4984
/**********************************************************************//**
5546
4985
Fetches a row from the table based on a row reference.
5547
@return 0, HA_ERR_KEY_NOT_FOUND, or error code */
4986
@return 0, HA_ERR_KEY_NOT_FOUND, or error code */
5550
4989
ha_innobase::rnd_pos(
5551
4990
/*=================*/
5552
unsigned char* buf, /*!< in/out: buffer for the row */
5553
unsigned char* pos) /*!< in: primary key value of the row in the
5554
MySQL format, or the row id if the clustered
5555
index was internally generated by InnoDB; the
5556
length of data in pos has to be ref_length */
4991
unsigned char* buf, /*!< in/out: buffer for the row */
4992
unsigned char* pos) /*!< in: primary key value of the row in the
4993
MySQL format, or the row id if the clustered
4994
index was internally generated by InnoDB; the
4995
length of data in pos has to be ref_length */
5559
uint keynr = active_index;
5561
ha_statistic_increment(&system_status_var::ha_read_rnd_count);
5563
ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
5565
if (prebuilt->clust_index_was_generated) {
5566
/* No primary key was defined for the table and we
5567
generated the clustered index from the row id: the
5568
row reference is the row id, not any key value
5569
that MySQL knows of */
5571
error = change_active_index(MAX_KEY);
5573
error = change_active_index(primary_key);
5580
/* Note that we assume the length of the row reference is fixed
5581
for the table, and it is == ref_length */
5583
error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
5588
change_active_index(keynr);
4998
uint keynr = active_index;
5000
ha_statistic_increment(&system_status_var::ha_read_rnd_count);
5002
ut_a(prebuilt->trx == session_to_trx(ha_session()));
5004
if (prebuilt->clust_index_was_generated) {
5005
/* No primary key was defined for the table and we
5006
generated the clustered index from the row id: the
5007
row reference is the row id, not any key value
5008
that MySQL knows of */
5010
error = change_active_index(MAX_KEY);
5012
error = change_active_index(primary_key);
5019
/* Note that we assume the length of the row reference is fixed
5020
for the table, and it is == ref_length */
5022
error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
5027
change_active_index(keynr);
5593
5032
/*********************************************************************//**
5639
5078
create_table_def(
5640
5079
/*=============*/
5641
trx_t* trx, /*!< in: InnoDB transaction handle */
5642
Table* form, /*!< in: information on table
5643
columns and indexes */
5644
const char* table_name, /*!< in: table name */
5645
const char* path_of_temp_table,/*!< in: if this is a table explicitly
5646
created by the user with the
5647
TEMPORARY keyword, then this
5648
parameter is the dir path where the
5649
table should be placed if we create
5650
an .ibd file for it (no .ibd extension
5651
in the path, though); otherwise this
5653
ulint flags) /*!< in: table flags */
5080
trx_t* trx, /*!< in: InnoDB transaction handle */
5081
Table* form, /*!< in: information on table
5082
columns and indexes */
5083
const char* table_name, /*!< in: table name */
5084
const char* path_of_temp_table,/*!< in: if this is a table explicitly
5085
created by the user with the
5086
TEMPORARY keyword, then this
5087
parameter is the dir path where the
5088
table should be placed if we create
5089
an .ibd file for it (no .ibd extension
5090
in the path, though); otherwise this
5092
ulint flags) /*!< in: table flags */
5656
dict_table_t* table;
5661
ulint nulls_allowed;
5662
ulint unsigned_type;
5664
ulint long_true_varchar;
5668
n_cols = form->getShare()->sizeFields();
5670
/* We pass 0 as the space id, and determine at a lower level the space
5671
id where to store the table */
5673
table = dict_mem_table_create(table_name, 0, n_cols, flags);
5675
if (path_of_temp_table) {
5676
table->dir_path_of_temp_table =
5677
mem_heap_strdup(table->heap, path_of_temp_table);
5680
for (i = 0; i < n_cols; i++) {
5681
field = form->getField(i);
5683
col_type = get_innobase_type_from_mysql_type(&unsigned_type,
5685
if (field->null_ptr) {
5688
nulls_allowed = DATA_NOT_NULL;
5691
if (field->binary()) {
5692
binary_type = DATA_BINARY_TYPE;
5699
if (dtype_is_string_type(col_type)) {
5701
charset_no = (ulint)field->charset()->number;
5703
if (UNIV_UNLIKELY(charset_no >= 256)) {
5704
/* in data0type.h we assume that the
5705
number fits in one byte in prtype */
5706
push_warning_printf(
5707
(Session*) trx->mysql_thd,
5708
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5709
ER_CANT_CREATE_TABLE,
5710
"In InnoDB, charset-collation codes"
5711
" must be below 256."
5712
" Unsupported code %lu.",
5713
(ulong) charset_no);
5714
return(ER_CANT_CREATE_TABLE);
5718
ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
5719
that this fits in one byte */
5720
col_len = field->pack_length();
5722
/* The MySQL pack length contains 1 or 2 bytes length field
5723
for a true VARCHAR. Let us subtract that, so that the InnoDB
5724
column length in the InnoDB data dictionary is the real
5725
maximum byte length of the actual data. */
5727
long_true_varchar = 0;
5729
if (field->type() == DRIZZLE_TYPE_VARCHAR) {
5730
col_len -= ((Field_varstring*)field)->pack_length_no_ptr();
5732
if (((Field_varstring*)field)->pack_length_no_ptr() == 2) {
5733
long_true_varchar = DATA_LONG_TRUE_VARCHAR;
5737
/* First check whether the column to be added has a
5738
system reserved name. */
5739
if (dict_col_name_is_reserved(field->field_name)){
5740
my_error(ER_WRONG_COLUMN_NAME, MYF(0), field->field_name);
5742
dict_mem_table_free(table);
5743
trx_commit_for_mysql(trx);
5749
dict_mem_table_add_col(table, table->heap,
5750
(char*) field->field_name,
5753
(ulint)field->type()
5754
| nulls_allowed | unsigned_type
5755
| binary_type | long_true_varchar,
5760
error = row_create_table_for_mysql(table, trx);
5762
if (error == DB_DUPLICATE_KEY) {
5764
char* buf_end = innobase_convert_identifier(
5765
buf, sizeof buf - 1, table_name, strlen(table_name),
5766
trx->mysql_thd, TRUE);
5769
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), buf);
5773
error = convert_error_code_to_mysql(error, flags, NULL);
5095
dict_table_t* table;
5100
ulint nulls_allowed;
5101
ulint unsigned_type;
5103
ulint long_true_varchar;
5107
n_cols = form->s->fields;
5109
/* We pass 0 as the space id, and determine at a lower level the space
5110
id where to store the table */
5112
table = dict_mem_table_create(table_name, 0, n_cols, flags);
5114
if (path_of_temp_table) {
5115
table->dir_path_of_temp_table =
5116
mem_heap_strdup(table->heap, path_of_temp_table);
5119
for (i = 0; i < n_cols; i++) {
5120
field = form->field[i];
5122
col_type = get_innobase_type_from_mysql_type(&unsigned_type,
5124
if (field->null_ptr) {
5127
nulls_allowed = DATA_NOT_NULL;
5130
if (field->binary()) {
5131
binary_type = DATA_BINARY_TYPE;
5138
if (dtype_is_string_type(col_type)) {
5140
charset_no = (ulint)field->charset()->number;
5142
if (UNIV_UNLIKELY(charset_no >= 256)) {
5143
/* in data0type.h we assume that the
5144
number fits in one byte in prtype */
5145
push_warning_printf(
5146
(Session*) trx->mysql_thd,
5147
DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5148
ER_CANT_CREATE_TABLE,
5149
"In InnoDB, charset-collation codes"
5150
" must be below 256."
5151
" Unsupported code %lu.",
5152
(ulong) charset_no);
5153
return(ER_CANT_CREATE_TABLE);
5157
ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
5158
that this fits in one byte */
5159
col_len = field->pack_length();
5161
/* The MySQL pack length contains 1 or 2 bytes length field
5162
for a true VARCHAR. Let us subtract that, so that the InnoDB
5163
column length in the InnoDB data dictionary is the real
5164
maximum byte length of the actual data. */
5166
long_true_varchar = 0;
5168
if (field->type() == DRIZZLE_TYPE_VARCHAR) {
5169
col_len -= ((Field_varstring*)field)->length_bytes;
5171
if (((Field_varstring*)field)->length_bytes == 2) {
5172
long_true_varchar = DATA_LONG_TRUE_VARCHAR;
5176
dict_mem_table_add_col(table, table->heap,
5177
(char*) field->field_name,
5180
(ulint)field->type()
5181
| nulls_allowed | unsigned_type
5182
| binary_type | long_true_varchar,
5187
error = row_create_table_for_mysql(table, trx);
5189
error = convert_error_code_to_mysql(error, flags, NULL);
5778
5194
/*****************************************************************//**
5784
trx_t* trx, /*!< in: InnoDB transaction handle */
5785
Table* form, /*!< in: information on table
5786
columns and indexes */
5787
ulint flags, /*!< in: InnoDB table flags */
5788
const char* table_name, /*!< in: table name */
5789
uint key_num) /*!< in: index number */
5200
trx_t* trx, /*!< in: InnoDB transaction handle */
5201
Table* form, /*!< in: information on table
5202
columns and indexes */
5203
ulint flags, /*!< in: InnoDB table flags */
5204
const char* table_name, /*!< in: table name */
5205
uint key_num) /*!< in: index number */
5792
dict_index_t* index;
5796
KeyPartInfo* key_part;
5803
ulint* field_lengths;
5805
key = &form->key_info[key_num];
5807
n_fields = key->key_parts;
5809
/* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */
5810
ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0);
5814
if (key_num == form->getShare()->getPrimaryKey()) {
5815
ind_type = ind_type | DICT_CLUSTERED;
5818
if (key->flags & HA_NOSAME ) {
5819
ind_type = ind_type | DICT_UNIQUE;
5822
/* We pass 0 as the space id, and determine at a lower level the space
5823
id where to store the table */
5825
index = dict_mem_index_create(table_name, key->name, 0,
5826
ind_type, n_fields);
5828
field_lengths = (ulint*) malloc(sizeof(ulint) * n_fields);
5830
for (i = 0; i < n_fields; i++) {
5831
key_part = key->key_part + i;
5833
/* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
5834
field in an index: we only store a specified number of first
5835
bytes of the column to the index field.) The flag does not
5836
seem to be properly set by MySQL. Let us fall back on testing
5837
the length of the key part versus the column. */
5840
for (j = 0; j < form->getShare()->sizeFields(); j++)
5843
field = form->getField(j);
5845
if (0 == innobase_strcasecmp(
5847
key_part->field->field_name)) {
5848
/* Found the corresponding column */
5854
ut_a(j < form->getShare()->sizeFields());
5856
col_type = get_innobase_type_from_mysql_type(
5857
&is_unsigned, key_part->field);
5859
if (DATA_BLOB == col_type
5860
|| (key_part->length < field->pack_length()
5861
&& field->type() != DRIZZLE_TYPE_VARCHAR)
5862
|| (field->type() == DRIZZLE_TYPE_VARCHAR
5863
&& key_part->length < field->pack_length()
5864
- ((Field_varstring*)field)->pack_length_no_ptr())) {
5866
prefix_len = key_part->length;
5868
if (col_type == DATA_INT
5869
|| col_type == DATA_FLOAT
5870
|| col_type == DATA_DOUBLE
5871
|| col_type == DATA_DECIMAL) {
5872
errmsg_printf(ERRMSG_LVL_ERROR,
5873
"MySQL is trying to create a column "
5874
"prefix index field, on an "
5875
"inappropriate data type. Table "
5876
"name %s, column name %s.",
5878
key_part->field->field_name);
5886
field_lengths[i] = key_part->length;
5888
dict_mem_index_add_field(index,
5889
(char*) key_part->field->field_name, prefix_len);
5892
/* Even though we've defined max_supported_key_part_length, we
5893
still do our own checking using field_lengths to be absolutely
5894
sure we don't create too long indexes. */
5895
error = row_create_index_for_mysql(index, trx, field_lengths);
5897
error = convert_error_code_to_mysql(error, flags, NULL);
5899
free(field_lengths);
5208
dict_index_t* index;
5212
KEY_PART_INFO* key_part;
5219
ulint* field_lengths;
5221
key = form->key_info + key_num;
5223
n_fields = key->key_parts;
5227
if (key_num == form->s->primary_key) {
5228
ind_type = ind_type | DICT_CLUSTERED;
5231
if (key->flags & HA_NOSAME ) {
5232
ind_type = ind_type | DICT_UNIQUE;
5235
/* We pass 0 as the space id, and determine at a lower level the space
5236
id where to store the table */
5238
index = dict_mem_index_create(table_name, key->name, 0,
5239
ind_type, n_fields);
5241
field_lengths = (ulint*) malloc(sizeof(ulint) * n_fields);
5243
for (i = 0; i < n_fields; i++) {
5244
key_part = key->key_part + i;
5246
/* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
5247
field in an index: we only store a specified number of first
5248
bytes of the column to the index field.) The flag does not
5249
seem to be properly set by MySQL. Let us fall back on testing
5250
the length of the key part versus the column. */
5253
for (j = 0; j < form->s->fields; j++) {
5255
field = form->field[j];
5257
if (0 == innobase_strcasecmp(
5259
key_part->field->field_name)) {
5260
/* Found the corresponding column */
5266
ut_a(j < form->s->fields);
5268
col_type = get_innobase_type_from_mysql_type(
5269
&is_unsigned, key_part->field);
5271
if (DATA_BLOB == col_type
5272
|| (key_part->length < field->pack_length()
5273
&& field->type() != DRIZZLE_TYPE_VARCHAR)
5274
|| (field->type() == DRIZZLE_TYPE_VARCHAR
5275
&& key_part->length < field->pack_length()
5276
- ((Field_varstring*)field)->length_bytes)) {
5278
prefix_len = key_part->length;
5280
if (col_type == DATA_INT
5281
|| col_type == DATA_FLOAT
5282
|| col_type == DATA_DOUBLE
5283
|| col_type == DATA_DECIMAL) {
5284
errmsg_printf(ERRMSG_LVL_ERROR,
5285
"MySQL is trying to create a column "
5286
"prefix index field, on an "
5287
"inappropriate data type. Table "
5288
"name %s, column name %s.",
5290
key_part->field->field_name);
5298
field_lengths[i] = key_part->length;
5300
dict_mem_index_add_field(index,
5301
(char*) key_part->field->field_name, prefix_len);
5304
/* Even though we've defined max_supported_key_part_length, we
5305
still do our own checking using field_lengths to be absolutely
5306
sure we don't create too long indexes. */
5307
error = row_create_index_for_mysql(index, trx, field_lengths);
5309
error = convert_error_code_to_mysql(error, flags, NULL);
5311
free(field_lengths);
5904
5316
/*****************************************************************//**
5968
5509
InnobaseEngine::doCreateTable(
5969
5510
/*================*/
5970
Session &session, /*!< in: Session */
5971
Table& form, /*!< in: information on table columns and indexes */
5972
const TableIdentifier &identifier,
5511
Session* session, /*!< in: Session */
5512
const char* table_name, /*!< in: table name */
5513
Table& form, /*!< in: information on table
5514
columns and indexes */
5973
5515
message::Table& create_proto)
5976
dict_table_t* innobase_table;
5981
char name2[FN_REFLEN];
5982
char norm_name[FN_REFLEN];
5983
ib_int64_t auto_inc_value;
5985
/* Cache the value of innodb_file_format, in case it is
5986
modified by another thread while the table is being created. */
5987
const ulint file_format = srv_file_format;
5988
bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
5992
const char *table_name= identifier.getPath().c_str();
5994
if (form.getShare()->sizeFields() > 1000) {
5995
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
5996
but we play safe here */
5998
return(HA_ERR_TO_BIG_ROW);
6001
/* Get the transaction associated with the current session, or create one
6002
if not yet created */
6004
parent_trx = check_trx_exists(&session);
6006
/* In case MySQL calls this in the middle of a SELECT query, release
6007
possible adaptive hash latch to avoid deadlocks of threads */
6009
trx_search_latch_release_if_reserved(parent_trx);
6011
trx = innobase_trx_allocate(&session);
6013
srv_lower_case_table_names = TRUE;
6015
strcpy(name2, table_name);
6017
normalize_table_name(norm_name, name2);
6019
/* Latch the InnoDB data dictionary exclusively so that no deadlocks
6020
or lock waits can happen in it during a table create operation.
6021
Drop table etc. do this latching in row0mysql.c. */
6023
row_mysql_lock_data_dictionary(trx);
6025
/* Create the table definition in InnoDB */
6029
#if 0 // Since we validate the options before this stage, we no longer need to do this.
6030
/* Validate create options if innodb_strict_mode is set. */
6031
if (! create_options_are_valid(&session, form, create_proto)) {
6032
error = ER_ILLEGAL_HA_CREATE_OPTION;
5518
dict_table_t* innobase_table;
5523
char name2[FN_REFLEN];
5524
char norm_name[FN_REFLEN];
5525
ib_int64_t auto_inc_value;
5527
/* Cache the value of innodb_file_format, in case it is
5528
modified by another thread while the table is being created. */
5529
const ulint file_format = srv_file_format;
5530
bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
5532
assert(session != NULL);
5535
/* Names passed in from server are in two formats:
5536
1. <database_name>/<table_name>: for normal table creation
5537
2. full path: for temp table creation, or sym link
5539
When srv_file_per_table is on, check for full path pattern, i.e.
5540
X:\dir\..., X is a driver letter, or
5541
\\dir1\dir2\..., UNC path
5542
returns error if it is in full path format, but not creating a temp.
5543
table. Currently InnoDB does not support symbolic link on Windows. */
5545
if (srv_file_per_table
5546
&& (! lex_identified_temp_table)) {
5548
if ((table_name[1] == ':')
5549
|| (table_name[0] == '\\' && table_name[1] == '\\')) {
5550
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot create table %s\n", table_name);
5551
return(HA_ERR_GENERIC);
6037
// We assume compact format by default
6038
iflags= DICT_TF_COMPACT;
6040
size_t num_engine_options= create_proto.engine().options_size();
6041
for (size_t x= 0; x < num_engine_options; ++x)
6043
if (boost::iequals(create_proto.engine().options(x).name(), "ROW_FORMAT"))
6045
if (boost::iequals(create_proto.engine().options(x).state(), "COMPRESSED"))
6047
iflags= DICT_TF_FORMAT_ZIP;
6049
else if (boost::iequals(create_proto.engine().options(x).state(), "COMPACT"))
6051
iflags= DICT_TF_FORMAT_ZIP;
6053
else if (boost::iequals(create_proto.engine().options(x).state(), "DYNAMIC"))
6055
iflags= DICT_TF_COMPACT;
6057
else if (boost::iequals(create_proto.engine().options(x).state(), "REDUNDANT"))
6059
iflags= DICT_TF_COMPACT;
6064
assert(0); // This should never happen since we have already validated the options.
6068
if (iflags == DICT_TF_FORMAT_ZIP)
6071
ROW_FORMAT=COMPRESSED without KEY_BLOCK_SIZE implies half the maximum KEY_BLOCK_SIZE.
6072
@todo implement KEY_BLOCK_SIZE
6074
iflags= (DICT_TF_ZSSIZE_MAX - 1)
6075
<< DICT_TF_ZSSIZE_SHIFT
6077
| DICT_TF_FORMAT_ZIP
6078
<< DICT_TF_FORMAT_SHIFT;
5556
if (form.s->fields > 1000) {
5557
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
5558
but we play safe here */
5560
return(HA_ERR_TO_BIG_ROW);
5563
/* Get the transaction associated with the current session, or create one
5564
if not yet created */
5566
parent_trx = check_trx_exists(session);
5568
/* In case MySQL calls this in the middle of a SELECT query, release
5569
possible adaptive hash latch to avoid deadlocks of threads */
5571
trx_search_latch_release_if_reserved(parent_trx);
5573
trx = innobase_trx_allocate(session);
5575
srv_lower_case_table_names = TRUE;
5577
strcpy(name2, table_name);
5579
normalize_table_name(norm_name, name2);
5581
/* Latch the InnoDB data dictionary exclusively so that no deadlocks
5582
or lock waits can happen in it during a table create operation.
5583
Drop table etc. do this latching in row0mysql.c. */
5585
row_mysql_lock_data_dictionary(trx);
5587
/* Create the table definition in InnoDB */
5591
/* Validate create options if innodb_strict_mode is set. */
5592
if (! create_options_are_valid(session, form, create_proto)) {
5593
error = ER_ILLEGAL_HA_CREATE_OPTION;
5597
if (create_proto.options().has_key_block_size()) {
5598
/* Determine the page_zip.ssize corresponding to the
5599
requested page size (key_block_size) in kilobytes. */
5602
ulint key_block_size = create_proto.options().key_block_size();
5604
for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX;
5605
ssize++, ksize <<= 1) {
5606
if (key_block_size == ksize) {
5607
iflags = ssize << DICT_TF_ZSSIZE_SHIFT
5609
| DICT_TF_FORMAT_ZIP
5610
<< DICT_TF_FORMAT_SHIFT;
5615
if (!srv_file_per_table) {
5616
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5617
ER_ILLEGAL_HA_CREATE_OPTION,
5618
"InnoDB: KEY_BLOCK_SIZE"
5619
" requires innodb_file_per_table.");
5623
if (file_format < DICT_TF_FORMAT_ZIP) {
5624
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5625
ER_ILLEGAL_HA_CREATE_OPTION,
5626
"InnoDB: KEY_BLOCK_SIZE"
5627
" requires innodb_file_format >"
5633
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5634
ER_ILLEGAL_HA_CREATE_OPTION,
5636
" KEY_BLOCK_SIZE=%lu.",
5637
create_proto.options().key_block_size());
5641
if (create_proto.options().has_row_type()) {
5643
/* KEY_BLOCK_SIZE was specified. */
5644
if (form.s->row_type != ROW_TYPE_COMPRESSED) {
5645
/* ROW_FORMAT other than COMPRESSED
5646
ignores KEY_BLOCK_SIZE. It does not
5647
make sense to reject conflicting
5648
KEY_BLOCK_SIZE and ROW_FORMAT, because
5649
such combinations can be obtained
5650
with ALTER TABLE anyway. */
5651
push_warning_printf(
5653
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5654
ER_ILLEGAL_HA_CREATE_OPTION,
5655
"InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
5656
" unless ROW_FORMAT=COMPRESSED.",
5657
create_proto.options().key_block_size());
5661
/* No KEY_BLOCK_SIZE */
5662
if (form.s->row_type == ROW_TYPE_COMPRESSED) {
5663
/* ROW_FORMAT=COMPRESSED without
5664
KEY_BLOCK_SIZE implies half the
5665
maximum KEY_BLOCK_SIZE. */
5666
iflags = (DICT_TF_ZSSIZE_MAX - 1)
5667
<< DICT_TF_ZSSIZE_SHIFT
5669
| DICT_TF_FORMAT_ZIP
5670
<< DICT_TF_FORMAT_SHIFT;
6079
5671
#if DICT_TF_ZSSIZE_MAX < 1
6080
5672
# error "DICT_TF_ZSSIZE_MAX < 1"
6083
if (SessionVAR(&session, strict_mode))
6085
if (! srv_file_per_table)
6087
push_warning_printf(
6089
DRIZZLE_ERROR::WARN_LEVEL_WARN,
6090
ER_ILLEGAL_HA_CREATE_OPTION,
6091
"InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.");
6093
else if (file_format < DICT_TF_FORMAT_ZIP)
6095
push_warning_printf(
6097
DRIZZLE_ERROR::WARN_LEVEL_WARN,
6098
ER_ILLEGAL_HA_CREATE_OPTION,
6099
"InnoDB: ROW_FORMAT=compressed requires innodb_file_format > Antelope.");
6104
/* Look for a primary key */
6106
primary_key_no= (form.getShare()->hasPrimaryKey() ?
6107
(int) form.getShare()->getPrimaryKey() :
6110
/* Our function innobase_get_mysql_key_number_for_index assumes
6111
the primary key is always number 0, if it exists */
6113
assert(primary_key_no == -1 || primary_key_no == 0);
6115
/* Check for name conflicts (with reserved name) for
6116
any user indices to be created. */
6117
if (innobase_index_name_is_reserved(trx, form.key_info,
6118
form.getShare()->keys)) {
6123
if (lex_identified_temp_table)
6124
iflags |= DICT_TF2_TEMPORARY << DICT_TF2_SHIFT;
6126
error= create_table_def(trx, &form, norm_name,
6127
lex_identified_temp_table ? name2 : NULL,
6130
session.setXaId((ib_uint64_t) ut_conv_dulint_to_longlong(trx->id));
6136
/* Create the keys */
6138
if (form.getShare()->sizeKeys() == 0 || primary_key_no == -1) {
6139
/* Create an index which is used as the clustered index;
6140
order the rows by their row id which is internally generated
6143
error = create_clustered_index_when_no_primary(trx, iflags, norm_name);
6149
if (primary_key_no != -1) {
6150
/* In InnoDB the clustered index must always be created first */
6151
if ((error = create_index(trx, &form, iflags, norm_name,
6152
(uint) primary_key_no))) {
6157
for (i = 0; i < form.getShare()->sizeKeys(); i++) {
6158
if (i != (uint) primary_key_no) {
6160
if ((error = create_index(trx, &form, iflags, norm_name,
6167
stmt = innobase_get_stmt(&session, &stmt_len);
6170
string generated_create_table;
6171
const char *query= stmt;
6173
if (session_sql_command(&session) == SQLCOM_CREATE_TABLE)
6175
message::transformTableDefinitionToSql(create_proto,
6176
generated_create_table,
6177
message::DRIZZLE, true);
6178
query= generated_create_table.c_str();
6181
error = row_table_add_foreign_constraints(trx,
6182
query, strlen(query),
6184
lex_identified_temp_table);
6186
error = convert_error_code_to_mysql(error, iflags, NULL);
6193
innobase_commit_low(trx);
6195
row_mysql_unlock_data_dictionary(trx);
6197
/* Flush the log to reduce probability that the .frm files and
6198
the InnoDB data dictionary get out-of-sync if the user runs
6199
with innodb_flush_log_at_trx_commit = 0 */
6201
log_buffer_flush_to_disk();
6203
innobase_table = dict_table_get(norm_name, FALSE);
6205
assert(innobase_table != 0);
6207
if (innobase_table) {
6208
/* We update the highest file format in the system table
6209
space, if this table has higher file format setting. */
6211
trx_sys_file_format_max_upgrade((const char**) &innobase_file_format_check,
6212
dict_table_get_format(innobase_table));
6215
/* Note: We can't call update_session() as prebuilt will not be
6216
setup at this stage and so we use session. */
6218
/* We need to copy the AUTOINC value from the old table if
6219
this is an ALTER TABLE or CREATE INDEX because CREATE INDEX
6220
does a table copy too. */
6222
if ((create_proto.options().has_auto_increment_value()
6223
|| session_sql_command(&session) == SQLCOM_ALTER_TABLE
6224
|| session_sql_command(&session) == SQLCOM_CREATE_INDEX)
6225
&& create_proto.options().auto_increment_value() != 0) {
6227
/* Query was one of :
6228
CREATE TABLE ...AUTO_INCREMENT = x; or
6229
ALTER TABLE...AUTO_INCREMENT = x; or
6230
CREATE INDEX x on t(...);
6231
Find out a table definition from the dictionary and get
6232
the current value of the auto increment field. Set a new
6233
value to the auto increment field if the value is greater
6234
than the maximum value in the column. */
6236
auto_inc_value = create_proto.options().auto_increment_value();
6238
dict_table_autoinc_lock(innobase_table);
6239
dict_table_autoinc_initialize(innobase_table, auto_inc_value);
6240
dict_table_autoinc_unlock(innobase_table);
6243
/* Tell the InnoDB server that there might be work for
6246
srv_active_wake_master_thread();
6248
trx_free_for_mysql(trx);
6250
if (lex_identified_temp_table)
6252
session.getMessageCache().storeTableMessage(identifier, create_proto);
6256
StorageEngine::writeDefinitionFromPath(identifier, create_proto);
5677
switch (form.s->row_type) {
5678
const char* row_format_name;
5679
case ROW_TYPE_REDUNDANT:
5681
case ROW_TYPE_COMPRESSED:
5682
case ROW_TYPE_DYNAMIC:
5684
= form.s->row_type == ROW_TYPE_COMPRESSED
5688
if (!srv_file_per_table) {
5689
push_warning_printf(
5691
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5692
ER_ILLEGAL_HA_CREATE_OPTION,
5693
"InnoDB: ROW_FORMAT=%s"
5694
" requires innodb_file_per_table.",
5696
} else if (file_format < DICT_TF_FORMAT_ZIP) {
5697
push_warning_printf(
5699
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5700
ER_ILLEGAL_HA_CREATE_OPTION,
5701
"InnoDB: ROW_FORMAT=%s"
5702
" requires innodb_file_format >"
5706
iflags |= DICT_TF_COMPACT
5707
| (DICT_TF_FORMAT_ZIP
5708
<< DICT_TF_FORMAT_SHIFT);
5713
case ROW_TYPE_NOT_USED:
5714
case ROW_TYPE_FIXED:
5716
error = ER_ILLEGAL_HA_CREATE_OPTION;
5718
case ROW_TYPE_DEFAULT:
5719
case ROW_TYPE_COMPACT:
5720
iflags = DICT_TF_COMPACT;
5723
} else if (!iflags) {
5724
/* No KEY_BLOCK_SIZE or ROW_FORMAT specified:
5725
use ROW_FORMAT=COMPACT by default. */
5726
iflags = DICT_TF_COMPACT;
5729
error = create_table_def(trx, &form, norm_name,
5730
lex_identified_temp_table ? name2 : NULL,
5737
/* Look for a primary key */
5739
primary_key_no= (form.s->primary_key != MAX_KEY ?
5740
(int) form.s->primary_key :
5743
/* Our function row_get_mysql_key_number_for_index assumes
5744
the primary key is always number 0, if it exists */
5746
assert(primary_key_no == -1 || primary_key_no == 0);
5748
/* Create the keys */
5750
if (form.s->keys == 0 || primary_key_no == -1) {
5751
/* Create an index which is used as the clustered index;
5752
order the rows by their row id which is internally generated
5755
error = create_clustered_index_when_no_primary(
5756
trx, iflags, norm_name);
5762
if (primary_key_no != -1) {
5763
/* In InnoDB the clustered index must always be created
5765
if ((error = create_index(trx, &form, iflags, norm_name,
5766
(uint) primary_key_no))) {
5771
for (i = 0; i < form.s->keys; i++) {
5773
if (i != (uint) primary_key_no) {
5775
if ((error = create_index(trx, &form, iflags, norm_name,
5782
if (trx->mysql_query_str) {
5783
error = row_table_add_foreign_constraints(trx,
5784
trx->mysql_query_str, norm_name,
5785
lex_identified_temp_table);
5787
error = convert_error_code_to_mysql(error, iflags, NULL);
5794
innobase_commit_low(trx);
5796
row_mysql_unlock_data_dictionary(trx);
5798
/* Flush the log to reduce probability that the .frm files and
5799
the InnoDB data dictionary get out-of-sync if the user runs
5800
with innodb_flush_log_at_trx_commit = 0 */
5802
log_buffer_flush_to_disk();
5804
innobase_table = dict_table_get(norm_name, FALSE);
5806
assert(innobase_table != 0);
5808
if (innobase_table) {
5809
/* We update the highest file format in the system table
5810
space, if this table has higher file format setting. */
5812
trx_sys_file_format_max_upgrade(
5813
(const char**) &innobase_file_format_check,
5814
dict_table_get_format(innobase_table));
5817
/* Note: We can't call update_session() as prebuilt will not be
5818
setup at this stage and so we use session. */
5820
/* We need to copy the AUTOINC value from the old table if
5821
this is an ALTER TABLE. */
5823
if ((create_proto.options().has_auto_increment_value()
5824
|| session_sql_command(session) == SQLCOM_ALTER_TABLE)
5825
&& create_proto.options().auto_increment_value() != 0) {
5827
/* Query was ALTER TABLE...AUTO_INCREMENT = x; or
5828
CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
5829
definition from the dictionary and get the current value
5830
of the auto increment field. Set a new value to the
5831
auto increment field if the value is greater than the
5832
maximum value in the column. */
5834
auto_inc_value = create_proto.options().auto_increment_value();
5836
dict_table_autoinc_lock(innobase_table);
5837
dict_table_autoinc_initialize(innobase_table, auto_inc_value);
5838
dict_table_autoinc_unlock(innobase_table);
5841
/* Tell the InnoDB server that there might be work for
5844
srv_active_wake_master_thread();
5846
trx_free_for_mysql(trx);
6262
innobase_commit_low(trx);
6264
row_mysql_unlock_data_dictionary(trx);
6266
trx_free_for_mysql(trx);
5851
innobase_commit_low(trx);
5853
row_mysql_unlock_data_dictionary(trx);
5855
trx_free_for_mysql(trx);
6271
5860
/*****************************************************************//**
6272
5861
Discards or imports an InnoDB tablespace.
6273
@return 0 == success, -1 == error */
5862
@return 0 == success, -1 == error */
6276
5865
ha_innobase::discard_or_import_tablespace(
6277
5866
/*======================================*/
6278
my_bool discard) /*!< in: TRUE if discard, else import */
5867
my_bool discard) /*!< in: TRUE if discard, else import */
6280
dict_table_t* dict_table;
6284
ut_a(prebuilt->trx);
6285
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6286
ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
6288
dict_table = prebuilt->table;
6289
trx = prebuilt->trx;
6292
err = row_discard_tablespace_for_mysql(dict_table->name, trx);
6294
err = row_import_tablespace_for_mysql(dict_table->name, trx);
6297
err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
5869
dict_table_t* dict_table;
5873
ut_a(prebuilt->trx);
5874
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
5875
ut_a(prebuilt->trx == session_to_trx(ha_session()));
5877
dict_table = prebuilt->table;
5878
trx = prebuilt->trx;
5881
err = row_discard_tablespace_for_mysql(dict_table->name, trx);
5883
err = row_import_tablespace_for_mysql(dict_table->name, trx);
5886
err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
6302
5891
/*****************************************************************//**
6303
5892
Deletes all rows of an InnoDB table.
6304
@return error number */
5893
@return error number */
6307
5896
ha_innobase::delete_all_rows(void)
6308
5897
/*==============================*/
6312
/* Get the transaction associated with the current session, or create one
6313
if not yet created, and update prebuilt->trx */
6315
update_session(getTable()->in_use);
6317
if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
6319
/* We only handle TRUNCATE TABLE t as a special case.
6320
DELETE FROM t will have to use ha_innobase::doDeleteRecord(),
6321
because DELETE is transactional while TRUNCATE is not. */
6322
return(errno=HA_ERR_WRONG_COMMAND);
6325
/* Truncate the table in InnoDB */
6327
error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
6328
if (error == DB_ERROR) {
6329
/* Cannot truncate; resort to ha_innobase::doDeleteRecord() */
6333
error = convert_error_code_to_mysql(error, prebuilt->table->flags,
5901
/* Get the transaction associated with the current session, or create one
5902
if not yet created, and update prebuilt->trx */
5904
update_session(ha_session());
5906
if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
5908
/* We only handle TRUNCATE TABLE t as a special case.
5909
DELETE FROM t will have to use ha_innobase::delete_row(),
5910
because DELETE is transactional while TRUNCATE is not. */
5911
return(errno=HA_ERR_WRONG_COMMAND);
5914
/* Truncate the table in InnoDB */
5916
error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
5917
if (error == DB_ERROR) {
5918
/* Cannot truncate; resort to ha_innobase::delete_row() */
5922
error = convert_error_code_to_mysql(error, prebuilt->table->flags,
6339
5928
/*****************************************************************//**
6440
5997
InnobaseEngine::doDropSchema(
6441
5998
/*===================*/
6442
const SchemaIdentifier &identifier)
6443
/*!< in: database path; inside InnoDB the name
6444
of the last directory in the path is used as
6445
the database name: for example, in 'mysql/data/test'
6446
the database name is 'test' */
6450
string schema_path(identifier.getPath());
6451
Session* session = current_session;
6453
/* Get the transaction associated with the current session, or create one
6454
if not yet created */
6456
assert(this == innodb_engine_ptr);
6458
/* In the Windows plugin, session = current_session is always NULL */
6460
trx_t* parent_trx = check_trx_exists(session);
6462
/* In case Drizzle calls this in the middle of a SELECT
6463
query, release possible adaptive hash latch to avoid
6464
deadlocks of threads */
6466
trx_search_latch_release_if_reserved(parent_trx);
6469
schema_path.append("/");
6470
trx = innobase_trx_allocate(session);
6471
error = row_drop_database_for_mysql(schema_path.c_str(), trx);
6473
/* Flush the log to reduce probability that the .frm files and
6474
the InnoDB data dictionary get out-of-sync if the user runs
6475
with innodb_flush_log_at_trx_commit = 0 */
6477
log_buffer_flush_to_disk();
6479
/* Tell the InnoDB server that there might be work for
6482
srv_active_wake_master_thread();
6484
innobase_commit_low(trx);
6485
trx_free_for_mysql(trx);
6487
return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement.
6490
void InnobaseEngine::dropTemporarySchema()
6492
SchemaIdentifier schema_identifier(GLOBAL_TEMPORARY_EXT);
6494
string schema_path(GLOBAL_TEMPORARY_EXT);
6496
schema_path.append("/");
6498
trx = trx_allocate_for_mysql();
6500
trx->mysql_thd = NULL;
6502
trx->check_foreigns = false;
6503
trx->check_unique_secondary = false;
6505
(void)row_drop_database_for_mysql(schema_path.c_str(), trx);
6507
/* Flush the log to reduce probability that the .frm files and
6508
the InnoDB data dictionary get out-of-sync if the user runs
6509
with innodb_flush_log_at_trx_commit = 0 */
6511
log_buffer_flush_to_disk();
6513
/* Tell the InnoDB server that there might be work for
6516
srv_active_wake_master_thread();
6518
innobase_commit_low(trx);
6519
trx_free_for_mysql(trx);
5999
const std::string &schema_name)
6000
/*!< in: database path; inside InnoDB the name
6001
of the last directory in the path is used as
6002
the database name: for example, in 'mysql/data/test'
6003
the database name is 'test' */
6007
string schema_path(schema_name);
6008
Session* session = current_session;
6010
/* Get the transaction associated with the current session, or create one
6011
if not yet created */
6013
assert(this == innodb_engine_ptr);
6015
/* In the Windows plugin, session = current_session is always NULL */
6017
trx_t* parent_trx = check_trx_exists(session);
6019
/* In case Drizzle calls this in the middle of a SELECT
6020
query, release possible adaptive hash latch to avoid
6021
deadlocks of threads */
6023
trx_search_latch_release_if_reserved(parent_trx);
6026
schema_path.append("/");
6027
trx = innobase_trx_allocate(session);
6028
error = row_drop_database_for_mysql(schema_path.c_str(), trx);
6030
/* Flush the log to reduce probability that the .frm files and
6031
the InnoDB data dictionary get out-of-sync if the user runs
6032
with innodb_flush_log_at_trx_commit = 0 */
6034
log_buffer_flush_to_disk();
6036
/* Tell the InnoDB server that there might be work for
6039
srv_active_wake_master_thread();
6041
innobase_commit_low(trx);
6042
trx_free_for_mysql(trx);
6044
return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement.
6521
6046
/*********************************************************************//**
6522
6047
Renames an InnoDB table.
6523
@return 0 or error code */
6048
@return 0 or error code */
6526
6051
innobase_rename_table(
6527
6052
/*==================*/
6528
trx_t* trx, /*!< in: transaction */
6529
const char* from, /*!< in: old name of the table */
6530
const char* to, /*!< in: new name of the table */
6531
ibool lock_and_commit)
6532
/*!< in: TRUE=lock data dictionary and commit */
6053
trx_t* trx, /*!< in: transaction */
6054
const char* from, /*!< in: old name of the table */
6055
const char* to, /*!< in: new name of the table */
6056
ibool lock_and_commit)
6057
/*!< in: TRUE=lock data dictionary and commit */
6535
char norm_to[FN_REFLEN];
6536
char norm_from[FN_REFLEN];
6538
srv_lower_case_table_names = TRUE;
6540
normalize_table_name(norm_to, to);
6541
normalize_table_name(norm_from, from);
6543
/* Serialize data dictionary operations with dictionary mutex:
6544
no deadlocks can occur then in these operations */
6546
if (lock_and_commit) {
6547
row_mysql_lock_data_dictionary(trx);
6550
error = row_rename_table_for_mysql(
6551
norm_from, norm_to, trx, lock_and_commit);
6553
if (error != DB_SUCCESS) {
6554
FILE* ef = dict_foreign_err_file;
6556
fputs("InnoDB: Renaming table ", ef);
6557
ut_print_name(ef, trx, TRUE, norm_from);
6559
ut_print_name(ef, trx, TRUE, norm_to);
6560
fputs(" failed!\n", ef);
6563
if (lock_and_commit) {
6564
row_mysql_unlock_data_dictionary(trx);
6566
/* Flush the log to reduce probability that the .frm
6567
files and the InnoDB data dictionary get out-of-sync
6568
if the user runs with innodb_flush_log_at_trx_commit = 0 */
6570
log_buffer_flush_to_disk();
6063
srv_lower_case_table_names = TRUE;
6065
// Magic number 64 arbitrary
6066
norm_to = (char*) malloc(strlen(to) + 64);
6067
norm_from = (char*) malloc(strlen(from) + 64);
6069
normalize_table_name(norm_to, to);
6070
normalize_table_name(norm_from, from);
6072
/* Serialize data dictionary operations with dictionary mutex:
6073
no deadlocks can occur then in these operations */
6075
if (lock_and_commit) {
6076
row_mysql_lock_data_dictionary(trx);
6079
error = row_rename_table_for_mysql(
6080
norm_from, norm_to, trx, lock_and_commit);
6082
if (error != DB_SUCCESS) {
6083
FILE* ef = dict_foreign_err_file;
6085
fputs("InnoDB: Renaming table ", ef);
6086
ut_print_name(ef, trx, TRUE, norm_from);
6088
ut_print_name(ef, trx, TRUE, norm_to);
6089
fputs(" failed!\n", ef);
6092
if (lock_and_commit) {
6093
row_mysql_unlock_data_dictionary(trx);
6095
/* Flush the log to reduce probability that the .frm
6096
files and the InnoDB data dictionary get out-of-sync
6097
if the user runs with innodb_flush_log_at_trx_commit = 0 */
6099
log_buffer_flush_to_disk();
6575
6107
/*********************************************************************//**
6576
6108
Renames an InnoDB table.
6577
@return 0 or error code */
6578
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
6109
@return 0 or error code */
6112
InnobaseEngine::doRenameTable(
6113
/*======================*/
6115
const char* from, /*!< in: old name of the table */
6116
const char* to) /*!< in: new name of the table */
6580
// A temp table alter table/rename is a shallow rename and only the
6581
// definition needs to be updated.
6582
if (to.getType() == message::Table::TEMPORARY && from.getType() == message::Table::TEMPORARY)
6584
session.getMessageCache().renameTableMessage(from, to);
6592
/* Get the transaction associated with the current session, or create one
6593
if not yet created */
6595
parent_trx = check_trx_exists(&session);
6597
/* In case MySQL calls this in the middle of a SELECT query, release
6598
possible adaptive hash latch to avoid deadlocks of threads */
6600
trx_search_latch_release_if_reserved(parent_trx);
6602
trx = innobase_trx_allocate(&session);
6604
error = innobase_rename_table(trx, from.getPath().c_str(), to.getPath().c_str(), TRUE);
6606
session.setXaId((ib_uint64_t) ut_conv_dulint_to_longlong(trx->id));
6608
/* Tell the InnoDB server that there might be work for
6611
srv_active_wake_master_thread();
6613
innobase_commit_low(trx);
6614
trx_free_for_mysql(trx);
6616
/* Add a special case to handle the Duplicated Key error
6617
and return DB_ERROR instead.
6618
This is to avoid a possible SIGSEGV error from mysql error
6619
handling code. Currently, mysql handles the Duplicated Key
6620
error by re-entering the storage layer and getting dup key
6621
info by calling get_dup_key(). This operation requires a valid
6622
table handle ('row_prebuilt_t' structure) which could no
6623
longer be available in the error handling stage. The suggested
6624
solution is to report a 'table exists' error message (since
6625
the dup key error here is due to an existing table whose name
6626
is the one we are trying to rename to) and return the generic
6628
if (error == (int) DB_DUPLICATE_KEY) {
6629
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to.getPath().c_str());
6633
error = convert_error_code_to_mysql(error, 0, NULL);
6637
// If this fails, we are in trouble
6638
plugin::StorageEngine::renameDefinitionFromPath(to, from);
6122
/* Get the transaction associated with the current session, or create one
6123
if not yet created */
6125
parent_trx = check_trx_exists(session);
6127
/* In case MySQL calls this in the middle of a SELECT query, release
6128
possible adaptive hash latch to avoid deadlocks of threads */
6130
trx_search_latch_release_if_reserved(parent_trx);
6132
trx = innobase_trx_allocate(session);
6134
error = innobase_rename_table(trx, from, to, TRUE);
6136
/* Tell the InnoDB server that there might be work for
6139
srv_active_wake_master_thread();
6141
innobase_commit_low(trx);
6142
trx_free_for_mysql(trx);
6144
error = convert_error_code_to_mysql(error, 0, NULL);
6644
6149
/*********************************************************************//**
6645
6150
Estimates the number of index records in a range.
6646
@return estimated number of rows */
6151
@return estimated number of rows */
6649
6154
ha_innobase::records_in_range(
6650
6155
/*==========================*/
6651
uint keynr, /*!< in: index number */
6652
key_range *min_key, /*!< in: start key value of the
6653
range, may also be 0 */
6654
key_range *max_key) /*!< in: range end key val, may
6156
uint keynr, /*!< in: index number */
6157
key_range *min_key, /*!< in: start key value of the
6158
range, may also be 0 */
6159
key_range *max_key) /*!< in: range end key val, may
6658
dict_index_t* index;
6659
unsigned char* key_val_buff2 = (unsigned char*) malloc(
6660
getTable()->getShare()->stored_rec_length
6661
+ getTable()->getShare()->max_key_length + 100);
6662
ulint buff2_len = getTable()->getShare()->stored_rec_length
6663
+ getTable()->getShare()->max_key_length + 100;
6664
dtuple_t* range_start;
6665
dtuple_t* range_end;
6671
ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
6673
prebuilt->trx->op_info = (char*)"estimating records in index range";
6675
/* In case MySQL calls this in the middle of a SELECT query, release
6676
possible adaptive hash latch to avoid deadlocks of threads */
6678
trx_search_latch_release_if_reserved(prebuilt->trx);
6680
active_index = keynr;
6682
key = &getTable()->key_info[active_index];
6684
index = innobase_get_index(keynr);
6686
/* There exists possibility of not being able to find requested
6687
index due to inconsistency between MySQL and InoDB dictionary info.
6688
Necessary message should have been printed in innobase_get_index() */
6689
if (UNIV_UNLIKELY(!index)) {
6690
n_rows = HA_POS_ERROR;
6694
heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6695
+ sizeof(dtuple_t)));
6697
range_start = dtuple_create(heap, key->key_parts);
6698
dict_index_copy_types(range_start, index, key->key_parts);
6700
range_end = dtuple_create(heap, key->key_parts);
6701
dict_index_copy_types(range_end, index, key->key_parts);
6703
row_sel_convert_mysql_key_to_innobase(
6704
range_start, (byte*) &key_val_buff[0],
6705
(ulint)upd_and_key_val_buff_len,
6707
(byte*) (min_key ? min_key->key :
6708
(const unsigned char*) 0),
6709
(ulint) (min_key ? min_key->length : 0),
6712
row_sel_convert_mysql_key_to_innobase(
6713
range_end, (byte*) key_val_buff2,
6715
(byte*) (max_key ? max_key->key :
6716
(const unsigned char*) 0),
6717
(ulint) (max_key ? max_key->length : 0),
6720
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
6722
mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
6725
if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
6727
n_rows = btr_estimate_n_rows_in_range(index, range_start,
6732
n_rows = HA_POS_ERROR;
6735
mem_heap_free(heap);
6738
free(key_val_buff2);
6740
prebuilt->trx->op_info = (char*)"";
6742
/* The MySQL optimizer seems to believe an estimate of 0 rows is
6743
always accurate and may return the result 'Empty set' based on that.
6744
The accuracy is not guaranteed, and even if it were, for a locking
6745
read we should anyway perform the search to set the next-key lock.
6746
Add 1 to the value to make sure MySQL does not make the assumption! */
6752
return((ha_rows) n_rows);
6163
dict_index_t* index;
6164
unsigned char* key_val_buff2 = (unsigned char*) malloc(
6165
table->s->stored_rec_length
6166
+ table->s->max_key_length + 100);
6167
ulint buff2_len = table->s->stored_rec_length
6168
+ table->s->max_key_length + 100;
6169
dtuple_t* range_start;
6170
dtuple_t* range_end;
6176
ut_a(prebuilt->trx == session_to_trx(ha_session()));
6178
prebuilt->trx->op_info = (char*)"estimating records in index range";
6180
/* In case MySQL calls this in the middle of a SELECT query, release
6181
possible adaptive hash latch to avoid deadlocks of threads */
6183
trx_search_latch_release_if_reserved(prebuilt->trx);
6185
active_index = keynr;
6187
key = table->key_info + active_index;
6189
index = dict_table_get_index_on_name(prebuilt->table, key->name);
6191
/* MySQL knows about this index and so we must be able to find it.*/
6194
heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6195
+ sizeof(dtuple_t)));
6197
range_start = dtuple_create(heap, key->key_parts);
6198
dict_index_copy_types(range_start, index, key->key_parts);
6200
range_end = dtuple_create(heap, key->key_parts);
6201
dict_index_copy_types(range_end, index, key->key_parts);
6203
row_sel_convert_mysql_key_to_innobase(
6204
range_start, (byte*) key_val_buff,
6205
(ulint)upd_and_key_val_buff_len,
6207
(byte*) (min_key ? min_key->key :
6208
(const unsigned char*) 0),
6209
(ulint) (min_key ? min_key->length : 0),
6212
row_sel_convert_mysql_key_to_innobase(
6213
range_end, (byte*) key_val_buff2,
6215
(byte*) (max_key ? max_key->key :
6216
(const unsigned char*) 0),
6217
(ulint) (max_key ? max_key->length : 0),
6220
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
6222
mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
6225
if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
6227
n_rows = btr_estimate_n_rows_in_range(index, range_start,
6232
n_rows = HA_POS_ERROR;
6235
mem_heap_free(heap);
6237
free(key_val_buff2);
6239
prebuilt->trx->op_info = (char*)"";
6241
/* The MySQL optimizer seems to believe an estimate of 0 rows is
6242
always accurate and may return the result 'Empty set' based on that.
6243
The accuracy is not guaranteed, and even if it were, for a locking
6244
read we should anyway perform the search to set the next-key lock.
6245
Add 1 to the value to make sure MySQL does not make the assumption! */
6251
return((ha_rows) n_rows);
6755
6254
/*********************************************************************//**
6756
6255
Gives an UPPER BOUND to the number of rows in a table. This is used in
6758
@return upper bound of rows */
6257
@return upper bound of rows */
6761
6260
ha_innobase::estimate_rows_upper_bound(void)
6762
6261
/*======================================*/
6764
dict_index_t* index;
6766
uint64_t local_data_file_length;
6768
/* We do not know if MySQL can call this function before calling
6769
external_lock(). To be safe, update the session of the current table
6772
update_session(getTable()->in_use);
6774
prebuilt->trx->op_info = (char*)
6775
"calculating upper bound for table rows";
6777
/* In case MySQL calls this in the middle of a SELECT query, release
6778
possible adaptive hash latch to avoid deadlocks of threads */
6780
trx_search_latch_release_if_reserved(prebuilt->trx);
6782
index = dict_table_get_first_index(prebuilt->table);
6784
ut_a(index->stat_n_leaf_pages > 0);
6786
local_data_file_length =
6787
((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6790
/* Calculate a minimum length for a clustered index record and from
6791
that an upper bound for the number of rows. Since we only calculate
6792
new statistics in row0mysql.c when a table has grown by a threshold
6793
factor, we must add a safety factor 2 in front of the formula below. */
6795
estimate = 2 * local_data_file_length /
6796
dict_index_calc_min_rec_len(index);
6798
prebuilt->trx->op_info = (char*)"";
6800
return((ha_rows) estimate);
6263
dict_index_t* index;
6265
uint64_t local_data_file_length;
6267
/* We do not know if MySQL can call this function before calling
6268
external_lock(). To be safe, update the session of the current table
6271
update_session(ha_session());
6273
prebuilt->trx->op_info = (char*)
6274
"calculating upper bound for table rows";
6276
/* In case MySQL calls this in the middle of a SELECT query, release
6277
possible adaptive hash latch to avoid deadlocks of threads */
6279
trx_search_latch_release_if_reserved(prebuilt->trx);
6281
index = dict_table_get_first_index(prebuilt->table);
6283
ut_a(index->stat_n_leaf_pages > 0);
6285
local_data_file_length =
6286
((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6289
/* Calculate a minimum length for a clustered index record and from
6290
that an upper bound for the number of rows. Since we only calculate
6291
new statistics in row0mysql.c when a table has grown by a threshold
6292
factor, we must add a safety factor 2 in front of the formula below. */
6294
estimate = 2 * local_data_file_length /
6295
dict_index_calc_min_rec_len(index);
6297
prebuilt->trx->op_info = (char*)"";
6299
return((ha_rows) estimate);
6803
6302
/*********************************************************************//**
6804
6303
How many seeks it will take to read through the table. This is to be
6805
6304
comparable to the number returned by records_in_range so that we can
6806
6305
decide if we should scan the table or use keys.
6807
@return estimated time measured in disk seeks */
6306
@return estimated time measured in disk seeks */
6810
6309
ha_innobase::scan_time()
6811
6310
/*====================*/
6813
/* Since MySQL seems to favor table scans too much over index
6814
searches, we pretend that a sequential read takes the same time
6815
as a random disk read, that is, we do not divide the following
6816
by 10, which would be physically realistic. */
6312
/* Since MySQL seems to favor table scans too much over index
6313
searches, we pretend that a sequential read takes the same time
6314
as a random disk read, that is, we do not divide the following
6315
by 10, which would be physically realistic. */
6818
return((double) (prebuilt->table->stat_clustered_index_size));
6317
return((double) (prebuilt->table->stat_clustered_index_size));
6821
6320
/******************************************************************//**
6822
6321
Calculate the time it takes to read a set of ranges through an index
6823
6322
This enables us to optimise reads for clustered indexes.
6824
@return estimated time measured in disk seeks */
6323
@return estimated time measured in disk seeks */
6827
6326
ha_innobase::read_time(
6828
6327
/*===================*/
6829
uint index, /*!< in: key number */
6830
uint ranges, /*!< in: how many ranges */
6831
ha_rows rows) /*!< in: estimated number of rows in the ranges */
6834
double time_for_scan;
6836
if (index != getTable()->getShare()->getPrimaryKey()) {
6838
return(Cursor::read_time(index, ranges, rows));
6843
return((double) rows);
6846
/* Assume that the read time is proportional to the scan time for all
6847
rows + at most one seek per range. */
6849
time_for_scan = scan_time();
6851
if ((total_rows = estimate_rows_upper_bound()) < rows) {
6853
return(time_for_scan);
6856
return(ranges + (double) rows / (double) total_rows * time_for_scan);
6859
/*********************************************************************//**
6860
Calculates the key number used inside MySQL for an Innobase index. We will
6861
first check the "index translation table" for a match of the index to get
6862
the index number. If there does not exist an "index translation table",
6863
or not able to find the index in the translation table, then we will fall back
6864
to the traditional way of looping through dict_index_t list to find a
6865
match. In this case, we have to take into account if we generated a
6866
default clustered index for the table
6867
@return the key number used inside MySQL */
6870
innobase_get_mysql_key_number_for_index(
6871
/*====================================*/
6872
INNOBASE_SHARE* share, /*!< in: share structure for index
6873
translation table. */
6874
const drizzled::Table* table, /*!< in: table in MySQL data
6876
dict_table_t* ib_table,/*!< in: table in Innodb data
6878
const dict_index_t* index) /*!< in: index */
6880
const dict_index_t* ind;
6888
/* If index does not belong to the table of share structure. Search
6889
index->table instead */
6890
if (index->table != ib_table
6891
&& strcmp(index->table->name, share->table_name)) {
6893
ind = dict_table_get_first_index(index->table);
6895
while (index != ind) {
6896
ind = dict_table_get_next_index(ind);
6900
if (row_table_got_default_clust_index(index->table)) {
6908
/* If index translation table exists, we will first check
6909
the index through index translation table for a match. */
6910
if (share->idx_trans_tbl.index_mapping) {
6911
for (i = 0; i < share->idx_trans_tbl.index_count; i++) {
6912
if (share->idx_trans_tbl.index_mapping[i] == index) {
6917
/* Print an error message if we cannot find the index
6918
** in the "index translation table". */
6919
errmsg_printf(ERRMSG_LVL_ERROR,
6920
"Cannot find index %s in InnoDB index "
6921
"translation table.", index->name);
6924
/* If we do not have an "index translation table", or not able
6925
to find the index in the translation table, we'll directly find
6926
matching index in the dict_index_t list */
6927
for (i = 0; i < table->getShare()->keys; i++) {
6928
ind = dict_table_get_index_on_name(
6929
ib_table, table->key_info[i].name);
6936
errmsg_printf(ERRMSG_LVL_ERROR,
6937
"Cannot find matching index number for index %s "
6938
"in InnoDB index list.", index->name);
6328
uint index, /*!< in: key number */
6329
uint ranges, /*!< in: how many ranges */
6330
ha_rows rows) /*!< in: estimated number of rows in the ranges */
6333
double time_for_scan;
6335
if (index != table->s->primary_key) {
6337
return(Cursor::read_time(index, ranges, rows));
6342
return((double) rows);
6345
/* Assume that the read time is proportional to the scan time for all
6346
rows + at most one seek per range. */
6348
time_for_scan = scan_time();
6350
if ((total_rows = estimate_rows_upper_bound()) < rows) {
6352
return(time_for_scan);
6355
return(ranges + (double) rows / (double) total_rows * time_for_scan);
6942
6358
/*********************************************************************//**
6943
6359
Returns statistics information of the table to the MySQL interpreter,
6944
6360
in various fields of the handle object. */
6947
6363
ha_innobase::info(
6948
6364
/*==============*/
6949
uint flag) /*!< in: what information MySQL requests */
6365
uint flag) /*!< in: what information MySQL requests */
6951
dict_table_t* ib_table;
6952
dict_index_t* index;
6953
ha_rows rec_per_key;
6957
os_file_stat_t stat_info;
6959
/* If we are forcing recovery at a high level, we will suppress
6960
statistics calculation on tables, because that may crash the
6961
server if an index is badly corrupted. */
6963
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
6965
/* We return success (0) instead of HA_ERR_CRASHED,
6966
because we want MySQL to process this query and not
6967
stop, like it would do if it received the error code
6973
/* We do not know if MySQL can call this function before calling
6974
external_lock(). To be safe, update the session of the current table
6977
update_session(getTable()->in_use);
6979
/* In case MySQL calls this in the middle of a SELECT query, release
6980
possible adaptive hash latch to avoid deadlocks of threads */
6982
prebuilt->trx->op_info = (char*)"returning various info to MySQL";
6984
trx_search_latch_release_if_reserved(prebuilt->trx);
6986
ib_table = prebuilt->table;
6988
if (flag & HA_STATUS_TIME) {
6989
/* In Analyze we call with this flag: update
6990
then statistics so that they are up-to-date */
6992
prebuilt->trx->op_info = "updating table statistics";
6994
dict_update_statistics(ib_table);
6996
prebuilt->trx->op_info = "returning various info to MySQL";
6998
fs::path get_status_path(getDataHomeCatalog());
6999
get_status_path /= ib_table->name;
7000
fs::change_extension(get_status_path, "dfe");
7002
/* Note that we do not know the access time of the table,
7003
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
7005
if (os_file_get_status(get_status_path.file_string().c_str(), &stat_info)) {
7006
stats.create_time = (ulong) stat_info.ctime;
7010
if (flag & HA_STATUS_VARIABLE) {
7011
n_rows = ib_table->stat_n_rows;
7013
/* Because we do not protect stat_n_rows by any mutex in a
7014
delete, it is theoretically possible that the value can be
7015
smaller than zero! TODO: fix this race.
7017
The MySQL optimizer seems to assume in a left join that n_rows
7018
is an accurate estimate if it is zero. Of course, it is not,
7019
since we do not have any locks on the rows yet at this phase.
7020
Since SHOW TABLE STATUS seems to call this function with the
7021
HA_STATUS_TIME flag set, while the left join optimizer does not
7022
set that flag, we add one to a zero value if the flag is not
7023
set. That way SHOW TABLE STATUS will show the best estimate,
7024
while the optimizer never sees the table empty. */
7030
if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
7034
/* Fix bug#40386: Not flushing query cache after truncate.
7035
n_rows can not be 0 unless the table is empty, set to 1
7036
instead. The original problem of bug#29507 is actually
7037
fixed in the server code. */
7038
if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
7042
/* We need to reset the prebuilt value too, otherwise
7043
checks for values greater than the last value written
7044
to the table will fail and the autoinc counter will
7045
not be updated. This will force doInsertRecord() into
7046
attempting an update of the table's AUTOINC counter. */
7048
prebuilt->autoinc_last_value = 0;
7051
stats.records = (ha_rows)n_rows;
7053
stats.data_file_length = ((uint64_t)
7054
ib_table->stat_clustered_index_size)
7056
stats.index_file_length = ((uint64_t)
7057
ib_table->stat_sum_of_other_index_sizes)
7060
/* Since fsp_get_available_space_in_free_extents() is
7061
acquiring latches inside InnoDB, we do not call it if we
7062
are asked by MySQL to avoid locking. Another reason to
7063
avoid the call is that it uses quite a lot of CPU.
7065
We do not update delete_length if no locking is requested
7066
so the "old" value can remain. delete_length is initialized
7067
to 0 in the ha_statistics' constructor. */
7068
if (!(flag & HA_STATUS_NO_LOCK)) {
7070
/* lock the data dictionary to avoid races with
7071
ibd_file_missing and tablespace_discarded */
7072
row_mysql_lock_data_dictionary(prebuilt->trx);
7074
/* ib_table->space must be an existent tablespace */
7075
if (!ib_table->ibd_file_missing
7076
&& !ib_table->tablespace_discarded) {
7078
stats.delete_length =
7079
fsp_get_available_space_in_free_extents(
7080
ib_table->space) * 1024;
7085
session= getTable()->in_use;
7088
push_warning_printf(
7090
DRIZZLE_ERROR::WARN_LEVEL_WARN,
7092
"InnoDB: Trying to get the free "
7093
"space for table %s but its "
7094
"tablespace has been discarded or "
7095
"the .ibd file is missing. Setting "
7096
"the free space to zero.",
7099
stats.delete_length = 0;
7102
row_mysql_unlock_data_dictionary(prebuilt->trx);
7105
stats.check_time = 0;
7107
if (stats.records == 0) {
7108
stats.mean_rec_length = 0;
7110
stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
7114
if (flag & HA_STATUS_CONST) {
7115
/* Verify the number of index in InnoDB and MySQL
7116
matches up. If prebuilt->clust_index_was_generated
7117
holds, InnoDB defines GEN_CLUST_INDEX internally */
7118
ulint num_innodb_index = UT_LIST_GET_LEN(ib_table->indexes) - prebuilt->clust_index_was_generated;
7120
if (getTable()->getShare()->keys != num_innodb_index) {
7121
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains %lu "
7122
"indexes inside InnoDB, which "
7123
"is different from the number of "
7124
"indexes %u defined in the MySQL ",
7125
ib_table->name, num_innodb_index,
7126
getTable()->getShare()->keys);
7129
for (i = 0; i < getTable()->getShare()->sizeKeys(); i++) {
7130
/* We could get index quickly through internal
7131
index mapping with the index translation table.
7132
The identity of index (match up index name with
7133
that of table->key_info[i]) is already verified in
7134
innobase_get_index(). */
7135
index = innobase_get_index(i);
7137
if (index == NULL) {
7138
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
7139
"indexes inside InnoDB than "
7140
"are defined in the MySQL "
7141
".frm file. Have you mixed up "
7142
".frm files from different "
7143
"installations? See "
7145
"innodb-troubleshooting.html\n",
7150
for (j = 0; j < getTable()->key_info[i].key_parts; j++) {
7152
if (j + 1 > index->n_uniq) {
7153
errmsg_printf(ERRMSG_LVL_ERROR,
6367
dict_table_t* ib_table;
6368
dict_index_t* index;
6369
ha_rows rec_per_key;
6373
char path[FN_REFLEN];
6374
os_file_stat_t stat_info;
6376
/* If we are forcing recovery at a high level, we will suppress
6377
statistics calculation on tables, because that may crash the
6378
server if an index is badly corrupted. */
6380
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
6382
/* We return success (0) instead of HA_ERR_CRASHED,
6383
because we want MySQL to process this query and not
6384
stop, like it would do if it received the error code
6390
/* We do not know if MySQL can call this function before calling
6391
external_lock(). To be safe, update the session of the current table
6394
update_session(ha_session());
6396
/* In case MySQL calls this in the middle of a SELECT query, release
6397
possible adaptive hash latch to avoid deadlocks of threads */
6399
prebuilt->trx->op_info = (char*)"returning various info to MySQL";
6401
trx_search_latch_release_if_reserved(prebuilt->trx);
6403
ib_table = prebuilt->table;
6405
if (flag & HA_STATUS_TIME) {
6406
if (innobase_stats_on_metadata) {
6407
/* In sql_show we call with this flag: update
6408
then statistics so that they are up-to-date */
6410
prebuilt->trx->op_info = "updating table statistics";
6412
dict_update_statistics(ib_table);
6414
prebuilt->trx->op_info = "returning various info to MySQL";
6417
snprintf(path, sizeof(path), "%s/%s%s",
6418
drizzle_data_home, ib_table->name, ".dfe");
6420
internal::unpack_filename(path,path);
6422
/* Note that we do not know the access time of the table,
6423
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
6425
if (os_file_get_status(path,&stat_info)) {
6426
stats.create_time = (ulong) stat_info.ctime;
6430
if (flag & HA_STATUS_VARIABLE) {
6431
n_rows = ib_table->stat_n_rows;
6433
/* Because we do not protect stat_n_rows by any mutex in a
6434
delete, it is theoretically possible that the value can be
6435
smaller than zero! TODO: fix this race.
6437
The MySQL optimizer seems to assume in a left join that n_rows
6438
is an accurate estimate if it is zero. Of course, it is not,
6439
since we do not have any locks on the rows yet at this phase.
6440
Since SHOW TABLE STATUS seems to call this function with the
6441
HA_STATUS_TIME flag set, while the left join optimizer does not
6442
set that flag, we add one to a zero value if the flag is not
6443
set. That way SHOW TABLE STATUS will show the best estimate,
6444
while the optimizer never sees the table empty. */
6450
if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
6454
/* Fix bug#40386: Not flushing query cache after truncate.
6455
n_rows can not be 0 unless the table is empty, set to 1
6456
instead. The original problem of bug#29507 is actually
6457
fixed in the server code. */
6458
if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
6462
/* We need to reset the prebuilt value too, otherwise
6463
checks for values greater than the last value written
6464
to the table will fail and the autoinc counter will
6465
not be updated. This will force write_row() into
6466
attempting an update of the table's AUTOINC counter. */
6468
prebuilt->autoinc_last_value = 0;
6471
stats.records = (ha_rows)n_rows;
6473
stats.data_file_length = ((uint64_t)
6474
ib_table->stat_clustered_index_size)
6476
stats.index_file_length = ((uint64_t)
6477
ib_table->stat_sum_of_other_index_sizes)
6480
/* Since fsp_get_available_space_in_free_extents() is
6481
acquiring latches inside InnoDB, we do not call it if we
6482
are asked by MySQL to avoid locking. Another reason to
6483
avoid the call is that it uses quite a lot of CPU.
6485
We do not update delete_length if no locking is requested
6486
so the "old" value can remain. delete_length is initialized
6487
to 0 in the ha_statistics' constructor. */
6488
if (!(flag & HA_STATUS_NO_LOCK)) {
6490
/* lock the data dictionary to avoid races with
6491
ibd_file_missing and tablespace_discarded */
6492
row_mysql_lock_data_dictionary(prebuilt->trx);
6494
/* ib_table->space must be an existent tablespace */
6495
if (!ib_table->ibd_file_missing
6496
&& !ib_table->tablespace_discarded) {
6498
stats.delete_length =
6499
fsp_get_available_space_in_free_extents(
6500
ib_table->space) * 1024;
6505
session = ha_session();
6507
push_warning_printf(
6509
DRIZZLE_ERROR::WARN_LEVEL_WARN,
6511
"InnoDB: Trying to get the free "
6512
"space for table %s but its "
6513
"tablespace has been discarded or "
6514
"the .ibd file is missing. Setting "
6515
"the free space to zero.",
6518
stats.delete_length = 0;
6521
row_mysql_unlock_data_dictionary(prebuilt->trx);
6524
stats.check_time = 0;
6526
if (stats.records == 0) {
6527
stats.mean_rec_length = 0;
6529
stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
6533
if (flag & HA_STATUS_CONST) {
6534
index = dict_table_get_first_index(ib_table);
6536
if (prebuilt->clust_index_was_generated) {
6537
index = dict_table_get_next_index(index);
6540
for (i = 0; i < table->s->keys; i++) {
6541
if (index == NULL) {
6542
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
6543
"indexes inside InnoDB than "
6544
"are defined in the MySQL "
6545
".frm file. Have you mixed up "
6546
".frm files from different "
6547
"installations? See "
6549
"innodb-troubleshooting.html\n",
6554
for (j = 0; j < table->key_info[i].key_parts; j++) {
6556
if (j + 1 > index->n_uniq) {
6557
errmsg_printf(ERRMSG_LVL_ERROR,
7154
6558
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
7155
6559
"statistics for %lu columns. Have you mixed up .frm files from different "
7156
6560
"installations? "
7157
6561
"See " REFMAN "innodb-troubleshooting.html\n",
7161
index->n_uniq, j + 1);
7165
dict_index_stat_mutex_enter(index);
7167
if (index->stat_n_diff_key_vals[j + 1] == 0) {
7169
rec_per_key = stats.records;
7171
rec_per_key = (ha_rows)(stats.records /
7172
index->stat_n_diff_key_vals[j + 1]);
7175
dict_index_stat_mutex_exit(index);
7177
/* Since MySQL seems to favor table scans
7178
too much over index searches, we pretend
7179
index selectivity is 2 times better than
7182
rec_per_key = rec_per_key / 2;
7184
if (rec_per_key == 0) {
7188
getTable()->key_info[i].rec_per_key[j]=
7189
rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
7190
(ulong) rec_per_key;
7195
if (flag & HA_STATUS_ERRKEY) {
7196
const dict_index_t* err_index;
7198
ut_a(prebuilt->trx);
7199
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
7201
err_index = trx_get_error_info(prebuilt->trx);
7204
errkey = (unsigned int)
7205
innobase_get_mysql_key_number_for_index(share, getTable(), ib_table,
7208
errkey = (unsigned int) prebuilt->trx->error_key_num;
7212
if ((flag & HA_STATUS_AUTO) && getTable()->found_next_number_field) {
7213
stats.auto_increment_value = innobase_peek_autoinc();
7216
prebuilt->trx->op_info = (char*)"";
6565
index->n_uniq, j + 1);
6569
if (index->stat_n_diff_key_vals[j + 1] == 0) {
6571
rec_per_key = stats.records;
6573
rec_per_key = (ha_rows)(stats.records /
6574
index->stat_n_diff_key_vals[j + 1]);
6577
/* Since MySQL seems to favor table scans
6578
too much over index searches, we pretend
6579
index selectivity is 2 times better than
6582
rec_per_key = rec_per_key / 2;
6584
if (rec_per_key == 0) {
6588
table->key_info[i].rec_per_key[j]=
6589
rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
6590
(ulong) rec_per_key;
6593
index = dict_table_get_next_index(index);
6597
if (flag & HA_STATUS_ERRKEY) {
6598
const dict_index_t* err_index;
6600
ut_a(prebuilt->trx);
6601
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6603
err_index = trx_get_error_info(prebuilt->trx);
6606
errkey = (unsigned int)
6607
row_get_mysql_key_number_for_index(err_index);
6609
errkey = (unsigned int) prebuilt->trx->error_key_num;
6613
if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
6614
stats.auto_increment_value = innobase_peek_autoinc();
6617
prebuilt->trx->op_info = (char*)"";
7221
6622
/**********************************************************************//**
7222
6623
Updates index cardinalities of the table, based on 8 random dives into
7223
6624
each index tree. This does NOT calculate exact statistics on the table.
7224
@return returns always 0 (success) */
6625
@return returns always 0 (success) */
7227
6628
ha_innobase::analyze(
7228
6629
/*=================*/
7229
Session*) /*!< in: connection thread handle */
6630
Session*) /*!< in: connection thread handle */
7231
/* Simply call ::info() with all the flags */
7232
info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
6632
/* Simply call ::info() with all the flags */
6633
info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
7237
6638
/*******************************************************************//**
7238
6639
Tries to check that an InnoDB table is not corrupted. If corruption is
7239
6640
noticed, prints to stderr information about it. In case of corruption
7240
6641
may also assert a failure and crash the server.
7241
@return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
6642
@return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
7244
6645
ha_innobase::check(
7245
6646
/*===============*/
7246
Session* session) /*!< in: user thread handle */
6647
Session* session) /*!< in: user thread handle */
7248
dict_index_t* index;
7250
ulint n_rows_in_table = ULINT_UNDEFINED;
7252
ulint old_isolation_level;
7254
assert(session == getTable()->in_use);
7255
ut_a(prebuilt->trx);
7256
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
7257
ut_a(prebuilt->trx == session_to_trx(session));
7259
if (prebuilt->mysql_template == NULL) {
7260
/* Build the template; we will use a dummy template
7261
in index scans done in checking */
7263
build_template(prebuilt, NULL, getTable(), ROW_MYSQL_WHOLE_ROW);
7266
if (prebuilt->table->ibd_file_missing) {
7267
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: Error:\n"
7268
"InnoDB: MySQL is trying to use a table handle"
7269
" but the .ibd file for\n"
7270
"InnoDB: table %s does not exist.\n"
7271
"InnoDB: Have you deleted the .ibd file"
7272
" from the database directory under\n"
7273
"InnoDB: the MySQL datadir, or have you"
7274
" used DISCARD TABLESPACE?\n"
7275
"InnoDB: Please refer to\n"
7276
"InnoDB: " REFMAN "innodb-troubleshooting.html\n"
7277
"InnoDB: how you can resolve the problem.\n",
7278
prebuilt->table->name);
7279
return(HA_ADMIN_CORRUPT);
7282
prebuilt->trx->op_info = "checking table";
7284
old_isolation_level = prebuilt->trx->isolation_level;
7286
/* We must run the index record counts at an isolation level
7287
>= READ COMMITTED, because a dirty read can see a wrong number
7288
of records in some index; to play safe, we use always
7289
REPEATABLE READ here */
7291
prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
7293
/* Enlarge the fatal lock wait timeout during CHECK TABLE. */
7294
mutex_enter(&kernel_mutex);
7295
srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
7296
mutex_exit(&kernel_mutex);
7298
for (index = dict_table_get_first_index(prebuilt->table);
7300
index = dict_table_get_next_index(index)) {
7302
fputs("Validating index ", stderr);
7303
ut_print_name(stderr, trx, FALSE, index->name);
7307
if (!btr_validate_index(index, prebuilt->trx)) {
7309
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7311
"InnoDB: The B-tree of"
7312
" index '%-.200s' is corrupted.",
7317
/* Instead of invoking change_active_index(), set up
7318
a dummy template for non-locking reads, disabling
7319
access to the clustered index. */
7320
prebuilt->index = index;
7322
prebuilt->index_usable = row_merge_is_index_usable(
7323
prebuilt->trx, prebuilt->index);
7325
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
7326
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7327
HA_ERR_TABLE_DEF_CHANGED,
7328
"InnoDB: Insufficient history for"
7334
prebuilt->sql_stat_start = TRUE;
7335
prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
7336
prebuilt->n_template = 0;
7337
prebuilt->need_to_access_clustered = FALSE;
7339
dtuple_set_n_fields(prebuilt->search_tuple, 0);
7341
prebuilt->select_lock_type = LOCK_NONE;
7343
if (!row_check_index_for_mysql(prebuilt, index, &n_rows)) {
7344
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7346
"InnoDB: The B-tree of"
7347
" index '%-.200s' is corrupted.",
7352
if (user_session->getKilled()) {
7357
fprintf(stderr, "%lu entries in index %s\n", n_rows,
7361
if (index == dict_table_get_first_index(prebuilt->table)) {
7362
n_rows_in_table = n_rows;
7363
} else if (n_rows != n_rows_in_table) {
7364
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7366
"InnoDB: Index '%-.200s'"
7367
" contains %lu entries,"
7371
(ulong) n_rows_in_table);
7376
/* Restore the original isolation level */
7377
prebuilt->trx->isolation_level = old_isolation_level;
7379
/* We validate also the whole adaptive hash index for all tables
7380
at every CHECK TABLE */
7382
if (!btr_search_validate()) {
7383
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7385
"InnoDB: The adaptive hash index is corrupted.");
7389
/* Restore the fatal lock wait timeout after CHECK TABLE. */
7390
mutex_enter(&kernel_mutex);
7391
srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
7392
mutex_exit(&kernel_mutex);
7394
prebuilt->trx->op_info = "";
7395
if (user_session->getKilled()) {
7396
my_error(ER_QUERY_INTERRUPTED, MYF(0));
7399
return(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
6651
assert(session == ha_session());
6652
ut_a(prebuilt->trx);
6653
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6654
ut_a(prebuilt->trx == session_to_trx(session));
6656
if (prebuilt->mysql_template == NULL) {
6657
/* Build the template; we will use a dummy template
6658
in index scans done in checking */
6660
build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
6663
ret = row_check_table_for_mysql(prebuilt);
6665
if (ret == DB_SUCCESS) {
6666
return(HA_ADMIN_OK);
6669
return(HA_ADMIN_CORRUPT);
7402
6672
/*************************************************************//**
7403
6673
Adds information about free space in the InnoDB tablespace to a table comment
7404
6674
which is printed out when a user calls SHOW TABLE STATUS. Adds also info on
7406
@return table comment + InnoDB free space + info on foreign keys */
6676
@return table comment + InnoDB free space + info on foreign keys */
7409
6679
ha_innobase::update_table_comment(
7410
6680
/*==============================*/
7411
const char* comment)/*!< in: table comment defined by user */
6681
const char* comment)/*!< in: table comment defined by user */
7413
uint length = (uint) strlen(comment);
7417
/* We do not know if MySQL can call this function before calling
7418
external_lock(). To be safe, update the session of the current table
7421
if (length > 64000 - 3) {
7422
return((char*)comment); /* string too long */
7425
update_session(getTable()->in_use);
7427
prebuilt->trx->op_info = (char*)"returning table comment";
7429
/* In case MySQL calls this in the middle of a SELECT query, release
7430
possible adaptive hash latch to avoid deadlocks of threads */
7432
trx_search_latch_release_if_reserved(prebuilt->trx);
7435
/* output the data to a temporary file */
7437
mutex_enter(&srv_dict_tmpfile_mutex);
7438
rewind(srv_dict_tmpfile);
7440
fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
7441
fsp_get_available_space_in_free_extents(
7442
prebuilt->table->space));
7444
dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
7445
prebuilt->trx, prebuilt->table);
7446
flen = ftell(srv_dict_tmpfile);
7449
} else if (length + flen + 3 > 64000) {
7450
flen = 64000 - 3 - length;
7453
/* allocate buffer for the full string, and
7454
read the contents of the temporary file */
7456
str = (char*) malloc(length + flen + 3);
7459
char* pos = str + length;
7461
memcpy(str, comment, length);
7465
rewind(srv_dict_tmpfile);
7466
flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
7470
mutex_exit(&srv_dict_tmpfile_mutex);
7472
prebuilt->trx->op_info = (char*)"";
7474
return(str ? str : (char*) comment);
6683
uint length = (uint) strlen(comment);
6687
/* We do not know if MySQL can call this function before calling
6688
external_lock(). To be safe, update the session of the current table
6691
if (length > 64000 - 3) {
6692
return((char*)comment); /* string too long */
6695
update_session(ha_session());
6697
prebuilt->trx->op_info = (char*)"returning table comment";
6699
/* In case MySQL calls this in the middle of a SELECT query, release
6700
possible adaptive hash latch to avoid deadlocks of threads */
6702
trx_search_latch_release_if_reserved(prebuilt->trx);
6705
/* output the data to a temporary file */
6707
mutex_enter(&srv_dict_tmpfile_mutex);
6708
rewind(srv_dict_tmpfile);
6710
fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
6711
fsp_get_available_space_in_free_extents(
6712
prebuilt->table->space));
6714
dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
6715
prebuilt->trx, prebuilt->table);
6716
flen = ftell(srv_dict_tmpfile);
6719
} else if (length + flen + 3 > 64000) {
6720
flen = 64000 - 3 - length;
6723
/* allocate buffer for the full string, and
6724
read the contents of the temporary file */
6726
str = (char*) malloc(length + flen + 3);
6729
char* pos = str + length;
6731
memcpy(str, comment, length);
6735
rewind(srv_dict_tmpfile);
6736
flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
6740
mutex_exit(&srv_dict_tmpfile_mutex);
6742
prebuilt->trx->op_info = (char*)"";
6744
return(str ? str : (char*) comment);
7477
6747
/*******************************************************************//**
7484
6754
ha_innobase::get_foreign_key_create_info(void)
7485
6755
/*==========================================*/
7490
ut_a(prebuilt != NULL);
7492
/* We do not know if MySQL can call this function before calling
7493
external_lock(). To be safe, update the session of the current table
7496
update_session(getTable()->in_use);
7498
prebuilt->trx->op_info = (char*)"getting info on foreign keys";
7500
/* In case MySQL calls this in the middle of a SELECT query,
7501
release possible adaptive hash latch to avoid
7502
deadlocks of threads */
7504
trx_search_latch_release_if_reserved(prebuilt->trx);
7506
mutex_enter(&srv_dict_tmpfile_mutex);
7507
rewind(srv_dict_tmpfile);
7509
/* output the data to a temporary file */
7510
dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
7511
prebuilt->trx, prebuilt->table);
7512
prebuilt->trx->op_info = (char*)"";
7514
flen = ftell(srv_dict_tmpfile);
7517
} else if (flen > 64000 - 1) {
7521
/* allocate buffer for the string, and
7522
read the contents of the temporary file */
7524
str = (char*) malloc(flen + 1);
7527
rewind(srv_dict_tmpfile);
7528
flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
7532
mutex_exit(&srv_dict_tmpfile_mutex);
6760
ut_a(prebuilt != NULL);
6762
/* We do not know if MySQL can call this function before calling
6763
external_lock(). To be safe, update the session of the current table
6766
update_session(ha_session());
6768
prebuilt->trx->op_info = (char*)"getting info on foreign keys";
6770
/* In case MySQL calls this in the middle of a SELECT query,
6771
release possible adaptive hash latch to avoid
6772
deadlocks of threads */
6774
trx_search_latch_release_if_reserved(prebuilt->trx);
6776
mutex_enter(&srv_dict_tmpfile_mutex);
6777
rewind(srv_dict_tmpfile);
6779
/* output the data to a temporary file */
6780
dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
6781
prebuilt->trx, prebuilt->table);
6782
prebuilt->trx->op_info = (char*)"";
6784
flen = ftell(srv_dict_tmpfile);
6787
} else if (flen > 64000 - 1) {
6791
/* allocate buffer for the string, and
6792
read the contents of the temporary file */
6794
str = (char*) malloc(flen + 1);
6797
rewind(srv_dict_tmpfile);
6798
flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
6802
mutex_exit(&srv_dict_tmpfile_mutex);
7540
ha_innobase::get_foreign_key_list(Session *session, List<ForeignKeyInfo> *f_key_list)
6810
ha_innobase::get_foreign_key_list(Session *session, List<FOREIGN_KEY_INFO> *f_key_list)
7542
6812
dict_foreign_t* foreign;
7544
6814
ut_a(prebuilt != NULL);
7545
update_session(getTable()->in_use);
6815
update_session(ha_session());
7546
6816
prebuilt->trx->op_info = (char*)"getting list of foreign keys";
7547
6817
trx_search_latch_release_if_reserved(prebuilt->trx);
7548
6818
mutex_enter(&(dict_sys->mutex));
7549
6819
foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
7551
6821
while (foreign != NULL) {
7554
LEX_STRING *name = 0;
7556
char uname[NAME_LEN + 1]; /* Unencoded name */
7557
char db_name[NAME_LEN + 1];
7558
const char *tmp_buff;
7561
tmp_buff = foreign->id;
7563
while (tmp_buff[i] != '/')
7566
LEX_STRING *tmp_foreign_id = session->make_lex_string(NULL, tmp_buff, strlen(tmp_buff), true);
7569
tmp_buff = foreign->referenced_table_name;
7572
while (tmp_buff[i] != '/')
7574
db_name[i]= tmp_buff[i];
7578
ulen= TableIdentifier::filename_to_tablename(db_name, uname, sizeof(uname));
7579
LEX_STRING *tmp_referenced_db = session->make_lex_string(NULL, uname, ulen, true);
7583
ulen= TableIdentifier::filename_to_tablename(tmp_buff, uname, sizeof(uname));
7584
LEX_STRING *tmp_referenced_table = session->make_lex_string(NULL, uname, ulen, true);
7586
/** Foreign Fields **/
7587
List<LEX_STRING> tmp_foreign_fields;
7588
List<LEX_STRING> tmp_referenced_fields;
7590
tmp_buff= foreign->foreign_col_names[i];
7591
name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
7592
tmp_foreign_fields.push_back(name);
7593
tmp_buff= foreign->referenced_col_names[i];
7594
name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
7595
tmp_referenced_fields.push_back(name);
7596
if (++i >= foreign->n_fields)
7601
if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
7604
tmp_buff= "CASCADE";
7606
else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
7609
tmp_buff= "SET NULL";
7611
else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
7614
tmp_buff= "NO ACTION";
7619
tmp_buff= "RESTRICT";
7621
LEX_STRING *tmp_delete_method = session->make_lex_string(NULL, tmp_buff, length, true);
7624
if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
7627
tmp_buff= "CASCADE";
7629
else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
7632
tmp_buff= "SET NULL";
7634
else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
7637
tmp_buff= "NO ACTION";
7642
tmp_buff= "RESTRICT";
7644
LEX_STRING *tmp_update_method = session->make_lex_string(NULL, tmp_buff, length, true);
7646
LEX_STRING *tmp_referenced_key_name = NULL;
7648
if (foreign->referenced_index &&
7649
foreign->referenced_index->name)
7651
tmp_referenced_key_name = session->make_lex_string(NULL,
7652
foreign->referenced_index->name, strlen(foreign->referenced_index->name), true);
7655
ForeignKeyInfo f_key_info(
7656
tmp_foreign_id, tmp_referenced_db, tmp_referenced_table,
7657
tmp_update_method, tmp_delete_method, tmp_referenced_key_name,
7658
tmp_foreign_fields, tmp_referenced_fields);
7660
ForeignKeyInfo *pf_key_info = (ForeignKeyInfo *)
7661
session->memdup(&f_key_info, sizeof(ForeignKeyInfo));
7662
f_key_list->push_back(pf_key_info);
7663
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
6823
FOREIGN_KEY_INFO f_key_info;
6824
LEX_STRING *name= 0;
6826
char uname[NAME_LEN+1]; /* Unencoded name */
6827
char db_name[NAME_LEN+1];
6828
const char *tmp_buff;
6830
tmp_buff= foreign->id;
6832
while (tmp_buff[i] != '/')
6835
f_key_info.forein_id = session->make_lex_string(NULL, tmp_buff, strlen(tmp_buff), true);
6836
tmp_buff= foreign->referenced_table_name;
6840
while (tmp_buff[i] != '/')
6842
db_name[i]= tmp_buff[i];
6846
ulen= filename_to_tablename(db_name, uname, sizeof(uname));
6847
f_key_info.referenced_db = session->make_lex_string(NULL, uname, ulen, true);
6851
ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
6852
f_key_info.referenced_table = session->make_lex_string(NULL, uname, ulen, true);
6855
tmp_buff= foreign->foreign_col_names[i];
6856
name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
6857
f_key_info.foreign_fields.push_back(name);
6858
tmp_buff= foreign->referenced_col_names[i];
6859
name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
6860
f_key_info.referenced_fields.push_back(name);
6861
if (++i >= foreign->n_fields)
6866
if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
6869
tmp_buff= "CASCADE";
6871
else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
6874
tmp_buff= "SET NULL";
6876
else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
6879
tmp_buff= "NO ACTION";
6884
tmp_buff= "RESTRICT";
6886
f_key_info.delete_method = session->make_lex_string(
6887
f_key_info.delete_method, tmp_buff, length, true);
6890
if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
6893
tmp_buff= "CASCADE";
6895
else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
6898
tmp_buff= "SET NULL";
6900
else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
6903
tmp_buff= "NO ACTION";
6908
tmp_buff= "RESTRICT";
6910
f_key_info.update_method = session->make_lex_string(
6911
f_key_info.update_method, tmp_buff, length, true);
6912
if (foreign->referenced_index &&
6913
foreign->referenced_index->name)
6915
f_key_info.referenced_key_name = session->make_lex_string(
6916
f_key_info.referenced_key_name,
6917
foreign->referenced_index->name,
6918
strlen(foreign->referenced_index->name), true);
6921
f_key_info.referenced_key_name= 0;
6923
FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *)
6924
session_memdup(session, &f_key_info, sizeof(FOREIGN_KEY_INFO));
6925
f_key_list->push_back(pf_key_info);
6926
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
7665
6928
mutex_exit(&(dict_sys->mutex));
7666
6929
prebuilt->trx->op_info = (char*)"";
7722
6985
ha_innobase::free_foreign_key_create_info(
7723
6986
/*======================================*/
7724
char* str) /*!< in, own: create info string to free */
6987
char* str) /*!< in, own: create info string to free */
7731
6994
/*******************************************************************//**
7732
6995
Tells something additional to the Cursor about how to do things.
7733
@return 0 or error number */
6996
@return 0 or error number */
7736
6999
ha_innobase::extra(
7737
7000
/*===============*/
7738
enum ha_extra_function operation)
7739
/*!< in: HA_EXTRA_FLUSH or some other flag */
7001
enum ha_extra_function operation)
7002
/*!< in: HA_EXTRA_FLUSH or some other flag */
7741
/* Warning: since it is not sure that MySQL calls external_lock
7742
before calling this function, the trx field in prebuilt can be
7745
switch (operation) {
7746
case HA_EXTRA_FLUSH:
7747
if (prebuilt->blob_heap) {
7748
row_mysql_prebuilt_free_blob_heap(prebuilt);
7751
case HA_EXTRA_RESET_STATE:
7752
reset_template(prebuilt);
7754
case HA_EXTRA_NO_KEYREAD:
7755
prebuilt->read_just_key = 0;
7757
case HA_EXTRA_KEYREAD:
7758
prebuilt->read_just_key = 1;
7760
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
7761
prebuilt->keep_other_fields_on_keyread = 1;
7764
/* IMPORTANT: prebuilt->trx can be obsolete in
7765
this method, because it is not sure that MySQL
7766
calls external_lock before this method with the
7767
parameters below. We must not invoke update_session()
7768
either, because the calling threads may change.
7769
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7770
case HA_EXTRA_IGNORE_DUP_KEY:
7771
session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_IGNORE;
7773
case HA_EXTRA_WRITE_CAN_REPLACE:
7774
session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_REPLACE;
7776
case HA_EXTRA_WRITE_CANNOT_REPLACE:
7777
session_to_trx(getTable()->in_use)->duplicates &= ~TRX_DUP_REPLACE;
7779
case HA_EXTRA_NO_IGNORE_DUP_KEY:
7780
session_to_trx(getTable()->in_use)->duplicates &=
7781
~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7783
default:/* Do nothing */
7004
/* Warning: since it is not sure that MySQL calls external_lock
7005
before calling this function, the trx field in prebuilt can be
7008
switch (operation) {
7009
case HA_EXTRA_FLUSH:
7010
if (prebuilt->blob_heap) {
7011
row_mysql_prebuilt_free_blob_heap(prebuilt);
7014
case HA_EXTRA_RESET_STATE:
7015
reset_template(prebuilt);
7017
case HA_EXTRA_NO_KEYREAD:
7018
prebuilt->read_just_key = 0;
7020
case HA_EXTRA_KEYREAD:
7021
prebuilt->read_just_key = 1;
7023
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
7024
prebuilt->keep_other_fields_on_keyread = 1;
7027
/* IMPORTANT: prebuilt->trx can be obsolete in
7028
this method, because it is not sure that MySQL
7029
calls external_lock before this method with the
7030
parameters below. We must not invoke update_session()
7031
either, because the calling threads may change.
7032
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7033
case HA_EXTRA_IGNORE_DUP_KEY:
7034
session_to_trx(ha_session())->duplicates |= TRX_DUP_IGNORE;
7036
case HA_EXTRA_WRITE_CAN_REPLACE:
7037
session_to_trx(ha_session())->duplicates |= TRX_DUP_REPLACE;
7039
case HA_EXTRA_WRITE_CANNOT_REPLACE:
7040
session_to_trx(ha_session())->duplicates &= ~TRX_DUP_REPLACE;
7042
case HA_EXTRA_NO_IGNORE_DUP_KEY:
7043
session_to_trx(ha_session())->duplicates &=
7044
~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7046
default:/* Do nothing */
7792
7055
ha_innobase::reset()
7794
if (prebuilt->blob_heap) {
7795
row_mysql_prebuilt_free_blob_heap(prebuilt);
7798
reset_template(prebuilt);
7800
/* TODO: This should really be reset in reset_template() but for now
7801
it's safer to do it explicitly here. */
7803
/* This is a statement level counter. */
7804
prebuilt->autoinc_last_value = 0;
7057
if (prebuilt->blob_heap) {
7058
row_mysql_prebuilt_free_blob_heap(prebuilt);
7061
reset_template(prebuilt);
7063
/* TODO: This should really be reset in reset_template() but for now
7064
it's safer to do it explicitly here. */
7066
/* This is a statement level counter. */
7067
prebuilt->autoinc_last_value = 0;
7809
7072
/******************************************************************//**
7810
7073
Maps a MySQL trx isolation level code to the InnoDB isolation level code
7811
@return InnoDB isolation level */
7074
@return InnoDB isolation level */
7814
7077
innobase_map_isolation_level(
7815
7078
/*=========================*/
7816
enum_tx_isolation iso) /*!< in: MySQL isolation level code */
7079
enum_tx_isolation iso) /*!< in: MySQL isolation level code */
7819
case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
7820
case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
7821
case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
7822
case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
7823
default: ut_a(0); return(0);
7082
case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
7083
case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
7084
case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
7085
case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
7086
default: ut_a(0); return(0);
7827
7090
/******************************************************************//**
7828
7091
As MySQL will execute an external lock for every new table it uses when it
7829
7092
starts to process an SQL statement. We can use this function to store the pointer to
7830
7093
the Session in the handle.
7834
7097
ha_innobase::external_lock(
7835
7098
/*=======================*/
7836
Session* session, /*!< in: handle to the user thread */
7837
int lock_type) /*!< in: lock type */
7099
Session* session, /*!< in: handle to the user thread */
7100
int lock_type) /*!< in: lock type */
7839
update_session(session);
7102
update_session(session);
7841
7104
trx_t *trx= prebuilt->trx;
7843
prebuilt->sql_stat_start = TRUE;
7844
prebuilt->hint_need_to_fetch_extra_cols = 0;
7846
reset_template(prebuilt);
7848
if (lock_type == F_WRLCK) {
7850
/* If this is a SELECT, then it is in UPDATE TABLE ...
7851
or SELECT ... FOR UPDATE */
7852
prebuilt->select_lock_type = LOCK_X;
7853
prebuilt->stored_select_lock_type = LOCK_X;
7856
if (lock_type != F_UNLCK) {
7857
/* MySQL is setting a new table lock */
7859
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
7860
&& prebuilt->select_lock_type == LOCK_NONE
7861
&& session_test_options(session,
7862
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7864
/* To get serializable execution, we let InnoDB
7865
conceptually add 'LOCK IN SHARE MODE' to all SELECTs
7866
which otherwise would have been consistent reads. An
7867
exception is consistent reads in the AUTOCOMMIT=1 mode:
7868
we know that they are read-only transactions, and they
7869
can be serialized also if performed as consistent
7872
prebuilt->select_lock_type = LOCK_S;
7873
prebuilt->stored_select_lock_type = LOCK_S;
7876
/* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
7877
TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
7878
an InnoDB table lock if it is released immediately at the end
7879
of LOCK TABLES, and InnoDB's table locks in that case cause
7880
VERY easily deadlocks.
7882
We do not set InnoDB table locks if user has not explicitly
7883
requested a table lock. Note that session_in_lock_tables(session)
7884
can hold in some cases, e.g., at the start of a stored
7885
procedure call (SQLCOM_CALL). */
7887
if (prebuilt->select_lock_type != LOCK_NONE) {
7888
trx->mysql_n_tables_locked++;
7891
prebuilt->mysql_has_locked = TRUE;
7896
/* MySQL is releasing a table lock */
7897
prebuilt->mysql_has_locked = FALSE;
7898
trx->mysql_n_tables_locked= 0;
7106
prebuilt->sql_stat_start = TRUE;
7107
prebuilt->hint_need_to_fetch_extra_cols = 0;
7109
reset_template(prebuilt);
7111
if (lock_type == F_WRLCK) {
7113
/* If this is a SELECT, then it is in UPDATE TABLE ...
7114
or SELECT ... FOR UPDATE */
7115
prebuilt->select_lock_type = LOCK_X;
7116
prebuilt->stored_select_lock_type = LOCK_X;
7119
if (lock_type != F_UNLCK) {
7120
/* MySQL is setting a new table lock */
7122
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
7123
&& prebuilt->select_lock_type == LOCK_NONE
7124
&& session_test_options(session,
7125
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7127
/* To get serializable execution, we let InnoDB
7128
conceptually add 'LOCK IN SHARE MODE' to all SELECTs
7129
which otherwise would have been consistent reads. An
7130
exception is consistent reads in the AUTOCOMMIT=1 mode:
7131
we know that they are read-only transactions, and they
7132
can be serialized also if performed as consistent
7135
prebuilt->select_lock_type = LOCK_S;
7136
prebuilt->stored_select_lock_type = LOCK_S;
7139
/* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
7140
TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
7141
an InnoDB table lock if it is released immediately at the end
7142
of LOCK TABLES, and InnoDB's table locks in that case cause
7143
VERY easily deadlocks.
7145
We do not set InnoDB table locks if user has not explicitly
7146
requested a table lock. Note that session_in_lock_tables(session)
7147
can hold in some cases, e.g., at the start of a stored
7148
procedure call (SQLCOM_CALL). */
7150
if (prebuilt->select_lock_type != LOCK_NONE) {
7151
trx->mysql_n_tables_locked++;
7154
prebuilt->mysql_has_locked = TRUE;
7159
/* MySQL is releasing a table lock */
7160
prebuilt->mysql_has_locked = FALSE;
7161
trx->mysql_n_tables_locked= 0;
7903
7166
/************************************************************************//**
7908
7171
innodb_show_status(
7909
7172
/*===============*/
7910
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7911
Session* session,/*!< in: the MySQL query thread of the caller */
7912
stat_print_fn *stat_print)
7173
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7174
Session* session,/*!< in: the MySQL query thread of the caller */
7175
stat_print_fn *stat_print)
7915
static const char truncated_msg[] = "... truncated...\n";
7916
const long MAX_STATUS_SIZE = 64000;
7917
ulint trx_list_start = ULINT_UNDEFINED;
7918
ulint trx_list_end = ULINT_UNDEFINED;
7920
assert(engine == innodb_engine_ptr);
7922
trx = check_trx_exists(session);
7924
innobase_release_stat_resources(trx);
7926
/* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
7929
long flen, usable_len;
7932
mutex_enter(&srv_monitor_file_mutex);
7933
rewind(srv_monitor_file);
7934
srv_printf_innodb_monitor(srv_monitor_file, FALSE,
7935
&trx_list_start, &trx_list_end);
7936
flen = ftell(srv_monitor_file);
7937
os_file_set_eof(srv_monitor_file);
7943
if (flen > MAX_STATUS_SIZE) {
7944
usable_len = MAX_STATUS_SIZE;
7949
/* allocate buffer for the string, and
7950
read the contents of the temporary file */
7952
if (!(str = (char*) malloc(usable_len + 1))) {
7953
mutex_exit(&srv_monitor_file_mutex);
7957
rewind(srv_monitor_file);
7958
if (flen < MAX_STATUS_SIZE) {
7959
/* Display the entire output. */
7960
flen = (long) fread(str, 1, flen, srv_monitor_file);
7961
} else if (trx_list_end < (ulint) flen
7962
&& trx_list_start < trx_list_end
7963
&& trx_list_start + (flen - trx_list_end)
7964
< MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
7965
/* Omit the beginning of the list of active transactions. */
7966
long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
7967
memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
7968
len += sizeof truncated_msg - 1;
7969
usable_len = (MAX_STATUS_SIZE - 1) - len;
7970
fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
7971
len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
7974
/* Omit the end of the output. */
7975
flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
7978
mutex_exit(&srv_monitor_file_mutex);
7980
bool result = FALSE;
7982
if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
7983
STRING_WITH_LEN(""), str, flen)) {
7178
static const char truncated_msg[] = "... truncated...\n";
7179
const long MAX_STATUS_SIZE = 64000;
7180
ulint trx_list_start = ULINT_UNDEFINED;
7181
ulint trx_list_end = ULINT_UNDEFINED;
7183
assert(engine == innodb_engine_ptr);
7185
trx = check_trx_exists(session);
7187
innobase_release_stat_resources(trx);
7189
/* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
7192
long flen, usable_len;
7195
mutex_enter(&srv_monitor_file_mutex);
7196
rewind(srv_monitor_file);
7197
srv_printf_innodb_monitor(srv_monitor_file,
7198
&trx_list_start, &trx_list_end);
7199
flen = ftell(srv_monitor_file);
7200
os_file_set_eof(srv_monitor_file);
7206
if (flen > MAX_STATUS_SIZE) {
7207
usable_len = MAX_STATUS_SIZE;
7212
/* allocate buffer for the string, and
7213
read the contents of the temporary file */
7215
if (!(str = (char*) malloc(usable_len + 1))) {
7216
mutex_exit(&srv_monitor_file_mutex);
7220
rewind(srv_monitor_file);
7221
if (flen < MAX_STATUS_SIZE) {
7222
/* Display the entire output. */
7223
flen = (long) fread(str, 1, flen, srv_monitor_file);
7224
} else if (trx_list_end < (ulint) flen
7225
&& trx_list_start < trx_list_end
7226
&& trx_list_start + (flen - trx_list_end)
7227
< MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
7228
/* Omit the beginning of the list of active transactions. */
7229
long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
7230
memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
7231
len += sizeof truncated_msg - 1;
7232
usable_len = (MAX_STATUS_SIZE - 1) - len;
7233
fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
7234
len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
7237
/* Omit the end of the output. */
7238
flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
7241
mutex_exit(&srv_monitor_file_mutex);
7243
bool result = FALSE;
7245
if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
7246
STRING_WITH_LEN(""), str, flen)) {
7991
7254
/************************************************************************//**
7992
Implements the SHOW MUTEX STATUS command.
7993
@return true on failure false on success*/
7255
Implements the SHOW MUTEX STATUS command. . */
7996
7258
innodb_mutex_show_status(
7997
7259
/*=====================*/
7998
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7999
Session* session, /*!< in: the MySQL query thread of the
8001
stat_print_fn* stat_print) /*!< in: function for printing
7260
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7261
Session* session, /*!< in: the MySQL query thread of the
7263
stat_print_fn* stat_print)
8004
char buf1[IO_SIZE], buf2[IO_SIZE];
8007
ulint block_mutex_oswait_count = 0;
8008
ulint block_lock_oswait_count = 0;
8009
mutex_t* block_mutex = NULL;
8010
rw_lock_t* block_lock = NULL;
7265
char buf1[IO_SIZE], buf2[IO_SIZE];
8011
7268
#ifdef UNIV_DEBUG
8012
ulint rw_lock_count= 0;
8013
ulint rw_lock_count_spin_loop= 0;
8014
ulint rw_lock_count_spin_rounds= 0;
8015
ulint rw_lock_count_os_wait= 0;
8016
ulint rw_lock_count_os_yield= 0;
8017
uint64_t rw_lock_wait_time= 0;
7269
ulint rw_lock_count= 0;
7270
ulint rw_lock_count_spin_loop= 0;
7271
ulint rw_lock_count_spin_rounds= 0;
7272
ulint rw_lock_count_os_wait= 0;
7273
ulint rw_lock_count_os_yield= 0;
7274
uint64_t rw_lock_wait_time= 0;
8018
7275
#endif /* UNIV_DEBUG */
8019
uint engine_name_len= strlen(innobase_engine_name), buf1len, buf2len;
8020
assert(engine == innodb_engine_ptr);
8022
mutex_enter(&mutex_list_mutex);
8024
for (mutex = UT_LIST_GET_FIRST(mutex_list); mutex != NULL;
8025
mutex = UT_LIST_GET_NEXT(list, mutex)) {
8026
if (mutex->count_os_wait == 0) {
8031
if (buf_pool_is_block_mutex(mutex)) {
8032
block_mutex = mutex;
8033
block_mutex_oswait_count += mutex->count_os_wait;
7276
uint engine_name_len= strlen(innobase_engine_name), buf1len, buf2len;
7277
assert(engine == innodb_engine_ptr);
7279
mutex_enter(&mutex_list_mutex);
7281
mutex = UT_LIST_GET_FIRST(mutex_list);
7283
while (mutex != NULL) {
7284
if (mutex->count_os_wait == 0
7285
|| buf_pool_is_block_mutex(mutex)) {
8036
7288
#ifdef UNIV_DEBUG
8037
if (mutex->mutex_type != 1) {
8038
if (mutex->count_using > 0) {
8039
buf1len= my_snprintf(buf1, sizeof(buf1),
8041
mutex->cmutex_name, mutex->cfile_name);
8042
buf2len= my_snprintf(buf2, sizeof(buf2),
8043
"count=%lu, spin_waits=%lu,"
8044
" spin_rounds=%lu, "
8045
"os_waits=%lu, os_yields=%lu,"
8046
" os_wait_times=%lu",
8048
mutex->count_spin_loop,
8049
mutex->count_spin_rounds,
8050
mutex->count_os_wait,
8051
mutex->count_os_yield,
8052
(ulong) (mutex->lspent_time/1000));
7289
if (mutex->mutex_type != 1) {
7290
if (mutex->count_using > 0) {
7291
buf1len= my_snprintf(buf1, sizeof(buf1),
7293
mutex->cmutex_name, mutex->cfile_name);
7294
buf2len= my_snprintf(buf2, sizeof(buf2),
7295
"count=%lu, spin_waits=%lu,"
7296
" spin_rounds=%lu, "
7297
"os_waits=%lu, os_yields=%lu,"
7298
" os_wait_times=%lu",
7300
mutex->count_spin_loop,
7301
mutex->count_spin_rounds,
7302
mutex->count_os_wait,
7303
mutex->count_os_yield,
7304
(ulong) (mutex->lspent_time/1000));
8054
if (stat_print(session, innobase_engine_name,
8055
engine_name_len, buf1, buf1len,
8057
mutex_exit(&mutex_list_mutex);
8062
rw_lock_count += mutex->count_using;
8063
rw_lock_count_spin_loop += mutex->count_spin_loop;
8064
rw_lock_count_spin_rounds += mutex->count_spin_rounds;
8065
rw_lock_count_os_wait += mutex->count_os_wait;
8066
rw_lock_count_os_yield += mutex->count_os_yield;
8067
rw_lock_wait_time += mutex->lspent_time;
7306
if (stat_print(session, innobase_engine_name,
7307
engine_name_len, buf1, buf1len,
7309
mutex_exit(&mutex_list_mutex);
7315
rw_lock_count += mutex->count_using;
7316
rw_lock_count_spin_loop += mutex->count_spin_loop;
7317
rw_lock_count_spin_rounds += mutex->count_spin_rounds;
7318
rw_lock_count_os_wait += mutex->count_os_wait;
7319
rw_lock_count_os_yield += mutex->count_os_yield;
7320
rw_lock_wait_time += mutex->lspent_time;
8069
7322
#else /* UNIV_DEBUG */
8070
buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
8071
mutex->cfile_name, (ulong) mutex->cline);
8072
buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
8073
(ulong) mutex->count_os_wait);
7323
buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
7324
mutex->cfile_name, (ulong) mutex->cline);
7325
buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
7326
mutex->count_os_wait);
8075
if (stat_print(session, innobase_engine_name,
8076
engine_name_len, buf1, buf1len,
8078
mutex_exit(&mutex_list_mutex);
7328
if (stat_print(session, innobase_engine_name,
7329
engine_name_len, buf1, buf1len,
7331
mutex_exit(&mutex_list_mutex);
8081
7334
#endif /* UNIV_DEBUG */
8085
buf1len = snprintf(buf1, sizeof buf1,
8087
block_mutex->cfile_name,
8088
(ulong) block_mutex->cline);
8089
buf2len = snprintf(buf2, sizeof buf2,
8091
(ulong) block_mutex_oswait_count);
8093
if (stat_print(session, innobase_engine_name,
8094
strlen(innobase_engine_name), buf1, buf1len,
8096
mutex_exit(&mutex_list_mutex);
8101
mutex_exit(&mutex_list_mutex);
8103
mutex_enter(&rw_lock_list_mutex);
8105
for (lock = UT_LIST_GET_FIRST(rw_lock_list); lock != NULL;
8106
lock = UT_LIST_GET_NEXT(list, lock)) {
8107
if (lock->count_os_wait == 0) {
8111
if (buf_pool_is_block_lock(lock)) {
8113
block_lock_oswait_count += lock->count_os_wait;
8117
buf1len = snprintf(buf1, sizeof buf1, "%s:%lu",
8118
lock->cfile_name, (ulong) lock->cline);
8119
buf2len = snprintf(buf2, sizeof buf2, "os_waits=%lu",
8120
(ulong) lock->count_os_wait);
8122
if (stat_print(session, innobase_engine_name,
8123
strlen(innobase_engine_name), buf1, buf1len,
8125
mutex_exit(&rw_lock_list_mutex);
8131
buf1len = snprintf(buf1, sizeof buf1,
8133
block_lock->cfile_name,
8134
(ulong) block_lock->cline);
8135
buf2len = snprintf(buf2, sizeof buf2,
8137
(ulong) block_lock_oswait_count);
8139
if (stat_print(session, innobase_engine_name,
8140
strlen(innobase_engine_name), buf1, buf1len,
8142
mutex_exit(&rw_lock_list_mutex);
8147
mutex_exit(&rw_lock_list_mutex);
7337
mutex = UT_LIST_GET_NEXT(list, mutex);
7340
mutex_exit(&mutex_list_mutex);
7342
mutex_enter(&rw_lock_list_mutex);
7344
lock = UT_LIST_GET_FIRST(rw_lock_list);
7346
while (lock != NULL) {
7347
if (lock->count_os_wait
7348
&& !buf_pool_is_block_lock(lock)) {
7349
buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
7350
lock->cfile_name, (unsigned long) lock->cline);
7351
buf2len= snprintf(buf2, sizeof(buf2),
7352
"os_waits=%lu", lock->count_os_wait);
7354
if (stat_print(session, innobase_engine_name,
7355
engine_name_len, buf1, buf1len,
7357
mutex_exit(&rw_lock_list_mutex);
7361
lock = UT_LIST_GET_NEXT(list, lock);
7364
mutex_exit(&rw_lock_list_mutex);
8149
7366
#ifdef UNIV_DEBUG
8150
buf2len = snprintf(buf2, sizeof buf2,
8151
"count=%lu, spin_waits=%lu, spin_rounds=%lu, "
8152
"os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
8153
(ulong) rw_lock_count,
8154
(ulong) rw_lock_count_spin_loop,
8155
(ulong) rw_lock_count_spin_rounds,
8156
(ulong) rw_lock_count_os_wait,
8157
(ulong) rw_lock_count_os_yield,
8158
(ulong) (rw_lock_wait_time / 1000));
7367
buf2len= my_snprintf(buf2, sizeof(buf2),
7368
"count=%lu, spin_waits=%lu, spin_rounds=%lu, "
7369
"os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
7370
rw_lock_count, rw_lock_count_spin_loop,
7371
rw_lock_count_spin_rounds,
7372
rw_lock_count_os_wait, rw_lock_count_os_yield,
7373
(ulong) (rw_lock_wait_time/1000));
8160
if (stat_print(session, innobase_engine_name, engine_name_len,
8161
STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
7375
if (stat_print(session, innobase_engine_name, engine_name_len,
7376
STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
8164
7379
#endif /* UNIV_DEBUG */
8169
7384
bool InnobaseEngine::show_status(Session* session,
8170
7385
stat_print_fn* stat_print,
8171
7386
enum ha_stat_type stat_type)
8173
assert(this == innodb_engine_ptr);
7388
assert(this == innodb_engine_ptr);
8175
switch (stat_type) {
8176
case HA_ENGINE_STATUS:
8177
return innodb_show_status(this, session, stat_print);
8178
case HA_ENGINE_MUTEX:
8179
return innodb_mutex_show_status(this, session, stat_print);
7390
switch (stat_type) {
7391
case HA_ENGINE_STATUS:
7392
return innodb_show_status(this, session, stat_print);
7393
case HA_ENGINE_MUTEX:
7394
return innodb_mutex_show_status(this, session, stat_print);
8185
7400
/************************************************************************//**
8265
7478
SELECT the read lock is released early on the 'const' tables where we only
8266
7479
fetch one row. MySQL does not call this when it releases all locks at the
8267
7480
end of an SQL statement.
8268
@return pointer to the next element in the 'to' array */
7481
@return pointer to the next element in the 'to' array */
8270
7483
THR_LOCK_DATA**
8271
7484
ha_innobase::store_lock(
8272
7485
/*====================*/
8273
Session* session, /*!< in: user thread handle */
8274
THR_LOCK_DATA** to, /*!< in: pointer to an array
8275
of pointers to lock structs;
8276
pointer to the 'lock' field
8277
of current handle is stored
8278
next to this array */
8279
enum thr_lock_type lock_type) /*!< in: lock type to store in
8280
'lock'; this may also be
7486
Session* session, /*!< in: user thread handle */
7487
THR_LOCK_DATA** to, /*!< in: pointer to an array
7488
of pointers to lock structs;
7489
pointer to the 'lock' field
7490
of current handle is stored
7491
next to this array */
7492
enum thr_lock_type lock_type) /*!< in: lock type to store in
7493
'lock'; this may also be
8285
/* Note that trx in this function is NOT necessarily prebuilt->trx
8286
because we call update_session() later, in ::external_lock()! Failure to
8287
understand this caused a serious memory corruption bug in 5.1.11. */
8289
trx = check_trx_exists(session);
8291
assert(EQ_CURRENT_SESSION(session));
8292
const uint32_t sql_command = session_sql_command(session);
8294
if (sql_command == SQLCOM_DROP_TABLE) {
8296
/* MySQL calls this function in DROP Table though this table
8297
handle may belong to another session that is running a query.
8298
Let us in that case skip any changes to the prebuilt struct. */
8300
} else if (lock_type == TL_READ_WITH_SHARED_LOCKS
8301
|| lock_type == TL_READ_NO_INSERT
8302
|| (lock_type != TL_IGNORE
8303
&& sql_command != SQLCOM_SELECT)) {
8305
/* The OR cases above are in this order:
8306
1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
8307
are processing a stored procedure or function, or
8308
2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
8309
3) this is a SELECT ... IN SHARE MODE, or
8310
4) we are doing a complex SQL statement like
8311
INSERT INTO ... SELECT ... and the logical logging (MySQL
8312
binlog) requires the use of a locking read, or
8313
MySQL is doing LOCK TABLES ... READ.
8314
5) we let InnoDB do locking reads for all SQL statements that
8315
are not simple SELECTs; note that select_lock_type in this
8316
case may get strengthened in ::external_lock() to LOCK_X.
8317
Note that we MUST use a locking read in all data modifying
8318
SQL statements, because otherwise the execution would not be
8319
serializable, and also the results from the update could be
8320
unexpected if an obsolete consistent read view would be
8323
ulint isolation_level;
8325
isolation_level = trx->isolation_level;
8327
if ((srv_locks_unsafe_for_binlog
8328
|| isolation_level <= TRX_ISO_READ_COMMITTED)
8329
&& isolation_level != TRX_ISO_SERIALIZABLE
8330
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
8331
&& (sql_command == SQLCOM_INSERT_SELECT
8332
|| sql_command == SQLCOM_REPLACE_SELECT
8333
|| sql_command == SQLCOM_UPDATE
8334
|| sql_command == SQLCOM_CREATE_TABLE)) {
8336
/* If we either have innobase_locks_unsafe_for_binlog
8337
option set or this session is using READ COMMITTED
8338
isolation level and isolation level of the transaction
8339
is not set to serializable and MySQL is doing
8340
INSERT INTO...SELECT or REPLACE INTO...SELECT
8341
or UPDATE ... = (SELECT ...) or CREATE ...
8342
SELECT... without FOR UPDATE or IN SHARE
8343
MODE in select, then we use consistent read
8346
prebuilt->select_lock_type = LOCK_NONE;
8347
prebuilt->stored_select_lock_type = LOCK_NONE;
8348
} else if (sql_command == SQLCOM_CHECKSUM) {
8349
/* Use consistent read for checksum table */
8351
prebuilt->select_lock_type = LOCK_NONE;
8352
prebuilt->stored_select_lock_type = LOCK_NONE;
8354
prebuilt->select_lock_type = LOCK_S;
8355
prebuilt->stored_select_lock_type = LOCK_S;
8358
} else if (lock_type != TL_IGNORE) {
8360
/* We set possible LOCK_X value in external_lock, not yet
8361
here even if this would be SELECT ... FOR UPDATE */
8363
prebuilt->select_lock_type = LOCK_NONE;
8364
prebuilt->stored_select_lock_type = LOCK_NONE;
8367
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
8369
/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
8370
TABLESPACE or TRUNCATE TABLE then allow multiple
8371
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
8372
< TL_WRITE_CONCURRENT_INSERT.
8375
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
8376
&& lock_type <= TL_WRITE)
8377
&& !session_tablespace_op(session)
8378
&& sql_command != SQLCOM_TRUNCATE
8379
&& sql_command != SQLCOM_CREATE_TABLE) {
8381
lock_type = TL_WRITE_ALLOW_WRITE;
8384
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
8385
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
8386
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
8387
to t2. Convert the lock to a normal read lock to allow
8388
concurrent inserts to t2.
8391
if (lock_type == TL_READ_NO_INSERT) {
8393
lock_type = TL_READ;
8396
lock.type = lock_type;
7498
/* Note that trx in this function is NOT necessarily prebuilt->trx
7499
because we call update_session() later, in ::external_lock()! Failure to
7500
understand this caused a serious memory corruption bug in 5.1.11. */
7502
trx = check_trx_exists(session);
7504
assert(EQ_CURRENT_SESSION(session));
7505
const uint32_t sql_command = session_sql_command(session);
7507
if (sql_command == SQLCOM_DROP_TABLE) {
7509
/* MySQL calls this function in DROP Table though this table
7510
handle may belong to another session that is running a query.
7511
Let us in that case skip any changes to the prebuilt struct. */
7513
} else if (lock_type == TL_READ_WITH_SHARED_LOCKS
7514
|| lock_type == TL_READ_NO_INSERT
7515
|| (lock_type != TL_IGNORE
7516
&& sql_command != SQLCOM_SELECT)) {
7518
/* The OR cases above are in this order:
7519
1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
7520
are processing a stored procedure or function, or
7521
2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
7522
3) this is a SELECT ... IN SHARE MODE, or
7523
4) we are doing a complex SQL statement like
7524
INSERT INTO ... SELECT ... and the logical logging (MySQL
7525
binlog) requires the use of a locking read, or
7526
MySQL is doing LOCK TABLES ... READ.
7527
5) we let InnoDB do locking reads for all SQL statements that
7528
are not simple SELECTs; note that select_lock_type in this
7529
case may get strengthened in ::external_lock() to LOCK_X.
7530
Note that we MUST use a locking read in all data modifying
7531
SQL statements, because otherwise the execution would not be
7532
serializable, and also the results from the update could be
7533
unexpected if an obsolete consistent read view would be
7536
ulint isolation_level;
7538
isolation_level = trx->isolation_level;
7540
if ((srv_locks_unsafe_for_binlog
7541
|| isolation_level == TRX_ISO_READ_COMMITTED)
7542
&& isolation_level != TRX_ISO_SERIALIZABLE
7543
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
7544
&& (sql_command == SQLCOM_INSERT_SELECT
7545
|| sql_command == SQLCOM_UPDATE
7546
|| sql_command == SQLCOM_CREATE_TABLE)) {
7548
/* If we either have innobase_locks_unsafe_for_binlog
7549
option set or this session is using READ COMMITTED
7550
isolation level and isolation level of the transaction
7551
is not set to serializable and MySQL is doing
7552
INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
7553
CREATE ... SELECT... without FOR UPDATE or
7554
IN SHARE MODE in select, then we use consistent
7557
prebuilt->select_lock_type = LOCK_NONE;
7558
prebuilt->stored_select_lock_type = LOCK_NONE;
7559
} else if (sql_command == SQLCOM_CHECKSUM) {
7560
/* Use consistent read for checksum table */
7562
prebuilt->select_lock_type = LOCK_NONE;
7563
prebuilt->stored_select_lock_type = LOCK_NONE;
7565
prebuilt->select_lock_type = LOCK_S;
7566
prebuilt->stored_select_lock_type = LOCK_S;
7569
} else if (lock_type != TL_IGNORE) {
7571
/* We set possible LOCK_X value in external_lock, not yet
7572
here even if this would be SELECT ... FOR UPDATE */
7574
prebuilt->select_lock_type = LOCK_NONE;
7575
prebuilt->stored_select_lock_type = LOCK_NONE;
7578
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
7580
/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
7581
TABLESPACE or TRUNCATE TABLE then allow multiple
7582
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
7583
< TL_WRITE_CONCURRENT_INSERT.
7586
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
7587
&& lock_type <= TL_WRITE)
7588
&& !session_tablespace_op(session)
7589
&& sql_command != SQLCOM_TRUNCATE
7590
&& sql_command != SQLCOM_CREATE_TABLE) {
7592
lock_type = TL_WRITE_ALLOW_WRITE;
7595
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
7596
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
7597
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
7598
to t2. Convert the lock to a normal read lock to allow
7599
concurrent inserts to t2.
7602
if (lock_type == TL_READ_NO_INSERT) {
7604
lock_type = TL_READ;
7607
lock.type = lock_type;
8404
7615
/*********************************************************************//**
8405
7616
Read the next autoinc value. Acquire the relevant locks before reading
8406
7617
the AUTOINC value. If SUCCESS then the table AUTOINC mutex will be locked
8407
7618
on return and all relevant locks acquired.
8408
@return DB_SUCCESS or error code */
7619
@return DB_SUCCESS or error code */
8411
7622
ha_innobase::innobase_get_autoinc(
8412
7623
/*==============================*/
8413
uint64_t* value) /*!< out: autoinc value */
7624
uint64_t* value) /*!< out: autoinc value */
8417
dict_table_autoinc_lock(prebuilt->table);
8418
prebuilt->autoinc_error= DB_SUCCESS;
8419
/* Determine the first value of the interval */
8420
*value = dict_table_autoinc_read(prebuilt->table);
8422
/* It should have been initialized during open. */
8424
prebuilt->autoinc_error = DB_UNSUPPORTED;
8425
dict_table_autoinc_unlock(prebuilt->table);
7628
prebuilt->autoinc_error = innobase_lock_autoinc();
7630
if (prebuilt->autoinc_error == DB_SUCCESS) {
7632
/* Determine the first value of the interval */
7633
*value = dict_table_autoinc_read(prebuilt->table);
7635
/* It should have been initialized during open. */
7639
return(prebuilt->autoinc_error);
8431
7642
/*******************************************************************//**
8432
7643
This function reads the global auto-inc counter. It doesn't use the
8433
7644
AUTOINC lock even if the lock mode is set to TRADITIONAL.
8434
@return the autoinc value */
7645
@return the autoinc value */
8437
7648
ha_innobase::innobase_peek_autoinc(void)
8438
7649
/*====================================*/
8441
dict_table_t* innodb_table;
8443
ut_a(prebuilt != NULL);
8444
ut_a(prebuilt->table != NULL);
8446
innodb_table = prebuilt->table;
8448
dict_table_autoinc_lock(innodb_table);
8450
auto_inc = dict_table_autoinc_read(innodb_table);
8454
dict_table_autoinc_unlock(innodb_table);
7652
dict_table_t* innodb_table;
7654
ut_a(prebuilt != NULL);
7655
ut_a(prebuilt->table != NULL);
7657
innodb_table = prebuilt->table;
7659
dict_table_autoinc_lock(innodb_table);
7661
auto_inc = dict_table_autoinc_read(innodb_table);
7665
dict_table_autoinc_unlock(innodb_table);
8459
7670
/*********************************************************************//**
8468
7679
ha_innobase::get_auto_increment(
8469
7680
/*============================*/
8470
uint64_t offset, /*!< in: table autoinc offset */
8471
uint64_t increment, /*!< in: table autoinc increment */
8472
uint64_t nb_desired_values, /*!< in: number of values reqd */
8473
uint64_t *first_value, /*!< out: the autoinc value */
8474
uint64_t *nb_reserved_values) /*!< out: count of reserved values */
7681
uint64_t offset, /*!< in: table autoinc offset */
7682
uint64_t increment, /*!< in: table autoinc increment */
7683
uint64_t nb_desired_values, /*!< in: number of values reqd */
7684
uint64_t *first_value, /*!< out: the autoinc value */
7685
uint64_t *nb_reserved_values) /*!< out: count of reserved values */
8478
uint64_t autoinc = 0;
8480
/* Prepare prebuilt->trx in the table handle */
8481
update_session(getTable()->in_use);
8483
error = innobase_get_autoinc(&autoinc);
8485
if (error != DB_SUCCESS) {
8486
*first_value = (~(uint64_t) 0);
8490
/* This is a hack, since nb_desired_values seems to be accurate only
8491
for the first call to get_auto_increment() for multi-row INSERT and
8492
meaningless for other statements e.g, LOAD etc. Subsequent calls to
8493
this method for the same statement results in different values which
8494
don't make sense. Therefore we store the value the first time we are
8495
called and count down from that as rows are written (see doInsertRecord()).
8498
trx = prebuilt->trx;
8500
/* Note: We can't rely on *first_value since some MySQL engines,
8501
in particular the partition engine, don't initialize it to 0 when
8502
invoking this method. So we are not sure if it's guaranteed to
8505
/* We need the upper limit of the col type to check for
8506
whether we update the table autoinc counter or not. */
8507
uint64_t col_max_value = innobase_get_int_col_max_value(getTable()->next_number_field);
8509
/* Called for the first time ? */
8510
if (trx->n_autoinc_rows == 0) {
8512
trx->n_autoinc_rows = (ulint) nb_desired_values;
8514
/* It's possible for nb_desired_values to be 0:
8515
e.g., INSERT INTO T1(C) SELECT C FROM T2; */
8516
if (nb_desired_values == 0) {
8518
trx->n_autoinc_rows = 1;
8521
set_if_bigger(*first_value, autoinc);
8522
/* Not in the middle of a mult-row INSERT. */
8523
} else if (prebuilt->autoinc_last_value == 0) {
8524
set_if_bigger(*first_value, autoinc);
8525
/* Check for -ve values. */
8526
} else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
8527
/* Set to next logical value. */
8528
ut_a(autoinc > trx->n_autoinc_rows);
8529
*first_value = (autoinc - trx->n_autoinc_rows) - 1;
8532
*nb_reserved_values = trx->n_autoinc_rows;
8534
/* This all current style autoinc. */
8538
uint64_t next_value;
8540
current = *first_value > col_max_value ? autoinc : *first_value;
8541
need = *nb_reserved_values * increment;
8543
/* Compute the last value in the interval */
8544
next_value = innobase_next_autoinc(current, need, offset, col_max_value);
8546
prebuilt->autoinc_last_value = next_value;
8548
if (prebuilt->autoinc_last_value < *first_value) {
8549
*first_value = (~(unsigned long long) 0);
8551
/* Update the table autoinc variable */
8552
dict_table_autoinc_update_if_greater(
8553
prebuilt->table, prebuilt->autoinc_last_value);
8557
/* The increment to be used to increase the AUTOINC value, we use
8558
this in doInsertRecord() and doUpdateRecord() to increase the autoinc counter
8559
for columns that are filled by the user. We need the offset and
8561
prebuilt->autoinc_offset = offset;
8562
prebuilt->autoinc_increment = increment;
8564
dict_table_autoinc_unlock(prebuilt->table);
7689
uint64_t autoinc = 0;
7691
/* Prepare prebuilt->trx in the table handle */
7692
update_session(ha_session());
7694
error = innobase_get_autoinc(&autoinc);
7696
if (error != DB_SUCCESS) {
7697
*first_value = (~(uint64_t) 0);
7701
/* This is a hack, since nb_desired_values seems to be accurate only
7702
for the first call to get_auto_increment() for multi-row INSERT and
7703
meaningless for other statements e.g, LOAD etc. Subsequent calls to
7704
this method for the same statement results in different values which
7705
don't make sense. Therefore we store the value the first time we are
7706
called and count down from that as rows are written (see write_row()).
7709
trx = prebuilt->trx;
7711
/* Note: We can't rely on *first_value since some MySQL engines,
7712
in particular the partition engine, don't initialize it to 0 when
7713
invoking this method. So we are not sure if it's guaranteed to
7716
/* Called for the first time ? */
7717
if (trx->n_autoinc_rows == 0) {
7719
trx->n_autoinc_rows = (ulint) nb_desired_values;
7721
/* It's possible for nb_desired_values to be 0:
7722
e.g., INSERT INTO T1(C) SELECT C FROM T2; */
7723
if (nb_desired_values == 0) {
7725
trx->n_autoinc_rows = 1;
7728
set_if_bigger(*first_value, autoinc);
7729
/* Not in the middle of a mult-row INSERT. */
7730
} else if (prebuilt->autoinc_last_value == 0) {
7731
set_if_bigger(*first_value, autoinc);
7734
*nb_reserved_values = trx->n_autoinc_rows;
7736
/* With old style AUTOINC locking we only update the table's
7737
AUTOINC counter after attempting to insert the row. */
7738
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
7740
uint64_t next_value;
7741
uint64_t col_max_value;
7743
/* We need the upper limit of the col type to check for
7744
whether we update the table autoinc counter or not. */
7745
col_max_value = innobase_get_int_col_max_value(
7746
table->next_number_field);
7748
need = *nb_reserved_values * increment;
7750
/* Compute the last value in the interval */
7751
next_value = innobase_next_autoinc(
7752
*first_value, need, offset, col_max_value);
7754
prebuilt->autoinc_last_value = next_value;
7756
if (prebuilt->autoinc_last_value < *first_value) {
7757
*first_value = (~(unsigned long long) 0);
7759
/* Update the table autoinc variable */
7760
dict_table_autoinc_update_if_greater(
7761
prebuilt->table, prebuilt->autoinc_last_value);
7764
/* This will force write_row() into attempting an update
7765
of the table's AUTOINC counter. */
7766
prebuilt->autoinc_last_value = 0;
7769
/* The increment to be used to increase the AUTOINC value, we use
7770
this in write_row() and update_row() to increase the autoinc counter
7771
for columns that are filled by the user. We need the offset and
7773
prebuilt->autoinc_offset = offset;
7774
prebuilt->autoinc_increment = increment;
7776
dict_table_autoinc_unlock(prebuilt->table);
8567
7779
/*******************************************************************//**
8796
8018
innobase_release_stat_resources(trx);
8020
if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
8022
if (trx->active_trans != 0)
8024
commit(session, TRUE);
8025
trx->active_trans= 0;
8030
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
8031
trx->global_read_view)
8033
/* At low transaction isolation levels we let
8034
each consistent read set its own snapshot */
8035
read_view_close_for_mysql(trx);
8800
8040
/*******************************************************************//**
8801
8041
This function is used to prepare an X/Open XA distributed transaction.
8802
@return 0 or error number */
8042
@return 0 or error number */
8804
InnobaseEngine::doXaPrepare(
8044
InnobaseEngine::doPrepare(
8805
8045
/*================*/
8806
Session* session,/*!< in: handle to the MySQL thread of
8807
the user whose XA transaction should
8809
bool all) /*!< in: TRUE - commit transaction
8810
FALSE - the current SQL statement
8814
trx_t* trx = check_trx_exists(session);
8816
assert(this == innodb_engine_ptr);
8818
/* we use support_xa value as it was seen at transaction start
8819
time, not the current session variable value. Any possible changes
8820
to the session variable take effect only in the next transaction */
8821
if (!trx->support_xa) {
8826
session->get_xid(reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
8828
/* Release a possible FIFO ticket and search latch. Since we will
8829
reserve the kernel mutex, we have to release the search system latch
8830
first to obey the latching order. */
8832
innobase_release_stat_resources(trx);
8835
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
8837
/* We were instructed to prepare the whole transaction, or
8838
this is an SQL statement end and autocommit is on */
8840
ut_ad(trx->conc_state != TRX_NOT_STARTED);
8842
error = (int) trx_prepare_for_mysql(trx);
8844
/* We just mark the SQL statement ended and do not do a
8845
transaction prepare */
8847
/* If we had reserved the auto-inc lock for some
8848
table in this SQL statement we release it now */
8850
row_unlock_table_autoinc_for_mysql(trx);
8852
/* Store the current undo_no of the transaction so that we
8853
know where to roll back if we have to roll back the next
8856
trx_mark_sql_stat_end(trx);
8859
/* Tell the InnoDB server that there might be work for utility
8862
srv_active_wake_master_thread();
8867
uint64_t InnobaseEngine::doGetCurrentTransactionId(Session *session)
8869
trx_t *trx= session_to_trx(session);
8870
return (ib_uint64_t) ut_conv_dulint_to_longlong(trx->id);
8873
uint64_t InnobaseEngine::doGetNewTransactionId(Session *session)
8875
trx_t*& trx = session_to_trx(session);
8879
trx = innobase_trx_allocate(session);
8881
innobase_trx_init(session, trx);
8884
mutex_enter(&kernel_mutex);
8885
trx->id= trx_sys_get_new_trx_id();
8886
mutex_exit(&kernel_mutex);
8888
uint64_t transaction_id= (ib_uint64_t) ut_conv_dulint_to_longlong(trx->id);
8890
return transaction_id;
8046
Session* session,/*!< in: handle to the MySQL thread of
8047
the user whose XA transaction should
8049
bool all) /*!< in: TRUE - commit transaction
8050
FALSE - the current SQL statement
8054
trx_t* trx = check_trx_exists(session);
8056
assert(this == innodb_engine_ptr);
8058
/* we use support_xa value as it was seen at transaction start
8059
time, not the current session variable value. Any possible changes
8060
to the session variable take effect only in the next transaction */
8061
if (!trx->support_xa) {
8066
session_get_xid(session, reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
8068
/* Release a possible FIFO ticket and search latch. Since we will
8069
reserve the kernel mutex, we have to release the search system latch
8070
first to obey the latching order. */
8072
innobase_release_stat_resources(trx);
8074
if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
8076
errmsg_printf(ERRMSG_LVL_ERROR,
8077
"trx->active_trans == 0, but trx->conc_state != "
8082
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
8084
/* We were instructed to prepare the whole transaction, or
8085
this is an SQL statement end and autocommit is on */
8087
ut_ad(trx->active_trans);
8089
error = (int) trx_prepare_for_mysql(trx);
8091
/* We just mark the SQL statement ended and do not do a
8092
transaction prepare */
8094
/* If we had reserved the auto-inc lock for some
8095
table in this SQL statement we release it now */
8097
row_unlock_table_autoinc_for_mysql(trx);
8099
/* Store the current undo_no of the transaction so that we
8100
know where to roll back if we have to roll back the next
8103
trx_mark_sql_stat_end(trx);
8106
/* Tell the InnoDB server that there might be work for utility
8109
srv_active_wake_master_thread();
8111
if (all || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
8114
/* For ibbackup to work the order of transactions in binlog
8115
and InnoDB must be the same. Consider the situation
8117
thread1> prepare; write to binlog; ...
8119
thread2> prepare; write to binlog; commit
8122
To ensure this will not happen we're taking the mutex on
8123
prepare, and releasing it on commit.
8125
Note: only do it for normal commits, done via ha_commit_trans.
8126
If 2pc protocol is executed by external transaction
8127
coordinator, it will be just a regular MySQL client
8128
executing XA PREPARE and XA COMMIT commands.
8129
In this case we cannot know how many minutes or hours
8130
will be between XA PREPARE and XA COMMIT, and we don't want
8131
to block for undefined period of time.
8133
pthread_mutex_lock(&prepare_commit_mutex);
8134
trx->active_trans = 2;
8893
8139
/*******************************************************************//**
8894
8140
This function is used to recover X/Open XA distributed transactions.
8895
@return number of prepared transactions stored in xid_list */
8141
@return number of prepared transactions stored in xid_list */
8897
InnobaseEngine::doXaRecover(
8143
InnobaseEngine::doRecover(
8898
8144
/*================*/
8899
::drizzled::XID* xid_list,/*!< in/out: prepared transactions */
8900
size_t len) /*!< in: number of slots in xid_list */
8145
::drizzled::XID* xid_list,/*!< in/out: prepared transactions */
8146
size_t len) /*!< in: number of slots in xid_list */
8902
assert(this == innodb_engine_ptr);
8904
if (len == 0 || xid_list == NULL) {
8909
return(trx_recover_for_mysql((::XID *)xid_list, len));
8148
assert(this == innodb_engine_ptr);
8150
if (len == 0 || xid_list == NULL) {
8155
return(trx_recover_for_mysql((::XID *)xid_list, len));
8912
8158
/*******************************************************************//**
8913
8159
This function is used to commit one X/Open XA distributed transaction
8914
8160
which is in the prepared state
8915
@return 0 or error number */
8161
@return 0 or error number */
8917
InnobaseEngine::doXaCommitXid(
8163
InnobaseEngine::doCommitXid(
8918
8164
/*===================*/
8919
::drizzled::XID* xid) /*!< in: X/Open XA transaction identification */
8165
::drizzled::XID* xid) /*!< in: X/Open XA transaction identification */
8923
assert(this == innodb_engine_ptr);
8925
trx = trx_get_trx_by_xid((::XID *)xid);
8928
innobase_commit_low(trx);
8169
assert(this == innodb_engine_ptr);
8171
trx = trx_get_trx_by_xid((::XID *)xid);
8174
innobase_commit_low(trx);
8936
8182
/*******************************************************************//**
8937
8183
This function is used to rollback one X/Open XA distributed transaction
8938
8184
which is in the prepared state
8939
@return 0 or error number */
8185
@return 0 or error number */
8941
InnobaseEngine::doXaRollbackXid(
8187
InnobaseEngine::doRollbackXid(
8942
8188
/*=====================*/
8943
::drizzled::XID* xid) /*!< in: X/Open XA transaction
8189
::drizzled::XID* xid) /*!< in: X/Open XA transaction
8948
assert(this == innodb_engine_ptr);
8950
trx = trx_get_trx_by_xid((::XID *)xid);
8953
return(innobase_rollback_trx(trx));
8194
assert(this == innodb_engine_ptr);
8196
trx = trx_get_trx_by_xid((::XID *)xid);
8199
return(innobase_rollback_trx(trx));
8960
8206
/************************************************************//**
8961
8207
Validate the file format name and return its corresponding id.
8962
@return valid file format id */
8208
@return valid file format id */
8965
8211
innobase_file_format_name_lookup(
8966
8212
/*=============================*/
8967
const char* format_name) /*!< in: pointer to file format name */
8213
const char* format_name) /*!< in: pointer to file format name */
8972
ut_a(format_name != NULL);
8974
/* The format name can contain the format id itself instead of
8975
the name and we check for that. */
8976
format_id = (uint) strtoul(format_name, &endp, 10);
8978
/* Check for valid parse. */
8979
if (*endp == '\0' && *format_name != '\0') {
8981
if (format_id <= DICT_TF_FORMAT_MAX) {
8987
for (format_id = 0; format_id <= DICT_TF_FORMAT_MAX;
8991
name = trx_sys_file_format_id_to_name(format_id);
8993
if (!innobase_strcasecmp(format_name, name)) {
9000
return(DICT_TF_FORMAT_MAX + 1);
8218
ut_a(format_name != NULL);
8220
/* The format name can contain the format id itself instead of
8221
the name and we check for that. */
8222
format_id = (uint) strtoul(format_name, &endp, 10);
8224
/* Check for valid parse. */
8225
if (*endp == '\0' && *format_name != '\0') {
8227
if (format_id <= DICT_TF_FORMAT_MAX) {
8233
for (format_id = 0; format_id <= DICT_TF_FORMAT_MAX;
8237
name = trx_sys_file_format_id_to_name(format_id);
8239
if (!innobase_strcasecmp(format_name, name)) {
8246
return(DICT_TF_FORMAT_MAX + 1);
9003
8249
/************************************************************//**
9004
8250
Validate the file format check value, is it one of "on" or "off",
9005
8251
as a side effect it sets the srv_check_file_format_at_startup variable.
9006
@return true if config value one of "on" or "off" */
8252
@return true if config value one of "on" or "off" */
9009
8255
innobase_file_format_check_on_off(
9010
8256
/*==============================*/
9011
const char* format_check) /*!< in: parameter value */
8257
const char* format_check) /*!< in: parameter value */
9015
if (!innobase_strcasecmp(format_check, "off")) {
9017
/* Set the value to disable checking. */
9018
srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
9020
} else if (!innobase_strcasecmp(format_check, "on")) {
9022
/* Set the value to the lowest supported format. */
9023
srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
8261
if (!innobase_strcasecmp(format_check, "off")) {
8263
/* Set the value to disable checking. */
8264
srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
8266
} else if (!innobase_strcasecmp(format_check, "on")) {
8268
/* Set the value to the lowest supported format. */
8269
srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
9031
8277
/************************************************************//**
9032
8278
Validate the file format check config parameters, as a side effect it
9033
8279
sets the srv_check_file_format_at_startup variable.
9034
@return the format_id if valid config value, otherwise, return -1 */
8280
@return true if valid config value */
9037
innobase_file_format_validate_and_set(
8283
innobase_file_format_check_validate(
9038
8284
/*================================*/
9039
const char* format_check) /*!< in: parameter value */
8285
const char* format_check) /*!< in: parameter value */
9043
format_id = innobase_file_format_name_lookup(format_check);
9045
if (format_id < DICT_TF_FORMAT_MAX + 1) {
9046
srv_check_file_format_at_startup = format_id;
9047
return((int) format_id);
8290
format_id = innobase_file_format_name_lookup(format_check);
8292
if (format_id < DICT_TF_FORMAT_MAX + 1) {
8293
srv_check_file_format_at_startup = format_id;
9053
8301
/*************************************************************//**
9054
8302
Check if it is a valid file format. This function is registered as
9055
8303
a callback with MySQL.
9056
@return 0 for valid file format */
8304
@return 0 for valid file format */
9059
8307
innodb_file_format_name_validate(
9060
8308
/*=============================*/
9061
Session* , /*!< in: thread handle */
9062
drizzle_sys_var* , /*!< in: pointer to system
9064
void* save, /*!< out: immediate result
9065
for update function */
9066
drizzle_value* value) /*!< in: incoming string */
8309
Session* , /*!< in: thread handle */
8310
drizzle_sys_var* , /*!< in: pointer to system
8312
void* save, /*!< out: immediate result
8313
for update function */
8314
drizzle_value* value) /*!< in: incoming string */
9068
const char* file_format_input;
9069
char buff[STRING_BUFFER_USUAL_SIZE];
9070
int len = sizeof(buff);
9073
ut_a(value != NULL);
9075
file_format_input = value->val_str(value, buff, &len);
9077
if (file_format_input != NULL) {
9080
format_id = innobase_file_format_name_lookup(
9083
if (format_id <= DICT_TF_FORMAT_MAX) {
9084
/* Save a pointer to the name in the
9085
'file_format_name_map' constant array. */
9086
*static_cast<const char**>(save) =
9087
trx_sys_file_format_id_to_name(format_id);
9093
*static_cast<const char**>(save) = NULL;
8316
const char* file_format_input;
8317
char buff[STRING_BUFFER_USUAL_SIZE];
8318
int len = sizeof(buff);
8321
ut_a(value != NULL);
8323
file_format_input = value->val_str(value, buff, &len);
8325
if (file_format_input != NULL) {
8328
format_id = innobase_file_format_name_lookup(
8331
if (format_id <= DICT_TF_FORMAT_MAX) {
8333
*static_cast<const char**>(save) = file_format_input;
8338
*static_cast<const char**>(save) = NULL;
9097
8342
/****************************************************************//**
9577
8813
static DRIZZLE_SYSVAR_STR(change_buffering, innobase_change_buffering,
9578
8814
PLUGIN_VAR_RQCMDARG,
9579
8815
"Buffer changes to reduce random access: "
9580
"OFF, ON, none, inserts.",
8816
"OFF, ON, inserting, deleting, changing, or purging.",
9581
8817
innodb_change_buffering_validate,
9582
8818
innodb_change_buffering_update, NULL);
9584
8820
static DRIZZLE_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
9585
8821
PLUGIN_VAR_RQCMDARG,
9586
"Number of pages that must be accessed sequentially for InnoDB to "
8822
"Number of pages that must be accessed sequentially for InnoDB to"
9587
8823
"trigger a readahead.",
9588
8824
NULL, NULL, 56, 0, 64, 0);
9590
static void init_options(drizzled::module::option_context &context)
9592
context("disable-checksums",
9593
"Disable InnoDB checksums validation.");
9594
context("data-home-dir",
9595
po::value<string>(),
9596
"The common part for InnoDB table spaces.");
9597
context("disable-doublewrite",
9598
"Disable InnoDB doublewrite buffer.");
9599
context("io-capacity",
9600
po::value<unsigned long>(&srv_io_capacity)->default_value(200),
9601
"Number of IOPs the server can do. Tunes the background IO rate");
9602
context("fast-shutdown",
9603
po::value<unsigned long>(&innobase_fast_shutdown)->default_value(1),
9604
"Speeds up the shutdown process of the InnoDB storage engine. Possible values are 0, 1 (faster) or 2 (fastest - crash-like).");
9605
context("file-per-table",
9606
po::value<bool>(&srv_file_per_table)->default_value(false)->zero_tokens(),
9607
"Stores each InnoDB table to an .ibd file in the database dir.");
9608
context("file-format",
9609
po::value<string>()->default_value("Antelope"),
9610
"File format to use for new tables in .ibd files.");
9611
context("file-format-check",
9612
po::value<string>()->default_value("on"),
9613
"The highest file format in the tablespace.");
9614
context("flush-log-at-trx-commit",
9615
po::value<unsigned long>(&srv_flush_log_at_trx_commit)->default_value(1),
9616
"Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second).");
9617
context("flush-method",
9618
po::value<string>(),
9619
"With which method to flush data.");
9620
#ifdef UNIV_LOG_ARCHIVE
9621
context("log-arch-dir",
9622
po::value<string>(),
9623
"Where full logs should be archived.");
9624
context("log-archive",
9625
po::value<bool>(&innobase_log_archive)->default_value(false)->zero_tokens(),
9626
"Set to 1 if you want to have logs archived.");
9627
#endif /* UNIV_LOG_ARCHIVE */
9628
context("log-group-home-dir",
9629
po::value<string>(),
9630
"Path to InnoDB log files.");
9631
context("max-dirty-pages-pct",
9632
po::value<unsigned long>(&srv_max_buf_pool_modified_pct)->default_value(75),
9633
"Percentage of dirty pages allowed in bufferpool.");
9634
context("disable-adaptive-flushing",
9635
"Do not attempt flushing dirty pages to avoid IO bursts at checkpoints.");
9636
context("max-purge-lag",
9637
po::value<unsigned long>(&srv_max_purge_lag)->default_value(0),
9638
"Desired maximum length of the purge queue (0 = no limit)");
9639
context("status-file",
9640
po::value<bool>(&innobase_create_status_file)->default_value(false)->zero_tokens(),
9641
"Enable SHOW INNODB STATUS output in the innodb_status.<pid> file");
9642
context("disable-stats-on-metadata",
9643
"Disable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)");
9644
context("stats-sample-pages",
9645
po::value<uint64_t>(&srv_stats_sample_pages)->default_value(8),
9646
"The number of index pages to sample when calculating statistics (default 8)");
9647
context("disable-adaptive-hash-index",
9648
"Enable InnoDB adaptive hash index (enabled by default)");
9649
context("replication-delay",
9650
po::value<unsigned long>(&srv_replication_delay)->default_value(0),
9651
"Replication thread delay (ms) on the slave server if innodb_thread_concurrency is reached (0 by default)");
9652
context("additional-mem-pool-size",
9653
po::value<long>(&innobase_additional_mem_pool_size)->default_value(8*1024*1024L),
9654
"Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.");
9655
context("autoextend-increment",
9656
po::value<uint32_t>(&srv_auto_extend_increment)->default_value(8L),
9657
"Data file autoextend increment in megabytes");
9658
context("buffer-pool-size",
9659
po::value<int64_t>(&innobase_buffer_pool_size)->default_value(128*1024*1024L),
9660
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.");
9661
context("commit-concurrency",
9662
po::value<unsigned long>(&innobase_commit_concurrency)->default_value(0),
9663
"Helps in performance tuning in heavily concurrent environments.");
9664
context("concurrency-tickets",
9665
po::value<unsigned long>(&srv_n_free_tickets_to_enter)->default_value(500L),
9666
"Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket");
9667
context("read-io-threads",
9668
po::value<unsigned long>(&innobase_read_io_threads)->default_value(4),
9669
"Number of background read I/O threads in InnoDB.");
9670
context("write-io-threads",
9671
po::value<unsigned long>(&innobase_write_io_threads)->default_value(4),
9672
"Number of background write I/O threads in InnoDB.");
9673
context("force-recovery",
9674
po::value<long>(&innobase_force_recovery)->default_value(0),
9675
"Helps to save your data in case the disk image of the database becomes corrupt.");
9676
context("log-buffer-size",
9677
po::value<long>(&innobase_log_buffer_size)->default_value(8*1024*1024L),
9678
"The size of the buffer which InnoDB uses to write log to the log files on disk.");
9679
context("log-file-size",
9680
po::value<int64_t>(&innobase_log_file_size)->default_value(20*1024*1024L),
9681
"The size of the buffer which InnoDB uses to write log to the log files on disk.");
9682
context("log-files-in-group",
9683
po::value<long>(&innobase_log_files_in_group)->default_value(2),
9684
"Number of log files in the log group. InnoDB writes to the files in a circular fashion.");
9685
context("mirrored-log-groups",
9686
po::value<long>(&innobase_mirrored_log_groups)->default_value(1),
9687
"Number of identical copies of log groups we keep for the database. Currently this should be set to 1.");
9688
context("open-files",
9689
po::value<long>(&innobase_open_files)->default_value(300L),
9690
"How many files at the maximum InnoDB keeps open at the same time.");
9691
context("sync-spin-loops",
9692
po::value<unsigned long>(&srv_n_spin_wait_rounds)->default_value(30L),
9693
"Count of spin-loop rounds in InnoDB mutexes (30 by default)");
9694
context("spin-wait-delay",
9695
po::value<unsigned long>(&srv_spin_wait_delay)->default_value(6L),
9696
"Maximum delay between polling for a spin lock (6 by default)");
9697
context("thread-concurrency",
9698
po::value<unsigned long>(&srv_thread_concurrency)->default_value(0),
9699
"Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.");
9700
context("thread-sleep-delay",
9701
po::value<unsigned long>(&srv_thread_sleep_delay)->default_value(10000L),
9702
"Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep");
9703
context("data-file-path",
9704
po::value<string>(),
9705
"Path to individual files and their sizes.");
9707
po::value<string>()->default_value(INNODB_VERSION_STR),
9709
context("use-internal-malloc",
9710
"Use InnoDB's internal memory allocator instal of the OS memory allocator.");
9711
context("change-buffering",
9712
po::value<string>(),
9713
"Buffer changes to reduce random access: OFF, ON, inserting, deleting, changing, or purging.");
9714
context("read-ahead-threshold",
9715
po::value<unsigned long>(&srv_read_ahead_threshold)->default_value(56),
9716
"Number of pages that must be accessed sequentially for InnoDB to trigger a readahead.");
9717
context("disable-xa",
9718
"Disable InnoDB support for the XA two-phase commit");
9719
context("disable-table-locks",
9720
"Disable InnoDB locking in LOCK TABLES");
9721
context("strict-mode",
9722
po::value<bool>()->default_value(false)->zero_tokens(),
9723
"Use strict mode when evaluating create options.");
9724
context("lock-wait-timeout",
9725
po::value<unsigned long>()->default_value(50),
9726
"Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout.");
9729
8826
static drizzle_sys_var* innobase_system_variables[]= {
9730
8827
DRIZZLE_SYSVAR(additional_mem_pool_size),
9731
8828
DRIZZLE_SYSVAR(autoextend_increment),
9831
8932
innobase_commit_concurrency_init_default(void)
9832
8933
/*==========================================*/
9834
DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
9835
= innobase_commit_concurrency;
9838
/***********************************************************************
9839
This function checks each index name for a table against reserved
9840
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
9841
this function pushes an warning message to the client, and returns true. */
9842
extern "C" UNIV_INTERN
9844
innobase_index_name_is_reserved(
9845
/*============================*/
9846
/* out: true if an index name
9847
matches the reserved name */
9848
const trx_t* trx, /* in: InnoDB transaction handle */
9849
const KeyInfo* key_info, /* in: Indexes to be created */
9850
ulint num_of_keys) /* in: Number of indexes to
9854
uint key_num; /* index number */
9856
for (key_num = 0; key_num < num_of_keys; key_num++) {
9857
key = &key_info[key_num];
9859
if (innobase_strcasecmp(key->name,
9860
innobase_index_reserve_name) == 0) {
9861
/* Push warning to drizzle */
9862
push_warning_printf((Session*)trx->mysql_thd,
9863
DRIZZLE_ERROR::WARN_LEVEL_WARN,
9864
ER_WRONG_NAME_FOR_INDEX,
9865
"Cannot Create Index with name "
9866
"'%s'. The name is reserved "
9867
"for the system default primary "
9869
innobase_index_reserve_name);
9871
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
9872
innobase_index_reserve_name);
8935
DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
8936
= innobase_commit_concurrency;
9881
8939
#ifdef UNIV_COMPILE_TEST_FUNCS
9883
8941
typedef struct innobase_convert_name_test_struct {
9891
const char* expected;
8949
const char* expected;
9892
8950
} innobase_convert_name_test_t;
9895
8953
test_innobase_convert_name()
9900
innobase_convert_name_test_t test_input[] = {
9901
{buf, sizeof(buf), "abcd", 4, NULL, TRUE, "\"abcd\""},
9902
{buf, 7, "abcd", 4, NULL, TRUE, "\"abcd\""},
9903
{buf, 6, "abcd", 4, NULL, TRUE, "\"abcd\""},
9904
{buf, 5, "abcd", 4, NULL, TRUE, "\"abc\""},
9905
{buf, 4, "abcd", 4, NULL, TRUE, "\"ab\""},
9907
{buf, sizeof(buf), "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9908
{buf, 9, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9909
{buf, 8, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9910
{buf, 7, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9911
{buf, 6, "ab@0060cd", 9, NULL, TRUE, "\"ab`c\""},
9912
{buf, 5, "ab@0060cd", 9, NULL, TRUE, "\"ab`\""},
9913
{buf, 4, "ab@0060cd", 9, NULL, TRUE, "\"ab\""},
9915
{buf, sizeof(buf), "ab\"cd", 5, NULL, TRUE,
9916
"\"#mysql50#ab\"\"cd\""},
9917
{buf, 17, "ab\"cd", 5, NULL, TRUE,
9918
"\"#mysql50#ab\"\"cd\""},
9919
{buf, 16, "ab\"cd", 5, NULL, TRUE,
9920
"\"#mysql50#ab\"\"c\""},
9921
{buf, 15, "ab\"cd", 5, NULL, TRUE,
9922
"\"#mysql50#ab\"\"\""},
9923
{buf, 14, "ab\"cd", 5, NULL, TRUE,
9925
{buf, 13, "ab\"cd", 5, NULL, TRUE,
9927
{buf, 12, "ab\"cd", 5, NULL, TRUE,
9929
{buf, 11, "ab\"cd", 5, NULL, TRUE,
9931
{buf, 10, "ab\"cd", 5, NULL, TRUE,
9934
{buf, sizeof(buf), "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
9935
{buf, 9, "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
9936
{buf, 8, "ab/cd", 5, NULL, TRUE, "\"ab\".\"c\""},
9937
{buf, 7, "ab/cd", 5, NULL, TRUE, "\"ab\".\"\""},
9938
{buf, 6, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
9939
{buf, 5, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
9940
{buf, 4, "ab/cd", 5, NULL, TRUE, "\"ab\""},
9941
{buf, 3, "ab/cd", 5, NULL, TRUE, "\"a\""},
9942
{buf, 2, "ab/cd", 5, NULL, TRUE, "\"\""},
9943
/* XXX probably "" is a better result in this case
9944
{buf, 1, "ab/cd", 5, NULL, TRUE, "."},
9946
{buf, 0, "ab/cd", 5, NULL, TRUE, ""},
9949
for (i = 0; i < sizeof(test_input) / sizeof(test_input[0]); i++) {
9955
fprintf(stderr, "TESTING %lu, %s, %lu, %s\n",
9956
test_input[i].buflen,
9958
test_input[i].idlen,
9959
test_input[i].expected);
9961
end = innobase_convert_name(
9963
test_input[i].buflen,
9965
test_input[i].idlen,
9966
test_input[i].session,
9967
test_input[i].file_id);
9969
res_len = (size_t) (end - test_input[i].buf);
9971
if (res_len != strlen(test_input[i].expected)) {
9973
fprintf(stderr, "unexpected len of the result: %u, "
9974
"expected: %u\n", (unsigned) res_len,
9975
(unsigned) strlen(test_input[i].expected));
9979
if (memcmp(test_input[i].buf,
9980
test_input[i].expected,
9981
strlen(test_input[i].expected)) != 0
9984
fprintf(stderr, "unexpected result: %.*s, "
9985
"expected: %s\n", (int) res_len,
9987
test_input[i].expected);
9992
fprintf(stderr, "OK: res: %.*s\n\n", (int) res_len,
9995
fprintf(stderr, "FAILED\n\n");
8958
innobase_convert_name_test_t test_input[] = {
8959
{buf, sizeof(buf), "abcd", 4, NULL, TRUE, "\"abcd\""},
8960
{buf, 7, "abcd", 4, NULL, TRUE, "\"abcd\""},
8961
{buf, 6, "abcd", 4, NULL, TRUE, "\"abcd\""},
8962
{buf, 5, "abcd", 4, NULL, TRUE, "\"abc\""},
8963
{buf, 4, "abcd", 4, NULL, TRUE, "\"ab\""},
8965
{buf, sizeof(buf), "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8966
{buf, 9, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8967
{buf, 8, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8968
{buf, 7, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8969
{buf, 6, "ab@0060cd", 9, NULL, TRUE, "\"ab`c\""},
8970
{buf, 5, "ab@0060cd", 9, NULL, TRUE, "\"ab`\""},
8971
{buf, 4, "ab@0060cd", 9, NULL, TRUE, "\"ab\""},
8973
{buf, sizeof(buf), "ab\"cd", 5, NULL, TRUE,
8974
"\"#mysql50#ab\"\"cd\""},
8975
{buf, 17, "ab\"cd", 5, NULL, TRUE,
8976
"\"#mysql50#ab\"\"cd\""},
8977
{buf, 16, "ab\"cd", 5, NULL, TRUE,
8978
"\"#mysql50#ab\"\"c\""},
8979
{buf, 15, "ab\"cd", 5, NULL, TRUE,
8980
"\"#mysql50#ab\"\"\""},
8981
{buf, 14, "ab\"cd", 5, NULL, TRUE,
8983
{buf, 13, "ab\"cd", 5, NULL, TRUE,
8985
{buf, 12, "ab\"cd", 5, NULL, TRUE,
8987
{buf, 11, "ab\"cd", 5, NULL, TRUE,
8989
{buf, 10, "ab\"cd", 5, NULL, TRUE,
8992
{buf, sizeof(buf), "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
8993
{buf, 9, "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
8994
{buf, 8, "ab/cd", 5, NULL, TRUE, "\"ab\".\"c\""},
8995
{buf, 7, "ab/cd", 5, NULL, TRUE, "\"ab\".\"\""},
8996
{buf, 6, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
8997
{buf, 5, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
8998
{buf, 4, "ab/cd", 5, NULL, TRUE, "\"ab\""},
8999
{buf, 3, "ab/cd", 5, NULL, TRUE, "\"a\""},
9000
{buf, 2, "ab/cd", 5, NULL, TRUE, "\"\""},
9001
/* XXX probably "" is a better result in this case
9002
{buf, 1, "ab/cd", 5, NULL, TRUE, "."},
9004
{buf, 0, "ab/cd", 5, NULL, TRUE, ""},
9007
for (i = 0; i < sizeof(test_input) / sizeof(test_input[0]); i++) {
9013
fprintf(stderr, "TESTING %lu, %s, %lu, %s\n",
9014
test_input[i].buflen,
9016
test_input[i].idlen,
9017
test_input[i].expected);
9019
end = innobase_convert_name(
9021
test_input[i].buflen,
9023
test_input[i].idlen,
9024
test_input[i].session,
9025
test_input[i].file_id);
9027
res_len = (size_t) (end - test_input[i].buf);
9029
if (res_len != strlen(test_input[i].expected)) {
9031
fprintf(stderr, "unexpected len of the result: %u, "
9032
"expected: %u\n", (unsigned) res_len,
9033
(unsigned) strlen(test_input[i].expected));
9037
if (memcmp(test_input[i].buf,
9038
test_input[i].expected,
9039
strlen(test_input[i].expected)) != 0
9042
fprintf(stderr, "unexpected result: %.*s, "
9043
"expected: %s\n", (int) res_len,
9045
test_input[i].expected);
9050
fprintf(stderr, "OK: res: %.*s\n\n", (int) res_len,
9053
fprintf(stderr, "FAILED\n\n");
10001
9059
#endif /* UNIV_COMPILE_TEST_FUNCS */