diff options
author | Michael Widenius <monty@askmonty.org> | 2010-01-04 19:54:42 +0200 |
---|---|---|
committer | Michael Widenius <monty@askmonty.org> | 2010-01-04 19:54:42 +0200 |
commit | d2f7348fdcb47a4fab6d3904143272f25535b5f0 (patch) | |
tree | d558e2e1bf43b20173bfdba5567a073c667a002c | |
parent | 08b84df418c8c99e3b8db367b35135a3da2ffdd7 (diff) | |
parent | 7ae95fdef2b5d4880d381d6ed46ad4aa996b03d3 (diff) | |
download | mariadb-git-d2f7348fdcb47a4fab6d3904143272f25535b5f0.tar.gz |
Merge with 5.1
134 files changed, 3193 insertions, 887 deletions
diff --git a/.bzrignore b/.bzrignore index e3cb25a09c9..bcfa640a119 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1924,3 +1924,7 @@ libmysqld/opt_table_elimination.cc libmysqld/ha_federatedx.cc tmp libmysqld/debug_sync.cc +client/rpl_filter.cc +client/rpl_filter.h +client/sql_list.cc +client/sql_list.h diff --git a/BUILD/FINISH.sh b/BUILD/FINISH.sh index 142ff7eb08e..75837db320f 100644 --- a/BUILD/FINISH.sh +++ b/BUILD/FINISH.sh @@ -1,6 +1,6 @@ -cflags="$c_warnings $extra_flags" -cxxflags="$cxx_warnings $base_cxxflags $extra_flags" -extra_configs="$extra_configs $local_infile_configs" +cflags="$c_warnings $extra_flags $EXTRA_FLAGS $EXTRA_CFLAGS" +cxxflags="$cxx_warnings $base_cxxflags $extra_flags $EXTRA_FLAGS $EXTRA_CXXFLAGS" +extra_configs="$extra_configs $local_infile_configs $EXTRA_CONFIGS" configure="./configure $base_configs $extra_configs" commands="\ diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 30148cde360..51a7d263131 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -34,6 +34,14 @@ parse_options() full_debug="=full";; --warning-mode=*) warning_mode=`get_key_value "$1"`;; + --extra-flags=*) + EXTRA_FLAGS=`get_key_value "$1"`;; + --extra-cflags=*) + EXTRA_CFLAGS=`get_key_value "$1"`;; + --extra-cxxflags=*) + EXTRA_CXXFLAGS=`get_key_value "$1"`;; + --extra-configs=*) + EXTRA_CONFIGS=`get_key_value "$1"`;; -c | --just-configure) just_configure=1;; -n | --just-print | --print) diff --git a/client/mysql.cc b/client/mysql.cc index a9cf6ff8fee..11ae66ec0a0 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1280,7 +1280,6 @@ sig_handler handle_sigint(int sig) MYSQL *kill_mysql= NULL; /* terminate if no query being executed, or we already tried interrupting */ - /* terminate if no query being executed, or we already tried interrupting */ if (!executing_query || (interrupted_query == 2)) { tee_fprintf(stdout, "Ctrl-C -- exit!\n"); @@ -1295,6 +1294,7 @@ sig_handler handle_sigint(int sig) goto err; } + /* First time try to kill the query, second time the connection */ interrupted_query++; /* mysqld < 5 does not understand KILL QUERY, skip to KILL CONNECTION */ @@ -1305,10 +1305,13 @@ sig_handler handle_sigint(int sig) sprintf(kill_buffer, "KILL %s%lu", (interrupted_query == 1) ? "QUERY " : "", mysql_thread_id(&mysql)); - tee_fprintf(stdout, "Ctrl-C -- sending \"%s\" to server ...\n", kill_buffer); + if (verbose) + tee_fprintf(stdout, "Ctrl-C -- sending \"%s\" to server ...\n", + kill_buffer); mysql_real_query(kill_mysql, kill_buffer, (uint) strlen(kill_buffer)); mysql_close(kill_mysql); - tee_fprintf(stdout, "Ctrl-C -- query aborted.\n"); + tee_fprintf(stdout, "Ctrl-C -- query killed. Continuing normally.\n"); + interrupted_query= 0; return; @@ -1321,7 +1324,6 @@ err: handler called mysql_end(). */ mysql_thread_end(); - return; #else mysql_end(sig); #endif @@ -2881,13 +2883,8 @@ com_help(String *buffer __attribute__((unused)), return com_server_help(buffer,line,help_arg); } - put_info("\nFor information about MySQL products and services, visit:\n" - " http://www.mysql.com/\n" - "For developer information, including the MySQL Reference Manual, " - "visit:\n" - " http://dev.mysql.com/\n" - "To buy MySQL Enterprise support, training, or other products, visit:\n" - " https://shop.mysql.com/\n", INFO_INFO); + put_info("\nGeneral information about MariaDB can be found at\n" + "http://askmonty.org/wiki/index.php/Manual:Contents\n", INFO_INFO); put_info("List of all MySQL commands:", INFO_INFO); if (!named_cmds) put_info("Note that all text commands must be first on line and end with ';'",INFO_INFO); diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 1533e602639..1a834e98035 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -857,7 +857,8 @@ int main(int argc, char **argv) if (!opt_write_binlog) { - if (disable_binlog()) { + if (disable_binlog()) + { first_error= 1; goto end; } diff --git a/client/mysqlslap.c b/client/mysqlslap.c index f0f377971ac..43d963cc22f 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -472,11 +472,10 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr) if (commit_rate) run_query(mysql, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0")); - if (pre_system) - if ((sysret= system(pre_system)) != 0) - fprintf(stderr, - "Warning: Execution of pre_system option returned %d.\n", - sysret); + if (pre_system && (sysret= system(pre_system)) != 0) + fprintf(stderr, + "Warning: Execution of pre_system option returned %d.\n", + sysret); /* Pre statements are always run after all other logic so they can @@ -490,11 +489,10 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr) if (post_statements) run_statements(mysql, post_statements); - if (post_system) - if ((sysret= system(post_system)) != 0) - fprintf(stderr, - "Warning: Execution of post_system option returned %d.\n", - sysret); + if (post_system && (sysret= system(post_system)) != 0) + fprintf(stderr, + "Warning: Execution of post_system option returned %d.\n", + sysret); /* We are finished with this run */ if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary) drop_primary_key_list(); diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 217b6852656..bc5c4ed76b8 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1267,6 +1267,7 @@ void abort_not_supported_test(const char *fmt, ...) DBUG_ENTER("abort_not_supported_test"); /* Print include filestack */ + fflush(stdout); fprintf(stderr, "The test '%s' is not supported by this installation\n", file_stack->file_name); fprintf(stderr, "Detected in file %s at line %d\n", @@ -3497,9 +3498,10 @@ void do_diff_files(struct st_command *command) if ((error= compare_files(ds_filename.str, ds_filename2.str)) && match_expected_error(command, error, NULL) < 0) { - /* Compare of the two files failed, append them to output - so the failure can be analyzed, but only if it was not - expected to fail. + /* + Compare of the two files failed, append them to output + so the failure can be analyzed, but only if it was not + expected to fail. */ show_diff(&ds_res, ds_filename.str, ds_filename2.str); log_file.write(&ds_res); @@ -5013,7 +5015,8 @@ void do_connect(struct st_command *command) con_options= ds_options.str; while (*con_options) { - char* end; + size_t length; + char *end; /* Step past any spaces in beginning of option*/ while (*con_options && my_isspace(charset_info, *con_options)) con_options++; @@ -5021,13 +5024,14 @@ void do_connect(struct st_command *command) end= con_options; while (*end && !my_isspace(charset_info, *end)) end++; - if (!strncmp(con_options, "SSL", 3)) + length= (size_t) (end - con_options); + if (length == 3 && !strncmp(con_options, "SSL", 3)) con_ssl= 1; - else if (!strncmp(con_options, "COMPRESS", 8)) + else if (length == 8 && !strncmp(con_options, "COMPRESS", 8)) con_compress= 1; - else if (!strncmp(con_options, "PIPE", 4)) + else if (length == 4 && !strncmp(con_options, "PIPE", 4)) con_pipe= 1; - else if (!strncmp(con_options, "SHM", 3)) + else if (length == 3 && !strncmp(con_options, "SHM", 3)) con_shm= 1; else die("Illegal option to connect: %.*s", @@ -5096,14 +5100,13 @@ void do_connect(struct st_command *command) mysql_options(&con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME, ds_shm.str); mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, &protocol); } - else if(shared_memory_base_name) + else if (shared_memory_base_name) { mysql_options(&con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME, - shared_memory_base_name); + shared_memory_base_name); } #endif - /* Use default db name */ if (ds_database.length == 0) dynstr_set(&ds_database, opt_db); @@ -6879,10 +6882,8 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command, MYSQL_STMT *stmt; DYNAMIC_STRING ds_prepare_warnings; DYNAMIC_STRING ds_execute_warnings; - ulonglong affected_rows; DBUG_ENTER("run_query_stmt"); DBUG_PRINT("query", ("'%-.60s'", query)); - LINT_INIT(affected_rows); /* Init a new stmt if it's not already one created for this connection @@ -6981,6 +6982,9 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command, handle_no_error(command); if (!disable_result_log) { + ulonglong affected_rows; + LINT_INIT(affected_rows); + /* Not all statements creates a result set. If there is one we can now create another normal result set that contains the meta @@ -7026,39 +7030,33 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command, Need to grab affected rows information before getting warnings here */ - { - ulonglong affected_rows; - LINT_INIT(affected_rows); + if (!disable_info) + affected_rows= mysql_affected_rows(mysql); - if (!disable_info) - affected_rows= mysql_affected_rows(mysql); + if (!disable_warnings) + { + /* Get the warnings from execute */ - if (!disable_warnings) + /* Append warnings to ds - if there are any */ + if (append_warnings(&ds_execute_warnings, mysql) || + ds_execute_warnings.length || + ds_prepare_warnings.length || + ds_warnings->length) { - /* Get the warnings from execute */ - - /* Append warnings to ds - if there are any */ - if (append_warnings(&ds_execute_warnings, mysql) || - ds_execute_warnings.length || - ds_prepare_warnings.length || - ds_warnings->length) - { - dynstr_append_mem(ds, "Warnings:\n", 10); - if (ds_warnings->length) - dynstr_append_mem(ds, ds_warnings->str, - ds_warnings->length); - if (ds_prepare_warnings.length) - dynstr_append_mem(ds, ds_prepare_warnings.str, - ds_prepare_warnings.length); - if (ds_execute_warnings.length) - dynstr_append_mem(ds, ds_execute_warnings.str, - ds_execute_warnings.length); - } + dynstr_append_mem(ds, "Warnings:\n", 10); + if (ds_warnings->length) + dynstr_append_mem(ds, ds_warnings->str, + ds_warnings->length); + if (ds_prepare_warnings.length) + dynstr_append_mem(ds, ds_prepare_warnings.str, + ds_prepare_warnings.length); + if (ds_execute_warnings.length) + dynstr_append_mem(ds, ds_execute_warnings.str, + ds_execute_warnings.length); } - - if (!disable_info) - append_info(ds, affected_rows, mysql_info(mysql)); } + if (!disable_info) + append_info(ds, affected_rows, mysql_info(mysql)); } end: @@ -7235,7 +7233,6 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) } dynstr_free(&query_str); - } if (sp_protocol_enabled && @@ -7662,6 +7659,7 @@ int main(int argc, char **argv) my_bool q_send_flag= 0, abort_flag= 0; uint command_executed= 0, last_command_executed= 0; char save_file[FN_REFLEN]; + bool empty_result= FALSE; MY_INIT(argv[0]); save_file[0]= 0; @@ -7819,6 +7817,7 @@ int main(int argc, char **argv) verbose_msg("Start processing test commands from '%s' ...", cur_file->file_name); while (!read_command(&command) && !abort_flag) { + my_bool ok_to_do; int current_line_inc = 1, processed = 0; if (command->type == Q_UNKNOWN || command->type == Q_COMMENT_WITH_COMMAND) get_command_type(command); @@ -7831,7 +7830,7 @@ int main(int argc, char **argv) command->type= Q_COMMENT; } - my_bool ok_to_do= cur_block->ok; + ok_to_do= cur_block->ok; /* Some commands need to be "done" the first time if they may get re-iterated over in a true context. This can only happen if there's @@ -8100,7 +8099,10 @@ int main(int argc, char **argv) abort_flag= 1; break; case Q_SKIP: - abort_not_supported_test("%s", command->first_argument); + /* Eval the query, thus replacing all environment variables */ + dynstr_set(&ds_res, 0); + do_eval(&ds_res, command->first_argument, command->end, FALSE); + abort_not_supported_test("%s",ds_res.str); break; case Q_RESULT: @@ -8167,8 +8169,6 @@ int main(int argc, char **argv) if (parsing_disabled) die("Test ended with parsing disabled"); - my_bool empty_result= FALSE; - /* The whole test has been executed _sucessfully_. Time to compare result or save it to record file. diff --git a/dbug/dbug.c b/dbug/dbug.c index dc92aa3d768..cad7fbb3030 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -497,12 +497,18 @@ int DbugParse(CODE_STATE *cs, const char *control) const char *end; int rel, f_used=0; struct settings *stack; + int org_cs_locked; stack= cs->stack; + if (!(org_cs_locked= cs->locked)) + { + cs->locked= 1; + pthread_mutex_lock(&THR_LOCK_dbug); + } + if (control[0] == '-' && control[1] == '#') control+=2; - rel= control[0] == '+' || control[0] == '-'; if ((!rel || (!stack->out_file && !stack->next))) { @@ -550,9 +556,11 @@ int DbugParse(CODE_STATE *cs, const char *control) while (control < end) { int c, sign= (*control == '+') ? 1 : (*control == '-') ? -1 : 0; - if (sign) control++; + if (sign) + control++; c= *control++; - if (*control == ',') control++; + if (*control == ',') + control++; /* XXX when adding new cases here, don't forget _db_explain_ ! */ switch (c) { case 'd': @@ -570,7 +578,7 @@ int DbugParse(CODE_STATE *cs, const char *control) { if (DEBUGGING) stack->keywords= ListDel(stack->keywords, control, end); - break; + break; } stack->keywords= ListAdd(stack->keywords, control, end); stack->flags |= DEBUG_ON; @@ -718,8 +726,13 @@ int DbugParse(CODE_STATE *cs, const char *control) control=end+1; end= DbugStrTok(control); } - return !rel || f_used; -} + if (!org_cs_locked) + { + pthread_mutex_unlock(&THR_LOCK_dbug); + cs->locked= 0; + } + return !rel || f_used;} + #define framep_trace_flag(cs, frp) (frp ? \ frp->level & TRACE_ON : \ @@ -1340,11 +1353,11 @@ void _db_doprnt_(const char *format,...) va_start(args,format); + if (!cs->locked) + pthread_mutex_lock(&THR_LOCK_dbug); if (_db_keyword_(cs, cs->u_keyword, 0)) { int save_errno=errno; - if (!cs->locked) - pthread_mutex_lock(&THR_LOCK_dbug); DoPrefix(cs, cs->u_line); if (TRACING) Indent(cs, cs->level + 1); @@ -1356,6 +1369,9 @@ void _db_doprnt_(const char *format,...) DbugFlush(cs); errno=save_errno; } + else if (!cs->locked) + pthread_mutex_unlock(&THR_LOCK_dbug); + va_end(args); } @@ -1386,10 +1402,10 @@ void _db_dump_(uint _line_, const char *keyword, CODE_STATE *cs; get_code_state_or_return; + if (!cs->locked) + pthread_mutex_lock(&THR_LOCK_dbug); if (_db_keyword_(cs, keyword, 0)) { - if (!cs->locked) - pthread_mutex_lock(&THR_LOCK_dbug); DoPrefix(cs, _line_); if (TRACING) { @@ -1420,6 +1436,8 @@ void _db_dump_(uint _line_, const char *keyword, (void) fputc('\n',cs->stack->out_file); DbugFlush(cs); } + else if (!cs->locked) + pthread_mutex_unlock(&THR_LOCK_dbug); } @@ -2105,7 +2123,8 @@ static void DBUGCloseFile(CODE_STATE *cs, FILE *fp) { if (fp != stderr && fp != stdout && fclose(fp) == EOF) { - pthread_mutex_lock(&THR_LOCK_dbug); + if (!cs->locked) + pthread_mutex_lock(&THR_LOCK_dbug); (void) fprintf(cs->stack->out_file, ERR_CLOSE, cs->process); perror(""); DbugFlush(cs); diff --git a/extra/yassl/taocrypt/include/block.hpp b/extra/yassl/taocrypt/include/block.hpp index bb34db5e07f..d5bc8756fdd 100644 --- a/extra/yassl/taocrypt/include/block.hpp +++ b/extra/yassl/taocrypt/include/block.hpp @@ -167,7 +167,8 @@ public: void CleanNew(word32 newSize) { New(newSize); - memset(buffer_, 0, sz_ * sizeof(T)); + if (sz_ > 0) + memset(buffer_, 0, sz_ * sizeof(T)); } void New(word32 newSize) diff --git a/mysql-test/include/have_big5.inc b/mysql-test/include/have_big5.inc index dad4a0a8eeb..d6ef1202bae 100644 --- a/mysql-test/include/have_big5.inc +++ b/mysql-test/include/have_big5.inc @@ -1,4 +1,2 @@ --- require r/have_big5.require -disable_query_log; -show collation like 'big5_chinese_ci'; -enable_query_log; +let collation=big5_chinese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_collation.inc b/mysql-test/include/have_collation.inc new file mode 100644 index 00000000000..99270fd4d3d --- /dev/null +++ b/mysql-test/include/have_collation.inc @@ -0,0 +1,3 @@ +if (!`SELECT count(*) AS 'true' FROM information_schema.collations WHERE collation_name LIKE '$collation'`) { + skip Test needs character set '$collation'; +} diff --git a/mysql-test/include/have_cp1250_ch.inc b/mysql-test/include/have_cp1250_ch.inc index 426fa658597..93fde6e9fe6 100644 --- a/mysql-test/include/have_cp1250_ch.inc +++ b/mysql-test/include/have_cp1250_ch.inc @@ -1,4 +1,2 @@ --- require r/have_cp1250_ch.require -disable_query_log; -show collation like 'cp1250_czech_cs'; -enable_query_log; +let collation=cp1250_czech_cs; +--source include/have_collation.inc diff --git a/mysql-test/include/have_cp1251.inc b/mysql-test/include/have_cp1251.inc index 2d5f1b3b529..32e9e7220fc 100644 --- a/mysql-test/include/have_cp1251.inc +++ b/mysql-test/include/have_cp1251.inc @@ -1,7 +1,2 @@ ---require r/have_cp1251.require - ---disable_query_log - -SHOW COLLATION LIKE 'cp1251_general_ci'; - ---enable_query_log +let collation=cp1251_general_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_cp866.inc b/mysql-test/include/have_cp866.inc index 27390d87d51..549ea22a0e3 100644 --- a/mysql-test/include/have_cp866.inc +++ b/mysql-test/include/have_cp866.inc @@ -1,7 +1,2 @@ ---require r/have_cp866.require - ---disable_query_log - -SHOW COLLATION LIKE 'cp866_general_ci'; - ---enable_query_log +let collation=cp866_general_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_cp932.inc b/mysql-test/include/have_cp932.inc index ecad979c02a..6e436b8b3f5 100644 --- a/mysql-test/include/have_cp932.inc +++ b/mysql-test/include/have_cp932.inc @@ -1,4 +1,2 @@ --- require r/have_cp932.require -disable_query_log; -show collation like 'cp932_japanese_ci'; -enable_query_log; +let collation=cp932_japanese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_eucjpms.inc b/mysql-test/include/have_eucjpms.inc index 6d96eefcc31..c38af5299c7 100644 --- a/mysql-test/include/have_eucjpms.inc +++ b/mysql-test/include/have_eucjpms.inc @@ -1,4 +1,2 @@ --- require r/have_eucjpms.require -disable_query_log; -show collation like 'eucjpms_japanese_ci'; -enable_query_log; +let collation=eucjpms_japanese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_euckr.inc b/mysql-test/include/have_euckr.inc index 4b4e870cf47..4da1a8363a3 100644 --- a/mysql-test/include/have_euckr.inc +++ b/mysql-test/include/have_euckr.inc @@ -1,4 +1,2 @@ --- require r/have_euckr.require -disable_query_log; -show collation like 'euckr_korean_ci'; -enable_query_log; +let collation=euckr_korean_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_gb2312.inc b/mysql-test/include/have_gb2312.inc index 27591c01b6c..6a9a0588be0 100644 --- a/mysql-test/include/have_gb2312.inc +++ b/mysql-test/include/have_gb2312.inc @@ -1,4 +1,2 @@ --- require r/have_gb2312.require -disable_query_log; -show collation like 'gb2312_chinese_ci'; -enable_query_log; +let collation=gb2312_chinese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_gbk.inc b/mysql-test/include/have_gbk.inc index 72252d6b00d..b8177aa655d 100644 --- a/mysql-test/include/have_gbk.inc +++ b/mysql-test/include/have_gbk.inc @@ -1,4 +1,2 @@ --- require r/have_gbk.require -disable_query_log; -show collation like 'gbk_chinese_ci'; -enable_query_log; +let collation=gbk_chinese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_koi8r.inc b/mysql-test/include/have_koi8r.inc index 1fe163565ba..02647f4555f 100644 --- a/mysql-test/include/have_koi8r.inc +++ b/mysql-test/include/have_koi8r.inc @@ -1,7 +1,2 @@ ---require r/have_koi8r.require - ---disable_query_log - -SHOW COLLATION LIKE 'koi8r_general_ci'; - ---enable_query_log +let collation=koi8r_general_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_latin2_ch.inc b/mysql-test/include/have_latin2_ch.inc index 215715a6aaf..f1e0d4e26aa 100644 --- a/mysql-test/include/have_latin2_ch.inc +++ b/mysql-test/include/have_latin2_ch.inc @@ -1,4 +1,2 @@ --- require r/have_latin2_ch.require -disable_query_log; -show collation like 'latin2_czech_cs'; -enable_query_log; +let collation=latin2_czech_cs; +--source include/have_collation.inc diff --git a/mysql-test/include/have_sjis.inc b/mysql-test/include/have_sjis.inc index ac6531ca868..a25dc51dfa7 100644 --- a/mysql-test/include/have_sjis.inc +++ b/mysql-test/include/have_sjis.inc @@ -1,4 +1,2 @@ --- require r/have_sjis.require -disable_query_log; -show collation like 'sjis_japanese_ci'; -enable_query_log; +let collation=sjis_japanese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_tis620.inc b/mysql-test/include/have_tis620.inc index ad5ba9dea69..d385ff2c621 100644 --- a/mysql-test/include/have_tis620.inc +++ b/mysql-test/include/have_tis620.inc @@ -1,4 +1,2 @@ --- require r/have_tis620.require -disable_query_log; -show collation like 'tis620_thai_ci'; -enable_query_log; +let collation=tis620_thai_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_ucs2.inc b/mysql-test/include/have_ucs2.inc index 324ed52dd02..885e20297aa 100644 --- a/mysql-test/include/have_ucs2.inc +++ b/mysql-test/include/have_ucs2.inc @@ -1,4 +1,2 @@ --- require r/have_ucs2.require -disable_query_log; -show collation like 'ucs2_general_ci'; -enable_query_log; +let collation=ucs2_general_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_ujis.inc b/mysql-test/include/have_ujis.inc index e4b2f50cf93..222c027ca5a 100644 --- a/mysql-test/include/have_ujis.inc +++ b/mysql-test/include/have_ujis.inc @@ -1,4 +1,2 @@ --- require r/have_ujis.require -disable_query_log; -show collation like 'ujis_japanese_ci'; -enable_query_log; +let collation=ujis_japanese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_utf8.inc b/mysql-test/include/have_utf8.inc index 58b74f4072f..177d39abfdc 100644 --- a/mysql-test/include/have_utf8.inc +++ b/mysql-test/include/have_utf8.inc @@ -1,7 +1,2 @@ ---require r/have_utf8.require - ---disable_query_log - -SHOW COLLATION LIKE 'utf8_general_ci'; - ---enable_query_log +let collation=utf8_general_ci; +--source include/have_collation.inc diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 28b79484aa8..c0f36ba03b9 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -101,7 +101,6 @@ sub init_pattern { sub collect_test_cases ($$) { my $suites= shift; # Semicolon separated list of test suites - my %found_suites; my $opt_cases= shift; my $cases= []; # Array of hash(one hash for each testcase) @@ -115,7 +114,6 @@ sub collect_test_cases ($$) { ["ha_innodb_plugin.dll", "ha_innodb_plugin.so", "ha_innodb_plugin.sl"], NOT_REQUIRED); - $do_innodb_plugin= ($::mysql_version_id >= 50100 && !(IS_WINDOWS && $::opt_embedded_server) && $lib_innodb_plugin); @@ -123,7 +121,6 @@ sub collect_test_cases ($$) { foreach my $suite (split(",", $suites)) { push(@$cases, collect_one_suite($suite, $opt_cases)); - $found_suites{$suite}= 1; last if $some_test_found; } @@ -136,12 +133,6 @@ sub collect_test_cases ($$) { { my $found= 0; my ($sname, $tname, $extension)= split_testname($test_name_spec); - if (defined($sname) && !defined($found_suites{$sname})) - { - $found_suites{$sname}= 1; - push(@$cases, collect_one_suite($sname)); - } - foreach my $test ( @$cases ) { # test->{name} is always in suite.name format @@ -247,7 +238,7 @@ sub split_testname { } -sub collect_one_suite($) +sub collect_one_suite { my $suite= shift; # Test suite name my $opt_cases= shift; @@ -767,7 +758,6 @@ sub process_opts_file { } } - ############################################################################## # # Collect information about a single test case diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index e0c5b004541..944f62b29e3 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -388,7 +388,7 @@ MSG } elsif (@$extra_warnings) { - mtr_error("There were errors/warnings in server logs after running test cases."); + mtr_error("There where errors/warnings in server logs after running test cases."); } elsif ($fail) { diff --git a/mysql-test/lib/v1/mysql-test-run.pl b/mysql-test/lib/v1/mysql-test-run.pl index a691003abcb..3e9f7e78510 100755 --- a/mysql-test/lib/v1/mysql-test-run.pl +++ b/mysql-test/lib/v1/mysql-test-run.pl @@ -178,6 +178,7 @@ our @opt_extra_mysqltest_opt; our $opt_compress; our $opt_ssl; +our $opt_skip_ssl; our $opt_ssl_supported; our $opt_ps_protocol; our $opt_sp_protocol; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 74e2a35798c..428557e6714 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -126,7 +126,7 @@ my $path_config_file; # The generated config file, var/my.cnf # executables will be used by the test suite. our $opt_vs_config = $ENV{'MTR_VS_CONFIG'}; -my $DEFAULT_SUITES= "main,binlog,federated,rpl,innodb,maria,parts"; +my $DEFAULT_SUITES= "main,binlog,federated,rpl,maria,parts"; my $opt_suites; our $opt_verbose= 0; # Verbose output, enable with --verbose @@ -201,10 +201,10 @@ my $opt_mark_progress; my $opt_sleep; -my $opt_testcase_timeout= 15; # minutes -my $opt_suite_timeout = 300; # minutes -my $opt_shutdown_timeout= 10; # seconds -my $opt_start_timeout = 180; # seconds +my $opt_testcase_timeout= 15; # 15 minutes +my $opt_suite_timeout = 360; # 6 hours +my $opt_shutdown_timeout= 10; # 10 seconds +my $opt_start_timeout = 180; # 180 seconds sub testcase_timeout { return $opt_testcase_timeout * 60; }; sub suite_timeout { return $opt_suite_timeout * 60; }; @@ -1319,6 +1319,8 @@ sub command_line_setup { { # Indicate that we are using debugger $glob_debugger= 1; + $opt_testcase_timeout= 60*60*24; # Don't abort debugging with timeout + $opt_suite_timeout= $opt_testcase_timeout; $opt_retry= 1; $opt_retry_failure= 1; @@ -2151,7 +2153,6 @@ sub environment_setup { # Create an environment variable to make it possible # to detect that valgrind is being used from test cases $ENV{'VALGRIND_TEST'}= $opt_valgrind; - } @@ -2908,8 +2909,8 @@ sub mysql_install_db { my $bootstrap_sql_file= "$opt_vardir/tmp/bootstrap.sql"; my $path_sql= my_find_file($install_basedir, - ["mysql", "sql/share", "share/mysql", - "share/mariadb", "share", "scripts"], + ["mysql", "sql/share", "share/mariadb", + "share/mysql", "share", "scripts"], "mysql_system_tables.sql", NOT_REQUIRED); @@ -3861,7 +3862,7 @@ sub extract_server_log ($$) { my ($error_log, $tname) = @_; # Open the servers .err log file and read all lines - # belonging to current tets into @lines + # belonging to current test into @lines my $Ferr = IO::File->new($error_log) or mtr_error("Could not open file '$error_log' for reading: $!"); @@ -5682,12 +5683,15 @@ Misc options servers to exit before finishing the process fast Run as fast as possible, dont't wait for servers to shutdown etc. - parallel=N Run tests in N parallel threads (default=1) + parallel=N Run tests in N parallel threads (default 1) Use parallel=auto for auto-setting of N repeat=N Run each test N number of times - retry=N Retry tests that fail N times, limit number of failures - to $opt_retry_failure - retry-failure=N Limit number of retries for a failed test + retry=N Retry tests that fail up to N times (default $opt_retry). + Retries are also limited by the maximum number of + failures before stopping, set with the --retry-failure + option + retry-failure=N When using the --retry option to retry failed tests, + stop when N failures have occured (default $opt_retry_failure) reorder Reorder tests to get fewer server restarts help Get this help text diff --git a/mysql-test/r/create-uca.result b/mysql-test/r/create-uca.result new file mode 100644 index 00000000000..2d2522a36a3 --- /dev/null +++ b/mysql-test/r/create-uca.result @@ -0,0 +1,31 @@ +drop table if exists t1,t2; +CREATE TABLE t1( +c1 INT DEFAULT 12 COMMENT 'column1', +c2 INT NULL COMMENT 'column2', +c3 INT NOT NULL COMMENT 'column3', +c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', +c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b', +c6 VARCHAR(255)) +COLLATE latin1_bin; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT '12' COMMENT 'column1', + `c2` int(11) DEFAULT NULL COMMENT 'column2', + `c3` int(11) NOT NULL COMMENT 'column3', + `c4` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', + `c5` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'b', + `c6` varchar(255) COLLATE latin1_bin DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_bin +CREATE TABLE t2 AS SELECT * FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `c1` int(11) DEFAULT '12' COMMENT 'column1', + `c2` int(11) DEFAULT NULL COMMENT 'column2', + `c3` int(11) NOT NULL COMMENT 'column3', + `c4` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', + `c5` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'b', + `c6` varchar(255) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1,t2; diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 29686d6e023..dc2cb6786c7 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1793,52 +1793,6 @@ t1 CREATE TABLE `t1` ( drop table t1; # -- -# -- Bug#21380: DEFAULT definition not always transfered by CREATE -# -- TABLE/SELECT to the new table. -# -- - -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t2; - -CREATE TABLE t1( -c1 INT DEFAULT 12 COMMENT 'column1', -c2 INT NULL COMMENT 'column2', -c3 INT NOT NULL COMMENT 'column3', -c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', -c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b', -c6 VARCHAR(255)) -COLLATE latin1_bin; - -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `c1` int(11) DEFAULT '12' COMMENT 'column1', - `c2` int(11) DEFAULT NULL COMMENT 'column2', - `c3` int(11) NOT NULL COMMENT 'column3', - `c4` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', - `c5` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'b', - `c6` varchar(255) COLLATE latin1_bin DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_bin - -CREATE TABLE t2 AS SELECT * FROM t1; - -SHOW CREATE TABLE t2; -Table Create Table -t2 CREATE TABLE `t2` ( - `c1` int(11) DEFAULT '12' COMMENT 'column1', - `c2` int(11) DEFAULT NULL COMMENT 'column2', - `c3` int(11) NOT NULL COMMENT 'column3', - `c4` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', - `c5` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'b', - `c6` varchar(255) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 - -DROP TABLE t2; -DROP TABLE t1; - -# -- End of test case for Bug#21380. - -# -- # -- Bug#18834: ALTER TABLE ADD INDEX on table with two timestamp fields # -- diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 428629e7e9e..c14422470ca 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -1211,3 +1211,47 @@ HEX(DAYNAME(19700101)) 0427043504420432043504400433 SET character_set_connection=latin1; End of 5.0 tests +Start of 5.1 tests +SET NAMES utf8; +CREATE TABLE t1 ( +a varchar(10) CHARACTER SET ucs2 COLLATE ucs2_czech_ci, +key(a) +); +INSERT INTO t1 VALUES +('aa'),('bb'),('cc'),('dd'),('ee'),('ff'),('gg'),('hh'),('ii'), +('jj'),('kk'),('ll'),('mm'),('nn'),('oo'),('pp'),('rr'),('ss'), +('tt'),('uu'),('vv'),('ww'),('xx'),('yy'),('zz'); +INSERT INTO t1 VALUES ('ca'),('cz'),('ch'); +INSERT INTO t1 VALUES ('da'),('dz'), (X'0064017E'); +EXPLAIN SELECT * FROM t1 WHERE a LIKE 'b%'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 23 NULL 1 Using where; Using index +EXPLAIN SELECT * FROM t1 WHERE a LIKE 'c%'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 23 NULL 30 Using where; Using index +SELECT * FROM t1 WHERE a LIKE 'c%'; +a +ca +cc +cz +ch +EXPLAIN SELECT * FROM t1 WHERE a LIKE 'ch%'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 23 NULL 1 Using where; Using index +SELECT * FROM t1 WHERE a LIKE 'ch%'; +a +ch +ALTER TABLE t1 MODIFY a VARCHAR(10) CHARACTER SET ucs2 COLLATE ucs2_croatian_ci; +EXPLAIN SELECT * FROM t1 WHERE a LIKE 'd%'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 23 NULL 1 Using where; Using index +SELECT hex(concat('d',_ucs2 0x017E,'%')); +hex(concat('d',_ucs2 0x017E,'%')) +0064017E0025 +EXPLAIN SELECT * FROM t1 WHERE a LIKE concat('d',_ucs2 0x017E,'%'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 23 NULL 1 Using where; Using index +SELECT hex(a) FROM t1 WHERE a LIKE concat('D',_ucs2 0x017E,'%'); +hex(a) +0064017E +DROP TABLE t1; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 4cfd06149f1..b3084d182a6 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1,3 +1,5 @@ +drop table if exists t1,t2,t3,t4; +drop database if exists mysqltest; drop table if exists t1,t2; set names utf8; select left(_utf8 0xD0B0D0B1D0B2,1); diff --git a/mysql-test/r/have_big5.require b/mysql-test/r/have_big5.require deleted file mode 100644 index 74aacf74b62..00000000000 --- a/mysql-test/r/have_big5.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -big5_chinese_ci big5 1 Yes Yes 1 diff --git a/mysql-test/r/have_cp1250_ch.require b/mysql-test/r/have_cp1250_ch.require deleted file mode 100644 index 2eb834d97e2..00000000000 --- a/mysql-test/r/have_cp1250_ch.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -cp1250_czech_cs cp1250 34 Yes 2 diff --git a/mysql-test/r/have_cp1251.require b/mysql-test/r/have_cp1251.require deleted file mode 100644 index 465e8338084..00000000000 --- a/mysql-test/r/have_cp1251.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -cp1251_general_ci cp1251 51 Yes 0 diff --git a/mysql-test/r/have_cp866.require b/mysql-test/r/have_cp866.require deleted file mode 100644 index da2a3e2f05e..00000000000 --- a/mysql-test/r/have_cp866.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -cp866_general_ci cp866 36 Yes 0 diff --git a/mysql-test/r/have_cp932.require b/mysql-test/r/have_cp932.require deleted file mode 100644 index 988d720ed2c..00000000000 --- a/mysql-test/r/have_cp932.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -cp932_japanese_ci cp932 95 Yes Yes 1 diff --git a/mysql-test/r/have_eucjpms.require b/mysql-test/r/have_eucjpms.require deleted file mode 100644 index f35621b2c1a..00000000000 --- a/mysql-test/r/have_eucjpms.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -eucjpms_japanese_ci eucjpms 97 Yes Yes 1 diff --git a/mysql-test/r/have_euckr.require b/mysql-test/r/have_euckr.require deleted file mode 100644 index 0771ceec570..00000000000 --- a/mysql-test/r/have_euckr.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -euckr_korean_ci euckr 19 Yes Yes 1 diff --git a/mysql-test/r/have_gb2312.require b/mysql-test/r/have_gb2312.require deleted file mode 100644 index 9bcb7c94a14..00000000000 --- a/mysql-test/r/have_gb2312.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -gb2312_chinese_ci gb2312 24 Yes Yes 1 diff --git a/mysql-test/r/have_gbk.require b/mysql-test/r/have_gbk.require deleted file mode 100644 index e19fead153a..00000000000 --- a/mysql-test/r/have_gbk.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -gbk_chinese_ci gbk 28 Yes Yes 1 diff --git a/mysql-test/r/have_koi8r.require b/mysql-test/r/have_koi8r.require deleted file mode 100644 index b109b9ae520..00000000000 --- a/mysql-test/r/have_koi8r.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -koi8r_general_ci koi8r 7 Yes 0 diff --git a/mysql-test/r/have_latin2_ch.require b/mysql-test/r/have_latin2_ch.require deleted file mode 100644 index 352401bbfe8..00000000000 --- a/mysql-test/r/have_latin2_ch.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -latin2_czech_cs latin2 2 Yes 4 diff --git a/mysql-test/r/have_sjis.require b/mysql-test/r/have_sjis.require deleted file mode 100644 index 72ce8ec88fe..00000000000 --- a/mysql-test/r/have_sjis.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -sjis_japanese_ci sjis 13 Yes Yes 1 diff --git a/mysql-test/r/have_tis620.require b/mysql-test/r/have_tis620.require deleted file mode 100644 index a1bf93ac491..00000000000 --- a/mysql-test/r/have_tis620.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -tis620_thai_ci tis620 18 Yes Yes 4 diff --git a/mysql-test/r/have_ucs2.require b/mysql-test/r/have_ucs2.require deleted file mode 100644 index c53250aeaef..00000000000 --- a/mysql-test/r/have_ucs2.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -ucs2_general_ci ucs2 35 Yes Yes 1 diff --git a/mysql-test/r/have_ujis.require b/mysql-test/r/have_ujis.require deleted file mode 100644 index 43a309ad74e..00000000000 --- a/mysql-test/r/have_ujis.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -ujis_japanese_ci ujis 12 Yes Yes 1 diff --git a/mysql-test/r/have_utf8.require b/mysql-test/r/have_utf8.require deleted file mode 100644 index 71f8ccfff47..00000000000 --- a/mysql-test/r/have_utf8.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -utf8_general_ci utf8 33 Yes Yes 1 diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 845083af478..021bf34a132 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -3160,15 +3160,6 @@ ALTER TABLE t2 MODIFY a INT NOT NULL; ERROR HY000: Error on rename of '#sql-temporary' to './test/t2' (errno: 150) DELETE FROM t1; DROP TABLE t2,t1; -CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY) -ENGINE=InnoDB; -INSERT INTO t1 VALUES (0xEFBCA4EFBCA4EFBCA4); -DELETE FROM t1; -INSERT INTO t1 VALUES ('DDD'); -SELECT * FROM t1; -a -DDD -DROP TABLE t1; CREATE TABLE t1 (id int PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB AUTO_INCREMENT=42; INSERT INTO t1 VALUES (0),(347),(0); diff --git a/mysql-test/r/innodb_utf8.result b/mysql-test/r/innodb_utf8.result new file mode 100644 index 00000000000..cdac7cdb65b --- /dev/null +++ b/mysql-test/r/innodb_utf8.result @@ -0,0 +1,10 @@ +drop table if exists t1; +CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (0xEFBCA4EFBCA4EFBCA4); +DELETE FROM t1; +INSERT INTO t1 VALUES ('DDD'); +SELECT * FROM t1; +a +DDD +DROP TABLE t1; diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index 8a87852d582..6be5c9fb130 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -319,3 +319,17 @@ SHOW ERRORS; Level Code Message Error 1051 Unknown table 't1' End of 5.0 tests +set sql_mode = default; +select CAST(a AS DECIMAL(13,5)) FROM (SELECT '' as a) t; +CAST(a AS DECIMAL(13,5)) +0.00000 +Warnings: +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Warning 1292 Truncated incorrect DECIMAL value: '' +create table t1 (a integer unsigned); +insert into t1 values (1),(-1),(0),(-2); +Warnings: +Warning 1264 Out of range value for column 'a' at row 2 +Warning 1264 Out of range value for column 'a' at row 4 +drop table t1; +End of 5.1 tests diff --git a/mysql-test/suite/federated/disabled.def b/mysql-test/suite/federated/disabled.def index f34cda61137..1287864ef16 100644 --- a/mysql-test/suite/federated/disabled.def +++ b/mysql-test/suite/federated/disabled.def @@ -9,5 +9,4 @@ # Do not use any TAB characters for whitespace. # ############################################################################## -federated_server : needs fixup diff --git a/mysql-test/suite/federated/federated_server.result b/mysql-test/suite/federated/federated_server.result index 227dec46ae5..9c6a062f530 100644 --- a/mysql-test/suite/federated/federated_server.result +++ b/mysql-test/suite/federated/federated_server.result @@ -175,6 +175,8 @@ CREATE TABLE db_bogus.t1 ( ) ; INSERT INTO db_bogus.t1 VALUES ('2','this is bogus'); +create user test_fed@localhost identified by 'foo'; +grant all on db_legitimate.* to test_fed@localhost; create server 's1' foreign data wrapper 'mysql' options (HOST '127.0.0.1', DATABASE 'db_legitimate', @@ -211,15 +213,14 @@ id name alter server s1 options (database 'db_bogus'); flush tables; select * from federated.t1; -id name -2 this is bogus +ERROR HY000: There was a problem processing the query on the foreign data source. Data source error: : 1044 : Access denied for user 'test_fed'@'localhost' to databa drop server if exists 's1'; ERROR 42000: Access denied; you need the SUPER privilege for this operation create server 's1' foreign data wrapper 'mysql' options (HOST '127.0.0.1', DATABASE 'db_legitimate', -USER 'root', -PASSWORD '', +USER 'test_fed', +PASSWORD 'foo', PORT SLAVE_PORT, SOCKET '', OWNER 'root'); @@ -228,8 +229,8 @@ drop server 's1'; create server 's1' foreign data wrapper 'mysql' options (HOST '127.0.0.1', DATABASE 'db_legitimate', -USER 'root', -PASSWORD '', +USER 'test_fed', +PASSWORD 'foo', PORT SLAVE_PORT, SOCKET '', OWNER 'root'); @@ -237,6 +238,7 @@ flush tables; select * from federated.t1; id name 1 this is legitimate +drop user test_fed@localhost; drop database db_legitimate; drop database db_bogus; drop user guest_super@localhost; @@ -275,6 +277,6 @@ call p1(); drop procedure p1; drop server if exists s; DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/suite/federated/federated_server.test b/mysql-test/suite/federated/federated_server.test index 5311bf770e1..65674abff63 100644 --- a/mysql-test/suite/federated/federated_server.test +++ b/mysql-test/suite/federated/federated_server.test @@ -239,6 +239,7 @@ alter server s1 options (database 'db_bogus'); connection master; flush tables; +--error ER_QUERY_ON_FOREIGN_DATA_SOURCE select * from federated.t1; connection conn_select; @@ -249,8 +250,8 @@ drop server if exists 's1'; eval create server 's1' foreign data wrapper 'mysql' options (HOST '127.0.0.1', DATABASE 'db_legitimate', - USER 'root', - PASSWORD '', + USER 'test_fed', + PASSWORD 'foo', PORT $SLAVE_MYPORT, SOCKET '', OWNER 'root'); @@ -261,8 +262,8 @@ drop server 's1'; eval create server 's1' foreign data wrapper 'mysql' options (HOST '127.0.0.1', DATABASE 'db_legitimate', - USER 'root', - PASSWORD '', + USER 'test_fed', + PASSWORD 'foo', PORT $SLAVE_MYPORT, SOCKET '', OWNER 'root'); @@ -273,6 +274,7 @@ select * from federated.t1; # clean up test connection slave; +drop user test_fed@localhost; drop database db_legitimate; drop database db_bogus; diff --git a/mysql-test/suite/funcs_1/r/innodb_func_view.result b/mysql-test/suite/funcs_1/r/innodb_func_view.result index 4beb0c8aaf2..c62c91f1d57 100644 --- a/mysql-test/suite/funcs_1/r/innodb_func_view.result +++ b/mysql-test/suite/funcs_1/r/innodb_func_view.result @@ -3372,9 +3372,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 29 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as decimal(37,2)) AS `CAST(my_varbinary_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3389,9 +3389,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 29 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 DROP VIEW v1; @@ -3408,11 +3408,11 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 28 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' Warning 1292 Truncated incorrect DECIMAL value: '-1' Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333' @@ -3430,11 +3430,11 @@ NULL NULL 1 -1.00 -1 -3333.33 -3333.3333 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' Warning 1292 Truncated incorrect DECIMAL value: '-1' Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333' @@ -3454,9 +3454,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 27 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as decimal(37,2)) AS `CAST(my_varchar_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3471,9 +3471,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 27 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 DROP VIEW v1; @@ -3490,11 +3490,11 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 26 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection @@ -3510,11 +3510,11 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 26 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' DROP VIEW v1; diff --git a/mysql-test/suite/funcs_1/r/memory_func_view.result b/mysql-test/suite/funcs_1/r/memory_func_view.result index 4e48d9412d1..f83a931af5c 100644 --- a/mysql-test/suite/funcs_1/r/memory_func_view.result +++ b/mysql-test/suite/funcs_1/r/memory_func_view.result @@ -3373,9 +3373,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 29 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as decimal(37,2)) AS `CAST(my_varbinary_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3390,9 +3390,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 29 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 DROP VIEW v1; @@ -3409,11 +3409,11 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 28 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' Warning 1292 Truncated incorrect DECIMAL value: '-1' Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333' @@ -3431,11 +3431,11 @@ NULL NULL 1 -1.00 -1 -3333.33 -3333.3333 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' Warning 1292 Truncated incorrect DECIMAL value: '-1' Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333' @@ -3455,9 +3455,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 27 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as decimal(37,2)) AS `CAST(my_varchar_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3472,9 +3472,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 27 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 DROP VIEW v1; @@ -3491,11 +3491,11 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 26 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection @@ -3511,11 +3511,11 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 26 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' DROP VIEW v1; diff --git a/mysql-test/suite/funcs_1/r/myisam_func_view.result b/mysql-test/suite/funcs_1/r/myisam_func_view.result index 4e48d9412d1..f83a931af5c 100644 --- a/mysql-test/suite/funcs_1/r/myisam_func_view.result +++ b/mysql-test/suite/funcs_1/r/myisam_func_view.result @@ -3373,9 +3373,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 29 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as decimal(37,2)) AS `CAST(my_varbinary_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3390,9 +3390,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 29 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 DROP VIEW v1; @@ -3409,11 +3409,11 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 28 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' Warning 1292 Truncated incorrect DECIMAL value: '-1' Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333' @@ -3431,11 +3431,11 @@ NULL NULL 1 -1.00 -1 -3333.33 -3333.3333 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' Warning 1292 Truncated incorrect DECIMAL value: '-1' Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333' @@ -3455,9 +3455,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 27 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as decimal(37,2)) AS `CAST(my_varchar_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3472,9 +3472,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 27 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 +Error 1366 Incorrect decimal value: '' for column '' at row 0 DROP VIEW v1; @@ -3491,11 +3491,11 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 26 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection @@ -3511,11 +3511,11 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 26 Warnings: -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Error 1366 Incorrect decimal value: '' for column '' at row -1 +Error 1366 Incorrect decimal value: '' for column '' at row 0 Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' DROP VIEW v1; diff --git a/mysql-test/suite/rpl/t/rpl_ignore_table.test b/mysql-test/suite/rpl/t/rpl_ignore_table.test index 66f96e8f4e8..15c4b193669 100644 --- a/mysql-test/suite/rpl/t/rpl_ignore_table.test +++ b/mysql-test/suite/rpl/t/rpl_ignore_table.test @@ -1,4 +1,6 @@ source include/master-slave.inc; +let collation=utf8_unicode_ci; +--source include/have_collation.inc # # BUG#16487 diff --git a/mysql-test/t/create-uca.test b/mysql-test/t/create-uca.test new file mode 100644 index 00000000000..0acb51f7286 --- /dev/null +++ b/mysql-test/t/create-uca.test @@ -0,0 +1,26 @@ +# Prerequisites +let collation=utf8_unicode_ci; +--source include/have_collation.inc + +# Initial cleanup +--disable_warnings +drop table if exists t1,t2; +--enable_warnings + +# +# Bug#21380: DEFAULT definition not always transfered by CREATE +# TABLE/SELECT to the new table. +# + +CREATE TABLE t1( + c1 INT DEFAULT 12 COMMENT 'column1', + c2 INT NULL COMMENT 'column2', + c3 INT NOT NULL COMMENT 'column3', + c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', + c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b', + c6 VARCHAR(255)) + COLLATE latin1_bin; +SHOW CREATE TABLE t1; +CREATE TABLE t2 AS SELECT * FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t1,t2; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 885803cb90f..57f4c82df87 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -1400,52 +1400,6 @@ drop table t1; --echo --echo # -- ---echo # -- Bug#21380: DEFAULT definition not always transfered by CREATE ---echo # -- TABLE/SELECT to the new table. ---echo # -- ---echo - - ---disable_warnings -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t2; ---enable_warnings - ---echo - -CREATE TABLE t1( - c1 INT DEFAULT 12 COMMENT 'column1', - c2 INT NULL COMMENT 'column2', - c3 INT NOT NULL COMMENT 'column3', - c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', - c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b', - c6 VARCHAR(255)) - COLLATE latin1_bin; - ---echo - -SHOW CREATE TABLE t1; - ---echo - -CREATE TABLE t2 AS SELECT * FROM t1; - ---echo - -SHOW CREATE TABLE t2; - ---echo - -DROP TABLE t2; -DROP TABLE t1; - ---echo ---echo # -- End of test case for Bug#21380. - -########################################################################### - ---echo ---echo # -- --echo # -- Bug#18834: ALTER TABLE ADD INDEX on table with two timestamp fields --echo # -- --echo diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index e247110658b..be1ca63d9e9 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -723,3 +723,34 @@ SELECT HEX(DAYNAME(19700101)); SET character_set_connection=latin1; --echo End of 5.0 tests + + +--echo Start of 5.1 tests +# +# Checking my_like_range_ucs2 +# +SET NAMES utf8; +CREATE TABLE t1 ( + a varchar(10) CHARACTER SET ucs2 COLLATE ucs2_czech_ci, + key(a) +); +INSERT INTO t1 VALUES +('aa'),('bb'),('cc'),('dd'),('ee'),('ff'),('gg'),('hh'),('ii'), +('jj'),('kk'),('ll'),('mm'),('nn'),('oo'),('pp'),('rr'),('ss'), +('tt'),('uu'),('vv'),('ww'),('xx'),('yy'),('zz'); +INSERT INTO t1 VALUES ('ca'),('cz'),('ch'); +INSERT INTO t1 VALUES ('da'),('dz'), (X'0064017E'); +# This one should scan only one row +EXPLAIN SELECT * FROM t1 WHERE a LIKE 'b%'; +# This one should scan many rows: 'c' is a contraction head +EXPLAIN SELECT * FROM t1 WHERE a LIKE 'c%'; +SELECT * FROM t1 WHERE a LIKE 'c%'; +EXPLAIN SELECT * FROM t1 WHERE a LIKE 'ch%'; +SELECT * FROM t1 WHERE a LIKE 'ch%'; +ALTER TABLE t1 MODIFY a VARCHAR(10) CHARACTER SET ucs2 COLLATE ucs2_croatian_ci; +EXPLAIN SELECT * FROM t1 WHERE a LIKE 'd%'; +SELECT hex(concat('d',_ucs2 0x017E,'%')); +EXPLAIN SELECT * FROM t1 WHERE a LIKE concat('d',_ucs2 0x017E,'%'); +SELECT hex(a) FROM t1 WHERE a LIKE concat('D',_ucs2 0x017E,'%'); + +DROP TABLE t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index bb64319f1e4..e222bc6b836 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -2,6 +2,15 @@ # Tests with the utf8 character set # +let collation=utf8_unicode_ci; +--source include/have_collation.inc + +--disable_warnings +drop table if exists t1,t2,t3,t4; +drop database if exists mysqltest; +--enable_warnings + + --disable_warnings drop table if exists t1,t2; --enable_warnings diff --git a/mysql-test/t/ddl_i18n_koi8r.test b/mysql-test/t/ddl_i18n_koi8r.test index fecef2f95d5..9df9806526c 100644 --- a/mysql-test/t/ddl_i18n_koi8r.test +++ b/mysql-test/t/ddl_i18n_koi8r.test @@ -36,6 +36,8 @@ --source include/have_cp866.inc --source include/have_cp1251.inc --source include/have_koi8r.inc +let collation=utf8_unicode_ci; +--source include/have_collation.inc ########################################################################### diff --git a/mysql-test/t/ddl_i18n_utf8.test b/mysql-test/t/ddl_i18n_utf8.test index 8788d0604f2..1d8c5676dee 100644 --- a/mysql-test/t/ddl_i18n_utf8.test +++ b/mysql-test/t/ddl_i18n_utf8.test @@ -36,6 +36,8 @@ --source include/have_cp866.inc --source include/have_cp1251.inc --source include/have_koi8r.inc +let collation=utf8_unicode_ci; +--source include/have_collation.inc ########################################################################### diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 9db55f6adaa..766e6d12cf4 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -2,6 +2,9 @@ # Test of fulltext index # +let collation=utf8_unicode_ci; +--source include/have_collation.inc + --disable_warnings drop table if exists t1,t2,t3; --enable_warnings diff --git a/mysql-test/t/fulltext2.test b/mysql-test/t/fulltext2.test index 9635e14d427..78c7c859e95 100644 --- a/mysql-test/t/fulltext2.test +++ b/mysql-test/t/fulltext2.test @@ -2,6 +2,9 @@ # test of new fulltext search features # +let collation=utf8_unicode_ci; +--source include/have_collation.inc + # # two-level tree # diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 6eb32b554bb..599c6f10d23 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -2353,18 +2353,6 @@ DELETE FROM t1; DROP TABLE t2,t1; # -# Bug #26835: table corruption after delete+insert -# - -CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY) -ENGINE=InnoDB; -INSERT INTO t1 VALUES (0xEFBCA4EFBCA4EFBCA4); -DELETE FROM t1; -INSERT INTO t1 VALUES ('DDD'); -SELECT * FROM t1; -DROP TABLE t1; - -# # Bug #23313 (AUTO_INCREMENT=# not reported back for InnoDB tables) # Bug #21404 (AUTO_INCREMENT value reset when Adding FKEY (or ALTER?)) # diff --git a/mysql-test/t/innodb_utf8.test b/mysql-test/t/innodb_utf8.test new file mode 100644 index 00000000000..e52019588b0 --- /dev/null +++ b/mysql-test/t/innodb_utf8.test @@ -0,0 +1,24 @@ +# +# Tests for innodb that requires not default character sets +# + +--source include/have_innodb.inc +let collation=utf8_unicode_ci; +--source include/have_collation.inc + +# Setup +--disable_warnings +drop table if exists t1; +--enable_warnings + +# +# Bug #26835: table corruption after delete+insert +# + +CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (0xEFBCA4EFBCA4EFBCA4); +DELETE FROM t1; +INSERT INTO t1 VALUES ('DDD'); +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/t/query_cache_ps_no_prot.test b/mysql-test/t/query_cache_ps_no_prot.test index 6f4263eeef9..16533c7194e 100644 --- a/mysql-test/t/query_cache_ps_no_prot.test +++ b/mysql-test/t/query_cache_ps_no_prot.test @@ -11,8 +11,9 @@ # We cannot run on embedded server because we use multiple sessions. --source include/not_embedded.inc - --source include/have_query_cache.inc +let collation=utf8_unicode_ci; +--source include/have_collation.inc # The file with expected results fits only to a run without # ps-protocol/sp-protocol/cursor-protocol/view-protocol. diff --git a/mysql-test/t/query_cache_ps_ps_prot.test b/mysql-test/t/query_cache_ps_ps_prot.test index dc49624788a..d431ce349d2 100644 --- a/mysql-test/t/query_cache_ps_ps_prot.test +++ b/mysql-test/t/query_cache_ps_ps_prot.test @@ -11,8 +11,9 @@ # We cannot run on embedded server because we use multiple sessions. --source include/not_embedded.inc - --source include/have_query_cache.inc +let collation=utf8_unicode_ci; +--source include/have_collation.inc # The file with expected results fits only to a run with "--ps-protocol". if (`SELECT $SP_PROTOCOL + $CURSOR_PROTOCOL + $VIEW_PROTOCOL > 0 diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test index 3c9129aedb1..508fc35d02c 100644 --- a/mysql-test/t/warnings.test +++ b/mysql-test/t/warnings.test @@ -194,7 +194,6 @@ DROP PROCEDURE sp1; DROP PROCEDURE sp2; DROP PROCEDURE sp3; - # # Bug#30059: End-space truncation warnings are inconsistent or incorrect # @@ -235,3 +234,15 @@ DROP TABLE t1; SHOW ERRORS; --echo End of 5.0 tests + +# +# Test warning with row numbers +# + +set sql_mode = default; +select CAST(a AS DECIMAL(13,5)) FROM (SELECT '' as a) t; +create table t1 (a integer unsigned); +insert into t1 values (1),(-1),(0),(-2); +drop table t1; + +--echo End of 5.1 tests diff --git a/plugin/fulltext/plugin_example.c b/plugin/fulltext/plugin_example.c index ab4f1f178d7..87eb7f3e150 100644 --- a/plugin/fulltext/plugin_example.c +++ b/plugin/fulltext/plugin_example.c @@ -145,7 +145,7 @@ static int simple_parser_deinit(MYSQL_FTPARSER_PARAM *param the list of search terms when parsing a search string. */ -static void add_word(MYSQL_FTPARSER_PARAM *param, char *word, size_t len) +static void add_word(MYSQL_FTPARSER_PARAM *param, const unsigned char *word, size_t len) { MYSQL_FTPARSER_BOOLEAN_INFO bool_info= { FT_TOKEN_WORD, 0, 0, 0, 0, ' ', 0 }; @@ -169,11 +169,11 @@ static void add_word(MYSQL_FTPARSER_PARAM *param, char *word, size_t len) static int simple_parser_parse(MYSQL_FTPARSER_PARAM *param) { - char *end, *start, *docend= (char *)param->doc + param->length; + const unsigned char *end, *start, *docend= param->doc + param->length; number_of_calls++; - for (end= start= (char *)param->doc;; end++) + for (end= start= param->doc;; end++) { if (end == docend) { diff --git a/scripts/mysqlbug.sh b/scripts/mysqlbug.sh index 64804b5de19..f0534d0e1e9 100644 --- a/scripts/mysqlbug.sh +++ b/scripts/mysqlbug.sh @@ -21,7 +21,7 @@ echo "Finding system information for a MySQL bug report" VERSION="@VERSION@@MYSQL_SERVER_SUFFIX@" COMPILATION_COMMENT="@COMPILATION_COMMENT@" -BUGmysql="mysql@lists.mysql.com" +BUGmysql="maria-developers@lists.launchpad.net" # This is set by configure COMP_CALL_INFO="CC='@SAVE_CC@' CFLAGS='@SAVE_CFLAGS@' CXX='@SAVE_CXX@' CXXFLAGS='@SAVE_CXXFLAGS@' LDFLAGS='@SAVE_LDFLAGS@' ASFLAGS='@SAVE_ASFLAGS@'" COMP_RUN_INFO="CC='@CC@' CFLAGS='@CFLAGS@' CXX='@CXX@' CXXFLAGS='@CXXFLAGS@' LDFLAGS='@LDFLAGS@' ASFLAGS='@ASFLAGS@'" diff --git a/sql-common/client.c b/sql-common/client.c index 9a8444a84e9..56d4cf04044 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -3208,7 +3208,7 @@ const char * STDCALL mysql_error(MYSQL *mysql) mysql Connection EXAMPLE - 4.1.0-alfa -> 40100 + MariaDB-4.1.0-alfa -> 40100 NOTES We will ensure that a newer server always has a bigger number. @@ -3221,7 +3221,11 @@ ulong STDCALL mysql_get_server_version(MYSQL *mysql) { uint major, minor, version; - char *pos= mysql->server_version, *end_pos; + const char *pos= mysql->server_version; + char *end_pos; + /* Skip possible prefix */ + while (*pos && !my_isdigit(&my_charset_latin1, *pos)) + pos++; major= (uint) strtoul(pos, &end_pos, 10); pos=end_pos+1; minor= (uint) strtoul(pos, &end_pos, 10); pos=end_pos+1; version= (uint) strtoul(pos, &end_pos, 10); diff --git a/sql/handler.cc b/sql/handler.cc index d511aa154ce..6900713af80 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1585,16 +1585,6 @@ int ha_recover(HASH *commit_list) if (info.commit_list) sql_print_information("Starting crash recovery..."); -#ifndef WILL_BE_DELETED_LATER - /* - for now, only InnoDB supports 2pc. It means we can always safely - rollback all pending transactions, without risking inconsistent data - */ - DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog - tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK - info.dry_run=FALSE; -#endif - for (info.len= MAX_XID_LIST_SIZE ; info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2) { diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index 208ddefb890..8b15ef4e586 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -38,7 +38,7 @@ int decimal_operation_results(int result) case E_DEC_TRUNCATED: push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, ER(WARN_DATA_TRUNCATED), - "", (long)-1); + "", (ulong) 0); break; case E_DEC_OVERFLOW: push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, @@ -54,7 +54,7 @@ int decimal_operation_results(int result) push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), - "decimal", "", "", (long)-1); + "decimal", "", "", (ulong) 0); break; case E_DEC_OOM: my_error(ER_OUT_OF_RESOURCES, MYF(0)); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 750a221a785..25144c15f89 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4196,8 +4196,10 @@ server."); Need to unlock as global_system_variables.table_plugin was acquired during plugin_init() */ + pthread_mutex_lock(&LOCK_global_system_variables); plugin_unlock(0, global_system_variables.table_plugin); global_system_variables.table_plugin= plugin; + pthread_mutex_unlock(&LOCK_global_system_variables); } } #if defined(WITH_MARIA_STORAGE_ENGINE) && defined(USE_MARIA_FOR_TMP_TABLES) diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index a8839425aa7..ce840da5f89 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -3173,22 +3173,22 @@ ER_CANT_CREATE_THREAD swe "Kan inte skapa en ny tråd (errno %d)" ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÎÏ×Õ Ç¦ÌËÕ (ÐÏÍÉÌËÁ %d). ñËÝÏ ×É ÎÅ ×ÉËÏÒÉÓÔÁÌÉ ÕÓÀ ÐÁÍ'ÑÔØ, ÔÏ ÐÒÏÞÉÔÁÊÔÅ ÄÏËÕÍÅÎÔÁæÀ ÄÏ ×ÁÛϧ ïó - ÍÏÖÌÉ×Ï ÃÅ ÐÏÍÉÌËÁ ïó" ER_WRONG_VALUE_COUNT_ON_ROW 21S01 - cze "Po-Bèet sloupcù neodpovídá poètu hodnot na øádku %ld" - dan "Kolonne antallet stemmer ikke overens med antallet af værdier i post %ld" - nla "Kolom aantal komt niet overeen met waarde aantal in rij %ld" - eng "Column count doesn't match value count at row %ld" - est "Tulpade hulk erineb väärtuste hulgast real %ld" - ger "Anzahl der Felder stimmt nicht mit der Anzahl der Werte in Zeile %ld überein" - hun "Az oszlopban talalhato ertek nem egyezik meg a %ld sorban szamitott ertekkel" - ita "Il numero delle colonne non corrisponde al conteggio alla riga %ld" - kor "Row %ld¿¡¼ Ä®·³ Ä«¿îÆ®¿Í value Ä«¿îÅÍ¿Í ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù." - por "Contagem de colunas não confere com a contagem de valores na linha %ld" - rum "Numarul de coloane nu corespunde cu numarul de valori la linia %ld" - rus "ëÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ× ÎÅ ÓÏ×ÐÁÄÁÅÔ Ó ËÏÌÉÞÅÓÔ×ÏÍ ÚÎÁÞÅÎÉÊ × ÚÁÐÉÓÉ %ld" - serbian "Broj kolona ne odgovara broju vrednosti u slogu %ld" - spa "El número de columnas no corresponde al número en la línea %ld" - swe "Antalet kolumner motsvarar inte antalet värden på rad: %ld" - ukr "ë¦ÌØ˦ÓÔØ ÓÔÏ×ÂÃ¦× ÎÅ ÓЦ×ÐÁÄÁ¤ Ú Ë¦ÌØ˦ÓÔÀ ÚÎÁÞÅÎØ Õ ÓÔÒÏæ %ld" + cze "Po-Bèet sloupcù neodpovídá poètu hodnot na øádku %lu" + dan "Kolonne antallet stemmer ikke overens med antallet af værdier i post %lu" + nla "Kolom aantal komt niet overeen met waarde aantal in rij %lu" + eng "Column count doesn't match value count at row %lu" + est "Tulpade hulk erineb väärtuste hulgast real %lu" + ger "Anzahl der Felder stimmt nicht mit der Anzahl der Werte in Zeile %lu überein" + hun "Az oszlopban talalhato ertek nem egyezik meg a %lu sorban szamitott ertekkel" + ita "Il numero delle colonne non corrisponde al conteggio alla riga %lu" + kor "Row %lu¿¡¼ Ä®·³ Ä«¿îÆ®¿Í value Ä«¿îÅÍ¿Í ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù." + por "Contagem de colunas não confere com a contagem de valores na linha %lu" + rum "Numarul de coloane nu corespunde cu numarul de valori la linia %lu" + rus "ëÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ× ÎÅ ÓÏ×ÐÁÄÁÅÔ Ó ËÏÌÉÞÅÓÔ×ÏÍ ÚÎÁÞÅÎÉÊ × ÚÁÐÉÓÉ %lu" + serbian "Broj kolona ne odgovara broju vrednosti u slogu %lu" + spa "El número de columnas no corresponde al número en la línea %lu" + swe "Antalet kolumner motsvarar inte antalet värden på rad: %lu" + ukr "ë¦ÌØ˦ÓÔØ ÓÔÏ×ÂÃ¦× ÎÅ ÓЦ×ÐÁÄÁ¤ Ú Ë¦ÌØ˦ÓÔÀ ÚÎÁÞÅÎØ Õ ÓÔÒÏæ %lu" ER_CANT_REOPEN_TABLE cze "Nemohu znovuotev-Bøít tabulku: '%-.192s" dan "Kan ikke genåbne tabel '%-.192s" @@ -4887,29 +4887,29 @@ ER_CUT_VALUE_GROUP_CONCAT swe "%d rad(er) kapades av group_concat()" ukr "%d line(s) was(were) cut by group_concat()" ER_WARN_TOO_FEW_RECORDS 01000 - eng "Row %ld doesn't contain data for all columns" - ger "Zeile %ld enthält nicht für alle Felder Daten" - nla "Rij %ld bevat niet de data voor alle kolommen" - por "Conta de registro é menor que a conta de coluna na linha %ld" - spa "Línea %ld no contiene datos para todas las columnas" + eng "Row %lu doesn't contain data for all columns" + ger "Zeile %lu enthält nicht für alle Felder Daten" + nla "Rij %lu bevat niet de data voor alle kolommen" + por "Conta de registro é menor que a conta de coluna na linha %lu" + spa "Línea %lu no contiene datos para todas las columnas" ER_WARN_TOO_MANY_RECORDS 01000 - eng "Row %ld was truncated; it contained more data than there were input columns" - ger "Zeile %ld gekürzt, die Zeile enthielt mehr Daten, als es Eingabefelder gibt" - nla "Regel %ld ingekort, bevatte meer data dan invoer kolommen" - por "Conta de registro é maior que a conta de coluna na linha %ld" - spa "Línea %ld fué truncada; La misma contine mas datos que las que existen en las columnas de entrada" + eng "Row %lu was truncated; it contained more data than there were input columns" + ger "Zeile %lu gekürzt, die Zeile enthielt mehr Daten, als es Eingabefelder gibt" + nla "Regel %lu ingekort, bevatte meer data dan invoer kolommen" + por "Conta de registro é maior que a conta de coluna na linha %lu" + spa "Línea %lu fué truncada; La misma contine mas datos que las que existen en las columnas de entrada" ER_WARN_NULL_TO_NOTNULL 22004 - eng "Column set to default value; NULL supplied to NOT NULL column '%s' at row %ld" - ger "Feld auf Vorgabewert gesetzt, da NULL für NOT-NULL-Feld '%s' in Zeile %ld angegeben" - por "Dado truncado, NULL fornecido para NOT NULL coluna '%s' na linha %ld" - spa "Datos truncado, NULL suministrado para NOT NULL columna '%s' en la línea %ld" + eng "Column set to default value; NULL supplied to NOT NULL column '%s' at row %lu" + ger "Feld auf Vorgabewert gesetzt, da NULL für NOT-NULL-Feld '%s' in Zeile %lu angegeben" + por "Dado truncado, NULL fornecido para NOT NULL coluna '%s' na linha %lu" + spa "Datos truncado, NULL suministrado para NOT NULL columna '%s' en la línea %lu" ER_WARN_DATA_OUT_OF_RANGE 22003 - eng "Out of range value for column '%s' at row %ld" + eng "Out of range value for column '%s' at row %lu" WARN_DATA_TRUNCATED 01000 - eng "Data truncated for column '%s' at row %ld" - ger "Daten abgeschnitten für Feld '%s' in Zeile %ld" - por "Dado truncado para coluna '%s' na linha %ld" - spa "Datos truncados para columna '%s' en la línea %ld" + eng "Data truncated for column '%s' at row %lu" + ger "Daten abgeschnitten für Feld '%s' in Zeile %lu" + por "Dado truncado para coluna '%s' na linha %lu" + spa "Datos truncados para columna '%s' en la línea %lu" ER_WARN_USING_OTHER_HANDLER eng "Using storage engine %s for table '%s'" ger "Für Tabelle '%s' wird Speicher-Engine %s benutzt" @@ -5090,8 +5090,8 @@ ER_UNKNOWN_TIME_ZONE eng "Unknown or incorrect time zone: '%-.64s'" ger "Unbekannte oder falsche Zeitzone: '%-.64s'" ER_WARN_INVALID_TIMESTAMP - eng "Invalid TIMESTAMP value in column '%s' at row %ld" - ger "Ungültiger TIMESTAMP-Wert in Feld '%s', Zeile %ld" + eng "Invalid TIMESTAMP value in column '%s' at row %lu" + ger "Ungültiger TIMESTAMP-Wert in Feld '%s', Zeile %lu" ER_INVALID_CHARACTER_STRING eng "Invalid %s character string: '%.64s'" ger "Ungültiger %s-Zeichen-String: '%.64s'" @@ -5322,8 +5322,8 @@ ER_DIVISION_BY_ZERO 22012 eng "Division by 0" ger "Division durch 0" ER_TRUNCATED_WRONG_VALUE_FOR_FIELD - eng "Incorrect %-.32s value: '%-.128s' for column '%.192s' at row %ld" - ger "Falscher %-.32s-Wert: '%-.128s' für Feld '%.192s' in Zeile %ld" + eng "Incorrect %-.32s value: '%-.128s' for column '%.192s' at row %lu" + ger "Falscher %-.32s-Wert: '%-.128s' für Feld '%.192s' in Zeile %lu" ER_ILLEGAL_VALUE_FOR_TYPE 22007 eng "Illegal %s '%-.192s' value found during parsing" ger "Nicht zulässiger %s-Wert '%-.192s' beim Parsen gefunden" @@ -5456,8 +5456,8 @@ ER_PROC_AUTO_REVOKE_FAIL eng "Failed to revoke all privileges to dropped routine" ger "Rücknahme aller Rechte für die gelöschte Routine fehlgeschlagen" ER_DATA_TOO_LONG 22001 - eng "Data too long for column '%s' at row %ld" - ger "Daten zu lang für Feld '%s' in Zeile %ld" + eng "Data too long for column '%s' at row %lu" + ger "Daten zu lang für Feld '%s' in Zeile %lu" ER_SP_BAD_SQLSTATE 42000 eng "Bad SQLSTATE: '%s'" ger "Ungültiger SQLSTATE: '%s'" diff --git a/sql/slave.cc b/sql/slave.cc index 94e20b594fb..5de79d55b31 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1117,18 +1117,27 @@ be equal for the Statement-format replication to work"; goto err; } } - else if (is_network_error(mysql_errno(mysql))) + else if (is_network_error(err_code= mysql_errno(mysql))) { - mi->report(WARNING_LEVEL, mysql_errno(mysql), - "Get master TIME_ZONE failed with error: %s", mysql_error(mysql)); + mi->report(ERROR_LEVEL, err_code, + "Get master TIME_ZONE failed with error: %s", + mysql_error(mysql)); goto network_err; - } + } + else if (err_code == ER_UNKNOWN_SYSTEM_VARIABLE) + { + /* We use ERROR_LEVEL to get the error logged to file */ + mi->report(ERROR_LEVEL, err_code, + + "MySQL master doesn't have a TIME_ZONE variable. Note that" + "if your timezone is not same between master and slave, your " + "slave may get wrong data into timestamp columns"); + } else { /* Fatal error */ errmsg= "The slave I/O thread stops because a fatal error is encountered \ when it try to get the value of TIME_ZONE global variable from master."; - err_code= mysql_errno(mysql); sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql)); goto err; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 580a6f7246f..99dad6e366b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8631,19 +8631,26 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, result=1; } /* Kill delayed insert threads */ - if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) && - ! in_use->killed) + if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT)) { - in_use->killed= THD::KILL_CONNECTION; - pthread_mutex_lock(&in_use->mysys_var->mutex); - if (in_use->mysys_var->current_cond) - { - pthread_mutex_lock(in_use->mysys_var->current_mutex); - signalled= 1; - pthread_cond_broadcast(in_use->mysys_var->current_cond); - pthread_mutex_unlock(in_use->mysys_var->current_mutex); - } - pthread_mutex_unlock(&in_use->mysys_var->mutex); + if (!in_use->killed) + { + in_use->killed= THD::KILL_CONNECTION; + pthread_mutex_lock(&in_use->mysys_var->mutex); + if (in_use->mysys_var->current_cond) + { + pthread_mutex_lock(in_use->mysys_var->current_mutex); + signalled= 1; + pthread_cond_broadcast(in_use->mysys_var->current_cond); + pthread_mutex_unlock(in_use->mysys_var->current_mutex); + } + pthread_mutex_unlock(&in_use->mysys_var->mutex); + } + /* + Don't abort locks. Instead give the delayed insert thread + time to finish it's inserts and die gracefully. + */ + continue; } /* Now we must abort all tables locks used by this thread diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 83108f58c68..8b23af4de37 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2170,7 +2170,7 @@ bool select_export::send_data(List<Item> &items) ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), "string", printable_buff, - item->name, row_count); + item->name, (ulong) row_count); } cvt_str.length(bytes); res= &cvt_str; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 278d0485c45..0ab18290eda 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2622,7 +2622,7 @@ bool Delayed_insert::handle_inserts(void) or if another thread is removing the current table definition from the table cache. */ - my_error(ER_DELAYED_CANT_CHANGE_LOCK,MYF(ME_FATALERROR), + my_error(ER_DELAYED_CANT_CHANGE_LOCK, MYF(ME_FATALERROR | ME_NOREFRESH), table->s->table_name.str); goto err; } @@ -2795,10 +2795,11 @@ bool Delayed_insert::handle_inserts(void) query_cache_invalidate3(&thd, table, 1); if (thr_reschedule_write_lock(*thd.lock->locks)) { - /* This is not known to happen. */ - my_error(ER_DELAYED_CANT_CHANGE_LOCK,MYF(ME_FATALERROR), - table->s->table_name.str); - goto err; + /* This is not known to happen. */ + my_error(ER_DELAYED_CANT_CHANGE_LOCK, + MYF(ME_FATALERROR | ME_NOREFRESH), + table->s->table_name.str); + goto err; } if (!using_bin_log) table->file->extra(HA_EXTRA_WRITE_CACHE); diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index 308215fe839..e06f39c073f 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -1,5 +1,5 @@ /* -Copyright (c) 2008, Patrick Galbraith +Copyright (c) 2008-2009, Patrick Galbraith & Antony Curtis All rights reserved. Redistribution and use in source and binary forms, with or without @@ -308,7 +308,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define MYSQL_SERVER 1q +#define MYSQL_SERVER 1 #include "mysql_priv.h" #include <mysql/plugin.h> @@ -1627,7 +1627,13 @@ static int free_server(federatedx_txn *txn, FEDERATEDX_SERVER *server) { MEM_ROOT mem_root; - txn->close(server); + if (!txn) + { + federatedx_txn tmp_txn; + tmp_txn.close(server); + } + else + txn->close(server); DBUG_ASSERT(server->io_count == 0); @@ -1785,21 +1791,25 @@ int ha_federatedx::close(void) if (stored_result) retval= free_result(); - /* Disconnect from mysql. thd may be null during refresh */ - txn= thd ? get_txn(thd, true) : new federatedx_txn(); + /* Disconnect from mysql */ + if (!thd || !(txn= get_txn(thd, true))) + { + federatedx_txn tmp_txn; + + tmp_txn.release(&io); - if (txn) + DBUG_ASSERT(io == NULL); + + if ((error= free_share(&tmp_txn, share))) + retval= error; + } + else { txn->release(&io); - DBUG_ASSERT(io == NULL); if ((error= free_share(txn, share))) retval= error; - - if (!thd) - delete txn; - } DBUG_RETURN(retval); } @@ -2793,14 +2803,16 @@ int ha_federatedx::rnd_end() int ha_federatedx::free_result() { int error; + federatedx_io *tmp_io= 0, **iop; DBUG_ASSERT(stored_result); - if ((error= txn->acquire(share, FALSE, &io))) + if (!*(iop= &io) && (error= txn->acquire(share, TRUE, (iop= &tmp_io)))) { DBUG_ASSERT(0); // Fail when testing return error; } - io->free_result(stored_result); + (*iop)->free_result(stored_result); stored_result= 0; + txn->release(&tmp_io); return 0; } @@ -2985,7 +2997,7 @@ int ha_federatedx::info(uint flag) { char error_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; uint error_code; - federatedx_io *tmp_io= 0; + federatedx_io *tmp_io= 0, **iop= 0; DBUG_ENTER("ha_federatedx::info"); error_code= ER_QUERY_ON_FOREIGN_DATA_SOURCE; @@ -2993,7 +3005,7 @@ int ha_federatedx::info(uint flag) /* we want not to show table status if not needed to do so */ if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_AUTO)) { - if ((error_code= txn->acquire(share, TRUE, &tmp_io))) + if (!*(iop= &io) && (error_code= txn->acquire(share, TRUE, (iop= &tmp_io)))) goto fail; } @@ -3006,13 +3018,13 @@ int ha_federatedx::info(uint flag) if (flag & HA_STATUS_CONST) stats.block_size= 4096; - if (tmp_io->table_metadata(&stats, share->table_name, + if ((*iop)->table_metadata(&stats, share->table_name, share->table_name_length, flag)) goto error; } if (flag & HA_STATUS_AUTO) - stats.auto_increment_value= tmp_io->last_insert_id(); + stats.auto_increment_value= (*iop)->last_insert_id(); /* If ::info created it's own transaction, close it. This happens in case @@ -3023,10 +3035,10 @@ int ha_federatedx::info(uint flag) DBUG_RETURN(0); error: - if (tmp_io) + if (iop && *iop) { my_sprintf(error_buffer, (error_buffer, ": %d : %s", - tmp_io->error_code(), tmp_io->error_str())); + (*iop)->error_code(), (*iop)->error_str())); my_error(error_code, MYF(0), error_buffer); } else diff --git a/storage/ndb/plug.in b/storage/ndb/plug.in index a7e351417b1..3d3349f7a8b 100644 --- a/storage/ndb/plug.in +++ b/storage/ndb/plug.in @@ -1,5 +1,5 @@ MYSQL_STORAGE_ENGINE(ndbcluster, ndbcluster, [Cluster Storage Engine], - [High Availability Clustered tables], [max]) + [High Availability Clustered tables],) MYSQL_PLUGIN_DIRECTORY(ndbcluster,[storage/ndb]) MYSQL_PLUGIN_STATIC(ndbcluster, [[\$(ndbcluster_libs) \$(ndbcluster_system_libs) \$(NDB_SCI_LIBS)]]) MYSQL_PLUGIN_ACTIONS(ndbcluster,[MYSQL_SETUP_NDBCLUSTER]) diff --git a/storage/pbxt/ChangeLog b/storage/pbxt/ChangeLog index dabfea6c168..eb0613b8c68 100644 --- a/storage/pbxt/ChangeLog +++ b/storage/pbxt/ChangeLog @@ -1,6 +1,58 @@ PBXT Release Notes ================== +------- 1.0.09f RC3 - 2009-11-30 + +RN291: Fixed bug #489088: On shutdown MySQL reports: [Warning] Plugin 'PBXT' will be forced to shutdown. + +RN290: Fixed bug #345524: pbxt does not compile on 64 bit windows. Currently atomic operations are not supported on this platform. + +RN286: Fixed a bug introduced in RN281, which could cause an index scan to hang. The original change was to prevent a warning in Valgrind. + +RN285: Merged changes required to compile with Drizzle. + +RN284: Fixed bug that cause the error "[ERROR] Invalid (old?) table or database name 'mysqld.1'", when running temp_table.test under MariaDB (thanks to Monty for his initial bug fix). Added a fix for partition table names as well. + +RN283: Added win_inttypes.h to the distribution. This file is only required for the Windows build. + +RN282: Fixed bug #451101: jump or move depends on uninitialised value in myxt_get_key_length + +RN281: Fixed bug #451080: Uninitialised memory write in XTDatabaseLog::xlog_append + +RN280: Fixed bug #451085: jump or move depends on uninitialised value in my_type_to_string + +RN279: Fixed bug #441000: xtstat crashes with segmentation fault on startup if max_pbxt_threads exceeded. + +------- 1.0.09e RC3 - 2009-11-20 + +RN278: Fixed compile error with MySQL 5.1.41. + +------- 1.0.09d RC3 - 2009-09-30 + +RN277: Added r/o flag to pbxt_max_threads server variable (this fix is related to bug #430637) + +RN276: Added test case for replication on tables w/o PKs (see bug #430716) + +RN275: Fixed bug #430600: 'Failed to read auto-increment value from storage engine' error. + +RN274: Fixed bug #431240: This report is public edit xtstat fails if no PBXT table has been created. xtstat now accepts --database=information_schema or --database=pbxt. Depending on this setting PBXT will either use the information_schema.pbxt_statistics or the pbxt.statistics table. If information_schema is used, then the statistics are displayed even when no PBXT table exists. Recovery activity is also displayed, unless pbxt_support_xa=1, in which case MySQL will wait for PBXT recovery to complete before allowing connections. + +RN273: Fixed bug #430633: XA_RBDEADLOCK is not returned on XA END after the transacting ended with a deadlock. + +RN272: Fixed bug #430596: Backup/restore does not work well even on a basic PBXT table with auto-increment. + +------- 1.0.09c RC3 - 2009-09-16 + +RN271: Windows build update: now you can simply put the pbxt directory under <mysql-root>/storage and build the PBXT engine as a part of the source tree. The engine will be linked statically. Be sure to specify the WITH_PBXT_STORAGE_ENGINE option when running win\configure.js + +RN270: Correctly disabled PBMS so that this version now compiles under Windows. If PBMS_ENABLED is defined, PBXT will not compile under Windows becaause of a getpid() call in pbms.h. + +------- 1.0.09 RC3 - 2009-09-09 + +RN269: Implemented online backup. A native online backup driver now performs BACKUP and RESTORE DATABASE operations for PBXT. NOTE: This feature is only supported by MySQL 6.0.9 or later. + +RN268: Implemented XA support. PBXT now supports all XA related MySQL statements. The variable pbxt_support_xa determines if XA support is enabled. Note: due to MySQL bug #47134, enabling XA support could lead to a crash. + ------- 1.0.08d RC2 - 2009-09-02 RN267: Fixed a bug that caused MySQL to crash on shutdown, after an incorrect command line parameter was given. The crash occurred because the background recovery task was not cleaned up before the PBXT engine was de-initialized. diff --git a/storage/pbxt/src/Makefile.am b/storage/pbxt/src/Makefile.am index a09d8f0a57b..5644517bcc0 100644 --- a/storage/pbxt/src/Makefile.am +++ b/storage/pbxt/src/Makefile.am @@ -22,7 +22,7 @@ noinst_HEADERS = bsearch_xt.h cache_xt.h ccutils_xt.h database_xt.h \ pbms_enabled.h sortedlist_xt.h strutil_xt.h \ tabcache_xt.h table_xt.h trace_xt.h thread_xt.h \ util_xt.h xaction_xt.h xactlog_xt.h lock_xt.h \ - systab_xt.h ha_xtsys.h discover_xt.h \ + systab_xt.h ha_xtsys.h discover_xt.h backup_xt.h \ pbms.h xt_config.h xt_defs.h xt_errno.h locklist_xt.h EXTRA_LTLIBRARIES = libpbxt.la @@ -32,7 +32,7 @@ libpbxt_la_SOURCES = bsearch_xt.cc cache_xt.cc ccutils_xt.cc database_xt.cc \ memory_xt.cc myxt_xt.cc pthread_xt.cc restart_xt.cc \ sortedlist_xt.cc strutil_xt.cc \ tabcache_xt.cc table_xt.cc trace_xt.cc thread_xt.cc \ - systab_xt.cc ha_xtsys.cc discover_xt.cc \ + systab_xt.cc ha_xtsys.cc discover_xt.cc backup_xt.cc \ util_xt.cc xaction_xt.cc xactlog_xt.cc lock_xt.cc locklist_xt.cc libpbxt_la_LDFLAGS = -module diff --git a/storage/pbxt/src/backup_xt.cc b/storage/pbxt/src/backup_xt.cc new file mode 100644 index 00000000000..da88c363822 --- /dev/null +++ b/storage/pbxt/src/backup_xt.cc @@ -0,0 +1,802 @@ +/* Copyright (c) 2009 PrimeBase Technologies GmbH + * + * PrimeBase XT + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * 2009-09-07 Paul McCullagh + * + * H&G2JCtL + */ + +#include "xt_config.h" + +#ifdef MYSQL_SUPPORTS_BACKUP + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> + +#include "mysql_priv.h" +#include <backup/api_types.h> +#include <backup/backup_engine.h> +#include <backup/backup_aux.h> // for build_table_list() +#include <hash.h> + +#include "ha_pbxt.h" + +#include "backup_xt.h" +#include "pthread_xt.h" +#include "filesys_xt.h" +#include "database_xt.h" +#include "strutil_xt.h" +#include "memory_xt.h" +#include "trace_xt.h" +#include "myxt_xt.h" + +#ifdef OK +#undef OK +#endif + +#ifdef byte +#undef byte +#endif + +#ifdef DEBUG +//#define TRACE_BACKUP_CALLS +//#define TEST_SMALL_BLOCK 100000 +#endif + +using backup::byte; +using backup::result_t; +using backup::version_t; +using backup::Table_list; +using backup::Table_ref; +using backup::Buffer; + +#ifdef TRACE_BACKUP_CALLS +#define XT_TRACE_CALL() ha_trace_function(__FUNC__, NULL) +#else +#define XT_TRACE_CALL() +#endif + +#define XT_RESTORE_BATCH_SIZE 10000 + +#define BUP_STATE_BEFORE_LOCK 0 +#define BUP_STATE_AFTER_LOCK 1 + +#define BUP_STANDARD_VAR_RECORD 1 +#define BUP_RECORD_BLOCK_4_START 2 // Part of a record, with a 4 byte total length, and 4 byte data length +#define BUP_RECORD_BLOCK_4 3 // Part of a record, with a 4 byte length +#define BUP_RECORD_BLOCK_4_END 4 // Last part of a record with a 4 byte length + +/* + * ----------------------------------------------------------------------- + * UTILITIES + */ + +#ifdef TRACE_BACKUP_CALLS +static void ha_trace_function(const char *function, char *table) +{ + char func_buf[50], *ptr; + XTThreadPtr thread = xt_get_self(); + + if ((ptr = strchr(function, '('))) { + ptr--; + while (ptr > function) { + if (!(isalnum(*ptr) || *ptr == '_')) + break; + ptr--; + } + ptr++; + xt_strcpy(50, func_buf, ptr); + if ((ptr = strchr(func_buf, '('))) + *ptr = 0; + } + else + xt_strcpy(50, func_buf, function); + if (table) + printf("%s %s (%s)\n", thread ? thread->t_name : "-unknown-", func_buf, table); + else + printf("%s %s\n", thread ? thread->t_name : "-unknown-", func_buf); +} +#endif + +/* + * ----------------------------------------------------------------------- + * BACKUP DRIVER + */ + +class PBXTBackupDriver: public Backup_driver +{ + public: + PBXTBackupDriver(const Table_list &); + virtual ~PBXTBackupDriver(); + + virtual size_t size(); + virtual size_t init_size(); + virtual result_t begin(const size_t); + virtual result_t end(); + virtual result_t get_data(Buffer &); + virtual result_t prelock(); + virtual result_t lock(); + virtual result_t unlock(); + virtual result_t cancel(); + virtual void free(); + void lock_tables_TL_READ_NO_INSERT(); + + private: + XTThreadPtr bd_thread; + int bd_state; + u_int bd_table_no; + XTOpenTablePtr bd_ot; + xtWord1 *bd_row_buf; + + /* Non-zero if we last returned only part of + * a row. + */ + xtWord1 *db_write_block(xtWord1 *buffer, xtWord1 bup_type, size_t *size, xtWord4 row_len); + xtWord1 *db_write_block(xtWord1 *buffer, xtWord1 bup_type, size_t *size, xtWord4 total_len, xtWord4 row_len); + + xtWord4 bd_row_offset; + xtWord4 bd_row_size; +}; + + +PBXTBackupDriver::PBXTBackupDriver(const Table_list &tables): +Backup_driver(tables), +bd_state(BUP_STATE_BEFORE_LOCK), +bd_table_no(0), +bd_ot(NULL), +bd_row_buf(NULL), +bd_row_offset(0), +bd_row_size(0) +{ +} + +PBXTBackupDriver::~PBXTBackupDriver() +{ +} + +/** Estimates total size of backup. @todo improve it */ +size_t PBXTBackupDriver::size() +{ + XT_TRACE_CALL(); + return UNKNOWN_SIZE; +} + +/** Estimates size of backup before lock. @todo improve it */ +size_t PBXTBackupDriver::init_size() +{ + XT_TRACE_CALL(); + return 0; +} + +result_t PBXTBackupDriver::begin(const size_t) +{ + THD *thd = current_thd; + XTExceptionRec e; + + XT_TRACE_CALL(); + + if (!(bd_thread = xt_ha_set_current_thread(thd, &e))) { + xt_log_exception(NULL, &e, XT_LOG_DEFAULT); + return backup::ERROR; + } + + return backup::OK; +} + +result_t PBXTBackupDriver::end() +{ + XT_TRACE_CALL(); + if (bd_ot) { + xt_tab_seq_exit(bd_ot); + xt_db_return_table_to_pool_ns(bd_ot); + bd_ot = NULL; + } + if (bd_thread->st_xact_data) { + if (!xt_xn_commit(bd_thread)) + return backup::ERROR; + } + return backup::OK; +} + +xtWord1 *PBXTBackupDriver::db_write_block(xtWord1 *buffer, xtWord1 bup_type, size_t *ret_size, xtWord4 row_len) +{ + register size_t size = *ret_size; + + *buffer = bup_type; // Record type identifier. + buffer++; + size--; + memcpy(buffer, bd_ot->ot_row_wbuffer, row_len); + buffer += row_len; + size -= row_len; + *ret_size = size; + return buffer; +} + +xtWord1 *PBXTBackupDriver::db_write_block(xtWord1 *buffer, xtWord1 bup_type, size_t *ret_size, xtWord4 total_len, xtWord4 row_len) +{ + register size_t size = *ret_size; + + *buffer = bup_type; // Record type identifier. + buffer++; + size--; + if (bup_type == BUP_RECORD_BLOCK_4_START) { + XT_SET_DISK_4(buffer, total_len); + buffer += 4; + size -= 4; + } + XT_SET_DISK_4(buffer, row_len); + buffer += 4; + size -= 4; + memcpy(buffer, bd_ot->ot_row_wbuffer+bd_row_offset, row_len); + buffer += row_len; + size -= row_len; + bd_row_size -= row_len; + bd_row_offset += row_len; + *ret_size = size; + return buffer; +} + +result_t PBXTBackupDriver::get_data(Buffer &buf) +{ + xtBool eof = FALSE; + size_t size; + xtWord4 row_len; + xtWord1 *buffer; + + XT_TRACE_CALL(); + + if (bd_state == BUP_STATE_BEFORE_LOCK) { + buf.table_num = 0; + buf.size = 0; + buf.last = FALSE; + return backup::READY; + } + + /* Open the backup table: */ + if (!bd_ot) { + XTThreadPtr self = bd_thread; + XTTableHPtr tab; + char path[PATH_MAX]; + + if (bd_table_no == m_tables.count()) { + buf.size = 0; + buf.table_num = 0; + buf.last = TRUE; + return backup::DONE; + } + + m_tables[bd_table_no].internal_name(path, sizeof(path)); + bd_table_no++; + try_(a) { + xt_ha_open_database_of_table(self, (XTPathStrPtr) path); + tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE, NULL); + pushr_(xt_heap_release, tab); + if (!(bd_ot = xt_db_open_table_using_tab(tab, bd_thread))) + xt_throw(self); + freer_(); // xt_heap_release(tab) + + /* Prepare the seqential scan: */ + xt_tab_seq_exit(bd_ot); + if (!xt_tab_seq_init(bd_ot)) + xt_throw(self); + + if (bd_row_buf) { + xt_free(self, bd_row_buf); + bd_row_buf = NULL; + } + bd_row_buf = (xtWord1 *) xt_malloc(self, bd_ot->ot_table->tab_dic.dic_mysql_buf_size); + bd_ot->ot_cols_req = bd_ot->ot_table->tab_dic.dic_no_of_cols; + } + catch_(a) { + ; + } + cont_(a); + + if (!bd_ot) + goto failed; + } + + buf.table_num = bd_table_no; +#ifdef TEST_SMALL_BLOCK + buf.size = TEST_SMALL_BLOCK; +#endif + size = buf.size; + buffer = (xtWord1 *) buf.data; + ASSERT_NS(size > 9); + + /* First check of a record was partically written + * last time. + */ + write_row: + if (bd_row_size > 0) { + row_len = bd_row_size; + if (bd_row_offset == 0) { + if (row_len+1 > size) { + ASSERT_NS(size > 9); + row_len = size - 9; + buffer = db_write_block(buffer, BUP_RECORD_BLOCK_4_START, &size, bd_row_size, row_len); + goto done; + } + buffer = db_write_block(buffer, BUP_STANDARD_VAR_RECORD, &size, row_len); + bd_row_size = 0; + } + else { + if (row_len+5 > size) { + row_len = size - 5; + buffer = db_write_block(buffer, BUP_RECORD_BLOCK_4, &size, 0, row_len); + goto done; + } + buffer = db_write_block(buffer, BUP_RECORD_BLOCK_4_END, &size, 0, row_len); + } + } + + /* Now continue with the sequential scan. */ + while (size > 1) { + if (!xt_tab_seq_next(bd_ot, bd_row_buf, &eof)) + goto failed; + if (eof) { + /* We will go the next table, on the next call. */ + xt_tab_seq_exit(bd_ot); + xt_db_return_table_to_pool_ns(bd_ot); + bd_ot = NULL; + break; + } + if (!(row_len = myxt_store_row_data(bd_ot, 0, (char *) bd_row_buf))) + goto failed; + if (row_len+1 > size) { + /* Does not fit: */ + bd_row_offset = 0; + bd_row_size = row_len; + /* Only add part of the row, if there is still + * quite a bit of space left: + */ + if (size >= (32 * 1024)) + goto write_row; + break; + } + buffer = db_write_block(buffer, BUP_STANDARD_VAR_RECORD, &size, row_len); + } + + done: + buf.size = buf.size - size; + /* This indicates wnd of data for a table! */ + buf.last = eof; + + return backup::OK; + + failed: + xt_log_and_clear_exception(bd_thread); + return backup::ERROR; +} + +result_t PBXTBackupDriver::prelock() +{ + XT_TRACE_CALL(); + return backup::READY; +} + +result_t PBXTBackupDriver::lock() +{ + XT_TRACE_CALL(); + bd_thread->st_xact_mode = XT_XACT_COMMITTED_READ; + bd_thread->st_ignore_fkeys = FALSE; + bd_thread->st_auto_commit = FALSE; + bd_thread->st_table_trans = FALSE; + bd_thread->st_abort_trans = FALSE; + bd_thread->st_stat_ended = FALSE; + bd_thread->st_stat_trans = FALSE; + bd_thread->st_is_update = FALSE; + if (!xt_xn_begin(bd_thread)) + return backup::ERROR; + bd_state = BUP_STATE_AFTER_LOCK; + return backup::OK; +} + +result_t PBXTBackupDriver::unlock() +{ + XT_TRACE_CALL(); + return backup::OK; +} + +result_t PBXTBackupDriver::cancel() +{ + XT_TRACE_CALL(); + return backup::OK; // free() will be called and suffice +} + +void PBXTBackupDriver::free() +{ + XT_TRACE_CALL(); + if (bd_ot) { + xt_tab_seq_exit(bd_ot); + xt_db_return_table_to_pool_ns(bd_ot); + bd_ot = NULL; + } + if (bd_row_buf) { + xt_free_ns(bd_row_buf); + bd_row_buf = NULL; + } + if (bd_thread->st_xact_data) + xt_xn_rollback(bd_thread); + delete this; +} + +void PBXTBackupDriver::lock_tables_TL_READ_NO_INSERT() +{ + XT_TRACE_CALL(); +} + +/* + * ----------------------------------------------------------------------- + * BACKUP DRIVER + */ + +class PBXTRestoreDriver: public Restore_driver +{ + public: + PBXTRestoreDriver(const Table_list &tables); + virtual ~PBXTRestoreDriver(); + + virtual result_t begin(const size_t); + virtual result_t end(); + virtual result_t send_data(Buffer &buf); + virtual result_t cancel(); + virtual void free(); + + private: + XTThreadPtr rd_thread; + u_int rd_table_no; + XTOpenTablePtr rd_ot; + STRUCT_TABLE *rd_my_table; + xtWord1 *rb_row_buf; + u_int rb_col_cnt; + u_int rb_insert_count; + + /* Long rows are accumulated here: */ + xtWord4 rb_row_len; + xtWord4 rb_data_size; + xtWord1 *rb_row_data; +}; + +PBXTRestoreDriver::PBXTRestoreDriver(const Table_list &tables): +Restore_driver(tables), +rd_thread(NULL), +rd_table_no(0), +rd_ot(NULL), +rb_row_buf(NULL), +rb_row_len(0), +rb_data_size(0), +rb_row_data(NULL) +{ +} + +PBXTRestoreDriver::~PBXTRestoreDriver() +{ +} + +result_t PBXTRestoreDriver::begin(const size_t) +{ + THD *thd = current_thd; + XTExceptionRec e; + + XT_TRACE_CALL(); + + if (!(rd_thread = xt_ha_set_current_thread(thd, &e))) { + xt_log_exception(NULL, &e, XT_LOG_DEFAULT); + return backup::ERROR; + } + + return backup::OK; +} + +result_t PBXTRestoreDriver::end() +{ + XT_TRACE_CALL(); + if (rd_ot) { + xt_db_return_table_to_pool_ns(rd_ot); + rd_ot = NULL; + } + //if (rb_row_buf) { + // xt_free_ns(rb_row_buf); + // rb_row_buf = NULL; + //} + if (rb_row_data) { + xt_free_ns(rb_row_data); + rb_row_data = NULL; + } + if (rd_thread->st_xact_data) { + if (!xt_xn_commit(rd_thread)) + return backup::ERROR; + } + return backup::OK; +} + + +result_t PBXTRestoreDriver::send_data(Buffer &buf) +{ + size_t size; + xtWord1 type; + xtWord1 *buffer; + xtWord4 row_len; + xtWord1 *rec_data; + + XT_TRACE_CALL(); + + if (buf.table_num != rd_table_no) { + XTThreadPtr self = rd_thread; + XTTableHPtr tab; + char path[PATH_MAX]; + + if (rd_ot) { + xt_db_return_table_to_pool_ns(rd_ot); + rd_ot = NULL; + } + + if (rd_thread->st_xact_data) { + if (!xt_xn_commit(rd_thread)) + goto failed; + } + if (!xt_xn_begin(rd_thread)) + goto failed; + rb_insert_count = 0; + + rd_table_no = buf.table_num; + m_tables[rd_table_no-1].internal_name(path, sizeof(path)); + try_(a) { + xt_ha_open_database_of_table(self, (XTPathStrPtr) path); + tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE, NULL); + pushr_(xt_heap_release, tab); + if (!(rd_ot = xt_db_open_table_using_tab(tab, rd_thread))) + xt_throw(self); + freer_(); // xt_heap_release(tab) + + rd_my_table = rd_ot->ot_table->tab_dic.dic_my_table; + if (rd_my_table->found_next_number_field) { + rd_my_table->in_use = current_thd; + rd_my_table->next_number_field = rd_my_table->found_next_number_field; + rd_my_table->mark_columns_used_by_index_no_reset(rd_my_table->s->next_number_index, rd_my_table->read_set); + } + + /* This is safe because only one thread can restore a table at + * a time! + */ + rb_row_buf = (xtWord1 *) rd_my_table->record[0]; + //if (rb_row_buf) { + // xt_free(self, rb_row_buf); + // rb_row_buf = NULL; + //} + //rb_row_buf = (xtWord1 *) xt_malloc(self, rd_ot->ot_table->tab_dic.dic_mysql_buf_size); + + rb_col_cnt = rd_ot->ot_table->tab_dic.dic_no_of_cols; + + } + catch_(a) { + ; + } + cont_(a); + + if (!rd_ot) + goto failed; + } + + buffer = (xtWord1 *) buf.data; + size = buf.size; + + while (size > 0) { + type = *buffer; + switch (type) { + case BUP_STANDARD_VAR_RECORD: + rec_data = buffer + 1; + break; + case BUP_RECORD_BLOCK_4_START: + buffer++; + row_len = XT_GET_DISK_4(buffer); + buffer += 4; + if (rb_data_size < row_len) { + if (!xt_realloc_ns((void **) &rb_row_data, row_len)) + goto failed; + rb_data_size = row_len; + } + row_len = XT_GET_DISK_4(buffer); + buffer += 4; + ASSERT_NS(row_len <= rb_data_size); + if (row_len > rb_data_size) { + xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT); + goto failed; + } + memcpy(rb_row_data, buffer, row_len); + rb_row_len = row_len; + buffer += row_len; + if (row_len + 9 > size) { + xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT); + goto failed; + } + size -= row_len + 9; + continue; + case BUP_RECORD_BLOCK_4: + buffer++; + row_len = XT_GET_DISK_4(buffer); + buffer += 4; + ASSERT_NS(rb_row_len + row_len <= rb_data_size); + if (rb_row_len + row_len > rb_data_size) { + xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT); + goto failed; + } + memcpy(rb_row_data + rb_row_len, buffer, row_len); + rb_row_len += row_len; + buffer += row_len; + if (row_len + 5 > size) { + xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT); + goto failed; + } + size -= row_len + 5; + continue; + case BUP_RECORD_BLOCK_4_END: + buffer++; + row_len = XT_GET_DISK_4(buffer); + buffer += 4; + ASSERT_NS(rb_row_len + row_len <= rb_data_size); + if (rb_row_len + row_len > rb_data_size) { + xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT); + goto failed; + } + memcpy(rb_row_data + rb_row_len, buffer, row_len); + buffer += row_len; + if (row_len + 5 > size) { + xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT); + goto failed; + } + size -= row_len + 5; + rec_data = rb_row_data; + break; + default: + xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT); + goto failed; + } + + if (!(row_len = myxt_load_row_data(rd_ot, rec_data, rb_row_buf, rb_col_cnt))) + goto failed; + + if (rd_ot->ot_table->tab_dic.dic_my_table->found_next_number_field) + ha_set_auto_increment(rd_ot, rd_ot->ot_table->tab_dic.dic_my_table->found_next_number_field); + + if (!xt_tab_new_record(rd_ot, rb_row_buf)) + goto failed; + + if (type == BUP_STANDARD_VAR_RECORD) { + buffer += row_len+1; + if (row_len + 1 > size) { + xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT); + goto failed; + } + size -= row_len + 1; + } + + rb_insert_count++; + if (rb_insert_count == XT_RESTORE_BATCH_SIZE) { + if (!xt_xn_commit(rd_thread)) + goto failed; + if (!xt_xn_begin(rd_thread)) + goto failed; + rb_insert_count = 0; + } + } + + return backup::OK; + + failed: + xt_log_and_clear_exception(rd_thread); + return backup::ERROR; +} + + +result_t PBXTRestoreDriver::cancel() +{ + XT_TRACE_CALL(); + /* Nothing to do in cancel(); free() will suffice */ + return backup::OK; +} + +void PBXTRestoreDriver::free() +{ + XT_TRACE_CALL(); + if (rd_ot) { + xt_db_return_table_to_pool_ns(rd_ot); + rd_ot = NULL; + } + //if (rb_row_buf) { + // xt_free_ns(rb_row_buf); + // rb_row_buf = NULL; + //} + if (rb_row_data) { + xt_free_ns(rb_row_data); + rb_row_data = NULL; + } + if (rd_thread->st_xact_data) + xt_xn_rollback(rd_thread); + delete this; +} + +/* + * ----------------------------------------------------------------------- + * BACKUP ENGINE FACTORY + */ + +#define PBXT_BACKUP_VERSION 1 + + +class PBXTBackupEngine: public Backup_engine +{ + public: + PBXTBackupEngine() { }; + + virtual version_t version() const { + return PBXT_BACKUP_VERSION; + }; + + virtual result_t get_backup(const uint32, const Table_list &, Backup_driver* &); + + virtual result_t get_restore(const version_t, const uint32, const Table_list &,Restore_driver* &); + + virtual void free() + { + delete this; + } +}; + +result_t PBXTBackupEngine::get_backup(const u_int count, const Table_list &tables, Backup_driver* &drv) +{ + PBXTBackupDriver *ptr = new PBXTBackupDriver(tables); + + if (!ptr) + return backup::ERROR; + drv = ptr; + return backup::OK; +} + +result_t PBXTBackupEngine::get_restore(const version_t ver, const uint32, + const Table_list &tables, Restore_driver* &drv) +{ + if (ver > PBXT_BACKUP_VERSION) + { + return backup::ERROR; + } + + PBXTRestoreDriver *ptr = new PBXTRestoreDriver(tables); + + if (!ptr) + return backup::ERROR; + drv = (Restore_driver *) ptr; + return backup::OK; +} + + +Backup_result_t pbxt_backup_engine(handlerton *self, Backup_engine* &be) +{ + be = new PBXTBackupEngine(); + + if (!be) + return backup::ERROR; + + return backup::OK; +} + +#endif diff --git a/storage/pbxt/src/backup_xt.h b/storage/pbxt/src/backup_xt.h new file mode 100644 index 00000000000..58171f6c31a --- /dev/null +++ b/storage/pbxt/src/backup_xt.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2009 PrimeBase Technologies GmbH + * + * PrimeBase XT + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * 2009-09-07 Paul McCullagh + * + * H&G2JCtL + */ + +#ifndef __backup_xt_h__ +#define __backup_xt_h__ + +#include "xt_defs.h" + +#ifdef MYSQL_SUPPORTS_BACKUP + +Backup_result_t pbxt_backup_engine(handlerton *self, Backup_engine* &be); + +#endif +#endif diff --git a/storage/pbxt/src/cache_xt.cc b/storage/pbxt/src/cache_xt.cc index aab8b9de0d0..a8b2ff20ea2 100644 --- a/storage/pbxt/src/cache_xt.cc +++ b/storage/pbxt/src/cache_xt.cc @@ -73,7 +73,7 @@ #define IDX_CAC_UNLOCK(i, o) xt_xsmutex_unlock(&(i)->cs_lock, (o)->t_id) #elif defined(IDX_CAC_USE_PTHREAD_RW) #define IDX_CAC_LOCK_TYPE xt_rwlock_type -#define IDX_CAC_INIT_LOCK(s, i) xt_init_rwlock(s, &(i)->cs_lock) +#define IDX_CAC_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, &(i)->cs_lock) #define IDX_CAC_FREE_LOCK(s, i) xt_free_rwlock(&(i)->cs_lock) #define IDX_CAC_READ_LOCK(i, o) xt_slock_rwlock_ns(&(i)->cs_lock) #define IDX_CAC_WRITE_LOCK(i, o) xt_xlock_rwlock_ns(&(i)->cs_lock) @@ -94,8 +94,12 @@ #define IDX_CAC_UNLOCK(i, s) xt_spinxslock_unlock(&(i)->cs_lock, (s)->t_id) #endif +#ifdef XT_NO_ATOMICS +#define ID_HANDLE_USE_PTHREAD_RW +#else #define ID_HANDLE_USE_SPINLOCK //#define ID_HANDLE_USE_PTHREAD_RW +#endif #if defined(ID_HANDLE_USE_PTHREAD_RW) #define ID_HANDLE_LOCK_TYPE xt_mutex_type @@ -374,7 +378,7 @@ xtPublic void xt_ind_release_handle(XTIndHandlePtr handle, xtBool have_lock, XTT { DcHandleSlotPtr hs; XTIndBlockPtr block = NULL; - u_int hash_idx = 0; + u_int hash_idx = 0; DcSegmentPtr seg = NULL; XTIndBlockPtr xblock; @@ -1379,7 +1383,7 @@ xtPublic xtBool xt_ind_fetch(XTOpenTablePtr ot, XTIndexPtr ind, xtIndexNodeID ad ASSERT_NS(iref->ir_xlock == 2); #endif if (!(block = ind_cac_fetch(ot, ind, address, &seg, TRUE))) - return 0; + return FAILED; branch_size = XT_GET_DISK_2(((XTIdxBranchDPtr) block->cb_data)->tb_size_2); if (XT_GET_INDEX_BLOCK_LEN(branch_size) < 2 || XT_GET_INDEX_BLOCK_LEN(branch_size) > XT_INDEX_PAGE_SIZE) { diff --git a/storage/pbxt/src/cache_xt.h b/storage/pbxt/src/cache_xt.h index fcd05a8fe34..5dd7de629e3 100644 --- a/storage/pbxt/src/cache_xt.h +++ b/storage/pbxt/src/cache_xt.h @@ -62,7 +62,7 @@ struct XTIdxReadBuffer; #define XT_IPAGE_UNLOCK(i, x) xt_atomicrwlock_unlock(i, x) #elif defined(XT_IPAGE_USE_PTHREAD_RW) #define XT_IPAGE_LOCK_TYPE xt_rwlock_type -#define XT_IPAGE_INIT_LOCK(s, i) xt_init_rwlock(s, i) +#define XT_IPAGE_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, i) #define XT_IPAGE_FREE_LOCK(s, i) xt_free_rwlock(i) #define XT_IPAGE_READ_LOCK(i) xt_slock_rwlock_ns(i) #define XT_IPAGE_WRITE_LOCK(i, s) xt_xlock_rwlock_ns(i) diff --git a/storage/pbxt/src/database_xt.cc b/storage/pbxt/src/database_xt.cc index c2231f6e854..288520dfed0 100644 --- a/storage/pbxt/src/database_xt.cc +++ b/storage/pbxt/src/database_xt.cc @@ -54,6 +54,8 @@ * GLOBALS */ +xtPublic XTDatabaseHPtr pbxt_database = NULL; // The global open database + xtPublic xtLogOffset xt_db_log_file_threshold; xtPublic size_t xt_db_log_buffer_size; xtPublic size_t xt_db_transaction_buffer_size; @@ -505,6 +507,15 @@ xtPublic XTDatabaseHPtr xt_get_database(XTThreadPtr self, char *path, xtBool mul * all index entries that are not visible have * been removed. * + * REASON WHY WE SET ROWID ON RECOVERY: + * The row ID is set on recovery because the + * change to the index may be lost after a crash. + * The change to the index is done by the sweeper, and + * there is no record of this change in the log. + * The sweeper will not "re-sweep" all transations + * that are recovered. As a result, this upadte + * of the index by the sweeper may be lost. + * * {OPEN-DB-SWEEPER-WAIT} * This has been moved to after the release of the open * database lock because: @@ -518,9 +529,12 @@ xtPublic XTDatabaseHPtr xt_get_database(XTThreadPtr self, char *path, xtBool mul * - To open the database it needs the open database * lock. */ + /* + * This has been moved, see: {WAIT-FOR-SW-AFTER-RECOV} pushr_(xt_heap_release, db); xt_wait_for_sweeper(self, db, 0); popr_(); + */ return db; } diff --git a/storage/pbxt/src/database_xt.h b/storage/pbxt/src/database_xt.h index 469bfa4adb6..21dfdde6f5a 100644 --- a/storage/pbxt/src/database_xt.h +++ b/storage/pbxt/src/database_xt.h @@ -105,6 +105,8 @@ typedef struct XTTablePath { #define XT_THREAD_IDLE 1 #define XT_THREAD_INERR 2 +#define XT_XA_HASH_TAB_SIZE 223 + typedef struct XTDatabase : public XTHeap { char *db_name; /* The name of the database, last component of the path! */ char *db_main_path; @@ -131,6 +133,9 @@ typedef struct XTDatabase : public XTHeap { u_int db_stat_sweep_waits; /* STATISTICS: count the sweeper waits. */ XTDatabaseLogRec db_xlog; /* The transaction log for this database. */ XTXactRestartRec db_restart; /* Database recovery stuff. */ + xt_mutex_type db_xn_xa_lock; + XTXactPreparePtr db_xn_xa_table[XT_XA_HASH_TAB_SIZE]; + XTSortedListPtr db_xn_xa_list; /* The "wait-for" list, of transactions waiting for other transactions. */ XTSortedListPtr db_xn_wait_for; /* The "wait-for" list, of transactions waiting for other transactions. */ u_int db_xn_call_start; /* Start of the post wait calls. */ @@ -198,6 +203,7 @@ void xt_check_database(XTThreadPtr self); void xt_add_pbxt_file(size_t size, char *path, const char *file); void xt_add_location_file(size_t size, char *path); +void xt_add_pbxt_dir(size_t size, char *path); void xt_add_system_dir(size_t size, char *path); void xt_add_data_dir(size_t size, char *path); @@ -244,4 +250,6 @@ inline void xt_xlog_check_long_writer(XTThreadPtr thread) } } +extern XTDatabaseHPtr pbxt_database; // The global open database + #endif diff --git a/storage/pbxt/src/datadic_xt.cc b/storage/pbxt/src/datadic_xt.cc index 9e709b61c59..265d09e29ba 100644 --- a/storage/pbxt/src/datadic_xt.cc +++ b/storage/pbxt/src/datadic_xt.cc @@ -35,7 +35,7 @@ #ifdef DEBUG #ifdef DRIZZLED -#include <drizzled/common_includes.h> +//#include <drizzled/common_includes.h> #else #include "mysql_priv.h" #endif @@ -437,11 +437,6 @@ class XTTokenizer { XTToken *nextToken(XTThreadPtr self, c_char *keyword, XTToken *tk); }; -void ri_free_token(XTThreadPtr XT_UNUSED(self), XTToken *tk) -{ - delete tk; -} - XTToken *XTTokenizer::newToken(XTThreadPtr self, u_int type, char *start, char *end) { if (!tkn_current) { diff --git a/storage/pbxt/src/datalog_xt.cc b/storage/pbxt/src/datalog_xt.cc index 1a8a0a47085..3530b516f62 100644 --- a/storage/pbxt/src/datalog_xt.cc +++ b/storage/pbxt/src/datalog_xt.cc @@ -410,7 +410,7 @@ static void dl_recover_log(XTThreadPtr self, XTDatabaseHPtr db, XTDataLogFilePtr ASSERT_NS(seq_read.sl_log_eof == seq_read.sl_rec_log_offset); data_log->dlf_log_eof = seq_read.sl_rec_log_offset; - if ((size_t) data_log->dlf_log_eof < sizeof(XTXactLogHeaderDRec)) { + if (data_log->dlf_log_eof < (off_t) sizeof(XTXactLogHeaderDRec)) { data_log->dlf_log_eof = sizeof(XTXactLogHeaderDRec); if (!dl_create_log_header(data_log, seq_read.sl_log_file, self)) xt_throw(self); @@ -1162,7 +1162,7 @@ xtBool XTDataLogBuffer::dlb_close_log(XTThreadPtr thread) /* When I use 'thread' instead of 'self', this means * that I will not throw an error. */ -xtBool XTDataLogBuffer::dlb_get_log_offset(xtLogID *log_id, xtLogOffset *out_offset, size_t req_size, struct XTThread *thread) +xtBool XTDataLogBuffer::dlb_get_log_offset(xtLogID *log_id, xtLogOffset *out_offset, size_t XT_UNUSED(req_size), struct XTThread *thread) { /* Note, I am allowing a log to grow beyond the threshold. * The amount depends on the maximum extended record size. @@ -1757,7 +1757,7 @@ static xtBool dl_collect_garbage(XTThreadPtr self, XTDatabaseHPtr db, XTDataLogF freer_(); // xt_unlock_mutex(&db->db_co_dlog_lock) /* Flush the transaction log. */ - if (!xt_xlog_flush_log(self)) + if (!xt_xlog_flush_log(db, self)) xt_throw(self); xt_lock_mutex_ns(&db->db_datalogs.dlc_head_lock); @@ -1891,7 +1891,7 @@ static xtBool dl_collect_garbage(XTThreadPtr self, XTDatabaseHPtr db, XTDataLogF freer_(); // xt_unlock_mutex(&db->db_co_dlog_lock) /* Flush the transaction log. */ - if (!xt_xlog_flush_log(self)) + if (!xt_xlog_flush_log(db, self)) xt_throw(self); /* Save state in source log header. */ diff --git a/storage/pbxt/src/discover_xt.cc b/storage/pbxt/src/discover_xt.cc index 1ca20fe8dd2..ab6d84396cc 100644 --- a/storage/pbxt/src/discover_xt.cc +++ b/storage/pbxt/src/discover_xt.cc @@ -31,6 +31,9 @@ #include <drizzled/session.h> #include <drizzled/server_includes.h> #include <drizzled/sql_base.h> +#include <drizzled/statement/alter_table.h> +#include <algorithm> +#include <sstream> #endif #include "strutil_xt.h" @@ -39,18 +42,273 @@ #include "ha_xtsys.h" #ifndef DRIZZLED -#if MYSQL_VERSION_ID > 60005 +#if MYSQL_VERSION_ID >= 50404 #define DOT_STR(x) x.str #else #define DOT_STR(x) x #endif #endif -#ifndef DRIZZLED +//#ifndef DRIZZLED #define LOCK_OPEN_HACK_REQUIRED -#endif // DRIZZLED +//#endif // DRIZZLED #ifdef LOCK_OPEN_HACK_REQUIRED +#ifdef DRIZZLED + +using namespace drizzled; +using namespace std; + +#define mysql_create_table_no_lock hacked_mysql_create_table_no_lock + +namespace drizzled { + +int rea_create_table(Session *session, const char *path, + const char *db, const char *table_name, + message::Table *table_proto, + HA_CREATE_INFO *create_info, + List<CreateField> &create_field, + uint32_t key_count,KEY *key_info); +} + +static uint32_t build_tmptable_filename(Session* session, + char *buff, size_t bufflen) +{ + uint32_t length; + ostringstream path_str, post_tmpdir_str; + string tmp; + + path_str << drizzle_tmpdir; + post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid; + post_tmpdir_str << session->thread_id << session->tmp_table++; + tmp= post_tmpdir_str.str(); + + transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower); + + path_str << tmp; + + if (bufflen < path_str.str().length()) + length= 0; + else + length= unpack_filename(buff, path_str.str().c_str()); + + return length; +} + +static bool mysql_create_table_no_lock(Session *session, + const char *db, const char *table_name, + HA_CREATE_INFO *create_info, + message::Table *table_proto, + AlterInfo *alter_info, + bool internal_tmp_table, + uint32_t select_field_count) +{ + char path[FN_REFLEN]; + uint32_t path_length; + uint db_options, key_count; + KEY *key_info_buffer; + Cursor *file; + bool error= true; + /* Check for duplicate fields and check type of table to create */ + if (!alter_info->create_list.elements) + { + my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS), + MYF(0)); + return true; + } + assert(strcmp(table_name,table_proto->name().c_str())==0); + if (check_engine(session, table_name, create_info)) + return true; + db_options= create_info->table_options; + if (create_info->row_type == ROW_TYPE_DYNAMIC) + db_options|=HA_OPTION_PACK_RECORD; + + /*if (!(file= create_info->db_type->getCursor((TableShare*) 0, session->mem_root))) + { + my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor)); + return true; + }*/ + + /* PMC - Done to avoid getting the partition handler by mistake! */ + if (!(file= new (session->mem_root) ha_xtsys(pbxt_hton, NULL))) + { + my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor)); + return true; + } + + set_table_default_charset(create_info, (char*) db); + + if (mysql_prepare_create_table(session, + create_info, + table_proto, + alter_info, + internal_tmp_table, + &db_options, file, + &key_info_buffer, &key_count, + select_field_count)) + goto err; + + /* Check if table exists */ + if (create_info->options & HA_LEX_CREATE_TMP_TABLE) + { + path_length= build_tmptable_filename(session, path, sizeof(path)); + } + else + { + #ifdef FN_DEVCHAR + /* check if the table name contains FN_DEVCHAR when defined */ + if (strchr(table_name, FN_DEVCHAR)) + { + my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name); + return true; + } +#endif + path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table); + } + + /* Check if table already exists */ + if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) && + session->find_temporary_table(db, table_name)) + { + if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) + { + create_info->table_existed= 1; // Mark that table existed + push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE, + ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), + table_name); + error= 0; + goto err; + } + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name); + goto err; + } + + //pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */ + if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)) + { + if (plugin::StorageEngine::getTableDefinition(*session, + path, + db, + table_name, + internal_tmp_table) == EEXIST) + { + if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) + { + error= false; + push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE, + ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), + table_name); + create_info->table_existed= 1; // Mark that table existed + } + else + my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); + + goto unlock_and_end; + } + /* + * We don't assert here, but check the result, because the table could be + * in the table definition cache and in the same time the .frm could be + * missing from the disk, in case of manual intervention which deletes + * the .frm file. The user has to use FLUSH TABLES; to clear the cache. + * Then she could create the table. This case is pretty obscure and + * therefore we don't introduce a new error message only for it. + * */ + if (TableShare::getShare(db, table_name)) + { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name); + goto unlock_and_end; + } + } + /* + * Check that table with given name does not already + * exist in any storage engine. In such a case it should + * be discovered and the error ER_TABLE_EXISTS_ERROR be returned + * unless user specified CREATE TABLE IF EXISTS + * The LOCK_open mutex has been locked to make sure no + * one else is attempting to discover the table. Since + * it's not on disk as a frm file, no one could be using it! + * */ + if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) + { + bool create_if_not_exists = + create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS; + + char table_path[FN_REFLEN]; + uint32_t table_path_length; + + table_path_length= build_table_filename(table_path, sizeof(table_path), + db, table_name, false); + + int retcode= plugin::StorageEngine::getTableDefinition(*session, + table_path, + db, + table_name, + false); + switch (retcode) + { + case ENOENT: + /* Normal case, no table exists. we can go and create it */ + break; + case EEXIST: + if (create_if_not_exists) + { + error= false; + push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE, + ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), + table_name); + create_info->table_existed= 1; // Mark that table existed + goto unlock_and_end; + } + my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); + goto unlock_and_end; + default: + my_error(retcode, MYF(0),table_name); + goto unlock_and_end; + } + } + + session->set_proc_info("creating table"); + create_info->table_existed= 0; // Mark that table is created + + create_info->table_options=db_options; + + if (rea_create_table(session, path, db, table_name, + table_proto, + create_info, alter_info->create_list, + key_count, key_info_buffer)) + goto unlock_and_end; + + if (create_info->options & HA_LEX_CREATE_TMP_TABLE) + { + /* Open table and put in temporary table list */ + if (!(session->open_temporary_table(path, db, table_name, 1, OTM_OPEN))) + { + (void) session->rm_temporary_table(create_info->db_type, path); + goto unlock_and_end; + } + } + + /* + * Don't write statement if: + * - It is an internal temporary table, + * - Row-based logging is used and it we are creating a temporary table, or + * - The binary log is not open. + * Otherwise, the statement shall be binlogged. + * */ + if (!internal_tmp_table && + ((!(create_info->options & HA_LEX_CREATE_TMP_TABLE)))) + write_bin_log(session, session->query, session->query_length); + error= false; +unlock_and_end: + //pthread_mutex_unlock(&LOCK_open); + +err: + session->set_proc_info("After create"); + delete file; + return(error); +} + +#else // MySQL case /////////////////////////////// /* * Unfortunately I cannot use the standard mysql_create_table_no_lock() because it will lock "LOCK_open" @@ -1229,13 +1487,13 @@ static bool mysql_create_table_no_lock(THD *thd, if (create_info->options & HA_LEX_CREATE_TMP_TABLE) { /* Open table and put in temporary table list */ -#if MYSQL_VERSION_ID > 60005 +#if MYSQL_VERSION_ID >= 50404 if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN))) #else if (!(open_temporary_table(thd, path, db, table_name, 1))) #endif { -#if MYSQL_VERSION_ID > 60005 +#if MYSQL_VERSION_ID >= 50404 (void) rm_temporary_table(create_info->db_type, path, false); #else (void) rm_temporary_table(create_info->db_type, path); @@ -1252,11 +1510,21 @@ static bool mysql_create_table_no_lock(THD *thd, - The binary log is not open. Otherwise, the statement shall be binlogged. */ + /* PBXT 1.0.09e + * Firstly we had a compile problem with MySQL 5.1.42 and + * the write_bin_log() call below: + * discover_xt.cc:1259: error: argument of type 'char* (Statement::)()' does not match 'const char*' + * + * And secondly, we should no write the BINLOG anyway because this is + * an internal PBXT system table. + * + * So I am just commenting out the code altogether. if (!internal_tmp_table && (!thd->current_stmt_binlog_row_based || (thd->current_stmt_binlog_row_based && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)))) - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + write_bin_log(thd, TRUE, thd->query, thd->query_length); + */ error= FALSE; unlock_and_end: pthread_mutex_unlock(&LOCK_open); @@ -1279,37 +1547,51 @@ warn: ////// END OF CUT AND PASTES FROM sql_table.cc //////// //////////////////////////////////////////////////////// +#endif // DRIZZLED #endif // LOCK_OPEN_HACK_REQUIRED //------------------------------ int xt_create_table_frm(handlerton *hton, THD* thd, const char *db, const char *name, DT_FIELD_INFO *info, DT_KEY_INFO *XT_UNUSED(keys), xtBool skip_existing) { #ifdef DRIZZLED - drizzled::message::Table table_proto; +#define MYLEX_CREATE_INFO create_info +#else +#define MYLEX_CREATE_INFO mylex.create_info +#endif + +#ifdef DRIZZLED + drizzled::statement::AlterTable *stmt = new drizzled::statement::AlterTable(thd); + HA_CREATE_INFO create_info; + //AlterInfo alter_info; + drizzled::message::Table table_proto; static const char *ext = ".dfe"; static const int ext_len = 4; + + table_proto.mutable_engine()->mutable_name()->assign("PBXT"); #else static const char *ext = ".frm"; static const int ext_len = 4; #endif int err = 1; - //HA_CREATE_INFO create_info = {0}; - //Alter_info alter_info; char field_length_buffer[12], *field_length_ptr; LEX *save_lex= thd->lex, mylex; - - memset(&mylex.create_info, 0, sizeof(HA_CREATE_INFO)); + + memset(&MYLEX_CREATE_INFO, 0, sizeof(HA_CREATE_INFO)); thd->lex = &mylex; - lex_start(thd); + lex_start(thd); +#ifdef DRIZZLED + mylex.statement = stmt; +#endif /* setup the create info */ - mylex.create_info.db_type = hton; + MYLEX_CREATE_INFO.db_type = hton; + #ifndef DRIZZLED mylex.create_info.frm_only = 1; #endif - mylex.create_info.default_table_charset = system_charset_info; + MYLEX_CREATE_INFO.default_table_charset = system_charset_info; /* setup the column info. */ while (info->field_name) { @@ -1335,7 +1617,7 @@ int xt_create_table_frm(handlerton *hton, THD* thd, const char *db, const char * #else if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length, info->field_flags, -#if MYSQL_VERSION_ID > 60005 +#if MYSQL_VERSION_ID >= 50404 HA_SM_DISK, COLUMN_FORMAT_TYPE_FIXED, #endif @@ -1370,7 +1652,7 @@ int xt_create_table_frm(handlerton *hton, THD* thd, const char *db, const char * table_proto.set_name(name); table_proto.set_type(drizzled::message::Table::STANDARD); - if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &table_proto, &mylex.alter_info, 1, 0, false)) + if (mysql_create_table_no_lock(thd, db, name, &create_info, &table_proto, &stmt->alter_info, 1, 0)) goto error; #else if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &mylex.alter_info, 1, 0)) diff --git a/storage/pbxt/src/filesys_xt.cc b/storage/pbxt/src/filesys_xt.cc index 2147626b20d..31e2cf961b6 100644 --- a/storage/pbxt/src/filesys_xt.cc +++ b/storage/pbxt/src/filesys_xt.cc @@ -56,6 +56,8 @@ //#define DEBUG_TRACE_FILES //#define INJECT_WRITE_REMAP_ERROR /* This is required to make testing on the Mac faster: */ +/* It turns of full file sync. */ +#define DEBUG_FAST_MAC #endif #ifdef DEBUG_TRACE_FILES @@ -63,10 +65,6 @@ #define PRINTF xt_trace #endif -#if defined(XT_MAC) && defined(F_FULLFSYNC) -#undef F_FULLFSYNC -#endif - #ifdef INJECT_WRITE_REMAP_ERROR #define INJECT_REMAP_FILE_SIZE 1000000 #define INJECT_REMAP_FILE_TYPE "xtd" @@ -883,7 +881,7 @@ xtPublic xtBool xt_flush_file(XTOpenFilePtr of, XTIOStatsPtr stat, XTThreadPtr X * fsync didn't really flush index pages to disk. fcntl(F_FULLFSYNC) is considered more effective * in such case. */ -#ifdef F_FULLFSYNC +#if defined(F_FULLFSYNC) && !defined(DEBUG_FAST_MAC) if (fcntl(of->of_filedes, F_FULLFSYNC, 0) == -1) { xt_register_ferrno(XT_REG_CONTEXT, errno, xt_file_path(of)); goto failed; diff --git a/storage/pbxt/src/filesys_xt.h b/storage/pbxt/src/filesys_xt.h index 585ed9bd8d0..d6762823cc0 100644 --- a/storage/pbxt/src/filesys_xt.h +++ b/storage/pbxt/src/filesys_xt.h @@ -102,7 +102,7 @@ xtBool xt_fs_rename(struct XTThread *self, char *from_path, char *to_path); #define FILE_MAP_UNLOCK(i, o) xt_xsmutex_unlock(i, o) #elif defined(FILE_MAP_USE_PTHREAD_RW) #define FILE_MAP_LOCK_TYPE xt_rwlock_type -#define FILE_MAP_INIT_LOCK(s, i) xt_init_rwlock(s, i) +#define FILE_MAP_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, i) #define FILE_MAP_FREE_LOCK(s, i) xt_free_rwlock(i) #define FILE_MAP_READ_LOCK(i, o) xt_slock_rwlock_ns(i) #define FILE_MAP_WRITE_LOCK(i, o) xt_xlock_rwlock_ns(i) diff --git a/storage/pbxt/src/ha_pbxt.cc b/storage/pbxt/src/ha_pbxt.cc index 315b7ff74d6..0db6d9556c7 100644 --- a/storage/pbxt/src/ha_pbxt.cc +++ b/storage/pbxt/src/ha_pbxt.cc @@ -35,6 +35,7 @@ #include <stdlib.h> #include <time.h> +#include <ctype.h> #ifdef DRIZZLED #include <drizzled/common.h> @@ -42,14 +43,21 @@ #include <mysys/my_alloc.h> #include <mysys/hash.h> #include <drizzled/field.h> -#include <drizzled/current_session.h> +#include <drizzled/session.h> #include <drizzled/data_home.h> #include <drizzled/error.h> #include <drizzled/table.h> #include <drizzled/field/timestamp.h> #include <drizzled/server_includes.h> +#include <drizzled/plugin/info_schema_table.h> extern "C" char **session_query(Session *session); #define my_strdup(a,b) strdup(a) + +using drizzled::plugin::Registry; +using drizzled::plugin::ColumnInfo; +using drizzled::plugin::InfoSchemaTable; +using drizzled::plugin::InfoSchemaMethods; + #else #include "mysql_priv.h" #include <mysql/plugin.h> @@ -71,7 +79,7 @@ extern "C" char **session_query(Session *session); #include "tabcache_xt.h" #include "systab_xt.h" #include "xaction_xt.h" -#include "restart_xt.h" +#include "backup_xt.h" #ifdef DEBUG //#define XT_USE_SYS_PAR_DEBUG_SIZES @@ -101,6 +109,10 @@ static void pbxt_drop_database(handlerton *hton, char *path); static int pbxt_close_connection(handlerton *hton, THD* thd); static int pbxt_commit(handlerton *hton, THD *thd, bool all); static int pbxt_rollback(handlerton *hton, THD *thd, bool all); +static int pbxt_prepare(handlerton *hton, THD *thd, bool all); +static int pbxt_recover(handlerton *hton, XID *xid_list, uint len); +static int pbxt_commit_by_xid(handlerton *hton, XID *xid); +static int pbxt_rollback_by_xid(handlerton *hton, XID *xid); #endif static void ha_aquire_exclusive_use(XTThreadPtr self, XTSharePtr share, ha_pbxt *mine); static void ha_release_exclusive_use(XTThreadPtr self, XTSharePtr share); @@ -123,7 +135,9 @@ static void ha_close_open_tables(XTThreadPtr self, XTSharePtr share, ha_pbxt *m #ifdef PBXT_HANDLER_TRACE #define PBXT_ALLOW_PRINTING -#define XT_TRACE_CALL() do { XTThreadPtr s = xt_get_self(); printf("%s %s\n", s ? s->t_name : "-unknown-", __FUNC__); } while (0) +#define XT_TRACE_CALL() ha_trace_function(__FUNC__, NULL) +#define XT_TRACE_METHOD() ha_trace_function(__FUNC__, pb_share->sh_table_path->ps_path) + #ifdef PBXT_TRACE_RETURN #define XT_RETURN(x) do { printf("%d\n", (int) (x)); return (x); } while (0) #define XT_RETURN_VOID do { printf("out\n"); return; } while (0) @@ -135,6 +149,7 @@ static void ha_close_open_tables(XTThreadPtr self, XTSharePtr share, ha_pbxt *m #else #define XT_TRACE_CALL() +#define XT_TRACE_METHOD() #define XT_RETURN(x) return (x) #define XT_RETURN_VOID return @@ -165,10 +180,10 @@ xtBool pbxt_crash_debug = TRUE; xtBool pbxt_crash_debug = FALSE; #endif + /* Variables for pbxt share methods */ static xt_mutex_type pbxt_database_mutex; // Prevent a database from being opened while it is being dropped static XTHashTabPtr pbxt_share_tables; // Hash used to track open tables -XTDatabaseHPtr pbxt_database = NULL; // The global open database static char *pbxt_index_cache_size; static char *pbxt_record_cache_size; static char *pbxt_log_cache_size; @@ -180,6 +195,12 @@ static char *pbxt_data_log_threshold; static char *pbxt_data_file_grow_size; static char *pbxt_row_file_grow_size; static int pbxt_max_threads; +static my_bool pbxt_support_xa; + +#ifndef DRIZZLED +// drizzle complains it's not used +static XTXactEnumXARec pbxt_xa_enum; +#endif #ifdef DEBUG #define XT_SHARE_LOCK_WAIT 5000 @@ -259,6 +280,33 @@ static HAVarParamsRec vp_row_file_grow_size = { "pbxt_row_file_grow_size", "256K //#define XT_AUTO_INCREMENT_DEF 1 #endif +#ifdef PBXT_HANDLER_TRACE +static void ha_trace_function(const char *function, char *table) +{ + char func_buf[50], *ptr; + XTThreadPtr thread = xt_get_self(); + + if ((ptr = strchr(function, '('))) { + ptr--; + while (ptr > function) { + if (!(isalnum(*ptr) || *ptr == '_')) + break; + ptr--; + } + ptr++; + xt_strcpy(50, func_buf, ptr); + if ((ptr = strchr(func_buf, '('))) + *ptr = 0; + } + else + xt_strcpy(50, func_buf, function); + if (table) + printf("%s %s (%s)\n", thread ? thread->t_name : "-unknown-", func_buf, table); + else + printf("%s %s\n", thread ? thread->t_name : "-unknown-", func_buf); +} +#endif + /* * ----------------------------------------------------------------------- * SHARED TABLE DATA @@ -584,6 +632,9 @@ xtPublic XTThreadPtr xt_ha_thd_to_self(THD *thd) /* The first bit is 1. */ static u_int ha_get_max_bit(MX_BITMAP *map) { +#ifdef DRIZZLED + return map->getFirstSet(); +#else my_bitmap_map *data_ptr = map->bitmap; my_bitmap_map *end_ptr = map->last_word_ptr; my_bitmap_map b; @@ -612,6 +663,7 @@ static u_int ha_get_max_bit(MX_BITMAP *map) cnt -= 32; } return 0; +#endif } /* @@ -684,9 +736,10 @@ xtPublic int xt_ha_pbxt_to_mysql_error(int xt_err) return(-1); // Unknown error } -xtPublic int xt_ha_pbxt_thread_error_for_mysql(THD *XT_UNUSED(thd), const XTThreadPtr self, int ignore_dup_key) +xtPublic int xt_ha_pbxt_thread_error_for_mysql(THD *thd, const XTThreadPtr self, int ignore_dup_key) { - int xt_err = self->t_exception.e_xt_err; + int xt_err = self->t_exception.e_xt_err; + xtBool dup_key = FALSE; XT_PRINT2(self, "xt_ha_pbxt_thread_error_for_mysql xt_err=%d auto commit=%d\n", (int) xt_err, (int) self->st_auto_commit); switch (xt_err) { @@ -725,6 +778,7 @@ xtPublic int xt_ha_pbxt_thread_error_for_mysql(THD *XT_UNUSED(thd), const XTThre /* If we are in auto-commit mode (and we are not ignoring * duplicate keys) then rollback the transaction automatically. */ + dup_key = TRUE; if (!ignore_dup_key && self->st_auto_commit) goto abort_transaction; break; @@ -790,26 +844,20 @@ xtPublic int xt_ha_pbxt_thread_error_for_mysql(THD *XT_UNUSED(thd), const XTThre /* Locks are held on tables. * Only rollback after locks are released. */ - self->st_auto_commit = TRUE; + /* I do not think this is required, because + * I tell mysql to rollback below, + * besides it is a hack! + self->st_auto_commit = TRUE; + */ self->st_abort_trans = TRUE; } -#ifdef xxxx -/* DBUG_ASSERT(thd->transaction.stmt.ha_list == NULL || - trans == &thd->transaction.stmt); in handler.cc now - * fails, and I don't know if this function can be called anymore! */ - /* Cause any other DBs to do a rollback as well... */ - if (thd) { - /* - * GOTCHA: - * This is a BUG in MySQL. I cannot rollback a transaction if - * pb_mysql_thd->in_sub_stmt! But I must....?! - */ -#ifdef MYSQL_SERVER - if (!thd->in_sub_stmt) - ha_rollback(thd); -#endif + /* Only tell MySQL to rollback if we automatically rollback. + * Note: calling this with (thd, FALSE), cause sp.test to fail. + */ + if (!dup_key) { + if (thd) + thd_mark_transaction_to_rollback(thd, TRUE); } -#endif } break; } @@ -908,7 +956,11 @@ static void pbxt_call_init(XTThreadPtr self) xt_db_data_file_grow_size = (size_t) data_file_grow_size; xt_db_row_file_grow_size = (size_t) row_file_grow_size; +#ifdef DRIZZLED + pbxt_ignore_case = TRUE; +#else pbxt_ignore_case = lower_case_table_names != 0; +#endif if (pbxt_ignore_case) pbxt_share_tables = xt_new_hashtable(self, ha_hash_comp_ci, ha_hash_ci, ha_hash_free, TRUE, FALSE); else @@ -968,7 +1020,7 @@ static void pbxt_call_exit(XTThreadPtr self) */ static void ha_exit(XTThreadPtr self) { - xt_xres_wait_for_recovery(self); + xt_xres_terminate_recovery(self); /* Wrap things up... */ xt_unuse_database(self, self); /* Just in case the main thread has a database in use (for testing)? */ @@ -1024,7 +1076,7 @@ static bool pbxt_show_status(handlerton *XT_UNUSED(hton), THD* thd, cont_(a); if (!not_ok) { - if (stat_print(thd, "PBXT", 4, "", 0, strbuf.sb_cstring, strbuf.sb_len)) + if (stat_print(thd, "PBXT", 4, "", 0, strbuf.sb_cstring, (uint) strbuf.sb_len)) not_ok = TRUE; } xt_sb_set_size(self, &strbuf, 0); @@ -1038,14 +1090,14 @@ static bool pbxt_show_status(handlerton *XT_UNUSED(hton), THD* thd, * return 1 on error, else 0. */ #ifdef DRIZZLED -static int pbxt_init(PluginRegistry ®istry) +static int pbxt_init(Registry ®istry) #else static int pbxt_init(void *p) #endif { int init_err = 0; - XT_TRACE_CALL(); + XT_PRINT0(NULL, "pbxt_init\n"); if (sizeof(xtWordPS) != sizeof(void *)) { printf("PBXT: This won't work, I require that sizeof(xtWordPS) == sizeof(void *)!\n"); @@ -1076,11 +1128,27 @@ static int pbxt_init(void *p) pbxt_hton->close_connection = pbxt_close_connection; /* close_connection, cleanup thread related data. */ pbxt_hton->commit = pbxt_commit; /* commit */ pbxt_hton->rollback = pbxt_rollback; /* rollback */ + if (pbxt_support_xa) { + pbxt_hton->prepare = pbxt_prepare; + pbxt_hton->recover = pbxt_recover; + pbxt_hton->commit_by_xid = pbxt_commit_by_xid; + pbxt_hton->rollback_by_xid = pbxt_rollback_by_xid; + } + else { + pbxt_hton->prepare = NULL; + pbxt_hton->recover = NULL; + pbxt_hton->commit_by_xid = NULL; + pbxt_hton->rollback_by_xid = NULL; + } pbxt_hton->create = pbxt_create_handler; /* Create a new handler */ pbxt_hton->drop_database = pbxt_drop_database; /* Drop a database */ pbxt_hton->panic = pbxt_panic; /* Panic call */ pbxt_hton->show_status = pbxt_show_status; pbxt_hton->flags = HTON_NO_FLAGS; /* HTON_CAN_RECREATE - Without this flags TRUNCATE uses delete_all_rows() */ + pbxt_hton->slot = (uint)-1; /* assign invald value, so we know when it's inited later */ +#if defined(MYSQL_SUPPORTS_BACKUP) && defined(XT_ENABLE_ONLINE_BACKUP) + pbxt_hton->get_backup_engine = pbxt_backup_engine; +#endif #endif if (!xt_init_logging()) /* Initialize logging */ goto error_1; @@ -1160,8 +1228,10 @@ static int pbxt_init(void *p) * Only real problem, 2 threads try to load the same * plugin at the same time. */ +#if MYSQL_VERSION_ID < 60014 myxt_mutex_unlock(&LOCK_plugin); #endif +#endif /* Can't do this here yet, because I need a THD! */ try_(b) { @@ -1195,8 +1265,10 @@ static int pbxt_init(void *p) if (thd) myxt_destroy_thread(thd, FALSE); #ifndef DRIZZLED +#if MYSQL_VERSION_ID < 60014 myxt_mutex_lock(&LOCK_plugin); #endif +#endif } #endif } @@ -1262,7 +1334,7 @@ static int pbxt_init(void *p) } #ifdef DRIZZLED -static int pbxt_end(PluginRegistry ®istry) +static int pbxt_end(Registry ®istry) #else static int pbxt_end(void *) #endif @@ -1378,7 +1450,7 @@ static int pbxt_commit(handlerton *hton, THD *thd, bool all) * transaction (!all && !self->st_auto_commit). */ if (all || self->st_auto_commit) { - XT_PRINT0(self, "xt_xn_commit\n"); + XT_PRINT0(self, "xt_xn_commit in pbxt_commit\n"); if (!xt_xn_commit(self)) err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE); @@ -1402,7 +1474,7 @@ static int pbxt_rollback(handlerton *hton, THD *thd, bool all) XTThreadPtr self; if ((self = (XTThreadPtr) *thd_ha_data(thd, hton))) { - XT_PRINT1(self, "pbxt_rollback all=%d\n", all); + XT_PRINT1(self, "pbxt_rollback all=%d in pbxt_commit\n", all); if (self->st_xact_data) { /* There are no table locks, rollback immediately in all cases @@ -1431,7 +1503,7 @@ static int pbxt_rollback(handlerton *hton, THD *thd, bool all) } #ifdef DRIZZLED -handler *PBXTStorageEngine::create(TABLE_SHARE *table, MEM_ROOT *mem_root) +Cursor *PBXTStorageEngine::create(TABLE_SHARE *table, MEM_ROOT *mem_root) { PBXTStorageEngine * const hton = this; #else @@ -1446,6 +1518,182 @@ static handler *pbxt_create_handler(handlerton *hton, TABLE_SHARE *table, MEM_RO /* * ----------------------------------------------------------------------- + * 2-PHASE COMMIT + * + */ + +#ifndef DRIZZLED + +static int pbxt_prepare(handlerton *hton, THD *thd, bool all) +{ + int err = 0; + XTThreadPtr self; + + XT_TRACE_CALL(); + if ((self = (XTThreadPtr) *thd_ha_data(thd, hton))) { + XT_PRINT1(self, "pbxt_commit all=%d\n", all); + + if (self->st_xact_data) { + /* There are no table locks, commit immediately in all cases + * except when this is a statement commit with an explicit + * transaction (!all && !self->st_auto_commit). + */ + if (all) { + XID xid; + + XT_PRINT0(self, "xt_xn_prepare in pbxt_prepare\n"); + thd_get_xid(thd, (MYSQL_XID*) &xid); + + if (!xt_xn_prepare(xid.length(), (xtWord1 *) &xid, self)) + err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE); + } + } + } + return err; +} + +static XTThreadPtr ha_temp_open_global_database(handlerton *hton, THD **ret_thd, int *temp_thread, char *thread_name, int *err) +{ + THD *thd; + XTThreadPtr self = NULL; + + *temp_thread = 0; + if ((thd = current_thd)) + self = (XTThreadPtr) *thd_ha_data(thd, hton); + else { + //thd = (THD *) myxt_create_thread(); + //*temp_thread |= 2; + } + + if (!self) { + XTExceptionRec e; + + if (!(self = xt_create_thread(thread_name, FALSE, TRUE, &e))) { + *err = xt_ha_pbxt_to_mysql_error(e.e_xt_err); + xt_log_exception(NULL, &e, XT_LOG_DEFAULT); + return NULL; + } + *temp_thread |= 1; + } + + xt_xres_wait_for_recovery(self, XT_RECOVER_DONE); + + try_(a) { + xt_open_database(self, mysql_real_data_home, TRUE); + } + catch_(a) { + *err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE); + if ((*temp_thread & 1)) + xt_free_thread(self); + if (*temp_thread & 2) + myxt_destroy_thread(thd, FALSE); + self = NULL; + } + cont_(a); + + *ret_thd = thd; + return self; +} + +static void ha_temp_close_database(XTThreadPtr self, THD *thd, int temp_thread) +{ + xt_unuse_database(self, self); + if (temp_thread & 1) + xt_free_thread(self); + if (temp_thread & 2) + myxt_destroy_thread(thd, TRUE); +} + +/* Return all prepared transactions, found during recovery. + * This function returns a count. If len is returned, the + * function will be called again. + */ +static int pbxt_recover(handlerton *hton, XID *xid_list, uint len) +{ + xtBool temp_thread; + XTThreadPtr self; + XTDatabaseHPtr db; + uint count = 0; + XTXactPreparePtr xap; + int err; + THD *thd; + + if (!(self = ha_temp_open_global_database(hton, &thd, &temp_thread, "TempForRecover", &err))) + return 0; + + db = self->st_database; + + for (count=0; count<len; count++) { + xap = xt_xn_enum_xa_data(db, &pbxt_xa_enum); + if (!xap) + break; + memcpy(&xid_list[count], xap->xp_xa_data, xap->xp_data_len); + } + + ha_temp_close_database(self, thd, temp_thread); + return (int) count; +} + +static int pbxt_commit_by_xid(handlerton *hton, XID *xid) +{ + xtBool temp_thread; + XTThreadPtr self; + XTDatabaseHPtr db; + int err = 0; + XTXactPreparePtr xap; + THD *thd; + + XT_TRACE_CALL(); + + if (!(self = ha_temp_open_global_database(hton, &thd, &temp_thread, "TempForCommitXA", &err))) + return err; + db = self->st_database; + + if ((xap = xt_xn_find_xa_data(db, xid->length(), (xtWord1 *) xid, TRUE, self))) { + if ((self->st_xact_data = xt_xn_get_xact(db, xap->xp_xact_id, self))) { + self->st_xact_data->xd_flags &= ~XT_XN_XAC_PREPARED; // Prepared transactions cannot be swept! + if (!xt_xn_commit(self)) + err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE); + } + xt_xn_delete_xa_data(db, xap, TRUE, self); + } + + ha_temp_close_database(self, thd, temp_thread); + return 0; +} + +static int pbxt_rollback_by_xid(handlerton *hton, XID *xid) +{ + int temp_thread; + XTThreadPtr self; + XTDatabaseHPtr db; + int err = 0; + XTXactPreparePtr xap; + THD *thd; + + XT_TRACE_CALL(); + + if (!(self = ha_temp_open_global_database(hton, &thd, &temp_thread, "TempForRollbackXA", &err))) + return err; + db = self->st_database; + + if ((xap = xt_xn_find_xa_data(db, xid->length(), (xtWord1 *) xid, TRUE, self))) { + if ((self->st_xact_data = xt_xn_get_xact(db, xap->xp_xact_id, self))) { + self->st_xact_data->xd_flags &= ~XT_XN_XAC_PREPARED; // Prepared transactions cannot be swept! + if (!xt_xn_rollback(self)) + err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE); + } + xt_xn_delete_xa_data(db, xap, TRUE, self); + } + + ha_temp_close_database(self, thd, temp_thread); + return 0; +} + +#endif + +/* + * ----------------------------------------------------------------------- * HANDLER LOCKING FUNCTIONS * * These functions are used get a lock on all handles of a particular table. @@ -1497,7 +1745,7 @@ static void ha_aquire_exclusive_use(XTThreadPtr self, XTSharePtr share, ha_pbxt ha_pbxt *handler; time_t end_time = time(NULL) + XT_SHARE_LOCK_TIMEOUT / 1000; - XT_PRINT1(self, "ha_aquire_exclusive_use %s PBXT X lock\n", share->sh_table_path->ps_path); + XT_PRINT1(self, "ha_aquire_exclusive_use (%s) PBXT X lock\n", share->sh_table_path->ps_path); /* GOTCHA: It is possible to hang here, if you hold * onto the sh_ex_mutex lock, before we really * have the exclusive lock (i.e. before all @@ -1578,7 +1826,7 @@ static void ha_release_exclusive_use(XTThreadPtr self, XTSharePtr share) static void ha_release_exclusive_use(XTThreadPtr XT_UNUSED(self), XTSharePtr share) #endif { - XT_PRINT1(self, "ha_release_exclusive_use %s PBXT X UNLOCK\n", share->sh_table_path->ps_path); + XT_PRINT1(self, "ha_release_exclusive_use (%s) PBXT X UNLOCK\n", share->sh_table_path->ps_path); xt_lock_mutex_ns((xt_mutex_type *) share->sh_ex_mutex); share->sh_table_lock = FALSE; xt_broadcast_cond_ns((xt_cond_type *) share->sh_ex_cond); @@ -1589,7 +1837,7 @@ static xtBool ha_wait_for_shared_use(ha_pbxt *mine, XTSharePtr share) { time_t end_time = time(NULL) + XT_SHARE_LOCK_TIMEOUT / 1000; - XT_PRINT1(xt_get_self(), "ha_wait_for_shared_use %s share lock wait...\n", share->sh_table_path->ps_path); + XT_PRINT1(xt_get_self(), "ha_wait_for_shared_use (%s) share lock wait...\n", share->sh_table_path->ps_path); mine->pb_ex_in_use = 0; xt_lock_mutex_ns((xt_mutex_type *) share->sh_ex_mutex); while (share->sh_table_lock) { @@ -1667,14 +1915,38 @@ xtPublic int ha_pbxt::reopen() * */ -int pbxt_statistics_fill_table(THD *thd, TABLE_LIST *tables, COND *cond) +static int pbxt_statistics_fill_table(THD *thd, TABLE_LIST *tables, COND *cond) { - XTThreadPtr self; + XTThreadPtr self = NULL; int err = 0; + if (!pbxt_hton) { + /* Can't do if PBXT is not loaded! */ + XTExceptionRec e; + + xt_exception_xterr(&e, XT_CONTEXT, XT_ERR_PBXT_NOT_INSTALLED); + xt_log_exception(NULL, &e, XT_LOG_DEFAULT); + /* Just return an empty set: */ + return 0; + } + if (!(self = ha_set_current_thread(thd, &err))) return xt_ha_pbxt_to_mysql_error(err); + + try_(a) { + /* If the thread has no open database, and the global + * database is already open, then open + * the database. Otherwise the statement will be + * executed without an open database, which means + * that the related statistics will be missing. + * + * This includes all background threads. + */ + if (!self->st_database && pbxt_database) { + xt_ha_open_database_of_table(self, (XTPathStrPtr) NULL); + } + err = myxt_statistics_fill_table(self, thd, tables, cond, system_charset_info); } catch_(a) { @@ -1684,6 +1956,24 @@ int pbxt_statistics_fill_table(THD *thd, TABLE_LIST *tables, COND *cond) return err; } +#ifdef DRIZZLED +ColumnInfo pbxt_statistics_fields_info[]= +{ + ColumnInfo("ID", 4, MYSQL_TYPE_LONG, 0, 0, "The ID of the statistic", SKIP_OPEN_TABLE), + ColumnInfo("Name", 40, MYSQL_TYPE_STRING, 0, 0, "The name of the statistic", SKIP_OPEN_TABLE), + ColumnInfo("Value", 8, MYSQL_TYPE_LONGLONG, 0, 0, "The accumulated value", SKIP_OPEN_TABLE), + ColumnInfo() +}; + +class PBXTStatisticsMethods : public InfoSchemaMethods +{ +public: + int fillTable(Session *session, TableList *tables, COND *cond) + { + return pbxt_statistics_fill_table(session, tables, cond); + } +}; +#else ST_FIELD_INFO pbxt_statistics_fields_info[]= { { "ID", 4, MYSQL_TYPE_LONG, 0, 0, "The ID of the statistic", SKIP_OPEN_TABLE}, @@ -1691,24 +1981,28 @@ ST_FIELD_INFO pbxt_statistics_fields_info[]= { "Value", 8, MYSQL_TYPE_LONGLONG, 0, 0, "The accumulated value", SKIP_OPEN_TABLE}, { 0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; +#endif #ifdef DRIZZLED static InfoSchemaTable *pbxt_statistics_table; - -int pbxt_init_statitics(PluginRegistry ®istry) +static PBXTStatisticsMethods pbxt_statistics_methods; +static int pbxt_init_statistics(Registry ®istry) #else -int pbxt_init_statitics(void *p) +static int pbxt_init_statistics(void *p) #endif { #ifdef DRIZZLED - pbxt_statistics_table = (InfoSchemaTable *)xt_calloc_ns(sizeof(InfoSchemaTable)); - pbxt_statistics_table->table_name= "PBXT_STATISTICS"; + //pbxt_statistics_table = (InfoSchemaTable *)xt_calloc_ns(sizeof(InfoSchemaTable)); + //pbxt_statistics_table->table_name= "PBXT_STATISTICS"; + pbxt_statistics_table = new InfoSchemaTable("PBXT_STATISTICS"); + pbxt_statistics_table->setColumnInfo(pbxt_statistics_fields_info); + pbxt_statistics_table->setInfoSchemaMethods(&pbxt_statistics_methods); registry.add(pbxt_statistics_table); #else ST_SCHEMA_TABLE *pbxt_statistics_table = (ST_SCHEMA_TABLE *) p; -#endif pbxt_statistics_table->fields_info = pbxt_statistics_fields_info; pbxt_statistics_table->fill_table = pbxt_statistics_fill_table; +#endif #if defined(XT_WIN) && defined(XT_COREDUMP) void register_crash_filter(); @@ -1721,14 +2015,14 @@ int pbxt_init_statitics(void *p) } #ifdef DRIZZLED -int pbxt_exit_statitics(PluginRegistry ®istry) +static int pbxt_exit_statistics(Registry ®istry) #else -int pbxt_exit_statitics(void *XT_UNUSED(p)) +static int pbxt_exit_statistics(void *XT_UNUSED(p)) #endif { #ifdef DRIZZLED registry.remove(pbxt_statistics_table); - xt_free_ns(pbxt_statistics_table); + delete pbxt_statistics_table; #endif return(0); } @@ -1758,7 +2052,11 @@ ha_pbxt::ha_pbxt(handlerton *hton, TABLE_SHARE *table_arg) : handler(hton, table * exist for the storage engine. This is also used by the default rename_table and * delete_table method in handler.cc. */ +#ifdef DRIZZLED +const char **PBXTStorageEngine::bas_ext() const +#else const char **ha_pbxt::bas_ext() const +#endif { return pbxt_extensions; } @@ -1800,11 +2098,13 @@ MX_TABLE_TYPES_T ha_pbxt::table_flags() const * purposes! HA_NOT_EXACT_COUNT | */ +#ifndef DRIZZLED /* * This basically means we have a file with the name of * database table (which we do). */ HA_FILE_BASED | +#endif /* * Not sure what this does (but MyISAM and InnoDB have it)?! * Could it mean that we support the handler functions. @@ -1971,7 +2271,7 @@ int ha_pbxt::open(const char *table_path, int XT_UNUSED(mode), uint XT_UNUSED(te if (!(self = ha_set_current_thread(thd, &err))) return xt_ha_pbxt_to_mysql_error(err); - XT_PRINT1(self, "ha_pbxt::open %s\n", table_path); + XT_PRINT1(self, "open (%s)\n", table_path); pb_ex_in_use = 1; try_(a) { @@ -2049,7 +2349,7 @@ int ha_pbxt::close(void) } } - XT_PRINT1(self, "ha_pbxt::close %s\n", pb_share && pb_share->sh_table_path->ps_path ? pb_share->sh_table_path->ps_path : "unknown"); + XT_PRINT1(self, "close (%s)\n", pb_share && pb_share->sh_table_path->ps_path ? pb_share->sh_table_path->ps_path : "unknown"); if (self) { try_(a) { @@ -2125,9 +2425,10 @@ void ha_pbxt::init_auto_increment(xtWord8 min_auto_inc) if (!TS(table)->next_number_key_offset) { // Autoincrement at key-start err = index_last(table->record[1]); - if (!err) + if (!err && !table->next_number_field->is_null(TS(table)->rec_buff_length)) { /* {PRE-INC} */ nr = (xtWord8) table->next_number_field->val_int_offset(TS(table)->rec_buff_length); + } } else { /* Do an index scan to find the largest value! */ @@ -2180,8 +2481,10 @@ void ha_pbxt::init_auto_increment(xtWord8 min_auto_inc) table->next_number_field = tmp_fie; table->in_use = tmp_thd; - if (xn_started) + if (xn_started) { + XT_PRINT0(self, "xt_xn_commit in init_auto_increment\n"); xt_xn_commit(self); + } } xt_spinlock_unlock(&tab->tab_ainc_lock); } @@ -2228,13 +2531,13 @@ void ha_pbxt::get_auto_increment(MX_ULONGLONG_T offset, MX_ULONGLONG_T increment * insert into t1 values (-1); * insert into t1 values (NULL); */ -void ha_pbxt::set_auto_increment(Field *nr) +xtPublic void ha_set_auto_increment(XTOpenTablePtr ot, Field *nr) { register XTTableHPtr tab; MX_ULONGLONG_T nr_int_val; nr_int_val = nr->val_int(); - tab = pb_open_tab->ot_table; + tab = ot->ot_table; if (nr->cmp((const unsigned char *)&tab->tab_auto_inc) > 0) { xt_spinlock_lock(&tab->tab_ainc_lock); @@ -2260,9 +2563,9 @@ void ha_pbxt::set_auto_increment(Field *nr) #else tab->tab_dic.dic_min_auto_inc = nr_int_val + 100; #endif - pb_open_tab->ot_thread = xt_get_self(); - if (!xt_tab_write_min_auto_inc(pb_open_tab)) - xt_log_and_clear_exception(pb_open_tab->ot_thread); + ot->ot_thread = xt_get_self(); + if (!xt_tab_write_min_auto_inc(ot)) + xt_log_and_clear_exception(ot->ot_thread); } } } @@ -2305,7 +2608,7 @@ int ha_pbxt::write_row(byte *buf) ASSERT_NS(pb_ex_in_use); - XT_PRINT1(pb_open_tab->ot_thread, "ha_pbxt::write_row %s\n", pb_share->sh_table_path->ps_path); + XT_PRINT1(pb_open_tab->ot_thread, "write_row (%s)\n", pb_share->sh_table_path->ps_path); XT_DISABLED_TRACE(("INSERT tx=%d val=%d\n", (int) pb_open_tab->ot_thread->st_xact_data->xd_start_xn_id, (int) XT_GET_DISK_4(&buf[1]))); //statistic_increment(ha_write_count,&LOCK_status); #ifdef PBMS_ENABLED @@ -2350,7 +2653,7 @@ int ha_pbxt::write_row(byte *buf) err = update_err; goto done; } - set_auto_increment(table->next_number_field); + ha_set_auto_increment(pb_open_tab, table->next_number_field); } if (!xt_tab_new_record(pb_open_tab, (xtWord1 *) buf)) { @@ -2423,7 +2726,7 @@ int ha_pbxt::update_row(const byte * old_data, byte * new_data) ASSERT_NS(pb_ex_in_use); - XT_PRINT1(self, "ha_pbxt::update_row %s\n", pb_share->sh_table_path->ps_path); + XT_PRINT1(self, "update_row (%s)\n", pb_share->sh_table_path->ps_path); XT_DISABLED_TRACE(("UPDATE tx=%d val=%d\n", (int) self->st_xact_data->xd_start_xn_id, (int) XT_GET_DISK_4(&new_data[1]))); //statistic_increment(ha_update_count,&LOCK_status); @@ -2472,7 +2775,7 @@ int ha_pbxt::update_row(const byte * old_data, byte * new_data) old_map = mx_tmp_use_all_columns(table, table->read_set); nr = table->found_next_number_field->val_int(); - set_auto_increment(table->found_next_number_field); + ha_set_auto_increment(pb_open_tab, table->found_next_number_field); mx_tmp_restore_column_map(table, old_map); } @@ -2504,7 +2807,7 @@ int ha_pbxt::delete_row(const byte * buf) ASSERT_NS(pb_ex_in_use); - XT_PRINT1(pb_open_tab->ot_thread, "ha_pbxt::delete_row %s\n", pb_share->sh_table_path->ps_path); + XT_PRINT1(pb_open_tab->ot_thread, "delete_row (%s)\n", pb_share->sh_table_path->ps_path); XT_DISABLED_TRACE(("DELETE tx=%d val=%d\n", (int) pb_open_tab->ot_thread->st_xact_data->xd_start_xn_id, (int) XT_GET_DISK_4(&buf[1]))); //statistic_increment(ha_delete_count,&LOCK_status); @@ -2829,7 +3132,8 @@ int ha_pbxt::xt_index_prev_read(XTOpenTablePtr ot, XTIndexPtr ind, xtBool key_on int ha_pbxt::index_init(uint idx, bool XT_UNUSED(sorted)) { - XTIndexPtr ind; + XTIndexPtr ind; + XTThreadPtr thread = pb_open_tab->ot_thread; /* select count(*) from smalltab_PBXT; * ignores the error below, and continues to @@ -2851,6 +3155,15 @@ int ha_pbxt::index_init(uint idx, bool XT_UNUSED(sorted)) printf("index_init %s index %d cols req=%d/%d read_bits=%X write_bits=%X index_bits=%X\n", pb_open_tab->ot_table->tab_name->ps_path, (int) idx, pb_open_tab->ot_cols_req, pb_open_tab->ot_cols_req, (int) *table->read_set->bitmap, (int) *table->write_set->bitmap, (int) *ind->mi_col_map.bitmap); #endif + /* Start a statement based transaction as soon + * as a read is done for a modify type statement! + * Previously, this was done too late! + */ + if (!thread->st_stat_trans) { + trans_register_ha(pb_mysql_thd, FALSE, pbxt_hton); + XT_PRINT0(thread, "ha_pbxt::update_row trans_register_ha all=FALSE\n"); + thread->st_stat_trans = TRUE; + } } else { pb_open_tab->ot_cols_req = ha_get_max_bit(table->read_set); @@ -2901,7 +3214,7 @@ int ha_pbxt::index_init(uint idx, bool XT_UNUSED(sorted)) #endif } - xt_xlog_check_long_writer(pb_open_tab->ot_thread); + xt_xlog_check_long_writer(thread); pb_open_tab->ot_thread->st_statistics.st_scan_index++; return 0; @@ -2911,7 +3224,7 @@ int ha_pbxt::index_end() { int err = 0; - XT_TRACE_CALL(); + XT_TRACE_METHOD(); XTThreadPtr thread = pb_open_tab->ot_thread; @@ -2991,7 +3304,7 @@ int ha_pbxt::index_read_xt(byte * buf, uint idx, const byte *key, uint key_len, ASSERT_NS(pb_ex_in_use); - XT_PRINT1(pb_open_tab->ot_thread, "ha_pbxt::index_read_xt %s\n", pb_share->sh_table_path->ps_path); + XT_PRINT1(pb_open_tab->ot_thread, "index_read_xt (%s)\n", pb_share->sh_table_path->ps_path); XT_DISABLED_TRACE(("search tx=%d val=%d update=%d\n", (int) pb_open_tab->ot_thread->st_xact_data->xd_start_xn_id, (int) XT_GET_DISK_4(key), pb_modified)); ind = (XTIndexPtr) pb_share->sh_dic_keys[idx]; @@ -3072,7 +3385,7 @@ int ha_pbxt::index_next(byte * buf) int err = 0; XTIndexPtr ind; - XT_TRACE_CALL(); + XT_TRACE_METHOD(); //statistic_increment(ha_read_next_count,&LOCK_status); ASSERT_NS(pb_ex_in_use); @@ -3114,7 +3427,7 @@ int ha_pbxt::index_next_same(byte * buf, const byte *key, uint length) XTIndexPtr ind; XTIdxSearchKeyRec search_key; - XT_TRACE_CALL(); + XT_TRACE_METHOD(); //statistic_increment(ha_read_next_count,&LOCK_status); ASSERT_NS(pb_ex_in_use); @@ -3154,7 +3467,7 @@ int ha_pbxt::index_prev(byte * buf) int err = 0; XTIndexPtr ind; - XT_TRACE_CALL(); + XT_TRACE_METHOD(); //statistic_increment(ha_read_prev_count,&LOCK_status); ASSERT_NS(pb_ex_in_use); @@ -3188,7 +3501,7 @@ int ha_pbxt::index_first(byte * buf) XTIndexPtr ind; XTIdxSearchKeyRec search_key; - XT_TRACE_CALL(); + XT_TRACE_METHOD(); //statistic_increment(ha_read_first_count,&LOCK_status); ASSERT_NS(pb_ex_in_use); @@ -3228,7 +3541,7 @@ int ha_pbxt::index_last(byte * buf) XTIndexPtr ind; XTIdxSearchKeyRec search_key; - XT_TRACE_CALL(); + XT_TRACE_METHOD(); //statistic_increment(ha_read_last_count,&LOCK_status); ASSERT_NS(pb_ex_in_use); @@ -3275,10 +3588,11 @@ int ha_pbxt::index_last(byte * buf) */ int ha_pbxt::rnd_init(bool scan) { - int err = 0; + int err = 0; + XTThreadPtr thread = pb_open_tab->ot_thread; - XT_PRINT1(pb_open_tab->ot_thread, "ha_pbxt::rnd_init %s\n", pb_share->sh_table_path->ps_path); - XT_DISABLED_TRACE(("seq scan tx=%d\n", (int) pb_open_tab->ot_thread->st_xact_data->xd_start_xn_id)); + XT_PRINT1(thread, "rnd_init (%s)\n", pb_share->sh_table_path->ps_path); + XT_DISABLED_TRACE(("seq scan tx=%d\n", (int) thread->st_xact_data->xd_start_xn_id)); /* Call xt_tab_seq_exit() to make sure the resources used by the previous * scan are freed. In particular make sure cache page ref count is decremented. @@ -3296,8 +3610,18 @@ int ha_pbxt::rnd_init(bool scan) xt_tab_seq_exit(pb_open_tab); /* The number of columns required: */ - if (pb_open_tab->ot_is_modify) + if (pb_open_tab->ot_is_modify) { pb_open_tab->ot_cols_req = table->read_set->MX_BIT_SIZE(); + /* Start a statement based transaction as soon + * as a read is done for a modify type statement! + * Previously, this was done too late! + */ + if (!thread->st_stat_trans) { + trans_register_ha(pb_mysql_thd, FALSE, pbxt_hton); + XT_PRINT0(thread, "ha_pbxt::update_row trans_register_ha all=FALSE\n"); + thread->st_stat_trans = TRUE; + } + } else { pb_open_tab->ot_cols_req = ha_get_max_bit(table->read_set); @@ -3322,14 +3646,14 @@ int ha_pbxt::rnd_init(bool scan) else xt_tab_seq_reset(pb_open_tab); - xt_xlog_check_long_writer(pb_open_tab->ot_thread); + xt_xlog_check_long_writer(thread); return err; } int ha_pbxt::rnd_end() { - XT_TRACE_CALL(); + XT_TRACE_METHOD(); /* * make permanent the lock for the last scanned row @@ -3358,7 +3682,7 @@ int ha_pbxt::rnd_next(byte *buf) int err = 0; xtBool eof; - XT_TRACE_CALL(); + XT_TRACE_METHOD(); ASSERT_NS(pb_ex_in_use); //statistic_increment(ha_read_rnd_next_count, &LOCK_status); xt_xlog_check_long_writer(pb_open_tab->ot_thread); @@ -3393,7 +3717,7 @@ int ha_pbxt::rnd_next(byte *buf) */ void ha_pbxt::position(const byte *XT_UNUSED(record)) { - XT_TRACE_CALL(); + XT_TRACE_METHOD(); ASSERT_NS(pb_ex_in_use); /* * I changed this from using little endian to big endian. @@ -3429,10 +3753,10 @@ int ha_pbxt::rnd_pos(byte * buf, byte *pos) { int err = 0; - XT_TRACE_CALL(); + XT_TRACE_METHOD(); ASSERT_NS(pb_ex_in_use); //statistic_increment(ha_read_rnd_count, &LOCK_status); - XT_PRINT1(pb_open_tab->ot_thread, "ha_pbxt::rnd_pos %s\n", pb_share->sh_table_path->ps_path); + XT_PRINT1(pb_open_tab->ot_thread, "rnd_pos (%s)\n", pb_share->sh_table_path->ps_path); pb_open_tab->ot_curr_rec_id = mi_uint4korr((xtWord1 *) pos); switch (xt_tab_dirty_read_record(pb_open_tab, (xtWord1 *) buf)) { @@ -3509,7 +3833,7 @@ int ha_pbxt::info(uint flag) XTOpenTablePtr ot; int in_use; - XT_TRACE_CALL(); + XT_TRACE_METHOD(); if (!(in_use = pb_ex_in_use)) { pb_ex_in_use = 1; @@ -3535,7 +3859,7 @@ int ha_pbxt::info(uint flag) stats.index_file_length = xt_ind_node_to_offset(ot->ot_table, ot->ot_table->tab_ind_eof); stats.delete_length = ot->ot_table->tab_rec_fnum * ot->ot_rec_size; //check_time = info.check_time; - stats.mean_rec_length = ot->ot_rec_size; + stats.mean_rec_length = (ulong) ot->ot_rec_size; } if (flag & HA_STATUS_CONST) { @@ -3551,7 +3875,9 @@ int ha_pbxt::info(uint flag) stats.block_size = XT_INDEX_PAGE_SIZE; if (share->tmp_table == NO_TMP_TABLE) -#if MYSQL_VERSION_ID > 60005 +#ifdef DRIZZLED +#define WHICH_MUTEX mutex +#elif MYSQL_VERSION_ID >= 50404 #define WHICH_MUTEX LOCK_ha_data #else #define WHICH_MUTEX mutex @@ -3559,19 +3885,15 @@ int ha_pbxt::info(uint flag) #ifdef SAFE_MUTEX -#if MYSQL_VERSION_ID < 60000 +#if MYSQL_VERSION_ID < 50404 #if MYSQL_VERSION_ID < 50123 safe_mutex_lock(&share->mutex,__FILE__,__LINE__); #else safe_mutex_lock(&share->mutex,0,__FILE__,__LINE__); #endif #else -#if MYSQL_VERSION_ID < 60004 - safe_mutex_lock(&share->mutex,__FILE__,__LINE__); -#else safe_mutex_lock(&share->WHICH_MUTEX,0,__FILE__,__LINE__); #endif -#endif #else // SAFE_MUTEX @@ -3675,7 +3997,7 @@ int ha_pbxt::extra(enum ha_extra_function operation) { int err = 0; - XT_PRINT2(xt_get_self(), "ha_pbxt::extra %s operation=%d\n", pb_share->sh_table_path->ps_path, operation); + XT_PRINT2(xt_get_self(), "ha_pbxt::extra (%s) operation=%d\n", pb_share->sh_table_path->ps_path, operation); switch (operation) { case HA_EXTRA_RESET_STATE: @@ -3771,14 +4093,14 @@ int ha_pbxt::extra(enum ha_extra_function operation) */ int ha_pbxt::reset(void) { - XT_TRACE_CALL(); + XT_TRACE_METHOD(); extra(HA_EXTRA_RESET_STATE); XT_RETURN(0); } void ha_pbxt::unlock_row() { - XT_TRACE_CALL(); + XT_TRACE_METHOD(); if (pb_open_tab) pb_open_tab->ot_table->tab_locks.xt_remove_temp_lock(pb_open_tab, FALSE); } @@ -3802,7 +4124,7 @@ int ha_pbxt::delete_all_rows() XTDDTable *tab_def = NULL; char path[PATH_MAX]; - XT_TRACE_CALL(); + XT_TRACE_METHOD(); if (thd_sql_command(thd) != SQLCOM_TRUNCATE) { /* Just like InnoDB we only handle TRUNCATE TABLE @@ -3906,7 +4228,7 @@ int ha_pbxt::analyze(THD *thd, HA_CHECK_OPT *XT_UNUSED(check_opt)) xtXactID clean_xn_id = 0; uint cnt = 10; - XT_TRACE_CALL(); + XT_TRACE_METHOD(); if (!pb_open_tab) { if ((err = reopen())) @@ -4056,7 +4378,7 @@ xtPublic int ha_pbxt::external_lock(THD *thd, int lock_type) ASSERT_NS(pb_ex_in_use); */ - XT_PRINT1(self, "ha_pbxt::EXTERNAL_LOCK %s lock_type=UNLOCK\n", pb_share->sh_table_path->ps_path); + XT_PRINT1(self, "EXTERNAL_LOCK (%s) lock_type=UNLOCK\n", pb_share->sh_table_path->ps_path); /* Make any temporary locks on this table permanent. * @@ -4189,10 +4511,9 @@ xtPublic int ha_pbxt::external_lock(THD *thd, int lock_type) xt_broadcast_cond_ns((xt_cond_type *) pb_share->sh_ex_cond); } else { - XT_PRINT2(self, "ha_pbxt::EXTERNAL_LOCK %s lock_type=%d\n", pb_share->sh_table_path->ps_path, lock_type); + XT_PRINT2(self, "ha_pbxt::EXTERNAL_LOCK (%s) lock_type=%d\n", pb_share->sh_table_path->ps_path, lock_type); if (pb_lock_table) { - pb_ex_in_use = 1; try_(a) { if (!pb_table_locked) @@ -4243,14 +4564,18 @@ xtPublic int ha_pbxt::external_lock(THD *thd, int lock_type) if ((pb_open_tab->ot_for_update = (lock_type == F_WRLCK))) { switch ((int) thd_sql_command(thd)) { case SQLCOM_DELETE: +#ifndef DRIZZLED case SQLCOM_DELETE_MULTI: +#endif /* turn DELETE IGNORE into normal DELETE. The IGNORE option causes problems because * when a record is deleted we add an xlog record which we cannot "rollback" later * when we find that an FK-constraint has failed. */ thd->lex->ignore = false; case SQLCOM_UPDATE: +#ifndef DRIZZLED case SQLCOM_UPDATE_MULTI: +#endif case SQLCOM_REPLACE: case SQLCOM_REPLACE_SELECT: case SQLCOM_INSERT: @@ -4265,7 +4590,9 @@ xtPublic int ha_pbxt::external_lock(THD *thd, int lock_type) case SQLCOM_DROP_TABLE: case SQLCOM_DROP_INDEX: case SQLCOM_LOAD: +#ifndef DRIZZLED case SQLCOM_REPAIR: +#endif case SQLCOM_OPTIMIZE: self->st_stat_modify = TRUE; break; @@ -4316,11 +4643,16 @@ xtPublic int ha_pbxt::external_lock(THD *thd, int lock_type) self->st_xact_mode = thd_tx_isolation(thd) <= ISO_READ_COMMITTED ? XT_XACT_COMMITTED_READ : XT_XACT_REPEATABLE_READ; self->st_ignore_fkeys = (thd_test_options(thd,OPTION_NO_FOREIGN_KEY_CHECKS)) != 0; self->st_auto_commit = (thd_test_options(thd, (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) == 0; +#ifdef DRIZZLED + self->st_table_trans = FALSE; +#else self->st_table_trans = thd_sql_command(thd) == SQLCOM_LOCK_TABLES; +#endif self->st_abort_trans = FALSE; self->st_stat_ended = FALSE; self->st_stat_trans = FALSE; XT_PRINT0(self, "xt_xn_begin\n"); + xt_xres_wait_for_recovery(self, XT_RECOVER_SWEPT); if (!xt_xn_begin(self)) { err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key); pb_ex_in_use = 0; @@ -4404,7 +4736,7 @@ int ha_pbxt::start_stmt(THD *thd, thr_lock_type lock_type) if (!(self = ha_set_current_thread(thd, &err))) return xt_ha_pbxt_to_mysql_error(err); - XT_PRINT2(self, "ha_pbxt::start_stmt %s lock_type=%d\n", pb_share->sh_table_path->ps_path, (int) lock_type); + XT_PRINT2(self, "ha_pbxt::start_stmt (%s) lock_type=%d\n", pb_share->sh_table_path->ps_path, (int) lock_type); if (!pb_open_tab) { if ((err = reopen())) @@ -4430,12 +4762,12 @@ int ha_pbxt::start_stmt(THD *thd, thr_lock_type lock_type) /* This section handles "auto-commit"... */ if (self->st_xact_data && self->st_auto_commit && self->st_table_trans) { if (self->st_abort_trans) { - XT_PRINT0(self, "xt_xn_rollback\n"); + XT_PRINT0(self, "xt_xn_rollback in start_stmt\n"); if (!xt_xn_rollback(self)) err = xt_ha_pbxt_thread_error_for_mysql(pb_mysql_thd, self, pb_ignore_dup_key); } else { - XT_PRINT0(self, "xt_xn_commit\n"); + XT_PRINT0(self, "xt_xn_commit in start_stmt\n"); if (!xt_xn_commit(self)) err = xt_ha_pbxt_thread_error_for_mysql(pb_mysql_thd, self, pb_ignore_dup_key); } @@ -4466,9 +4798,11 @@ int ha_pbxt::start_stmt(THD *thd, thr_lock_type lock_type) if (pb_open_tab->ot_for_update) { switch ((int) thd_sql_command(thd)) { case SQLCOM_UPDATE: - case SQLCOM_UPDATE_MULTI: case SQLCOM_DELETE: +#ifndef DRIZZLED + case SQLCOM_UPDATE_MULTI: case SQLCOM_DELETE_MULTI: +#endif case SQLCOM_REPLACE: case SQLCOM_REPLACE_SELECT: case SQLCOM_INSERT: @@ -4483,14 +4817,15 @@ int ha_pbxt::start_stmt(THD *thd, thr_lock_type lock_type) case SQLCOM_DROP_TABLE: case SQLCOM_DROP_INDEX: case SQLCOM_LOAD: +#ifndef DRIZZLED case SQLCOM_REPAIR: +#endif case SQLCOM_OPTIMIZE: self->st_stat_modify = TRUE; break; } } - /* (***) This is required at this level! * No matter how often it is called, it is still the start of a * statement. We need to make sure statements that are NOT mistaken @@ -4516,6 +4851,7 @@ int ha_pbxt::start_stmt(THD *thd, thr_lock_type lock_type) self->st_stat_ended = FALSE; self->st_stat_trans = FALSE; XT_PRINT0(self, "xt_xn_begin\n"); + xt_xres_wait_for_recovery(self, XT_RECOVER_SWEPT); if (!xt_xn_begin(self)) { err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key); goto complete; @@ -4673,7 +5009,9 @@ THR_LOCK_DATA **ha_pbxt::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_ * */ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE) && +#ifndef DRIZZLED !(thd_in_lock_tables(thd) && thd_sql_command(thd) == SQLCOM_LOCK_TABLES) && +#endif !thd_tablespace_op(thd) && thd_sql_command(thd) != SQLCOM_TRUNCATE && thd_sql_command(thd) != SQLCOM_OPTIMIZE && @@ -4691,22 +5029,23 @@ THR_LOCK_DATA **ha_pbxt::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_ * Stewart: removed SQLCOM_CALL, not sure of implications. */ - if (lock_type == TL_READ_NO_INSERT && - (!thd_in_lock_tables(thd) + if (lock_type == TL_READ_NO_INSERT #ifndef DRIZZLED + && (!thd_in_lock_tables(thd) || thd_sql_command(thd) == SQLCOM_CALL + ) #endif - )) + ) { lock_type = TL_READ; } - XT_PRINT3(xt_get_self(), "ha_pbxt::store_lock %s %d->%d\n", pb_share->sh_table_path->ps_path, pb_lock.type, lock_type); + XT_PRINT3(xt_get_self(), "store_lock (%s) %d->%d\n", pb_share->sh_table_path->ps_path, pb_lock.type, lock_type); pb_lock.type = lock_type; } #ifdef PBXT_HANDLER_TRACE else { - XT_PRINT3(xt_get_self(), "ha_pbxt::store_lock %s %d->%d (ignore/unlock)\n", pb_share->sh_table_path->ps_path, lock_type, lock_type); + XT_PRINT3(xt_get_self(), "store_lock (%s) %d->%d (ignore/unlock)\n", pb_share->sh_table_path->ps_path, lock_type, lock_type); } #endif *to++= &pb_lock; @@ -4723,15 +5062,23 @@ THR_LOCK_DATA **ha_pbxt::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_ * during create if the table_flag HA_DROP_BEFORE_CREATE was specified for * the storage engine. */ +#ifdef DRIZZLED +int PBXTStorageEngine::doDropTable(Session &, std::string table_path_str) +#else int ha_pbxt::delete_table(const char *table_path) +#endif { THD *thd = current_thd; int err = 0; XTThreadPtr self = NULL; XTSharePtr share; +#ifdef DRIZZLED + const char *table_path = table_path_str.c_str(); +#endif + STAT_TRACE(self, *thd_query(thd)); - XT_PRINT1(self, "ha_pbxt::delete_table %s\n", table_path); + XT_PRINT1(self, "delete_table (%s)\n", table_path); if (XTSystemTableShare::isSystemTable(table_path)) return delete_system_table(table_path); @@ -4795,7 +5142,7 @@ int ha_pbxt::delete_table(const char *table_path) #endif } catch_(a) { - err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key); + err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE); #ifdef DRIZZLED if (err == HA_ERR_NO_SUCH_TABLE) err = ENOENT; @@ -4819,7 +5166,11 @@ int ha_pbxt::delete_table(const char *table_path) return err; } +#ifdef DRIZZLED +int PBXTStorageEngine::delete_system_table(const char *table_path) +#else int ha_pbxt::delete_system_table(const char *table_path) +#endif { THD *thd = current_thd; XTExceptionRec e; @@ -4857,7 +5208,13 @@ int ha_pbxt::delete_system_table(const char *table_path) * This function can be used to move a table from one database to * another. */ +#ifdef DRIZZLED +int PBXTStorageEngine::doRenameTable(Session *, + const char *from, + const char *to) +#else int ha_pbxt::rename_table(const char *from, const char *to) +#endif { THD *thd = current_thd; int err = 0; @@ -4865,15 +5222,13 @@ int ha_pbxt::rename_table(const char *from, const char *to) XTSharePtr share; XTDatabaseHPtr to_db; - XT_TRACE_CALL(); - if (XTSystemTableShare::isSystemTable(from)) return rename_system_table(from, to); if (!(self = ha_set_current_thread(thd, &err))) return xt_ha_pbxt_to_mysql_error(err); - XT_PRINT2(self, "ha_pbxt::rename_table %s -> %s\n", from, to); + XT_PRINT2(self, "rename_table (%s -> %s)\n", from, to); #ifdef PBMS_ENABLED PBMSResultRec result; @@ -4929,7 +5284,7 @@ int ha_pbxt::rename_table(const char *from, const char *to) #endif } catch_(a) { - err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key); + err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE); } cont_(a); @@ -4940,7 +5295,11 @@ int ha_pbxt::rename_table(const char *from, const char *to) XT_RETURN(err); } +#ifdef DRIZZLED +int PBXTStorageEngine::rename_system_table(const char *XT_UNUSED(from), const char *XT_UNUSED(to)) +#else int ha_pbxt::rename_system_table(const char *XT_UNUSED(from), const char *XT_UNUSED(to)) +#endif { return ER_NOT_SUPPORTED_YET; } @@ -5029,7 +5388,15 @@ ha_rows ha_pbxt::records_in_range(uint inx, key_range *min_key, key_range *max_k * Called from handle.cc by ha_create_table(). */ +#ifdef DRIZZLED +int PBXTStorageEngine::doCreateTable(Session *, + const char *table_path, + Table &table_arg, + HA_CREATE_INFO &create_info, + drizzled::message::Table &XT_UNUSED(proto)) +#else int ha_pbxt::create(const char *table_path, TABLE *table_arg, HA_CREATE_INFO *create_info) +#endif { THD *thd = current_thd; int err = 0; @@ -5037,37 +5404,61 @@ int ha_pbxt::create(const char *table_path, TABLE *table_arg, HA_CREATE_INFO *cr XTDDTable *tab_def = NULL; XTDictionaryRec dic; - memset(&dic, 0, sizeof(dic)); + if ((strcmp(table_path, "./pbxt/location") == 0) || (strcmp(table_path, "./pbxt/statistics") == 0)) + return 0; - XT_TRACE_CALL(); + memset(&dic, 0, sizeof(dic)); if (!(self = ha_set_current_thread(thd, &err))) return xt_ha_pbxt_to_mysql_error(err); +#ifdef DRIZZLED + XT_PRINT2(self, "create (%s) %s\n", table_path, (create_info.options & HA_LEX_CREATE_TMP_TABLE) ? "temporary" : ""); +#else + XT_PRINT2(self, "create (%s) %s\n", table_path, (create_info->options & HA_LEX_CREATE_TMP_TABLE) ? "temporary" : ""); +#endif STAT_TRACE(self, *thd_query(thd)); - XT_PRINT1(self, "ha_pbxt::create %s\n", table_path); try_(a) { xt_ha_open_database_of_table(self, (XTPathStrPtr) table_path); +#ifdef DRIZZLED + for (uint i=0; i<TS(&table_arg)->keys; i++) { + if (table_arg.key_info[i].key_length > XT_INDEX_MAX_KEY_SIZE) + xt_throw_sulxterr(XT_CONTEXT, XT_ERR_KEY_TOO_LARGE, table_arg.key_info[i].name, (u_long) XT_INDEX_MAX_KEY_SIZE); + } +#else for (uint i=0; i<TS(table_arg)->keys; i++) { if (table_arg->key_info[i].key_length > XT_INDEX_MAX_KEY_SIZE) xt_throw_sulxterr(XT_CONTEXT, XT_ERR_KEY_TOO_LARGE, table_arg->key_info[i].name, (u_long) XT_INDEX_MAX_KEY_SIZE); } +#endif /* ($) auto_increment_value will be zero if * AUTO_INCREMENT is not used. Otherwise * Query was ALTER TABLE ... AUTO_INCREMENT = x; or * CREATE TABLE ... AUTO_INCREMENT = x; */ +#ifdef DRIZZLED + tab_def = xt_ri_create_table(self, true, (XTPathStrPtr) table_path, *thd_query(thd), myxt_create_table_from_table(self, &table_arg)); + tab_def->checkForeignKeys(self, create_info.options & HA_LEX_CREATE_TMP_TABLE); +#else tab_def = xt_ri_create_table(self, true, (XTPathStrPtr) table_path, *thd_query(thd), myxt_create_table_from_table(self, table_arg)); tab_def->checkForeignKeys(self, create_info->options & HA_LEX_CREATE_TMP_TABLE); +#endif dic.dic_table = tab_def; +#ifdef DRIZZLED + dic.dic_my_table = &table_arg; + dic.dic_tab_flags = (create_info.options & HA_LEX_CREATE_TMP_TABLE) ? XT_TAB_FLAGS_TEMP_TAB : 0; + dic.dic_min_auto_inc = (xtWord8) create_info.auto_increment_value; /* ($) */ + dic.dic_def_ave_row_size = table_arg.s->getAvgRowLength(); +#else dic.dic_my_table = table_arg; dic.dic_tab_flags = (create_info->options & HA_LEX_CREATE_TMP_TABLE) ? XT_TAB_FLAGS_TEMP_TAB : 0; dic.dic_min_auto_inc = (xtWord8) create_info->auto_increment_value; /* ($) */ dic.dic_def_ave_row_size = (xtWord8) table_arg->s->avg_row_length; +#endif myxt_setup_dictionary(self, &dic); /* @@ -5089,7 +5480,7 @@ int ha_pbxt::create(const char *table_path, TABLE *table_arg, HA_CREATE_INFO *cr if (tab_def) tab_def->finalize(self); dic.dic_table = NULL; - err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key); + err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE); } cont_(a); @@ -5161,7 +5552,7 @@ bool ha_pbxt::get_error_message(int XT_UNUSED(error), String *buf) if (!self->t_exception.e_xt_err) return FALSE; - buf->copy(self->t_exception.e_err_msg, strlen(self->t_exception.e_err_msg), system_charset_info); + buf->copy(self->t_exception.e_err_msg, (uint32) strlen(self->t_exception.e_err_msg), system_charset_info); return TRUE; } @@ -5421,16 +5812,31 @@ static MYSQL_SYSVAR_INT(sweeper_priority, xt_db_sweeper_priority, #ifdef DRIZZLED static MYSQL_SYSVAR_INT(max_threads, pbxt_max_threads, - PLUGIN_VAR_OPCMDARG, + PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, "The maximum number of threads used by PBXT", NULL, NULL, 500, 20, 20000, 1); #else static MYSQL_SYSVAR_INT(max_threads, pbxt_max_threads, - PLUGIN_VAR_OPCMDARG, + PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, "The maximum number of threads used by PBXT, 0 = set according to MySQL max_connections.", NULL, NULL, 0, 0, 20000, 1); #endif +#ifndef DEBUG +static MYSQL_SYSVAR_BOOL(support_xa, pbxt_support_xa, + PLUGIN_VAR_OPCMDARG, + "Enable PBXT support for the XA two-phase commit, default is enabled", + NULL, NULL, TRUE); +#else +static MYSQL_SYSVAR_BOOL(support_xa, pbxt_support_xa, + PLUGIN_VAR_OPCMDARG, + "Enable PBXT support for the XA two-phase commit, default is disabled (due to assertion failure in MySQL)", + /* The problem is, in MySQL an assertion fails in debug mode: + * Assertion failed: (total_ha_2pc == (ulong) opt_bin_log+1), function ha_recover, file handler.cc, line 1557. + */ + NULL, NULL, FALSE); +#endif + static struct st_mysql_sys_var* pbxt_system_variables[] = { MYSQL_SYSVAR(index_cache_size), MYSQL_SYSVAR(record_cache_size), @@ -5448,6 +5854,7 @@ static struct st_mysql_sys_var* pbxt_system_variables[] = { MYSQL_SYSVAR(offline_log_function), MYSQL_SYSVAR(sweeper_priority), MYSQL_SYSVAR(max_threads), + MYSQL_SYSVAR(support_xa), NULL }; #endif @@ -5494,8 +5901,8 @@ mysql_declare_plugin(pbxt) "Paul McCullagh, PrimeBase Technologies GmbH", "PBXT internal system statitics", PLUGIN_LICENSE_GPL, - pbxt_init_statitics, /* plugin init */ - pbxt_exit_statitics, /* plugin deinit */ + pbxt_init_statistics, /* plugin init */ + pbxt_exit_statistics, /* plugin deinit */ #ifndef DRIZZLED 0x0005, #endif diff --git a/storage/pbxt/src/ha_pbxt.h b/storage/pbxt/src/ha_pbxt.h index d48bcd34147..a7548d6fa86 100644 --- a/storage/pbxt/src/ha_pbxt.h +++ b/storage/pbxt/src/ha_pbxt.h @@ -27,9 +27,9 @@ #ifdef DRIZZLED #include <drizzled/common.h> -#include <drizzled/handler.h> -#include <drizzled/plugin/storage_engine.h> #include <mysys/thr_lock.h> +#include <drizzled/cursor.h> + #else #include "mysql_priv.h" #endif @@ -53,17 +53,31 @@ class ha_pbxt; #ifdef DRIZZLED -class PBXTStorageEngine : public StorageEngine { +class PBXTStorageEngine : public drizzled::plugin::StorageEngine +{ + + int delete_system_table(const char *table_path); + int rename_system_table(const char * from, const char * to); + public: PBXTStorageEngine(std::string name_arg) - : StorageEngine(name_arg, HTON_NO_FLAGS) {} + : drizzled::plugin::StorageEngine(name_arg, HTON_NO_FLAGS) {} + + void operator delete(void *) {} + void operator delete[] (void *) {} /* override */ int close_connection(Session *); /* override */ int commit(Session *, bool); /* override */ int rollback(Session *, bool); - /* override */ handler *create(TABLE_SHARE *, MEM_ROOT *); + /* override */ Cursor *create(TABLE_SHARE *, MEM_ROOT *); /* override */ void drop_database(char *); /* override */ bool show_status(Session *, stat_print_fn *, enum ha_stat_type); + /* override */ const char **bas_ext() const; + /* override */ int doCreateTable(Session *session, const char *table_name, + Table &table_arg, HA_CREATE_INFO + &create_info, drizzled::message::Table &proto); + /* override */ int doRenameTable(Session *, const char *from, const char *to); + /* override */ int doDropTable(Session &session, std::string table_path); }; typedef PBXTStorageEngine handlerton; @@ -139,9 +153,9 @@ class ha_pbxt: public handler * don't implement this method unless you really have indexes. */ const char *index_type(uint inx) { (void) inx; return "BTREE"; } - +#ifndef DRIZZLED const char **bas_ext() const; - +#endif MX_UINT8_T table_cache_type(); /* @@ -241,11 +255,13 @@ class ha_pbxt: public handler int optimize(THD* thd, HA_CHECK_OPT* check_opt); int check(THD* thd, HA_CHECK_OPT* check_opt); ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key); - int delete_table(const char *from); +#ifndef DRIZZLED int delete_system_table(const char *table_path); - int rename_table(const char * from, const char * to); + int delete_table(const char *from); int rename_system_table(const char * from, const char * to); + int rename_table(const char * from, const char * to); int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info); //required +#endif void update_create_info(HA_CREATE_INFO *create_info); THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type); //required @@ -277,6 +293,7 @@ struct XTThread *xt_ha_thd_to_self(THD* thd); int xt_ha_pbxt_to_mysql_error(int xt_err); int xt_ha_pbxt_thread_error_for_mysql(THD *thd, const XTThreadPtr self, int ignore_dup_key); void xt_ha_all_threads_close_database(XTThreadPtr self, XTDatabase *db); +void ha_set_auto_increment(XTOpenTablePtr ot, Field *nr); /* * These hooks are suppossed to only be used by InnoDB: diff --git a/storage/pbxt/src/ha_xtsys.h b/storage/pbxt/src/ha_xtsys.h index 598abe0938f..16fb4a140ae 100644 --- a/storage/pbxt/src/ha_xtsys.h +++ b/storage/pbxt/src/ha_xtsys.h @@ -30,8 +30,9 @@ #ifdef DRIZZLED #include <drizzled/common.h> -#include <drizzled/handler.h> +#include <drizzled/handler_structs.h> #include <drizzled/current_session.h> +#include <drizzled/cursor.h> #else #include "mysql_priv.h" #endif diff --git a/storage/pbxt/src/heap_xt.cc b/storage/pbxt/src/heap_xt.cc index dcfa1dae11f..a4e3fec1611 100644 --- a/storage/pbxt/src/heap_xt.cc +++ b/storage/pbxt/src/heap_xt.cc @@ -73,7 +73,7 @@ xtPublic void xt_check_heap(XTThreadPtr XT_NDEBUG_UNUSED(self), XTHeapPtr XT_NDE } #ifdef DEBUG_MEMORY -xtPublic void xt_mm_heap_reference(XTThreadPtr self, XTHeapPtr hp, u_int line, c_char *file) +xtPublic void xt_mm_heap_reference(XTThreadPtr XT_UNUSED(self), XTHeapPtr hp, u_int line, c_char *file) #else xtPublic void xt_heap_reference(XTThreadPtr, XTHeapPtr hp) #endif diff --git a/storage/pbxt/src/index_xt.cc b/storage/pbxt/src/index_xt.cc index 91e03c3e424..81437caf723 100644 --- a/storage/pbxt/src/index_xt.cc +++ b/storage/pbxt/src/index_xt.cc @@ -829,14 +829,25 @@ static void idx_next_branch_item(XTTableHPtr XT_UNUSED(tab), XTIndexPtr ind, XTI result->sr_item.i_item_offset += result->sr_item.i_item_size + result->sr_item.i_node_ref_size; bitem = branch->tb_data + result->sr_item.i_item_offset; - if (ind->mi_fix_key) - ilen = result->sr_item.i_item_size; + if (result->sr_item.i_item_offset < result->sr_item.i_total_size) { + if (ind->mi_fix_key) + ilen = result->sr_item.i_item_size; + else { + ilen = myxt_get_key_length(ind, bitem) + XT_RECORD_REF_SIZE; + result->sr_item.i_item_size = ilen; + } + xt_get_res_record_ref(bitem + ilen - XT_RECORD_REF_SIZE, result); /* (Only valid if i_item_offset < i_total_size) */ + } else { - ilen = myxt_get_key_length(ind, bitem) + XT_RECORD_REF_SIZE; - result->sr_item.i_item_size = ilen; + result->sr_item.i_item_size = 0; + result->sr_rec_id = 0; + result->sr_row_id = 0; } - xt_get_res_record_ref(bitem + ilen - XT_RECORD_REF_SIZE, result); /* (Only valid if i_item_offset < i_total_size) */ - result->sr_branch = IDX_GET_NODE_REF(tab, bitem, result->sr_item.i_node_ref_size); + if (result->sr_item.i_node_ref_size) + /* IDX_GET_NODE_REF() loads the branch reference to the LEFT of the item. */ + result->sr_branch = IDX_GET_NODE_REF(tab, bitem, result->sr_item.i_node_ref_size); + else + result->sr_branch = 0; } xtPublic void xt_prev_branch_item_fix(XTTableHPtr XT_UNUSED(tab), XTIndexPtr XT_UNUSED(ind), XTIdxBranchDPtr branch, register XTIdxResultRec *result) @@ -3987,7 +3998,7 @@ xtPublic xtBool xt_flush_indices(XTOpenTablePtr ot, off_t *bytes_flushed, xtBool * here. */ if (!(tab->tab_dic.dic_tab_flags & XT_TAB_FLAGS_TEMP_TAB)) { - if (!xt_xlog_flush_log(ot->ot_thread)) + if (!xt_xlog_flush_log(tab->tab_db, ot->ot_thread)) goto failed_2; if (!il->il_flush(ot)) goto failed_2; diff --git a/storage/pbxt/src/lock_xt.cc b/storage/pbxt/src/lock_xt.cc index 6a2d7a5b0e3..4513de17c5e 100644 --- a/storage/pbxt/src/lock_xt.cc +++ b/storage/pbxt/src/lock_xt.cc @@ -1246,7 +1246,7 @@ xtPublic void xt_spinlock_init(XTThreadPtr self, XTSpinLockPtr spl) (void) self; spl->spl_lock = 0; #ifdef XT_NO_ATOMICS - xt_init_mutex(self, &spl->spl_mutex); + xt_init_mutex_with_autoname(self, &spl->spl_mutex); #endif #ifdef DEBUG spl->spl_locker = 0; diff --git a/storage/pbxt/src/locklist_xt.h b/storage/pbxt/src/locklist_xt.h index 4170e220ae1..17852b66d0b 100644 --- a/storage/pbxt/src/locklist_xt.h +++ b/storage/pbxt/src/locklist_xt.h @@ -24,11 +24,16 @@ #ifndef __xt_locklist_h__ #define __xt_locklist_h__ +/* + * XT_THREAD_LOCK_INFO and DEBUG_LOCKING code must be updated to avoid calls to xt_get_self() as it can be called before hton->slot is + * assigned by MySQL which is used by xt_get_self() + */ + #ifdef DEBUG -#define XT_THREAD_LOCK_INFO +//#define XT_THREAD_LOCK_INFO #ifndef XT_WIN /* We need DEBUG_LOCKING in order to enable pthread function wrappers */ -#define DEBUG_LOCKING +//#define DEBUG_LOCKING #endif #endif diff --git a/storage/pbxt/src/memory_xt.cc b/storage/pbxt/src/memory_xt.cc index a920a47e29b..b2f6c248b3c 100644 --- a/storage/pbxt/src/memory_xt.cc +++ b/storage/pbxt/src/memory_xt.cc @@ -34,7 +34,7 @@ #include "trace_xt.h" #ifdef DEBUG -//#define RECORD_MM +#define RECORD_MM #endif #ifdef DEBUG @@ -367,9 +367,8 @@ static long mm_find_pointer(void *ptr) return(-1); } -static long mm_add_pointer(void *ptr, u_int id) +static long mm_add_pointer(void *ptr, u_int XT_UNUSED(id)) { -#pragma unused(id) register int i, n, guess; if (mm_nr_in_use == mm_total_allocated) { diff --git a/storage/pbxt/src/myxt_xt.cc b/storage/pbxt/src/myxt_xt.cc index fdcc078c957..2b5d59e72fb 100644 --- a/storage/pbxt/src/myxt_xt.cc +++ b/storage/pbxt/src/myxt_xt.cc @@ -36,7 +36,7 @@ #include <drizzled/current_session.h> #include <drizzled/sql_lex.h> #include <drizzled/session.h> -extern "C" struct charset_info_st *session_charset(Session *session); +//extern "C" struct charset_info_st *session_charset(Session *session); extern pthread_key_t THR_Session; #else #include "mysql_priv.h" @@ -171,7 +171,9 @@ xtPublic u_int myxt_create_key_from_key(XTIndexPtr ind, xtWord1 *key, xtWord1 *o for (u_int i=0; i<ind->mi_seg_count && (int) k_length > 0; i++, old += keyseg->length, keyseg++) { +#ifndef DRIZZLED enum ha_base_keytype type = (enum ha_base_keytype) keyseg->type; +#endif u_int length = keyseg->length < k_length ? keyseg->length : k_length; u_int char_length; xtWord1 *pos; @@ -192,14 +194,18 @@ xtPublic u_int myxt_create_key_from_key(XTIndexPtr ind, xtWord1 *key, xtWord1 *o pos = old; if (keyseg->flag & HA_SPACE_PACK) { uchar *end = pos + length; +#ifndef DRIZZLED if (type != HA_KEYTYPE_NUM) { +#endif while (end > pos && end[-1] == ' ') end--; +#ifndef DRIZZLED } else { while (pos < end && pos[0] == ' ') pos++; } +#endif k_length -= length; length = (u_int) (end-pos); FIX_LENGTH(cs, pos, length, char_length); @@ -276,6 +282,7 @@ xtPublic u_int myxt_create_key_from_row(XTIndexPtr ind, xtWord1 *key, xtWord1 *r char_length= ((cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : length); pos = record + keyseg->start; +#ifndef DRIZZLED if (type == HA_KEYTYPE_BIT) { if (keyseg->bit_length) @@ -289,17 +296,22 @@ xtPublic u_int myxt_create_key_from_row(XTIndexPtr ind, xtWord1 *key, xtWord1 *r key+= length; continue; } +#endif if (keyseg->flag & HA_SPACE_PACK) { end = pos + length; +#ifndef DRIZZLED if (type != HA_KEYTYPE_NUM) { +#endif while (end > pos && end[-1] == ' ') end--; +#ifndef DRIZZLED } else { while (pos < end && pos[0] == ' ') pos++; } +#endif length = (u_int) (end-pos); FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); @@ -333,6 +345,7 @@ xtPublic u_int myxt_create_key_from_row(XTIndexPtr ind, xtWord1 *key, xtWord1 *r if (keyseg->flag & HA_SWAP_KEY) { /* Numerical column */ #ifdef HAVE_ISNAN +#ifndef DRIZZLED if (type == HA_KEYTYPE_FLOAT) { float nr; @@ -345,7 +358,9 @@ xtPublic u_int myxt_create_key_from_row(XTIndexPtr ind, xtWord1 *key, xtWord1 *r continue; } } - else if (type == HA_KEYTYPE_DOUBLE) { + else +#endif + if (type == HA_KEYTYPE_DOUBLE) { double nr; float8get(nr,pos); @@ -414,6 +429,7 @@ xtPublic u_int myxt_create_foreign_key_from_row(XTIndexPtr ind, xtWord1 *key, xt char_length= ((cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : length); pos = record + keyseg->start; +#ifndef DRIZZLED if (type == HA_KEYTYPE_BIT) { if (keyseg->bit_length) @@ -427,17 +443,22 @@ xtPublic u_int myxt_create_foreign_key_from_row(XTIndexPtr ind, xtWord1 *key, xt key+= length; continue; } +#endif if (keyseg->flag & HA_SPACE_PACK) { end = pos + length; +#ifndef DRIZZLED if (type != HA_KEYTYPE_NUM) { +#endif while (end > pos && end[-1] == ' ') end--; +#ifndef DRIZZLED } else { while (pos < end && pos[0] == ' ') pos++; } +#endif length = (u_int) (end-pos); FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); @@ -471,6 +492,7 @@ xtPublic u_int myxt_create_foreign_key_from_row(XTIndexPtr ind, xtWord1 *key, xt if (keyseg->flag & HA_SWAP_KEY) { /* Numerical column */ #ifdef HAVE_ISNAN +#ifndef DRIZZLED if (type == HA_KEYTYPE_FLOAT) { float nr; @@ -483,7 +505,9 @@ xtPublic u_int myxt_create_foreign_key_from_row(XTIndexPtr ind, xtWord1 *key, xt continue; } } - else if (type == HA_KEYTYPE_DOUBLE) { + else +#endif + if (type == HA_KEYTYPE_DOUBLE) { double nr; float8get(nr,pos); @@ -622,7 +646,6 @@ static char *mx_get_length_and_data(Field *field, char *dest, xtWord4 *len) case MYSQL_TYPE_SET: case MYSQL_TYPE_GEOMETRY: #else - case DRIZZLE_TYPE_TINY: case DRIZZLE_TYPE_LONG: case DRIZZLE_TYPE_DOUBLE: case DRIZZLE_TYPE_NULL: @@ -740,7 +763,6 @@ static void mx_set_length_and_data(Field *field, char *dest, xtWord4 len, char * case MYSQL_TYPE_SET: case MYSQL_TYPE_GEOMETRY: #else - case DRIZZLE_TYPE_TINY: case DRIZZLE_TYPE_LONG: case DRIZZLE_TYPE_DOUBLE: case DRIZZLE_TYPE_NULL: @@ -825,6 +847,7 @@ xtPublic xtBool myxt_create_row_from_key(XTOpenTablePtr XT_UNUSED(ot), XTIndexPt } record[keyseg->null_pos] &= ~keyseg->null_bit; } +#ifndef DRIZZLED if (keyseg->type == HA_KEYTYPE_BIT) { uint length = keyseg->length; @@ -845,6 +868,7 @@ xtPublic xtBool myxt_create_row_from_key(XTOpenTablePtr XT_UNUSED(ot), XTIndexPt key+= length; continue; } +#endif if (keyseg->flag & HA_SPACE_PACK) { uint length; @@ -854,16 +878,20 @@ xtPublic xtBool myxt_create_row_from_key(XTOpenTablePtr XT_UNUSED(ot), XTIndexPt goto err; #endif pos = record+keyseg->start; +#ifndef DRIZZLED if (keyseg->type != (int) HA_KEYTYPE_NUM) { +#endif memcpy(pos,key,(size_t) length); bfill(pos+length,keyseg->length-length,' '); +#ifndef DRIZZLED } else { bfill(pos,keyseg->length-length,' '); memcpy(pos+keyseg->length-length,key,(size_t) length); } +#endif key+=length; continue; } @@ -945,7 +973,7 @@ xtPublic xtBool myxt_create_row_from_key(XTOpenTablePtr XT_UNUSED(ot), XTIndexPt static int my_compare_bin(uchar *a, uint a_length, uchar *b, uint b_length, my_bool part_key, my_bool skip_end_space) { - uint length= min(a_length,b_length); + uint length= a_length < b_length ? a_length : b_length; uchar *end= a+ length; int flag; @@ -1023,6 +1051,7 @@ xtPublic u_int myxt_get_key_length(XTIndexPtr ind, xtWord1 *key_buf) get_key_pack_length(seg_len, pack_len, key_data); key_data += seg_len; break; +#ifndef DRIZZLED case HA_KEYTYPE_NUM: { /* Numeric key */ if (keyseg->flag & HA_SPACE_PACK) @@ -1035,15 +1064,16 @@ xtPublic u_int myxt_get_key_length(XTIndexPtr ind, xtWord1 *key_buf) case HA_KEYTYPE_INT8: case HA_KEYTYPE_SHORT_INT: case HA_KEYTYPE_USHORT_INT: + case HA_KEYTYPE_INT24: + case HA_KEYTYPE_FLOAT: + case HA_KEYTYPE_BIT: +#endif case HA_KEYTYPE_LONG_INT: case HA_KEYTYPE_ULONG_INT: - case HA_KEYTYPE_INT24: case HA_KEYTYPE_UINT24: - case HA_KEYTYPE_FLOAT: case HA_KEYTYPE_DOUBLE: case HA_KEYTYPE_LONGLONG: case HA_KEYTYPE_ULONGLONG: - case HA_KEYTYPE_BIT: key_data += keyseg->length; break; case HA_KEYTYPE_END: @@ -1190,6 +1220,7 @@ xtPublic int myxt_compare_key(XTIndexPtr ind, int search_flags, uint key_length, b += b_length; break; } +#ifndef DRIZZLED case HA_KEYTYPE_INT8: { int i_1 = (int) *((signed char *) a); @@ -1218,6 +1249,7 @@ xtPublic int myxt_compare_key(XTIndexPtr ind, int search_flags, uint key_length, b += keyseg->length; break; } +#endif case HA_KEYTYPE_LONG_INT: { int32 l_1 = sint4korr(a); int32 l_2 = sint4korr(b); @@ -1236,6 +1268,7 @@ xtPublic int myxt_compare_key(XTIndexPtr ind, int search_flags, uint key_length, b += keyseg->length; break; } +#ifndef DRIZZLED case HA_KEYTYPE_INT24: { int32 l_1 = sint3korr(a); int32 l_2 = sint3korr(b); @@ -1245,6 +1278,7 @@ xtPublic int myxt_compare_key(XTIndexPtr ind, int search_flags, uint key_length, b += keyseg->length; break; } +#endif case HA_KEYTYPE_UINT24: { int32 l_1 = uint3korr(a); int32 l_2 = uint3korr(b); @@ -1254,6 +1288,7 @@ xtPublic int myxt_compare_key(XTIndexPtr ind, int search_flags, uint key_length, b += keyseg->length; break; } +#ifndef DRIZZLED case HA_KEYTYPE_FLOAT: { float f_1, f_2; @@ -1270,6 +1305,7 @@ xtPublic int myxt_compare_key(XTIndexPtr ind, int search_flags, uint key_length, b += keyseg->length; break; } +#endif case HA_KEYTYPE_DOUBLE: { double d_1, d_2; @@ -1286,6 +1322,7 @@ xtPublic int myxt_compare_key(XTIndexPtr ind, int search_flags, uint key_length, b += keyseg->length; break; } +#ifndef DRIZZLED case HA_KEYTYPE_NUM: { /* Numeric key */ if (keyseg->flag & HA_SPACE_PACK) { @@ -1339,6 +1376,7 @@ xtPublic int myxt_compare_key(XTIndexPtr ind, int search_flags, uint key_length, b += b_length; break; } +#endif #ifdef HAVE_LONG_LONG case HA_KEYTYPE_LONGLONG: { longlong ll_a = sint8korr(a); @@ -1359,9 +1397,11 @@ xtPublic int myxt_compare_key(XTIndexPtr ind, int search_flags, uint key_length, break; } #endif +#ifndef DRIZZLED case HA_KEYTYPE_BIT: /* TODO: What here? */ break; +#endif case HA_KEYTYPE_END: /* Ready */ goto end; } @@ -1410,16 +1450,19 @@ xtPublic u_int myxt_key_seg_length(XTIndexSegRec *keyseg, u_int key_offset, xtWo key_length = has_null + a_length + pack_len; break; } +#ifndef DRIZZLED case HA_KEYTYPE_INT8: case HA_KEYTYPE_SHORT_INT: case HA_KEYTYPE_USHORT_INT: + case HA_KEYTYPE_INT24: + case HA_KEYTYPE_FLOAT: +#endif case HA_KEYTYPE_LONG_INT: case HA_KEYTYPE_ULONG_INT: - case HA_KEYTYPE_INT24: case HA_KEYTYPE_UINT24: - case HA_KEYTYPE_FLOAT: case HA_KEYTYPE_DOUBLE: break; +#ifndef DRIZZLED case HA_KEYTYPE_NUM: { /* Numeric key */ if (keyseg->flag & HA_SPACE_PACK) { @@ -1428,14 +1471,17 @@ xtPublic u_int myxt_key_seg_length(XTIndexSegRec *keyseg, u_int key_offset, xtWo } break; } +#endif #ifdef HAVE_LONG_LONG case HA_KEYTYPE_LONGLONG: case HA_KEYTYPE_ULONGLONG: break; #endif +#ifndef DRIZZLED case HA_KEYTYPE_BIT: /* TODO: What here? */ break; +#endif case HA_KEYTYPE_END: /* Ready */ break; } @@ -1486,7 +1532,7 @@ xtPublic xtWord4 myxt_store_row_length(XTOpenTablePtr ot, char *rec_buff) return row_size; } -static xtWord4 mx_store_row(XTOpenTablePtr ot, xtWord4 row_size, char *rec_buff) +xtPublic xtWord4 myxt_store_row_data(XTOpenTablePtr ot, xtWord4 row_size, char *rec_buff) { TABLE *table = ot->ot_table->tab_dic.dic_my_table; char *sdata; @@ -1614,8 +1660,9 @@ xtPublic size_t myxt_load_row_length(XTOpenTablePtr ot, size_t buffer_size, xtWo } /* Unload from PBXT variable length format to the MySQL row format. */ -xtPublic xtBool myxt_load_row(XTOpenTablePtr ot, xtWord1 *source_buf, xtWord1 *dest_buff, u_int col_cnt) +xtPublic xtWord4 myxt_load_row_data(XTOpenTablePtr ot, xtWord1 *source_buf, xtWord1 *dest_buff, u_int col_cnt) { + xtWord1 *input_buf = source_buf; TABLE *table; xtWord4 len; Field *curr_field; @@ -1624,7 +1671,7 @@ xtPublic xtBool myxt_load_row(XTOpenTablePtr ot, xtWord1 *source_buf, xtWord1 *d if (!(table = ot->ot_table->tab_dic.dic_my_table)) { xt_register_taberr(XT_REG_CONTEXT, XT_ERR_NO_DICTIONARY, ot->ot_table->tab_name); - return FAILED; + return 0; } /* According to the InnoDB implementation: @@ -1657,7 +1704,7 @@ xtPublic xtBool myxt_load_row(XTOpenTablePtr ot, xtWord1 *source_buf, xtWord1 *d default: // Length byte if (*source_buf > 240) { xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_RECORD_FORMAT); - return FAILED; + return 0; } len = *source_buf; source_buf++; @@ -1671,7 +1718,12 @@ xtPublic xtBool myxt_load_row(XTOpenTablePtr ot, xtWord1 *source_buf, xtWord1 *d source_buf += len; } - return OK; + return (xtWord4) (source_buf - input_buf); +} + +xtPublic xtBool myxt_load_row(XTOpenTablePtr ot, xtWord1 *source_buf, xtWord1 *dest_buff, u_int col_cnt) +{ + return myxt_load_row_data(ot, source_buf, dest_buff, col_cnt) != 0; } xtPublic xtBool myxt_find_column(XTOpenTablePtr ot, u_int *col_idx, const char *col_name) @@ -1784,7 +1836,7 @@ xtPublic xtBool myxt_store_row(XTOpenTablePtr ot, XTTabRecInfoPtr rec_info, char else { xtWord4 row_size; - if (!(row_size = mx_store_row(ot, XT_REC_EXT_HEADER_SIZE, rec_buff))) + if (!(row_size = myxt_store_row_data(ot, XT_REC_EXT_HEADER_SIZE, rec_buff))) return FAILED; if (row_size - XT_REC_FIX_EXT_HEADER_DIFF <= ot->ot_rec_size) { rec_info->ri_fix_rec_buf = (XTTabRecFixDPtr) &ot->ot_row_wbuffer[XT_REC_FIX_EXT_HEADER_DIFF]; @@ -1951,7 +2003,7 @@ static TABLE *my_open_table(XTThreadPtr self, XTDatabaseHPtr XT_UNUSED(db), XTPa #ifdef DRIZZLED share->init(db_name, 0, name, path); - if ((error = open_table_def(thd, share)) || + if ((error = open_table_def(*thd, share)) || (error = open_table_from_share(thd, share, "", 0, (uint32_t) READ_ALL, 0, table, OTM_OPEN))) { xt_free(self, table); @@ -1995,7 +2047,7 @@ static TABLE *my_open_table(XTThreadPtr self, XTDatabaseHPtr XT_UNUSED(db), XTPa return NULL; } -#if MYSQL_VERSION_ID >= 60003 +#if MYSQL_VERSION_ID >= 50404 if ((error = open_table_from_share(thd, share, "", 0, (uint) READ_ALL, 0, table, OTM_OPEN))) #else if ((error = open_table_from_share(thd, share, "", 0, (uint) READ_ALL, 0, table, FALSE))) @@ -2145,7 +2197,10 @@ static XTIndexPtr my_create_index(XTThreadPtr self, TABLE *table_arg, u_int idx, if (options & HA_OPTION_PACK_KEYS || (index->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY | HA_SPACE_PACK_USED))) { - if (key_part->length > 8 && (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_NUM || + if (key_part->length > 8 && (type == HA_KEYTYPE_TEXT || +#ifndef DRIZZLED + type == HA_KEYTYPE_NUM || +#endif (type == HA_KEYTYPE_BINARY && !field->zero_pack()))) { /* No blobs here */ @@ -2213,8 +2268,12 @@ static XTIndexPtr my_create_index(XTThreadPtr self, TABLE *table_arg, u_int idx, else if (field->type() == MYSQL_TYPE_ENUM) { switch (seg->length) { case 2: +#ifdef DRIZZLED + ASSERT_NS(FALSE); +#else seg->type = HA_KEYTYPE_USHORT_INT; break; +#endif case 3: seg->type = HA_KEYTYPE_UINT24; break; @@ -2675,7 +2734,11 @@ xtPublic xtBool myxt_load_dictionary(XTThreadPtr self, XTDictionaryPtr dic, XTDa if (!(my_tab = my_open_table(self, db, tab_path))) return FAILED; dic->dic_my_table = my_tab; +#ifdef DRIZZLED + dic->dic_def_ave_row_size = (xtWord8) my_tab->s->getAvgRowLength(); +#else dic->dic_def_ave_row_size = (xtWord8) my_tab->s->avg_row_length; +#endif myxt_setup_dictionary(self, dic); dic->dic_keys = (XTIndexPtr *) xt_calloc(self, sizeof(XTIndexPtr) * TS(my_tab)->keys); for (uint i=0; i<TS(my_tab)->keys; i++) @@ -2805,8 +2868,10 @@ static void ha_create_dd_index(XTThreadPtr self, XTDDIndex *ind, KEY *key) static char *my_type_to_string(XTThreadPtr self, Field *field, TABLE *XT_UNUSED(my_tab)) { - char buffer[MAX_FIELD_WIDTH + 400], *ptr; + char buffer[MAX_FIELD_WIDTH + 400]; + const char *ptr; String type((char *) buffer, sizeof(buffer), system_charset_info); + xtWord4 len; /* GOTCHA: * - Above sets the string length to the same as the buffer, @@ -2817,10 +2882,17 @@ static char *my_type_to_string(XTThreadPtr self, Field *field, TABLE *XT_UNUSED( */ type.length(0); field->sql_type(type); - ptr = type.c_ptr(); + ptr = type.ptr(); + len = type.length(); + + if (len >= sizeof(buffer)) + len = sizeof(buffer)-1; + if (ptr != buffer) - xt_strcpy(sizeof(buffer), buffer, ptr); + xt_strcpy(sizeof(buffer), buffer, ptr); + buffer[len] = 0; + if (field->has_charset()) { /* Always include the charset so that we can compare types * for FK/PK releations. @@ -2877,6 +2949,10 @@ xtPublic XTDDTable *myxt_create_table_from_table(XTThreadPtr self, TABLE *my_tab xtPublic void myxt_static_convert_identifier(XTThreadPtr XT_UNUSED(self), MX_CHARSET_INFO *cs, char *from, char *to, size_t to_len) { +#ifdef DRIZZLED + ((void *)cs); + xt_strcpy(to_len, to, from); +#else uint errors; /* @@ -2888,11 +2964,16 @@ xtPublic void myxt_static_convert_identifier(XTThreadPtr XT_UNUSED(self), MX_CHA xt_strcpy(to_len, to, from); else strconvert(cs, from, &my_charset_utf8_general_ci, to, to_len, &errors); +#endif } // cs == current_thd->charset() xtPublic char *myxt_convert_identifier(XTThreadPtr self, MX_CHARSET_INFO *cs, char *from) { +#ifdef DRIZZLED + char *to = xt_dup_string(self, from); + ((void *)cs); +#else uint errors; u_int len; char *to; @@ -2904,6 +2985,7 @@ xtPublic char *myxt_convert_identifier(XTThreadPtr self, MX_CHARSET_INFO *cs, ch to = (char *) xt_malloc(self, len); strconvert(cs, from, &my_charset_utf8_general_ci, to, len, &errors); } +#endif return to; } @@ -2954,9 +3036,9 @@ xtPublic MX_CHARSET_INFO *myxt_getcharset(bool convert) THD *thd = current_thd; if (thd) - return thd_charset(thd); + return (MX_CHARSET_INFO *)thd_charset(thd); } - return &my_charset_utf8_general_ci; + return (MX_CHARSET_INFO *)&my_charset_utf8_general_ci; } xtPublic void *myxt_create_thread() @@ -3011,12 +3093,26 @@ xtPublic void *myxt_create_thread() return NULL; } - if (!(new_thd = new THD())) { + if (!(new_thd = new THD)) { my_thread_end(); xt_register_error(XT_REG_CONTEXT, XT_ERR_MYSQL_ERROR, 0, "Unable to create MySQL thread (THD)"); return NULL; } + /* + * If PBXT is the default storage engine, then creating any THD objects will add extra + * references to the PBXT plugin object. because the threads are created but PBXT + * this creates a self reference, and the reference count does not go to zero + * on shutdown. + * + * The server then issues a message that it is forcing shutdown of the plugin. + * + * However, the engine reference is not required by the THDs used by PBXT, so + * I just remove them here. + */ + plugin_unlock(NULL, new_thd->variables.table_plugin); + new_thd->variables.table_plugin = NULL; + new_thd->thread_stack = (char *) &new_thd; new_thd->store_globals(); lex_start(new_thd); @@ -3051,7 +3147,7 @@ xtPublic void myxt_destroy_thread(void *thread, xtBool end_threads) #else close_thread_tables(thd); #endif - + delete thd; /* Remember that we don't have a THD */ @@ -3128,11 +3224,12 @@ xtPublic int myxt_statistics_fill_table(XTThreadPtr self, void *th, void *ta, vo const char *stat_name; u_llong stat_value; XTStatisticsRec statistics; + XTDatabaseHPtr db = self->st_database; xt_gather_statistics(&statistics); for (u_int rec_id=0; !err && rec_id<XT_STAT_CURRENT_MAX; rec_id++) { stat_name = xt_get_stat_meta_data(rec_id)->sm_name; - stat_value = xt_get_statistic(&statistics, self->st_database, rec_id); + stat_value = xt_get_statistic(&statistics, db, rec_id); col=0; mx_put_u_llong(table, col++, rec_id+1); @@ -3213,19 +3310,31 @@ static void myxt_bitmap_init(XTThreadPtr self, MX_BITMAP *map, u_int n_bits) my_bitmap_map *buf; uint size_in_bytes = (((n_bits) + 31) / 32) * 4; - buf = (my_bitmap_map *) xt_malloc(self, size_in_bytes); + buf = (my_bitmap_map *) xt_malloc(self, size_in_bytes); + +#ifdef DRIZZLED + map->init(buf, n_bits); +#else map->bitmap= buf; map->n_bits= n_bits; create_last_word_mask(map); bitmap_clear_all(map); +#endif } static void myxt_bitmap_free(XTThreadPtr self, MX_BITMAP *map) { +#ifdef DRIZZLED + my_bitmap_map *buf = map->getBitmap(); + if (buf) + xt_free(self, buf); + map->setBitmap(NULL); +#else if (map->bitmap) { xt_free(self, map->bitmap); map->bitmap = NULL; } +#endif } /* @@ -3269,3 +3378,29 @@ XTDDColumn *XTDDColumnFactory::createFromMySQLField(XTThread *self, TABLE *my_ta return col; } +/* + * ----------------------------------------------------------------------- + * utilities + */ + +/* + * MySQL (not sure about Drizzle) first calls hton->init and then assigns the plugin a thread slot + * which is used by xt_get_self(). This is a problem as pbxt_init() starts a number of daemon threads + * which could try to use the slot before it is assigned. This code waits till slot is inited. + * We cannot directly check hton->slot as in some versions of MySQL it can be 0 before init which is a + * valid value. + */ +extern ulong total_ha; + +xtPublic void myxt_wait_pbxt_plugin_slot_assigned(XTThread *self) +{ +#ifdef DRIZZLED + static LEX_STRING plugin_name = { C_STRING_WITH_LEN("PBXT") }; + + while (!self->t_quit && !Registry::singleton().find(&plugin_name)) + xt_sleep_milli_second(1); +#else + while(!self->t_quit && (pbxt_hton->slot >= total_ha)) + xt_sleep_milli_second(1); +#endif +} diff --git a/storage/pbxt/src/myxt_xt.h b/storage/pbxt/src/myxt_xt.h index 484440a15b6..546b57c6e84 100644 --- a/storage/pbxt/src/myxt_xt.h +++ b/storage/pbxt/src/myxt_xt.h @@ -52,8 +52,10 @@ void myxt_set_default_row_from_key(XTOpenTablePtr ot, XTIndexPtr ind, xtWord1 * void myxt_print_key(XTIndexPtr ind, xtWord1 *key_value); xtWord4 myxt_store_row_length(XTOpenTablePtr ot, char *rec_buff); +xtWord4 myxt_store_row_data(XTOpenTablePtr ot, xtWord4 row_size, char *rec_buff); xtBool myxt_store_row(XTOpenTablePtr ot, XTTabRecInfoPtr rec_info, char *rec_buff); size_t myxt_load_row_length(XTOpenTablePtr ot, size_t buffer_size, xtWord1 *source_buf, u_int *ret_col_cnt); +xtWord4 myxt_load_row_data(XTOpenTablePtr ot, xtWord1 *source_buf, xtWord1 *dest_buff, u_int col_cnt); xtBool myxt_load_row(XTOpenTablePtr ot, xtWord1 *source_buf, xtWord1 *dest_buff, u_int col_cnt); xtBool myxt_find_column(XTOpenTablePtr ot, u_int *col_idx, const char *col_name); void myxt_get_column_name(XTOpenTablePtr ot, u_int col_idx, u_int len, char *col_name); @@ -93,4 +95,6 @@ public: static XTDDColumn *createFromMySQLField(XTThread *self, STRUCT_TABLE *, Field *); }; +void myxt_wait_pbxt_plugin_slot_assigned(XTThread *self); + #endif diff --git a/storage/pbxt/src/pbms.h b/storage/pbxt/src/pbms.h index 28ed7e5b4df..26753ce6581 100644 --- a/storage/pbxt/src/pbms.h +++ b/storage/pbxt/src/pbms.h @@ -344,16 +344,16 @@ public: int couldBeURL(char *blob_url, int size) { if (blob_url && (size < PBMS_BLOB_URL_SIZE)) { - char buffer[PBMS_BLOB_URL_SIZE+1]; - u_int32_t db_id = 0; - u_int32_t tab_id = 0; - u_int64_t blob_id = 0; - u_int64_t blob_ref_id = 0; - u_int64_t blob_size = 0; - u_int32_t auth_code = 0; - u_int32_t server_id = 0; - char type, junk[5]; - int scanned; + char buffer[PBMS_BLOB_URL_SIZE+1]; + unsigned long db_id = 0; + unsigned long tab_id = 0; + unsigned long long blob_id = 0; + unsigned long long blob_ref_id = 0; + unsigned long long blob_size = 0; + unsigned long auth_code = 0; + unsigned long server_id = 0; + char type, junk[5]; + int scanned; junk[0] = 0; if (blob_url[size]) { // There is no guarantee that the URL will be null terminated. @@ -364,12 +364,12 @@ public: scanned = sscanf(blob_url, URL_FMT"%4s", &db_id, &type, &tab_id, &blob_id, &auth_code, &server_id, &blob_ref_id, &blob_size, junk); if (scanned != 8) {// If junk is found at the end this will also result in an invalid URL. - printf("Bad URL \"%s\": scanned = %d, junk: %d, %d, %d, %d\n", blob_url, scanned, junk[0], junk[1], junk[2], junk[3]); + printf("Bad URL \"%s\": scanned = %d, junk: %d, %d, %d, %d\n", blob_url, scanned, junk[0], junk[1], junk[2], junk[3]); return 0; } if (junk[0] || (type != '~' && type != '_')) { - printf("Bad URL \"%s\": scanned = %d, junk: %d, %d, %d, %d\n", blob_url, scanned, junk[0], junk[1], junk[2], junk[3]); + printf("Bad URL \"%s\": scanned = %d, junk: %d, %d, %d, %d\n", blob_url, scanned, junk[0], junk[1], junk[2], junk[3]); return 0; } diff --git a/storage/pbxt/src/pbms_enabled.cc b/storage/pbxt/src/pbms_enabled.cc index 452665f5d94..cea6b231fdf 100644 --- a/storage/pbxt/src/pbms_enabled.cc +++ b/storage/pbxt/src/pbms_enabled.cc @@ -29,15 +29,10 @@ * */ -/* - The following two lines backported by psergey. Remove them when we merge from PBXT again. -*/ #include "xt_config.h" -#ifdef PBMS_ENABLED -#define PBMS_API pbms_enabled_api +#ifdef PBMS_ENABLED -#include "pbms_enabled.h" #ifdef DRIZZLED #include <sys/stat.h> #include <drizzled/common_includes.h> @@ -47,11 +42,15 @@ #include <mysql/plugin.h> #define session_alloc(sess, size) thd_alloc(sess, size); #define current_session current_thd -#endif +#endif -#define GET_BLOB_FIELD(t, i) (Field_blob *)(t->field[t->s->blob_field[i]]) -#define DB_NAME(f) (f->table->s->db.str) -#define TAB_NAME(f) (*(f->table_name)) +#define GET_BLOB_FIELD(t, i) (Field_blob *)(t->field[t->s->blob_field[i]]) +#define DB_NAME(f) (f->table->s->db.str) +#define TAB_NAME(f) (*(f->table_name)) + +#define PBMS_API pbms_enabled_api + +#include "pbms_enabled.h" static PBMS_API pbms_api; @@ -242,4 +241,4 @@ void pbms_completed(TABLE *table, bool ok) return ; } -#endif
\ No newline at end of file +#endif // PBMS_ENABLED diff --git a/storage/pbxt/src/pbms_enabled.h b/storage/pbxt/src/pbms_enabled.h index f389db1d3f3..7e62c32f34f 100644 --- a/storage/pbxt/src/pbms_enabled.h +++ b/storage/pbxt/src/pbms_enabled.h @@ -35,13 +35,6 @@ #include "pbms.h" -#ifdef DRIZZLED -#include <drizzled/server_includes.h> -#define TABLE Table -#else -#include <mysql_priv.h> -#endif - /* * pbms_initialize() should be called from the engines plugIn's 'init()' function. * The engine_name is the name of your engine, "PBXT" or "InnoDB" for example. diff --git a/storage/pbxt/src/pthread_xt.cc b/storage/pbxt/src/pthread_xt.cc index d87bbd31722..2dfb8a64af2 100755 --- a/storage/pbxt/src/pthread_xt.cc +++ b/storage/pbxt/src/pthread_xt.cc @@ -578,8 +578,8 @@ xtPublic int xt_p_mutex_unlock(xt_mutex_type *mutex) xtPublic int xt_p_mutex_destroy(xt_mutex_type *mutex) { - ASSERT_NS(mutex->mu_init == 12345); - mutex->mu_init = 89898; + //ASSERT_NS(mutex->mu_init == 12345); + mutex->mu_init = 11111; #ifdef XT_THREAD_LOCK_INFO xt_thread_lock_info_free(&mutex->mu_lock_info); #endif diff --git a/storage/pbxt/src/restart_xt.cc b/storage/pbxt/src/restart_xt.cc index 0e0e4306a2e..b34fdd76679 100644 --- a/storage/pbxt/src/restart_xt.cc +++ b/storage/pbxt/src/restart_xt.cc @@ -34,12 +34,16 @@ #include "ha_pbxt.h" +#ifdef DRIZZLED +#include <drizzled/data_home.h> +using drizzled::plugin::Registry; +#endif + #include "xactlog_xt.h" #include "database_xt.h" #include "util_xt.h" #include "strutil_xt.h" #include "filesys_xt.h" -#include "restart_xt.h" #include "myxt_xt.h" #include "trace_xt.h" @@ -57,13 +61,27 @@ //#define PRINTF xt_ftracef //#define PRINTF xt_trace -void xt_print_bytes(xtWord1 *buf, u_int len) +/* + * ----------------------------------------------------------------------- + * GLOBALS + */ + +xtPublic int pbxt_recovery_state; + +/* + * ----------------------------------------------------------------------- + * UTILITIES + */ + +#ifdef TRACE_RECORD_DATA +static void xt_print_bytes(xtWord1 *buf, u_int len) { for (u_int i=0; i<len; i++) { PRINTF("%02x ", (u_int) *buf); buf++; } } +#endif void xt_print_log_record(xtLogID log, xtLogOffset offset, XTXactLogBufferDPtr record) { @@ -252,7 +270,7 @@ void xt_print_log_record(xtLogID log, xtLogOffset offset, XTXactLogBufferDPtr re rec_type = "DELETE"; break; case XT_LOG_ENT_DELETE_FL: - rec_type = "DELETE-FL-BG"; + rec_type = "DELETE-FL"; break; case XT_LOG_ENT_UPDATE_BG: rec_type = "UPDATE-BG"; @@ -320,6 +338,11 @@ void xt_print_log_record(xtLogID log, xtLogOffset offset, XTXactLogBufferDPtr re case XT_LOG_ENT_END_OF_LOG: rec_type = "END OF LOG"; break; + case XT_LOG_ENT_PREPARE: + rec_type = "PREPARE"; + xn_id = XT_GET_DISK_4(record->xp.xp_xact_id_4); + xn_set = TRUE; + break; } if (log) @@ -327,6 +350,8 @@ void xt_print_log_record(xtLogID log, xtLogOffset offset, XTXactLogBufferDPtr re PRINTF("%s ", rec_type); if (type) PRINTF("op=%lu tab=%lu %s=%lu ", (u_long) op_no, (u_long) tab_id, type, (u_long) rec_id); + else if (tab_id) + PRINTF("tab=%lu ", (u_long) tab_id); if (row_id) PRINTF("row=%lu ", (u_long) row_id); if (log_id) @@ -459,6 +484,7 @@ static xtBool xres_open_table(XTThreadPtr self, XTWriterStatePtr ws, xtTableID t } return OK; } + ws->ws_tab_gone = tab_id; return FAILED; } @@ -629,6 +655,7 @@ static void xres_apply_change(XTThreadPtr self, XTOpenTablePtr ot, XTXactLogBuff xtWord1 *rec_data = NULL; XTTabRecFreeDPtr free_data; + ASSERT(ot->ot_thread == self); if (tab->tab_dic.dic_key_count == 0) check_index = FALSE; @@ -1300,7 +1327,7 @@ static void xres_apply_operations(XTThreadPtr self, XTWriterStatePtr ws, xtBool * These operations are applied even though operations * in sequence are missing. */ -xtBool xres_sync_operations(XTThreadPtr self, XTDatabaseHPtr db, XTWriterStatePtr ws) +static xtBool xres_sync_operations(XTThreadPtr self, XTDatabaseHPtr db, XTWriterStatePtr ws) { u_int edx; XTTableEntryPtr te_ptr; @@ -1881,15 +1908,6 @@ xtBool XTXactRestart::xres_check_checksum(XTXlogCheckpointDPtr buffer, size_t si void XTXactRestart::xres_recover_progress(XTThreadPtr self, XTOpenFilePtr *of, int perc) { #ifdef XT_USE_GLOBAL_DB - if (!perc) { - char file_path[PATH_MAX]; - - xt_strcpy(PATH_MAX, file_path, xres_db->db_main_path); - xt_add_pbxt_file(PATH_MAX, file_path, "recovery-progress"); - *of = xt_open_file(self, file_path, XT_FS_CREATE | XT_FS_MAKE_PATH); - xt_set_eof_file(self, *of, 0); - } - if (perc > 100) { char file_path[PATH_MAX]; @@ -1905,6 +1923,15 @@ void XTXactRestart::xres_recover_progress(XTThreadPtr self, XTOpenFilePtr *of, i else { char number[40]; + if (!*of) { + char file_path[PATH_MAX]; + + xt_strcpy(PATH_MAX, file_path, xres_db->db_main_path); + xt_add_pbxt_file(PATH_MAX, file_path, "recovery-progress"); + *of = xt_open_file(self, file_path, XT_FS_CREATE | XT_FS_MAKE_PATH); + xt_set_eof_file(self, *of, 0); + } + sprintf(number, "%d", perc); if (!xt_pwrite_file(*of, 0, strlen(number), number, &self->st_statistics.st_x, self)) xt_throw(self); @@ -1927,10 +1954,11 @@ xtBool XTXactRestart::xres_restart(XTThreadPtr self, xtLogID *log_id, xtLogOffse off_t bytes_to_read; volatile xtBool print_progress = FALSE; volatile off_t perc_size = 0, next_goal = 0; - int perc_complete = 1; + int perc_complete = 1, perc_to_write = 1; XTOpenFilePtr progress_file = NULL; xtBool min_ram_xn_id_set = FALSE; u_int log_count; + time_t start_time; memset(&ws, 0, sizeof(ws)); @@ -1955,12 +1983,11 @@ xtBool XTXactRestart::xres_restart(XTThreadPtr self, xtLogID *log_id, xtLogOffse /* Don't print anything about recovering an empty database: */ if (bytes_to_read != 0) xt_logf(XT_NT_INFO, "PBXT: Recovering from %lu-%llu, bytes to read: %llu\n", (u_long) xres_cp_log_id, (u_llong) xres_cp_log_offset, (u_llong) bytes_to_read); - if (bytes_to_read >= 10*1024*1024) { - print_progress = TRUE; - perc_size = bytes_to_read / 100; - next_goal = perc_size; - xres_recover_progress(self, &progress_file, 0); - } + + print_progress = FALSE; + start_time = time(NULL); + perc_size = bytes_to_read / 100; + next_goal = perc_size; if (!db->db_xlog.xlog_seq_start(&ws.ws_seqread, xres_cp_log_id, xres_cp_log_offset, FALSE)) { ok = FALSE; @@ -1983,17 +2010,28 @@ xtBool XTXactRestart::xres_restart(XTThreadPtr self, xtLogID *log_id, xtLogOffse #ifdef PRINT_LOG_ON_RECOVERY xt_print_log_record(ws.ws_seqread.xseq_rec_log_id, ws.ws_seqread.xseq_rec_log_offset, record); #endif - if (print_progress && bytes_read > next_goal) { - if (((perc_complete - 1) % 25) == 0) - xt_logf(XT_NT_INFO, "PBXT: "); - if ((perc_complete % 25) == 0) - xt_logf(XT_NT_INFO, "%2d\n", (int) perc_complete); - else - xt_logf(XT_NT_INFO, "%2d ", (int) perc_complete); - xt_log_flush(self); - xres_recover_progress(self, &progress_file, perc_complete); - next_goal += perc_size; - perc_complete++; + if (bytes_read >= next_goal) { + while (bytes_read >= next_goal) { + next_goal += perc_size; + perc_complete++; + } + if (!print_progress) { + if (time(NULL) - start_time > 2) + print_progress = TRUE; + } + if (print_progress) { + while (perc_to_write < perc_complete) { + if (((perc_to_write - 1) % 25) == 0) + xt_logf(XT_NT_INFO, "PBXT: "); + if ((perc_to_write % 25) == 0) + xt_logf(XT_NT_INFO, "%2d\n", (int) perc_to_write); + else + xt_logf(XT_NT_INFO, "%2d ", (int) perc_to_write); + xt_log_flush(self); + xres_recover_progress(self, &progress_file, perc_to_write); + perc_to_write++; + } + } } switch (record->xl.xl_status_1) { case XT_LOG_ENT_HEADER: @@ -2053,8 +2091,11 @@ xtBool XTXactRestart::xres_restart(XTThreadPtr self, xtLogID *log_id, xtLogOffse xact->xd_end_xn_id = xn_id; xact->xd_flags |= XT_XN_XAC_ENDED | XT_XN_XAC_SWEEP; xact->xd_flags &= ~XT_XN_XAC_RECOVERED; // We can expect an end record on cleanup! + xact->xd_flags &= ~XT_XN_XAC_PREPARED; // Prepared transactions cannot be swept! if (record->xl.xl_status_1 == XT_LOG_ENT_COMMIT) xact->xd_flags |= XT_XN_XAC_COMMITTED; + if (xt_sl_get_size(db->db_xn_xa_list) > 0) + xt_xn_delete_xa_data_by_xact(db, xn_id, self); } break; case XT_LOG_ENT_CLEANUP: @@ -2071,6 +2112,14 @@ xtBool XTXactRestart::xres_restart(XTThreadPtr self, xtLogID *log_id, xtLogOffse rec_log_id = XT_GET_DISK_4(record->xl.xl_log_id_4); xt_dl_set_to_delete(self, db, rec_log_id); break; + case XT_LOG_ENT_PREPARE: + xn_id = XT_GET_DISK_4(record->xp.xp_xact_id_4); + if ((xact = xt_xn_get_xact(db, xn_id, self))) { + xact->xd_flags |= XT_XN_XAC_PREPARED; + if (!xt_xn_store_xa_data(db, xn_id, record->xp.xp_xa_len_1, record->xp.xp_xa_data, self)) + xt_throw(self); + } + break; default: xt_xres_apply_in_order(self, &ws, ws.ws_seqread.xseq_rec_log_id, ws.ws_seqread.xseq_rec_log_offset, record); break; @@ -2534,7 +2583,8 @@ static void xres_cp_main(XTThreadPtr self) /* This condition means we could checkpoint: */ if (!(xt_sl_get_size(db->db_datalogs.dlc_to_delete) == 0 && xt_sl_get_size(db->db_datalogs.dlc_deleted) == 0 && - xt_comp_log_pos(log_id, log_offset, db->db_restart.xres_cp_log_id, db->db_restart.xres_cp_log_offset) <= 0)) + xt_comp_log_pos(log_id, log_offset, db->db_restart.xres_cp_log_id, db->db_restart.xres_cp_log_offset) <= 0) && + xt_sl_get_size(db->db_xn_xa_list) == 0) break; xres_cp_wait_for_log_writer(self, db, 400); @@ -2654,7 +2704,7 @@ xtPublic xtBool xt_begin_checkpoint(XTDatabaseHPtr db, xtBool have_table_lock, X * until they are flushed. */ /* This is an alternative to the above. - if (!xt_xlog_flush_log(self)) + if (!xt_xlog_flush_log(db, self)) xt_throw(self); */ xt_lock_mutex_ns(&db->db_wr_lock); @@ -2776,6 +2826,14 @@ xtPublic xtBool xt_end_checkpoint(XTDatabaseHPtr db, XTThreadPtr thread, xtBool size_t chk_size = 0; u_int no_of_logs = 0; + /* As long as we have outstanding XA transactions, we may not checkpoint! */ + if (xt_sl_get_size(db->db_xn_xa_list) > 0) { +#ifdef DEBUG + printf("Checkpoint must wait\n"); +#endif + return OK; + } + #ifdef NEVER_CHECKPOINT return OK; #endif @@ -3183,7 +3241,7 @@ xtPublic void xt_dump_xlogs(XTDatabaseHPtr db, xtLogID start_log) * D A T A B A S E R E C O V E R Y T H R E A D */ -extern XTDatabaseHPtr pbxt_database; + static XTThreadPtr xres_recovery_thread; static void *xn_xres_run_recovery_thread(XTThreadPtr self) @@ -3193,18 +3251,18 @@ static void *xn_xres_run_recovery_thread(XTThreadPtr self) if (!(mysql_thread = (THD *) myxt_create_thread())) xt_throw(self); - while (!xres_recovery_thread->t_quit && !ha_resolve_by_legacy_type(mysql_thread, DB_TYPE_PBXT)) - xt_sleep_milli_second(1); + myxt_wait_pbxt_plugin_slot_assigned(self); if (!xres_recovery_thread->t_quit) { - /* {GLOBAL-DB} - * It can happen that something will just get in before this - * thread and open/recover the database! - */ - if (!pbxt_database) { - try_(a) { + try_(a) { + /* {GLOBAL-DB} + * It can happen that something will just get in before this + * thread and open/recover the database! + */ + if (!pbxt_database) { xt_open_database(self, mysql_real_data_home, TRUE); - /* This can be done at the same time by a foreground thread, + /* {GLOBAL-DB} + * This can be done at the same time as the recovery thread, * strictly speaking I need a lock. */ if (!pbxt_database) { @@ -3212,11 +3270,22 @@ static void *xn_xres_run_recovery_thread(XTThreadPtr self) xt_heap_reference(self, pbxt_database); } } - catch_(a) { - xt_log_and_clear_exception(self); - } - cont_(a); + else + xt_use_database(self, pbxt_database, XT_FOR_USER); + + pbxt_recovery_state = XT_RECOVER_DONE; + + /* {WAIT-FOR-SW-AFTER-RECOV} + * Moved to here... + */ + xt_wait_for_sweeper(self, self->st_database, 0); + + pbxt_recovery_state = XT_RECOVER_SWEPT; } + catch_(a) { + xt_log_and_clear_exception(self); + } + cont_(a); } /* @@ -3261,11 +3330,12 @@ xtPublic void xt_xres_start_database_recovery(XTThreadPtr self) sprintf(name, "DB-RECOVERY-%s", xt_last_directory_of_path(mysql_real_data_home)); xt_remove_dir_char(name); + pbxt_recovery_state = XT_RECOVER_PENDING; xres_recovery_thread = xt_create_daemon(self, name); xt_run_thread(self, xres_recovery_thread, xn_xres_run_recovery_thread); } -xtPublic void xt_xres_wait_for_recovery(XTThreadPtr self) +xtPublic void xt_xres_terminate_recovery(XTThreadPtr self) { XTThreadPtr thr_rec; diff --git a/storage/pbxt/src/restart_xt.h b/storage/pbxt/src/restart_xt.h index bcef7191443..73128c4ded8 100644 --- a/storage/pbxt/src/restart_xt.h +++ b/storage/pbxt/src/restart_xt.h @@ -37,6 +37,8 @@ struct XTOpenTable; struct XTDatabase; struct XTTable; +extern int pbxt_recovery_state; + typedef struct XTWriterState { struct XTDatabase *ws_db; xtBool ws_in_recover; @@ -132,6 +134,16 @@ void xt_print_log_record(xtLogID log, off_t offset, XTXactLogBufferDPtr record); void xt_dump_xlogs(struct XTDatabase *db, xtLogID start_log); void xt_xres_start_database_recovery(XTThreadPtr self); -void xt_xres_wait_for_recovery(XTThreadPtr self); +void xt_xres_terminate_recovery(XTThreadPtr self); + +#define XT_RECOVER_PENDING 0 +#define XT_RECOVER_DONE 1 +#define XT_RECOVER_SWEPT 2 + +inline void xt_xres_wait_for_recovery(XTThreadPtr XT_UNUSED(self), int state) +{ + while (pbxt_recovery_state < state) + xt_sleep_milli_second(100); +} #endif diff --git a/storage/pbxt/src/strutil_xt.cc b/storage/pbxt/src/strutil_xt.cc index feab735d14c..baeb53bbc33 100644 --- a/storage/pbxt/src/strutil_xt.cc +++ b/storage/pbxt/src/strutil_xt.cc @@ -21,8 +21,10 @@ * H&G2JCtL */ -#include "mysql_priv.h" #include "xt_config.h" + +#include <stdio.h> +#include <string.h> #include <ctype.h> #include "strutil_xt.h" @@ -107,13 +109,17 @@ xtPublic void xt_2nd_last_name_of_path(size_t size, char *dest, c_char *path) *dest = 0; return; } - /* If temporary file */ - if (!is_prefix(path, mysql_data_home) && + + /* {INVALID-OLD-TABLE-FIX} + * I have changed the implementation of + * this bug fix (see {INVALID-OLD-TABLE-FIX}). + if (!is_prefix(path, mysql_data_home) && !is_prefix(path, mysql_real_data_home)) { *dest= 0; return; } + */ ptr = path + len - 1; while (ptr != path && !XT_IS_DIR_CHAR(*ptr)) @@ -374,7 +380,7 @@ xtPublic void xt_int8_to_byte_size(xtInt8 value, char *string) /* Version number must also be set in configure.in! */ xtPublic c_char *xt_get_version(void) { - return "1.0.08d RC"; + return "1.0.09f RC"; } /* Copy and URL decode! */ diff --git a/storage/pbxt/src/systab_xt.cc b/storage/pbxt/src/systab_xt.cc index 19d6c1d0ccb..783debca115 100644 --- a/storage/pbxt/src/systab_xt.cc +++ b/storage/pbxt/src/systab_xt.cc @@ -130,7 +130,7 @@ static int pbms_discover_handler(handlerton *hton, THD* thd, const char *db, con * MYSQL UTILITIES */ -void xt_my_set_notnull_in_record(Field *field, char *record) +static void xt_my_set_notnull_in_record(Field *field, char *record) { if (field->null_ptr) record[(uint) (field->null_ptr - (uchar *) field->table->record[0])] &= (uchar) ~field->null_bit; @@ -518,7 +518,7 @@ bool XTStatisticsTable::seqScanRead(xtWord4 rec_id, char *buf) * SYSTEM TABLE SHARES */ -void st_path_to_table_name(size_t size, char *buffer, const char *path) +static void st_path_to_table_name(size_t size, char *buffer, const char *path) { char *str; diff --git a/storage/pbxt/src/tabcache_xt.cc b/storage/pbxt/src/tabcache_xt.cc index 7e8cc9e1f6e..9897525ad69 100644 --- a/storage/pbxt/src/tabcache_xt.cc +++ b/storage/pbxt/src/tabcache_xt.cc @@ -590,7 +590,7 @@ xtBool XTTabCache::tc_fetch(XT_ROW_REC_FILE_PTR file, xtRefID ref_id, XTTabCache * So there could be a deadlock if I don't flush the log! */ if ((self = xt_get_self())) { - if (!xt_xlog_flush_log(self)) + if (!xt_xlog_flush_log(tci_table->tab_db, self)) goto failed; } @@ -1150,6 +1150,8 @@ static void *tabc_fr_run_thread(XTThreadPtr self) int count; void *mysql_thread; + myxt_wait_pbxt_plugin_slot_assigned(self); + mysql_thread = myxt_create_thread(); while (!self->t_quit) { diff --git a/storage/pbxt/src/tabcache_xt.h b/storage/pbxt/src/tabcache_xt.h index 46973037b49..fae8ad9be66 100644 --- a/storage/pbxt/src/tabcache_xt.h +++ b/storage/pbxt/src/tabcache_xt.h @@ -168,7 +168,7 @@ typedef struct XTTableSeq { #define TAB_CAC_UNLOCK(i, o) xt_xsmutex_unlock(i, o) #elif defined(TAB_CAC_USE_PTHREAD_RW) #define TAB_CAC_LOCK_TYPE xt_rwlock_type -#define TAB_CAC_INIT_LOCK(s, i) xt_init_rwlock(s, i) +#define TAB_CAC_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, i) #define TAB_CAC_FREE_LOCK(s, i) xt_free_rwlock(i) #define TAB_CAC_READ_LOCK(i, o) xt_slock_rwlock_ns(i) #define TAB_CAC_WRITE_LOCK(i, o) xt_xlock_rwlock_ns(i) diff --git a/storage/pbxt/src/table_xt.cc b/storage/pbxt/src/table_xt.cc index 2671f02c057..55cc695e7c2 100644 --- a/storage/pbxt/src/table_xt.cc +++ b/storage/pbxt/src/table_xt.cc @@ -35,7 +35,6 @@ #include <drizzled/common.h> #include <mysys/thr_lock.h> #include <drizzled/dtcollation.h> -#include <drizzled/plugin/storage_engine.h> #else #include "mysql_priv.h" #endif @@ -48,7 +47,6 @@ #include "cache_xt.h" #include "trace_xt.h" #include "index_xt.h" -#include "restart_xt.h" #include "systab_xt.h" #ifdef DEBUG @@ -2347,7 +2345,7 @@ xtPublic void xt_flush_table(XTThreadPtr self, XTOpenTablePtr ot) } -xtPublic XTOpenTablePtr tab_open_table(XTTableHPtr tab) +static XTOpenTablePtr tab_open_table(XTTableHPtr tab) { volatile XTOpenTablePtr ot; XTThreadPtr self; @@ -2588,7 +2586,7 @@ xtPublic xtBool xt_tab_put_log_op_rec_data(XTOpenTablePtr ot, u_int status, xtRe return FAILED; } - return xt_xlog_modify_table(ot, status, op_seq, free_rec_id, rec_id, size, buffer); + return xt_xlog_modify_table(tab->tab_id, status, op_seq, free_rec_id, rec_id, size, buffer, ot->ot_thread); } xtPublic xtBool xt_tab_put_log_rec_data(XTOpenTablePtr ot, u_int status, xtRecordID free_rec_id, xtRecordID rec_id, size_t size, xtWord1 *buffer, xtOpSeqNo *op_seq) @@ -2606,7 +2604,7 @@ xtPublic xtBool xt_tab_put_log_rec_data(XTOpenTablePtr ot, u_int status, xtRecor return FAILED; } - return xt_xlog_modify_table(ot, status, *op_seq, free_rec_id, rec_id, size, buffer); + return xt_xlog_modify_table(tab->tab_id, status, *op_seq, free_rec_id, rec_id, size, buffer, ot->ot_thread); } xtPublic xtBool xt_tab_get_rec_data(XTOpenTablePtr ot, xtRecordID rec_id, size_t size, xtWord1 *buffer) @@ -3541,7 +3539,7 @@ xtPublic xtBool xt_tab_free_row(XTOpenTablePtr ot, XTTableHPtr tab, xtRowID row_ tab->tab_row_fnum++; xt_unlock_mutex_ns(&tab->tab_row_lock); - if (!xt_xlog_modify_table(ot, XT_LOG_ENT_ROW_FREED, op_seq, 0, row_id, sizeof(XTTabRowRefDRec), (xtWord1 *) &free_row)) + if (!xt_xlog_modify_table(tab->tab_id, XT_LOG_ENT_ROW_FREED, op_seq, 0, row_id, sizeof(XTTabRowRefDRec), (xtWord1 *) &free_row, ot->ot_thread)) return FAILED; return OK; @@ -3791,7 +3789,7 @@ xtPublic int xt_tab_remove_record(XTOpenTablePtr ot, xtRecordID rec_id, xtWord1 xt_unlock_mutex_ns(&tab->tab_rec_lock); free_rec->rf_rec_type_1 = old_rec_type; - return xt_xlog_modify_table(ot, XT_LOG_ENT_REC_REMOVED_BI, op_seq, (xtRecordID) new_rec_type, rec_id, rec_size, ot->ot_row_rbuffer); + return xt_xlog_modify_table(tab->tab_id, XT_LOG_ENT_REC_REMOVED_BI, op_seq, (xtRecordID) new_rec_type, rec_id, rec_size, ot->ot_row_rbuffer, ot->ot_thread); } static xtRowID tab_new_row(XTOpenTablePtr ot, XTTableHPtr tab) @@ -3837,7 +3835,7 @@ static xtRowID tab_new_row(XTOpenTablePtr ot, XTTableHPtr tab) op_seq = tab->tab_seq.ts_get_op_seq(); xt_unlock_mutex_ns(&tab->tab_row_lock); - if (!xt_xlog_modify_table(ot, status, op_seq, next_row_id, row_id, 0, NULL)) + if (!xt_xlog_modify_table(tab->tab_id, status, op_seq, next_row_id, row_id, 0, NULL, ot->ot_thread)) return 0; XT_DISABLED_TRACE(("new row tx=%d row=%d\n", (int) ot->ot_thread->st_xact_data->xd_start_xn_id, (int) row_id)); @@ -3868,7 +3866,7 @@ xtPublic xtBool xt_tab_set_row(XTOpenTablePtr ot, u_int status, xtRowID row_id, if (!tab->tab_rows.xt_tc_write(ot->ot_row_file, row_id, 0, sizeof(XTTabRowRefDRec), (xtWord1 *) &row_buf, &op_seq, TRUE, ot->ot_thread)) return FAILED; - return xt_xlog_modify_table(ot, status, op_seq, 0, row_id, sizeof(XTTabRowRefDRec), (xtWord1 *) &row_buf); + return xt_xlog_modify_table(tab->tab_id, status, op_seq, 0, row_id, sizeof(XTTabRowRefDRec), (xtWord1 *) &row_buf, ot->ot_thread); } xtPublic xtBool xt_tab_free_record(XTOpenTablePtr ot, u_int status, xtRecordID rec_id, xtBool clean_delete) @@ -3937,7 +3935,7 @@ xtPublic xtBool xt_tab_free_record(XTOpenTablePtr ot, u_int status, xtRecordID r tab->tab_rec_fnum++; xt_unlock_mutex_ns(&tab->tab_rec_lock); - if (!xt_xlog_modify_table(ot, status, op_seq, rec_id, rec_id, sizeof(XTactFreeRecEntryDRec) - offsetof(XTactFreeRecEntryDRec, fr_stat_id_1), &free_rec.fr_stat_id_1)) + if (!xt_xlog_modify_table(tab->tab_id, status, op_seq, rec_id, rec_id, sizeof(XTactFreeRecEntryDRec) - offsetof(XTactFreeRecEntryDRec, fr_stat_id_1), &free_rec.fr_stat_id_1, ot->ot_thread)) return FAILED; } return OK; @@ -4016,7 +4014,7 @@ static xtBool tab_add_record(XTOpenTablePtr ot, XTTabRecInfoPtr rec_info, u_int } xt_unlock_mutex_ns(&tab->tab_rec_lock); - if (!xt_xlog_modify_table(ot, status, op_seq, next_rec_id, rec_id, rec_info->ri_rec_buf_size, (xtWord1 *) rec_info->ri_fix_rec_buf)) + if (!xt_xlog_modify_table(tab->tab_id, status, op_seq, next_rec_id, rec_id, rec_info->ri_rec_buf_size, (xtWord1 *) rec_info->ri_fix_rec_buf, ot->ot_thread)) return FAILED; if (rec_info->ri_ext_rec) { @@ -4932,6 +4930,12 @@ xtPublic void xt_tab_seq_exit(XTOpenTablePtr ot) #endif #endif +xtPublic void xt_tab_seq_repeat(XTOpenTablePtr ot) +{ + ot->ot_seq_rec_id--; + ot->ot_seq_offset -= ot->ot_table->tab_dic.dic_rec_size; +} + xtPublic xtBool xt_tab_seq_next(XTOpenTablePtr ot, xtWord1 *buffer, xtBool *eof) { register XTTableHPtr tab = ot->ot_table; @@ -5094,7 +5098,7 @@ static xtBool tab_exec_repair_pending(XTDatabaseHPtr db, int what, char *table_n return FALSE; } else { - if (!xt_open_file_ns(&of, file_path, XT_FS_DEFAULT)) + if (!xt_open_file_ns(&of, file_path, XT_FS_DEFAULT | XT_FS_MISSING_OK)) return FALSE; } if (!of) @@ -5190,15 +5194,76 @@ static xtBool tab_exec_repair_pending(XTDatabaseHPtr db, int what, char *table_n return FALSE; } -xtPublic void tab_make_table_name(XTTableHPtr tab, char *table_name, size_t size) +static void tab_make_table_name(XTTableHPtr tab, char *table_name, size_t size) { - char name_buf[XT_IDENTIFIER_NAME_SIZE*3+3]; + char *nptr; + + nptr = xt_last_name_of_path(tab->tab_name->ps_path); + if (xt_starts_with(nptr, "#sql")) { + /* {INVALID-OLD-TABLE-FIX} + * Temporary files can have strange paths, for example + * ..../var/tmp/mysqld.1/#sqldaec_1_6 + * This occurs, for example, occurs when the temp_table.test is + * run using the PBXT suite in MariaDB: + * ./mtr --suite=pbxt --do-test=temp_table + * + * Calling myxt_static_convert_file_name, with a '.', in the name + * causes the error: + * [ERROR] Invalid (old?) table or database name 'mysqld.1' + * To prevent this, we do not convert the temporary + * table names using the mysql functions. + * + * Note, this bug was found by Monty, and fixed by modifying + * xt_2nd_last_name_of_path(), see {INVALID-OLD-TABLE-FIX}. + * + */ + xt_2nd_last_name_of_path(size, table_name, tab->tab_name->ps_path); + xt_strcat(size, table_name, "."); + xt_strcat(size, table_name, nptr); + } + else { + char name_buf[XT_TABLE_NAME_SIZE*3+3]; + char *part_ptr; + size_t len; + + xt_2nd_last_name_of_path(sizeof(name_buf), name_buf, tab->tab_name->ps_path); + myxt_static_convert_file_name(name_buf, table_name, size); + xt_strcat(size, table_name, "."); + + /* Handle partition extensions to table names: */ + if ((part_ptr = strstr(nptr, "#P#"))) + xt_strncpy(sizeof(name_buf), name_buf, nptr, part_ptr - nptr); + else + xt_strcpy(sizeof(name_buf), name_buf, nptr); + + len = strlen(table_name); + myxt_static_convert_file_name(name_buf, table_name + len, size - len); + + if (part_ptr) { + /* Add the partition extension (which is relevant to the engine). */ + char *sub_part_ptr; - xt_2nd_last_name_of_path(sizeof(name_buf), name_buf, tab->tab_name->ps_path); - myxt_static_convert_file_name(name_buf, table_name, size); - xt_strcat(size, table_name, "."); - myxt_static_convert_file_name(xt_last_name_of_path(tab->tab_name->ps_path), name_buf, sizeof(name_buf)); - xt_strcat(size, table_name, name_buf); + part_ptr += 3; + if ((sub_part_ptr = strstr(part_ptr, "#SP#"))) + xt_strncpy(sizeof(name_buf), name_buf, part_ptr, sub_part_ptr - part_ptr); + else + xt_strcpy(sizeof(name_buf), name_buf, part_ptr); + + xt_strcat(size, table_name, " ("); + len = strlen(table_name); + myxt_static_convert_file_name(name_buf, table_name + len, size - len); + + if (sub_part_ptr) { + + sub_part_ptr += 4; + xt_strcat(size, table_name, " - "); + len = strlen(table_name); + myxt_static_convert_file_name(sub_part_ptr, table_name + len, size - len); + } + + xt_strcat(size, table_name, ")"); + } + } } xtPublic xtBool xt_tab_is_table_repair_pending(XTTableHPtr tab) diff --git a/storage/pbxt/src/table_xt.h b/storage/pbxt/src/table_xt.h index 8378534ce77..f7d7e1c6526 100644 --- a/storage/pbxt/src/table_xt.h +++ b/storage/pbxt/src/table_xt.h @@ -127,7 +127,7 @@ struct XTTablePath; #define XT_TAB_ROW_UNLOCK(i, s) xt_xsmutex_unlock(i, (s)->t_id) #elif defined(XT_TAB_ROW_USE_PTHREAD_RW) #define XT_TAB_ROW_LOCK_TYPE xt_rwlock_type -#define XT_TAB_ROW_INIT_LOCK(s, i) xt_init_rwlock(s, i) +#define XT_TAB_ROW_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, i) #define XT_TAB_ROW_FREE_LOCK(s, i) xt_free_rwlock(i) #define XT_TAB_ROW_READ_LOCK(i, s) xt_slock_rwlock_ns(i) #define XT_TAB_ROW_WRITE_LOCK(i, s) xt_xlock_rwlock_ns(i) @@ -528,13 +528,14 @@ xtBool xt_table_exists(struct XTDatabase *db); void xt_enum_tables_init(u_int *edx); XTTableEntryPtr xt_enum_tables_next(struct XTThread *self, struct XTDatabase *db, u_int *edx); -void xt_enum_files_of_tables_init(struct XTDatabase *db, char *tab_name, xtTableID tab_id, XTFilesOfTablePtr ft); +void xt_enum_files_of_tables_init(XTPathStrPtr tab_name, xtTableID tab_id, XTFilesOfTablePtr ft); xtBool xt_enum_files_of_tables_next(XTFilesOfTablePtr ft); xtBool xt_tab_seq_init(XTOpenTablePtr ot); void xt_tab_seq_reset(XTOpenTablePtr ot); void xt_tab_seq_exit(XTOpenTablePtr ot); xtBool xt_tab_seq_next(XTOpenTablePtr ot, xtWord1 *buffer, xtBool *eof); +void xt_tab_seq_repeat(XTOpenTablePtr ot); xtBool xt_tab_new_record(XTOpenTablePtr ot, xtWord1 *buffer); xtBool xt_tab_delete_record(XTOpenTablePtr ot, xtWord1 *buffer); diff --git a/storage/pbxt/src/thread_xt.cc b/storage/pbxt/src/thread_xt.cc index 150ac7a3789..524c5bc5ac3 100644 --- a/storage/pbxt/src/thread_xt.cc +++ b/storage/pbxt/src/thread_xt.cc @@ -75,6 +75,13 @@ static xt_mutex_type thr_array_lock; /* Global accumulated statistics: */ static XTStatisticsRec thr_statistics; +#ifdef DEBUG +static void break_in_assertion(c_char *expr, c_char *func, c_char *file, u_int line) +{ + printf("%s(%s:%d) %s\n", func, file, (int) line, expr); +} +#endif + /* * ----------------------------------------------------------------------- * Error logging @@ -658,6 +665,9 @@ static c_char *thr_get_err_string(int xt_err) case XT_ERR_FK_REF_TEMP_TABLE: str = "Foreign key may not reference temporary table"; break; case XT_ERR_MYSQL_SHUTDOWN: str = "Cannot open table, MySQL has shutdown"; break; case XT_ERR_MYSQL_NO_THREAD: str = "Cannot create thread, MySQL has shutdown"; break; + case XT_ERR_BUFFER_TOO_SMALL: str = "System backup buffer too small"; break; + case XT_ERR_BAD_BACKUP_FORMAT: str = "Unknown or corrupt backup format, restore aborted"; break; + case XT_ERR_PBXT_NOT_INSTALLED: str = "PBXT plugin is not installed"; break; default: str = "Unknown XT error"; break; } return str; @@ -862,6 +872,11 @@ xtPublic xtBool xt_exception_errno(XTExceptionPtr e, XTThreadPtr self, c_char *f return FAILED; } +xtPublic void xt_exception_xterr(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err) +{ + xt_exception_error(e, self, func, file, line, xt_err, 0, thr_get_err_string(xt_err)); +} + /* * ----------------------------------------------------------------------- * LOG ERRORS @@ -887,7 +902,7 @@ xtPublic xtBool xt_assert(XTThreadPtr self, c_char *expr, c_char *func, c_char * #ifdef DEBUG //xt_set_fflush(TRUE); //xt_dump_trace(); - printf("%s(%s:%d) %s\n", func, file, (int) line, expr); + break_in_assertion(expr, func, file, line); #ifdef CRASH_ON_ASSERT abort(); #endif diff --git a/storage/pbxt/src/thread_xt.h b/storage/pbxt/src/thread_xt.h index 69f828758a1..001f4adc33f 100644 --- a/storage/pbxt/src/thread_xt.h +++ b/storage/pbxt/src/thread_xt.h @@ -536,6 +536,8 @@ extern struct XTThread **xt_thr_array; * Function prototypes */ +extern "C" void *thr_main(void *data); + void xt_get_now(char *buffer, size_t len); xtBool xt_init_logging(void); void xt_exit_logging(void); @@ -583,6 +585,7 @@ void xt_register_xterr(c_char *func, c_char *file, u_int line, int xt_err); void xt_exceptionf(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, int sys_err, c_char *fmt, ...); void xt_exception_error(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, int sys_err, c_char *msg); xtBool xt_exception_errno(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int err); +void xt_exception_xterr(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err); void xt_log_errno(XTThreadPtr self, c_char *func, c_char *file, u_int line, int err); @@ -610,7 +613,7 @@ void xt_critical_wait(void); void xt_yield(void); void xt_sleep_milli_second(u_int t); xtBool xt_suspend(XTThreadPtr self); -xtBool xt_unsuspend(XTThreadPtr self, XTThreadPtr target); +xtBool xt_unsuspend(XTThreadPtr target); void xt_lock_thread(XTThreadPtr thread); void xt_unlock_thread(XTThreadPtr thread); xtBool xt_wait_thread(XTThreadPtr thread); diff --git a/storage/pbxt/src/util_xt.cc b/storage/pbxt/src/util_xt.cc index 7e805e6e044..192c990c48b 100644 --- a/storage/pbxt/src/util_xt.cc +++ b/storage/pbxt/src/util_xt.cc @@ -150,6 +150,23 @@ xtPublic xtWord1 xt_get_checksum1(xtWord1 *data, size_t len) return (xtWord1) (sum ^ (sum >> 24) ^ (sum >> 16) ^ (sum >> 8)); } +xtPublic xtWord4 xt_get_checksum4(xtWord1 *data, size_t len) +{ + register xtWord4 sum = 0, g; + xtWord1 *chk; + + chk = data + len - 1; + while (chk > data) { + sum = (sum << 4) + *chk; + if ((g = sum & 0xF0000000)) { + sum = sum ^ (g >> 24); + sum = sum ^ g; + } + chk--; + } + return sum; +} + /* * --------------- Data Buffer ------------------ */ diff --git a/storage/pbxt/src/util_xt.h b/storage/pbxt/src/util_xt.h index bb5003b10fb..28d47544ef9 100644 --- a/storage/pbxt/src/util_xt.h +++ b/storage/pbxt/src/util_xt.h @@ -39,6 +39,7 @@ xtWord4 xt_file_name_to_id(char *file_name); xtBool xt_time_difference(register xtWord4 now, register xtWord4 then); xtWord2 xt_get_checksum(xtWord1 *data, size_t len, u_int interval); xtWord1 xt_get_checksum1(xtWord1 *data, size_t len); +xtWord4 xt_get_checksum4(xtWord1 *data, size_t len); typedef struct XTDataBuffer { size_t db_size; diff --git a/storage/pbxt/src/xaction_xt.cc b/storage/pbxt/src/xaction_xt.cc index 82039ace2b3..86be55a6bcf 100644 --- a/storage/pbxt/src/xaction_xt.cc +++ b/storage/pbxt/src/xaction_xt.cc @@ -1075,6 +1075,7 @@ xtPublic void xt_xn_init_db(XTThreadPtr self, XTDatabaseHPtr db) #endif xt_spinlock_init_with_autoname(self, &db->db_xn_id_lock); xt_spinlock_init_with_autoname(self, &db->db_xn_wait_spinlock); + xt_init_mutex_with_autoname(self, &db->db_xn_xa_lock); //xt_init_mutex_with_autoname(self, &db->db_xn_wait_lock); //xt_init_cond(self, &db->db_xn_wait_cond); xt_init_mutex_with_autoname(self, &db->db_sw_lock); @@ -1096,6 +1097,9 @@ xtPublic void xt_xn_init_db(XTThreadPtr self, XTDatabaseHPtr db) } } + /* Create a sorted list for XA transactions recovered: */ + db->db_xn_xa_list = xt_new_sortedlist(self, sizeof(XTXactXARec), 100, 50, xt_xn_xa_compare, db, NULL, FALSE, FALSE); + /* Initialize the data logs: */ db->db_datalogs.dlc_init(self, db); @@ -1146,6 +1150,7 @@ xtPublic void xt_xn_exit_db(XTThreadPtr self, XTDatabaseHPtr db) printf("=========> MAX TXs NOT CLEAN: %lu\n", not_clean_max); printf("=========> MAX TXs IN RAM: %lu\n", in_ram_max); #endif + XTXactPreparePtr xap, xap_next; xt_stop_sweeper(self, db); // Should be done already! xt_stop_writer(self, db); // Should be done already! @@ -1187,6 +1192,19 @@ xtPublic void xt_xn_exit_db(XTThreadPtr self, XTDatabaseHPtr db) xt_free_mutex(&db->db_sw_lock); //xt_free_cond(&db->db_xn_wait_cond); //xt_free_mutex(&db->db_xn_wait_lock); + xt_free_mutex(&db->db_xn_xa_lock); + for (u_int i=0; i<XT_XA_HASH_TAB_SIZE; i++) { + xap = db->db_xn_xa_table[i]; + while (xap) { + xap_next = xap->xp_next; + xt_free(self, xap); + xap = xap_next; + } + } + if (db->db_xn_xa_list) { + xt_free_sortedlist(self, db->db_xn_xa_list); + db->db_xn_xa_list = NULL; + } xt_spinlock_free(self, &db->db_xn_wait_spinlock); xt_spinlock_free(self, &db->db_xn_id_lock); #ifdef DEBUG_RAM_LIST @@ -1428,7 +1446,7 @@ static xtBool xn_end_xact(XTThreadPtr thread, u_int status) wait_xn_id = thread->st_prev_xact[thread->st_last_xact]; thread->st_prev_xact[thread->st_last_xact] = xn_id; /* This works because XT_MAX_XACT_BEHIND == 2! */ - ASSERT_NS((thread->st_last_xact + 1) % XT_MAX_XACT_BEHIND == thread->st_last_xact ^ 1); + ASSERT_NS((thread->st_last_xact + 1) % XT_MAX_XACT_BEHIND == (thread->st_last_xact ^ 1)); thread->st_last_xact ^= 1; while (xt_xn_is_before(db->db_xn_to_clean_id, wait_xn_id) && (db->db_sw_faster & XT_SW_TOO_FAR_BEHIND)) { xt_critical_wait(); @@ -1548,6 +1566,149 @@ xtPublic int xt_xn_status(XTOpenTablePtr ot, xtXactID xn_id, xtRecordID XT_UNUSE return XT_XN_ABORTED; } +/* ---------------------------------------------------------------------- + * XA Functionality + */ + +xtPublic int xt_xn_xa_compare(XTThreadPtr XT_UNUSED(self), register const void *XT_UNUSED(thunk), register const void *a, register const void *b) +{ + xtXactID *x = (xtXactID *) a; + XTXactXAPtr y = (XTXactXAPtr) b; + + if (*x == y->xx_xact_id) + return 0; + if (xt_xn_is_before(*x, y->xx_xact_id)) + return -1; + return 1; +} + +xtPublic xtBool xt_xn_prepare(int len, xtWord1 *xa_data, XTThreadPtr thread) +{ + XTXactDataPtr xact; + + ASSERT_NS(thread->st_xact_data); + if ((xact = thread->st_xact_data)) { + xtXactID xn_id = xact->xd_start_xn_id; + + /* Only makes sense if the transaction has already been logged: */ + if ((thread->st_xact_data->xd_flags & XT_XN_XAC_LOGGED)) { + if (!xt_xlog_modify_table(0, XT_LOG_ENT_PREPARE, xn_id, 0, 0, len, xa_data, thread)) + return FAILED; + } + } + return OK; +} + +xtPublic xtBool xt_xn_store_xa_data(XTDatabaseHPtr db, xtXactID xact_id, int len, xtWord1 *xa_data, XTThreadPtr XT_UNUSED(thread)) +{ + XTXactPreparePtr xap; + u_int idx; + XTXactXARec xx; + + if (!(xap = (XTXactPreparePtr) xt_malloc_ns(offsetof(XTXactPrepareRec, xp_xa_data) + len))) + return FAILED; + xap->xp_xact_id = xact_id; + xap->xp_hash = xt_get_checksum4(xa_data, len); + xap->xp_data_len = len; + memcpy(xap->xp_xa_data, xa_data, len); + xx.xx_xact_id = xact_id; + xx.xx_xa_ptr = xap; + + idx = xap->xp_hash % XT_XA_HASH_TAB_SIZE; + xt_lock_mutex_ns(&db->db_xn_xa_lock); + if (!xt_sl_insert(NULL, db->db_xn_xa_list, &xact_id, &xx)) { + xt_unlock_mutex_ns(&db->db_xn_xa_lock); + xt_free_ns(xap); + } + xap->xp_next = db->db_xn_xa_table[idx]; + db->db_xn_xa_table[idx] = xap; + xt_unlock_mutex_ns(&db->db_xn_xa_lock); + return OK; +} + +xtPublic void xt_xn_delete_xa_data_by_xact(XTDatabaseHPtr db, xtXactID xact_id, XTThreadPtr thread) +{ + XTXactXAPtr xx; + + xt_lock_mutex_ns(&db->db_xn_xa_lock); + if (!(xx = (XTXactXAPtr) xt_sl_find(NULL, db->db_xn_xa_list, &xact_id))) + return; + xt_xn_delete_xa_data(db, xx->xx_xa_ptr, TRUE, thread); +} + +xtPublic void xt_xn_delete_xa_data(XTDatabaseHPtr db, XTXactPreparePtr xap, xtBool unlock, XTThreadPtr XT_UNUSED(thread)) +{ + u_int idx; + XTXactPreparePtr xap_ptr, xap_pptr = NULL; + + xt_sl_delete(NULL, db->db_xn_xa_list, &xap->xp_xact_id); + idx = xap->xp_hash % XT_XA_HASH_TAB_SIZE; + xap_ptr = db->db_xn_xa_table[idx]; + while (xap_ptr) { + if (xap_ptr == xap) + break; + xap_pptr = xap_ptr; + xap_ptr = xap_ptr->xp_next; + } + if (xap_ptr) { + if (xap_pptr) + xap_pptr->xp_next = xap_ptr->xp_next; + else + db->db_xn_xa_table[idx] = xap_ptr->xp_next; + xt_free_ns(xap); + } + if (unlock) + xt_unlock_mutex_ns(&db->db_xn_xa_lock); +} + +xtPublic XTXactPreparePtr xt_xn_find_xa_data(XTDatabaseHPtr db, int len, xtWord1 *xa_data, xtBool lock, XTThreadPtr XT_UNUSED(thread)) +{ + xtWord4 hash; + XTXactPreparePtr xap; + u_int idx; + + if (lock) + xt_lock_mutex_ns(&db->db_xn_xa_lock); + hash = xt_get_checksum4(xa_data, len); + idx = hash % XT_XA_HASH_TAB_SIZE; + xap = db->db_xn_xa_table[idx]; + while (xap) { + if (xap->xp_hash == hash && + xap->xp_data_len == len && + memcmp(xap->xp_xa_data, xa_data, len) == 0) { + break; + } + xap = xap->xp_next; + } + + return xap; +} + +xtPublic XTXactPreparePtr xt_xn_enum_xa_data(XTDatabaseHPtr db, XTXactEnumXAPtr exa) +{ + XTXactXAPtr xx; + + if (!exa->exa_locked) { + xt_lock_mutex_ns(&db->db_xn_xa_lock); + exa->exa_locked = TRUE; + } + + if ((xx = (XTXactXAPtr) xt_sl_item_at(db->db_xn_xa_list, exa->exa_index))) { + exa->exa_index++; + return xx->xx_xa_ptr; + } + + if (exa->exa_locked) { + exa->exa_locked = FALSE; + xt_unlock_mutex_ns(&db->db_xn_xa_lock); + } + return NULL; +} + +/* ---------------------------------------------------------------------- + * S W E E P E R F U N C T I O N S + */ + xtPublic xtWord8 xt_xn_bytes_to_sweep(XTDatabaseHPtr db, XTThreadPtr thread) { xtXactID xn_id; @@ -2047,7 +2208,7 @@ static xtBool xn_sw_cleanup_variation(XTThreadPtr self, XNSweeperStatePtr ss, XT if(!tab->tab_recs.xt_tc_write_cond(self, ot->ot_rec_file, rec_id, rec_head.tr_rec_type_1, &op_seq, xn_id, row_id, stat_id, rec_type)) /* this means record was not updated by xt_tc_write_bor and doesn't need to */ break; - if (!xt_xlog_modify_table(ot, XT_LOG_ENT_REC_CLEANED_1, op_seq, 0, rec_id, 1, &rec_head.tr_rec_type_1)) + if (!xt_xlog_modify_table(tab->tab_id, XT_LOG_ENT_REC_CLEANED_1, op_seq, 0, rec_id, 1, &rec_head.tr_rec_type_1, self)) throw_(); xn_sw_clean_indices(self, ot, rec_id, row_id, rec_buf, ss->ss_databuf.db_data); break; @@ -2397,8 +2558,10 @@ static void xn_sw_main(XTThreadPtr self) if ((xact = xt_xn_get_xact(db, db->db_xn_to_clean_id, self))) { xtXactID xn_id; - if (!(xact->xd_flags & XT_XN_XAC_SWEEP)) - /* Transaction has not yet ending, and ready to sweep. */ + /* The sweep flag is set when the transaction is ready for sweeping. + * Prepared transactions may not be swept! + */ + if (!(xact->xd_flags & XT_XN_XAC_SWEEP) || (xact->xd_flags & XT_XN_XAC_PREPARED)) goto sleep; /* Check if we can cleanup the transaction. @@ -2493,7 +2656,7 @@ static void xn_sw_main(XTThreadPtr self) * we flush the log. */ if (now >= idle_start + 2) { - if (!xt_xlog_flush_log(self)) + if (!xt_xlog_flush_log(db, self)) xt_throw(self); ss->ss_flush_pending = FALSE; } @@ -2516,7 +2679,7 @@ static void xn_sw_main(XTThreadPtr self) } if (ss->ss_flush_pending) { - xt_xlog_flush_log(self); + xt_xlog_flush_log(db, self); ss->ss_flush_pending = FALSE; } diff --git a/storage/pbxt/src/xaction_xt.h b/storage/pbxt/src/xaction_xt.h index 7bcc46dfcf3..ac742088ebb 100644 --- a/storage/pbxt/src/xaction_xt.h +++ b/storage/pbxt/src/xaction_xt.h @@ -87,6 +87,7 @@ struct XTOpenTable; #define XT_XN_XAC_CLEANED 8 /* The transaction has been cleaned. */ #define XT_XN_XAC_RECOVERED 16 /* This transaction was detected on recovery. */ #define XT_XN_XAC_SWEEP 32 /* End ID has been set, OK to sweep. */ +#define XT_XN_XAC_PREPARED 64 /* The transaction was prepared (used only by recovery). */ #define XT_XN_VISIBLE 0 /* The transaction is committed, and the record is visible. */ #define XT_XN_NOT_VISIBLE 1 /* The transaction is committed, but not visible. */ @@ -95,6 +96,24 @@ struct XTOpenTable; #define XT_XN_OTHER_UPDATE 4 /* The record was updated by someone else. */ #define XT_XN_REREAD 5 /* The transaction is not longer in RAM, status is unkown, retry. */ +typedef struct XTXactPrepare { + xtXactID xp_xact_id; + xtWord4 xp_hash; + struct XTXactPrepare *xp_next; /* Next item in hash table. */ + int xp_data_len; + xtWord1 xp_xa_data[XT_MAX_XA_DATA_SIZE]; +} XTXactPrepareRec, *XTXactPreparePtr; + +typedef struct XTXactXA { + xtXactID xx_xact_id; + XTXactPreparePtr xx_xa_ptr; +} XTXactXARec, *XTXactXAPtr; + +typedef struct XTXactEnumXA { + u_int exa_index; + xtBool exa_locked; +} XTXactEnumXARec, *XTXactEnumXAPtr; + typedef struct XTXactData { xtXactID xd_start_xn_id; /* Note: may be zero!. */ xtXactID xd_end_xn_id; /* Note: may be zero!. */ @@ -105,6 +124,7 @@ typedef struct XTXactData { int xd_flags; xtWord4 xd_end_time; xtThreadID xd_thread_id; + xtWord4 xd_xa_hash; /* 0 if no XA transaction. */ /* A transaction may be indexed twice in the hash table. * Once on the start sequence number, and once on the @@ -123,7 +143,7 @@ typedef struct XTXactData { #if defined(XT_XACT_USE_PTHREAD_RW) #define XT_XACT_LOCK_TYPE xt_rwlock_type -#define XT_XACT_INIT_LOCK(s, i) xt_init_rwlock(s, i) +#define XT_XACT_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, i) #define XT_XACT_FREE_LOCK(s, i) xt_free_rwlock(i) #define XT_XACT_READ_LOCK(i, s) xt_slock_rwlock_ns(i) #define XT_XACT_WRITE_LOCK(i, s) xt_xlock_rwlock_ns(i) @@ -183,6 +203,14 @@ void xt_xn_wakeup_thread(xtThreadID thd_id); xtXactID xt_xn_get_curr_id(struct XTDatabase *db); xtWord8 xt_xn_bytes_to_sweep(struct XTDatabase *db, struct XTThread *thread); +int xt_xn_xa_compare(struct XTThread *self, register const void *thunk, register const void *a, register const void *b); +xtBool xt_xn_prepare(int len, xtWord1 *xa_data, struct XTThread *thread); +xtBool xt_xn_store_xa_data(struct XTDatabase *db, xtXactID xn_id, int len, xtWord1 *xa_data, struct XTThread *thread); +void xt_xn_delete_xa_data_by_xact(struct XTDatabase *db, xtXactID xact_id, struct XTThread *thread); +void xt_xn_delete_xa_data(struct XTDatabase *db, XTXactPreparePtr xap, xtBool unlock, struct XTThread *thread); +XTXactPreparePtr xt_xn_find_xa_data(struct XTDatabase *db, int len, xtWord1 *xa_data, xtBool lock, struct XTThread *thread); +XTXactPreparePtr xt_xn_enum_xa_data(struct XTDatabase *db, XTXactEnumXAPtr exa); + XTXactDataPtr xt_xn_add_old_xact(struct XTDatabase *db, xtXactID xn_id, struct XTThread *thread); XTXactDataPtr xt_xn_get_xact(struct XTDatabase *db, xtXactID xn_id, struct XTThread *thread); xtBool xt_xn_delete_xact(struct XTDatabase *db, xtXactID xn_id, struct XTThread *thread); diff --git a/storage/pbxt/src/xactlog_xt.cc b/storage/pbxt/src/xactlog_xt.cc index fac32ea0a09..f50dbc802bb 100644 --- a/storage/pbxt/src/xactlog_xt.cc +++ b/storage/pbxt/src/xactlog_xt.cc @@ -1108,6 +1108,9 @@ xtBool XTDatabaseLog::xlog_append(XTThreadPtr thread, size_t size1, xtWord1 *dat if ((part_size = xl_write_buf_pos % 512)) { part_size = 512 - part_size; xl_write_buffer[xl_write_buf_pos] = XT_LOG_ENT_END_OF_LOG; +#ifdef HAVE_valgrind + memset(xl_write_buffer + xl_write_buf_pos + 1, 0x66, part_size); +#endif if (!xt_pwrite_file(xl_log_file, xl_write_log_offset, xl_write_buf_pos+part_size, xl_write_buffer, &thread->st_statistics.st_xlog, thread)) goto write_failed; } @@ -1477,9 +1480,9 @@ void XTDatabaseLog::xlog_name(size_t size, char *path, xtLogID log_id) * T H R E A D T R A N S A C T I O N B U F F E R */ -xtPublic xtBool xt_xlog_flush_log(XTThreadPtr thread) +xtPublic xtBool xt_xlog_flush_log(struct XTDatabase *db, XTThreadPtr thread) { - return thread->st_database->db_xlog.xlog_flush(thread); + return db->db_xlog.xlog_flush(thread); } xtPublic xtBool xt_xlog_log_data(XTThreadPtr thread, size_t size, XTXactLogBufferDPtr log_entry, xtBool commit) @@ -1488,15 +1491,14 @@ xtPublic xtBool xt_xlog_log_data(XTThreadPtr thread, size_t size, XTXactLogBuffe } /* Allocate a record from the free list. */ -xtPublic xtBool xt_xlog_modify_table(struct XTOpenTable *ot, u_int status, xtOpSeqNo op_seq, xtRecordID free_rec_id, xtRecordID rec_id, size_t size, xtWord1 *data) +xtPublic xtBool xt_xlog_modify_table(xtTableID tab_id, u_int status, xtOpSeqNo op_seq, xtRecordID free_rec_id, xtRecordID rec_id, size_t size, xtWord1 *data, XTThreadPtr thread) { XTXactLogBufferDRec log_entry; - XTThreadPtr thread = ot->ot_thread; - XTTableHPtr tab = ot->ot_table; size_t len; xtWord4 sum = 0; int check_size = 1; XTXactDataPtr xact = NULL; + xtBool commit = FALSE; switch (status) { case XT_LOG_ENT_REC_MODIFIED: @@ -1505,7 +1507,7 @@ xtPublic xtBool xt_xlog_modify_table(struct XTOpenTable *ot, u_int status, xtOpS case XT_LOG_ENT_DELETE: check_size = 2; XT_SET_DISK_4(log_entry.xu.xu_op_seq_4, op_seq); - XT_SET_DISK_4(log_entry.xu.xu_tab_id_4, tab->tab_id); + XT_SET_DISK_4(log_entry.xu.xu_tab_id_4, tab_id); XT_SET_DISK_4(log_entry.xu.xu_rec_id_4, rec_id); XT_SET_DISK_2(log_entry.xu.xu_size_2, size); len = offsetof(XTactUpdateEntryDRec, xu_rec_type_1); @@ -1521,7 +1523,7 @@ xtPublic xtBool xt_xlog_modify_table(struct XTOpenTable *ot, u_int status, xtOpS case XT_LOG_ENT_DELETE_FL: check_size = 2; XT_SET_DISK_4(log_entry.xf.xf_op_seq_4, op_seq); - XT_SET_DISK_4(log_entry.xf.xf_tab_id_4, tab->tab_id); + XT_SET_DISK_4(log_entry.xf.xf_tab_id_4, tab_id); XT_SET_DISK_4(log_entry.xf.xf_rec_id_4, rec_id); XT_SET_DISK_2(log_entry.xf.xf_size_2, size); XT_SET_DISK_4(log_entry.xf.xf_free_rec_id_4, free_rec_id); @@ -1539,14 +1541,14 @@ xtPublic xtBool xt_xlog_modify_table(struct XTOpenTable *ot, u_int status, xtOpS case XT_LOG_ENT_REC_REMOVED_EXT: ASSERT_NS(size == 1 + XT_XACT_ID_SIZE + sizeof(XTTabRecFreeDRec)); XT_SET_DISK_4(log_entry.fr.fr_op_seq_4, op_seq); - XT_SET_DISK_4(log_entry.fr.fr_tab_id_4, tab->tab_id); + XT_SET_DISK_4(log_entry.fr.fr_tab_id_4, tab_id); XT_SET_DISK_4(log_entry.fr.fr_rec_id_4, rec_id); len = offsetof(XTactFreeRecEntryDRec, fr_stat_id_1); break; case XT_LOG_ENT_REC_REMOVED_BI: check_size = 2; XT_SET_DISK_4(log_entry.rb.rb_op_seq_4, op_seq); - XT_SET_DISK_4(log_entry.rb.rb_tab_id_4, tab->tab_id); + XT_SET_DISK_4(log_entry.rb.rb_tab_id_4, tab_id); XT_SET_DISK_4(log_entry.rb.rb_rec_id_4, rec_id); XT_SET_DISK_2(log_entry.rb.rb_size_2, size); log_entry.rb.rb_new_rec_type_1 = (xtWord1) free_rec_id; @@ -1556,42 +1558,42 @@ xtPublic xtBool xt_xlog_modify_table(struct XTOpenTable *ot, u_int status, xtOpS case XT_LOG_ENT_REC_MOVED: ASSERT_NS(size == 8); XT_SET_DISK_4(log_entry.xw.xw_op_seq_4, op_seq); - XT_SET_DISK_4(log_entry.xw.xw_tab_id_4, tab->tab_id); + XT_SET_DISK_4(log_entry.xw.xw_tab_id_4, tab_id); XT_SET_DISK_4(log_entry.xw.xw_rec_id_4, rec_id); len = offsetof(XTactWriteRecEntryDRec, xw_rec_type_1); break; case XT_LOG_ENT_REC_CLEANED: ASSERT_NS(size == offsetof(XTTabRecHeadDRec, tr_prev_rec_id_4) + XT_RECORD_ID_SIZE); XT_SET_DISK_4(log_entry.xw.xw_op_seq_4, op_seq); - XT_SET_DISK_4(log_entry.xw.xw_tab_id_4, tab->tab_id); + XT_SET_DISK_4(log_entry.xw.xw_tab_id_4, tab_id); XT_SET_DISK_4(log_entry.xw.xw_rec_id_4, rec_id); len = offsetof(XTactWriteRecEntryDRec, xw_rec_type_1); break; case XT_LOG_ENT_REC_CLEANED_1: ASSERT_NS(size == 1); XT_SET_DISK_4(log_entry.xw.xw_op_seq_4, op_seq); - XT_SET_DISK_4(log_entry.xw.xw_tab_id_4, tab->tab_id); + XT_SET_DISK_4(log_entry.xw.xw_tab_id_4, tab_id); XT_SET_DISK_4(log_entry.xw.xw_rec_id_4, rec_id); len = offsetof(XTactWriteRecEntryDRec, xw_rec_type_1); break; case XT_LOG_ENT_REC_UNLINKED: ASSERT_NS(size == offsetof(XTTabRecHeadDRec, tr_prev_rec_id_4) + XT_RECORD_ID_SIZE); XT_SET_DISK_4(log_entry.xw.xw_op_seq_4, op_seq); - XT_SET_DISK_4(log_entry.xw.xw_tab_id_4, tab->tab_id); + XT_SET_DISK_4(log_entry.xw.xw_tab_id_4, tab_id); XT_SET_DISK_4(log_entry.xw.xw_rec_id_4, rec_id); len = offsetof(XTactWriteRecEntryDRec, xw_rec_type_1); break; case XT_LOG_ENT_ROW_NEW: ASSERT_NS(size == 0); XT_SET_DISK_4(log_entry.xa.xa_op_seq_4, op_seq); - XT_SET_DISK_4(log_entry.xa.xa_tab_id_4, tab->tab_id); + XT_SET_DISK_4(log_entry.xa.xa_tab_id_4, tab_id); XT_SET_DISK_4(log_entry.xa.xa_row_id_4, rec_id); len = offsetof(XTactRowAddedEntryDRec, xa_row_id_4) + XT_ROW_ID_SIZE; break; case XT_LOG_ENT_ROW_NEW_FL: ASSERT_NS(size == 0); XT_SET_DISK_4(log_entry.xa.xa_op_seq_4, op_seq); - XT_SET_DISK_4(log_entry.xa.xa_tab_id_4, tab->tab_id); + XT_SET_DISK_4(log_entry.xa.xa_tab_id_4, tab_id); XT_SET_DISK_4(log_entry.xa.xa_row_id_4, rec_id); XT_SET_DISK_4(log_entry.xa.xa_free_list_4, free_rec_id); sum ^= XT_CHECKSUM4_REC(free_rec_id); @@ -1602,10 +1604,17 @@ xtPublic xtBool xt_xlog_modify_table(struct XTOpenTable *ot, u_int status, xtOpS case XT_LOG_ENT_ROW_FREED: ASSERT_NS(size == sizeof(XTTabRowRefDRec)); XT_SET_DISK_4(log_entry.wr.wr_op_seq_4, op_seq); - XT_SET_DISK_4(log_entry.wr.wr_tab_id_4, tab->tab_id); + XT_SET_DISK_4(log_entry.wr.wr_tab_id_4, tab_id); XT_SET_DISK_4(log_entry.wr.wr_row_id_4, rec_id); len = offsetof(XTactWriteRowEntryDRec, wr_ref_id_4); break; + case XT_LOG_ENT_PREPARE: + check_size = 2; + XT_SET_DISK_4(log_entry.xp.xp_xact_id_4, op_seq); + log_entry.xp.xp_xa_len_1 = (xtWord1) size; + len = offsetof(XTXactPrepareEntryDRec, xp_xa_data); + commit = TRUE; + break; default: ASSERT_NS(FALSE); len = 0; @@ -1615,7 +1624,7 @@ xtPublic xtBool xt_xlog_modify_table(struct XTOpenTable *ot, u_int status, xtOpS xtWord1 *dptr = data; xtWord4 g; - sum ^= op_seq ^ (tab->tab_id << 8) ^ XT_CHECKSUM4_REC(rec_id); + sum ^= op_seq ^ (tab_id << 8) ^ XT_CHECKSUM4_REC(rec_id); if ((g = sum & 0xF0000000)) { sum = sum ^ (g >> 24); sum = sum ^ g; @@ -1643,9 +1652,9 @@ xtPublic xtBool xt_xlog_modify_table(struct XTOpenTable *ot, u_int status, xtOpS xt_print_log_record(0, 0, &log_entry); #endif if (xact) - return thread->st_database->db_xlog.xlog_append(thread, len, (xtWord1 *) &log_entry, size, data, FALSE, &xact->xd_begin_log, &xact->xd_begin_offset); + return thread->st_database->db_xlog.xlog_append(thread, len, (xtWord1 *) &log_entry, size, data, commit, &xact->xd_begin_log, &xact->xd_begin_offset); - return thread->st_database->db_xlog.xlog_append(thread, len, (xtWord1 *) &log_entry, size, data, FALSE, NULL, NULL); + return thread->st_database->db_xlog.xlog_append(thread, len, (xtWord1 *) &log_entry, size, data, commit, NULL, NULL); } /* @@ -1905,6 +1914,7 @@ xtBool XTDatabaseLog::xlog_verify(XTXactLogBufferDPtr record, size_t rec_size, x xtRecordID rec_id, free_rec_id; int check_size = 1; xtWord1 *dptr; + xtWord4 g; switch (record->xh.xh_status_1) { case XT_LOG_ENT_HEADER: @@ -2019,13 +2029,19 @@ xtBool XTDatabaseLog::xlog_verify(XTXactLogBufferDPtr record, size_t rec_size, x return record->xe.xe_checksum_1 == (XT_CHECKSUM_1(sum) ^ XT_CHECKSUM_1(log_id)); case XT_LOG_ENT_END_OF_LOG: return FALSE; + case XT_LOG_ENT_PREPARE: + check_size = 2; + op_seq = XT_GET_DISK_4(record->xp.xp_xact_id_4); + tab_id = 0; + rec_id = 0; + dptr = record->xp.xp_xa_data; + rec_size -= offsetof(XTXactPrepareEntryDRec, xp_xa_data); + break; default: ASSERT_NS(FALSE); return FALSE; } - xtWord4 g; - sum ^= (xtWord4) op_seq ^ ((xtWord4) tab_id << 8) ^ XT_CHECKSUM4_REC(rec_id); if ((g = sum & 0xF0000000)) { @@ -2193,6 +2209,14 @@ xtBool XTDatabaseLog::xlog_seq_next(XTXactSeqReadPtr seq, XTXactLogBufferDPtr *r } goto return_empty; } + case XT_LOG_ENT_PREPARE: + check_size = 2; + len = offsetof(XTXactPrepareEntryDRec, xp_xa_data); + if (len > max_rec_len) + /* The size is not in the buffer: */ + goto read_more; + len += (size_t) record->xp.xp_xa_len_1; + break; default: /* It is possible to land here after a crash, if the * log was not completely written. @@ -2231,7 +2255,7 @@ xtBool XTDatabaseLog::xlog_seq_next(XTXactSeqReadPtr seq, XTXactLogBufferDPtr *r goto return_empty; } - /* The record is not completely in the buffer: */ + /* The record is now completely in the buffer: */ seq->xseq_record_len = len; *ret_entry = (XTXactLogBufferDPtr) seq->xseq_buffer; return OK; @@ -2428,7 +2452,7 @@ static void xlog_wr_wait_for_log_flush(XTThreadPtr self, XTDatabaseHPtr db) if (reason == XT_LOG_CACHE_FULL || reason == XT_TIME_TO_WRITE || reason == XT_CHECKPOINT_REQ) { /* Make sure that we have something to write: */ if (db->db_xlog.xlog_bytes_to_write() < 2 * 1204 * 1024) - xt_xlog_flush_log(self); + xt_xlog_flush_log(db, self); } #ifdef TRACE_WRITER_ACTIVITY @@ -2529,6 +2553,7 @@ static void xlog_wr_main(XTThreadPtr self) case XT_LOG_ENT_ABORT: case XT_LOG_ENT_CLEANUP: case XT_LOG_ENT_OP_SYNC: + case XT_LOG_ENT_PREPARE: break; case XT_LOG_ENT_DEL_LOG: xtLogID log_id; diff --git a/storage/pbxt/src/xactlog_xt.h b/storage/pbxt/src/xactlog_xt.h index 2db11898ec2..db1cf944c1b 100644 --- a/storage/pbxt/src/xactlog_xt.h +++ b/storage/pbxt/src/xactlog_xt.h @@ -160,6 +160,7 @@ typedef struct XTXLogCache { #define XT_LOG_ENT_END_OF_LOG 37 /* This is a record that indicates the end of the log, and * fills to the end of a 512 byte block. */ +#define XT_LOG_ENT_PREPARE 39 /* XA prepare log entry. */ #define XT_LOG_FILE_MAGIC 0xAE88FE12 #define XT_LOG_VERSION_NO 1 @@ -201,6 +202,14 @@ typedef struct XTXactEndEntry { XTDiskValue4 xe_not_used_4; /* Was the end sequence number (no longer used - v1.0.04+), set to zero). */ } XTXactEndEntryDRec, *XTXactEndEntryDPtr; +typedef struct XTXactPrepareEntry { + xtWord1 xp_status_1; /* XT_LOG_ENT_PREPARE */ + XTDiskValue2 xp_checksum_2; + XTDiskValue4 xp_xact_id_4; /* The transaction. */ + xtWord1 xp_xa_len_1; /* The length of the XA data. */ + xtWord1 xp_xa_data[XT_MAX_XA_DATA_SIZE]; +} XTXactPrepareEntryDRec, *XTXactPrepareEntryDPtr; + typedef struct XTXactCleanupEntry { xtWord1 xc_status_1; /* XT_LOG_ENT_CLEANUP */ xtWord1 xc_checksum_1; @@ -344,6 +353,7 @@ typedef union XTXactLogBuffer { XTactOpSyncEntryDRec os; XTactExtRecEntryDRec er; XTactNoOpEntryDRec no; + XTXactPrepareEntryDRec xp; } XTXactLogBufferDRec, *XTXactLogBufferDPtr; /* ---------------------------------------- */ @@ -453,9 +463,9 @@ private: xtBool xlog_open_log(xtLogID log_id, off_t curr_eof, struct XTThread *thread); } XTDatabaseLogRec, *XTDatabaseLogPtr; -xtBool xt_xlog_flush_log(struct XTThread *thread); +xtBool xt_xlog_flush_log(struct XTDatabase *db, struct XTThread *thread); xtBool xt_xlog_log_data(struct XTThread *thread, size_t len, XTXactLogBufferDPtr log_entry, xtBool commit); -xtBool xt_xlog_modify_table(struct XTOpenTable *ot, u_int status, xtOpSeqNo op_seq, xtRecordID free_list, xtRecordID address, size_t size, xtWord1 *data); +xtBool xt_xlog_modify_table(xtTableID tab_id, u_int status, xtOpSeqNo op_seq, xtRecordID free_list, xtRecordID address, size_t size, xtWord1 *data, struct XTThread *thread); void xt_xlog_init(struct XTThread *self, size_t cache_size); void xt_xlog_exit(struct XTThread *self); diff --git a/storage/pbxt/src/xt_config.h b/storage/pbxt/src/xt_config.h index 399789da043..f3749071087 100644 --- a/storage/pbxt/src/xt_config.h +++ b/storage/pbxt/src/xt_config.h @@ -50,7 +50,9 @@ const int max_connections = 500; /* * Make sure we use the thread safe version of the library. */ +#ifndef _THREAD_SAFE // Seems to be defined by some Drizzle header #define _THREAD_SAFE +#endif /* * This causes things to be defined like stuff in inttypes.h @@ -72,12 +74,12 @@ const int max_connections = 500; #define XT_MAC #endif -#if defined(MSDOS) || defined(__WIN__) +#if defined(MSDOS) || defined(__WIN__) || defined(_WIN64) #define XT_WIN #endif #ifdef XT_WIN -#ifdef _DEBUG +#if defined(_DEBUG) && !defined(DEBUG) #define DEBUG #endif // _DEBUG #else @@ -101,8 +103,13 @@ const int max_connections = 500; * Definition of which atomic operations to use: */ #ifdef XT_WIN +#ifdef _WIN64 +/* 64-bit Windows atomic ops are not yet supported: */ +#define XT_NO_ATOMICS +#else /* MS Studio style embedded assembler for x86 */ #define XT_ATOMIC_WIN32_X86 +#endif #elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) /* Use GNU style embedded assembler for x86 */ #define XT_ATOMIC_GNUC_X86 @@ -115,4 +122,10 @@ const int max_connections = 500; #define XT_NO_ATOMICS #endif +#ifndef DRIZZLED +#if MYSQL_VERSION_ID >= 50404 +#define MYSQL_SUPPORTS_BACKUP +#endif +#endif + #endif diff --git a/storage/pbxt/src/xt_defs.h b/storage/pbxt/src/xt_defs.h index 98867f746c9..15562fdfc95 100644 --- a/storage/pbxt/src/xt_defs.h +++ b/storage/pbxt/src/xt_defs.h @@ -379,6 +379,19 @@ typedef struct XTPathStr { */ //#define XT_IMPLEMENT_NO_ACTION +/* Define this value if online-backup should be supported. + * Note that, online backup is currently only supported + * by MySQL 6.0.9 or later + */ +#define XT_ENABLE_ONLINE_BACKUP + +/* Define this switch if you don't want to use atomic + * synchronisation. + */ +#ifndef XT_NO_ATOMICS +//#define XT_NO_ATOMICS +#endif + /* ---------------------------------------------------------------------- * GLOBAL CONSTANTS */ @@ -406,6 +419,8 @@ typedef struct XTPathStr { #define XT_ADD_PTR(p, l) ((void *) ((char *) (p) + (l))) +#define XT_MAX_XA_DATA_SIZE (3*4 + 128) /* Corresponds to the maximum size of struct xid_t in handler.h. */ + /* ---------------------------------------------------------------------- * DEFINES DEPENDENT ON CONSTANTS */ @@ -744,6 +759,7 @@ extern xtBool pbxt_crash_debug; #define MYSQL_PLUGIN_VAR_HEADER DRIZZLE_PLUGIN_VAR_HEADER #define MYSQL_SYSVAR_STR DRIZZLE_SYSVAR_STR #define MYSQL_SYSVAR_INT DRIZZLE_SYSVAR_INT +#define MYSQL_SYSVAR_BOOL DRIZZLE_SYSVAR_BOOL #define MYSQL_SYSVAR DRIZZLE_SYSVAR #define MYSQL_STORAGE_ENGINE_PLUGIN DRIZZLE_STORAGE_ENGINE_PLUGIN #define MYSQL_INFORMATION_SCHEMA_PLUGIN DRIZZLE_INFORMATION_SCHEMA_PLUGIN @@ -752,9 +768,8 @@ extern xtBool pbxt_crash_debug; #define mx_tmp_use_all_columns(x, y) (x)->use_all_columns(y) #define mx_tmp_restore_column_map(x, y) (x)->restore_column_map(y) -#define MX_BIT_FAST_TEST_AND_SET(x, y) bitmap_test_and_set(x, y) -#define MX_TABLE_TYPES_T handler::Table_flags +#define MX_TABLE_TYPES_T Cursor::Table_flags #define MX_UINT8_T uint8_t #define MX_ULONG_T uint32_t #define MX_ULONGLONG_T uint64_t @@ -762,6 +777,10 @@ extern xtBool pbxt_crash_debug; #define MX_CHARSET_INFO struct charset_info_st #define MX_CONST_CHARSET_INFO const struct charset_info_st #define MX_CONST const +#define MX_BITMAP MyBitmap +#define MX_BIT_SIZE() numOfBitsInMap() +#define MX_BIT_SET(x, y) (x)->setBit(y) +#define MX_BIT_FAST_TEST_AND_SET(x, y) (x)->testAndSet(y) #define my_bool bool #define int16 int16_t @@ -771,6 +790,7 @@ extern xtBool pbxt_crash_debug; #define uchar unsigned char #define longlong int64_t #define ulonglong uint64_t +#define handler Cursor #define HAVE_LONG_LONG @@ -823,10 +843,13 @@ extern xtBool pbxt_crash_debug; class PBXTStorageEngine; typedef PBXTStorageEngine handlerton; +class Session; + +extern "C" void session_mark_transaction_to_rollback(Session *session, bool all); #else // DRIZZLED /* The MySQL case: */ -#if MYSQL_VERSION_ID >= 60008 +#if MYSQL_VERSION_ID >= 50404 #define STRUCT_TABLE struct TABLE #else #define STRUCT_TABLE struct st_table @@ -844,13 +867,13 @@ typedef PBXTStorageEngine handlerton; #define MX_CHARSET_INFO CHARSET_INFO #define MX_CONST_CHARSET_INFO struct charset_info_st #define MX_CONST +#define MX_BITMAP MY_BITMAP +#define MX_BIT_SIZE() n_bits +#define MX_BIT_SET(x, y) bitmap_set_bit(x, y) #endif // DRIZZLED -#define MX_BITMAP MY_BITMAP -#define MX_BIT_SIZE() n_bits #define MX_BIT_IS_SUBSET(x, y) bitmap_is_subset(x, y) -#define MX_BIT_SET(x, y) bitmap_set_bit(x, y) #ifndef XT_SCAN_CORE_DEFINED #define XT_SCAN_CORE_DEFINED diff --git a/storage/pbxt/src/xt_errno.h b/storage/pbxt/src/xt_errno.h index 60e43d5fdfa..959c9422043 100644 --- a/storage/pbxt/src/xt_errno.h +++ b/storage/pbxt/src/xt_errno.h @@ -119,6 +119,9 @@ #define XT_ERR_FK_REF_TEMP_TABLE -95 #define XT_ERR_MYSQL_SHUTDOWN -98 #define XT_ERR_MYSQL_NO_THREAD -99 +#define XT_ERR_BUFFER_TOO_SMALL -100 +#define XT_ERR_BAD_BACKUP_FORMAT -101 +#define XT_ERR_PBXT_NOT_INSTALLED -102 #ifdef XT_WIN #define XT_ENOMEM ERROR_NOT_ENOUGH_MEMORY diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 2607e0f6d43..7ad25fb3565 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1498,6 +1498,14 @@ void my_hash_sort_ucs2_bin(CHARSET_INFO *cs __attribute__((unused)), } } + +static inline my_wc_t +ucs2_to_wc(const uchar *ptr) +{ + return (((uint) ptr[0]) << 8) + ptr[1]; +} + + /* ** Calculate min_str and max_str that ranges a LIKE string. ** Arguments: @@ -1531,6 +1539,7 @@ my_bool my_like_range_ucs2(CHARSET_INFO *cs, for ( ; ptr + 1 < end && min_str + 1 < min_end && charlen > 0 ; ptr+=2, charlen--) { + my_wc_t wc; if (ptr[0] == '\0' && ptr[1] == escape && ptr + 1 < end) { ptr+=2; /* Skip escape */ @@ -1567,9 +1576,9 @@ fill_max_and_min: } if (have_contractions && ptr + 3 < end && - ptr[0] == '\0' && - my_uca_can_be_contraction_head(cs, (uchar) ptr[1])) + my_uca_can_be_contraction_head(cs, (wc= ucs2_to_wc((uchar*) ptr)))) { + my_wc_t wc2; /* Contraction head found */ if (ptr[2] == '\0' && (ptr[3] == w_one || ptr[3] == w_many)) { @@ -1581,9 +1590,8 @@ fill_max_and_min: Check if the second letter can be contraction part, and if two letters really produce a contraction. */ - if (ptr[2] == '\0' && - my_uca_can_be_contraction_tail(cs, (uchar) ptr[3]) && - my_uca_contraction2_weight(cs,(uchar) ptr[1], (uchar) ptr[3])) + if (my_uca_can_be_contraction_tail(cs, (wc2= ucs2_to_wc((uchar*) ptr + 2))) && + my_uca_contraction2_weight(cs, wc , wc2)) { /* Contraction found */ if (charlen == 1 || min_str + 2 >= min_end) diff --git a/unittest/mysys/Makefile.am b/unittest/mysys/Makefile.am index 7fb487ffabf..115eeb8df7a 100644 --- a/unittest/mysys/Makefile.am +++ b/unittest/mysys/Makefile.am @@ -24,7 +24,7 @@ LDADD = $(top_builddir)/unittest/mytap/libmytap.a \ $(top_builddir)/strings/libmystrings.a EXTRA_DIST = CMakeLists.txt -noinst_PROGRAMS = bitmap-t base64-t lf-t waiting_threads-t +noinst_PROGRAMS = bitmap-t base64-t my_atomic-t lf-t waiting_threads-t if NEED_THREAD # my_atomic-t is used to check thread functions, so it is safe to |