Beta Draft: 2016-08-16

Chapter 8 Statement Execution

Table of Contents

8.1 Transaction Handling
8.1.1 Processing Warnings
8.2 Error Handling

This section explains statement execution, with information on how to handle transactions and errors.

8.1 Transaction Handling

Transactions can be used to group operations into an atomic unit. Either all operations of a transaction succeed when they are committed, or none. It is possible to roll back a transaction as long as it has not been committed.

Transactions can be started in a session using the startTransaction() method, committed with commitTransaction() and cancelled or rolled back with rollbackTransaction(). This is illustrated in the following example. The example assumes that the test schema exists and that the collection my_collection does not exist.

MySQL Shell JavaScript Code

var mysqlx = require('mysqlx').mysqlx;

// Connect to server
var session = mysqlx.getSession( {
  host: 'localhost', port: 33060,
  dbUser: 'mike', dbPassword: 's3cr3t!' } );

// Get the Schema test
var db = session.getSchema('test');

// Create a new collection
var myColl = db.createCollection('my_collection');

// Start a transaction
session.startTransaction();
try {
  myColl.add({name: 'Jack', age: 15, height: 1.76, weight: 69.4}).execute();
  myColl.add({name: 'Susanne', age: 24, height: 1.65}).execute();
  myColl.add({name: 'Mike', age: 39, height: 1.9, weight: 74.3}).execute();

  // Commit the transaction if everything went well
  session.commit();

  print('Data inserted successfully.');
}
catch (err) {
  // Rollback the transaction in case of an error
  session.rollback();

  // Printing the error message
  print('Data could not be inserted: ' + err.message);
}

MySQL Shell Python Code

import mysqlx

# Connect to server
session = mysqlx.getSession( {
        'host': 'localhost', 'port': 33060,
        'dbUser': 'mike', 'dbPassword': 's3cr3t!' } )

# Get the Schema test
db = session.getSchema('test')

# Create a new collection
myColl = db.createCollection('my_collection')

# Start a transaction
session.startTransaction()
try:
        myColl.add({'name': 'Jack', 'age': 15, 'height': 1.76, 'weight': 69.4}).execute()
        myColl.add({'name': 'Susanne', 'age': 24, 'height': 1.65}).execute()
        myColl.add({'name': 'Mike', 'age': 39, 'height': 1.9, 'weight': 74.3}).execute()

        # Commit the transaction if everything went well
        session.commit()

        print 'Data inserted successfully.'
except Exception, err:
        # Rollback the transaction in case of an error
        session.rollback()

        # Printing the error message
        print 'Data could not be inserted: %s' % str(err)

C# Code

{
  // Connect to server
  var session = MySQLX.GetSession("server=localhost;port=33060;user=mike;password=s3cr3t!;");

  // Get the Schema test
  var db = session.GetSchema("test");

  // Create a new collection
  var myColl = db.CreateCollection("my_collection");

  // Start a transaction
  session.StartTransaction();
  try
  {
	myColl.Add(new { name = "Jack", age = 15, height = 1.76, weight = 69.4}).Execute();
	myColl.Add(new { name = "Susanne", age = 24, height = 1.65}).Execute();
	myColl.Add(new { name = "Mike", age = 39, height = 1.9, weight = 74.3}).Execute();

	// Commit the transaction if everything went well
	session.Commit();

	Console.WriteLine("Data inserted successfully.");
  }
  catch(Exception err)
  {
	// Rollback the transaction in case of an error
	session.Rollback();

	// Printing the error message
	Console.WriteLine("Data could not be inserted: " + err.Message);
  }
}

Java Code

import com.mysql.cj.api.x.*;
import com.mysql.cj.x.MysqlxSessionFactory;

// Connect to server
String url = "mysqlx://localhost:33060/test?user=mike&password=s3cr3t!"
XSession session = new MysqlxSessionFactory().getSession(url);

Schema db = session.getSchema("test");

// Create a new collection
Collection myColl = db.createCollection("my_collection");

// Start a transaction
session.startTransaction();
try {
  List<String> jsonStrings = Arrays.asList(
    "{\\"name\\":\\"Jack\\", \\"age\\":15}",
    "{\\"name\\":\\"Susanne\\", \\"age\\":24}",
    "{\\"name\\":\\"Mike\\", \\"age\\":39}");
  myColl.add(jsonStrings);

  session.commit();
  System.out.println('Data inserted successfully.');
} catch (Exception err) {
  // Rollback the transaction in case of an error
  session.rollback();

  // Printing the error message
  System.out.println("Data could not be inserted: " + err.getMessage());
}

