Commit 6257ee76 authored by unknown's avatar unknown

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
parent d1782bea
jani@hynda.mysql.fi
heikki@donna.mysql.fi
monty@donna.mysql.fi
paul@central.snake.net
monty@tik.mysql.fi
......@@ -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
......@@ -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
......
......@@ -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:
......
......@@ -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;
......
......@@ -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;
......
......@@ -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 ()
......
......@@ -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;
}
......
......@@ -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.
......@@ -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;
......
......@@ -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()
{
......
......@@ -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 @@ class handler :public Sql_alloc
/* 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);
......@@ -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;
......
......@@ -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},
......
......@@ -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;
......
......@@ -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;
......
......@@ -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()
......
......@@ -268,7 +268,8 @@ class THD :public ilink {
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;
......
......@@ -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;
......
......@@ -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
......
......@@ -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)
......
......@@ -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:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment