                                   [Image]
                       A Java Class Library for mSQL
----------------------------------------------------------------------------
                            An MsqlJava Tutorial
                                 Draft Only
----------------------------------------------------------------------------
Prerequisites

Before you are able to use the MsqlJava package, you must of course have
access to an mSQL server. If you do not already have a copy of mSQL, you can
obtain one from ftp://kirk.bond.edu.au/pub/Minerva/msql. You should also
consult the mSQL FAQ for a description of mSQL, details of supported
platforms and information about the mSQL mailing list.

If you are planning on using MsqlJava in applets that will be browsed with
Netscape Navigator 2.0, you will also need to ensure that the mSQL server is
running on the same machine as the http server that will supply the applet
to the browser. This is because Netscape 2.0 and Netscape Gold impose a
security restriction on the destination of socket connections to and from
applets. No such restrictions need apply if you are developing applications
or using a browser with a different SecurityManager.

----------------------------------------------------------------------------
Establishing a connection to the server - the Msql class

Communication between the client and the mSQL server occurs over a tcp
connection to either port 1112 (if the server is running as root) or port
4333 (otherwise). Within the MsqlJava package, this communication channel is
established and managed using the Msql class as follows.

To establish a connection to the server first instantiate an Msql object:

                // Instantiate an Msql object
                Msql msql = new Msql();

Then use one of the four versions of the Connect method to initiate
communication and identify the client to the server. The first version of
Connect takes only one argument, the name of the host running the mSQL
server. It assumes that the destination port is the root port (1112).

                // Connect to the server using the root port (1112)
                try {
                        msql.Connect("mama.minmet.uq.oz.au");
                } catch(MsqlException e) {
                }

Note that the Connect method can throw an MsqlException if the connection
fails for any reason. All(?) exceptions possible during the connection
process are caught within the Connect method and re-issued as
MsqlExceptions. The idea behind this was to reduce the amount of code needed
in the client to deal with exceptions. This seemed like a good idea at the
time but as I will discuss later when dealing with Exception handling it is
something that needs refinement. Nevertheless, you need to catch
MsqlExceptions that provide indication that the Connection did not succeed.

The second variant of the Connect method can be used to connect to mSQL
daemons that are not running as root. Ths method accepts two arguments, the
name of the host and a boolean which takes the value true if the connection
is to the root port, false otherwise.

                // Connect to the server using the mortal port (4333)
                try {
                        msql.Connect("mama.minmet.uq.oz.au", false);
                } catch(MsqlException e) {
                }

The two remaining variants of the Connect method are the same as those above
but with the addition of an extra parameter, username, for reasons discussed
below.

Several things occur as part of the Connect method. First a socket is opened
to the destination host and port. This can give rise to UnknownHost,
UnknownService, Protocol, Socket and Security Exceptions which at the moment
are re-issued as MsqlExceptions containing the same error string as the
original Exception.

Next a string indicating the version of the server is received by the
client. This can give rise to an IOException which once again is re-issued
as an MsqlException.

The client then attempts to determine the name of the user of the client
machine. In fact, with the current version of MsqlJava, this functionality
is disabled and the client assumes the name 'nobody' instead. This is
because Netscape Navigator 2.0 throws a SecurityException (properties) if
the user name is queried. This is why I have introduced the two new versions
of the above Connect methods which allow you to set a value of the username
which is suited to your purpose.

The user name is then sent to the server for it to use when determining
access restrictions using the mSQL Access Control List. IOExceptions can
arise from this process. Again, these are re-issued as MsqlExceptions.

The client then receives a status string from the server indicating whether
the user was granted access ot not. Once again IOExceptions can be thrown as
a result of this procedure (although as before they are re-issued as
MsqlExceptions). If the user is denied access for any reason, an
MsqlException is thrown.

Assuming no exceptions ar thrown, the connection is establish at this point
and ready for use.

----------------------------------------------------------------------------
Closing the connection

Closing the connection is simple:

                // Close the connection
                try {
                        msql.Close();
                } catch(MsqlException e) {
                }

All the previously discussed Exceptions can be thrown.

----------------------------------------------------------------------------
Selecting a database

Anyone familiar with previoud versions of MsqlJava will notice that the
methods in the next two sections have been simplified in this version of the
library. To provide some degree of back compatibility, I have provided new
methods _ListDBs, _ListTables and _ListFields which have the same syntax and
semantics as previous versions of the functions below.

A list of databases available on a server can be obtained using the ListDBs
method of the Msql class.

                // Request a list of available databases
                try {
                        String database[] = msql.ListDBs();
                } catch(MsqlException e) {
                }

Once the database of interest has been identified, it must be selected
before it can be used.

                // Select the database
                try {
                        msql.SelectDB(database[3]);
                } catch(MsqlException e) {
                }

----------------------------------------------------------------------------
Inspecting the schema

It is often desirable to be able to find out details of the schema of the
selected database. This can be done using the ListTables and ListFields
methods of the Msql class.

To get a list is tables available in the currently selected database:

                // Request a list of available tables
                try {
                        String table[] = msql.ListTables();
                } catch(MsqlException e) {
                }

