You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by el...@apache.org on 2016/03/07 19:28:09 UTC
[31/59] [partial] calcite git commit: [CALCITE-1078] Detach avatica
from the core calcite Maven project
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/main/protobuf/common.proto
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/protobuf/common.proto b/avatica/core/src/main/protobuf/common.proto
new file mode 100644
index 0000000..bd116c3
--- /dev/null
+++ b/avatica/core/src/main/protobuf/common.proto
@@ -0,0 +1,275 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+option java_package = "org.apache.calcite.avatica.proto";
+
+// Details about a connection
+message ConnectionProperties {
+ bool is_dirty = 1;
+ bool auto_commit = 2;
+ bool has_auto_commit = 7; // field is a Boolean, need to discern null and default value
+ bool read_only = 3;
+ bool has_read_only = 8; // field is a Boolean, need to discern null and default value
+ uint32 transaction_isolation = 4;
+ string catalog = 5;
+ string schema = 6;
+}
+
+// Statement handle
+message StatementHandle {
+ string connection_id = 1;
+ uint32 id = 2;
+ Signature signature = 3;
+}
+
+// Results of preparing a statement
+message Signature {
+ repeated ColumnMetaData columns = 1;
+ string sql = 2;
+ repeated AvaticaParameter parameters = 3;
+ CursorFactory cursor_factory = 4;
+ StatementType statementType = 5;
+}
+
+// Has to be consistent with Meta.StatementType
+enum StatementType {
+ SELECT = 0;
+ INSERT = 1;
+ UPDATE = 2;
+ DELETE = 3;
+ UPSERT = 4;
+ MERGE = 5;
+ OTHER_DML = 6;
+ CREATE = 7;
+ DROP = 8;
+ ALTER = 9;
+ OTHER_DDL = 10;
+ CALL = 11;
+}
+
+message ColumnMetaData {
+ uint32 ordinal = 1;
+ bool auto_increment = 2;
+ bool case_sensitive = 3;
+ bool searchable = 4;
+ bool currency = 5;
+ uint32 nullable = 6;
+ bool signed = 7;
+ uint32 display_size = 8;
+ string label = 9;
+ string column_name = 10;
+ string schema_name = 11;
+ uint32 precision = 12;
+ uint32 scale = 13;
+ string table_name = 14;
+ string catalog_name = 15;
+ bool read_only = 16;
+ bool writable = 17;
+ bool definitely_writable = 18;
+ string column_class_name = 19;
+ AvaticaType type = 20;
+}
+
+enum Rep {
+ PRIMITIVE_BOOLEAN = 0;
+ PRIMITIVE_BYTE = 1;
+ PRIMITIVE_CHAR = 2;
+ PRIMITIVE_SHORT = 3;
+ PRIMITIVE_INT = 4;
+ PRIMITIVE_LONG = 5;
+ PRIMITIVE_FLOAT = 6;
+ PRIMITIVE_DOUBLE = 7;
+ BOOLEAN = 8;
+ BYTE = 9;
+ CHARACTER = 10;
+ SHORT = 11;
+ INTEGER = 12;
+ LONG = 13;
+ FLOAT = 14;
+ DOUBLE = 15;
+ BIG_INTEGER = 25;
+ BIG_DECIMAL = 26;
+ JAVA_SQL_TIME = 16;
+ JAVA_SQL_TIMESTAMP = 17;
+ JAVA_SQL_DATE = 18;
+ JAVA_UTIL_DATE = 19;
+ BYTE_STRING = 20;
+ STRING = 21;
+ NUMBER = 22;
+ OBJECT = 23;
+ NULL = 24;
+ ARRAY = 27;
+ STRUCT = 28;
+ MULTISET = 29;
+}
+
+// Base class for a column type
+message AvaticaType {
+ uint32 id = 1;
+ string name = 2;
+ Rep rep = 3;
+
+ repeated ColumnMetaData columns = 4; // Only present when name = STRUCT
+ AvaticaType component = 5; // Only present when name = ARRAY
+}
+
+// Metadata for a parameter
+message AvaticaParameter {
+ bool signed = 1;
+ uint32 precision = 2;
+ uint32 scale = 3;
+ uint32 parameter_type = 4;
+ string type_name = 5;
+ string class_name = 6;
+ string name = 7;
+}
+
+// Information necessary to convert an Iterable into a Calcite Cursor
+message CursorFactory {
+ enum Style {
+ OBJECT = 0;
+ RECORD = 1;
+ RECORD_PROJECTION = 2;
+ ARRAY = 3;
+ LIST = 4;
+ MAP = 5;
+ }
+
+ Style style = 1;
+ string class_name = 2;
+ repeated string field_names = 3;
+}
+
+// A collection of rows
+message Frame {
+ uint64 offset = 1;
+ bool done = 2;
+ repeated Row rows = 3;
+}
+
+// A row is a collection of values
+message Row {
+ repeated ColumnValue value = 1;
+}
+
+// Database property, list of functions the database provides for a certain operation
+message DatabaseProperty {
+ string name = 1;
+ repeated string functions = 2;
+}
+
+// Message which encapsulates another message to support a single RPC endpoint
+message WireMessage {
+ string name = 1;
+ bytes wrapped_message = 2;
+}
+
+// A value might be a TypedValue or an Array of TypedValue's
+message ColumnValue {
+ repeated TypedValue value = 1; // deprecated, use array_value or scalar_value
+ repeated TypedValue array_value = 2;
+ bool has_array_value = 3; // Is an array value set?
+ TypedValue scalar_value = 4;
+}
+
+// Generic wrapper to support any SQL type. Struct-like to work around no polymorphism construct.
+message TypedValue {
+ Rep type = 1; // The actual type that was serialized in the general attribute below
+
+ bool bool_value = 2; // boolean
+ string string_value = 3; // char/varchar
+ sint64 number_value = 4; // var-len encoding lets us shove anything from byte to long
+ // includes numeric types and date/time types.
+ bytes bytes_values = 5; // binary/varbinary
+ double double_value = 6; // big numbers
+ bool null = 7; // a null object
+}
+
+// The severity of some unexpected outcome to an operation.
+// Protobuf enum values must be unique across all other enums
+enum Severity {
+ UNKNOWN_SEVERITY = 0;
+ FATAL_SEVERITY = 1;
+ ERROR_SEVERITY = 2;
+ WARNING_SEVERITY = 3;
+}
+
+// Enumeration corresponding to DatabaseMetaData operations
+enum MetaDataOperation {
+ GET_ATTRIBUTES = 0;
+ GET_BEST_ROW_IDENTIFIER = 1;
+ GET_CATALOGS = 2;
+ GET_CLIENT_INFO_PROPERTIES = 3;
+ GET_COLUMN_PRIVILEGES = 4;
+ GET_COLUMNS = 5;
+ GET_CROSS_REFERENCE = 6;
+ GET_EXPORTED_KEYS = 7;
+ GET_FUNCTION_COLUMNS = 8;
+ GET_FUNCTIONS = 9;
+ GET_IMPORTED_KEYS = 10;
+ GET_INDEX_INFO = 11;
+ GET_PRIMARY_KEYS = 12;
+ GET_PROCEDURE_COLUMNS = 13;
+ GET_PROCEDURES = 14;
+ GET_PSEUDO_COLUMNS = 15;
+ GET_SCHEMAS = 16;
+ GET_SCHEMAS_WITH_ARGS = 17;
+ GET_SUPER_TABLES = 18;
+ GET_SUPER_TYPES = 19;
+ GET_TABLE_PRIVILEGES = 20;
+ GET_TABLES = 21;
+ GET_TABLE_TYPES = 22;
+ GET_TYPE_INFO = 23;
+ GET_UDTS = 24;
+ GET_VERSION_COLUMNS = 25;
+}
+
+// Represents the breadth of arguments to DatabaseMetaData functions
+message MetaDataOperationArgument {
+ enum ArgumentType {
+ STRING = 0;
+ BOOL = 1;
+ INT = 2;
+ REPEATED_STRING = 3;
+ REPEATED_INT = 4;
+ NULL = 5;
+ }
+
+ string string_value = 1;
+ bool bool_value = 2;
+ sint32 int_value = 3;
+ repeated string string_array_values = 4;
+ repeated sint32 int_array_values = 5;
+ ArgumentType type = 6;
+}
+
+enum StateType {
+ SQL = 0;
+ METADATA = 1;
+}
+
+message QueryState {
+ StateType type = 1;
+ string sql = 2;
+ MetaDataOperation op = 3;
+ repeated MetaDataOperationArgument args = 4;
+ bool has_args = 5;
+ bool has_sql = 6;
+ bool has_op = 7;
+}
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/main/protobuf/requests.proto
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/protobuf/requests.proto b/avatica/core/src/main/protobuf/requests.proto
new file mode 100644
index 0000000..31b0941
--- /dev/null
+++ b/avatica/core/src/main/protobuf/requests.proto
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+syntax = "proto3";
+
+option java_package = "org.apache.calcite.avatica.proto";
+
+import "common.proto";
+
+// Request for Meta#getCatalogs()
+message CatalogsRequest {
+ string connection_id = 1;
+}
+
+// Request for Meta#getDatabaseProperties()
+message DatabasePropertyRequest {
+ string connection_id = 1;
+}
+
+// Request for Meta#getSchemas(String, org.apache.calcite.avatica.Meta.Pat)}
+message SchemasRequest {
+ string catalog = 1;
+ string schema_pattern = 2;
+ string connection_id = 3;
+}
+
+// Request for Request for Meta#getTables(String, org.apache.calcite.avatica.Meta.Pat,
+// org.apache.calcite.avatica.Meta.Pat, java.util.List)
+message TablesRequest {
+ string catalog = 1;
+ string schema_pattern = 2;
+ string table_name_pattern = 3;
+ repeated string type_list = 4;
+ bool has_type_list = 6; // Having an empty type_list is distinct from a null type_list
+ string connection_id = 7;
+}
+
+// Request for Meta#getTableTypes()
+message TableTypesRequest {
+ string connection_id = 1;
+}
+
+// Request for Meta#getColumns(String, org.apache.calcite.avatica.Meta.Pat,
+// org.apache.calcite.avatica.Meta.Pat, org.apache.calcite.avatica.Meta.Pat).
+message ColumnsRequest {
+ string catalog = 1;
+ string schema_pattern = 2;
+ string table_name_pattern = 3;
+ string column_name_pattern = 4;
+ string connection_id = 5;
+}
+
+// Request for Meta#getTypeInfo()
+message TypeInfoRequest {
+ string connection_id = 1;
+}
+
+// Request for Meta#prepareAndExecute(Meta.StatementHandle, String, long, Meta.PrepareCallback)
+message PrepareAndExecuteRequest {
+ string connection_id = 1;
+ string sql = 2;
+ uint64 max_row_count = 3;
+ uint32 statement_id = 4;
+}
+
+// Request for Meta.prepare(Meta.ConnectionHandle, String, long)
+message PrepareRequest {
+ string connection_id = 1;
+ string sql = 2;
+ uint64 max_row_count = 3;
+}
+
+// Request for Meta#fetch(Meta.StatementHandle, List, long, int)
+message FetchRequest {
+ string connection_id = 1;
+ uint32 statement_id = 2;
+ uint64 offset = 3;
+ uint32 fetch_max_row_count = 4; // Maximum number of rows to be returned in the frame. Negative means no limit.
+}
+
+// Request for Meta#createStatement(Meta.ConnectionHandle)
+message CreateStatementRequest {
+ string connection_id = 1;
+}
+
+// Request for Meta#closeStatement(Meta.StatementHandle)
+message CloseStatementRequest {
+ string connection_id = 1;
+ uint32 statement_id = 2;
+}
+
+// Request for Meta#openConnection(Meta.ConnectionHandle, Map<String, String>)
+message OpenConnectionRequest {
+ string connection_id = 1;
+ map<string, string> info = 2;
+}
+
+// Request for Meta#closeConnection(Meta.ConnectionHandle)
+message CloseConnectionRequest {
+ string connection_id = 1;
+}
+
+message ConnectionSyncRequest {
+ string connection_id = 1;
+ ConnectionProperties conn_props = 2;
+}
+
+// Request for Meta#execute(Meta.ConnectionHandle, list, long)
+message ExecuteRequest {
+ StatementHandle statementHandle = 1;
+ repeated TypedValue parameter_values = 2;
+ uint64 max_row_count = 3;
+ bool has_parameter_values = 4;
+}
+
+
+message SyncResultsRequest {
+ string connection_id = 1;
+ uint32 statement_id = 2;
+ QueryState state = 3;
+ uint64 offset = 4;
+}
+
+// Request to invoke a commit on a Connection
+message CommitRequest {
+ string connection_id = 1;
+}
+
+// Request to invoke rollback on a Connection
+message RollbackRequest {
+ string connection_id = 1;
+}
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/main/protobuf/responses.proto
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/protobuf/responses.proto b/avatica/core/src/main/protobuf/responses.proto
new file mode 100644
index 0000000..01a62ed
--- /dev/null
+++ b/avatica/core/src/main/protobuf/responses.proto
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+syntax = "proto3";
+
+option java_package = "org.apache.calcite.avatica.proto";
+
+import "common.proto";
+
+// Response that contains a result set.
+message ResultSetResponse {
+ string connection_id = 1;
+ uint32 statement_id = 2;
+ bool own_statement = 3;
+ Signature signature = 4;
+ Frame first_frame = 5;
+ uint64 update_count = 6; // -1 for normal result sets, else this response contains a dummy result set
+ // with no signature nor other data.
+ RpcMetadata metadata = 7;
+}
+
+// Response to PrepareAndExecuteRequest
+message ExecuteResponse {
+ repeated ResultSetResponse results = 1;
+ bool missing_statement = 2; // Did the request fail because of no-cached statement
+ RpcMetadata metadata = 3;
+}
+
+// Response to PrepareRequest
+message PrepareResponse {
+ StatementHandle statement = 1;
+ RpcMetadata metadata = 2;
+}
+
+// Response to FetchRequest
+message FetchResponse {
+ Frame frame = 1;
+ bool missing_statement = 2; // Did the request fail because of no-cached statement
+ bool missing_results = 3; // Did the request fail because of a cached-statement w/o ResultSet
+ RpcMetadata metadata = 4;
+}
+
+// Response to CreateStatementRequest
+message CreateStatementResponse {
+ string connection_id = 1;
+ uint32 statement_id = 2;
+ RpcMetadata metadata = 3;
+}
+
+// Response to CloseStatementRequest
+message CloseStatementResponse {
+ RpcMetadata metadata = 1;
+}
+
+// Response to OpenConnectionRequest {
+message OpenConnectionResponse {
+ RpcMetadata metadata = 1;
+}
+
+// Response to CloseConnectionRequest {
+message CloseConnectionResponse {
+ RpcMetadata metadata = 1;
+}
+
+// Response to ConnectionSyncRequest
+message ConnectionSyncResponse {
+ ConnectionProperties conn_props = 1;
+ RpcMetadata metadata = 2;
+}
+
+message DatabasePropertyElement {
+ DatabaseProperty key = 1;
+ TypedValue value = 2;
+ RpcMetadata metadata = 3;
+}
+
+// Response for Meta#getDatabaseProperties()
+message DatabasePropertyResponse {
+ repeated DatabasePropertyElement props = 1;
+ RpcMetadata metadata = 2;
+}
+
+// Send contextual information about some error over the wire from the server.
+message ErrorResponse {
+ repeated string exceptions = 1; // exception stacktraces, many for linked exceptions.
+ bool has_exceptions = 7; // are there stacktraces contained?
+ string error_message = 2; // human readable description
+ Severity severity = 3;
+ uint32 error_code = 4; // numeric identifier for error
+ string sql_state = 5; // five-character standard-defined value
+ RpcMetadata metadata = 6;
+}
+
+message SyncResultsResponse {
+ bool missing_statement = 1; // Server doesn't have the statement with the ID from the request
+ bool more_results = 2; // Should the client fetch() to get more results
+ RpcMetadata metadata = 3;
+}
+
+// Generic metadata for the server to return with each response.
+message RpcMetadata {
+ string server_address = 1; // The host:port of the server
+}
+
+// Response to a commit request
+message CommitResponse {
+
+}
+
+// Response to a rollback request
+message RollbackResponse {
+
+}
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/main/resources/META-INF/LICENSE
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/resources/META-INF/LICENSE b/avatica/core/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000..7764d41
--- /dev/null
+++ b/avatica/core/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,257 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
+
+
+-----------------------------------------------------------------------
+
+APACHE CALCITE SUBCOMPONENTS:
+
+The Apache Calcite project contains subcomponents with separate copyright
+notices and license terms. Your use of the source code for the these
+subcomponents is subject to the terms and conditions of the following
+licenses.
+
+-----------------------------------------------------------------------
+ 3-clause BSD license
+-----------------------------------------------------------------------
+
+The Apache Calcite Avatica project bundles Protocol Buffers, which is available
+under the following "3-clause BSD" license:
+
+ Copyright 2014, Google Inc. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+
+ Neither the name of Google Inc. nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Code generated by the Protocol Buffer compiler is owned by the owner
+ of the input file used when generating it. This code is not
+ standalone and requires a support library to be linked with it. This
+ support library is itself covered by the above license.
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/main/resources/META-INF/services/java.sql.Driver
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/resources/META-INF/services/java.sql.Driver b/avatica/core/src/main/resources/META-INF/services/java.sql.Driver
new file mode 100644
index 0000000..beb1ac0
--- /dev/null
+++ b/avatica/core/src/main/resources/META-INF/services/java.sql.Driver
@@ -0,0 +1 @@
+org.apache.calcite.avatica.remote.Driver
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/main/scripts/generate-protobuf.sh
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/scripts/generate-protobuf.sh b/avatica/core/src/main/scripts/generate-protobuf.sh
new file mode 100755
index 0000000..c4d3abe
--- /dev/null
+++ b/avatica/core/src/main/scripts/generate-protobuf.sh
@@ -0,0 +1,99 @@
+#! /usr/bin/env bash
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to you under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This script will regenerate the protobuf code for Avatica. Slightly
+# modified script over one in Accumulo.
+
+# NOTES:
+# To support this script being called by other modules, only edit the right side.
+# In other scripts, set the variables that diverge from the defaults below, then call this script.
+# Leave the BUILD_DIR and FINAL_DIR alone for Maven builds.
+# ========================================================================================================================
+[[ -z $REQUIRED_PROTOC_VERSION ]] && REQUIRED_PROTOC_VERSION='libprotoc 3.0.0'
+[[ -z $BUILD_DIR ]] && BUILD_DIR='target/proto-tmp'
+[[ -z $FINAL_DIR ]] && FINAL_DIR='src/main'
+# ========================================================================================================================
+
+fail() {
+ echo "$@"
+ exit 1
+}
+
+# Test to see if we have protoc installed
+VERSION=$(protoc --version 2>/dev/null | grep -F "${REQUIRED_PROTOC_VERSION}" | wc -l)
+if [[ $VERSION -ne 1 ]] ; then
+ # Nope: bail
+ echo "****************************************************"
+ echo "*** protoc is not available"
+ echo "*** expecting 'protoc --version' to return ${REQUIRED_PROTOC_VERSION}"
+ echo "*** generated code will not be updated"
+ fail "****************************************************"
+fi
+
+# Ensure output directories are created
+PROTOC_ARGS="-I src/main/protobuf --java_out=$BUILD_DIR"
+rm -rf $BUILD_DIR
+mkdir -p $BUILD_DIR
+
+protoc ${PROTOC_ARGS} src/main/protobuf/*.proto || fail unable to generate Java protocol buffer classes
+
+# For all generated protobuf code, suppress all warnings and add the LICENSE header
+s='@SuppressWarnings({"unused", "rawtypes"})'
+find $BUILD_DIR -name '*.java' -print0 | xargs -0 sed -i.orig -e 's/\(public final class \)/'"$s"' \1/'
+
+PREFIX="/*
+"
+LINE_NOTATION=" *"
+SUFFIX="
+ */"
+FILE_SUFFIX=(.java)
+
+for file in "${FILE_SUFFIX[@]}"; do
+ for f in $(find $BUILD_DIR/ -name "*$file"); do
+ cat - "$f" > "${f}-with-license" <<EOF
+${PREFIX}${LINE_NOTATION} Licensed to the Apache Software Foundation (ASF) under one or more
+${LINE_NOTATION} contributor license agreements. See the NOTICE file distributed with
+${LINE_NOTATION} this work for additional information regarding copyright ownership.
+${LINE_NOTATION} The ASF licenses this file to you under the Apache License, Version 2.0
+${LINE_NOTATION} (the "License"); you may not use this file except in compliance with
+${LINE_NOTATION} the License. You may obtain a copy of the License at
+${LINE_NOTATION}
+${LINE_NOTATION} http://www.apache.org/licenses/LICENSE-2.0
+${LINE_NOTATION}
+${LINE_NOTATION} Unless required by applicable law or agreed to in writing, software
+${LINE_NOTATION} distributed under the License is distributed on an "AS IS" BASIS,
+${LINE_NOTATION} WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+${LINE_NOTATION} See the License for the specific language governing permissions and
+${LINE_NOTATION} limitations under the License.${SUFFIX}
+EOF
+ done
+done
+
+# For every generated java file, compare it with the version-controlled one, and copy the ones that have changed into place
+SDIR="${BUILD_DIR}/org/apache/calcite/avatica/proto"
+DDIR="${FINAL_DIR}/java/org/apache/calcite/avatica/proto"
+FILE_SUFFIX=(.java)
+mkdir -p "$DDIR"
+for file in "${FILE_SUFFIX[@]}"; do
+ for f in $(find $SDIR -name *$file); do
+ DEST=$DDIR/$(basename "$f")
+ if ! cmp -s "${f}-with-license" "${DEST}" ; then
+ echo cp -f "${f}-with-license" "${DEST}"
+ cp -f "${f}-with-license" "${DEST}" || fail unable to copy files to java workspace
+ fi
+ done
+done
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/AvaticaConnectionTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/AvaticaConnectionTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/AvaticaConnectionTest.java
new file mode 100644
index 0000000..a1414c3
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/AvaticaConnectionTest.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.Properties;
+
+/**
+ * Tests for AvaticaConnection
+ */
+public class AvaticaConnectionTest {
+
+ @Test
+ public void testNumExecuteRetries() {
+ AvaticaConnection statement = Mockito.mock(AvaticaConnection.class);
+
+ Mockito.when(statement.getNumStatementRetries(Mockito.any(Properties.class)))
+ .thenCallRealMethod();
+
+ // Bad argument should throw an exception
+ try {
+ statement.getNumStatementRetries(null);
+ Assert.fail("Calling getNumStatementRetries with a null object should throw an exception");
+ } catch (NullPointerException e) {
+ // Pass
+ }
+
+ Properties props = new Properties();
+
+ // Verify the default value
+ Assert.assertEquals(Long.valueOf(AvaticaConnection.NUM_EXECUTE_RETRIES_DEFAULT).longValue(),
+ statement.getNumStatementRetries(props));
+
+ // Set a non-default value
+ props.setProperty(AvaticaConnection.NUM_EXECUTE_RETRIES_KEY, "10");
+
+ // Verify that we observe that value
+ Assert.assertEquals(10, statement.getNumStatementRetries(props));
+ }
+
+}
+
+// End AvaticaConnectionTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/FrameTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/FrameTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/FrameTest.java
new file mode 100644
index 0000000..bdd989b
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/FrameTest.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica;
+
+import org.apache.calcite.avatica.Meta.Frame;
+import org.apache.calcite.avatica.proto.Common;
+import org.apache.calcite.avatica.proto.Common.ColumnValue;
+import org.apache.calcite.avatica.proto.Common.TypedValue;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests serialization of {@link Frame}.
+ */
+public class FrameTest {
+
+ private static final TypedValue NUMBER_VALUE = TypedValue.newBuilder().setNumberValue(1)
+ .setType(Common.Rep.LONG).build();
+
+ private void serializeAndTestEquality(Frame frame) {
+ Frame frameCopy = Frame.fromProto(frame.toProto());
+
+ assertEquals(frame.done, frameCopy.done);
+ assertEquals(frame.offset, frameCopy.offset);
+
+ Iterable<Object> origRows = frame.rows;
+ Iterable<Object> copiedRows = frameCopy.rows;
+
+ assertEquals("Expected rows to both be null, or both be non-null",
+ origRows == null, copiedRows == null);
+
+ Iterator<Object> origIter = origRows.iterator();
+ Iterator<Object> copiedIter = copiedRows.iterator();
+ while (origIter.hasNext() && copiedIter.hasNext()) {
+ Object orig = origIter.next();
+ Object copy = copiedIter.next();
+
+ assertEquals(orig == null, copy == null);
+
+ // This is goofy, but it seems like an Array comes from the JDBC implementation but then
+ // the resulting Frame has a List to support the Avatica typed Accessors
+ assertEquals(Object[].class, orig.getClass());
+ assertTrue("Expected List but got " + copy.getClass(), copy instanceof List);
+
+ @SuppressWarnings("unchecked")
+ List<Object> copyList = (List<Object>) copy;
+
+ assertArrayEquals((Object[]) orig, copyList.toArray(new Object[0]));
+ }
+
+ assertEquals(origIter.hasNext(), copiedIter.hasNext());
+ }
+
+ @Test
+ public void testEmpty() {
+ serializeAndTestEquality(Frame.EMPTY);
+ }
+
+ @Test
+ public void testSingleRow() {
+ ArrayList<Object> rows = new ArrayList<>();
+ rows.add(new Object[] {"string", Integer.MAX_VALUE, new Date().getTime()});
+
+ Frame singleRow = new Frame(0, true, rows);
+
+ serializeAndTestEquality(singleRow);
+ }
+
+ @Test
+ public void testMultipleRows() {
+ ArrayList<Object> rows = new ArrayList<>();
+ rows.add(new Object[] {"string", Integer.MAX_VALUE, new Date().getTime()});
+ rows.add(new Object[] {"gnirts", 0, Long.MIN_VALUE});
+ rows.add(new Object[] {"", null, Long.MAX_VALUE});
+
+ Frame singleRow = new Frame(0, true, rows);
+
+ serializeAndTestEquality(singleRow);
+ }
+
+ @Test public void testMalformedColumnValue() {
+ // Invalid ColumnValue: has an array and scalar
+ final ColumnValue bothAttributesColumnValue = ColumnValue.newBuilder().setHasArrayValue(true)
+ .setScalarValue(NUMBER_VALUE).build();
+ // Note omission of setScalarValue(TypedValue).
+ final ColumnValue neitherAttributeColumnValue = ColumnValue.newBuilder().setHasArrayValue(false)
+ .build();
+
+ try {
+ Frame.validateColumnValue(bothAttributesColumnValue);
+ fail("Validating the ColumnValue should have failed as it has an array and scalar");
+ } catch (IllegalArgumentException e) {
+ // Pass
+ }
+
+ try {
+ Frame.validateColumnValue(neitherAttributeColumnValue);
+ fail("Validating the ColumnValue should have failed as it has neither an array nor scalar");
+ } catch (IllegalArgumentException e) {
+ // Pass
+ }
+ }
+
+ @Test public void testColumnValueBackwardsCompatibility() {
+ // 1
+ final ColumnValue oldStyleScalarValue = ColumnValue.newBuilder().addValue(NUMBER_VALUE).build();
+ // [1, 1]
+ final ColumnValue oldStyleArrayValue = ColumnValue.newBuilder().addValue(NUMBER_VALUE)
+ .addValue(NUMBER_VALUE).build();
+
+ assertFalse(Frame.isNewStyleColumn(oldStyleScalarValue));
+ assertFalse(Frame.isNewStyleColumn(oldStyleArrayValue));
+
+ Object scalar = Frame.parseOldStyleColumn(oldStyleScalarValue);
+ assertEquals(1L, scalar);
+
+ Object array = Frame.parseOldStyleColumn(oldStyleArrayValue);
+ assertEquals(Arrays.asList(1L, 1L), array);
+ }
+
+ @Test public void testColumnValueParsing() {
+ // 1
+ final ColumnValue scalarValue = ColumnValue.newBuilder().setScalarValue(NUMBER_VALUE).build();
+ // [1, 1]
+ final ColumnValue arrayValue = ColumnValue.newBuilder().addArrayValue(NUMBER_VALUE)
+ .addArrayValue(NUMBER_VALUE).setHasArrayValue(true).build();
+
+ assertTrue(Frame.isNewStyleColumn(scalarValue));
+ assertTrue(Frame.isNewStyleColumn(arrayValue));
+
+ Object scalar = Frame.parseColumn(scalarValue);
+ assertEquals(1L, scalar);
+
+ Object array = Frame.parseColumn(arrayValue);
+ assertEquals(Arrays.asList(1L, 1L), array);
+ }
+}
+
+// End FrameTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/QueryStateTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/QueryStateTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/QueryStateTest.java
new file mode 100644
index 0000000..d97bfa2
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/QueryStateTest.java
@@ -0,0 +1,513 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica;
+
+import org.apache.calcite.avatica.remote.MetaDataOperation;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests that {@link QueryState} properly retains the necessary state to recreate
+ * a {@link ResultSet}.
+ */
+public class QueryStateTest {
+
+ private Connection conn;
+ private DatabaseMetaData metadata;
+ private Statement statement;
+
+
+ @Before
+ public void setup() throws Exception {
+ conn = Mockito.mock(Connection.class);
+ metadata = Mockito.mock(DatabaseMetaData.class);
+ statement = Mockito.mock(Statement.class);
+
+ Mockito.when(conn.getMetaData()).thenReturn(metadata);
+ }
+
+ @Test
+ public void testMetadataGetAttributes() throws Exception {
+ final String catalog = "catalog";
+ final String schemaPattern = null;
+ final String typeNamePattern = "%";
+ final String attributeNamePattern = "%";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_ATTRIBUTES, catalog, schemaPattern,
+ typeNamePattern, attributeNamePattern);
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getAttributes(catalog, schemaPattern, typeNamePattern,
+ attributeNamePattern);
+ }
+
+ @Test
+ public void testMetadataGetBestRowIdentifier() throws Exception {
+ final String catalog = "catalog";
+ final String schema = null;
+ final String table = "table";
+ final int scope = 1;
+ final boolean nullable = true;
+
+ QueryState state = new QueryState(MetaDataOperation.GET_BEST_ROW_IDENTIFIER, new Object[] {
+ catalog,
+ schema,
+ table,
+ scope,
+ nullable
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getBestRowIdentifier(catalog, schema, table, scope, nullable);
+ }
+
+ @Test
+ public void testMetadataGetCatalogs() throws Exception {
+ QueryState state = new QueryState(MetaDataOperation.GET_CATALOGS, new Object[0]);
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getCatalogs();
+ }
+
+ @Test
+ public void testMetadataGetColumnPrivileges() throws Exception {
+ final String catalog = null;
+ final String schema = "schema";
+ final String table = "table";
+ final String columnNamePattern = "%";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_COLUMN_PRIVILEGES, new Object[] {
+ catalog,
+ schema,
+ table,
+ columnNamePattern
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getColumnPrivileges(catalog, schema, table, columnNamePattern);
+ }
+
+ @Test
+ public void testMetadataGetColumns() throws Exception {
+ final String catalog = null;
+ final String schemaPattern = "%";
+ final String tableNamePattern = "%";
+ final String columnNamePattern = "%";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_COLUMNS, new Object[] {
+ catalog,
+ schemaPattern,
+ tableNamePattern,
+ columnNamePattern
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getColumns(catalog, schemaPattern, tableNamePattern,
+ columnNamePattern);
+ }
+
+ @Test
+ public void testMetadataGetCrossReference() throws Exception {
+ final String parentCatalog = null;
+ final String parentSchema = null;
+ final String parentTable = "%";
+ final String foreignCatalog = null;
+ final String foreignSchema = null;
+ final String foreignTable = "%";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_CROSS_REFERENCE, new Object[] {
+ parentCatalog,
+ parentSchema,
+ parentTable,
+ foreignCatalog,
+ foreignSchema,
+ foreignTable
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getCrossReference(parentCatalog, parentSchema, parentTable,
+ foreignCatalog, foreignSchema, foreignTable);
+ }
+
+ @Test
+ public void testMetadataGetExportedKeys() throws Exception {
+ final String catalog = "";
+ final String schema = null;
+ final String table = "mytable";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_EXPORTED_KEYS, new Object[] {
+ catalog,
+ schema,
+ table
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getExportedKeys(catalog, schema, table);
+ }
+
+ @Test
+ public void testMetadataGetFunctionColumns() throws Exception {
+ final String catalog = null;
+ final String schemaPattern = "%";
+ final String functionNamePattern = "%";
+ final String columnNamePattern = "%";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_FUNCTION_COLUMNS, new Object[] {
+ catalog,
+ schemaPattern,
+ functionNamePattern,
+ columnNamePattern
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getFunctionColumns(catalog, schemaPattern, functionNamePattern,
+ columnNamePattern);
+ }
+
+ @Test
+ public void testMetadataGetFunctions() throws Exception {
+ final String catalog = null;
+ final String schemaPattern = "%";
+ final String functionNamePattern = "%";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_FUNCTIONS, new Object[] {
+ catalog,
+ schemaPattern,
+ functionNamePattern
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getFunctions(catalog, schemaPattern, functionNamePattern);
+ }
+
+ @Test
+ public void testMetadataGetImportedKeys() throws Exception {
+ final String catalog = "";
+ final String schema = null;
+ final String table = "my_table";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_IMPORTED_KEYS, new Object[] {
+ catalog,
+ schema,
+ table
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getImportedKeys(catalog, schema, table);
+ }
+
+ @Test
+ public void testMetadataGetIndexInfo() throws Exception {
+ final String catalog = "";
+ final String schema = null;
+ final String table = "my_table";
+ final boolean unique = true;
+ final boolean approximate = true;
+
+ QueryState state = new QueryState(MetaDataOperation.GET_INDEX_INFO, new Object[] {
+ catalog,
+ schema,
+ table,
+ unique,
+ approximate
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getIndexInfo(catalog, schema, table, unique, approximate);
+ }
+
+ @Test
+ public void testMetadataGetPrimaryKeys() throws Exception {
+ final String catalog = "";
+ final String schema = null;
+ final String table = "my_table";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_PRIMARY_KEYS, new Object[] {
+ catalog,
+ schema,
+ table
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getPrimaryKeys(catalog, schema, table);
+ }
+
+ @Test
+ public void testMetadataGetProcedureColumns() throws Exception {
+ final String catalog = "";
+ final String schemaPattern = null;
+ final String procedureNamePattern = "%";
+ final String columnNamePattern = "%";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_PROCEDURE_COLUMNS, new Object[] {
+ catalog,
+ schemaPattern,
+ procedureNamePattern,
+ columnNamePattern
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getProcedureColumns(catalog, schemaPattern, procedureNamePattern,
+ columnNamePattern);
+ }
+
+ @Test
+ public void testMetadataGetProcedures() throws Exception {
+ final String catalog = "";
+ final String schemaPattern = null;
+ final String procedureNamePattern = "%";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_PROCEDURES, new Object[] {
+ catalog,
+ schemaPattern,
+ procedureNamePattern,
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getProcedures(catalog, schemaPattern, procedureNamePattern);
+ }
+
+ @Test
+ public void testMetadataGetPseudoColumns() throws Exception {
+ final String catalog = "";
+ final String schemaPattern = null;
+ final String tableNamePattern = "%";
+ final String columnNamePattern = "%";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_PSEUDO_COLUMNS, new Object[] {
+ catalog,
+ schemaPattern,
+ tableNamePattern,
+ columnNamePattern
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getPseudoColumns(catalog, schemaPattern, tableNamePattern,
+ columnNamePattern);
+ }
+
+ @Test
+ public void testMetadataGetSchemas() throws Exception {
+ QueryState state = new QueryState(MetaDataOperation.GET_SCHEMAS, new Object[0]);
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getSchemas();
+ }
+
+ @Test
+ public void testMetadataGetSchemasWithArgs() throws Exception {
+ final String catalog = "";
+ final String schemaPattern = null;
+
+ QueryState state = new QueryState(MetaDataOperation.GET_SCHEMAS_WITH_ARGS, new Object[] {
+ catalog,
+ schemaPattern
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getSchemas(catalog, schemaPattern);
+ }
+
+ @Test
+ public void testMetadataGetSuperTables() throws Exception {
+ final String catalog = "";
+ final String schemaPattern = null;
+ final String tableNamePattern = "%";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_SUPER_TABLES, new Object[] {
+ catalog,
+ schemaPattern,
+ tableNamePattern
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getSuperTables(catalog, schemaPattern, tableNamePattern);
+ }
+
+ @Test
+ public void testMetadataGetSuperTypes() throws Exception {
+ final String catalog = "";
+ final String schemaPattern = null;
+ final String tableNamePattern = "%";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_SUPER_TYPES, new Object[] {
+ catalog,
+ schemaPattern,
+ tableNamePattern
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getSuperTypes(catalog, schemaPattern, tableNamePattern);
+ }
+
+ @Test
+ public void testMetadataGetTablePrivileges() throws Exception {
+ final String catalog = "";
+ final String schemaPattern = null;
+ final String tableNamePattern = "%";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_TABLE_PRIVILEGES, new Object[] {
+ catalog,
+ schemaPattern,
+ tableNamePattern
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getTablePrivileges(catalog, schemaPattern, tableNamePattern);
+ }
+
+ @Test
+ public void testMetadataGetTables() throws Exception {
+ final String catalog = "";
+ final String schemaPattern = null;
+ final String tableNamePattern = "%";
+ final String[] types = new String[] {"VIEW", "TABLE"};
+
+ QueryState state = new QueryState(MetaDataOperation.GET_TABLES, new Object[] {
+ catalog,
+ schemaPattern,
+ tableNamePattern,
+ types
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getTables(catalog, schemaPattern, tableNamePattern, types);
+ }
+
+ @Test
+ public void testMetadataGetTableTypes() throws Exception {
+ QueryState state = new QueryState(MetaDataOperation.GET_TABLE_TYPES, new Object[0]);
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getTableTypes();
+ }
+
+ @Test
+ public void testMetadataGetTypeInfo() throws Exception {
+ QueryState state = new QueryState(MetaDataOperation.GET_TYPE_INFO, new Object[0]);
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getTypeInfo();
+ }
+
+ @Test
+ public void testMetadataGetUDTs() throws Exception {
+ final String catalog = "";
+ final String schemaPattern = null;
+ final String typeNamePattern = "%";
+ final int[] types = new int[] {1, 2};
+
+ QueryState state = new QueryState(MetaDataOperation.GET_UDTS, new Object[] {
+ catalog,
+ schemaPattern,
+ typeNamePattern,
+ types
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getUDTs(catalog, schemaPattern, typeNamePattern, types);
+ }
+
+ @Test
+ public void testMetadataGetVersionColumns() throws Exception {
+ final String catalog = "";
+ final String schemaPattern = null;
+ final String table = "my_table";
+
+ QueryState state = new QueryState(MetaDataOperation.GET_VERSION_COLUMNS, new Object[] {
+ catalog,
+ schemaPattern,
+ table
+ });
+
+ state.invoke(conn, statement);
+
+ Mockito.verify(metadata).getVersionColumns(catalog, schemaPattern, table);
+ }
+
+ @Test
+ public void testSerialization() throws Exception {
+ final String catalog = "catalog";
+ final String schema = null;
+ final String table = "table";
+ final int scope = 1;
+ final boolean nullable = true;
+
+ QueryState state = new QueryState(MetaDataOperation.GET_BEST_ROW_IDENTIFIER, new Object[] {
+ catalog,
+ schema,
+ table,
+ scope,
+ nullable
+ });
+
+ assertEquals(state, QueryState.fromProto(state.toProto()));
+
+ final String schemaPattern = null;
+ final String typeNamePattern = "%";
+ final int[] types = new int[] {1, 2};
+
+ state = new QueryState(MetaDataOperation.GET_UDTS, new Object[] {
+ catalog,
+ schemaPattern,
+ typeNamePattern,
+ types
+ });
+
+ assertEquals(state, QueryState.fromProto(state.toProto()));
+
+ state = new QueryState("SELECT * FROM foo");
+
+ assertEquals(state, QueryState.fromProto(state.toProto()));
+ }
+
+}
+
+// End QueryStateTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/metrics/MetricsHelperTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/metrics/MetricsHelperTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/metrics/MetricsHelperTest.java
new file mode 100644
index 0000000..c85312d
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/metrics/MetricsHelperTest.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica.metrics;
+
+import org.apache.calcite.avatica.remote.MetricsHelper;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test class for {@link MetricsHelper}.
+ */
+public class MetricsHelperTest {
+
+ @Test(expected = NullPointerException.class) public void testNullConcat() {
+ MetricsHelper.concat(null, "foo");
+ }
+
+ @Test public void testConcat() {
+ String suffix = "suffix";
+ String finalName = getClass().getName() + "." + suffix;
+ assertEquals(finalName, MetricsHelper.concat(getClass(), suffix));
+ }
+
+}
+
+// End MetricsHelperTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AbstractHandlerTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AbstractHandlerTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AbstractHandlerTest.java
new file mode 100644
index 0000000..012cccc
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AbstractHandlerTest.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica.remote;
+
+import org.apache.calcite.avatica.AvaticaSeverity;
+import org.apache.calcite.avatica.remote.Handler.HandlerResponse;
+import org.apache.calcite.avatica.remote.Service.ErrorResponse;
+import org.apache.calcite.avatica.remote.Service.Request;
+import org.apache.calcite.avatica.remote.Service.Response;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Objects;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test for common functionality across {@link Handler} implementations.
+ */
+public class AbstractHandlerTest {
+
+ private String exceptionToString(Exception e) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ Objects.requireNonNull(e).printStackTrace(pw);
+ return sw.toString();
+ }
+
+ @Test public void testExceptionUnwrappingWithoutContext() {
+ @SuppressWarnings("unchecked")
+ AbstractHandler<String> handler = Mockito.mock(AbstractHandler.class);
+
+ Mockito.when(handler.unwrapException(Mockito.any(Exception.class))).thenCallRealMethod();
+
+ Exception e = new RuntimeException();
+ Response resp = handler.unwrapException(e);
+ assertTrue("Response should be ErrorResponse, but was " + resp.getClass(),
+ resp instanceof ErrorResponse);
+ ErrorResponse errorResp = (ErrorResponse) resp;
+ assertEquals(ErrorResponse.UNKNOWN_ERROR_CODE, errorResp.errorCode);
+ assertEquals(AvaticaSeverity.UNKNOWN, errorResp.severity);
+ assertEquals(Arrays.asList(exceptionToString(e)), errorResp.exceptions);
+
+ e = new AvaticaRuntimeException();
+ resp = handler.unwrapException(e);
+ assertTrue("Response should be ErrorResponse, but was " + resp.getClass(),
+ resp instanceof ErrorResponse);
+ errorResp = (ErrorResponse) resp;
+ assertEquals(ErrorResponse.UNKNOWN_ERROR_CODE, errorResp.errorCode);
+ assertEquals(AvaticaSeverity.UNKNOWN, errorResp.severity);
+ assertEquals(Arrays.asList(exceptionToString(e)), errorResp.exceptions);
+ }
+
+ @Test public void testExceptionUnwrappingWithContext() {
+ @SuppressWarnings("unchecked")
+ AbstractHandler<String> handler = Mockito.mock(AbstractHandler.class);
+
+ Mockito.when(handler.unwrapException(Mockito.any(Exception.class))).thenCallRealMethod();
+
+ final String msg = "Something failed!";
+ AvaticaRuntimeException e = new AvaticaRuntimeException(msg,
+ ErrorResponse.UNKNOWN_ERROR_CODE, ErrorResponse.UNKNOWN_SQL_STATE, AvaticaSeverity.FATAL);
+ Response resp = handler.unwrapException(e);
+ assertTrue("Response should be ErrorResponse, but was " + resp.getClass(),
+ resp instanceof ErrorResponse);
+ ErrorResponse errorResp = (ErrorResponse) resp;
+ assertEquals(ErrorResponse.UNKNOWN_ERROR_CODE, errorResp.errorCode);
+ assertEquals(AvaticaSeverity.FATAL, errorResp.severity);
+ assertEquals(Arrays.asList(exceptionToString(e)), errorResp.exceptions);
+ assertEquals(msg, errorResp.errorMessage);
+ }
+
+ @Test public void testFailedResponseSerialization() throws IOException {
+ @SuppressWarnings("unchecked")
+ final AbstractHandler<String> handler = Mockito.mock(AbstractHandler.class);
+ final Request request = Mockito.mock(Request.class);
+ final Response response = Mockito.mock(Response.class);
+ final IOException exception = new IOException();
+ final ErrorResponse errorResponse = Mockito.mock(ErrorResponse.class);
+ final String serializedErrorResponse = "An ErrorResponse";
+
+ // Accept a serialized request
+ Mockito.when(handler.apply(Mockito.anyString())).thenCallRealMethod();
+ // Deserialize it back into a POJO
+ Mockito.when(handler.decode(Mockito.anyString())).thenReturn(request);
+ // Construct the Response for that Request
+ Mockito.when(request.accept(Mockito.any(Service.class))).thenReturn(response);
+ // Throw an IOException when serializing the Response.
+ Mockito.when(handler.encode(response)).thenThrow(exception);
+ // Convert the IOException into an ErrorResponse
+ Mockito.when(handler.unwrapException(exception)).thenReturn(errorResponse);
+ Mockito.when(handler.encode(errorResponse)).thenReturn(serializedErrorResponse);
+
+ HandlerResponse<String> handlerResp = handler.apply("this is mocked out");
+ assertEquals(500, handlerResp.getStatusCode());
+ assertEquals(serializedErrorResponse, handlerResp.getResponse());
+ }
+
+ @Test public void testFailedErrorResponseSerialization() throws IOException {
+ @SuppressWarnings("unchecked")
+ final AbstractHandler<String> handler = Mockito.mock(AbstractHandler.class);
+ final Request request = Mockito.mock(Request.class);
+ final Response response = Mockito.mock(Response.class);
+ final IOException exception = new IOException();
+ final ErrorResponse errorResponse = Mockito.mock(ErrorResponse.class);
+
+ // Accept a serialized request
+ Mockito.when(handler.apply(Mockito.anyString())).thenCallRealMethod();
+ // Deserialize it back into a POJO
+ Mockito.when(handler.decode(Mockito.anyString())).thenReturn(request);
+ // Construct the Response for that Request
+ Mockito.when(request.accept(Mockito.any(Service.class))).thenReturn(response);
+ // Throw an IOException when serializing the Response.
+ Mockito.when(handler.encode(response)).thenThrow(exception);
+ // Convert the IOException into an ErrorResponse
+ Mockito.when(handler.unwrapException(exception)).thenReturn(errorResponse);
+ // Fail to serialize the ErrorResponse
+ Mockito.when(handler.encode(errorResponse)).thenThrow(exception);
+
+ try {
+ handler.apply("this is mocked out");
+ } catch (RuntimeException e) {
+ assertEquals(exception, e.getCause());
+ }
+ }
+
+ @Test public void testFailedRequestDeserialization() throws IOException {
+ @SuppressWarnings("unchecked")
+ final AbstractHandler<String> handler = Mockito.mock(AbstractHandler.class);
+ final IOException exception = new IOException();
+
+ // Accept a serialized request
+ Mockito.when(handler.apply(Mockito.anyString())).thenCallRealMethod();
+ // Throw an Exception trying to convert it back into a POJO
+ Mockito.when(handler.decode(Mockito.anyString())).thenThrow(exception);
+
+ try {
+ handler.apply("this is mocked out");
+ } catch (RuntimeException e) {
+ assertEquals(exception, e.getCause());
+ }
+ }
+}
+
+// End AbstractHandlerTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AvaticaHttpClientFactoryTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AvaticaHttpClientFactoryTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AvaticaHttpClientFactoryTest.java
new file mode 100644
index 0000000..cd64329
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AvaticaHttpClientFactoryTest.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica.remote;
+
+import org.apache.calcite.avatica.BuiltInConnectionProperty;
+import org.apache.calcite.avatica.ConnectionConfig;
+import org.apache.calcite.avatica.ConnectionConfigImpl;
+
+import org.junit.Test;
+
+import java.net.URL;
+import java.util.Properties;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for the factory that creates http clients.
+ */
+public class AvaticaHttpClientFactoryTest {
+
+ @Test public void testDefaultHttpClient() throws Exception {
+ Properties props = new Properties();
+ URL url = new URL("http://localhost:8765");
+ ConnectionConfig config = new ConnectionConfigImpl(props);
+ AvaticaHttpClientFactory httpClientFactory = new AvaticaHttpClientFactoryImpl();
+
+ AvaticaHttpClient client = httpClientFactory.getClient(url, config);
+ assertTrue("Client was an instance of " + client.getClass(),
+ client instanceof AvaticaCommonsHttpClientImpl);
+ }
+
+ @Test public void testOverridenHttpClient() throws Exception {
+ Properties props = new Properties();
+ props.setProperty(BuiltInConnectionProperty.HTTP_CLIENT_IMPL.name(),
+ AvaticaHttpClientImpl.class.getName());
+ URL url = new URL("http://localhost:8765");
+ ConnectionConfig config = new ConnectionConfigImpl(props);
+ AvaticaHttpClientFactory httpClientFactory = new AvaticaHttpClientFactoryImpl();
+
+ AvaticaHttpClient client = httpClientFactory.getClient(url, config);
+ assertTrue("Client was an instance of " + client.getClass(),
+ client instanceof AvaticaHttpClientImpl);
+ }
+}
+
+// End AvaticaHttpClientFactoryTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AvaticaHttpClientTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AvaticaHttpClientTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AvaticaHttpClientTest.java
new file mode 100644
index 0000000..33369d2
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AvaticaHttpClientTest.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica.remote;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.Assert.assertArrayEquals;
+
+/**
+ * Tests for the HTTP transport.
+ */
+public class AvaticaHttpClientTest {
+ private static final String REQUEST =
+ "{\"request\":\"createStatement\",\"connectionId\":\"8f3f28ee-d0bb-4cdb-a4b1-8f6e8476c534\"}";
+ private static final String RESPONSE =
+ "{\"response\":\"createStatement\",\"connectionId\":"
+ + "\"8f3f28ee-d0bb-4cdb-a4b1-8f6e8476c534\",\"statementId\":1608176856}";
+
+ @Test
+ public void testRetryOnUnavailable() throws Exception {
+ // HTTP-503, try again
+ URL url = new URL("http://127.0.0.1:8765");
+ final HttpURLConnection cnxn = Mockito.mock(HttpURLConnection.class);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ByteArrayInputStream bais = new ByteArrayInputStream(RESPONSE.getBytes(StandardCharsets.UTF_8));
+
+ // Create the HTTP client
+ AvaticaHttpClientImpl client = new AvaticaHttpClientImpl(url) {
+ @Override HttpURLConnection openConnection() throws IOException {
+ return cnxn;
+ }
+ };
+
+ // HTTP 503 then 200
+ Mockito.when(cnxn.getResponseCode()).thenReturn(HttpURLConnection.HTTP_UNAVAILABLE,
+ HttpURLConnection.HTTP_OK);
+
+ Mockito.when(cnxn.getOutputStream()).thenReturn(baos);
+ Mockito.when(cnxn.getInputStream()).thenReturn(bais);
+
+ byte[] response = client.send(REQUEST.getBytes(StandardCharsets.UTF_8));
+
+ assertArrayEquals(RESPONSE.getBytes(StandardCharsets.UTF_8), response);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testServerError() throws Exception {
+ // HTTP 500 should error out
+ URL url = new URL("http://127.0.0.1:8765");
+ final HttpURLConnection cnxn = Mockito.mock(HttpURLConnection.class);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // Create the HTTP client
+ AvaticaHttpClientImpl client = new AvaticaHttpClientImpl(url) {
+ @Override HttpURLConnection openConnection() throws IOException {
+ return cnxn;
+ }
+ };
+
+ // HTTP 500
+ Mockito.when(cnxn.getResponseCode()).thenReturn(HttpURLConnection.HTTP_INTERNAL_ERROR);
+
+ Mockito.when(cnxn.getOutputStream()).thenReturn(baos);
+
+ // Should throw an RTE
+ client.send(REQUEST.getBytes(StandardCharsets.UTF_8));
+ }
+
+}
+
+// End AvaticaHttpClientTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ErrorResponseTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ErrorResponseTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ErrorResponseTest.java
new file mode 100644
index 0000000..f66cb26
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ErrorResponseTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica.remote;
+
+import org.apache.calcite.avatica.AvaticaClientRuntimeException;
+import org.apache.calcite.avatica.AvaticaSeverity;
+import org.apache.calcite.avatica.remote.Service.ErrorResponse;
+import org.apache.calcite.avatica.remote.Service.RpcMetadataResponse;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * A test class for ErrorResponse.
+ */
+public class ErrorResponseTest {
+
+ @Test public void testEquality() {
+ final String message = "There was an error";
+ final int code = 23;
+ final String state = "a1b2c";
+ final AvaticaSeverity severity = AvaticaSeverity.ERROR;
+ final List<String> exceptions = Arrays.asList("Server Stacktrace 1", "Server Stacktace 2");
+ final RpcMetadataResponse metadata = new RpcMetadataResponse("localhost:8765");
+ assertEquals(new ErrorResponse(message, code, state, severity, exceptions, metadata),
+ new ErrorResponse(message, code, state, severity, exceptions, metadata));
+ }
+
+ @Test public void testToClientRTE() {
+ final String message = "There was an error";
+ final int code = 23;
+ final String state = "a1b2c";
+ final AvaticaSeverity severity = AvaticaSeverity.ERROR;
+ final List<String> exceptions = Arrays.asList("Server Stacktrace 1", "Server Stacktace 2");
+ final RpcMetadataResponse metadata = new RpcMetadataResponse("localhost:8765");
+ final ErrorResponse resp = new ErrorResponse(message, code, state, severity, exceptions,
+ metadata);
+ AvaticaClientRuntimeException exception = resp.toException();
+ assertTrue("Expected error message to end with '" + resp.errorMessage + "', but was '"
+ + exception.getMessage() + "'", exception.getMessage().endsWith(resp.errorMessage));
+ assertEquals(resp.errorCode, exception.getErrorCode());
+ assertEquals(resp.severity, exception.getSeverity());
+ assertEquals(resp.sqlState, exception.getSqlState());
+ assertEquals(resp.exceptions, exception.getServerExceptions());
+ assertEquals(resp.rpcMetadata, exception.getRpcMetadata());
+ }
+}
+
+// End ErrorResponseTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/remote/MetaDataOperationTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/MetaDataOperationTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/MetaDataOperationTest.java
new file mode 100644
index 0000000..c64b32c
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/MetaDataOperationTest.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica.remote;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for {@link MetaDataOperation}
+ */
+public class MetaDataOperationTest {
+
+ @Test
+ public void testProtobufSerialization() {
+ for (MetaDataOperation metadataOp : MetaDataOperation.values()) {
+ assertEquals(metadataOp, MetaDataOperation.fromProto(metadataOp.toProto()));
+ }
+ }
+
+}
+
+// End MetaDataOperationTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufHandlerTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufHandlerTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufHandlerTest.java
new file mode 100644
index 0000000..afb15c3
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufHandlerTest.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica.remote;
+
+import org.apache.calcite.avatica.Meta;
+import org.apache.calcite.avatica.Meta.Frame;
+import org.apache.calcite.avatica.metrics.noop.NoopMetricsSystem;
+import org.apache.calcite.avatica.proto.Common;
+import org.apache.calcite.avatica.proto.Common.ColumnValue;
+import org.apache.calcite.avatica.proto.Requests;
+import org.apache.calcite.avatica.proto.Responses;
+import org.apache.calcite.avatica.remote.Handler.HandlerResponse;
+import org.apache.calcite.avatica.remote.Service.FetchRequest;
+import org.apache.calcite.avatica.remote.Service.FetchResponse;
+import org.apache.calcite.avatica.remote.Service.RpcMetadataResponse;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+/**
+ * Test basic serialization of objects with protocol buffers.
+ */
+public class ProtobufHandlerTest {
+
+ // Mocks
+ private Service service;
+ private ProtobufTranslation translation;
+
+ // Real objects
+ private ProtobufHandler handler;
+
+ @Before
+ public void setupMocks() {
+ // Mocks
+ service = Mockito.mock(Service.class);
+ translation = Mockito.mock(ProtobufTranslation.class);
+
+ // Real objects
+ handler = new ProtobufHandler(service, translation, NoopMetricsSystem.getInstance());
+ }
+
+ @Test
+ public void testFetch() throws Exception {
+ final String connectionId = "cnxn1";
+ final int statementId = 30;
+ final long offset = 10;
+ final int fetchMaxRowCount = 100;
+ final List<Common.TypedValue> values = new ArrayList<>();
+
+ values.add(Common.TypedValue.newBuilder().setType(Common.Rep.BOOLEAN).setBoolValue(true)
+ .build());
+ values.add(Common.TypedValue.newBuilder().setType(Common.Rep.STRING)
+ .setStringValue("my_string").build());
+
+ Requests.FetchRequest protoRequest = Requests.FetchRequest.newBuilder()
+ .setConnectionId(connectionId).setStatementId(statementId)
+ .setOffset(offset).setFetchMaxRowCount(fetchMaxRowCount)
+ .build();
+ byte[] serializedRequest = protoRequest.toByteArray();
+
+ FetchRequest request = new FetchRequest().deserialize(protoRequest);
+
+ List<Object> frameRows = new ArrayList<>();
+ frameRows.add(new Object[] {true, "my_string"});
+
+ Meta.Frame frame = Frame.create(0, true, frameRows);
+ RpcMetadataResponse metadata = new RpcMetadataResponse("localhost:8765");
+ FetchResponse response = new FetchResponse(frame, false, false, metadata);
+
+ when(translation.parseRequest(serializedRequest)).thenReturn(request);
+ when(service.apply(request)).thenReturn(response);
+ when(translation.serializeResponse(response))
+ .thenReturn(response.serialize().toByteArray());
+
+ HandlerResponse<byte[]> handlerResponse = handler.apply(serializedRequest);
+ byte[] serializedResponse = handlerResponse.getResponse();
+ assertEquals(200, handlerResponse.getStatusCode());
+
+ Responses.FetchResponse protoResponse = Responses.FetchResponse.parseFrom(serializedResponse);
+
+ Common.Frame protoFrame = protoResponse.getFrame();
+
+ assertEquals(frame.offset, protoFrame.getOffset());
+ assertEquals(frame.done, protoFrame.getDone());
+
+ List<Common.Row> rows = protoFrame.getRowsList();
+ assertEquals(1, rows.size());
+ Common.Row row = rows.get(0);
+ List<Common.ColumnValue> columnValues = row.getValueList();
+ assertEquals(2, columnValues.size());
+
+ Iterator<Common.ColumnValue> iter = columnValues.iterator();
+ assertTrue(iter.hasNext());
+ Common.ColumnValue column = iter.next();
+ assertTrue("The Column should have contained a scalar: " + column,
+ column.hasField(ColumnValue.getDescriptor()
+ .findFieldByNumber(ColumnValue.SCALAR_VALUE_FIELD_NUMBER)));
+
+ Common.TypedValue value = column.getScalarValue();
+ assertEquals(Common.Rep.BOOLEAN, value.getType());
+ assertEquals(true, value.getBoolValue());
+
+ assertTrue(iter.hasNext());
+ column = iter.next();
+ assertTrue("The Column should have contained a scalar: " + column,
+ column.hasField(ColumnValue.getDescriptor()
+ .findFieldByNumber(ColumnValue.SCALAR_VALUE_FIELD_NUMBER)));
+ value = column.getScalarValue();
+ assertEquals(Common.Rep.STRING, value.getType());
+ assertEquals("my_string", value.getStringValue());
+ }
+
+}
+
+// End ProtobufHandlerTest.java