23
23
#pragma implementation // gcc: Class implementation
26
#include <drizzled/server_includes.h>
26
#include "mysql_priv.h"
27
27
#include "rpl_filter.h"
28
#include <drizzled/drizzled_error_messages.h>
28
#include <myisampack.h>
31
32
While we have legacy_db_type, we have this array to
39
40
#define BITMAP_STACKBUF_SIZE (128/8)
41
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
42
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0}, {NullS,0} };
43
44
/* number of entries in handlertons[] */
44
45
uint32_t total_ha= 0;
52
53
{ C_STRING_WITH_LEN("INNOBASE") }, { C_STRING_WITH_LEN("INNODB") },
53
54
{ C_STRING_WITH_LEN("HEAP") }, { C_STRING_WITH_LEN("MEMORY") },
57
58
const char *ha_row_type[] = {
61
62
const char *tx_isolation_names[] =
62
63
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
64
65
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
65
66
tx_isolation_names, NULL};
67
68
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
68
uint32_t known_extensions_id= 0;
69
uint known_extensions_id= 0;
114
115
/* my_strnncoll is a macro and gcc doesn't do early expansion of macro */
115
if (thd && !my_charset_utf8_general_ci.coll->strnncoll(&my_charset_utf8_general_ci,
116
(const unsigned char *)name->str, name->length,
117
(const unsigned char *)STRING_WITH_LEN("DEFAULT"), 0))
116
if (thd && !my_charset_latin1.coll->strnncoll(&my_charset_latin1,
117
(const uchar *)name->str, name->length,
118
(const uchar *)STRING_WITH_LEN("DEFAULT"), 0))
118
119
return ha_default_plugin(thd);
120
if ((plugin= my_plugin_lock_by_name(thd, name, DRIZZLE_STORAGE_ENGINE_PLUGIN)))
121
if ((plugin= my_plugin_lock_by_name(thd, name, MYSQL_STORAGE_ENGINE_PLUGIN)))
122
123
handlerton *hton= plugin_data(plugin, handlerton *);
123
124
if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
135
136
for (table_alias= sys_table_aliases; table_alias->str; table_alias+= 2)
137
if (!my_strnncoll(&my_charset_utf8_general_ci,
138
(const unsigned char *)name->str, name->length,
139
(const unsigned char *)table_alias->str, table_alias->length))
138
if (!my_strnncoll(&my_charset_latin1,
139
(const uchar *)name->str, name->length,
140
(const uchar *)table_alias->str, table_alias->length))
141
142
name= table_alias + 1;
303
311
/* Allocate a pointer array for the error message strings. */
304
312
if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
306
free((unsigned char*) errmsgs);
314
my_free((uchar*) errmsgs, MYF(0));
326
if (hton && plugin->plugin->deinit)
327
(void)plugin->plugin->deinit(hton);
335
hton->panic(hton, HA_PANIC_CLOSE);
329
free((unsigned char*)hton);
337
my_free((uchar*)hton, MYF(0));
345
353
structure. Apparently get_backup_engine was not NULL even though it was
348
memset(hton, 0, sizeof(hton));
356
bzero(hton, sizeof(hton));
349
357
/* Historical Requirement */
350
358
plugin->data= hton; // shortcut for the future
351
359
if (plugin->plugin->init)
353
361
if (plugin->plugin->init(hton))
355
sql_print_error(_("Plugin '%s' init function returned error."),
363
sql_print_error("Plugin '%s' init function returned error.",
356
364
plugin->name.str);
381
389
if (idx == (int) DB_TYPE_DEFAULT)
383
sql_print_warning(_("Too many storage engines!"));
391
sql_print_warning("Too many storage engines!");
386
394
if (hton->db_type != DB_TYPE_UNKNOWN)
387
sql_print_warning(_("Storage engine '%s' has conflicting typecode. "
388
"Assigning value %d."), plugin->plugin->name, idx);
395
sql_print_warning("Storage engine '%s' has conflicting typecode. "
396
"Assigning value %d.", plugin->plugin->name, idx);
389
397
hton->db_type= (enum legacy_db_type) idx;
391
399
installed_htons[hton->db_type]= hton;
409
417
"memory" hton which will be configurable longterm. We should be able to
410
418
remove partition and myisammrg.
412
if (strcmp(plugin->plugin->name, "MEMORY") == 0)
420
switch (hton->db_type) {
415
if (strcmp(plugin->plugin->name, "MyISAM") == 0)
416
425
myisam_hton= hton;
464
477
void ha_drop_database(char* path)
466
plugin_foreach(NULL, dropdb_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, path);
479
plugin_foreach(NULL, dropdb_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, path);
470
483
static bool closecon_handlerton(THD *thd, plugin_ref plugin,
471
void *unused __attribute__((unused)))
484
void *unused __attribute__((__unused__)))
473
486
handlerton *hton= plugin_data(plugin, handlerton *);
489
502
void ha_close_connection(THD* thd)
491
plugin_foreach(thd, closecon_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
504
plugin_foreach(thd, closecon_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0);
494
507
/* ========================================================================
764
777
to maintain atomicity: if CREATE TABLE .. SELECT failed,
765
778
the newly created table is deleted.
766
779
In addition, some DDL statements issue interim transaction
767
commits: e.g. ALTER Table issues a commit after data is copied
780
commits: e.g. ALTER TABLE issues a commit after data is copied
768
781
from the original table to the internal temporary table. Other
769
782
statements, e.g. CREATE TABLE ... SELECT do not always commit
771
784
And finally there is a group of DDL statements such as
772
RENAME/DROP Table that doesn't start a new transaction
785
RENAME/DROP TABLE that doesn't start a new transaction
773
786
and doesn't commit.
775
788
This diversity makes it hard to say what will happen if
857
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
870
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
858
871
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
859
872
ha_resolve_storage_engine_name(ht));
1145
1158
if (is_real_trans && thd->transaction.all.modified_non_trans_table &&
1146
1159
!thd->slave_thread && thd->killed != THD::KILL_CONNECTION)
1147
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1160
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1148
1161
ER_WARNING_NOT_COMPLETE_ROLLBACK,
1149
1162
ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
1222
1235
xaop.result= 1;
1224
1237
plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
1225
DRIZZLE_STORAGE_ENGINE_PLUGIN, &xaop);
1238
MYSQL_STORAGE_ENGINE_PLUGIN, &xaop);
1227
1240
return xaop.result;
1264
1277
while ((got= hton->recover(hton, info->list, info->len)) > 0 )
1266
sql_print_information(_("Found %d prepared transaction(s) in %s"),
1279
sql_print_information("Found %d prepared transaction(s) in %s",
1267
1280
got, ha_resolve_storage_engine_name(hton));
1268
1281
for (int i=0; i < got; i ++)
1282
1295
// recovery mode
1283
1296
if (info->commit_list ?
1284
hash_search(info->commit_list, (unsigned char *)&x, sizeof(x)) != 0 :
1297
hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 :
1285
1298
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
1287
1300
hton->commit_by_xid(hton, info->list+i);
1345
1358
plugin_foreach(NULL, xarecover_handlerton,
1346
DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1359
MYSQL_STORAGE_ENGINE_PLUGIN, &info);
1348
free((unsigned char*)info.list);
1361
my_free((uchar*)info.list, MYF(0));
1349
1362
if (info.found_foreign_xids)
1350
sql_print_warning(_("Found %d prepared XA transactions"),
1363
sql_print_warning("Found %d prepared XA transactions",
1351
1364
info.found_foreign_xids);
1352
1365
if (info.dry_run && info.found_my_xids)
1354
sql_print_error(_("Found %d prepared transactions! It means that drizzled "
1355
"was not shut down properly last time and critical "
1356
"recovery information (last binlog or %s file) was "
1357
"manually deleted after a crash. You have to start "
1358
"drizzled with the --tc-heuristic-recover switch to "
1359
"commit or rollback pending transactions."),
1367
sql_print_error("Found %d prepared transactions! It means that mysqld was "
1368
"not shut down properly last time and critical recovery "
1369
"information (last binlog or %s file) was manually deleted "
1370
"after a crash. You have to start mysqld with "
1371
"--tc-heuristic-recover switch to commit or rollback "
1372
"pending transactions.",
1360
1373
info.found_my_xids, opt_tc_log_file);
1363
1376
if (info.commit_list)
1364
sql_print_information(_("Crash recovery finished."));
1377
sql_print_information("Crash recovery finished.");
1434
1447
static bool release_temporary_latches(THD *thd, plugin_ref plugin,
1435
void *unused __attribute__((unused)))
1448
void *unused __attribute__((__unused__)))
1437
1450
handlerton *hton= plugin_data(plugin, handlerton *);
1446
1459
int ha_release_temporary_latches(THD *thd)
1448
plugin_foreach(thd, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1461
plugin_foreach(thd, release_temporary_latches, MYSQL_STORAGE_ENGINE_PLUGIN,
1471
1484
assert(ht->savepoint_set != 0);
1472
1485
if ((err= ht->savepoint_rollback(ht, thd,
1473
(unsigned char *)(sv+1)+ht->savepoint_offset)))
1486
(uchar *)(sv+1)+ht->savepoint_offset)))
1474
1487
{ // cannot happen
1475
1488
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1526
if ((err= ht->savepoint_set(ht, thd, (unsigned char *)(sv+1)+ht->savepoint_offset)))
1539
if ((err= ht->savepoint_set(ht, thd, (uchar *)(sv+1)+ht->savepoint_offset)))
1527
1540
{ // cannot happen
1528
1541
my_error(ER_GET_ERRNO, MYF(0), err);
1552
1565
if (!ht->savepoint_release)
1554
1567
if ((err= ht->savepoint_release(ht, thd,
1555
(unsigned char *)(sv+1) + ht->savepoint_offset)))
1568
(uchar *)(sv+1) + ht->savepoint_offset)))
1556
1569
{ // cannot happen
1557
1570
my_error(ER_GET_ERRNO, MYF(0), err);
1579
1592
bool warn= true;
1581
plugin_foreach(thd, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1594
plugin_foreach(thd, snapshot_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &warn);
1584
1597
Same idea as when one wants to CREATE TABLE in one engine which does not
1588
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1601
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1589
1602
"This MySQL server does not support any "
1590
1603
"consistent-read capable storage engine");
1595
static bool flush_handlerton(THD *thd __attribute__((unused)),
1608
static bool flush_handlerton(THD *thd __attribute__((__unused__)),
1596
1609
plugin_ref plugin,
1597
void *arg __attribute__((unused)))
1610
void *arg __attribute__((__unused__)))
1599
1612
handlerton *hton= plugin_data(plugin, handlerton *);
1600
1613
if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1609
1622
if (db_type == NULL)
1611
1624
if (plugin_foreach(NULL, flush_handlerton,
1612
DRIZZLE_STORAGE_ENGINE_PLUGIN, 0))
1625
MYSQL_STORAGE_ENGINE_PLUGIN, 0))
1649
1662
struct Ha_delete_table_error_handler: public Internal_error_handler
1652
virtual bool handle_error(uint32_t sql_errno,
1665
virtual bool handle_error(uint sql_errno,
1653
1666
const char *message,
1654
DRIZZLE_ERROR::enum_warning_level level,
1667
MYSQL_ERROR::enum_warning_level level,
1656
char buff[DRIZZLE_ERRMSG_SIZE];
1669
char buff[MYSQL_ERRMSG_SIZE];
1661
1674
Ha_delete_table_error_handler::
1662
handle_error(uint32_t sql_errno __attribute__((unused)),
1675
handle_error(uint sql_errno __attribute__((__unused__)),
1663
1676
const char *message,
1664
DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
1665
THD *thd __attribute__((unused)))
1677
MYSQL_ERROR::enum_warning_level level __attribute__((__unused__)),
1678
THD *thd __attribute__((__unused__)))
1667
1680
/* Grab the error message */
1668
1681
strmake(buff, message, sizeof(buff)-1);
1681
1694
char tmp_path[FN_REFLEN];
1684
1697
TABLE_SHARE dummy_share;
1686
memset(&dummy_table, 0, sizeof(dummy_table));
1687
memset(&dummy_share, 0, sizeof(dummy_share));
1699
bzero((char*) &dummy_table, sizeof(dummy_table));
1700
bzero((char*) &dummy_share, sizeof(dummy_share));
1688
1701
dummy_table.s= &dummy_share;
1690
/* DB_TYPE_UNKNOWN is used in ALTER Table when renaming only .frm files */
1703
/* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */
1691
1704
if (table_type == NULL ||
1692
1705
! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type)))
1693
1706
return(ENOENT);
1723
1736
XXX: should we convert *all* errors to warnings here?
1724
1737
What if the error is fatal?
1726
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
1739
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error,
1727
1740
ha_delete_table_error_handler.buff);
1741
1754
on this->table->mem_root and we will not be able to reclaim that memory
1742
1755
when the clone handler object is destroyed.
1744
if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1757
if (!(new_handler->ref= (uchar*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1746
1759
if (new_handler && !new_handler->ha_open(table,
1747
1760
table->s->normalized_path.str,
1749
1762
HA_OPEN_IGNORE_IF_LOCKED))
1750
1763
return new_handler;
1775
1788
Try O_RDONLY if cannot open as O_RDWR
1776
1789
Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
1778
int handler::ha_open(Table *table_arg, const char *name, int mode,
1791
int handler::ha_open(TABLE *table_arg, const char *name, int mode,
1779
1792
int test_if_locked)
1804
1817
(void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
1806
1819
/* ref is already allocated for us if we're called from handler::clone() */
1807
if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
1820
if (!ref && !(ref= (uchar*) alloc_root(&table->mem_root,
1808
1821
ALIGN_SIZE(ref_length)*2)))
1843
1856
This is never called for InnoDB tables, as these table types
1844
1857
has the HA_STATS_RECORDS_IS_EXACT set.
1846
int handler::read_first_row(unsigned char * buf, uint32_t primary_key)
1859
int handler::read_first_row(uchar * buf, uint primary_key)
1848
1861
register int error;
2031
2044
assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
2033
if ((nr= table->next_number_field->val_int()) != 0)
2046
if (((nr= table->next_number_field->val_int()) != 0) ||
2047
(table->auto_increment_field_not_null && (thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO)))
2036
2050
Update next_insert_id if we had already generated a value in this
2059
2073
handler::estimation_rows_to_insert was set by
2060
2074
handler::ha_start_bulk_insert(); if 0 it means "unknown".
2062
uint32_t nb_already_reserved_intervals=
2076
uint nb_already_reserved_intervals=
2063
2077
thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
2064
2078
uint64_t nb_desired_values;
2196
2210
@param first_value (OUT) the first value reserved by the handler
2197
2211
@param nb_reserved_values (OUT) how many values the handler reserved
2199
void handler::get_auto_increment(uint64_t offset __attribute__((unused)),
2200
uint64_t increment __attribute__((unused)),
2201
uint64_t nb_desired_values __attribute__((unused)),
2213
void handler::get_auto_increment(uint64_t offset __attribute__((__unused__)),
2214
uint64_t increment __attribute__((__unused__)),
2215
uint64_t nb_desired_values __attribute__((__unused__)),
2202
2216
uint64_t *first_value,
2203
2217
uint64_t *nb_reserved_values)
2225
unsigned char key[MAX_KEY_LENGTH];
2239
uchar key[MAX_KEY_LENGTH];
2226
2240
key_copy(key, table->record[0],
2227
2241
table->key_info + table->s->next_number_index,
2228
2242
table->s->next_number_key_offset);
2269
void handler::print_keydup_error(uint32_t key_nr, const char *msg)
2283
void handler::print_keydup_error(uint key_nr, const char *msg)
2271
2285
/* Write the duplicated key in the error message */
2272
2286
char key[MAX_KEY_LENGTH];
2283
2297
/* Table is opened and defined at this point */
2284
2298
key_unpack(&str,table,(uint) key_nr);
2285
uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint) strlen(msg);
2299
uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(msg);
2286
2300
if (str.length() >= max_length)
2288
2302
str.length(max_length-4);
2327
2341
case HA_ERR_FOUND_DUPP_KEY:
2329
uint32_t key_nr=get_dup_key(error);
2343
uint key_nr=get_dup_key(error);
2330
2344
if ((int) key_nr >= 0)
2332
2346
print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
2338
2352
case HA_ERR_FOREIGN_DUPLICATE_KEY:
2340
uint32_t key_nr= get_dup_key(error);
2354
uint key_nr= get_dup_key(error);
2341
2355
if ((int) key_nr >= 0)
2343
uint32_t max_length;
2344
2358
/* Write the key in the error message */
2345
2359
char key[MAX_KEY_LENGTH];
2346
2360
String str(key,sizeof(key),system_charset_info);
2347
2361
/* Table is opened and defined at this point */
2348
2362
key_unpack(&str,table,(uint) key_nr);
2349
max_length= (DRIZZLE_ERRMSG_SIZE-
2363
max_length= (MYSQL_ERRMSG_SIZE-
2350
2364
(uint) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
2351
2365
if (str.length() >= max_length)
2439
2453
case HA_ERR_DROP_INDEX_FK:
2441
2455
const char *ptr= "???";
2442
uint32_t key_nr= get_dup_key(error);
2456
uint key_nr= get_dup_key(error);
2443
2457
if ((int) key_nr >= 0)
2444
2458
ptr= table->key_info[key_nr].name;
2445
2459
my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
2497
2511
Returns true if this is a temporary error
2499
bool handler::get_error_message(int error __attribute__((unused)),
2500
String* buf __attribute__((unused)))
2513
bool handler::get_error_message(int error __attribute__((__unused__)),
2514
String* buf __attribute__((__unused__)))
2522
2536
if (!keypart->fieldnr)
2524
2538
Field *field= table->field[keypart->fieldnr-1];
2525
if (field->type() == DRIZZLE_TYPE_BLOB)
2539
if (field->type() == MYSQL_TYPE_BLOB)
2527
2541
if (check_opt->sql_flags & TT_FOR_UPGRADE)
2528
2542
check_opt->flags= T_MEDIUM;
2554
2568
update frm version for temporary tables as this code doesn't support
2555
2569
temporary tables.
2557
if (table->s->mysql_version == DRIZZLE_VERSION_ID)
2571
if (table->s->mysql_version == MYSQL_VERSION_ID)
2560
strxmov(path, table->s->normalized_path.str, reg_ext, NULL);
2574
strxmov(path, table->s->normalized_path.str, reg_ext, NullS);
2562
2576
if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
2564
unsigned char version[4];
2565
2579
char *key= table->s->table_cache_key.str;
2566
uint32_t key_length= table->s->table_cache_key.length;
2580
uint key_length= table->s->table_cache_key.length;
2568
2582
HASH_SEARCH_STATE state;
2570
int4store(version, DRIZZLE_VERSION_ID);
2584
int4store(version, MYSQL_VERSION_ID);
2572
if (pwrite(file, (unsigned char*)version, 4, 51L) == 0)
2586
if (pwrite(file, (uchar*)version, 4, 51L) == 0)
2578
for (entry=(Table*) hash_first(&open_cache,(unsigned char*) key,key_length, &state);
2592
for (entry=(TABLE*) hash_first(&open_cache,(uchar*) key,key_length, &state);
2580
entry= (Table*) hash_next(&open_cache,(unsigned char*) key,key_length, &state))
2581
entry->s->mysql_version= DRIZZLE_VERSION_ID;
2594
entry= (TABLE*) hash_next(&open_cache,(uchar*) key,key_length, &state))
2595
entry->s->mysql_version= MYSQL_VERSION_ID;
2585
my_close(file,MYF(MY_WME));
2599
VOID(my_close(file,MYF(MY_WME)));
2586
2600
return(result);
2593
2607
key if error because of duplicated keys
2595
uint32_t handler::get_dup_key(int error)
2609
uint handler::get_dup_key(int error)
2597
2611
table->file->errkey = (uint) -1;
2598
2612
if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
2685
if ((table->s->mysql_version >= DRIZZLE_VERSION_ID) &&
2699
if ((table->s->mysql_version >= MYSQL_VERSION_ID) &&
2686
2700
(check_opt->sql_flags & TT_FOR_UPGRADE))
2689
if (table->s->mysql_version < DRIZZLE_VERSION_ID)
2703
if (table->s->mysql_version < MYSQL_VERSION_ID)
2691
2705
if ((error= check_old_types()))
2983
2997
Tell the storage engine that it is allowed to "disable transaction" in the
2984
2998
handler. It is a hint that ACID is not required - it is used in NDB for
2985
ALTER Table, for example, when data are copied to temporary table.
2999
ALTER TABLE, for example, when data are copied to temporary table.
2986
3000
A storage engine may treat this hint any way it likes. NDB for example
2987
3001
starts to commit every now and then automatically.
2988
3002
This hint can be safely ignored.
3008
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
3022
int handler::index_next_same(uchar *buf, const uchar *key, uint keylen)
3011
3025
if (!(error=index_next(buf)))
3013
3027
my_ptrdiff_t ptrdiff= buf - table->record[0];
3014
unsigned char *save_record_0= NULL;
3028
uchar *save_record_0= NULL;
3015
3029
KEY *key_info= NULL;
3016
3030
KEY_PART_INFO *key_part;
3017
3031
KEY_PART_INFO *key_part_end= NULL;
3088
3102
if (update_create_info)
3089
table.updateCreateInfo(create_info);
3103
update_create_info_from_table(create_info, &table);
3091
3105
name= check_lowercase_names(table.file, share.path.str, name_buff);
3093
3107
error= table.file->ha_create(name, &table, create_info);
3094
closefrm(&table, 0);
3108
VOID(closefrm(&table, 0));
3097
strxmov(name_buff, db, ".", table_name, NULL);
3111
strxmov(name_buff, db, ".", table_name, NullS);
3098
3112
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
3118
3132
int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
3121
unsigned char *frmblob;
3123
3137
char path[FN_REFLEN];
3124
3138
HA_CREATE_INFO create_info;
3126
3140
TABLE_SHARE share;
3128
memset(&create_info, 0, sizeof(create_info));
3142
bzero((uchar*) &create_info,sizeof(create_info));
3129
3143
if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
3131
3145
/* Table could not be discovered and thus not created */
3140
3154
build_table_filename(path, FN_REFLEN-1, db, name, "", 0);
3141
3155
// Save the frm file
3142
3156
error= writefrm(path, frmblob, frmlen);
3157
my_free(frmblob, MYF(0));
3158
table.updateCreateInfo(&create_info);
3172
update_create_info_from_table(&create_info, &table);
3159
3173
create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
3161
3175
check_lowercase_names(table.file, path, path);
3162
3176
error=table.file->ha_create(path, &table, &create_info);
3163
closefrm(&table, 1);
3177
VOID(closefrm(&table, 1));
3165
3179
return(error != 0);
3186
3200
Init a key cache if it has not been initied before.
3188
int ha_init_key_cache(const char *name __attribute__((unused)),
3202
int ha_init_key_cache(const char *name __attribute__((__unused__)),
3189
3203
KEY_CACHE *key_cache)
3191
3205
if (!key_cache->key_cache_inited)
3193
3207
pthread_mutex_lock(&LOCK_global_system_variables);
3194
3208
uint32_t tmp_buff_size= (uint32_t) key_cache->param_buff_size;
3195
uint32_t tmp_block_size= (uint) key_cache->param_block_size;
3196
uint32_t division_limit= key_cache->param_division_limit;
3197
uint32_t age_threshold= key_cache->param_age_threshold;
3209
uint tmp_block_size= (uint) key_cache->param_block_size;
3210
uint division_limit= key_cache->param_division_limit;
3211
uint age_threshold= key_cache->param_age_threshold;
3198
3212
pthread_mutex_unlock(&LOCK_global_system_variables);
3199
3213
return(!init_key_cache(key_cache,
3200
3214
tmp_block_size,
3215
3229
pthread_mutex_lock(&LOCK_global_system_variables);
3216
3230
long tmp_buff_size= (long) key_cache->param_buff_size;
3217
3231
long tmp_block_size= (long) key_cache->param_block_size;
3218
uint32_t division_limit= key_cache->param_division_limit;
3219
uint32_t age_threshold= key_cache->param_age_threshold;
3232
uint division_limit= key_cache->param_division_limit;
3233
uint age_threshold= key_cache->param_age_threshold;
3220
3234
pthread_mutex_unlock(&LOCK_global_system_variables);
3221
3235
return(!resize_key_cache(key_cache, tmp_block_size,
3234
3248
if (key_cache->key_cache_inited)
3236
3250
pthread_mutex_lock(&LOCK_global_system_variables);
3237
uint32_t division_limit= key_cache->param_division_limit;
3238
uint32_t age_threshold= key_cache->param_age_threshold;
3251
uint division_limit= key_cache->param_division_limit;
3252
uint age_threshold= key_cache->param_age_threshold;
3239
3253
pthread_mutex_unlock(&LOCK_global_system_variables);
3240
3254
change_key_cache_param(key_cache, division_limit, age_threshold);
3297
3311
int ha_discover(THD *thd, const char *db, const char *name,
3298
unsigned char **frmblob, size_t *frmlen)
3312
uchar **frmblob, size_t *frmlen)
3300
3314
int error= -1; // Table does not exist in any handler
3301
3315
st_discover_args args= {db, name, frmblob, frmlen};
3306
3320
if (plugin_foreach(thd, discover_handlerton,
3307
DRIZZLE_STORAGE_ENGINE_PLUGIN, &args))
3321
MYSQL_STORAGE_ENGINE_PLUGIN, &args))
3366
3380
st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE};
3367
3381
plugin_foreach(thd, table_exists_in_engine_handlerton,
3368
DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
3382
MYSQL_STORAGE_ENGINE_PLUGIN, &args);
3369
3383
return(args.err);
3390
3404
Estimated cost of 'index only' scan
3393
double handler::index_only_read_time(uint32_t keynr, double records)
3407
double handler::index_only_read_time(uint keynr, double records)
3395
3409
double read_time;
3396
uint32_t keys_per_block= (stats.block_size/2/
3410
uint keys_per_block= (stats.block_size/2/
3397
3411
(table->key_info[keynr].key_length + ref_length) + 1);
3398
3412
read_time=((double) (records + keys_per_block-1) /
3399
3413
(double) keys_per_block);
3440
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3454
handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
3441
3455
void *seq_init_param,
3442
uint32_t n_ranges_arg __attribute__((unused)),
3443
uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3456
uint n_ranges_arg __attribute__((__unused__)),
3457
uint *bufsz, uint *flags, COST_VECT *cost)
3445
3459
KEY_MULTI_RANGE range;
3446
3460
range_seq_t seq_it;
3447
3461
ha_rows rows, total_rows= 0;
3448
uint32_t n_ranges=0;
3449
3463
THD *thd= current_thd;
3451
3465
/* Default MRR implementation doesn't need buffer */
3528
3542
other Error or can't perform the requested scan
3531
int handler::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
3532
uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3545
int handler::multi_range_read_info(uint keyno, uint n_ranges, uint n_rows,
3546
uint *bufsz, uint *flags, COST_VECT *cost)
3534
3548
*bufsz= 0; /* Default implementation doesn't need a buffer */
3592
3606
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3593
uint32_t n_ranges, uint32_t mode,
3594
HANDLER_BUFFER *buf __attribute__((unused)))
3607
uint n_ranges, uint mode,
3608
HANDLER_BUFFER *buf __attribute__((__unused__)))
3596
3610
mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
3597
3611
mrr_funcs= *seq_funcs;
3693
3707
int DsMrr_impl::dsmrr_init(handler *h, KEY *key,
3694
3708
RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3695
uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
3709
uint n_ranges, uint mode, HANDLER_BUFFER *buf)
3699
3713
Item *pushed_cond= NULL;
3700
3714
handler *new_h2;
3701
3715
keyno= h->active_index;
3788
static int rowid_cmp(void *h, unsigned char *a, unsigned char *b)
3802
static int rowid_cmp(void *h, uchar *a, uchar *b)
3790
3804
return ((handler*)h)->cmp_ref(a, b);
3808
3822
@retval other Error
3811
int DsMrr_impl::dsmrr_fill_buffer(handler *unused __attribute__((unused)))
3825
int DsMrr_impl::dsmrr_fill_buffer(handler *unused __attribute__((__unused__)))
3813
3827
char *range_info;
3816
3830
rowids_buf_cur= rowids_buf;
3817
3831
while ((rowids_buf_cur < rowids_buf_end) &&
3834
3848
dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
3836
3850
/* Sort the buffer contents by rowid */
3837
uint32_t elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3838
uint32_t n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
3851
uint elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3852
uint n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
3840
3854
my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
3894
3908
DS-MRR implementation: multi_range_read_info() function
3896
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
3897
uint32_t *flags, COST_VECT *cost)
3910
int DsMrr_impl::dsmrr_info(uint keyno, uint n_ranges, uint rows, uint *bufsz,
3911
uint *flags, COST_VECT *cost)
3900
uint32_t def_flags= *flags;
3901
uint32_t def_bufsz= *bufsz;
3914
uint def_flags= *flags;
3915
uint def_bufsz= *bufsz;
3903
3917
/* Get cost/flags/mem_usage of default MRR implementation */
3904
3918
res= h->handler::multi_range_read_info(keyno, n_ranges, rows, &def_bufsz,
3920
3934
DS-MRR Implementation: multi_range_read_info_const() function
3923
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3924
void *seq_init_param, uint32_t n_ranges,
3925
uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3937
ha_rows DsMrr_impl::dsmrr_info_const(uint keyno, RANGE_SEQ_IF *seq,
3938
void *seq_init_param, uint n_ranges,
3939
uint *bufsz, uint *flags, COST_VECT *cost)
3928
uint32_t def_flags= *flags;
3929
uint32_t def_bufsz= *bufsz;
3942
uint def_flags= *flags;
3943
uint def_bufsz= *bufsz;
3930
3944
/* Get cost/flags/mem_usage of default MRR implementation */
3931
3945
rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
3932
3946
n_ranges, &def_bufsz,
3974
3988
@retval false No
3977
bool DsMrr_impl::key_uses_partial_cols(uint32_t keyno)
3991
bool DsMrr_impl::key_uses_partial_cols(uint keyno)
3979
3993
KEY_PART_INFO *kp= table->key_info[keyno].key_part;
3980
3994
KEY_PART_INFO *kp_end= kp + table->key_info[keyno].key_parts;
4010
4024
@retval false DS-MRR implementation should be used
4013
bool DsMrr_impl::choose_mrr_impl(uint32_t keyno, ha_rows rows, uint32_t *flags,
4014
uint32_t *bufsz, COST_VECT *cost)
4027
bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
4028
uint *bufsz, COST_VECT *cost)
4016
4030
COST_VECT dsmrr_cost;
4030
uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
4044
uint add_len= table->key_info[keyno].key_length + h->ref_length;
4031
4045
*bufsz -= add_len;
4032
4046
if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
4077
4091
for even 1 rowid)
4080
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint32_t keynr, ha_rows rows, uint32_t flags,
4081
uint32_t *buffer_size, COST_VECT *cost)
4094
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
4095
uint *buffer_size, COST_VECT *cost)
4083
4097
uint32_t max_buff_entries, elem_size;
4084
4098
ha_rows rows_in_full_step, rows_in_last_step;
4085
uint32_t n_full_steps;
4086
4100
double index_read_cost;
4088
4102
elem_size= h->ref_length + sizeof(void*) * (!test(flags & HA_MRR_NO_ASSOCIATION));
4114
*buffer_size= cmax((ulong)*buffer_size,
4128
*buffer_size= max(*buffer_size,
4115
4129
(size_t)(1.2*rows_in_last_step) * elem_size +
4116
4130
h->ref_length + table->key_info[keynr].key_length);
4207
4221
@param cost OUT The cost.
4210
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
4224
void get_sweep_read_cost(TABLE *table, ha_rows nrows, bool interrupted,
4211
4225
COST_VECT *cost)
4263
4277
int handler::read_range_first(const key_range *start_key,
4264
4278
const key_range *end_key,
4265
4279
bool eq_range_arg,
4266
bool sorted __attribute__((unused)))
4280
bool sorted __attribute__((__unused__)))
4371
int handler::index_read_idx_map(unsigned char * buf, uint32_t index, const unsigned char * key,
4385
int handler::index_read_idx_map(uchar * buf, uint index, const uchar * key,
4372
4386
key_part_map keypart_map,
4373
4387
enum ha_rkey_function find_flag)
4433
4447
known_extensions_id= mysys_usage_id;
4435
4449
plugin_foreach(NULL, exts_handlerton,
4436
DRIZZLE_STORAGE_ENGINE_PLUGIN, &found_exts);
4450
MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts);
4438
4452
ext= (const char **) my_once_alloc(sizeof(char *)*
4439
4453
(found_exts.elements+1),
4455
static bool stat_print(THD *thd, const char *type, uint32_t type_len,
4456
const char *file, uint32_t file_len,
4457
const char *status, uint32_t status_len)
4469
static bool stat_print(THD *thd, const char *type, uint type_len,
4470
const char *file, uint file_len,
4471
const char *status, uint status_len)
4459
4473
Protocol *protocol= thd->protocol;
4460
4474
protocol->prepare_for_resend();
4501
4515
- table is not mysql.event
4504
static bool check_table_binlog_row_based(THD *thd, Table *table)
4518
static bool check_table_binlog_row_based(THD *thd, TABLE *table)
4506
4520
if (table->s->cached_row_logging_check == -1)
4544
4558
if (thd->get_binlog_table_maps() == 0)
4546
DRIZZLE_LOCK *locks[3];
4560
MYSQL_LOCK *locks[3];
4547
4561
locks[0]= thd->extra_lock;
4548
4562
locks[1]= thd->lock;
4549
4563
locks[2]= thd->locked_tables;
4550
for (uint32_t i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
4564
for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
4552
DRIZZLE_LOCK const *const lock= locks[i];
4566
MYSQL_LOCK const *const lock= locks[i];
4553
4567
if (lock == NULL)
4556
Table **const end_ptr= lock->table + lock->table_count;
4557
for (Table **table_ptr= lock->table ;
4570
TABLE **const end_ptr= lock->table + lock->table_count;
4571
for (TABLE **table_ptr= lock->table ;
4558
4572
table_ptr != end_ptr ;
4561
Table *const table= *table_ptr;
4575
TABLE *const table= *table_ptr;
4562
4576
if (table->current_lock == F_WRLCK &&
4563
4577
check_table_binlog_row_based(thd, table))
4581
typedef bool Log_func(THD*, Table*, bool, const unsigned char*, const unsigned char*);
4595
typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*);
4583
static int binlog_log_row(Table* table,
4584
const unsigned char *before_record,
4585
const unsigned char *after_record,
4597
static int binlog_log_row(TABLE* table,
4598
const uchar *before_record,
4599
const uchar *after_record,
4586
4600
Log_func *log_func)
4588
4602
if (table->no_replicate)
4619
4633
We cache the table flags if the locking succeeded. Otherwise, we
4620
4634
keep them as they were when they were fetched in ha_open().
4622
DRIZZLE_EXTERNAL_LOCK(lock_type);
4636
MYSQL_EXTERNAL_LOCK(lock_type);
4624
4638
int error= external_lock(thd, lock_type);
4625
4639
if (error == 0)
4634
4648
int handler::ha_reset()
4636
4650
/* Check that we have called all proper deallocation functions */
4637
assert((unsigned char*) table->def_read_set.bitmap +
4651
assert((uchar*) table->def_read_set.bitmap +
4638
4652
table->s->column_bitmap_size ==
4639
(unsigned char*) table->def_write_set.bitmap);
4653
(uchar*) table->def_write_set.bitmap);
4640
4654
assert(bitmap_is_set_all(&table->s->all_set));
4641
4655
assert(table->key_read == 0);
4642
4656
/* ensure that ha_index_end / ha_rnd_end has been called */
4652
int handler::ha_write_row(unsigned char *buf)
4666
int handler::ha_write_row(uchar *buf)
4655
4669
Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
4656
DRIZZLE_INSERT_ROW_START();
4670
MYSQL_INSERT_ROW_START();
4658
4672
mark_trx_read_write();
4662
4676
if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
4663
4677
return(error); /* purecov: inspected */
4664
DRIZZLE_INSERT_ROW_END();
4678
MYSQL_INSERT_ROW_END();
4669
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
4683
int handler::ha_update_row(const uchar *old_data, uchar *new_data)
4672
4686
Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;