/* * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.sql.rowset; import java.sql.*; import javax.sql.*; import javax.naming.*; import java.io.*; import java.math.*; import java.util.*; import javax.sql.rowset.*; /** * The JoinRowSet interface provides a mechanism for combining related * data from different RowSet objects into one JoinRowSet * object, which represents an SQL JOIN. * In other words, a JoinRowSet object acts as a * container for the data from RowSet objects that form an SQL * JOIN relationship. *

* The Joinable interface provides the methods for setting, * retrieving, and unsetting a match column, the basis for * establishing an SQL JOIN relationship. The match column may * alternatively be set by supplying it to the appropriate version of the * JointRowSet method addRowSet. * *

1.0 Overview

* Disconnected RowSet objects (CachedRowSet objects * and implementations extending the CachedRowSet interface) * do not have a standard way to establish an SQL JOIN between * RowSet objects without the expensive operation of * reconnecting to the data source. The JoinRowSet * interface is specifically designed to address this need. *

* Any RowSet object * can be added to a JoinRowSet object to become * part of an SQL JOIN relationship. This means that both connected * and disconnected RowSet objects can be part of a JOIN. * RowSet objects operating in a connected environment * (JdbcRowSet objects) are * encouraged to use the database to which they are already * connected to establish SQL JOIN relationships between * tables directly. However, it is possible for a * JdbcRowSet object to be added to a JoinRowSet object * if necessary. *

* Any number of RowSet objects can be added to an * instance of JoinRowSet provided that they * can be related in an SQL JOIN. * By definition, the SQL JOIN statement is used to * combine the data contained in two or more relational database tables based * upon a common attribute. The Joinable interface provides the methods * for establishing a common attribute, which is done by setting a * match column. The match column commonly coincides with * the primary key, but there is * no requirement that the match column be the same as the primary key. * By establishing and then enforcing column matches, * a JoinRowSet object establishes JOIN relationships * between RowSet objects without the assistance of an available * relational database. *

* The type of JOIN to be established is determined by setting * one of the JoinRowSet constants using the method * setJoinType. The following SQL JOIN types can be set: *

* Note that if no type is set, the JOIN will automatically be an * inner join. The comments for the fields in the * JoinRowSet interface explain these JOIN types, which are * standard SQL JOIN types. * *

2.0 Using a JoinRowSet Object for Creating a JOIN

* When a JoinRowSet object is created, it is empty. * The first RowSet object to be added becomes the basis for the * JOIN relationship. * Applications must determine which column in each of the * RowSet objects to be added to the JoinRowSet object * should be the match column. All of the * RowSet objects must contain a match column, and the values in * each match column must be ones that can be compared to values in the other match * columns. The columns do not have to have the same name, though they often do, * and they do not have to store the exact same data type as long as the data types * can be compared. *

* A match column can be be set in two ways: *

*

3.0 Sample Usage

*

* The following code fragment adds two CachedRowSet * objects to a JoinRowSet object. Note that in this example, * no SQL JOIN type is set, so the default JOIN type, * which is INNER_JOIN, is established. *

* In the following code fragment, the table EMPLOYEES, whose match * column is set to the first column (EMP_ID), is added to the * JoinRowSet object jrs. Then * the table ESSP_BONUS_PLAN, whose match column is likewise * the EMP_ID column, is added. When this second * table is added to jrs, only the rows in * ESSP_BONUS_PLAN whose EMP_ID value matches an * EMP_ID value in the EMPLOYEES table are added. * In this case, everyone in the bonus plan is an employee, so all of the rows * in the table ESSP_BONUS_PLAN are added to the JoinRowSet * object. In this example, both CachedRowSet objects being added * have implemented the Joinable interface and can therefore call * the Joinable method setMatchColumn. *

 *     JoinRowSet jrs = new JoinRowSetImpl();
 *
 *     ResultSet rs1 = stmt.executeQuery("SELECT * FROM EMPLOYEES");
 *     CachedRowSet empl = new CachedRowSetImpl();
 *     empl.populate(rs1);
 *     empl.setMatchColumn(1);
 *     jrs.addRowSet(empl);
 *
 *     ResultSet rs2 = stmt.executeQuery("SELECT * FROM ESSP_BONUS_PLAN");
 *     CachedRowSet bonus = new CachedRowSetImpl();
 *     bonus.populate(rs2);
 *     bonus.setMatchColumn(1); // EMP_ID is the first column
 *     jrs.addRowSet(bonus);
 * 
*

* At this point, jrs is an inside JOIN of the two RowSet objects * based on their EMP_ID columns. The application can now browse the * combined data as if it were browsing one single RowSet object. * Because jrs is itself a RowSet object, an application can * navigate or modify it using RowSet methods. *

 *     jrs.first();
 *     int employeeID = jrs.getInt(1);
 *     String employeeName = jrs.getString(2);
 * 
*

* Note that because the SQL JOIN must be enforced when an application * adds a second or subsequent RowSet object, there * may be an initial degradation in performance while the JOIN is * being performed. *

* The following code fragment adds an additional CachedRowSet object. * In this case, the match column (EMP_ID) is set when the * CachedRowSet object is added to the JoinRowSet object. *

 *     ResultSet rs3 = stmt.executeQuery("SELECT * FROM 401K_CONTRIB");
 *     CachedRowSet fourO1k = new CachedRowSetImpl();
 *     four01k.populate(rs3);
 *     jrs.addRowSet(four01k, 1);
 * 
*

* The JoinRowSet object jrs now contains values from all three * tables. The data in each row in four01k in which the value for the * EMP_ID column matches a value for the EMP_ID column * in jrs has been added to jrs. * *

4.0 JoinRowSet Methods

* The JoinRowSet interface supplies several methods for adding * RowSet objects and for getting information about the * JoinRowSet object. * * * @since 1.5 */ public interface JoinRowSet extends WebRowSet { /** * Adds the given RowSet object to this JoinRowSet * object. If the RowSet object * is the first to be added to this JoinRowSet * object, it forms the basis of the JOIN relationship to be * established. *

* This method should be used only when the given RowSet * object already has a match column that was set with the Joinable * method setMatchColumn. *

* Note: A Joinable object is any RowSet object * that has implemented the Joinable interface. * * @param rowset the RowSet object that is to be added to this * JoinRowSet object; it must implement the * Joinable interface and have a match column set * @throws SQLException if (1) an empty rowset is added to the to this * JoinRowSet object, (2) a match column has not been * set for rowset, or (3) rowset * violates the active JOIN * @see Joinable#setMatchColumn */ public void addRowSet(Joinable rowset) throws SQLException; /** * Adds the given RowSet object to this JoinRowSet * object and sets the designated column as the match column for * the RowSet object. If the RowSet object * is the first to be added to this JoinRowSet * object, it forms the basis of the JOIN relationship to be * established. *

* This method should be used when RowSet does not already have a match * column set. * * @param rowset the RowSet object that is to be added to this * JoinRowSet object; it may implement the * Joinable interface * @param columnIdx an int that identifies the column to become the * match column * @throws SQLException if (1) rowset is an empty rowset or * (2) rowset violates the active JOIN * @see Joinable#unsetMatchColumn */ public void addRowSet(RowSet rowset, int columnIdx) throws SQLException; /** * Adds rowset to this JoinRowSet object and * sets the designated column as the match column. If rowset * is the first to be added to this JoinRowSet * object, it forms the basis for the JOIN relationship to be * established. *

* This method should be used when the given RowSet object * does not already have a match column. * * @param rowset the RowSet object that is to be added to this * JoinRowSet object; it may implement the * Joinable interface * @param columnName the String object giving the name of the * column to be set as the match column * @throws SQLException if (1) rowset is an empty rowset or * (2) the match column for rowset does not satisfy the * conditions of the JOIN */ public void addRowSet(RowSet rowset, String columnName) throws SQLException; /** * Adds one or more RowSet objects contained in the given * array of RowSet objects to this JoinRowSet * object and sets the match column for * each of the RowSet objects to the match columns * in the given array of column indexes. The first element in * columnIdx is set as the match column for the first * RowSet object in rowset, the second element of * columnIdx is set as the match column for the second element * in rowset, and so on. *

* The first RowSet object added to this JoinRowSet * object forms the basis for the JOIN relationship. *

* This method should be used when the given RowSet object * does not already have a match column. * * @param rowset an array of one or more RowSet objects * to be added to the JOIN; it may implement the * Joinable interface * @param columnIdx an array of int values indicating the index(es) * of the columns to be set as the match columns for the RowSet * objects in rowset * @throws SQLException if (1) an empty rowset is added to this * JoinRowSet object, (2) a match column is not set * for a RowSet object in rowset, or (3) * a RowSet object being added violates the active * JOIN */ public void addRowSet(RowSet[] rowset, int[] columnIdx) throws SQLException; /** * Adds one or more RowSet objects contained in the given * array of RowSet objects to this JoinRowSet * object and sets the match column for * each of the RowSet objects to the match columns * in the given array of column names. The first element in * columnName is set as the match column for the first * RowSet object in rowset, the second element of * columnName is set as the match column for the second element * in rowset, and so on. *

* The first RowSet object added to this JoinRowSet * object forms the basis for the JOIN relationship. *

* This method should be used when the given RowSet object(s) * does not already have a match column. * * @param rowset an array of one or more RowSet objects * to be added to the JOIN; it may implement the * Joinable interface * @param columnName an array of String values indicating the * names of the columns to be set as the match columns for the * RowSet objects in rowset * @throws SQLException if (1) an empty rowset is added to this * JoinRowSet object, (2) a match column is not set * for a RowSet object in rowset, or (3) * a RowSet object being added violates the active * JOIN */ public void addRowSet(RowSet[] rowset, String[] columnName) throws SQLException; /** * Returns a Collection object containing the * RowSet objects that have been added to this * JoinRowSet object. * This should return the 'n' number of RowSet contained * within the JOIN and maintain any updates that have occurred while in * this union. * * @return a Collection object consisting of the * RowSet objects added to this JoinRowSet * object * @throws SQLException if an error occurs generating the * Collection object to be returned */ public Collection getRowSets() throws java.sql.SQLException; /** * Returns a String array containing the names of the * RowSet objects added to this JoinRowSet * object. * * @return a String array of the names of the * RowSet objects in this JoinRowSet * object * @throws SQLException if an error occurs retrieving the names of * the RowSet objects * @see CachedRowSet#setTableName */ public String[] getRowSetNames() throws java.sql.SQLException; /** * Creates a new CachedRowSet object containing the * data in this JoinRowSet object, which can be saved * to a data source using the SyncProvider object for * the CachedRowSet object. *

* If any updates or modifications have been applied to the JoinRowSet * the CachedRowSet returned by the method will not be able to persist * it's changes back to the originating rows and tables in the * in the datasource. The CachedRowSet instance returned should not * contain modification data and it should clear all properties of * it's originating SQL statement. An application should reset the * SQL statement using the RowSet.setCommand method. *

* In order to allow changes to be persisted back to the datasource * to the originating tables, the acceptChanges method * should be used and called on a JoinRowSet object instance. Implementations * can leverage the internal data and update tracking in their * implementations to interact with the SyncProvider to persist any * changes. * * @return a CachedRowSet containing the contents of the JoinRowSet * @throws SQLException if an error occurs assembling the CachedRowSet * object * @see javax.sql.RowSet * @see javax.sql.rowset.CachedRowSet * @see javax.sql.rowset.spi.SyncProvider */ public CachedRowSet toCachedRowSet() throws java.sql.SQLException; /** * Indicates if CROSS_JOIN is supported by a JoinRowSet * implementation * * @return true if the CROSS_JOIN is supported; false otherwise */ public boolean supportsCrossJoin(); /** * Indicates if INNER_JOIN is supported by a JoinRowSet * implementation * * @return true is the INNER_JOIN is supported; false otherwise */ public boolean supportsInnerJoin(); /** * Indicates if LEFT_OUTER_JOIN is supported by a JoinRowSet * implementation * * @return true is the LEFT_OUTER_JOIN is supported; false otherwise */ public boolean supportsLeftOuterJoin(); /** * Indicates if RIGHT_OUTER_JOIN is supported by a JoinRowSet * implementation * * @return true is the RIGHT_OUTER_JOIN is supported; false otherwise */ public boolean supportsRightOuterJoin(); /** * Indicates if FULL_JOIN is supported by a JoinRowSet * implementation * * @return true is the FULL_JOIN is supported; false otherwise */ public boolean supportsFullJoin(); /** * Allow the application to adjust the type of JOIN imposed * on tables contained within the JoinRowSet object instance. * Implementations should throw a SQLException if they do * not support a given JOIN type. * * @param joinType the standard JoinRowSet.XXX static field definition * of a SQL JOIN to re-configure a JoinRowSet instance on * the fly. * @throws SQLException if an unsupported JOIN type is set * @see #getJoinType */ public void setJoinType(int joinType) throws SQLException; /** * Return a SQL-like description of the WHERE clause being used * in a JoinRowSet object. An implementation can describe * the WHERE clause of the SQL JOIN by supplying a SQL * strings description of JOIN or provide a textual * description to assist applications using a JoinRowSet * * @return whereClause a textual or SQL description of the logical * WHERE clause used in the JoinRowSet instance * @throws SQLException if an error occurs in generating a representation * of the WHERE clause. */ public String getWhereClause() throws SQLException; /** * Returns a int describing the set SQL JOIN type * governing this JoinRowSet instance. The returned type will be one of * standard JoinRowSet types: CROSS_JOIN, INNER_JOIN, * LEFT_OUTER_JOIN, RIGHT_OUTER_JOIN or * FULL_JOIN. * * @return joinType one of the standard JoinRowSet static field * definitions of a SQL JOIN. JoinRowSet.INNER_JOIN * is returned as the default JOIN type is no type has been * explicitly set. * @throws SQLException if an error occurs determining the SQL JOIN * type supported by the JoinRowSet instance. * @see #setJoinType */ public int getJoinType() throws SQLException; /** * An ANSI-style JOIN providing a cross product of two tables */ public static int CROSS_JOIN = 0; /** * An ANSI-style JOIN providing a inner join between two tables. Any * unmatched rows in either table of the join should be discarded. */ public static int INNER_JOIN = 1; /** * An ANSI-style JOIN providing a left outer join between two * tables. In SQL, this is described where all records should be * returned from the left side of the JOIN statement. */ public static int LEFT_OUTER_JOIN = 2; /** * An ANSI-style JOIN providing a right outer join between * two tables. In SQL, this is described where all records from the * table on the right side of the JOIN statement even if the table * on the left has no matching record. */ public static int RIGHT_OUTER_JOIN = 3; /** * An ANSI-style JOIN providing a a full JOIN. Specifies that all * rows from either table be returned regardless of matching * records on the other table. */ public static int FULL_JOIN = 4; }