C++ Code

// Transaction support not yet implemented in Connector/C++

8.1.1 Processing Warnings

Similar to the execution of single statements committing or rolling back a transaction can also trigger warnings. To be able to process these warnings the replied result object of Session.commit(); or Session.rollback(); needs to be checked.

This is shown in the following example. The example assumes that the test schema exists and that the collection my_collection does not exist.

MySQL Shell JavaScript Code

var mysqlx = require('mysqlx').mysqlx;

// Connect to server
var mySession = mysqlx.getSession( {
        host: 'localhost', port: 33060,
        dbUser: 'mike', dbPassword: 's3cr3t!' } );

// Get the Schema test
var myDb = mySession.getSchema('test');

// Create a new collection
var myColl = myDb.createCollection('my_collection');

// Start a transaction
mySession.startTransaction();
try
{
    myColl.add({'name': 'Jack', 'age': 15, 'height': 1.76, 'weight': 69.4}).execute();
    myColl.add({'name': 'Susanne', 'age': 24, 'height': 1.65}).execute();
    myColl.add({'name': 'Mike', 'age': 39, 'height': 1.9, 'weight': 74.3}).execute();

    // Commit the transaction if everything went well
    var reply = mySession.commit();

    // handle warnings
    if (reply.warningCount){
      var warnings = reply.getWarnings();
      for (index in warnings){
        var warning = warnings[index];
        print ('Type ['+ warning.Level + '] (Code ' + warning.Code + '): ' + warning.Message + '\n');
      }
    }

    print ('Data inserted successfully.');
}
catch(err)
{
    // Rollback the transaction in case of an error
    reply = mySession.rollback();

    // handle warnings
    if (reply.warningCount){
      var warnings = reply.getWarnings();
      for (index in warnings){
        var warning = warnings[index];
        print ('Type ['+ warning.Level + '] (Code ' + warning.Code + '): ' + warning.Message + '\n');
      }
    }

    // Printing the error message
    print ('Data could not be inserted: ' + err.message);
}

MySQL Shell Python Code

import mysqlx

# Connect to server
mySession = mysqlx.getSession( {
        'host': 'localhost', 'port': 33060,
        'dbUser': 'mike', 'dbPassword': 's3cr3t!' } )

# Get the Schema test
myDb = mySession.getSchema('test')

# Create a new collection
myColl = myDb.createCollection('my_collection')

# Start a transaction
mySession.startTransaction()
try:
    myColl.add({'name': 'Jack', 'age': 15, 'height': 1.76, 'weight': 69.4}).execute()
    myColl.add({'name': 'Susanne', 'age': 24, 'height': 1.65}).execute()
    myColl.add({'name': 'Mike', 'age': 39, 'height': 1.9, 'weight': 74.3}).execute()

    # Commit the transaction if everything went well
    reply = mySession.commit()

    # handle warnings
    if reply.warningCount:
      for warning in result.getWarnings():
        print 'Type [%s] (Code %s): %s\n' % (warning.Level, warning.Code, warning.Message)

    print 'Data inserted successfully.'
except Exception, err:
    # Rollback the transaction in case of an error
    reply = mySession.rollback()

    # handle warnings
    if reply.warningCount:
      for warning in result.getWarnings():
        print 'Type [%s] (Code %s): %s\n' % (warning.Level, warning.Code, warning.Message)

    # Printing the error message
    print 'Data could not be inserted: %s' % str(err)

C# Code

{
  // Connect to server
  var session = MySqlX.GetSession("server=localhost;port=33060;user=mike;password=s3cr3t!;");

  // Get the Schema test
  var db = session.GetSchema("test");

  // Create a new collection
  var myColl = db.CreateCollection("my_collection");

  // Start a transaction
  session.StartTransaction();
  int warningCount = 0;
  try
  {
	var result = myColl.Add(new { name = "Jack", age = 15, height = 1.76, weight = 69.4}).Execute();
	warningCount += result.Warnings.Count;
	result = myColl.Add(new { name = "Susanne", age = 24, height = 1.65}).Execute();
	warningCount += result.Warnings.Count;
	result = myColl.Add(new { name = "Mike", age = 39, height = 1.9, weight = 74.3}).Execute();
	warningCount += result.Warnings.Count;

	// Commit the transaction if everything went well
	session.Commit();
	if(warningCount > 0)
	{
	  // handle warnings
	}

	Console.WriteLine("Data inserted successfully.");
  }
  catch (Exception err)
  {
	// Rollback the transaction in case of an error
	session.Rollback();
	if(warningCount > 0)
	{
	  // handle warnings
	}

	// Printing the error message
	Console.WriteLine("Data could not be inserted: " + err.Message);
  }
}

Java Code

// c.f. "standard transaction handling"

C++ Code

// Transaction support not yet implemented in Connector/C++

By default all warnings are sent from the server to the client. If an operation is known to generate many warnings and the warnings are of no value to the application then sending the warnings can be suppressed. This helps to save bandwith. Session.setFetchWarnings() controls whether warnings are discarded at the server or are sent to the client. Session.getFetchWarnings() is used to learn the currently active setting.

MySQL Shell JavaScript Code

var mysqlx = require('mysqlx').mysqlx;

function process_warnings(result){
  if (result.getWarningCount()){
    var warnings = result.getWarnings();
    for (index in warnings){
      var warning = warnings[index];
      print ('Type ['+ warning.Level + '] (Code ' + warning.Code + '): ' + warning.Message + '\n');
    }
  }
  else{
    print ("No warnings were returned.\n");
  }
}

// Connect to server
var mySession = mysqlx.getNodeSession( {
  host: 'localhost', port: 33060,
  dbUser: 'mike', dbPassword: 's3cr3t!' } );

// Disables warning generation
mySession.setFetchWarnings(false);
var result = mySession.sql('drop schema if exists unexisting').execute();
process_warnings(result);

// Enables warning generation
mySession.setFetchWarnings(true);
var result = mySession.sql('drop schema if exists unexisting').execute();
process_warnings(result);

MySQL Shell Python Code

import mysqlx

def process_warnings(result):
  if result.getWarningCount():
    for warning in result.getWarnings():
      print 'Type [%s] (Code %s): %s\n' % (warning.Level, warning.Code, warning.Message)
  else:
    print "No warnings were returned.\n"


# Connect to server
mySession = mysqlx.getNodeSession( {
  'host': 'localhost', 'port': 33060,
  'dbUser': 'mike', 'dbPassword': 's3cr3t!' } );

# Disables warning generation
mySession.setFetchWarnings(False)
result = mySession.sql('drop schema if exists unexisting').execute()
process_warnings(result)

# Enables warning generation
mySession.setFetchWarnings(True)
result = mySession.sql('drop schema if exists unexisting').execute()
process_warnings(result)

Node.js JavaScript Code

C# Code

{
  // Assumptions: test schema exists, my_collection exists

  XSession mySession = null;
  try
  {
	// Connect to server on localhost
	mySession = MySQLX.GetSession("server=localhost;port=33060;user=mike;password=s3cr3t!;");
  }
  catch (Exception err)
  {
	Console.WriteLine("The database session could not be opened: " + err.Message);
	throw;
  }

  try
  {
	var myDb = mySession.GetSchema("test");

	// Use the collection "my_collection"
	var myColl = myDb.GetCollection("my_collection");

	// Find a document
	var myDoc = myColl.Find("name like :param").Limit(1)
	  .Bind("param", "S%").Execute();

	// Print document
	PrintResult(myDoc.FetchOne());
  }
  catch (Exception err)
  {
	Console.WriteLine("The following error occurred: " + err.Message);
  }
  finally
  {
	// Close the session in any case
	mySession.Close();
  }
}

Java Code

C++ Code

// getWarnings() not yet implemented in Connector/C++

8.2 Error Handling

When writing scripts for MySQL Shell you can often simply rely on the exception handling done by MySQL Shell. For all other languages either proper exception handling is required to catch errors or the traditional error handling pattern needs to be used if the language does not support exceptions.

The default error handling can be changed by creating a custom SessionContext and passing it to the mysqlx.getSession() function. This enables switching from exceptions to result based error checking.

The following examples show how to perform proper error handling for the various languages. The example assumes that the test schema exists and that the collection my_collection exists.

MySQL Shell JavaScript Code

var mysqlx = require('mysqlx').mysqlx;

var mySession;

try {
  // Connect to server on localhost
  mySession = mysqlx.getSession( {
    host: 'localhost', port: 33060,
    dbUser: 'mike', dbPassword: 's3cr3t!' } );
}
catch (err) {
  print('The database session could not be opened: ' + err.message);
}

try {
  var myDb = mySession.getSchema('test');

  // Use the collection 'my_collection'
  var myColl = myDb.getCollection('my_collection');

  // Find a document
  var myDoc = myColl.find('name like :param').limit(1)
    .bind('param','S%').execute();

  // Print document
  print(myDoc.first());
}
catch (err) {
  print('The following error occurred: ' + err.message);
}
finally {
  // Close the session in any case
  mySession.close();
}

MySQL Shell Python Code

import mysqlx

mySession

try:
        # Connect to server on localhost
        mySession = mysqlx.getSession( {
                'host': 'localhost', 'port': 33060,
                'dbUser': 'mike', 'dbPassword': 's3cr3t!' } )

except Exception, err:
        print 'The database session could not be opened: %s' % str(err)

try:
        myDb = mySession.getSchema('test')

        # Use the collection 'my_collection'
        myColl = myDb.getCollection('my_collection')

        # Find a document
        myDoc = myColl.find('name like :param').limit(1).bind('param','S%').execute()

        # Print document
        print myDoc.first()
except Exception, err:
        print 'The following error occurred: %s' % str(err)
finally:
        # Close the session in any case
        mySession.close()

Node.js JavaScript Code

var mysqlx = require('mysqlx').mysqlx;

// Connect to server on localhost
mysqlx.getSession( {
    host: 'localhost', port: 33060,
    dbUser: 'mike', dbPassword: 's3cr3t!'
}).then(function (mySession) {
  // This can't throw an error as we check existence at a later operation only
  var myDb = mySession.getSchema('test');

  // Use the collection 'my_collection'
  // This can't throw an error as we check existence at a later operation only
  var myColl = myDb.getCollection('my_collection');

  // Find a document
  myColl.find('name like :param').limit(1)
  .bind('param','S%').execute(function (row) {
    console.log(row);
  }).catch(function (err) {
    print('The following error occurred: ' + err.message);
  });

  session.close();
}).catch (err) {
  console.log('The database session could not be opened: ' + err.message);
});

C# Code

Java Code

import com.mysql.cj.api.x.*;
import com.mysql.cj.x.MysqlxSessionFactory;

XSession mySession;

try {
  // Connect to server on localhost
  String url = "mysqlx://localhost:33060/test?user=mike&password=s3cr3t!"
  mySession = new MysqlxSessionFactory().getSession(url);
} catch (Exception err) {
  System.err.println("The database session could not be opened: " + err.getMessage());
}

try {
  Schema myDb = mySession.getSchema("test");

  // Use the collection 'my_collection'
  Collection myColl = myDb.getCollection("my_collection");

  // Find a document
  DocResult myDoc = myColl.find("name like :param").limit(1)
    .bind("param", "S%").execute();

  // Print document
  System.out.println(myDoc.fetchOne());
} catch (MysqlxError err) { // special exception class for server errors
  System.err.println("The following error occurred: " + err.getMessage());
} finally {
  // Close the session in any case
  mySession.close();
}

C++ Code

#include <mysqlx.h>

try
{
  // Connect to server on localhost
  XSession session(33060, "mike", "s3cr3t!");

  try
  {
    Schema db = session.getSchema("test");

    // Use the collection 'my_collection'
    Collection myColl = db.getCollection("my_collection");

    // Find a document
    auto myDoc = myColl.find("name like :param").limit(1)
                       .bind("param", "S%").execute();

    // Print document
    cout << myDoc.fetchOne() << endl;

    // Exit with success code
    exit(0);
  }
  catch (Error &err)
  {
    cout <<"The following error occurred: " <<err <<endl;
    exit(1);
  }

  // Note: session is closed automatically when session object
  // is destructed.

}
catch (Error &err)
{
  cout <<"The database session could not be opened: " <<err <<endl;

  // Exit with error code
  exit(1);
}