--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaConnectionProperty.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaConnectionProperty.java Wed Jun 20 15:38:40 2018 -0400
@@ -33,6 +33,10 @@
/**
* A set of {@link ConnectionProperty} commonly supported. Implementations are not
* required to support all of these properties.
+ *
+ * ISSUE: Need others such as IDLE_TIMEOUT, TIME_TO_LIVE_TIMEOUT, etc. Can we
+ * get away with just ConnectionProperties or do we need DataSourceProperties
+ * as well, MAX_CACHED_CONNECTIONS, etc?
*
*/
public enum AdbaConnectionProperty implements ConnectionProperty {
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaType.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaType.java Wed Jun 20 15:38:40 2018 -0400
@@ -25,6 +25,13 @@
package jdk.incubator.sql2;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+
/**
* <P>Defines the constants that are used to identify generic
* SQL types, called JDBC types.
@@ -37,168 +44,172 @@
/**
* Identifies the generic SQL type {@code BIT}.
*/
- BIT,
+ BIT(Boolean.class),
/**
* Identifies the generic SQL type {@code TINYINT}.
*/
- TINYINT,
+ TINYINT(Byte.class),
/**
* Identifies the generic SQL type {@code SMALLINT}.
*/
- SMALLINT,
+ SMALLINT(Short.class),
/**
* Identifies the generic SQL type {@code INTEGER}.
*/
- INTEGER,
+ INTEGER(Integer.class),
/**
* Identifies the generic SQL type {@code BIGINT}.
*/
- BIGINT,
+ BIGINT(Long.class),
/**
* Identifies the generic SQL type {@code FLOAT}.
*/
- FLOAT,
+ FLOAT(Double.class),
/**
* Identifies the generic SQL type {@code REAL}.
*/
- REAL,
+ REAL(Float.class),
/**
* Identifies the generic SQL type {@code DOUBLE}.
*/
- DOUBLE,
+ DOUBLE(Double.class),
/**
* Identifies the generic SQL type {@code NUMERIC}.
*/
- NUMERIC,
+ NUMERIC(BigDecimal.class),
/**
* Identifies the generic SQL type {@code DECIMAL}.
*/
- DECIMAL,
+ DECIMAL(BigDecimal.class),
/**
* Identifies the generic SQL type {@code CHAR}.
*/
- CHAR,
+ CHAR(String.class),
/**
* Identifies the generic SQL type {@code VARCHAR}.
*/
- VARCHAR,
+ VARCHAR(String.class),
/**
* Identifies the generic SQL type {@code LONG VARCHAR}.
*/
- LONG_VARCHAR,
+ LONG_VARCHAR(String.class),
/**
* Identifies the generic SQL type {@code DATE}.
*/
- DATE,
+ DATE(LocalDate.class),
/**
* Identifies the generic SQL type {@code TIME}.
*/
- TIME,
+ TIME(LocalTime.class),
/**
* Identifies the generic SQL type {@code TIMESTAMP}.
*/
- TIMESTAMP,
+ TIMESTAMP(LocalDateTime.class),
/**
* Identifies the generic SQL type {@code BINARY}.
*/
- BINARY,
+ BINARY(byte[].class),
/**
* Identifies the generic SQL type {@code VARBINARY}.
*/
- VARBINARY,
+ VARBINARY(byte[].class),
/**
* Identifies the generic SQL type {@code LONG VARBINARY}.
*/
- LONG_VARBINARY,
+ LONG_VARBINARY(byte[].class),
/**
* Identifies the generic SQL value {@code NULL}.
*/
- NULL,
+ NULL(Void.class),
/**
* Indicates that the SQL type
* is database-specific and gets mapped to a Java object that can be
* accessed via the methods getObject and setObject.
*/
- OTHER,
+ OTHER(Object.class),
/**
* Indicates that the SQL type
* is database-specific and gets mapped to a Java object that can be
* accessed via the methods getObject and setObject.
*/
- JAVA_OBJECT,
+ JAVA_OBJECT(Object.class),
/**
* Identifies the generic SQL type {@code DISTINCT}.
*/
- DISTINCT,
+ DISTINCT(Object.class),
/**
* Identifies the generic SQL type {@code STRUCT}.
*/
- STRUCT,
+ STRUCT(SqlStruct.class),
/**
* Identifies the generic SQL type {@code ARRAY}.
*/
- ARRAY,
+ ARRAY(Object[].class), //TODO questionable. really want <?>[]
/**
* Identifies the generic SQL type {@code BLOB}.
*/
- BLOB,
+ BLOB(SqlBlob.class),
/**
* Identifies the generic SQL type {@code CLOB}.
*/
- CLOB,
+ CLOB(SqlClob.class),
/**
* Identifies the generic SQL type {@code REF}.
*/
- REF,
+ REF(SqlRef.class),
/**
* Identifies the generic SQL type {@code DATALINK}.
*/
- DATALINK,
+ DATALINK(Void.class), //TODO
/**
* Identifies the generic SQL type {@code BOOLEAN}.
*/
- BOOLEAN,
-
+ BOOLEAN(Boolean.class),
/**
* Identifies the SQL type {@code ROWID}.
*/
- ROWID,
+ ROWID(Void.class), //TODO
/**
* Identifies the generic SQL type {@code NCHAR}.
*/
- NCHAR,
+ NCHAR(String.class),
/**
* Identifies the generic SQL type {@code NVARCHAR}.
*/
- NVARCHAR,
+ NVARCHAR(String.class),
/**
* Identifies the generic SQL type {@code LONG NVARCHAR}.
*/
- LONG_NVARCHAR,
+ LONG_NVARCHAR(String.class),
/**
* Identifies the generic SQL type {@code NCLOB}.
*/
- NCLOB,
+ NCLOB(SqlClob.class),
/**
* Identifies the generic SQL type {@code SQLXML}.
*/
- SQLXML,
+ SQLXML(Void.class), //TODO
/**
* Identifies the generic SQL type {@code REF CURSOR}.
*/
- REF_CURSOR,
+ REF_CURSOR(Void.class), //TODO
/**
* Identifies the generic SQL type {@code TIME WITH TIME ZONE}.
*/
- TIME_WITH_TIME_ZONE,
+ TIME_WITH_TIME_ZONE(OffsetTime.class),
/**
* Identifies the generic SQL type {@code TIMESTAMP WITH TIME ZONE}.
*/
- TIMESTAMP_WITH_TIME_ZONE;
+ TIMESTAMP_WITH_TIME_ZONE(OffsetDateTime.class);
+ protected final Class javaType;
+
+ AdbaType(Class type) {
+ javaType = type;
+ }
/**
*{@inheritDoc }
@@ -229,4 +240,9 @@
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
+ @Override
+ public <T> Class<T> getJavaType() {
+ return javaType;
+ }
+
}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ArrayCountOperation.java Wed Jun 20 15:12:52 2018 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2017, 2018, 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 jdk.incubator.sql2;
-
-import java.time.Duration;
-import java.util.List;
-import java.util.concurrent.CompletionStage;
-import java.util.function.Consumer;
-import java.util.stream.Collector;
-
-/**
- * A database operation that returns a count that is executed multiple times
- * with multiple sets of parameter values in one database operation. The
- * parameters are submitted to the database in the same order as in the
- * sequences passed to the set methods. The count results are passed to the
- * collector in the same order they are produced by the database. The
- * value of the Operation is the final result produced by the collector.
- *
- * @param <T> the type of the result of collecting the counts
- */
-public interface ArrayCountOperation<T> extends Operation<T> {
-
- /**
- * Set a sequence of parameter values. The value is captured and should not be
- * modified before the {@link Operation} is completed.
- *
- * The Operation is completed exceptionally with ClassCastException if any of
- * the values cannot be converted to the specified SQL type.
- *
- * @param id the identifier of the parameter marker to be set
- * @param values the sequence of values the parameter is to be set to
- * @param type the SQL type of the values to send to the database
- * @return this Operation
- * @throws IllegalArgumentException if the length of values is not the same as
- * the length of the previously set parameter sequences or if the same id was
- * passed in a previous call.
- * @throws IllegalStateException if the {@link Operation} has been submitted
- */
- public ArrayCountOperation<T> set(String id, List<?> values, SqlType type);
-
- /**
- * Set a sequence of parameter values. Use a default SQL type determined by
- * the type of the value argument. The value is captured and should not be
- * modified before the {@link Operation} is completed.
- *
- * The Operation is completed exceptionally with ClassCastException if any of
- * the values cannot be converted to the specified SQL type.
- *
- * @param id the identifier of the parameter marker to be set
- * @param values the value the parameter is to be set to
- * @return this {@link Operation}
- * @throws IllegalArgumentException if the length of value is not the same as
- * the length of the previously set parameter sequences or if the same id was
- * passed in a previous call.
- * @throws IllegalStateException if the {@link Operation} has been submitted
- */
- public ArrayCountOperation<T> set(String id, List<?> values);
-
- /**
- * Set a sequence of parameter values. The first parameter is captured and
- * should not be modified before the {@link Operation} is completed.
- *
- * The Operation is completed exceptionally with ClassCastException if any of
- * the values cannot be converted to the specified SQL type.
- *
- * @param <S> the Java type of the individual parameter values
- * @param id the identifier of the parameter marker to be set
- * @param values the value the parameter is to be set to
- * @param type the SQL type of the value to send to the database
- * @return this Operation
- * @throws IllegalArgumentException if the length of value is not the same as
- * the length of the previously set parameter sequences or if the same id was
- * passed in a previous call.
- * @throws IllegalStateException if the {@link Operation} has been submitted
- */
- public <S> ArrayCountOperation<T> set(String id, S[] values, SqlType type);
-
- /**
- * Set a sequence of parameter values. Use a default SQL type determined by
- * the type of the value argument. The parameter is captured and should not be
- * modified before the {@link Operation} is completed.
- *
- * The Operation is completed exceptionally with ClassCastException if any of
- * the values cannot be converted to the specified SQL type.
- *
- * @param <S> the Java type of the individual parameter values
- * @param id the identifier of the parameter marker to be set
- * @param values the value the parameter is to be set to
- * @return this Operation
- * @throws IllegalArgumentException if the length of value is not the same as
- * the length of the previously set parameter sequences or if the same id was
- * passed in a previous call.
- * @throws IllegalStateException if the {@link Operation} has been submitted
- */
- public <S> ArrayCountOperation<T> set(String id, S[] values);
-
- /**
- * Provide a source for a sequence of parameter values.
- *
- * This Operation is not executed until source is completed normally. If
- * source completes exceptionally this Operation completes exceptionally with
- * an IllegealArgumentException with the source's exception as the cause.
- *
- * The Operation is completed exceptionally with ClassCastException if any of
- * the values of the source cannot be converted to the specified SQL type.
- *
- * If the length of the value of source is not the same as the length of all
- * other parameter sequences this Operation is completed exceptionally with
- * IllegalArgumentException.
- *
- * @param id the identifier of the parameter marker to be set
- * @param source supplies the values the parameter is to be set to
- * @param type the SQL type of the value to send to the database
- * @return this Operation
- * @throws IllegalArgumentException if the same id was passed in a previous
- * call.
- * @throws IllegalStateException if the {@link Operation} has been submitted
- */
- public ArrayCountOperation<T> set(String id, CompletionStage<?> source, SqlType type);
-
- /**
- * Provide a source for a sequence of parameter values. Use a default SQL type
- * determined by the element type of the value of the source.
- *
- * This Operation is not executed until source is completed normally. If
- * source completes exceptionally this Operation completes exceptionally with
- * an IllegealArgumentException with the source's exception as the cause.
- *
- * The Operation is completed exceptionally with ClassCastException if any of
- * the values of the source cannot be converted to the specified SQL type.
- *
- * If the length of the value of source is not the same as the length of all
- * other parameter sequences this Operation is completed exceptionally with
- * IllegalArgumentException.
- *
- * @param id the identifier of the parameter marker to be set
- * @param source supplies the values the parameter is to be set to
- * @return this {@link Operation}
- * @throws IllegalArgumentException if the same id was passed in a previous
- * call.
- * @throws IllegalStateException if the {@link Operation} has been submitted
- */
- public ArrayCountOperation<T> set(String id, CompletionStage<?> source);
-
- /**
- * Provides a {@link Collector} to reduce the sequence of Counts.The result of
- * the {@link Operation} is the result of calling finisher on the final
- * accumulated result. If the {@link Collector} is
- * {@link Collector.Characteristics#UNORDERED} counts may be accumulated out of
- * order. If the {@link Collector} is
- * {@link Collector.Characteristics#CONCURRENT} then the sequence of counts may be
- * split into subsequences that are reduced separately and then combined.
- *
- * @param <A> the type of the accumulator
- * @param <S> the type of the final result
- * @param c the Collector. Not null.
- * @return This ArrayCountOperation
- * @throws IllegalStateException if this method had been called previously or
- * this Operation has been submitted.
- */
- public <A, S extends T> ArrayCountOperation<T> collect(Collector<? super Result.Count, A, S> c);
-
- @Override
- public ArrayCountOperation<T> onError(Consumer<Throwable> handler);
-
- @Override
- public ArrayCountOperation<T> timeout(Duration minTime);
-
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ArrayRowCountOperation.java Wed Jun 20 15:38:40 2018 -0400
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2017, 2018, 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 jdk.incubator.sql2;
+
+import java.time.Duration;
+import java.util.List;
+import java.util.concurrent.CompletionStage;
+import java.util.function.Consumer;
+import java.util.stream.Collector;
+
+/**
+ * A database operation that returns a count that is executed multiple times
+ * with multiple sets of parameter values in one database operation. The
+ * parameters are submitted to the database in the same order as in the
+ * sequences passed to the set methods. The count results are passed to the
+ * collector in the same order they are produced by the database. The
+ * value of the Operation is the final result produced by the collector.
+ *
+ * @param <T> the type of the result of collecting the counts
+ */
+public interface ArrayRowCountOperation<T> extends Operation<T> {
+
+ /**
+ * Set a sequence of parameter values. The value is captured and should not be
+ * modified before the {@link Operation} is completed.
+ *
+ * The Operation is completed exceptionally with ClassCastException if any of
+ * the values cannot be converted to the specified SQL type.
+ *
+ * @param id the identifier of the parameter marker to be set
+ * @param values the sequence of values the parameter is to be set to
+ * @param type the SQL type of the values to send to the database
+ * @return this Operation
+ * @throws IllegalArgumentException if the length of values is not the same as
+ * the length of the previously set parameter sequences or if the same id was
+ * passed in a previous call.
+ * @throws IllegalStateException if the {@link Operation} has been submitted
+ */
+ public ArrayRowCountOperation<T> set(String id, List<?> values, SqlType type);
+
+ /**
+ * Set a sequence of parameter values. Use a default SQL type determined by
+ * the type of the value argument. The value is captured and should not be
+ * modified before the {@link Operation} is completed.
+ *
+ * The Operation is completed exceptionally with ClassCastException if any of
+ * the values cannot be converted to the specified SQL type.
+ *
+ * @param id the identifier of the parameter marker to be set
+ * @param values the value the parameter is to be set to
+ * @return this {@link Operation}
+ * @throws IllegalArgumentException if the length of value is not the same as
+ * the length of the previously set parameter sequences or if the same id was
+ * passed in a previous call.
+ * @throws IllegalStateException if the {@link Operation} has been submitted
+ */
+ public ArrayRowCountOperation<T> set(String id, List<?> values);
+
+ /**
+ * Set a sequence of parameter values. The first parameter is captured and
+ * should not be modified before the {@link Operation} is completed.
+ *
+ * The Operation is completed exceptionally with ClassCastException if any of
+ * the values cannot be converted to the specified SQL type.
+ *
+ * @param <S> the Java type of the individual parameter values
+ * @param id the identifier of the parameter marker to be set
+ * @param values the value the parameter is to be set to
+ * @param type the SQL type of the value to send to the database
+ * @return this Operation
+ * @throws IllegalArgumentException if the length of value is not the same as
+ * the length of the previously set parameter sequences or if the same id was
+ * passed in a previous call.
+ * @throws IllegalStateException if the {@link Operation} has been submitted
+ */
+ public <S> ArrayRowCountOperation<T> set(String id, S[] values, SqlType type);
+
+ /**
+ * Set a sequence of parameter values. Use a default SQL type determined by
+ * the type of the value argument. The parameter is captured and should not be
+ * modified before the {@link Operation} is completed.
+ *
+ * The Operation is completed exceptionally with ClassCastException if any of
+ * the values cannot be converted to the specified SQL type.
+ *
+ * @param <S> the Java type of the individual parameter values
+ * @param id the identifier of the parameter marker to be set
+ * @param values the value the parameter is to be set to
+ * @return this Operation
+ * @throws IllegalArgumentException if the length of value is not the same as
+ * the length of the previously set parameter sequences or if the same id was
+ * passed in a previous call.
+ * @throws IllegalStateException if the {@link Operation} has been submitted
+ */
+ public <S> ArrayRowCountOperation<T> set(String id, S[] values);
+
+ /**
+ * Provide a source for a sequence of parameter values.
+ *
+ * This Operation is not executed until source is completed normally. If
+ * source completes exceptionally this Operation completes exceptionally with
+ * an IllegealArgumentException with the source's exception as the cause.
+ *
+ * The Operation is completed exceptionally with ClassCastException if any of
+ * the values of the source cannot be converted to the specified SQL type.
+ *
+ * If the length of the value of source is not the same as the length of all
+ * other parameter sequences this Operation is completed exceptionally with
+ * IllegalArgumentException.
+ *
+ * @param id the identifier of the parameter marker to be set
+ * @param source supplies the values the parameter is to be set to
+ * @param type the SQL type of the value to send to the database
+ * @return this Operation
+ * @throws IllegalArgumentException if the same id was passed in a previous
+ * call.
+ * @throws IllegalStateException if the {@link Operation} has been submitted
+ */
+ public ArrayRowCountOperation<T> set(String id, CompletionStage<?> source, SqlType type);
+
+ /**
+ * Provide a source for a sequence of parameter values. Use a default SQL type
+ * determined by the element type of the value of the source.
+ *
+ * This Operation is not executed until source is completed normally. If
+ * source completes exceptionally this Operation completes exceptionally with
+ * an IllegealArgumentException with the source's exception as the cause.
+ *
+ * The Operation is completed exceptionally with ClassCastException if any of
+ * the values of the source cannot be converted to the specified SQL type.
+ *
+ * If the length of the value of source is not the same as the length of all
+ * other parameter sequences this Operation is completed exceptionally with
+ * IllegalArgumentException.
+ *
+ * @param id the identifier of the parameter marker to be set
+ * @param source supplies the values the parameter is to be set to
+ * @return this {@link Operation}
+ * @throws IllegalArgumentException if the same id was passed in a previous
+ * call.
+ * @throws IllegalStateException if the {@link Operation} has been submitted
+ */
+ public ArrayRowCountOperation<T> set(String id, CompletionStage<?> source);
+
+ /**
+ * Provides a {@link Collector} to reduce the sequence of Counts.The result of
+ * the {@link Operation} is the result of calling finisher on the final
+ * accumulated result. If the {@link Collector} is
+ * {@link Collector.Characteristics#UNORDERED} counts may be accumulated out of
+ * order. If the {@link Collector} is
+ * {@link Collector.Characteristics#CONCURRENT} then the sequence of counts may be
+ * split into subsequences that are reduced separately and then combined.
+ *
+ * @param <A> the type of the accumulator
+ * @param <S> the type of the final result
+ * @param c the Collector. Not null.
+ * @return This ArrayRowCountOperation
+ * @throws IllegalStateException if this method had been called previously or
+ * this Operation has been submitted.
+ */
+ public <A, S extends T> ArrayRowCountOperation<T> collect(Collector<? super Result.RowCount, A, S> c);
+
+ @Override
+ public ArrayRowCountOperation<T> onError(Consumer<Throwable> handler);
+
+ @Override
+ public ArrayRowCountOperation<T> timeout(Duration minTime);
+
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Connection.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Connection.java Wed Jun 20 15:38:40 2018 -0400
@@ -259,12 +259,15 @@
* Return a {@link Connection} with the attributes specified. Note that the
* {@link Connection} may not be connected to a server. Call one of the
* {@link connect} convenience methods to connect the {@link Connection} to
- * a server. The lifecycle of the new {@link Connection} is {@link Lifecycle#NEW}.
+ * a server. The lifecycle of the new {@link Connection} is
+ * {@link Lifecycle#NEW}.
*
* @return a {@link Connection}
* @throws IllegalStateException if this method has already been called or
* if the implementation cannot create a Connection with the specified
* {@link ConnectionProperty}s.
+ * @throws IllegalStateException if the {@link DataSource} that created this
+ * {@link Builder} is closed
*/
public Connection build();
}
@@ -471,13 +474,14 @@
/**
* Create an endTransaction {@link Operation}, set it to rollback only,
- * and submit it. Convenience method.
+ * and submit it. The endTransaction is never skipped. Convenience method.
*
* @return this {@link OperationGroup}
*/
public default CompletionStage<TransactionOutcome> rollback() {
Transaction t = transaction();
t.setRollbackOnly();
+ catchErrors();
return this.endTransactionOperation(t).submit().getCompletionStage();
}
@@ -547,6 +551,29 @@
public ShardingKey.Builder shardingKeyBuilder();
/**
+ * Provide a method that this {@link Connection} will call to control the rate
+ * of {@link Operation} submission. This {@link Connection} will call
+ * {@code request} with a positive argument when the {@link Connection} is
+ * able to accept more {@link Operation} submissions. The difference between
+ * the sum of all arguments passed to {@code request} and the number of
+ * {@link Operation}s submitted after this method is called is the
+ * <i>demand</i>. The demand must always be non-negative. If an
+ * {@link Operation} is submitted that would make the demand negative the call
+ * to {@link Operation#submit} throws {@link IllegalStateException}. Prior to
+ * a call to {@code requestHook}, the demand is defined to be infinite.
+ * After a call to {@code requestHook}, the demand is defined to be
+ * zero and is subsequently computed as described previously.
+ * {@link Operation}s submitted prior to the call to {@code requestHook} do
+ * not affect the demand.
+ *
+ * @param request accepts calls to increase the demand. Not null.
+ * @return this {@link Connection}
+ * @throws IllegalStateException if this method has been called previously or
+ * this {@link Connection} is not active.
+ */
+ public Connection requestHook(Consumer<Long> request);
+
+ /**
* Make this {@link Connection} ready for use. A newly created
* {@link Connection} is active. Calling this method on a {@link Connection}
* that is active is a no-op. If the lifecycle is {@link Lifecycle#INACTIVE}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSource.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSource.java Wed Jun 20 15:38:40 2018 -0400
@@ -30,7 +30,7 @@
import java.util.function.Consumer;
/**
- * Uses the builder pattern to get a {@link Connection}. A {@link getConnection}
+ * Uses the builder pattern to get a {@link Connection}. A {@link DataSource#getConnection}
* method is provided as a convenience.
*
* Implementations must be thread safe.
@@ -42,6 +42,8 @@
* Instances of this type are used to build {@link DataSource}s. This type is
* immutable once configured. No property can be set more than once. No
* property can be set after {@link build} is called.
+ *
+ * ISSUE: Probably need property(DataSourceProperty prop, Object value).
*/
public interface Builder {
@@ -135,6 +137,34 @@
}
/**
+ * Provide a method that the built {@link DataSource} will call to control the
+ * rate of {@link DataSource#connectOperation} submissions. The built
+ * {@link DataSource} will call {@code request} with a positive argument
+ * when the {@link DataSource} is able to accept more
+ * {@link DataSource#connectOperation} submissions. The difference between
+ * the sum of all arguments passed to {@code request} and the number of
+ * calls to {@link DataSource#builder} is the
+ * <i>demand</i>. The demand must always be non-negative. If a call is made to
+ * {@link DataSource#builder} that would make the demand negative that call
+ * throws {@link IllegalStateException}. If {@code requestHook} is not called,
+ * the demand is defined to be infinite.
+ *
+ * <p>
+ * An implementation may choose to delay detection of insufficient demand.
+ * Instead of checking when {@link DataSource#builder} is called an
+ * implementation may choose to check at some later point in Connection
+ * creation such as {@link Connection.Builder.build} or
+ * {@code Connection#connectOperation().submit()} or even later. In any case
+ * an implementation must throw IllegalStateException before allocating
+ * or waiting to allocate scarce resources if the demand is negative.</p>
+ *
+ * @param request accepts calls to increase the demand. Not null.
+ * @return this {@link Builder}
+ * @throws IllegalStateException if this method has been called previously
+ */
+ public Builder requestHook(Consumer<Long> request);
+
+ /**
* Return a DataSource configured as specified.
*
* @return a configured {@link DataSource}. Not {@code null}.
@@ -151,6 +181,7 @@
* the returned builder.
*
* @return a new {@link Connection} builder. Not {@code null}.
+ * @throws IllegalStateException if this {@link DataSource} is closed
*/
public Connection.Builder builder();
@@ -159,6 +190,7 @@
* method for use with try with resources.
*
* @return a {@link Connection}
+ * @throws IllegalStateException if this {@link DataSource} is closed
*/
public default Connection getConnection() {
return builder().build().connect();
@@ -171,6 +203,7 @@
*
* @param handler for errors in the connect {@link Operation}
* @return a {@link Connection}
+ * @throws IllegalStateException if this {@link DataSource} is closed
*/
public default Connection getConnection(Consumer<Throwable> handler) {
return builder().build().connect(handler);
@@ -188,6 +221,7 @@
* @return SQL in the format supported by this {@link DataSource}. Not {@code null}.
* @throws IllegalArgumentException if the {@code format} is not supported or
* if the {@link DataSource} cannot translate the SQL
+ * @throws IllegalStateException if this {@link DataSource} is closed
*/
public default String translateSql(String format, String source) throws SqlException {
throw new IllegalArgumentException("Unsupported format: \"" + format + "\"");
@@ -199,6 +233,7 @@
* ISSUE: Just an idea
*
* @return an array of Strings each of which identifies a supported format
+ * @throws IllegalStateException if this {@link DataSource} is closed
*/
public default List<String> supportedTranslateSqlFormats() {
return new LinkedList<>();
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSourceFactory.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSourceFactory.java Wed Jun 20 15:38:40 2018 -0400
@@ -26,7 +26,6 @@
import java.util.ServiceLoader;
import java.util.ServiceLoader.Provider;
-import java.util.function.Function;
/**
* This interface supports injecting a {@link DataSourceFactory}. The SPI
@@ -42,13 +41,14 @@
* Uses SPI to find a {@link DataSourceFactory} with the requested name or
* {@code null} if one is not found.
*
+ * @param <T>
* @param name the name of the class that implements the factory
* @return a {@link DataSourceFactory} for {@code name} or {@code null} if one
* is not found
*/
- public static DataSourceFactory forName(String name) {
+ public static <T extends DataSourceFactory> T newFactory(String name) {
if (name == null) throw new IllegalArgumentException("DataSourceFactory name is null");
- return ServiceLoader
+ return (T)ServiceLoader
.load(DataSourceFactory.class)
.stream()
.filter(p -> p.type().getName().equals(name))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Examples.java Wed Jun 20 15:38:40 2018 -0400
@@ -0,0 +1,371 @@
+package jdk.incubator.sql2;
+
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Flow;
+import java.util.concurrent.Semaphore;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+
+/**
+ * Simple example code using various aspects of ADBA. These do not necessarily
+ * demonstrate the best way to use each feature, just one way.
+ */
+public class Examples {
+
+ // DataSourceFactory
+
+ public DataSource getDataSource(String url, String user, String pass) {
+ return DataSourceFactory.newFactory("oracle.database.adba")
+ .builder()
+ .url("//host.oracle.com:5521/example")
+ .username("scott")
+ .password("tiger")
+ .build();
+ }
+
+ // RowCountOperation
+
+ public void insertItem(DataSource ds, Item item) {
+ try (Connection conn = ds.getConnection()) {
+ conn.rowCountOperation("insert into tab values (:id, :name, :answer)")
+ .set("id", item.id(), AdbaType.NUMERIC)
+ .set("name", item.name(), AdbaType.VARCHAR)
+ .set("answer", item.answer(), AdbaType.NUMERIC)
+ .submit();
+ }
+ }
+
+ // RowOperation
+
+ public void idsForAnswer(DataSource ds, List<Integer> result, int correctAnswer) {
+ try (Connection conn = ds.getConnection()) {
+ conn.<List<Integer>>rowOperation("select id, name, answer from tab where answer = :target")
+ .set("target", correctAnswer, AdbaType.NUMERIC)
+ .collect(() -> result,
+ (list, row) -> list.add(row.at("id").get(Integer.class)) )
+ .submit();
+ }
+ }
+
+ // RowOperation
+
+ public CompletionStage<List<Item>> itemsForAnswer(DataSource ds, int answer) {
+ try (Connection conn = ds.getConnection()) {
+ return conn.<List<Item>>rowOperation("select id, name, answer from tab where answer = :target")
+ .set("target", 42, AdbaType.NUMERIC)
+ .collect(Collectors.mapping(
+ row -> new Item(row.at("id").get(Integer.class),
+ row.at("name").get(String.class),
+ row.at("answer").get(Integer.class) ),
+ Collectors.toList() ))
+ .submit()
+ .getCompletionStage();
+ }
+ }
+
+ // Independent OperationGroup
+
+ public void insertItemsIndependent(DataSource ds, List<Item> list) {
+ String sql = "insert into tab values (:id, :name, :answer)";
+ try (Connection conn = ds.getConnection()) {
+ OperationGroup group = conn.operationGroup()
+ .independent();
+ for (Item elem : list) {
+ group.rowCountOperation(sql)
+ .set("id", elem.id)
+ .set("name", elem.name)
+ .set("answer", elem.answer)
+ .submit()
+ .getCompletionStage()
+ .exceptionally( t -> {
+ System.out.println(elem.id);
+ return null;
+ });
+ }
+ group.submit();
+ }
+ }
+
+ // Held OperationGroup
+
+ public void insertItemsHold(DataSource ds, List<Item> list) {
+ String sql = "insert into tabone values (:id, :name, :answer)";
+ try (Connection conn = ds.getConnection()) {
+ OperationGroup group = conn.operationGroup()
+ .independent();
+ group.submitHoldingForMoreMembers();
+ for (Item elem : list) {
+ group.rowCountOperation(sql)
+ .set("elem_", elem)
+ .submit()
+ .getCompletionStage()
+ .exceptionally( t -> {
+ System.out.println(elem.id);
+ return null;
+ });
+ }
+ group.releaseProhibitingMoreMembers();
+ }
+ }
+
+ // Parallel, Independent OperationGroup
+
+ public void updateListParallel(List<Item> list, DataSource ds) {
+ String query = "select id from tab where answer = :answer";
+ String update = "update tab set name = :name where id = :id";
+ try (Connection conn = ds.getConnection()) {
+ OperationGroup<Object, Object> group = conn.operationGroup()
+ .independent()
+ .parallel();
+ group.submitHoldingForMoreMembers();
+ for (Item elem : list) {
+ CompletionStage<Integer> idPromise = group.<List<Integer>>rowOperation(query)
+ .set("answer", elem.answer, AdbaType.NUMERIC)
+ .collect( Collector.of(
+ () -> new ArrayList<>(),
+ (l, row) -> l.add( row.at("id").get(Integer.class) ),
+ (l, r) -> l ))
+ .submit()
+ .getCompletionStage()
+ .thenApply( l -> l.get(0) );
+ group.rowCountOperation(update)
+ .set("id", idPromise)
+ .set("name", "the ultimate question")
+ .submit()
+ .getCompletionStage()
+ .exceptionally( t -> {
+ System.out.println(elem.id);
+ return null;
+ });
+ }
+ group.releaseProhibitingMoreMembers();
+ }
+ }
+
+ // Transaction
+
+ public void transaction(DataSource ds) {
+ try (Connection conn = ds.getConnection(t -> System.out.println("ERROR: " + t.toString()))) {
+ Transaction trans = conn.transaction();
+ CompletionStage<Integer> idPromise = conn.<Integer>rowOperation("select empno, ename from emp where ename = :1 for update")
+ .set("1", "CLARK", AdbaType.VARCHAR)
+ .collect(Collectors.collectingAndThen(
+ Collectors.mapping(r -> r.at("empno").get(Integer.class),
+ Collectors.toList()),
+ l -> l.get(0)))
+ .onError( t -> trans.setRollbackOnly() )
+ .submit()
+ .getCompletionStage();
+ conn.<Long>rowCountOperation("update emp set deptno = :1 where empno = :2")
+ .set("1", 50, AdbaType.INTEGER)
+ .set("2", idPromise, AdbaType.INTEGER)
+ .apply(c -> {
+ if (c.getCount() != 1L) {
+ trans.setRollbackOnly();
+ throw new RuntimeException("updated wrong number of rows");
+ }
+ return c.getCount();
+ })
+ .onError(t -> trans.setRollbackOnly() )
+ .submit();
+ // .getCompletionStage()
+ // .exceptionally( t -> { trans.setRollbackOnly(); return null; } ) // incorrect
+ conn.catchErrors();
+ conn.commitMaybeRollback(trans);
+ }
+ }
+
+ // RowPublisherOperation
+
+ public CompletionStage<List<String>> rowSubscriber(DataSource ds) {
+
+ String sql = "select empno, ename from emp";
+ CompletableFuture<List<String>> result = new CompletableFuture<>();
+
+ Flow.Subscriber<Result.RowColumn> subscriber = new Flow.Subscriber<>() {
+
+ Flow.Subscription subscription;
+ List<String> names = new ArrayList<>();
+ int demand = 0;
+
+ @Override
+ public void onSubscribe(Flow.Subscription subscription) {
+ this.subscription = subscription;
+ this.subscription.request(10);
+ demand += 10;
+ }
+
+ @Override
+ public void onNext(Result.RowColumn column) {
+ names.add(column.at("ename").get(String.class));
+ if (--demand < 1) {
+ subscription.request(10);
+ demand += 10;
+ }
+ }
+
+ @Override
+ public void onError(Throwable throwable) {
+ result.completeExceptionally(throwable);
+ }
+
+ @Override
+ public void onComplete() {
+ result.complete(names);
+ }
+
+ };
+
+ try (Connection conn = ds.getConnection()) {
+ return conn.<List<String>>rowPublisherOperation(sql)
+ .subscribe(subscriber, result)
+ .submit()
+ .getCompletionStage();
+ }
+ }
+
+ // Control Operation Submission Rate
+
+ public CompletionStage<Long> insertRecords(DataSource ds, DataInputStream in) {
+ String insert = "insert into tab values (@record)";
+ try (Connection conn = ds.getConnection()) {
+ OperationGroup<Long, Long> group = conn.<Long, Long>operationGroup()
+ .independent()
+ .collect(Collectors.summingLong(c -> c));
+ group.submitHoldingForMoreMembers();
+ Semaphore demand = new Semaphore(0);
+ conn.requestHook( n -> demand.release(n.intValue()) );
+ while (in.available() > 0) {
+ demand.acquire(1); // user thread blocked by Semaphore, not by ADBA
+ group.<Long>rowCountOperation(insert)
+ .set("record", in.readUTF(), AdbaType.VARCHAR)
+ .apply(c -> c.getCount())
+ .submit();
+ }
+ return group.releaseProhibitingMoreMembers()
+ .getCompletionStage();
+ }
+ catch (IOException | InterruptedException ex) {
+ throw new SqlException(ex);
+ }
+ }
+
+ // ArrayRowCountOperation
+
+ public CompletionStage<Long> arrayInsert(DataSource ds,
+ List<Integer> ids,
+ List<String> names,
+ List<Integer> answers) {
+ String sql = "insert into tab values (?, ?, ?)";
+ try (Connection conn = ds.getConnection()) {
+ return conn.<Long>arrayRowCountOperation(sql)
+ .collect(Collectors.summingLong( c -> c.getCount() ))
+ .set("1",ids, AdbaType.INTEGER)
+ .set("2", names, AdbaType.VARCHAR)
+ .set("3", answers, AdbaType.INTEGER)
+ .submit()
+ .getCompletionStage();
+ }
+ }
+
+ // ArrayRowCountOperation -- transposed
+
+ public CompletionStage<Long> transposedArrayInsert(DataSource ds, List<Item> items) {
+ String sql = "insert into tab values (?, ?, ?)";
+ try (Connection conn = ds.getConnection()) {
+ return conn.<Long>arrayRowCountOperation(sql)
+ .collect(Collectors.summingLong( c -> c.getCount() ))
+ .set("1", items.stream().map(Item::id).collect(Collectors.toList()), AdbaType.INTEGER)
+ .set("2", items.stream().map(Item::name).collect(Collectors.toList()), AdbaType.VARCHAR)
+ .set("3", items.stream().map(Item::answer).collect(Collectors.toList()), AdbaType.INTEGER)
+ .submit()
+ .getCompletionStage();
+ }
+ }
+
+ // OutOperation
+
+ public CompletionStage<Item> getItem(DataSource ds, int id) {
+ String sql = "call item_for_id(:id, :name, :answer)";
+ try (Connection conn = ds.getConnection()) {
+ return conn.<Item>outOperation(sql)
+ .set("id", id, AdbaType.INTEGER)
+ .outParameter("name", AdbaType.VARCHAR)
+ .outParameter("answer", AdbaType.INTEGER)
+ .apply( out -> new Item(id,
+ out.at("name").get(String.class),
+ out.at("answer").get(Integer.class)) )
+ .submit()
+ .getCompletionStage();
+ }
+ }
+
+ // MultiOperation
+
+ // LocalOperation
+
+ // ConnectionProperty
+
+ // Sharding
+
+ // TransactionOutcome
+
+ // Column navigation
+
+ // Error handling
+
+ static public class Item {
+ public int id;
+ public String name;
+ public int answer;
+
+ public Item(int i, String n, int a) {
+ id =i;
+ name = n;
+ answer = a;
+ }
+
+ public int id() {
+ return id;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public int answer() {
+ return answer;
+ }
+ }
+
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/MultiOperation.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/MultiOperation.java Wed Jun 20 15:38:40 2018 -0400
@@ -33,14 +33,15 @@
/**
* A multi-operation is an {@link Operation} that returns one or more results in
* addition to the out result defined by the {@link Operation}. Each result is
- * processed by an Operation. The Operations can be created by calling rowOperation,
- * rowProcessorOperation, or countOperation if the kind of results is known. These
- * results are processed in the order the Operations are submitted. Any results
- * not processed by an explicit Operation is processed by calling the appropriate
- * handler specified by onRows or onCount. If any result is an error that error
- * is processed by calling the handler specified by onError. If the appropriate
- * handler is not specified that result is ignored, including errors.
- *
+ * processed by an Operation. The Operations can be created by calling
+ * rowOperation, rowProcessorOperation, or countOperation if the kind of results
+ * is known. These results are processed in the order the Operations are
+ * submitted. Any results not processed by an explicit Operation is processed by
+ * calling the appropriate handler specified by onRows or onCount. If any result
+ * is an error that error is processed by calling the handler specified by
+ * onError. If the appropriate handler is not specified that result is ignored,
+ * including errors.
+ *
* ISSUE: Should this have a collector?
*
* @param <T> The type of the result of this {@link Operation}
@@ -51,86 +52,90 @@
* Returns a {@link RowOperation} to process a row sequence result. The
* {@link Operation}s are executed in the order they are submitted. If a
* result is of the wrong type for the next submitted {@link Operation} the
- * {@link MultiOperation} is completed with
- * {@link IllegalStateException}.
+ * {@link MultiOperation} is completed with {@link IllegalStateException}.
*
* @return a {@link RowOperation} that is part of this {@link MultiOperation}
*/
public RowOperation<T> rowOperation();
/**
- * Returns a {@link RowProcessorOperation} to process a row sequence result. The
- * {@link Operation}s are executed in the order they are submitted. If a
+ * Returns a {@link RowPublisherOperation} to process a row sequence result.
+ * The {@link Operation}s are executed in the order they are submitted. If a
* result is of the wrong type for the next submitted {@link Operation} the
- * {@link MultiOperation} is completed with
- * {@link IllegalStateException}.
+ * {@link MultiOperation} is completed with {@link IllegalStateException}.
*
- * @return a {@link RowProcessorOperation} that is part of this {@link MultiOperation}
+ * @return a {@link RowPublisherOperation} that is part of this
+ * {@link MultiOperation}
*/
- public RowProcessorOperation<T> rowProcessorOperation();
+ public RowPublisherOperation<T> rowProcessorOperation();
/**
- * Returns a {@link CountOperation} to process a count result. The {@link Operation}s
- * are executed in the order they are submitted. If a result is of the wrong
- * type for the next submitted Operation the {@link MultiOperation} is completed
- * with {@link IllegalStateException}.
+ * Returns a {@link RowCountOperation} to process a count result. The
+ * {@link Operation}s are executed in the order they are submitted. If a
+ * result is of the wrong type for the next submitted Operation the
+ * {@link MultiOperation} is completed with {@link IllegalStateException}.
*
- * @return a {@link CountOperation} that is part of this {@link MultiOperation}
+ * @return a {@link RowCountOperation} that is part of this
+ * {@link MultiOperation}
*/
- public CountOperation<T> countOperation();
+ public RowCountOperation<T> rowCountOperation();
/**
- * Provides a handler for trailing count results. The provided handler is called for
- * each count result not processed by CountOperation. When called the first argument is the number of results
- * that preceeded the current result. The second argument is a
- * {@link CountOperation} that will process the current result. This
- * {@link CountOperation} has not been configured in any way nor has it been
- * submitted. The handler configures the {@link CountOperation} and submits
- * it. The count result is processed when the {@link CountOperation} is
- * submitted. If the {@link CountOperation} is not submitted when the handler
- * returns the count result is ignored.
- *
+ * Provides a handler for trailing count results. The provided handler is
+ * called for each count result not processed by RowCountOperation. When
+ * called the first argument is the number of results that preceeded the
+ * current result. The second argument is a {@link RowCountOperation} that
+ * will process the current result. This {@link RowCountOperation} has not
+ * been configured in any way nor has it been submitted. The handler
+ * configures the {@link RowCountOperation} and submits it. The count result
+ * is processed when the {@link RowCountOperation} is submitted. If the
+ * {@link RowCountOperation} is not submitted when the handler returns the
+ * count result is ignored.
+ *
* If this method is not called any trailing count results are ignored.
*
* @param handler not null
* @return this MultiOperation
* @throws IllegalStateException if this method was called previously
*/
- public MultiOperation<T> onCount(BiConsumer<Integer, CountOperation<T>> handler);
+ public MultiOperation<T> onCount(BiConsumer<Integer, RowCountOperation<T>> handler);
/**
- * Provides a handler for trailing row sequence results. The provided handler is called
- * for each row sequence result not processed by a RowOperation. When called the first argument is the number
- * of results that preceeded the current result. The second argument is a
- * {@link RowOperation} that will process the current result. This
- * {@link RowOperation} has not been configured in any way nor has it been
- * submitted. The handler configures the {@link RowOperation} and submits it.
- * The row sequence result is processed when the {@link RowOperation} is
- * submitted. If the {@link RowOperation} is not submitted when the handler
- * returns, the row sequence result is ignored.
- *
+ * Provides a handler for trailing row sequence results. The provided handler
+ * is called for each row sequence result not processed by a RowOperation.
+ * When called the first argument is the number of results that preceeded the
+ * current result. The second argument is a {@link RowOperation} that will
+ * process the current result. This {@link RowOperation} has not been
+ * configured in any way nor has it been submitted. The handler configures the
+ * {@link RowOperation} and submits it. The row sequence result is processed
+ * when the {@link RowOperation} is submitted. If the {@link RowOperation} is
+ * not submitted when the handler returns, the row sequence result is ignored.
+ *
* If this method is not called any trailing row sequence results are ignored.
- *
- * ISSUE: Should there be a version of this method that provides
- * RowProcessorOperations? If so only one of that method or this one can be called.
+ *
+ * ISSUE: Should there be a version of this method that provides
+ * RowProcessorOperations? If so only one of that method or this one can be
+ * called.
*
* @param handler
* @return This MultiOperation
* @throws IllegalStateException if this method was called previously
*/
public MultiOperation<T> onRows(BiConsumer<Integer, RowOperation<T>> handler);
-
+
/**
- * Provides an error handler for this {@link Operation}. The provided handler
- * is called for each error that occurs. When called the first argument is the
+ * Provides an error handler for this {@link Operation}. The provided handler
+ * is called for each error that occurs. When called the first argument is the
* number of results, including errors, that preceeded the current error. The
* second argument is a {@link Throwable} corresponding to the error. When the
- * handler returns processing of the MultiOperation results continues.
- * Only one onError method may be called.
- *
+ * handler returns processing of the MultiOperation results continues. Only
+ * one onError method may be called.
+ *
* @param handler a BiConsumer that handles an error
* @return this MultiOperation
- * @throws IllegalStateException if this method was called previously
+ * @throws IllegalStateException if this method or
+ * {@link MultiOperation#onError(java.util.function.Consumer)} was called
+ * previously
*/
public MultiOperation<T> onError(BiConsumer<Integer, Throwable> handler);
// Covariant overrides
@@ -139,15 +144,15 @@
* This handler is called if the execution fails completely. If the execution
* returns any individual results, even if any or all of those results are
* errors, this handler is not called.
- *
+ *
* @param handler
- * @return
+ * @return
*/
@Override
public MultiOperation<T> onError(Consumer<Throwable> handler);
-
+
@Override
- public MultiOperation<T> apply(Function<Result.OutParameterMap, ? extends T> processor);
+ public MultiOperation<T> apply(Function<Result.OutColumn, ? extends T> processor);
@Override
public MultiOperation<T> outParameter(String id, SqlType type);
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OperationGroup.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OperationGroup.java Wed Jun 20 15:38:40 2018 -0400
@@ -26,7 +26,6 @@
import java.time.Duration;
import java.util.concurrent.CompletionStage;
-import java.util.concurrent.Flow;
import java.util.function.Consumer;
import java.util.logging.Logger;
import java.util.stream.Collector;
@@ -195,7 +194,7 @@
*
* ISSUE: Need a better name.
*
- * @return a Submission
+ * @return a Submission for this OperationGroup
* @throws IllegalStateException if this {@link OperationGroup} has been
* submitted
*/
@@ -209,19 +208,16 @@
* queue this {@link OperationGroup} will be completed and removed from the
* queue.
*
- * Calling this method when this {@link OperationGroup} is not held is a
- * no-op.
- *
* Note: There is no covariant override of this method in Connection as there
* is only a small likelihood of needing it.
*
* ISSUE: Need a better name.
*
- * @return this OperationGroup
+ * @return the same Submission that was returned by {@link OperationGroup#submitHoldingForMoreMembers}
* @throws IllegalStateException if this {@link OperationGroup} has been
* completed or is not held.
*/
- public OperationGroup<S, T> releaseProhibitingMoreMembers();
+ public Submission<T> releaseProhibitingMoreMembers();
/**
* Provides a {@link Collector} to reduce the results of the member
@@ -276,7 +272,7 @@
}
/**
- * Return a new {@link ArrayCountOperation}.
+ * Return a new {@link ArrayRowCountOperation}.
* <p>
* Usage Note: Frequently use of this method will require a type witness to
* enable correct type inferencing.
@@ -287,30 +283,33 @@
* .submit ...
* </code></pre>
*
- * @param <R> the result type of the returned {@link ArrayCountOperation}
+ * @param <R> the result type of the returned {@link ArrayRowCountOperation}
* @param sql SQL to be executed. Must return an update count.
- * @return a new {@link ArrayCountOperation} that is a member of this
+ * @return a new {@link ArrayRowCountOperation} that is a member of this
* {@link OperationGroup}
* @throws IllegalStateException if the {@link OperationGroup} has been
* submitted and is not held
*/
- public <R extends S> ArrayCountOperation<R> arrayCountOperation(String sql);
+ public <R extends S> ArrayRowCountOperation<R> arrayRowCountOperation(String sql);
/**
- * Return a new {@link CountOperation}.
+ * Return a new {@link ParameterizedRowCountOperation}.
*
* @param <R> the result type of the returned {@link CountOperation}
* @param sql SQL to be executed. Must return an update count.
- * @return an new {@link CountOperation} that is a member of this
+ * @return an new {@link ParameterizedRowCountOperation} that is a member of this
* {@link OperationGroup}
* @throws IllegalStateException if the {@link OperationGroup} has been
* submitted and is not held
*/
- public <R extends S> ParameterizedCountOperation<R> countOperation(String sql);
+ public <R extends S> ParameterizedRowCountOperation<R> rowCountOperation(String sql);
/**
* Return a new {@link Operation} for a SQL that doesn't return any result,
* for example DDL. The result of this Operation is always null.
+ *
+ * The result of the returned Operation must be Void but specifying that here
+ * causes problems.
*
* @param sql SQL for the {@link Operation}.
* @return a new {@link Operation} that is a member of this
@@ -350,18 +349,18 @@
public <R extends S> ParameterizedRowOperation<R> rowOperation(String sql);
/**
- * Return a new {@link RowProcessorOperation} that is a member {@link Operation}
- * of this {@link OperationGroup}.
- *
+ * Return a new {@link ParameterizedRowPublisherOperation} that is a member
+ * {@link Operation} of this {@link OperationGroup}.
+ *
* @param <R> the type of the result of the returned
- * {@link RowProcessorOperation}
+ * {@link ParameterizedRowPublisherOperation}
* @param sql SQL for the {@link Operation}. Must return a row sequence.
- * @return a new {@link RowProcessorOperation} that is a member of this
- * {@link OperationGroup}
+ * @return a new {@link ParameterizedRowPublisherOperation} that is a member
+ * of this {@link OperationGroup}
* @throws IllegalStateException if the {@link OperationGroup} has been
* submitted and is not held
*/
- public <R extends S> RowProcessorOperation<R> rowProcessorOperation(String sql);
+ public <R extends S> ParameterizedRowPublisherOperation<R> rowPublisherOperation(String sql);
/**
* Return a new {@link MultiOperation} that is a member
@@ -383,6 +382,11 @@
* transaction is ended with a commit unless the {@link Transaction} has been
* {@link Transaction#setRollbackOnly} in which case the transaction is ended
* with a rollback.
+ *
+ * <p>
+ * An endTransaction Operation may be skipped. To insure that it will not be
+ * skipped it should immediately follow a catch Operation. All end transaction
+ * convenience methods do so.</p>
*
* The type argument {@link S} of the containing {@link OperationGroup} must
* be a supertype of {@link TransactionOutcome}.
@@ -398,7 +402,8 @@
/**
* Convenience method that creates and submits a endTransaction
* {@link Operation} that commits by default but can be set to rollback by
- * calling {@link Transaction#setRollbackOnly}.
+ * calling {@link Transaction#setRollbackOnly}. The endTransaction Operation
+ * is never skipped.
*
* @param trans the Transaction that determines whether the {@link Operation} is a
* database commit or a database rollback.
@@ -407,6 +412,7 @@
* submitted and is not held or is parallel.
*/
public default CompletionStage<TransactionOutcome> commitMaybeRollback(Transaction trans) {
+ catchErrors();
return this.endTransactionOperation(trans).submit().getCompletionStage();
}
@@ -422,44 +428,6 @@
public <R extends S> LocalOperation<R> localOperation();
/**
- * Returns a Flow.Processor that subscribes to a sequence of Operations and
- * produces a sequence of corresponding Submissions.The Operations must be
- * members of this OperationGroup. Calling Subscription.onNext with any
- * Operation that is not a member of this OperationGroup, that is was not
- * created by calling one of the Operation factory methods on this
- * OperationGroup, will cause the Subscription to be canceled and call
- * Subscriber.onError with IllegalArgumentException. The method
- * Subscription.onNext will call submit on each Operation it is passed and
- * publish the resulting Submission. Since an Operation can only be submitted
- * once, submitting an Operation and calling onNext with that submitted
- * Operation will cause the Subscription to be canceled and Subscriber.onError
- * to be called with IllegalStateException. The Processor does not retain
- * Submissions to produce to a subsequently attached Subscriber.
- *
- * If there is no Subscriber to the Processor, the Processor will request
- * Operations as appropriate. If there is a Subscriber to the Processor, the
- * Processor will request Operations no faster than the Subscriber requests
- * Submissions.
- *
- * Each call to this method returns a new Flow.processor. The Submissions
- * published to each Processor are exactly those generated by calling submit
- * on the Operations passed as arguments to onNext on the same Processor.
- * Calling this method while there is an active Processor will throw
- * IllegalStateException.
- *
- * Note: If any Operation is submitted directly, that is by calling submit
- * rather than passing it to onNext, the Submission returned by the submit
- * call will not be published.
- *
- * @param <R>
- * @return a Flow.Processor that accepts {@link Operation}s and generates
- * {@link Submission}s
- * @throws IllegalStateException if there is an active Processor or if this
- * {@link OperationGroup} is submitted and not held
- */
- public <R extends S> Flow.Processor<Operation<R>, Submission<R>> operationProcessor();
-
- /**
* Supply a {@link Logger} for the implementation of this
* {@link OperationGroup} to use to log significant events. Exactly what
* events are logged, at what Level the events are logged and with what
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OutOperation.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OutOperation.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -60,7 +60,7 @@
* @throws IllegalStateException if this method has been called previously on
* this {@link Operation} or this {@link Operation} has been submitted.
*/
- public OutOperation<T> apply(Function<Result.OutParameterMap, ? extends T> processor);
+ public OutOperation<T> apply(Function<Result.OutColumn, ? extends T> processor);
// Covariant overrides
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedOperation.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedOperation.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedRowCountOperation.java Wed Jun 20 15:38:40 2018 -0400
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017, 2018, 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 jdk.incubator.sql2;
+
+import java.time.Duration;
+import java.util.concurrent.CompletionStage;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * A {@link ParameterizedRowCountOperation} is a {@link ParameterizedOperation} that returns a count.
+ *
+ * @param <T> the type of the result of this {@link Operation}
+ */
+public interface ParameterizedRowCountOperation<T> extends ParameterizedOperation<T>, RowCountOperation<T> {
+
+ /**
+ * Returns a {@link RowOperation} to process the auto-generated keys, if any, returned
+ * by this {@link Operation}. If no keys are named the columns of the returned
+ * rows are implementation dependent. If keys are specified the columns of the
+ * returned rows are the keys. The {@link RowOperation} must be submitted before this
+ * {@link Operation} is submitted. If it has not submitting this {@link Operation} will
+ * result throw {@link IllegalStateException}.
+ *
+ * ISSUE: Should this be in {@link RowCountOperation}?
+ *
+ * @param keys the names of the returned columns or null.
+ * @return A RowOperation that will process the auto-generated keys
+ * @throws IllegalStateException if this method has already been called on this
+ * {@link Operation} or if this {@link Operation} has already been submitted.
+ */
+ public RowOperation<T> returning(String ... keys);
+
+ // Covariant overrides
+
+ @Override
+ public ParameterizedRowCountOperation<T> onError(Consumer<Throwable> handler);
+
+ @Override
+ ParameterizedRowCountOperation<T> apply(Function<Result.RowCount, ? extends T> processor);
+
+ @Override
+ public ParameterizedRowCountOperation<T> set(String id, Object value);
+
+ @Override
+ public ParameterizedRowCountOperation<T> set(String id, Object value, SqlType type);
+
+ @Override
+ public ParameterizedRowCountOperation<T> set(String id, CompletionStage<?> source);
+
+ @Override
+ public ParameterizedRowCountOperation<T> set(String id, CompletionStage<?> source, SqlType type);
+
+ @Override
+ public ParameterizedRowCountOperation<T> timeout(Duration minTime);
+
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedRowOperation.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedRowOperation.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -46,7 +46,7 @@
public ParameterizedRowOperation<T> fetchSize(long rows) throws IllegalArgumentException;
@Override
- public <A, S extends T> ParameterizedRowOperation<T> collect(Collector<? super Result.Row, A, S> c);
+ public <A, S extends T> ParameterizedRowOperation<T> collect(Collector<? super Result.RowColumn, A, S> c);
@Override
public ParameterizedRowOperation<T> set(String id, Object value, SqlType type);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedRowPublisherOperation.java Wed Jun 20 15:38:40 2018 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, 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 jdk.incubator.sql2;
+
+import java.time.Duration;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Flow;
+import java.util.function.Consumer;
+
+/**
+ * An Operation that accepts parameters, subscribes to a sequence of rows, and
+ * returns a result.
+ *
+ * @param <T> the type of the result of this {@link Operation}
+ */
+public interface ParameterizedRowPublisherOperation<T>
+ extends RowPublisherOperation<T>, ParameterizedOperation<T> {
+
+ // Covariant overrides
+
+ @Override
+ public ParameterizedRowPublisherOperation<T> subscribe(Flow.Subscriber<? super Result.RowColumn> subscriber,
+ CompletionStage<? extends T> result);
+
+ @Override
+ public ParameterizedRowPublisherOperation<T> set(String id, Object value, SqlType type);
+
+ @Override
+ public ParameterizedRowPublisherOperation<T> set(String id, CompletionStage<?> source, SqlType type);
+
+ @Override
+ public ParameterizedRowPublisherOperation<T> set(String id, CompletionStage<?> source);
+
+ @Override
+ public ParameterizedRowPublisherOperation<T> set(String id, Object value);
+
+ @Override
+ public ParameterizedRowPublisherOperation<T> onError(Consumer<Throwable> handler);
+
+ @Override
+ public ParameterizedRowPublisherOperation<T> timeout(Duration minTime);
+
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/PrimitiveOperation.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/PrimitiveOperation.java Wed Jun 20 15:38:40 2018 -0400
@@ -35,8 +35,8 @@
* class of errors. The two types are not distinguished in the JavaDoc as making
* such a distinction would not add clarity.
*
- * @see Operation
- * @see OperationGroup#catchOperation
+ * @see Operation
+ * @see OperationGroup#catchOperation
*/
public interface PrimitiveOperation<T> {
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Result.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Result.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -22,16 +22,16 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+package jdk.incubator.sql2;
-package jdk.incubator.sql2;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.function.Consumer;
/**
- * All or part of the result of a database operation (lower case).
- *
- * A {@link Result} is valid only for the duration of the call it is passed to. Once
- * that call has returned, the {@link Result} passed to that call is invalid and any
- * calls to it throw {@link IllegalStateException}. {@link Result}s are not required to be
- * thread-safe.
*
*/
public interface Result {
@@ -39,96 +39,273 @@
/**
* A {@link Result} that is just a number of rows modified, a {@link Long}.
*
- * Note: It is certainly true that this is not needed; {@link Long} could be used
- * instead. Seems like there might be a documentational advantage to having
- * this type. If you don't like it, just mentally replace it with {@link Long}
- * everywhere it appears.
+ * Note: It is certainly true that this is not needed; {@link Long} could be
+ * used instead. Seems like there might be a documentational advantage to
+ * having this type. If you don't like it, just mentally replace it with
+ * {@link Long} everywhere it appears.
*/
- public static interface Count extends Result {
+ public static interface RowCount extends Result {
/**
*
- * @return The number of rows returned
+ * @return
*/
public long getCount();
}
/**
- * A {@link Result} where the components can be retrieved by name. What
- * constitutes a name is implementation dependent.
- *
+ * A mutable handle to one value of an ordered sequence of columns of a row or
+ * of out parameters. Columns have a 1-based index and optionally an
+ * identifier. Identifiers are not guaranteed to be unique. Only {@code clone}
+ * and {@code slice} create new instances. All other methods return this
+ * instance (modifying it if necessary) including {@code forEach},
+ * {@code next}, and {@code iterator}.
*/
- public static interface ResultMap extends Result {
+ public interface Column extends Result, Iterable<Column>, Iterator<Column>, Cloneable {
+
+ /**
+ * Return the value of this column as an instance of the given type.
+ *
+ * @param <T>
+ * @param type
+ * @return the value of this {@link Column}
+ */
+ public <T> T get(Class<T> type);
+
+ /**
+ * Return the value of this {@link Column} as an instance of the default
+ * Java type for this column.
+ *
+ * @param <T>
+ * @return the value of this {@link Column}
+ */
+ public default <T> T get() {
+ return get(javaType());
+ }
+
+ /**
+ * Return the identifier of this {@link Column}. May be null.
+ *
+ * @return the identifier of this {@link Column}. May be null
+ */
+ public String identifier();
+
+ /**
+ * Return the 1-based index of this {@link Column}. The returned value is
+ * relative to the slice if this {@link Column} is the result of a call to
+ * {@code slice()}. {@code
+ * col.slice(n).index() == 1}.
+ *
+ * @return the index of this {@link Column}
+ */
+ public int index();
+
+ /**
+ * Return the 1-based index of this {@link Column} relative to the original
+ * sequence of values.
+ * {@code col.absoluteIndex() == col.slice(n).absoluteIndex()}.
+ *
+ * @return the absolute 1-based index of this {@link Column}
+ */
+ public int absoluteIndex();
+
+ /**
+ * Return the SQL type of the value of this {@link Column}.
+ *
+ * @return the SQL type of this value
+ */
+ public SqlType sqlType();
+
+ /**
+ * Return the Java type that best represents the value of this
+ * {@link Column}.
+ *
+ * @param <T>
+ * @return a {@link Class} that best represents the value of this
+ * {@link Column}
+ */
+ public <T>Class<T> javaType();
+
+ /**
+ * The length of the current value if defined.
+ *
+ * @return
+ * @throws UnsupportedOperationException if the length of the current value
+ * is undefined
+ */
+ public long length();
+
+ /**
+ * Return the number of remaining values accessible by this {@link Column}
+ * excluding the current value. This is the number of times {@code next()}
+ * can be called before {@code hasNext()} returns false.
+ *
+ * @return the number of values remaining
+ */
+ public int numberOfValuesRemaining();
/**
- * Return the value indicated by the {@code id}. The {@code id} may be either the id for an
- * OUT parameter marker or for a column. See {@link OutOperation} and
- * {@link RowOperation}.
+ * Modify this {@link Column} to point to a value identified by id.
+ *
+ * @apiNote The value specified for {@code id} represents the name of a
+ * column or parameter marker for the underlying data source and is
+ * implementation specific. This may be a simple SQL identifier, a quoted
+ * identifier, or any other type of identifier supported by the data source.
+ * <p>
+ * Consult your implementation's documentation for additional
+ * information.
+ *
+ * @param id an identifier. Not null
+ * @return this {@link Column}
+ * @throws NoSuchElementException if id does not identify exactly one value
+ */
+ public Column at(String id);
+
+ /**
+ * Modify this {@link Column} to point to the value at {@code index}. The
+ * first value is at index 1. Negative numbers count back from the last
+ * value. The last value is at index -1.
*
- * @param <T> the type of the returned value
- * @param id the name of the column or OUT parameter marker
- * @param type the value indicated by {@code id} is converted to this type
- * @return a value of type {@code T}
- * @throws IllegalArgumentException if id is not the identifier of a value
- * in this {@link ResultMap}
- * @throws IllegalStateException if the call that was passed this {@link ResultMap} has
- * ended
- * @throws ClassCastException if the returned value cannot be converted to the
- * specified type -- ISSUE: Not really a class cast. Maybe a new unchecked exception.
+ * @param index a new index
+ * @return this {@link Column}
+ * @throws NoSuchElementException if {@code index > length} or
+ * {@code index < -length}
*/
- public <T> T get(String id, Class<T> type);
+ public Column at(int index);
+
+ /**
+ * Modify this {@link Column} to point to the value at the current index +
+ * {@code offset}. If {@code offset} is 0 this is a noop. If {@code offset}
+ * is negative the new index is less than the current index. If the new
+ * index would be less than 1 or greater than length this {@link Column} is
+ * not modified and {@link IllegalArgumentException} is thrown.
+ *
+ * @param offset an increment to the current index
+ * @return this {@link Column}
+ * @throws NoSuchElementException if the new index would be less than 1 or
+ * greater than {@code length}
+ */
+ public default Column next(int offset) {
+ int newIndex = index() + offset;
+ if (offset > numberOfValuesRemaining() || newIndex < 1) {
+ throw new NoSuchElementException();
+ }
+ return at(newIndex);
+ }
/**
- * Returns a {@code {@link String}[]} that contains the identifiers that reference the
- * values of this {@link ResultMap} in the same order these values are returned by the
- * database. A {@code null} value in the array means there is a returned value for
- * which no identifier was defined. There is no way to retrieve such a
- * value.
+ * Return a new {@link Column} that is a handle to a subsequence of the
+ * sequence of values referenced by this {@link Column}. The subsequence
+ * consists of {@code numValues} number of values. If {@code numValues} is
+ * positive the values are the value of this column and its successors. If
+ * {@code numValues} is negative the values are the predecessors of this
+ * column not including this {@link Column}. The order of the values of the
+ * new {@link Column} is the same as the order of the values of this
+ * {@link Column}. The returned {@link Column} points to the first value of
+ * the slice. This {@link Column} is not modified.
+ *
+ * @param numValues the number of columns to include in the slice
+ * @return a new {@link Column}.
+ * @throws NoSuchElementException if the current index plus
+ * {@code numValues} is greater than the number of values of this
+ * {@link Column} or less than 1
+ */
+ public Column slice(int numValues);
+
+ /**
+ * Return a new {@link Column} that is a duplicate of this {@link Column}.
+ * This {@link Column} is not modified.
+ *
+ * @return a new {@link Column}
+ */
+ public Column clone();
+
+ /**
+ * Modify this {@link Column} to point to the next value in the sequence.
*
- * By default the values in the array are the identifier portion of the out
- * parameter markers in the SQL. Alternatively the implementation may assign
- * other identifiers, typically column names or aliases. If there
- * are values that have no associated identifier the corresponding value in
- * the array will be null.
+ * @return this {@link Column}
+ * @throws NoSuchElementException if the new index would be greater than
+ * {@code length}
+ */
+ @Override
+ public default Column next() {
+ return next(1);
+ }
+
+ @Override
+ public default boolean hasNext() {
+ return numberOfValuesRemaining() > 0;
+ }
+
+ @Override
+ public default void forEach(Consumer<? super Column> action) {
+ do {
+ action.accept(this);
+ } while (hasNext());
+ }
+
+ @Override
+ public default Column iterator() {
+ return this;
+ }
+
+ /**
+ * TODO This almost certainly works correctly but it doesn't integrate well
+ * with the other access patterns. A better approach would be a Spliterator
+ * that overrides trySplit and creates new slices for each batch.
*
- * @return an array containing the value identifiers. Not {@code null}.
- * @throws IllegalStateException if the call that was passed this {@link ResultMap} has
- * ended
+ * There is a fundamental problem with mixing Spliterator with the other
+ * access patterns. The other patterns assume navigation from one column to
+ * an arbitrary other column. Spliterator.trySplit can divide the column
+ * sequence in arbitrary places invalidating the assumption about column
+ * navigation.
+ *
+ * @return a {@link java.util.Spliterator}
*/
- public String[] getIdentifiers();
+ @Override
+ public default Spliterator<Column> spliterator() {
+ List list = new ArrayList<>(numberOfValuesRemaining());
+ this.clone().forEach(c -> list.add(c.slice(1)));
+ return java.util.Spliterators.spliterator(list.toArray(), numberOfValuesRemaining());
+ }
}
/**
- * Used by {@link OutOperation} to expose the out parameters of a call.
+ * Used by {@link OutOperation} to expose the out parameters of a stored
+ * procedure call.
+ *
+ * This exists to allow for future additions.
*/
- public static interface OutParameterMap extends ResultMap {
+ public interface OutColumn extends Column {
+
}
/**
* Used by {@link RowOperation} to expose each row of a row sequence.
*/
- public static interface Row extends ResultMap {
+ public static interface RowColumn extends Column {
/**
- * The count of {@link Row}s in the {@link Row} sequence preceeding this {@link Row}. For the first
- * row in the Row sequence the {@link rowNumber} is 0.
+ * The count of rows in the row sequence preceeding this {@link RowColumn}.
+ * For the first row in the row sequence the {@code rowNumber} is 0.
*
- * @return the count of {@link Row}s in the {@link Row} sequence preceeding this {@link Row}
- * @throws IllegalStateException if the call that was passed this {@link Result} has
- * ended
+ * @return the count of rows in the row sequence preceeding this
+ * {@link RowColumn}
+ * @throws IllegalStateException if the call that was passed this
+ * {@link Result} has ended
*/
public long rowNumber();
/**
- * Terminate processing of the rows in this {@link RowOperation}. The result of the
- * call that was passed this {@link Row} will be the result of the {@link Operation}. No
- * further rows in the row sequence will be processed. All subsequent rows,
- * if any, will be ignored. Any rows already fetched will not be processed.
- * Any rows not yet fetched may or may not be fetched. If fetched they will
- * not be processed.
+ * Terminate processing of the rows in this {@link RowOperation}. No further
+ * rows in the row sequence will be processed. All subsequent rows, if any,
+ * will be ignored. Any rows already fetched will not be processed. Any rows
+ * not yet fetched may or may not be fetched. If fetched they will not be
+ * processed. The RowOperation will be completed normally, as though the
+ * current row were the last row of the row sequence.
*
- * @throws IllegalStateException if the call that was passed this {@link Result} has
- * ended
+ * @throws IllegalStateException if the call that was passed this
+ * {@link RowColumn} has ended
*/
public void cancel();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowCountOperation.java Wed Jun 20 15:38:40 2018 -0400
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, 2018, 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 jdk.incubator.sql2;
+
+import java.time.Duration;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * An {@link Operation} that returns a count.
+ *
+ * @param <T> the type of the result of the {@link Operation}
+ * @see ParameterizedCountOperation
+ */
+public interface RowCountOperation<T> extends Operation<T> {
+
+ /**
+ * Sets the result processor for this {@link Operation}.
+ *
+ * @param function processes the count produced by executing this
+ * {@link Operation} and returns the result
+ * @return this {@link RowCountOperation}
+ * @throws IllegalStateException if this method has been called previously
+ */
+ public RowCountOperation<T> apply(Function<Result.RowCount, ? extends T> function);
+
+ @Override
+ public RowCountOperation<T> onError(Consumer<Throwable> handler);
+
+ @Override
+ public RowCountOperation<T> timeout(Duration minTime);
+
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowOperation.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowOperation.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -25,7 +25,9 @@
package jdk.incubator.sql2;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
+import java.util.function.Supplier;
import java.util.stream.Collector;
/**
@@ -63,7 +65,21 @@
* @throws IllegalStateException if this method had been called previously or
* this Operation has been submitted.
*/
- public <A, S extends T> RowOperation<T> collect(Collector<? super Result.Row, A, S> c);
+ public <A, S extends T> RowOperation<T> collect(Collector<? super Result.RowColumn, A, S> c);
+
+ /**
+ * Convenience method to collect the rows when the accumulated result is the
+ * final result.
+ *
+ * @param <S> the type of the accumulated result
+ * @param supplier supplies the accumulated result
+ * @param accumulator accumulates each RowColumn into the accumulated result
+ * @return this RowOperation
+ */
+ public default <S extends T> RowOperation<T> collect(Supplier<S> supplier,
+ BiConsumer<S, Result.RowColumn> accumulator) {
+ return collect(Collector.of(supplier, accumulator, (l, r) -> l));
+ }
@Override
public RowOperation<T> onError(Consumer<Throwable> handler);
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowProcessorOperation.java Wed Jun 20 15:12:52 2018 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,215 +0,0 @@
-/*
- * Copyright (c) 2017, 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 jdk.incubator.sql2;
-
-import java.time.Duration;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.Flow;
-import java.util.function.Consumer;
-
-/**
- * A RowProcessorOperation handles a database action that returns a sequence of
- * rows. The rows are handled by a java.util.concurrent.Flow.Processor. A
- * RowProcessorOperation is conceptually a Row Publisher and a result Subscriber.
- * The configured Processor transforms the Row stream into a result stream.
- * Configuring a Processor causes the RowProcessorOperation to subscribe the
- * Processor to the stream of rows and for the RowProcessorOperation itself to
- * subscribe to the stream of results published by the Processor. The last
- * result produced is the result of the RowProcessorOperation.
- *
- * The RowProcessorOperation will insure that the demand for results is positive.
- *
- * Calling Submission.cancel will call cancel on the result Subscription. The
- * Processor should call cancel on the row Subscription when cancel is called on
- * the result Subscription.
- *
- * @param <T> the type of the result of the {@link Operation}
- */
-public interface RowProcessorOperation<T> extends ParameterizedOperation<T> {
-
- /** DRAFT
- * Accepts a Processor that subscribes to a stream of Rows and publishes
- * a stream of result values. This Operation will subscribe to the stream of
- * results. The last published result value is the result of the
- * Operation.
- *
- * This Operation will insure result demand is eventually positive until
- * resultSubscriber.onComplete or resultSubscriber.onError is called. This
- * Operation will call resultSubscription.cancel if this Operation is canceled.
- *
- * While there are more rows and row demand is positive and rowSubscription.cancel
- * has not been called, this Operation will eventually call rowToResult.onNext
- * with the next row in the row sequence. The Result.Row argument to onNext is
- * only valid for the duration of that call. When there are no more Rows this
- * Operation will call rowToResult.onComplete. If there is an error this
- * Operation will call rowToResult.onError with the appropriate Exception whether
- * or not any rows were published.
- *
- * If resultSubscriber.onError is called this Operation completes
- * exceptionally with the passed exception. After all rows are published if
- * neither resultSubscriber.onComplete or resultSubscriber.onError is
- * called this Operation will complete exceptionally after the inactivity
- * timeout expires.
- *
- * If this Operation is skipped it will be completed exceptionally with
- * SqlSkippedException but no calls will be made to rowToResult.
- *
- * Calling Row.cancel is the same as calling Subscription.cancel on the Row
- * Subscription.
- *
- * @param rowToResult subscribes to a stream of Result.Rows and publishes a
- * stream of results of type T
- * @return this RowProcessorOperation
- */
- public RowProcessorOperation<T> rowProcessor(Flow.Processor<Result.Row, ? extends T> rowToResult);
-
- /** DRAFT
- * Subscribe to the stream of Rows returned by this Operation. The result of
- * this Operation is null. This is a convenience method.
- *
- * @param rowSubscriber subscribes to a stream of Result.Rows
- * @return this RowProcessorOperation
- */
- public default RowProcessorOperation<T> subscribe(Flow.Subscriber<Result.Row> rowSubscriber) {
-
- // create a Row to result Processor that passes the Rows to rowSubscriber
- // and publishes a single null as its only result.
- Flow.Processor<Result.Row, T> rowToResult
- = new Flow.Processor<Result.Row, T>() {
-
- protected boolean isResultPending = false;
- protected long resultDemand = 0;
-
- protected Flow.Subscription rowSubscription;
-
- protected Flow.Subscriber<? super T> resultSubscriber;
-
- protected Flow.Subscription resultSubscription = new Flow.Subscription() {
- @Override
- public void request(long n) {
- resultDemand += n;
- if (isResultPending && resultDemand > 0) {
- resultSubscriber.onNext(null);
- resultDemand--;
- resultSubscriber.onComplete();
- isResultPending = false;
- }
- }
-
- @Override
- public void cancel() {
- rowSubscription.cancel();
- }
- };
-
- @Override
- public void onSubscribe(Flow.Subscription subscription) {
- rowSubscription = subscription;
- rowSubscriber.onSubscribe(rowSubscription);
-
- }
-
- @Override
- public void onNext(Result.Row item) {
- rowSubscriber.onNext(item);
- }
-
- @Override
- public void onError(Throwable throwable) {
- rowSubscriber.onError(throwable);
- resultSubscriber.onError(throwable);
- }
-
- @Override
- public void onComplete() {
- rowSubscriber.onComplete();
- if (resultDemand > 0) {
- resultSubscriber.onNext(null);
- resultSubscriber.onComplete();
- } else {
- isResultPending = true;
- }
- }
-
- @Override
- public void subscribe(Flow.Subscriber<? super T> subscriber) {
- resultSubscriber = subscriber;
- resultSubscriber.onSubscribe(resultSubscription);
- }
- };
-
- return rowProcessor(rowToResult);
- }
-
- /** DRAFT
- * Sets the minimum time the Operation will wait for Processor activity before
- * terminating. If all of the following hold for some time exceeding minTime,
- * this Operation will be completed exceptionally with
- * {@link java.util.concurrent.TimeoutException}.
- * <ul>
- * <li>no calls to the onNext, onComplete, or onError methods of the result
- * Subscriber, ie the Subscriber passed to rowToResult.subscribe</li>
- * <li>the demand for Rows is zero or all rows have been published</li>
- * </ul>
- * If the Operation can publish no more rows either because all rows have
- * been published or because the demand for rows is 0 and rowToResult
- * has neither published a result nor terminated the stream and this state has
- * continued for at least minTime, the Operation is completed exceptionally.
- *
- * The default value is one minute.
- *
- * Note: The minTime parameter value must be small to guarantee that the
- * Connection does not hang for long periods. The default is large enough
- * that it most likely is insignificant for most apps, but small enough to
- * kick loose a hung Connection in semi-reasonable time.
- *
- * @param minTime minimum time with the Processor making no progress before the
- * Operation is terminated.
- * @return this RowProcessorOperation
- */
- public RowProcessorOperation<T> inactivityTimeout(Duration minTime);
-
-
- // Covariant overrides
-
- @Override
- public RowProcessorOperation<T> onError(Consumer<Throwable> handler);
-
- @Override
- public RowProcessorOperation<T> set(String id, Object value, SqlType type);
-
- @Override
- public RowProcessorOperation<T> set(String id, CompletionStage<?> source, SqlType type);
-
- @Override
- public RowProcessorOperation<T> set(String id, CompletionStage<?> source);
-
- @Override
- public RowProcessorOperation<T> set(String id, Object value);
-
- @Override
- public RowProcessorOperation<T> timeout(Duration minTime);
-
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowPublisherOperation.java Wed Jun 20 15:38:40 2018 -0400
@@ -0,0 +1,33 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package jdk.incubator.sql2;
+
+import java.time.Duration;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Flow;
+import java.util.function.Consumer;
+
+public interface RowPublisherOperation<T> extends Operation<T> {
+
+ /**
+ * * DRAFT Subscribe to the stream of Rows returned by this Operation. The
+ * result of this Operation is the value of the {@code result} parameter.
+ *
+ * @param subscriber Not null.
+ * @param result Not null.
+ * @return this RowPublisherOperation
+ */
+ public RowPublisherOperation<T> subscribe(Flow.Subscriber<? super Result.RowColumn> subscriber,
+ CompletionStage<? extends T> result);
+ // Covariant overrides
+
+ @Override
+ public RowPublisherOperation<T> onError(Consumer<Throwable> handler);
+
+ @Override
+ public RowPublisherOperation<T> timeout(Duration minTime);
+
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ShardingKey.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ShardingKey.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlArray.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlArray.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlBlob.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlBlob.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlClob.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlClob.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlColumns.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlColumns.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlException.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlException.java Wed Jun 20 15:38:40 2018 -0400
@@ -72,6 +72,14 @@
private final int position;
// Constructors
+
+ public SqlException(Throwable ex) {
+ super(ex);
+ this.sqlState = null;
+ this.vendorCode = -1;
+ this.sqlString = null;
+ this.position = -1;
+ }
/**
*
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlParameter.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlParameter.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlRef.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlRef.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -28,7 +28,7 @@
/**
*
- * @param <T> the type of SQL REF
+ * @param <T>
*/
public interface SqlRef<T> {
@@ -38,7 +38,7 @@
* ISSUE: Oracle Database JDBC driver may do a round trip for this. Is this
* that heavy in other databases?
*
- * @return the fully-qualified SQL name of the referenced SQL structured type
+ * @return
*/
public String getReferentTypeName();
@@ -64,8 +64,7 @@
* Create and return an Operation that will set the value of the REF in the
* database.
*
- * @param value an Object representing the SQL structured type instance
- * that this Ref object will reference
+ * @param value
* @return an Operation that will store the new referent into the REF
*/
public Operation<Void> storeOperation(T value);
@@ -74,8 +73,7 @@
* Submit an Operation that will store the new value of the referent into
* the REF in the database.
*
- * @param value an Object representing the SQL structured type instance
- * that this Ref object will reference
+ * @param value
* @return a Future that will complete when the submitted Operation completes.
*/
public default CompletionStage<Void> store(T value) {
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlStruct.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlStruct.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlType.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlType.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -26,32 +26,31 @@
package jdk.incubator.sql2;
/**
- * An object that is used to identify a generic SQL type, called a JDBC type or
- * a vendor specific data type.
- *
- * @since 1.8
+ * Remove dependence on java.sql.
*/
public interface SqlType {
- /**
- * Returns the {@code SQLType} name that represents a SQL data type.
- *
- * @return The name of this {@code SQLType}.
- */
+ /**
+ *
+ * @return
+ */
public String getName();
- /**
- * Returns the name of the vendor that supports this data type. The value
- * returned typically is the package name for this vendor.
- *
- * @return The name of the vendor for this data type
- */
+ /**
+ *
+ * @return
+ */
public String getVendor();
- /**
- * Returns the vendor specific type number for the data type.
- *
- * @return An Integer representing the vendor specific data type
- */
+ /**
+ *
+ * @return
+ */
public Integer getVendorTypeNumber();
+
+ /**
+ *
+ * @return Java type
+ */
+ public <T> Class<T> getJavaType();
}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Submission.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Submission.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Transaction.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Transaction.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/TransactionOutcome.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/TransactionOutcome.java Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -35,6 +35,11 @@
UNKNOWN,
/**
+ * The outcome of the transaction is in doubt.
+ */
+ IN_DOUBT,
+
+ /**
* The transaction committed successfully.
*/
COMMIT,
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/package-info.java Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/package-info.java Wed Jun 20 15:38:40 2018 -0400
@@ -186,7 +186,7 @@
* effort in an app using that feature only to discover in production that the
* performance is unacceptable. For example, if an implementation can only support
* {@link Operation#timeout} through active polling it would be better for that
- * implementation to throw UnsupportedFeatureException if
+ * implementation to throw {@link UnsupportedOperationException} if
* {@link Operation#timeout} is called.</p>
*
* <h3>Execution Model</h3>
@@ -208,9 +208,9 @@
* of the result processor if there is one or with the result of the action if
* there is no result processor. If the action or the result processing causes
* an unhandled error the {@link java.util.concurrent.CompletionStage} is
- * completed exceptionally. The CompletionStage is completed asynchronously,
- * as though it were created by calling an <i>async</i> method on
- * CompletionStage.
+ * completed exceptionally. The {@link java.util.concurrent.CompletionStage} is
+ * completed asynchronously, as though it were created by calling an
+ * <i>async</i> method on {@link java.util.concurrent.CompletionStage}.
* </p>
*
* <p>
@@ -232,7 +232,7 @@
* If the {@link OperationGroup} has a condition, the value of the condition is
* retrieved. If the value is {@link Boolean#FALSE} the action is complete and
* the {@link java.util.concurrent.CompletionStage} is completed with null. If
- * the value completes exceptionally the action is complete and the
+ * the condition value completes exceptionally the action is complete and the
* {@link java.util.concurrent.CompletionStage} is completed exceptionally
* with the same exception. If the condition value is {@link Boolean#TRUE} or
* there is no condition the {@link Operation}s in the collection are executed
@@ -240,26 +240,26 @@
* {@link OperationGroup} is not held and all the {@link Operation}s have been
* executed.</li>
* <li>
- * If the {@link OperationGroup} is parallel more than one {@link Operation} may
- * be executed at a time.</li>
+ * If the {@link OperationGroup} is parallel more than one member
+ * {@link Operation} may be executed at a time.</li>
* <li>
- * If the {@link OperationGroup} is dependent and an {@link Operation} completes
- * exceptionally all {@link Operation}s in the collection that are yet to begin
+ * If the {@link OperationGroup} is dependent and a member {@link Operation} completes
+ * exceptionally all member {@link Operation}s that are yet to begin
* execution are completed exceptionally with a {@link SqlSkippedException}. The
* cause of that exception is the {@link Throwable} that caused the
* {@link Operation} to be completed exceptionally. If an {@link Operation} is
* in flight when another {@link Operation} completes exceptionally the in
* flight {@link Operation} may either be allowed to complete uninterrupted or
- * it may be completed exceptionally. The {@link OperationGroup} is completed
- * exceptionally with the {@link Throwable} that caused the {@link Operation} to
- * complete exceptionally.
+ * it may be completed exceptionally. The {@link OperationGroup} is dependent it
+ * is completed exceptionally with the {@link Throwable} that caused the
+ * {@link Operation} to complete exceptionally.
*
* <p>
* Note: the {@link Operation}s returned by {@link Connection#closeOperation}
* and {@link OperationGroup#catchOperation} are never skipped, i.e. never
* completed exceptionally with {@link SqlSkippedException}. The {@link Operation}
* returned by {@link OperationGroup#catchOperation} never completes
- * execeptionally so the following {@link Operation} is always executed normally.
+ * exceptionally so the following {@link Operation} is always executed normally.
* No {@link Operation} can be submitted after the {@link Operation} returned by
* {@link Connection#closeOperation} has been submitted.</p> </li>
* <li>
@@ -293,7 +293,7 @@
* <p>
* The creation of Operations and the subsequent execution of those Operations
* are separated in time. It is quite reasonable to determine that a transaction
- * should commit after the Operation that ends the transaction is created.
+ * should commit after the Operation that ends the transaction is submitted.
* But if the execution of the transaction does not result in the expected results
* it might be necessary to rollback the transaction rather than commit it. This
* determination depends on the execution of the Operations long after the
@@ -333,6 +333,64 @@
* the transaction to rollback.</p>
*
*
+ * <h3>Implementation Note</h3>
+ *
+ * <p>
+ * If an implementation exposes any implementation specific types and methods, the
+ * implementation is expected to provide covariant overrides for all methods that
+ * return the standard super-type of the implementation specific type.</p>
+ *
+ * <p>
+ * Consider an implementation that adds a method foo() to RowCountOperation. To do
+ * that it would have to expose a type FooRowCountOperation extends RowCountOperation.
+ * So that an application can transparently access foo, the implementation would
+ * also have to expose FooDataSource, FooOperationGroup and FooConnection. Further
+ * each of these types would have to declare covariant overrides for every method
+ * that returns a direct super-type of one of these types.</p>
+ * <ul>
+ * <li>FooDataSourceFactory must override builder to return FooDataSource.Builder</li>
+ * <li>FooDataSource.Builder must override url, password, etc to return a
+ * FooDataSource.Builder. build must return a FooDataSource.</li>
+ * <li>FooDataSource must override builder to return FooConnection.Builder</li>
+ * <li>FooConnection.Builder must override url, password, etc to return a
+ * FooConnection.Builder. build must return a FooConnection</li>
+ * <li>FooDataSource must override getConnection to return FooConnection</li>
+ * <li>FooConnection must extend FooOperationGroup</li>
+ * <li>FooOperationGroup> must override rowCountOperation to return FooRowCountOperation</li>
+ * <li>FooRowCountOperation must override apply and onError to return FooRowCountOperation</li>
+ * </ul>
+ * <p>
+ * The intent is to transparently expose the vendor extension without use of casts.
+ * Example: </p>
+ *
+ * <pre>
+ * {@code
+ * FooDataSourceFactory factory = DataSourceFatory.newFactory("com.foo.FooDataSourceFatory");
+ * FooDataSource dataSource = factory.builder()
+ * .url("scott/tiger@host:port")
+ * .build();
+ * FooConnection conn = dataSource.getConnection();
+ * CompletionStage<Long> count = conn.rowOperation(sql)
+ * .set("param", value, AdbaType.VARCHAR)
+ * .foo()
+ * .submit()
+ * .getCompletionStage();
+ * }
+ * </pre>
+ *
+ * <p>
+ * Notice that there are no casts, yet both standard methods an the vendor extension
+ * method foo can be referenced. This is possible only if the implementation exposes
+ * all the necessary types and provides covariant overrides for every method that
+ * returns one of those types. Implementations are expected (required?) to do this.
+ * </p>
+ *
+ * <p>
+ * If an implementation does not expose any implementation specific methods or
+ * types, that implementation is not required to provide covariant overrides that
+ * return implementation specific types.</p>
+ *
+ *
*/
package jdk.incubator.sql2;