summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authormonty@tik.mysql.fi <>2001-03-21 01:02:22 +0200
committermonty@tik.mysql.fi <>2001-03-21 01:02:22 +0200
commit6f9a73a1bae03ccf3e26371b453e31feb72fd2da (patch)
tree8a311781a9b85fe972ca9c89a0dc75654d3b3250 /sql
parentef75476c671bda70da7b65e5c499790eea786ebb (diff)
downloadmariadb-git-6f9a73a1bae03ccf3e26371b453e31feb72fd2da.tar.gz
Added isolation levels
Added SELECT .. FOR UPDATE and SELECT .. IN SHARE MODE
Diffstat (limited to 'sql')
-rw-r--r--sql/handler.cc17
-rw-r--r--sql/handler.h8
-rw-r--r--sql/item_strfunc.cc122
-rw-r--r--sql/lex.h12
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/mysqld.cc18
-rw-r--r--sql/sql_class.cc47
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc38
-rw-r--r--sql/sql_update.cc2
-rw-r--r--sql/sql_yacc.yy90
12 files changed, 253 insertions, 108 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index 96c19c904fe..5216941f473 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -59,6 +59,10 @@ const char *ha_row_type[] = {
TYPELIB ha_table_typelib= {array_elements(ha_table_type)-4,"",
ha_table_type+1};
+const char *tx_isolation_names[] =
+{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE"};
+TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names),"",
+ tx_isolation_names};
/* Use other database handler if databasehandler is not incompiled */
@@ -203,6 +207,7 @@ int ha_autocommit_or_rollback(THD *thd, int error)
}
else
(void) ha_rollback_stmt(thd);
+ thd->tx_isolation=thd->session_tx_isolation;
}
#endif
DBUG_RETURN(error);
@@ -248,6 +253,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
#endif
if (error && trans == &thd->transaction.all && mysql_bin_log.is_open())
sql_print_error("Error: Got error during commit; Binlog is not up to date!");
+ thd->tx_isolation=thd->session_tx_isolation;
}
#endif // using transactions
DBUG_RETURN(error);
@@ -286,11 +292,22 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
reinit_io_cache(&thd->transaction.trans_log,
WRITE_CACHE, (my_off_t) 0, 0, 1);
thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
+ thd->tx_isolation=thd->session_tx_isolation;
}
#endif /* USING_TRANSACTIONS */
DBUG_RETURN(error);
}
+void ha_set_spin_retries(uint retries)
+{
+#ifdef HAVE_GEMINI_DB
+ if (!gemini_skip)
+ {
+ gemini_set_option_long(GEM_OPTID_SPIN_RETRIES, retries);
+ }
+#endif /* HAVE_GEMINI_DB */
+}
+
bool ha_flush_logs()
{
diff --git a/sql/handler.h b/sql/handler.h
index 1c8a83ac9ed..463eef20ee4 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -108,7 +108,7 @@ enum db_type { DB_TYPE_UNKNOWN=0,DB_TYPE_DIAB_ISAM=1,
DB_TYPE_HASH,DB_TYPE_MISAM,DB_TYPE_PISAM,
DB_TYPE_RMS_ISAM, DB_TYPE_HEAP, DB_TYPE_ISAM,
DB_TYPE_MRG_ISAM, DB_TYPE_MYISAM, DB_TYPE_MRG_MYISAM,
- DB_TYPE_BERKELEY_DB, DB_TYPE_INNOBASE,
+ DB_TYPE_BERKELEY_DB, DB_TYPE_INNOBASE, DB_TYPE_GEMINI,
DB_TYPE_DEFAULT };
enum row_type { ROW_TYPE_DEFAULT, ROW_TYPE_FIXED, ROW_TYPE_DYNAMIC,
@@ -127,6 +127,9 @@ typedef struct st_thd_trans {
void *gemini_tid;
} THD_TRANS;
+enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
+ ISO_REPEATABLE_READ, ISO_SERIALIZABLE};
+
typedef struct st_ha_create_information
{
ulong table_options;
@@ -310,7 +313,7 @@ public:
/* Some extern variables used with handlers */
extern const char *ha_row_type[];
-extern TYPELIB ha_table_typelib;
+extern TYPELIB ha_table_typelib, tx_isolation_typelib;
/* Wrapper functions */
#define ha_commit_stmt(thd) (ha_commit_trans((thd), &((thd)->transaction.stmt)))
@@ -332,5 +335,6 @@ void ha_key_cache(void);
int ha_commit_trans(THD *thd, THD_TRANS *trans);
int ha_rollback_trans(THD *thd, THD_TRANS *trans);
int ha_autocommit_or_rollback(THD *thd, int error);
+void ha_set_spin_retries(uint retries);
bool ha_flush_logs(void);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index ec47f42f2ec..1ddff29783b 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -218,77 +218,75 @@ String *Item_func_concat_ws::val_str(String *str)
goto null;
use_as_buff= &tmp_value;
- str->length(0);
+ str->length(0); // QQ; Should be removed
res=str;
// Skip until non-null and non-empty argument is found.
// If not, return the empty string
- for (i=0; !(res= args[i]->val_str(str)) || !res->length(); i++)
- {
- if ((i + 1) == arg_count)
- return &empty_string;
- }
+ for (i=0;
+ !(res= args[i]->val_str(str)) || !res->length() && i < arg_count;
+ i++) ;
+ if (i == arg_count)
+ return &empty_string;
for (i++; i < arg_count ; i++)
{
if (!(res2= args[i]->val_str(use_as_buff)) || !res2->length())
- continue;
- else
+ continue; // Skipp NULL and empty string
+
+ if (res->length() + sep_str->length() + res2->length() >
+ max_allowed_packet)
+ goto null; // Error check
+ if (res->alloced_length() >=
+ res->length() + sep_str->length() + res2->length())
+ { // Use old buffer
+ res->append(*sep_str); // res->length() > 0 always
+ res->append(*res2);
+ use_as_buff= &tmp_value;
+ }
+ else if (str->alloced_length() >=
+ res->length() + sep_str->length() + res2->length())
{
- if (res->length() + sep_str->length() + res2->length() >
- max_allowed_packet)
- goto null; // Error check
- if (res->alloced_length() >=
- res->length() + sep_str->length() + res2->length())
- { // Use old buffer
- res->append(*sep_str); // res->length() > 0 always
- res->append(*res2);
- use_as_buff= &tmp_value;
- }
- else if (str->alloced_length() >=
- res->length() + sep_str->length() + res2->length())
- {
- str->copy(*res);
- str->append(*sep_str);
- str->append(*res2);
- res=str;
- use_as_buff= &tmp_value;
- }
- else if (res == &tmp_value)
- {
- if ((res->length() && res->append(*sep_str)) || res->append(*res2))
- goto null; // Must be a blob
- }
- else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
- res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
- {
- /*
- This happens really seldom:
- In this case res2 is sub string of tmp_value. We will
- now work in place in tmp_value to set it to res | res2
- */
- /* Chop the last characters in tmp_value that isn't in res2 */
- tmp_value.length((uint32) (res2->ptr() - tmp_value.ptr()) +
- res2->length());
- /* Place res2 at start of tmp_value, remove chars before res2 */
- if (res->append(*sep_str))
- goto null;
- if (tmp_value.replace(0,(uint32) (res2->ptr() - tmp_value.ptr()),
- *res))
- goto null;
- res= &tmp_value;
- use_as_buff=str; // Put next arg here
- }
- else
- { // Two big const strings
- if (tmp_value.alloc(max_length) ||
- tmp_value.copy(*res) ||
- tmp_value.append(*sep_str) ||
- tmp_value.append(*res2))
- goto null;
- res= &tmp_value;
- use_as_buff=str;
- }
+ str->copy(*res);
+ str->append(*sep_str);
+ str->append(*res2);
+ res=str;
+ use_as_buff= &tmp_value;
+ }
+ else if (res == &tmp_value)
+ {
+ if ((res->length() && res->append(*sep_str)) || res->append(*res2))
+ goto null; // Must be a blob
+ }
+ else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
+ res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
+ {
+ /*
+ This happens really seldom:
+ In this case res2 is sub string of tmp_value. We will
+ now work in place in tmp_value to set it to res | res2
+ */
+ /* Chop the last characters in tmp_value that isn't in res2 */
+ tmp_value.length((uint32) (res2->ptr() - tmp_value.ptr()) +
+ res2->length());
+ /* Place res2 at start of tmp_value, remove chars before res2 */
+ if (res->append(*sep_str))
+ goto null;
+ if (tmp_value.replace(0,(uint32) (res2->ptr() - tmp_value.ptr()),
+ *res))
+ goto null;
+ res= &tmp_value;
+ use_as_buff=str; // Put next arg here
+ }
+ else
+ { // Two big const strings
+ if (tmp_value.alloc(max_length) ||
+ tmp_value.copy(*res) ||
+ tmp_value.append(*sep_str) ||
+ tmp_value.append(*res2))
+ goto null;
+ res= &tmp_value;
+ use_as_buff=str;
}
}
return res;
diff --git a/sql/lex.h b/sql/lex.h
index 6f030aa524d..898110f8d15 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -86,6 +86,7 @@ static SYMBOL symbols[] = {
{ "COLUMNS", SYM(COLUMNS),0,0},
{ "COMMENT", SYM(COMMENT_SYM),0,0},
{ "COMMIT", SYM(COMMIT_SYM),0,0},
+ { "COMMITTED", SYM(COMMITTED_SYM),0,0},
{ "COMPRESSED", SYM(COMPRESSED_SYM),0,0},
{ "CONSTRAINT", SYM(CONSTRAINT),0,0},
{ "CREATE", SYM(CREATE),0,0},
@@ -144,6 +145,8 @@ static SYMBOL symbols[] = {
{ "FULL", SYM(FULL),0,0},
{ "FULLTEXT", SYM(FULLTEXT_SYM),0,0},
{ "FUNCTION", SYM(UDF_SYM),0,0},
+ { "GEMINI", SYM(GEMINI_SYM),0,0},
+ { "GLOBAL", SYM(GLOBAL_SYM),0,0},
{ "GRANT", SYM(GRANT),0,0},
{ "GRANTS", SYM(GRANTS),0,0},
{ "GROUP", SYM(GROUP),0,0},
@@ -174,6 +177,7 @@ static SYMBOL symbols[] = {
{ "INTO", SYM(INTO),0,0},
{ "IF", SYM(IF),0,0},
{ "IS", SYM(IS),0,0},
+ { "ISOLATION", SYM(ISOLATION),0,0},
{ "ISAM", SYM(ISAM_SYM),0,0},
{ "JOIN", SYM(JOIN_SYM),0,0},
{ "KEY", SYM(KEY_SYM),0,0},
@@ -182,6 +186,7 @@ static SYMBOL symbols[] = {
{ "LAST_INSERT_ID", SYM(LAST_INSERT_ID),0,0},
{ "LEADING", SYM(LEADING),0,0},
{ "LEFT", SYM(LEFT),0,0},
+ { "LEVEL", SYM(LEVEL_SYM),0,0},
{ "LIKE", SYM(LIKE),0,0},
{ "LINES", SYM(LINES),0,0},
{ "LIMIT", SYM(LIMIT),0,0},
@@ -212,6 +217,7 @@ static SYMBOL symbols[] = {
{ "MIN_ROWS", SYM(MIN_ROWS),0,0},
{ "MINUTE", SYM(MINUTE_SYM),0,0},
{ "MINUTE_SECOND", SYM(MINUTE_SECOND_SYM),0,0},
+ { "MODE", SYM(MODE_SYM),0,0},
{ "MODIFY", SYM(MODIFY_SYM),0,0},
{ "MONTH", SYM(MONTH_SYM),0,0},
{ "MRG_MYISAM", SYM(MERGE_SYM),0,0},
@@ -252,6 +258,7 @@ static SYMBOL symbols[] = {
{ "RENAME", SYM(RENAME),0,0},
{ "REPAIR", SYM(REPAIR),0,0},
{ "REPLACE", SYM(REPLACE),0,0},
+ { "REPEATABLE", SYM(REPEATABLE_SYM),0,0},
{ "RESET", SYM(RESET_SYM),0,0},
{ "RESTORE", SYM(RESTORE_SYM),0,0},
{ "RESTRICT", SYM(RESTRICT),0,0},
@@ -264,7 +271,10 @@ static SYMBOL symbols[] = {
{ "ROWS", SYM(ROWS_SYM),0,0},
{ "SECOND", SYM(SECOND_SYM),0,0},
{ "SELECT", SYM(SELECT_SYM),0,0},
+ { "SERIALIZABLE", SYM(SERIALIZABLE_SYM),0,0},
+ { "SESSION", SYM(SESSION_SYM),0,0},
{ "SET", SYM(SET),0,0},
+ { "SHARE", SYM(SHARE_SYM),0,0},
{ "SHOW", SYM(SHOW),0,0},
{ "SHUTDOWN", SYM(SHUTDOWN),0,0},
{ "SLAVE", SYM(SLAVE),0,0},
@@ -305,9 +315,11 @@ static SYMBOL symbols[] = {
{ "TINYTEXT", SYM(TINYTEXT),0,0},
{ "TINYINT", SYM(TINYINT),0,0},
{ "TRAILING", SYM(TRAILING),0,0},
+ { "TRANSACTION", SYM(TRANSACTION_SYM),0,0},
{ "TRUNCATE", SYM(TRUNCATE_SYM),0,0},
{ "TO", SYM(TO_SYM),0,0},
{ "TYPE", SYM(TYPE_SYM),0,0},
+ { "UNCOMMITTED", SYM(UNCOMMITTED_SYM),0,0},
{ "UNION", SYM(UNION_SYM),0,0},
{ "UNIQUE", SYM(UNIQUE_SYM),0,0},
{ "UNLOCK", SYM(UNLOCK_SYM),0,0},
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index a975cab3c7c..1e7f939bf80 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -251,6 +251,7 @@ void kill_mysql(void);
void close_connection(NET *net,uint errcode=0,bool lock=1);
bool check_access(THD *thd,uint access,const char *db=0,uint *save_priv=0,
bool no_grant=0);
+bool check_process_priv(THD *thd=0);
int generate_table(THD *thd, TABLE_LIST *table_list,
TABLE *locked_table);
@@ -538,6 +539,7 @@ extern String empty_string;
extern struct show_var_st init_vars[];
extern struct show_var_st status_vars[];
extern enum db_type default_table_type;
+extern enum enum_tx_isolation default_tx_isolation;
#ifndef __WIN__
extern pthread_t signal_thread;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index e85afd6b856..951984453f0 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -278,6 +278,7 @@ char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION;
const char *first_keyword="first";
const char **errmesg; /* Error messages */
const char *myisam_recover_options_str="OFF";
+enum_tx_isolation default_tx_isolation=ISO_READ_COMMITTED;
my_string mysql_unix_port=NULL,mysql_tmpdir=NULL;
ulong my_bind_addr; /* the address we bind to */
DATE_FORMAT dayord;
@@ -2426,7 +2427,7 @@ enum options {
OPT_INNOBASE_FLUSH_LOG_AT_TRX_COMMIT,
OPT_SAFE_SHOW_DB,
OPT_GEMINI_SKIP, OPT_INNOBASE_SKIP,
- OPT_TEMP_POOL
+ OPT_TEMP_POOL, OPT_TX_ISOLATION
};
static struct option long_options[] = {
@@ -2553,6 +2554,7 @@ static struct option long_options[] = {
#ifdef __WIN__
{"standalone", no_argument, 0, (int) OPT_STANDALONE},
#endif
+ {"transaction-isolation", required_argument, 0, (int) OPT_TX_ISOLATION},
{"temp-pool", no_argument, 0, (int) OPT_TEMP_POOL},
{"tmpdir", required_argument, 0, 't'},
{"use-locking", no_argument, 0, (int) OPT_USE_LOCKING},
@@ -2946,6 +2948,8 @@ static void usage(void)
Don't give threads different priorities.\n\
--socket=... Socket file to use for connection\n\
-t, --tmpdir=path Path for temporary files\n\
+ --transaction-isolation\n\
+ Default transaction isolation level\n\
--temp-pool Use a pool of temporary files\n\
-u, --user=user_name Run mysqld daemon as user\n\
-V, --version output version information and exit");
@@ -3080,6 +3084,7 @@ static void get_options(int argc,char **argv)
case 'a':
opt_ansi_mode=1;
thd_startup_options|=OPTION_ANSI_MODE;
+ default_tx_isolation= ISO_SERIALIZABLE;
break;
case 'b':
strmov(mysql_home,optarg);
@@ -3455,6 +3460,17 @@ static void get_options(int argc,char **argv)
charsets_dir = mysql_charsets_dir;
break;
#include "sslopt-case.h"
+ case OPT_TX_ISOLATION:
+ {
+ int type;
+ if ((type=find_type(optarg, &tx_isolation_typelib, 2)) <= 0)
+ {
+ fprintf(stderr,"Unknown transaction isolation type: %s\n",optarg);
+ exit(1);
+ }
+ default_tx_isolation= (enum_tx_isolation) (type-1);
+ break;
+ }
#ifdef HAVE_BERKELEY_DB
case OPT_BDB_LOG:
berkeley_logdir=optarg;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 925061594a9..6ea37d8a07a 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -79,50 +79,59 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
insert_id_used(0),in_lock_tables(0),
global_read_lock(0),bootstrap(0)
{
- proc_info="login";
- where="field list";
host=user=priv_user=db=query=ip=0;
locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password=
query_start_used=0;
query_length=col_access=0;
query_error=0;
-#ifdef SIGNAL_WITH_VIO_CLOSE
- active_vio = 0;
- pthread_mutex_init(&active_vio_lock, NULL);
-#endif
- server_id = ::server_id;
- server_status=SERVER_STATUS_AUTOCOMMIT;
next_insert_id=last_insert_id=0;
open_tables=temporary_tables=0;
tmp_table=0;
lock=locked_tables=0;
used_tables=0;
+ gemini_spin_retries=0;
cuted_fields=sent_row_count=0L;
- options=thd_startup_options;
- update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE;
start_time=(time_t) 0;
current_linfo = 0;
slave_thread = 0;
slave_proxy_id = 0;
last_nx_table = last_nx_db = 0;
+ cond_count=0;
+ convert_set=0;
+ mysys_var=0;
+ net.vio=0;
+ ull=0;
+ system_thread=0;
+#ifdef __WIN__
+ real_id = 0;
+#endif
+#ifdef SIGNAL_WITH_VIO_CLOSE
+ active_vio = 0;
+ pthread_mutex_init(&active_vio_lock, NULL);
+#endif
+
+ /* Variables with default values */
+ proc_info="login";
+ where="field list";
+ server_id = ::server_id;
+ server_status=SERVER_STATUS_AUTOCOMMIT;
+ update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE;
+ options=thd_startup_options;
inactive_timeout=net_wait_timeout;
open_options=ha_open_options;
- cond_count=0;
+ tx_isolation=session_tx_isolation=default_tx_isolation;
command=COM_CONNECT;
set_query_id=1;
default_select_limit= HA_POS_ERROR;
max_join_size= ((::max_join_size != ~ (ulong) 0L) ? ::max_join_size :
HA_POS_ERROR);
- convert_set=0;
- mysys_var=0;
db_access=NO_ACCESS;
+
+ /* Initialize sub structures */
+ bzero((char*) &mem_root,sizeof(mem_root));
hash_init(&user_vars, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
(void (*)(void*)) free_var,0);
- net.vio=0;
- ull=0;
- system_thread=0;
- bzero((char*) &mem_root,sizeof(mem_root));
#ifdef USING_TRANSACTIONS
if (opt_using_transactions)
{
@@ -134,10 +143,6 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
transaction.trans_log.end_of_file= max_binlog_cache_size;
}
#endif
-
-#ifdef __WIN__
- real_id = 0 ;
-#endif
}
THD::~THD()
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 1b444598401..09bb95b516e 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -268,7 +268,8 @@ public:
long dbug_thread_id;
pthread_t real_id;
uint current_tablenr,tmp_table,cond_count,col_access,query_length;
- uint server_status,open_options;
+ uint server_status,open_options, gemini_spin_retries;
+ enum_tx_isolation tx_isolation, session_tx_isolation;
char scramble[9];
bool slave_thread;
bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 7f52cc3e84c..e5c8cc08a5b 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -139,7 +139,9 @@ typedef struct st_lex {
enum_sql_command sql_command;
enum lex_states next_state;
enum enum_duplicates duplicates;
+ enum enum_tx_isolation tx_isolation;
uint in_sum_expr,grant,grant_tot_col,which_columns, sort_default;
+ uint gemini_spin_retries;
thr_lock_type lock_option;
bool create_refs,drop_primary,drop_if_exists,local_file;
bool in_comment,ignore_space,verbose;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 1884a8825ba..9cb1c9b119f 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -971,7 +971,7 @@ bool do_command(THD *thd)
send_ok(net); // Tell client we are alive
break;
case COM_PROCESS_INFO:
- if (!thd->priv_user[0] && check_access(thd,PROCESS_ACL,any_db))
+ if (!thd->priv_user[0] && check_process_priv(thd))
break;
mysql_log.write(thd,command,NullS);
mysqld_list_processes(thd,thd->master_access & PROCESS_ACL ? NullS :
@@ -984,7 +984,7 @@ bool do_command(THD *thd)
break;
}
case COM_DEBUG:
- if (check_access(thd,PROCESS_ACL,any_db))
+ if (check_process_priv(thd))
break; /* purecov: inspected */
mysql_print_status(thd);
mysql_log.write(thd,command,NullS);
@@ -1110,12 +1110,16 @@ mysql_execute_command(void)
#endif
break;
}
-
- if (lex->options & SELECT_HIGH_PRIORITY)
+ else
{
+ /*
+ Normal select:
+ Change lock if we are using SELECT HIGH PRIORITY,
+ FOR UPDATE or IN SHARE MODE
+ */
TABLE_LIST *table;
for (table = tables ; table ; table=table->next)
- table->lock_type=TL_READ_HIGH_PRIORITY;
+ table->lock_type= lex->lock_option;
}
if (!(res=open_and_lock_tables(thd,tables)))
@@ -1141,7 +1145,7 @@ mysql_execute_command(void)
}
case SQLCOM_PURGE:
{
- if(check_access(thd, PROCESS_ACL, any_db))
+ if (check_process_priv(thd))
goto error;
res = purge_master_logs(thd, lex->to_log);
break;
@@ -1174,14 +1178,14 @@ mysql_execute_command(void)
}
case SQLCOM_SHOW_SLAVE_STAT:
{
- if(check_access(thd, PROCESS_ACL, any_db))
+ if (check_process_priv(thd))
goto error;
res = show_master_info(thd);
break;
}
case SQLCOM_SHOW_MASTER_STAT:
{
- if (check_access(thd, PROCESS_ACL, any_db))
+ if (check_process_priv(thd))
goto error;
res = show_binlog_info(thd);
break;
@@ -1414,7 +1418,7 @@ mysql_execute_command(void)
DBUG_VOID_RETURN;
#else
{
- if(check_access(thd, PROCESS_ACL, any_db))
+ if (check_process_priv(thd))
goto error;
res = show_binlogs(thd);
break;
@@ -1632,13 +1636,13 @@ mysql_execute_command(void)
DBUG_VOID_RETURN;
#else
if ((specialflag & SPECIAL_SKIP_SHOW_DB) &&
- check_access(thd,PROCESS_ACL,any_db))
+ check_process_priv(thd))
goto error;
res= mysqld_show_dbs(thd, (lex->wild ? lex->wild->ptr() : NullS));
break;
#endif
case SQLCOM_SHOW_PROCESSLIST:
- if (!thd->priv_user[0] && check_access(thd,PROCESS_ACL,any_db))
+ if (!thd->priv_user[0] && check_process_priv(thd))
break;
mysqld_list_processes(thd,thd->master_access & PROCESS_ACL ? NullS :
thd->priv_user,lex->verbose);
@@ -1778,6 +1782,12 @@ mysql_execute_command(void)
thd->update_lock_default= ((thd->options & OPTION_LOW_PRIORITY_UPDATES) ?
TL_WRITE_LOW_PRIORITY : TL_WRITE);
thd->default_select_limit=lex->select_limit;
+ thd->tx_isolation=lex->tx_isolation;
+ if (thd->gemini_spin_retries != lex->gemini_spin_retries)
+ {
+ thd->gemini_spin_retries= lex->gemini_spin_retries;
+ ha_set_spin_retries(thd->gemini_spin_retries);
+ }
DBUG_PRINT("info",("options: %ld limit: %ld",
thd->options,(long) thd->default_select_limit));
@@ -2092,6 +2102,12 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv,
}
+bool check_process_priv(THD *thd)
+{
+ return (check_access(thd ? thd : current_thd,PROCESS_ACL,any_db));
+}
+
+
/*
** Check the privilege for all used tables. Table privileges are cached
** in the table list for GRANT checking
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index a4e5dea5e76..688a5cebfee 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -20,8 +20,6 @@
#include "mysql_priv.h"
#include "sql_acl.h"
-#define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1))
-
/* Return 0 if row hasn't changed */
static bool compare_record(TABLE *table, ulong query_id)
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 34cdb3dbf13..2207d8834b2 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -54,6 +54,7 @@ inline Item *or_or_concat(Item* A, Item* B)
Key::Keytype key_type;
enum db_type db_type;
enum row_type row_type;
+ enum enum_tx_isolation tx_isolation;
String *string;
key_part_spec *key_part;
TABLE_LIST *table_list;
@@ -141,6 +142,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CASCADE
%token CHECKSUM_SYM
%token CHECK_SYM
+%token COMMITTED_SYM
%token COLUMNS
%token COLUMN_SYM
%token CONSTRAINT
@@ -166,6 +168,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token FROM
%token FULL
%token FULLTEXT_SYM
+%token GEMINI_SYM
+%token GEMINI_SPIN_RETRIES
+%token GLOBAL_SYM
%token GRANT
%token GRANTS
%token GREATEST_SYM
@@ -183,12 +188,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token INNOBASE_SYM
%token INTO
%token IN_SYM
+%token ISOLATION
%token ISAM_SYM
%token JOIN_SYM
%token KEYS
%token KEY_SYM
%token LEADING
%token LEAST_SYM
+%token LEVEL_SYM
%token LEX_HOSTNAME
%token LIKE
%token LINES
@@ -244,6 +251,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token REGEXP
%token RELOAD
%token RENAME
+%token REPEATABLE_SYM
%token RESTORE_SYM
%token RESTRICT
%token REVOKE
@@ -251,6 +259,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token ROW_FORMAT_SYM
%token ROW_SYM
%token SET
+%token SERIALIZABLE_SYM
+%token SESSION_SYM
%token SHUTDOWN
%token STARTING
%token STATUS_SYM
@@ -262,6 +272,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token TEXT_STRING
%token TO_SYM
%token TRAILING
+%token TRANSACTION_SYM
%token TYPE_SYM
%token FUNC_ARG0
%token FUNC_ARG1
@@ -270,6 +281,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token UDF_RETURNS_SYM
%token UDF_SONAME_SYM
%token UDF_SYM
+%token UNCOMMITTED_SYM
%token UNION_SYM
%token UNIQUE_SYM
%token USAGE
@@ -361,6 +373,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MAKE_SET_SYM
%token MINUTE_SECOND_SYM
%token MINUTE_SYM
+%token MODE_SYM
%token MODIFY_SYM
%token MONTH_SYM
%token NOW_SYM
@@ -372,6 +385,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token RIGHT
%token ROUND
%token SECOND_SYM
+%token SHARE_SYM
%token SUBSTRING
%token SUBSTRING_INDEX
%token TRIM
@@ -484,6 +498,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <row_type> row_types
+%type <tx_isolation> tx_isolation isolation_types
+
%type <udf_type> udf_func_type
%type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword
@@ -749,7 +765,8 @@ table_types:
| MERGE_SYM { $$= DB_TYPE_MRG_MYISAM; }
| HEAP_SYM { $$= DB_TYPE_HEAP; }
| BERKELEY_DB_SYM { $$= DB_TYPE_BERKELEY_DB; }
- | INNOBASE_SYM { $$= DB_TYPE_INNOBASE; }
+ | INNOBASE_SYM { $$= DB_TYPE_INNOBASE; }
+ | GEMINI_SYM { $$= DB_TYPE_GEMINI; }
row_types:
DEFAULT { $$= ROW_TYPE_DEFAULT; }
@@ -1216,9 +1233,10 @@ select:
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SELECT;
+ lex->lock_option=TL_READ;
mysql_init_select(lex);
}
- select_options select_item_list select_into
+ select_options select_item_list select_into select_lock_type
select_into:
/* empty */
@@ -1240,13 +1258,20 @@ select_option_list:
select_option:
STRAIGHT_JOIN { Lex->options|= SELECT_STRAIGHT_JOIN; }
- | HIGH_PRIORITY { Lex->options|= SELECT_HIGH_PRIORITY; }
+ | HIGH_PRIORITY { Lex->lock_option= TL_READ_HIGH_PRIORITY; }
| DISTINCT { Lex->options|= SELECT_DISTINCT; }
| SQL_SMALL_RESULT { Lex->options|= SELECT_SMALL_RESULT; }
| SQL_BIG_RESULT { Lex->options|= SELECT_BIG_RESULT; }
| SQL_BUFFER_RESULT { Lex->options|= OPTION_BUFFER_RESULT; }
| ALL {}
+select_lock_type:
+ /* empty */
+ | FOR_SYM UPDATE_SYM
+ { Lex->lock_option= TL_WRITE; }
+ | IN_SYM SHARE_SYM MODE_SYM
+ { Lex->lock_option= TL_READ_WITH_SHARED_LOCKS; }
+
select_item_list:
select_item_list ',' select_item
| select_item
@@ -2124,8 +2149,10 @@ opt_low_priority:
delete:
DELETE_SYM
- { Lex->sql_command= SQLCOM_DELETE; Lex->options=0;
- Lex->lock_option= current_thd->update_lock_default; }
+ {
+ Lex->sql_command= SQLCOM_DELETE; Lex->options=0;
+ Lex->lock_option= current_thd->update_lock_default;
+ }
opt_delete_options FROM table
where_clause delete_limit_clause
@@ -2479,6 +2506,7 @@ keyword:
| AGAINST {}
| AGGREGATE_SYM {}
| AUTOCOMMIT {}
+ | AUTO_INC {}
| AVG_ROW_LENGTH {}
| AVG_SYM {}
| BACKUP_SYM {}
@@ -2491,6 +2519,7 @@ keyword:
| CHECK_SYM {}
| COMMENT_SYM {}
| COMMIT_SYM {}
+ | COMMITTED_SYM {}
| COMPRESSED_SYM {}
| DATA_SYM {}
| DATETIME {}
@@ -2510,12 +2539,16 @@ keyword:
| FIXED_SYM {}
| FLUSH_SYM {}
| GRANTS {}
+ | GEMINI_SYM {}
+ | GLOBAL_SYM {}
| HEAP_SYM {}
| HOSTS_SYM {}
| HOUR_SYM {}
| IDENTIFIED_SYM {}
+ | ISOLATION {}
| ISAM_SYM {}
| INNOBASE_SYM {}
+ | LEVEL_SYM {}
| LOCAL_SYM {}
| LOGS_SYM {}
| MAX_ROWS {}
@@ -2532,6 +2565,7 @@ keyword:
| MINUTE_SYM {}
| MIN_ROWS {}
| MODIFY_SYM {}
+ | MODE_SYM {}
| MONTH_SYM {}
| MYISAM_SYM {}
| NATIONAL_SYM {}
@@ -2550,6 +2584,7 @@ keyword:
| RAID_TYPE {}
| RELOAD {}
| REPAIR {}
+ | REPEATABLE_SYM {}
| RESET_SYM {}
| RESTORE_SYM {}
| ROLLBACK_SYM {}
@@ -2557,6 +2592,9 @@ keyword:
| ROW_FORMAT_SYM {}
| ROW_SYM {}
| SECOND_SYM {}
+ | SERIALIZABLE_SYM {}
+ | SESSION_SYM {}
+ | SHARE_SYM {}
| SHUTDOWN {}
| START_SYM {}
| STATUS_SYM {}
@@ -2564,11 +2602,13 @@ keyword:
| STRING_SYM {}
| TEMPORARY {}
| TEXT_SYM {}
+ | TRANSACTION_SYM {}
| TRUNCATE_SYM {}
| TIMESTAMP {}
| TIME_SYM {}
| TYPE_SYM {}
| UDF_SYM {}
+ | UNCOMMITTED_SYM {}
| VARIABLES {}
| WORK_SYM {}
| YEAR_SYM {}
@@ -2579,9 +2619,12 @@ keyword:
set:
SET opt_option
{
+ THD *thd=current_thd;
Lex->sql_command= SQLCOM_SET_OPTION;
- Lex->options=current_thd->options;
- Lex->select_limit=current_thd->default_select_limit;
+ Lex->options=thd->options;
+ Lex->select_limit=thd->default_select_limit;
+ Lex->gemini_spin_retries=thd->gemini_spin_retries;
+ Lex->tx_isolation=thd->tx_isolation;
}
option_value_list
@@ -2601,6 +2644,7 @@ option_value:
else
Lex->options|= $1;
}
+ | set_isolation
| AUTOCOMMIT equal NUM
{
if (atoi($3.str) != 0) /* Test NOT AUTOCOMMIT */
@@ -2641,6 +2685,14 @@ option_value:
{
current_thd->next_insert_id=$3;
}
+ | GEMINI_SPIN_RETRIES equal ULONG_NUM
+ {
+ Lex->gemini_spin_retries= $3;
+ }
+ | GEMINI_SPIN_RETRIES equal DEFAULT
+ {
+ Lex->gemini_spin_retries= 1;
+ }
| CHAR_SYM SET IDENT
{
CONVERT *tmp;
@@ -2702,7 +2754,7 @@ text_or_password:
}
set_option:
- SQL_BIG_TABLES { $$= OPTION_BIG_TABLES; }
+ SQL_BIG_TABLES { $$= OPTION_BIG_TABLES; }
| SQL_BIG_SELECTS { $$= OPTION_BIG_SELECTS; }
| SQL_LOG_OFF { $$= OPTION_LOG_OFF; }
| SQL_LOG_UPDATE
@@ -2724,6 +2776,28 @@ set_option:
| SQL_BUFFER_RESULT { $$= OPTION_BUFFER_RESULT; }
| SQL_QUOTE_SHOW_CREATE { $$= OPTION_QUOTE_SHOW_CREATE; }
+
+set_isolation:
+ GLOBAL_SYM tx_isolation
+ {
+ if (check_process_priv())
+ YYABORT;
+ default_tx_isolation= $2;
+ }
+ | SESSION_SYM tx_isolation
+ { current_thd->session_tx_isolation= $2; }
+ | tx_isolation
+ { Lex->tx_isolation= $1; }
+
+tx_isolation:
+ TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types { $$=$4; }
+
+isolation_types:
+ READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; }
+ | READ_SYM COMMITTED_SYM { $$= ISO_READ_COMMITTED; }
+ | REPEATABLE_SYM READ_SYM { $$= ISO_REPEATABLE_READ; }
+ | SERIALIZABLE_SYM { $$= ISO_SERIALIZABLE; }
+
/* Lock function */
lock: