summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <monty@tik.mysql.fi>2001-03-21 01:02:22 +0200
committerunknown <monty@tik.mysql.fi>2001-03-21 01:02:22 +0200
commit6257ee7613836c397bda6c3533ca4a114d60e045 (patch)
tree8a311781a9b85fe972ca9c89a0dc75654d3b3250
parentd1782bea92ebf698cdcf898007f3b015ba502493 (diff)
downloadmariadb-git-6257ee7613836c397bda6c3533ca4a114d60e045.tar.gz
Added isolation levels
Added SELECT .. FOR UPDATE and SELECT .. IN SHARE MODE Docs/manual.texi: Updated information about SET TRANSACTION ISOLATION LEVEL configure.in: Upgraded version number isam/_dbug.c: Fixed wrong fprintf isam/isamchk.c: Added new error message myisam/mi_check.c: Added new error message mysql-test/mysql-test-run.sh: Don't wait too long for server start mysys/mf_keycache.c: Cleaned up some error messages scripts/mysqlhotcopy.sh: Applied patch for --resetmaster --resetslave sql-bench/bench-init.pl.sh: Fix for windows sql/handler.cc: Added isolation levels and gemini spinlocks sql/handler.h: Added isolation levels sql/item_strfunc.cc: Cleanup of CONCAT_WS() sql/lex.h: Added isolation levels sql/mysql_priv.h: Added isolation levels sql/mysqld.cc: Added isolation levels sql/sql_class.cc: Added isolation levels Moved variable initialization to different code segments sql/sql_class.h: Added isolation levels sql/sql_lex.h: Added isolation levels sql/sql_parse.cc: Added isolation levels sql/sql_update.cc: cleanup BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted
-rw-r--r--BitKeeper/etc/logging_ok5
-rw-r--r--Docs/manual.texi76
-rw-r--r--configure.in2
-rw-r--r--isam/_dbug.c2
-rw-r--r--isam/isamchk.c10
-rw-r--r--myisam/mi_check.c3
-rw-r--r--mysql-test/mysql-test-run.sh2
-rw-r--r--mysys/mf_keycache.c21
-rw-r--r--scripts/mysqlhotcopy.sh26
-rw-r--r--sql-bench/bench-init.pl.sh15
-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
22 files changed, 381 insertions, 142 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index abbe1d55830..01a1261eae5 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -1,4 +1 @@
-jani@hynda.mysql.fi
-heikki@donna.mysql.fi
-monty@donna.mysql.fi
-paul@central.snake.net
+monty@tik.mysql.fi
diff --git a/Docs/manual.texi b/Docs/manual.texi
index 62382d89990..b8651afec34 100644
--- a/Docs/manual.texi
+++ b/Docs/manual.texi
@@ -9738,7 +9738,7 @@ uses:
@cindex options, command-line
@cindex mysqld options
@node Command-line options, Option files, Automatic start, Post-installation
-@subsection Command-line Options
+@subsection mysqld Command-line Options
@code{mysqld} accepts the following command-line options:
@@ -9952,6 +9952,9 @@ Disable using thread priorities for faster response time.
Socket file to use for local connections instead of default
@code{/tmp/mysql.sock}.
+@item transaction-isolation= @{ READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE @}
+Sets the default transaction isolation level. @xref{SET TRANSACTION}.
+
@item -t, --tmpdir=path
Path for temporary files. It may be useful if your default @code{/tmp}
directory resides on a partition too small to hold temporary tables.
@@ -10816,6 +10819,9 @@ This forces all function names to be treated as reserved words.
@item
@code{REAL} will be a synonym for @code{FLOAT} instead of a synonym of
@code{DOUBLE}.
+@item
+The default transaction isolation level is @code{SERIALIZABLE}.
+@xref{SET TRANSACTION}.
@end itemize
@node Differences from ANSI, Missing functions, ANSI mode, Compatibility
@@ -13463,6 +13469,7 @@ to restart @code{mysqld} with @code{--skip-grant-tables} to run
* COMMIT:: @code{BEGIN/COMMIT/ROLLBACK} syntax
* LOCK TABLES:: @code{LOCK TABLES/UNLOCK TABLES} syntax
* SET OPTION:: @code{SET OPTION} syntax
+* SET TRANSACTION::
* GRANT:: @code{GRANT} and @code{REVOKE} syntax
* CREATE INDEX:: @code{CREATE INDEX} syntax
* DROP INDEX:: @code{DROP INDEX} syntax
@@ -13485,7 +13492,7 @@ to restart @code{mysqld} with @code{--skip-grant-tables} to run
* Number syntax:: Numbers
* Hexadecimal values:: Hexadecimal values
* NULL values:: @code{NULL} values
-* Legal names:: Database, table, index, column and alias names
+* Legal names:: Database, Table, Index, Column, and Alias Names
@end menu
@node String syntax, Number syntax, Literals, Literals
@@ -19327,7 +19334,8 @@ SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[HAVING where_definition]
[ORDER BY @{unsigned_integer | col_name | formula@} [ASC | DESC] ,...]
[LIMIT [offset,] rows]
- [PROCEDURE procedure_name] ]
+ [PROCEDURE procedure_name]
+ [FOR UPDATE | IN SHARE MODE]]
@end example
@c help end
@@ -19570,6 +19578,17 @@ If you use @code{INTO DUMPFILE} instead of @code{INTO OUTFILE}, @strong{MySQL}
will only write one row into the file, without any column or line
terminations and without any escaping. This is useful if you want to
store a blob in a file.
+
+@item
+Note that any file created by @code{INTO OUTFILE} and @code{INTO
+DUMPFILE} is going to be readable for all users! The reason is that the
+@strong{MySQL} server can't create a file that is owned by anyone else
+than the user it's running as (you should never run @code{mysqld} as root),
+the file has to be word readable so that you can retrieve the rows.
+
+@item
+If you are using @code{FOR UPDATE} on a table handler with page/row locks,
+the examined rows will be write locked.
@end itemize
@findex JOIN
@@ -20739,6 +20758,9 @@ write is aborted with an disk full error message.
@findex SHOW TABLE STATUS
@findex SHOW GRANTS
@findex SHOW CREATE TABLE
+@findex SHOW MASTER STATUS
+@findex SHOW MASTER LOGS
+@findex SHOW SLAVE STATUS
@node SHOW, EXPLAIN, KILL, Reference
@section @code{SHOW} Syntax (Get Information About Tables, Columns,...)
@@ -22042,7 +22064,7 @@ table you will get an error (@code{ER_WARNING_NOT_COMPLETE_ROLLBACK}) as
a warning. All transactional safe tables will be restored but any
non-transactional table will not change.
-If you are using @code{BEGIN} or @code{SET AUTO_COMMIT=0}, you
+If you are using @code{BEGIN} or @code{SET AUTOCOMMIT=0}, you
should use the @strong{MySQL} binary log for backups instead of the
old update log; The transaction is stored in the binary log
in one chunk, during @code{COMMIT}, the to ensure and @code{ROLLBACK}:ed
@@ -22057,6 +22079,9 @@ a @code{COMMIT} before executing the command):
@item @code{TRUNCATE}
@end multitable
+You can change the isolation level for transactions with
+@code{SET TRANSACTION ISOLATION LEVEL ...}. @xref{SET TRANSACTION}.
+
@findex LOCK TABLES
@findex UNLOCK TABLES
@node LOCK TABLES, SET OPTION, COMMIT, Reference
@@ -22162,7 +22187,7 @@ automaticly commit any active transactions before attempting to lock the
tables.
@findex SET OPTION
-@node SET OPTION, GRANT, LOCK TABLES, Reference
+@node SET OPTION, SET TRANSACTION, LOCK TABLES, Reference
@section @code{SET} Syntax
@example
@@ -22303,6 +22328,30 @@ command when inserting an @code{AUTO_INCREMENT} value. This is mainly used
with the update log.
@end table
+@findex ISOLATION LEVEL
+@node SET TRANSACTION, GRANT, SET OPTION, Reference
+@section @code{SET TRANSACTION} Syntax
+
+@example
+SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
+[READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE]
+@end example
+
+Sets the transaction isolation level for the global, whole session or
+the next transaction.
+
+The default behaveour is to set the isolation level for the next (not started)
+isolation level.
+
+If you set the @code{GLOBAL} privilege it will affect all new created threads.
+You will need the @code{PROCESS} privilege to do do this.
+
+Setting the @code{SESSION} privilege will affect the following and all
+future transactions.
+
+You can set the default isolation level for @code{mysqld} with
+@code{--transaction-isolation=...}. @xref{Command-line options}.
+
@cindex privileges, granting
@cindex privileges, revoking
@cindex global privileges
@@ -22311,7 +22360,7 @@ with the update log.
@findex GRANT
@findex REVOKE
-@node GRANT, CREATE INDEX, SET OPTION, Reference
+@node GRANT, CREATE INDEX, SET TRANSACTION, Reference
@section @code{GRANT} and @code{REVOKE} Syntax
@example
@@ -36053,7 +36102,7 @@ direct from a remote mysql server!
@code{mysqlbinlog --help} will give you more information of how to use
this program!
-If you are using @code{BEGIN} or @code{SET AUTO_COMMIT=0}, you must use
+If you are using @code{BEGIN} or @code{SET AUTOCOMMIT=0}, you must use
the @strong{MySQL} binary log for backups instead of the old update log.
The binary logging is done immediately after a query completes but before
@@ -42245,8 +42294,6 @@ Added @code{IDENTITY} as a synonym for @code{AUTO_INCREMENT} (like SyBase).
@item
Added @code{ORDER BY} syntax to @code{UPDATE} and @code{DELETE}.
@item
-Added @code{SELECT ... WITH UPDATE} and @code{SELECT ... IN SHARE MODE} to
-get more locking options.
@end itemize
@node News-3.23.x, News-3.22.x, News-4.0.x, News
@@ -42278,6 +42325,7 @@ users uses this code as the rest of the code and because of this we are
not yet 100 % confident in this code.
@menu
+* News-3.23.36::
* News-3.23.35:: Changes in release 3.23.35
* News-3.23.34a:: Changes in release 3.23.34a
* News-3.23.34:: Changes in release 3.23.34
@@ -42317,7 +42365,15 @@ not yet 100 % confident in this code.
* News-3.23.0:: Changes in release 3.23.0
@end menu
-@node News-3.23.35, News-3.23.34a, News-3.23.x, News-3.23.x
+@node News-3.23.36, News-3.23.35, News-3.23.x, News-3.23.x
+@appendixsubsec Changes in release 3.23.36
+@itemize @bullet
+Added @code{SET TRANSACTION ISOLATION LEVEL ...}
+@item
+Added @code{SELECT ... FOR UPDATE}.
+@end itemize
+
+@node News-3.23.35, News-3.23.34a, News-3.23.36, News-3.23.x
@appendixsubsec Changes in release 3.23.35
@itemize @bullet
@item
diff --git a/configure.in b/configure.in
index 6cacea83f36..494e47c99d3 100644
--- a/configure.in
+++ b/configure.in
@@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM
# The Docs Makefile.am parses this line!
-AM_INIT_AUTOMAKE(mysql, 3.23.35)
+AM_INIT_AUTOMAKE(mysql, 3.23.36)
AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10
diff --git a/isam/_dbug.c b/isam/_dbug.c
index 644d0e420d6..fd0a0b46562 100644
--- a/isam/_dbug.c
+++ b/isam/_dbug.c
@@ -85,7 +85,7 @@ void _nisam_print_key(FILE *stream, register N_KEYSEG *keyseg, const uchar *key)
key=end;
break;
case HA_KEYTYPE_INT24:
- VOID(fprintf(stream,"%d",sint3korr(key)));
+ VOID(fprintf(stream,"%ld",sint3korr(key)));
key=end;
break;
case HA_KEYTYPE_UINT24:
diff --git a/isam/isamchk.c b/isam/isamchk.c
index ce96655a7a5..bb9b7bfa16b 100644
--- a/isam/isamchk.c
+++ b/isam/isamchk.c
@@ -284,7 +284,7 @@ static struct option long_options[] =
static void print_version(void)
{
- printf("%s Ver 5.15 for %s at %s\n",my_progname,SYSTEM_TYPE,
+ printf("%s Ver 5.16 for %s at %s\n",my_progname,SYSTEM_TYPE,
MACHINE_TYPE);
}
@@ -1793,6 +1793,9 @@ my_string name;
if (share->base.options & HA_OPTION_COMPRESS_RECORD)
printf(" Huff tree Bits");
VOID(putchar('\n'));
+ if (verbose > 2 && share->base.pack_bits)
+ printf("- %-7d%-35s\n",share->base.pack_bits,"bit field");
+
start=1;
for (field=0 ; field < share->base.fields ; field++)
{
@@ -2806,6 +2809,11 @@ static int sort_get_next_record()
}
DBUG_RETURN(0);
}
+ if (!searching)
+ {
+ print_info("Found wrong packed record at %lu",
+ (ulong) sort_info.start_recpos);
+ }
try_next:
pos=sort_info.start_recpos+1;
searching=1;
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 699f0f5ad68..4bd6747d499 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -2342,6 +2342,9 @@ static int sort_get_next_record(SORT_INFO *sort_info)
}
DBUG_RETURN(0);
}
+ if (!searching)
+ mi_check_print_info(param,"Found wrong stored record at %s",
+ llstr(sort_info->start_recpos,llbuff));
try_next:
pos=(sort_info->start_recpos+=MI_DYN_ALIGN_SIZE);
searching=1;
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 16d26fc48b2..24b62a69b9f 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -241,7 +241,7 @@ SLAVE_MYSQLD=$MYSQLD #this can be changed later if we are doing gcov
#--
wait_for_server_start ()
{
- $MYSQLADMIN --no-defaults -u $DBUSER --silent -w2 --host=$hostname --port=$1 ping >/dev/null
+ $MYSQLADMIN --no-defaults -u $DBUSER --silent -O connect_timeout=10 -w2 --host=$hostname --port=$1 ping >/dev/null 2>&1
}
prompt_user ()
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index 72d0d4a5e10..da02ec3da18 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -237,7 +237,7 @@ static inline void link_file_to_changed(SEC_LINK *next)
#endif
#ifndef DBUG_OFF
-static void test_key_cache(char *where, my_bool lock);
+static void test_key_cache(const char *where, my_bool lock);
#endif
@@ -622,9 +622,10 @@ int flush_key_blocks(File file, enum flush_type type)
/* Test if disk-cachee is ok */
-static void test_key_cache(char *where, my_bool lock)
+static void test_key_cache(const char *where, my_bool lock)
{
- reg1 uint i,found,error,changed;
+ reg1 uint i,error;
+ ulong found,changed;
SEC_LINK *pos,**prev;
if (lock)
@@ -642,13 +643,13 @@ static void test_key_cache(char *where, my_bool lock)
error=1;
DBUG_PRINT("error",
("hash: %d pos: %lx : prev: %lx != pos->prev: %lx",
- i,pos,prev,pos->prev_hash));
+ i,(ulong) pos,(ulong) prev,(ulong) pos->prev_hash));
}
if (((pos->diskpos/KEYCACHE_BLOCK_SIZE)+pos->file) % _my_hash_blocks != i)
{
DBUG_PRINT("error",("hash: %d pos: %lx : Wrong disk_buffer %ld",
- i,pos,pos->diskpos));
+ i,(ulong) pos,(ulong) pos->diskpos));
error=1;
}
}
@@ -667,7 +668,7 @@ static void test_key_cache(char *where, my_bool lock)
pos= _my_hash_root[i]; found=0;
while (pos && found < 10)
{
- DBUG_PRINT("loop",("pos: %lx prev: %lx next: %lx file: %d disk_buffer: %ld", pos,pos->prev_hash,pos->next_hash,pos->file,pos->diskpos));
+ DBUG_PRINT("loop",("pos: %lx prev: %lx next: %lx file: %d disk_buffer: %ld", (ulong) pos, (ulong) pos->prev_hash, (ulong) pos->next_hash, (ulong) pos->file, (ulong) pos->diskpos));
found++; pos= pos->next_hash;
}
}
@@ -685,7 +686,9 @@ static void test_key_cache(char *where, my_bool lock)
if (pos->next_used->prev_used != pos)
{
DBUG_PRINT("error",("pos: %lx next_used: %lx next_used->prev: %lx",
- pos,pos->next_used,pos->next_used->prev_hash));
+ (ulong) pos,
+ (ulong) pos->next_used,
+ (ulong) pos->next_used->prev_hash));
error=1;
}
pos=pos->next_used;
@@ -696,7 +699,7 @@ static void test_key_cache(char *where, my_bool lock)
}
if (found != _my_blocks_used)
{
- DBUG_PRINT("error",("Found %d of %d keyblocks",found,_my_blocks_used));
+ DBUG_PRINT("error",("Found %lu of %lu keyblocks",found,_my_blocks_used));
error=1;
}
@@ -751,7 +754,7 @@ static void test_key_cache(char *where, my_bool lock)
}
if (changed != 0)
{
- DBUG_PRINT("error",("Found %d blocks that wasn't in changed blocks",
+ DBUG_PRINT("error",("Found %lu blocks that wasn't in changed blocks",
changed));
error=1;
}
diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh
index bf857c67cea..346ceb55d73 100644
--- a/scripts/mysqlhotcopy.sh
+++ b/scripts/mysqlhotcopy.sh
@@ -36,7 +36,7 @@ WARNING: THIS IS VERY MUCH A FIRST-CUT ALPHA. Comments/patches welcome.
# Documentation continued at end of file
-my $VERSION = "1.10";
+my $VERSION = "1.11";
my $opt_tmpdir = $ENV{TMPDIR} || "/tmp";
@@ -65,6 +65,8 @@ Usage: $0 db_name [new_db_name | directory]
--suffix=# suffix for names of copied databases
--checkpoint=# insert checkpoint entry into specified db.table
--flushlog flush logs once all tables are locked
+ --resetmaster reset the binlog once all tables are locked
+ --resetslave reset the master.info once all tables are locked
--tmpdir=# temporary directory (instead of $opt_tmpdir)
Try 'perldoc $0 for more complete documentation'
@@ -100,6 +102,8 @@ GetOptions( \%opt,
"suffix=s",
"checkpoint=s",
"flushlog",
+ "resetmaster",
+ "resetslave",
"tmpdir|t=s",
"dryrun|n",
) or usage("Invalid option");
@@ -369,6 +373,8 @@ if ( $opt{dryrun} ) {
print "LOCK TABLES $hc_locks\n";
print "FLUSH TABLES /*!32323 $hc_tables */\n";
print "FLUSH LOGS\n" if ( $opt{flushlog} );
+ print "RESET MASTER\n" if ( $opt{resetmaster} );
+ print "RESET SLAVE\n" if ( $opt{resetslave} );
}
else {
my $start = time;
@@ -381,6 +387,8 @@ else {
$dbh->do("FLUSH TABLES /*!32323 $hc_tables */");
printf "Flushed tables ($hc_tables) in %d seconds.\n", time-$start unless $opt{quiet};
$dbh->do( "FLUSH LOGS" ) if ( $opt{flushlog} );
+ $dbh->do( "RESET MASTER" ) if ( $opt{resetmaster} );
+ $dbh->do( "RESET SLAVE" ) if ( $opt{resetslave} );
}
my @failed = ();
@@ -658,6 +666,18 @@ of keeping the backup directory after the copy successfully completes.
Rotate the log files by executing "FLUSH LOGS" after all tables are
locked, and before they are copied.
+=item --resetmaster
+
+Reset the bin-log by executing "RESET MASTER" after all tables are
+locked, and before they are copied. Usefull if you are recovering a
+slave in a replication setup.
+
+=item --resetslave
+
+Reset the master.info by executing "RESET SLAVE" after all tables are
+locked, and before they are copied. Usefull if you are recovering a
+server in a mutual replication setup.
+
=item --regexp pattern
Copy all databases with names matching the pattern
@@ -742,6 +762,7 @@ Study the code inside this script and only rely on it if I<you> believe
that it does the right thing for you.
Patches adding bug fixes, documentation and new features are welcome.
+Please send these to internals@mysql.com.
=head1 TO DO
@@ -780,3 +801,6 @@ Monty - working --noindex (copy only first 2048 bytes of index file)
Fixes for --method=scp
Ask Bjoern Hansen - Cleanup code to fix a few bugs and enable -w again.
+
+Emil S. Hansen - Added resetslave and resetmaster.
+
diff --git a/sql-bench/bench-init.pl.sh b/sql-bench/bench-init.pl.sh
index 165b15a0ede..c316bae1e4d 100644
--- a/sql-bench/bench-init.pl.sh
+++ b/sql-bench/bench-init.pl.sh
@@ -152,8 +152,9 @@ sub merge_limits
{
foreach $name (split(",",$cmp))
{
- $tmp_server= get_server($name,$opt_host, $opt_database,
- $opt_odbc) || die "Unknown SQL server: $name\n";
+ $tmp_server= (get_server($name,$opt_host, $opt_database,
+ $opt_odbc,machine_part())
+ || die "Unknown SQL server: $name\n");
$limits=$tmp_server->{'limits'};
%new_limits=();
foreach $limit (keys(%$limits))
@@ -365,11 +366,13 @@ sub print_time
sub machine_part
{
- my ($name);
+ my ($name,$orig);
return $opt_machine if (length($opt_machine)); # Specified by user
- $name=machine();
- $name="win9$1" if ($name =~ /win.*9(\d)/i);
- $name="NT_$1" if ($name =~ /Windows NT.*(\d+\.\d+)/i);
+# Specified by user
+ $orig=$name=machine();
+ $name="win9$1" if ($orig =~ /win.*9(\d)/i);
+ $name="NT_$1" if ($orig =~ /Windows NT.*(\d+\.\d+)/i);
+ $name="win2k" if ($orig =~ /Windows 2000/i);
$name =~ s/\s+/_/g; # Make the filenames easier to parse
$name =~ s/-/_/g;
$name =~ s/\//_/g;
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: