//***************************************************************************
// (c) Copyright IBM Corp. 2007 All rights reserved.
// 
// The following sample of source code ("Sample") is owned by International 
// Business Machines Corporation or one of its subsidiaries ("IBM") and is 
// copyrighted and licensed, not sold. You may use, copy, modify, and 
// distribute the Sample in any form without payment to IBM, for the purpose of 
// assisting you in the development of your applications.
// 
// The Sample code is provided to you on an "AS IS" basis, without warranty of 
// any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR 
// IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Some jurisdictions do 
// not allow for the exclusion or limitation of implied warranties, so the above 
// limitations or exclusions may not apply to you. IBM shall not be liable for 
// any damages you suffer as a result of using, copying, modifying or 
// distributing the Sample, even if IBM has been advised of the possibility of 
// such damages.
//***************************************************************************
//
// SOURCE FILE NAME: TbUnion.java
//
// SAMPLE: How to insert through a UNION ALL view
//
// SQL Statements USED:
//         SELECT
//         CREATE TABLE
//         ALTER TABLE
//         DROP TABLE
//         CREATE VIEW
//         DROP VIEW
//         INSERT
//         DELETE
//         UPDATE
//
// Classes used from Util.java are:
//         Db
//         Data
//         JdbcException
//
//                           
// Output will vary depending on the JDBC driver connectivity used.
//***************************************************************************
//
// For more information on the sample programs, see the README file.
//
// For information on developing Java applications see the Developing Java Applications book.
//
// For information on using SQL statements, see the SQL Reference.
//
// For the latest information on programming, compiling, and running DB2
// applications, visit the DB2 Information Center at
//     http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp
//**************************************************************************/

import java.lang.*;
import java.sql.*;

class TbUnion
{
  public static void main(String argv[])
  {
    try
    {
      Db db = new Db(argv);

      System.out.println();
      System.out.println(
        "  THIS SAMPLE SHOWS HOW TO INSERT THROUGH A 'UNION ALL' VIEW.\n");

      // Connect to the 'sample' database
      db.connect();

      // Create tables Q1, Q2, Q3 and Q4 and add constraints to them.
      // Also create a view FY which is a view over the full year.
      CreateTablesAndView(db.con);

      // Insert some values directly into tables Q1, Q2, Q3 and Q4
      InsertInitialValuesInTables(db.con);

      // Demonstrate how to insert through a UNION ALL view
      InsertUsingUnionAll(db.con);

      // Modify the constraints of table Q1
      NewConstraints(db.con);

      // Attempt to insert data through a UNION ALL view where no table
      // accepts the row
      InsertWhenNoTableAcceptsIt(db.con);

      // Attempt to insert data through a UNION ALL view where more than
      // one table accepts the row
      InsertWhenMoreThanOneTableAcceptsIt(db.con);

      // Drop, recreate and reinitialize the tables and view
      DropTablesAndView(db.con);
      CreateTablesAndView(db.con);
      InsertInitialValuesInTables(db.con);
  
      // Create a new view and perform some updates through it.  This shows how
      // updates through a view with row migration affect the underlying
      // tables
      UpdateWithRowMovement(db.con);

      // Show two special cases of row migration involving tables with 
      // overlapping constraints
      UpdateWithRowMovementSpecialCase(db.con);

      // Drop tables Q1, Q2, Q3 and Q4 and the view FY
      DropTablesAndView(db.con);

      // Disconnect from the 'sample' database
      db.disconnect();
    }
    catch (Exception e)
    {
      JdbcException jdbcExc = new JdbcException(e);
      jdbcExc.handle();
    }
  } // main

  // This method create tables Q1, Q2, Q3 and Q4 and adds constraints
  // to them. It also creates a view FY which is a view over the full year.
  public static void CreateTablesAndView(Connection con)
  {
    try
    {
      System.out.println();
      System.out.println(
        "  CREATE TABLES Q1,Q2,Q3 AND Q4 BY INVOKING\n" +
        "  THE STATEMENTS:\n\n" +
        "    CREATE TABLE Q1(product_no INT, sales INT, date DATE)\n" +
        "    CREATE TABLE Q2 LIKE Q1\n" +
        "    CREATE TABLE Q3 LIKE Q1\n" +
        "    CREATE TABLE Q4 LIKE Q1\n");

      // Create tables Q1, Q2, Q3 and Q4
      Statement stmt = con.createStatement();
      stmt.execute(
        "CREATE TABLE Q1(product_no INT, sales INT, date DATE)");
      stmt.execute("CREATE TABLE Q2 LIKE Q1");
      stmt.execute("CREATE TABLE Q3 LIKE Q1");
      stmt.execute("CREATE TABLE Q4 LIKE Q1");

      System.out.println(
        "  ADD CONSTRAINTS TO TABLES Q1, Q2, Q3 AND Q4 BY INVOKING\n" +
        "  THE STATEMENTS:\n\n" +
        "    ALTER TABLE Q1 ADD CONSTRAINT Q1_CHK_DATE" + 
        " CHECK (MONTH(date) IN (1, 2, 3))\n" +
        "    ALTER TABLE Q2 ADD CONSTRAINT Q2_CHK_DATE" + 
        " CHECK (MONTH(date) IN (4, 5, 6))\n" +
        "    ALTER TABLE Q3 ADD CONSTRAINT Q3_CHK_DATE" + 
        " CHECK (MONTH(date) IN (7, 8, 9))\n" +
        "    ALTER TABLE Q4 ADD CONSTRAINT Q4_CHK_DATE" + 
        " CHECK (MONTH(date) IN (10,11,12))\n");

      // Adds constraints to tables Q1, Q2, Q3 and Q4
      stmt.execute("ALTER TABLE Q1 ADD CONSTRAINT Q1_CHK_DATE " +
                   "CHECK (MONTH(date) IN (1, 2, 3))");
      stmt.execute("ALTER TABLE Q2 ADD CONSTRAINT Q2_CHK_DATE " +
                   "CHECK (MONTH(date) IN (4, 5, 6))");
      stmt.execute("ALTER TABLE Q3 ADD CONSTRAINT Q3_CHK_DATE " +
                   "CHECK (MONTH(date) IN (7, 8, 9))");
      stmt.execute("ALTER TABLE Q4 ADD CONSTRAINT Q4_CHK_DATE " +
                   "CHECK (MONTH(date) IN (10, 11, 12))");

      System.out.println(
        "  CREATE A VIEW 'FY' BY INVOKING THE STATEMENT:\n\n" +
        "    CREATE VIEW FY AS\n" + 
        "      SELECT product_no, sales, date FROM Q1\n" +
        "      UNION ALL\n" +
        "      SELECT product_no, sales, date FROM Q2\n" +
        "      UNION ALL\n" +
        "      SELECT product_no, sales, date FROM Q3\n" +
        "      UNION ALL\n" +
        "      SELECT product_no, sales, date FROM Q4\n");

      // Create the view FY, a view over the full year.
      stmt.execute("CREATE VIEW FY AS" + 
                   "  SELECT product_no, sales, date FROM Q1" +
                   "  UNION ALL" +
                   "  SELECT product_no, sales, date FROM Q2" +
                   "  UNION ALL" +
                   "  SELECT product_no, sales, date FROM Q3" +
                   "  UNION ALL" +
                   "  SELECT product_no, sales, date FROM Q4");
      stmt.close();
      con.commit();
    }
    catch (Exception e)
    {
      JdbcException jdbcExc = new JdbcException(e, con);
      jdbcExc.handle();
    }
  }

  // This method inserts some values directly into tables Q1, Q2, Q3 and Q4
  public static void InsertInitialValuesInTables(Connection con)
  {
    try
    {
      System.out.println(
        "  INSERT INITIAL VALUES INTO TABLES Q1, Q2, Q3, Q4 BY INVOKING\n" +
        "  THE STATEMENTS:\n\n" +
        "    INSERT INTO Q1 VALUES (5, 6, '2001-01-02'),\n" +
        "                          (8, 100, '2001-02-28')\n" +
        "    INSERT INTO Q2 VALUES (3,  10, '2001-04-11'),\n" +
        "                          (5,  15, '2001-05-19')\n" +
        "    INSERT INTO Q3 VALUES (1,  12, '2001-08-27')\n" +
        "    INSERT INTO Q4 VALUES (3,  14, '2001-12-29'),\n" +
        "                          (2,  21, '2001-12-12')");

      // Insert initial values into tables Q1, Q2, Q3 and Q4
      Statement stmt = con.createStatement();
      stmt.execute("INSERT INTO Q1 VALUES (5, 6, '2001-01-02')," +
                   "   	                  (8, 100, '2001-02-28')");
      stmt.execute("INSERT INTO Q2 VALUES (3,  10, '2001-04-11')," +
                   "                      (5,  15, '2001-05-19')");
      stmt.execute("INSERT INTO Q3 VALUES (1,  12, '2001-08-27')");
      stmt.execute("INSERT INTO Q4 VALUES (3,  14, '2001-12-29')," +
                   "                      (2,  21, '2001-12-12')");

      stmt.close();

      // Display the view FY after inserting values into the tables
      DisplayData(con, "SELECT * FROM FY ORDER BY date, product_no");
      con.commit();
    }
    catch (Exception e)
    {
      JdbcException jdbcExc = new JdbcException(e, con);
      jdbcExc.handle();
    }
  }

  // This method drops tables Q1, Q2, Q3 and Q4 and the view FY
  public static void DropTablesAndView(Connection con)
  {
    try
    {
      System.out.println(
        "\n  DROP TABLES Q1,Q2,Q3,Q4 AND VIEW FY BY INVOKING\n" +
        "  THE STATEMENTS:\n\n" +
        "    DROP VIEW FY\n" +
        "    DROP TABLE Q1\n" +
        "    DROP TABLE Q2\n" +
        "    DROP TABLE Q3\n" +
	"    DROP TABLE Q4");

      Statement stmt = con.createStatement();
      stmt.execute("DROP VIEW FY");
      stmt.execute("DROP TABLE Q1");
      stmt.execute("DROP TABLE Q2");
      stmt.execute("DROP TABLE Q3");
      stmt.execute("DROP TABLE Q4");
      stmt.close();
      con.commit();
    }
    catch (Exception e)
    {
      JdbcException jdbcExc = new JdbcException(e, con);
      jdbcExc.handle();
    }
  }

  // Helper method: This method displays the results of the query
  // specified by 'querystr'
  public static void DisplayData(Connection con, String querystr)
  {
    try
    {
      Integer prod_num = new Integer(0);
      Integer sales_amt = new Integer(0);
      String sales_date = new String();

      System.out.println();
      System.out.println(
        "    " + querystr + "\n\n" +
        "    PRODUCT_NO  SALES       DATE\n" +
        "    ----------- ----------- ----------");

      Statement stmt = con.createStatement();
      ResultSet rs = stmt.executeQuery(querystr);

      while (rs.next())
      {
        prod_num = Integer.valueOf(rs.getString(1));
        sales_amt = Integer.valueOf(rs.getString(2));
        sales_date = rs.getString(3);
        
        System.out.print("    "+Data.format(prod_num, 11) +
                         " " + Data.format(sales_amt, 11) +
                         " " + Data.format(sales_date, 10));
        System.out.println();
      }
      rs.close();
      stmt.close();
    }
    catch (Exception e)
    {
      JdbcException jdbcExc = new JdbcException(e, con);
      jdbcExc.handle();
    }
  }

  // This method demonstrates how to insert through a UNION ALL view
  public static void InsertUsingUnionAll(Connection con)
  {
    try
    {
      System.out.println();
      System.out.println(
        "  ----------------------------------------------------------\n" +
        "  USE THE SQL STATEMENT:\n\n" +
        "    INSERT\n\n" +
        "  TO INSERT DATA THROUGH THE 'UNION ALL' VIEW.\n");

      System.out.println(
        "  CONTENTS OF THE VIEW 'FY' BEFORE INSERTING DATA:");

      // Display the initial content of the view FY before inserting new
      // rows
      DisplayData(con, "SELECT * FROM FY ORDER BY date, product_no");

      // INSERT data into tables Q1, Q2, Q3 and Q4 through the
      // UNION ALL view FY
      System.out.println();
      System.out.println(
        "  INSERT DATA THROUGH THE 'UNION ALL' VIEW" +
        " BY INVOKING THE STATEMENT:\n\n" +
        "    INSERT INTO FY VALUES (1, 20, '2001-06-03'),\n" +
        "                          (2, 30, '2001-03-21'),\n" +
        "                          (2, 25, '2001-08-30')\n");
 
      Statement stmt = con.createStatement();
      stmt.executeUpdate(
        "INSERT INTO FY VALUES (1, 20, '2001-06-03')," +
        "                      (2, 30, '2001-03-21')," +
        "                      (2, 25, '2001-08-30')");
      stmt.close();

      // Display the final content of all tables
      System.out.println(
        "  CONTENTS OF THE TABLES Q1, Q2, Q3, AND Q4 AFTER INSERTING DATA:");
      DisplayData(con, "SELECT * FROM Q1 ORDER BY date, product_no");
      DisplayData(con, "SELECT * FROM Q2 ORDER BY date, product_no");
      DisplayData(con, "SELECT * FROM Q3 ORDER BY date, product_no");
      DisplayData(con, "SELECT * FROM Q4 ORDER BY date, product_no");

      con.rollback();
    }
    catch (Exception e)
    {
      JdbcException jdbcExc = new JdbcException(e, con);
      jdbcExc.handle();
    }
  }

  // This method modifies the constraints of table Q1
  public static void NewConstraints(Connection con)
  {
    try
    {
      System.out.println();
      Statement stmt = con.createStatement();

      System.out.println(
        "  CHANGE THE CONSTRAINTS OF TABLE 'Q1' BY" +
        " INVOKING THE STATEMENTS:\n\n" +
        "    DELETE FROM FY\n" +
        "    ALTER TABLE Q1 DROP CONSTRAINT Q1_CHK_DATE\n" +
        "    ALTER TABLE Q1 ADD CONSTRAINT Q1_CHK_DATE" +
        " CHECK (MONTH(date) IN (4, 2, 3))");
 
      // Drop the constraint Q1_CHK_DATE and add a new one
      stmt.execute("DELETE FROM FY");
      stmt.execute("ALTER TABLE Q1 DROP CONSTRAINT Q1_CHK_DATE");
      stmt.execute("ALTER TABLE Q1 ADD CONSTRAINT Q1_CHK_DATE" + 
                   "  CHECK (MONTH(date) IN (4, 2, 3))");
      stmt.close();
      con.commit();
    }
    catch (Exception e)
    {
      JdbcException jdbcExc = new JdbcException(e, con);
      jdbcExc.handle();
    }
  }    

  // This method attempts to insert data through a UNION ALL view where no
  // table accepts the row
  public static void InsertWhenNoTableAcceptsIt(Connection con)
  {
    try
    {
      System.out.println();
      System.out.println(
        "  ----------------------------------------------------------\n" +
        "  USE THE SQL STATEMENT:\n\n" +
        "    INSERT\n\n" +
        "  TO ATTEMPT TO INSERT DATA THROUGH A 'UNION ALL' VIEW WHERE\n" +
        "  NO TABLE ACCEPTS THE ROW\n");

      System.out.println(
        "  NO TABLE ACCEPTS A ROW WITH 'MONTH' = 1." + 
        " AN ATTEMPT TO INSERT A ROW WITH\n" +
        "  'MONTH' = 1, WOULD CAUSE A 'NO TARGET' ERROR TO BE RAISED");

      Statement stmt = con.createStatement();

      System.out.println();
      System.out.println(
        "  ATTEMPT TO INSERT A ROW WITH 'MONTH' = 1" +
        " BY INVOKING THE STATEMENT:\n\n" +
        "    INSERT INTO FY VALUES (5, 35, '2001-01-14')\n");
 
      // Attempt to insert a row with 'MONTH' = 1 which no table will accept
      stmt.executeUpdate(
        "INSERT INTO FY VALUES (5, 35, '2001-01-14')");
      stmt.close();

      con.rollback();
      System.out.println("  Rollback Done.");
    }
    catch (Exception e)
    {
      JdbcException jdbcExc = new JdbcException(e, con);
      jdbcExc.handleExpectedErr();
    }
  }

  // This method attempts to insert data through a UNION ALL view where more
  // than one table accepts the row
  public static void InsertWhenMoreThanOneTableAcceptsIt(Connection con)
  {
    try
    {
      System.out.println();
      System.out.println(
        "  ----------------------------------------------------------\n" +
        "  USE THE SQL STATEMENT:\n\n" +
        "    INSERT\n\n" +
        "  TO ATTEMPT TO INSERT DATA THROUGH A 'UNION ALL' VIEW WHERE\n" +
        "  MORE THAN ONE TABLE ACCEPTS THE ROW\n");

      System.out.println(
        "  BOTH TABLES Q1 AND Q2 ACCEPT A ROW WITH 'MONTH' = 4." +
        " AN ATTEMPT TO\n" +
        "  INSERT A ROW WITH 'MONTH' = 4, WOULD CAUSE AN 'AMBIGUOUS" +
        " TARGET' ERROR\n" +
        "  TO BE RAISED");

      Statement stmt = con.createStatement();

      System.out.println();
      System.out.println(
        "  ATTEMPT TO INSERT A ROW WITH 'MONTH' = 4" +
        " BY INVOKING THE STATEMENT:\n\n" +
        "    INSERT INTO FY VALUES (3, 30, '2001-04-21')\n");

      // Attempt to insert a row with 'MONTH' = 4 which is accepted
      // by both tables Q1 and Q2 
      stmt.executeUpdate(
        "INSERT INTO FY VALUES (3, 30, '2001-04-21')");
      stmt.close();

      con.rollback();
      System.out.println("  Rollback Done.");
    }
    catch (Exception e)
    {
      JdbcException jdbcExc = new JdbcException(e, con);
      jdbcExc.handleExpectedErr();
    }
  }

  // This function creates a new view.  The new view has the WITH ROW 
  // MIGRATION clause in it, which enables row migration.  It performs some 
  // updates through this view to show how row migration affects the 
  // underlying tables. 
  public static void UpdateWithRowMovement(Connection con)
  {
    try
    {
      Statement stmt = con.createStatement();

      System.out.println(
        "\n  CREATE A VIEW 'vfullyear' BY INVOKING THE STATEMENT:\n\n" +
        "    CREATE VIEW vfullyear AS\n" +
        "      SELECT product_no, sales, date FROM Q1\n" +
        "      UNION ALL\n" +
        "      SELECT product_no, sales, date FROM Q2\n" +
        "      UNION ALL\n" +
        "      SELECT product_no, sales, date FROM Q3\n" +
        "      UNION ALL\n" +
        "      SELECT product_no, sales, date FROM Q4\n" +
        "      WITH ROW MOVEMENT\n");
  
      // Create the view vfullyear, this is the same as view FY with the
      // exception that it has the WITH ROW MOVEMENT clause.  This additional
      // clause allows updates through the view to move rows across the underlying
      // tables (row migration) as necessary.
      stmt.execute( 
        "CREATE VIEW vfullyear AS" +
        "  SELECT product_no, sales, date FROM Q1" +
        "  UNION ALL" +
        "  SELECT product_no, sales, date FROM Q2" +
        "  UNION ALL" +
        "  SELECT product_no, sales, date FROM Q3" +
        "  UNION ALL" +
        "  SELECT product_no, sales, date FROM Q4" +
        "  WITH ROW MOVEMENT");

      System.out.println(
        "  CONTENTS OF THE TABLES Q1 AND Q2 BEFORE ROW MOVEMENT OCCURS");
      DisplayData(con, "SELECT * FROM Q1");
      DisplayData(con, "SELECT * FROM Q2");
  
      System.out.println(
        "\n  UPDATE VALUES IN VIEW vfullyear BY INVOKING\n" +
        "  THE STATEMENT:\n\n" +
        "    UPDATE vfullyear SET date = date + 2 MONTHS\n" +
        "                     WHERE date='2001-02-28'");
		  
      // Demonstrate row movement by executing the following UPDATE statement.
      // This statement causes a row to move from table Q1 to table Q2.
      stmt.execute( 
        "UPDATE vfullyear SET date = date + 2 MONTHS" +
        "                 WHERE date='2001-02-28'");

      System.out.println(
        "\n  CONTENTS OF THE TABLES Q1 AND Q2 AFTER ROW MOVEMENT OCCURS");
      DisplayData(con, "SELECT * FROM Q1");
      DisplayData(con, "SELECT * FROM Q2");

      System.out.println(
        "\n  DROP THE VIEW vfullyear BY INVOKING\n" +
        "  THE STATEMENT:\n\n" +
        "    DROP VIEW vfullyear");
           
      stmt.execute("DROP VIEW vfullyear");
      
      stmt.close();
      con.commit();
    }
    catch (Exception e)
    {
      JdbcException jdbcExc = new JdbcException(e, con);
      jdbcExc.handle();
    }
  } // UpdateWithRowMovement

  // This function creates three new tables and one new view.  It performs some
  // updates through the view to show two special cases of row migration.
  public static void UpdateWithRowMovementSpecialCase(Connection con)
  {
    try
    {
      Statement stmt = con.createStatement();

      System.out.println(
        "\n  CREATE TABLES T1,T2 AND T3 BY INVOKING\n" +
        "  THE STATEMENTS:\n\n" +
        "    CREATE TABLE T1(name CHAR, grade INT)\n" +
        "    CREATE TABLE T2 LIKE T1\n" +
        "    CREATE TABLE T3 LIKE T1\n");
 
      stmt.execute("CREATE TABLE T1(name CHAR, grade INT)");
      stmt.execute("CREATE TABLE T2 LIKE T1");
      stmt.execute("CREATE TABLE T3 LIKE T1");

      System.out.println(
        "  INSERT INITIAL VALUES INTO TABLES T1, T2, T3 BY INVOKING\n" +
        "  THE STATEMENTS:\n\n" +
        "    INSERT INTO T1 VALUES ('a', 40), ('b', 55)\n" +
        "    INSERT INTO T2 VALUES ('c', 50), ('d', 75)\n" +
        "    INSERT INTO T3 VALUES ('d', 90), ('e', 95)");
   
      stmt.execute("INSERT INTO T1 VALUES ('a', 40), ('b', 55)");
      stmt.execute("INSERT INTO T2 VALUES ('c', 50), ('d', 75)");
      stmt.execute("INSERT INTO T3 VALUES ('d', 90), ('e', 95)");
 
      System.out.println(
        "\n  ADD CONSTRAINTS TO TABLES T1, T2 AND T3 BY INVOKING\n" +
        "  THE STATEMENTS:\n\n" +
        "    ALTER TABLE T1 ADD CONSTRAINT T1_CHK_GRADE\n" +
        "      CHECK (grade >= 0 AND grade <= 55)\n" +
        "    ALTER TABLE T2 ADD CONSTRAINT T2_CHK_GRADE\n" +
        "      CHECK (grade >= 50 AND grade <= 100)\n" +
        "    ALTER TABLE T3 ADD CONSTRAINT T3_CHK_GRADE\n" +
        "      CHECK (grade >= 90 AND grade <= 100)\n");
  
      stmt.execute(
        "ALTER TABLE T1 ADD CONSTRAINT T1_CHK_GRADE" +
        " CHECK (grade >= 0 AND grade <= 55)");

      stmt.execute(
        "ALTER TABLE T2 ADD CONSTRAINT T2_CHK_GRADE" +
        " CHECK (grade >= 50 AND grade <= 100)");

      stmt.execute(
        "ALTER TABLE T3 ADD CONSTRAINT T3_CHK_GRADE" +
        " CHECK (grade >= 90 AND grade <= 100)");

    }
    catch(Exception e)
    {
      JdbcException jdbcExc = new JdbcException(e, con);
      jdbcExc.handle();
    }
    try
    {
      Statement stmt = con.createStatement();

      System.out.println(
        "  CREATE A VIEW 'vmarks' BY INVOKING THE STATEMENT:\n\n" +
        "    CREATE VIEW vmarks AS\n" +
        "      SELECT name, grade FROM T1\n" +
        "      UNION ALL\n" +
        "      SELECT name, grade FROM T2\n" +
        "      UNION ALL\n" +
        "      SELECT name, grade FROM T3\n" +
        "      WITH ROW MOVEMENT\n");
 
      stmt.execute(
        "CREATE VIEW vmarks AS" +
        "  SELECT name, grade FROM T1" +
        "  UNION ALL" +
        "  SELECT name, grade FROM T2" +
        "  UNION ALL" +
        "  SELECT name, grade FROM T3" +
        "  WITH ROW MOVEMENT");
   
      System.out.println(
        "  ATTEMPT TO UPDATE THE ROW WITH grade = 50" +
        " BY INVOKING THE STATEMENT:\n\n" +
        "    UPDATE vmarks SET GRADE = 60 WHERE GRADE = 50");
  
      // Attempt to update the row where grade = 50, which satisfies constraints
      // for both tables T2 and T3.  In this case no error is raised as row 
      // migration doesn't apply.  The row does not need to be moved because it 
      // satisfies all constraints of the table it is already in.
      stmt.execute(
        "UPDATE vmarks SET grade = 60" +
        "              WHERE grade = 50");
   
      System.out.println(
        "\n  ATTEMPT TO UPDATE THE ROW WITH grade = 90" +
        " BY INVOKING THE STATEMENT:\n\n" +
        "    UPDATE vmarks SET GRADE = 50 WHERE GRADE = 90");
  
      // Attempt to update the row where grade = 90, which satisfies constraints
      // for both tables T1 and T2.  An error is raised since this update is 
      // ambiguous.  A similar error is raised on an ambiguous insert statement.
      stmt.execute( 
        "UPDATE vmarks SET grade = 50" +
        "              WHERE grade = 90");
    }
    catch(Exception e)
    {
      JdbcException jdbcExc = new JdbcException(e, con);
      jdbcExc.handleExpectedErr();
    }
    try
    {
      Statement stmt = con.createStatement();

      System.out.println(
        "\n  DROP TABLES T1,T2,T3 AND VIEW vmarks BY INVOKING\n" +
        "  THE STATEMENTS:\n\n" +
        "    DROP VIEW vmarks\n" +
        "    DROP TABLE T1\n" +
        "    DROP TABLE T2\n" +
        "    DROP TABLE T3");
  
      stmt.execute("DROP VIEW vmarks");
      stmt.execute("DROP TABLE T1");
      stmt.execute("DROP TABLE T2");
      stmt.execute("DROP TABLE T3");

      stmt.close();
      con.commit();
    }
    catch (Exception e)
    {
      JdbcException jdbcExc = new JdbcException(e, con);
      jdbcExc.handle();
    }
  } // UpdateWithRowMovementSpecialCase
} // TbUnion