ConcurrentTestCommand represents a command, sequentially executed by
Used to extend functionality of mtsql.
ConcurrentTestCommandGenerator creates instances of
abstract base to handle SQLExceptions
Describes a thread that failed
ConcurrentTestCommandScript creates instances of
Used to extend functionality of mtsql.
Sample mtsql plugin.
Indicates that a command should have failed, but instead succeeded, which is a test error
ConcurrentCommandGenerator provides a Java API for
constructing concurrent JDBC tests: an instance of the class represents a
test case, which contains several sequences of SQL commands (abstracted as
ConcurrentCommand). Each sequence is run in its
own thread as a separate jdbc client (ie a separate
java.sql.Connection). There are facilties to synchronize these
command threads. Only a simple command sequence is supported: no branching,
An alternative is to define a test by writing a test script in
mtsql format, as described below. An instance of
ConcurrentCommandScript parses and executes a script.
The syntactic structure of an mtsql script is:
<directive>* <setup section>? <cleanup section>? <thread section>+ <directive> := @[no]lockstep | @enable | @disable <setup section> := @setup <basic command>* @end <cleanup section> := @setup <basic command>* @end <thread section> := @thread <thread-name>? <command>* @end <command> := <basic command> | <command prefix>? <threadly command> | <synchronization point>
Blank lines and comments are allowed anywhere. A comment starts with two hyphens and runs to the end of the line. Command names start with an '@'. Some commands run to the end of the line; but a command that contains SQL can span lines and ends with a semicolon.
Running a section means running its commands in sequence. First the setup section (if any) is run. Next all the thread sections are run at once, each in its own thread. When all these threads complete, the cleanup section (if any) is run.
The threads are synchronized by inserting synchronization points (@sync).
When a thread reaches a @sync, it waits until all threads are waiting on the same @sync: then all threads proceed. @sync points have no names. Clearly all thread sections must contain the same number of @sync points.
The directive @lockstep has the same effect as adding a @sync after each command in every thread section. Clearly it requires that all thread sections have the same number of commands. The default is the antonym @nolockstep.
The directive @disable means "skip this script". The deault is the antonym @enable.
When a sql command fails, the rest of its section is skipped. However, if
the attribute force is true the error is ignored, and the section
continues. force has an independent value in each section. Within a
section it can be toggled using the sql directive
val, where val can be true, false, on, off. (This
is modelled after sqlline and sqllineClient. Other sqlline
!-directives are ignored.)
An error in a thread section will stop that thread, but the other threads continue (with one fewer partner to synchronize with), and finally the cleanup section runs. If the setup section quits, then only the cleanup section is run.
<SQL statement>: An SQL statement terminated by a semicolon. The statement can span lines.
@include FILE Reads and executes the contents of FILE, another mtsql script. Inclusions may nest.
@sleep N -- thread sleeps for N milliseconds @echo MESSAGE -- prints the message to stdout <SQL statement> ';' -- executes the SQL @timeout N <SQL> ';' -- executes the SQL with the given ms timeout @rowlimit N <SQL> ';' -- executes the SQL, stops after N rows @err <SQL> ';' -- executes the SQL, expecting it to fail @repeat N <command>+ @end Denotes a repeated block of commands, with repeat count = N. N must be positive. @prepare SQL-STATEMENT ';' Prepares the sql. A thread has at most one prepared statement at a time. @print FORMAT Sets the result-printing format for the current prepared statement. FORMAT is a sequence of the phrases: none -- means print nothing all -- means print all rows (the default) every N -- means print the rows 0, N, 2N, etc. count -- means print row number (starts with 0). time -- means print the time each printed row was fetched total -- means print a final summary, with row count and net fetch time (not including any timeout). (Sorry, no way yet to print selected columns, to print time in a special way, etc.) @fetch <timeout>? Starts fetching and printing result rows, with an optional timeout (in msecs). Stop on EOD or on timeout. @close Closes the current prepared statement. However that an open prepared statement will be closed automatically at the end of its thread. @shell <Shell Command> Runs the command in a spawned subshell, proceeds after it concludes, but quits if it fails. For @shell and @echo, the command or message runs to the end of the line in the script, but can be continued if the line ends with a single '\'.
Needed mainly to pass arguments to the command of @shell, but also useful to parameterize SQL statements, timeout values etc.
@var VAR Declares a variable VAR @var VAR1 VAR2 ... VARn Declares n variables.
The initial value of a script variable VAR is taken from the shell environment variable of the same name. The value can be set to a different value when the script is run, by employing a phrase VAR=VALUE on the mtsql command line.
A command-line tool that runs an mtsql script against a specified JDBC connection,a nd prints the query results. (But see @print command to filter the output.)
Usage: mtsql [-qvg] -u SERVER -d DRIVER [-n USER] [-p PASSWORD]
[VAR=VALUE]* SCRIPT [SCRIPT]*
Flags: -q : (quiet) do not print results.
-v : (verbose) trace as script is parsed.
-g : (debug) print command lists before starting the threads
-u SERVER : sets the target; a JDBC URL.
-d DRIVER : sets the jdbc driver; a class on the classpath
VAR=VALUE : binds the script variable VAR to the VALUE; VAR must be declared at the beginning of the script(s) in a @var command.
-- redundant: @nolockstep -- Two threads reading the same data. @thread 1,2 -- pre execute the SQL to prime the pumps @timeout 1000 select * from sales.bids; @prepare select * from sales.bids; -- rendezvous with writer thread @sync @fetch 15000 @sync @close @end @thread writer -- rendezvous with reader threads @sync @sleep 5000 insert into sales.bids values(1, 'ORCL', 100, 12.34, 10000, 'Oracle at 12.34'); commit; insert into sales.bids values(2, 'MSFT', 101, 23.45, 20000, 'Microsoft at 23.45'); commit; -- real test has more inserts here @sync @end
The output from each thread is stored in a temporary file until
the test completes. At that point, the files are merged together
into a single
.log file containing the results of each
thread, in the order the threads were defined. The output for the
example script looks like:
-- thread 1 > select * from sales.bids; +---------+------------+ | DEPTNO | NAME | +---------+------------+ | 10 | Sales | | 20 | Marketing | | 30 | Accounts | +---------+------------+ > > select * from sales.bids; +---------+------------+ | DEPTNO | NAME | +---------+------------+ | 10 | Sales | | 20 | Marketing | | 30 | Accounts | +---------+------------+ -- end of thread 1 -- thread 2 > select * from sales.bids; +---------+------------+ | DEPTNO | NAME | +---------+------------+ | 10 | Sales | | 20 | Marketing | | 30 | Accounts | +---------+------------+ > > select * from sales.bids; +---------+------------+ | DEPTNO | NAME | +---------+------------+ | 10 | Sales | | 20 | Marketing | | 30 | Accounts | +---------+------------+ -- end of thread 2 -- thread writer > insert into sales.bids > values(1, 'ORCL', 100, 12.34, 10000, 'Oracle at 12.34'); 1 row affected. > commit; > insert into sales.bids > values(2, 'MSFT', 101, 23.45, 20000, 'Microsoft at 23.45'); 1 row affected. > commit; -- end of thread writer
(Yes the results of the select statements are obviously wrong.)
Copyright © 2012–2018 The Apache Software Foundation. All rights reserved.