To get details of the structure of a particular table, use the ListFields
method.

                try {
                        MsqlFieldDesc field[] = msql.ListFields(table[2]);
                } catch(MsqlException e) {
                }

This method returns an array of MsqlFieldDesc objects, each of which
describes the field name (including the name of the base table from which it
derives), field type, field length and flags indicating whether the field is
a key, and whether it is allowed to contain NULL values.

Information regarding a field can be determined using the following
MsqlFieldDesc methods.

                String tableName = field[i].TableName();
                String fieldName = field[i].FieldName();
                int fieldType = field[i].FieldType();
                int fieldLength = field[i].FieldLength();
                boolean key = field[i].IsKey();
                boolean nonnull = field[i].NonNull();

Knowing the name of a table associated with a field may not seem important
at this stage, but it is very relevant when the field is present in a table
which results from the join of other tables.
----------------------------------------------------------------------------
Performing a SELECT Query

The Msql Query method is used to issue all queries to the server. Only
SELECT queries, however, expect to receive data in response. Other queries
require only status information indicating the success or failure of the
operation.

SQL SELECT queries result in the production of a table. This table is in
general derived from the underlying base tables using methods of relational
algebra. In particular it will generally be the result of joins and
restrictions on the base tables. What does this all mean? It means that in
general, the schema of the table returned by the SELECT query is not defined
withing the conceptual schema of the database. Since knowledge of the schema
is in general necessary, details of the schema must be returned with the
table which results from the SELECT.

And this is exactly what mSQL does. In response to a SELECT query, mSQL
returns two tables, one containing the requested data, the other containing
information describing the characteristics of columns present in the first
table. In MsqlJava both pieces of information are stored in an instance of
an MsqlResult class.

With that in mind, the Query can be issued as:

                try {
                        MsqlResult result = msql.Query(
                                "select country.Name, domain.Count "+
                                "from country, domain "+
                                "where country.Domain = domain.Domain "+
                                "order by domain.Count"
                        );
                } catch(MsqlException e) {
                }

Data from the table can be fetched a row at a time by using the FetchRow
method:

                String row[];
                while((row = result.FetchRow()) != null) {
                }

Note that the data are at present returned as an array of Strings regardless
of the underlying types. It is left to the user to convert mSQL interger and
real field types to int and float/double, respectively, using Int, Float and
Double valueOf methods. I may add this functionality into the next release.

Field descriptions of this data can be obtained in a manner similar to the
Msql ListFields method described above. Note that this ListFields method is
different and a member of the MsqlResult class.

                MsqlFieldDesc field[] = result.LisFields();

Any errors are detected by catching MsqlExceptions as with other Msql
methods previously discussed.

----------------------------------------------------------------------------
Performing other Queries

Other SQL queries are performed in a similar manner, but a null value is
returned by the Query method:

                try {
                        // Please don't do this!
                        msql.Query(
                                "insert into country values ('au', 'Australia')"
                        );
                } catch(MsqlException e) {
                }

If the operation fails an MsqlException is thrown by the Query method.

----------------------------------------------------------------------------

Handling Exceptions

Well I tried to make exception handling easier by catching as many types of Exceptions as I thought necessary within the functions that make up MsqlJava and th

To start with it is probably simplest to just print out the error message contained in the MsqlException and then abort the activity which failed. For example:

                try {
                        ...
                } catch (MsqlExcpetion e) {
                        System.out.println(e.getMessage());
                        return null;
                }

This is all pretty standard.

----------------------------------------------------------------------------
Putting it all together

OK. So what does a simple MsqlJava client look like when you put it all
together? Like this.

        import java.awt.*;
        import java.lang.*;

        public class Demo extends java.applet.Applet {

                public Demo() {

                        Msql msql;
                        MsqlResult result;

                        try {
                                msql = new Msql();
                                msql.Connect(
                                        "mama.minmet.uq.oz.au",
                                        "darryl",
                                        true
                                );
                                msql.SelectDB("demo");

                                result = msql.Query(
                                        "select * from date"
                                );

                                String row[];
                                int rows = result.NumRows();
                                int cols = result.NumFields();

                                while((row = result.FetchRow()) != null) {
                                        for(int i=0; i < cols; i++)
                                                System.out.println(row[i]);
                                        System.out.println();
                                }

                                msql.Close();
                        } catch(MsqlException e) {
                                System.out.println("Oops: "+e.getMessage());
                        }
                }
        }

Try it out.

----------------------------------------------------------------------------
Where do I put the class files?

To use the MsqlJava classes with an applet on one of your home pages, place
the class files in the distribution into the same directory as the html file
which refernces the applet. This directory will also contain your own class
files. To start with, also keep your source (java) files there and compile
them in place.

Remember to set permissions on all the class files so that the httpd has
access to them. Failing to do this will result in the applet not loading.

Have fun! I hope this has helped. Please give me feedback at the address
below.

----------------------------------------------------------------------------
Inside MsqlJava

Yet to be done.

----------------------------------------------------------------------------
 Darryl Collins                   [Image]                          [Image]
 Computer Systems Manager
 Mining & Metallurgical           [Image]
 Engineering
 University of Queensland
 D.Collins@minmet.uq.oz.au
