blob: b7a67974966c8ae70b42cf07c293c34ef679785c [file] [log] [blame]
/*
* 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.proto.Common;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.protobuf.Descriptors.FieldDescriptor;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Objects;
/** Concrete implementation of {@link Meta.ConnectionProperties}. Provides additional state
* tracking to enable {@code RemoteMeta} to lazily push changes up to a query server.
*
* <p>{@code Meta} instances should probably hold authority on the {@code isDirty}
* flag because {@code AvaticaConnection} instances have no way of knowing if they're local or
* remote.
*/
public class ConnectionPropertiesImpl implements Meta.ConnectionProperties {
private static final FieldDescriptor CATALOG_DESCRIPTOR = Common.ConnectionProperties
.getDescriptor().findFieldByNumber(Common.ConnectionProperties.CATALOG_FIELD_NUMBER);
private static final FieldDescriptor SCHEMA_DESCRIPTOR = Common.ConnectionProperties
.getDescriptor().findFieldByNumber(Common.ConnectionProperties.SCHEMA_FIELD_NUMBER);
private static final FieldDescriptor TRANSACTION_ISOLATION_DESCRIPTOR = Common
.ConnectionProperties.getDescriptor().findFieldByNumber(
Common.ConnectionProperties.TRANSACTION_ISOLATION_FIELD_NUMBER);
private boolean isDirty = false;
private Boolean autoCommit;
private Boolean readOnly;
private Integer transactionIsolation;
private String catalog;
private String schema;
// TODO: replace with Meta.ConnectionProperties$EMPTY instance?
public ConnectionPropertiesImpl() {}
public ConnectionPropertiesImpl(Connection conn) throws SQLException {
this(conn.getAutoCommit(), conn.isReadOnly(), conn.getTransactionIsolation(),
conn.getCatalog(), conn.getSchema());
}
@JsonCreator
public ConnectionPropertiesImpl(
@JsonProperty("autoCommit") Boolean autoCommit,
@JsonProperty("readOnly") Boolean readOnly,
@JsonProperty("transactionIsolation") Integer transactionIsolation,
@JsonProperty("catalog") String catalog,
@JsonProperty("schema") String schema) {
this.autoCommit = autoCommit;
this.readOnly = readOnly;
this.transactionIsolation = transactionIsolation;
this.catalog = catalog;
this.schema = schema;
}
public ConnectionPropertiesImpl setDirty(boolean val) {
this.isDirty = val;
return this;
}
public boolean isDirty() {
return this.isDirty;
}
@Override public boolean isEmpty() {
return autoCommit == null && readOnly == null && transactionIsolation == null
&& catalog == null && schema == null;
}
/** Overwrites fields in {@code this} with any non-null fields in {@code that}. Sets
* {@code isDirty} if any fields are changed.
*
* @return {@code this}
*/
@Override public ConnectionPropertiesImpl merge(Meta.ConnectionProperties that) {
if (this == that) {
return this;
}
if (that.isAutoCommit() != null && !Objects.equals(this.autoCommit, that.isAutoCommit())) {
this.autoCommit = that.isAutoCommit();
this.isDirty = true;
}
if (that.isReadOnly() != null && !Objects.equals(this.readOnly, that.isReadOnly())) {
this.readOnly = that.isReadOnly();
this.isDirty = true;
}
if (that.getTransactionIsolation() != null
&& !Objects.equals(this.transactionIsolation, that.getTransactionIsolation())) {
this.transactionIsolation = that.getTransactionIsolation();
this.isDirty = true;
}
if (that.getCatalog() != null && !that.getCatalog().equalsIgnoreCase(this.catalog)) {
this.catalog = that.getCatalog();
this.isDirty = true;
}
if (that.getSchema() != null && !that.getSchema().equalsIgnoreCase(this.schema)) {
this.schema = that.getSchema();
this.isDirty = true;
}
return this;
}
/** Sets {@code autoCommit} status and flag as dirty.
*
* @return {@code this}
*/
@Override public Meta.ConnectionProperties setAutoCommit(boolean val) {
this.autoCommit = val;
this.isDirty = true;
return this;
}
@Override public Boolean isAutoCommit() {
return this.autoCommit;
}
/** Sets {@code readOnly} status and flag as dirty.
*
* @return {@code this}
*/
@Override public Meta.ConnectionProperties setReadOnly(boolean val) {
this.readOnly = val;
this.isDirty = true;
return this;
}
@Override public Boolean isReadOnly() {
return this.readOnly;
}
/** Sets {@code transactionIsolation} status and flag as dirty.
*
* @return {@code this}
*/
@Override public Meta.ConnectionProperties setTransactionIsolation(int val) {
this.transactionIsolation = val;
this.isDirty = true;
return this;
}
public Integer getTransactionIsolation() {
return this.transactionIsolation;
}
/** Sets {@code catalog} and flag as dirty.
*
* @return {@code this}
*/
@Override public Meta.ConnectionProperties setCatalog(String val) {
this.catalog = val;
this.isDirty = true;
return this;
}
@Override public String getCatalog() {
return this.catalog;
}
/** Sets {@code schema} and flag as dirty.
*
* @return {@code this}
*/
@Override public Meta.ConnectionProperties setSchema(String val) {
this.schema = val;
this.isDirty = true;
return this;
}
public String getSchema() {
return this.schema;
}
@Override public int hashCode() {
return Objects.hash(autoCommit, catalog, isDirty, readOnly, schema,
transactionIsolation);
}
@Override public boolean equals(Object o) {
return o == this
|| o instanceof ConnectionPropertiesImpl
&& Objects.equals(autoCommit, ((ConnectionPropertiesImpl) o).autoCommit)
&& Objects.equals(catalog, ((ConnectionPropertiesImpl) o).catalog)
&& isDirty == ((ConnectionPropertiesImpl) o).isDirty
&& Objects.equals(readOnly, ((ConnectionPropertiesImpl) o).readOnly)
&& Objects.equals(schema, ((ConnectionPropertiesImpl) o).schema)
&& Objects.equals(transactionIsolation,
((ConnectionPropertiesImpl) o).transactionIsolation);
}
public Common.ConnectionProperties toProto() {
Common.ConnectionProperties.Builder builder = Common.ConnectionProperties.newBuilder();
if (null != autoCommit) {
builder.setHasAutoCommit(true);
builder.setAutoCommit(autoCommit.booleanValue());
} else {
// Be explicit to avoid default value confusion
builder.setHasAutoCommit(false);
}
if (null != catalog) {
builder.setCatalog(catalog);
}
builder.setIsDirty(isDirty);
if (null != readOnly) {
builder.setHasReadOnly(true);
builder.setReadOnly(readOnly.booleanValue());
} else {
// Be explicit to avoid default value confusion
builder.setHasReadOnly(false);
}
if (null != schema) {
builder.setSchema(schema);
}
if (null != transactionIsolation) {
builder.setTransactionIsolation(transactionIsolation.intValue());
}
return builder.build();
}
public static ConnectionPropertiesImpl fromProto(Common.ConnectionProperties proto) {
String catalog = null;
if (proto.hasField(CATALOG_DESCRIPTOR)) {
catalog = proto.getCatalog();
}
String schema = null;
if (proto.hasField(SCHEMA_DESCRIPTOR)) {
schema = proto.getSchema();
}
Boolean autoCommit = null;
if (proto.getHasAutoCommit()) {
autoCommit = Boolean.valueOf(proto.getAutoCommit());
}
Boolean readOnly = null;
if (proto.getHasReadOnly()) {
readOnly = Boolean.valueOf(proto.getReadOnly());
}
Integer transactionIsolation = null;
if (proto.hasField(TRANSACTION_ISOLATION_DESCRIPTOR)) {
transactionIsolation = Integer.valueOf(proto.getTransactionIsolation());
}
ConnectionPropertiesImpl impl = new ConnectionPropertiesImpl(autoCommit, readOnly,
transactionIsolation, catalog, schema);
impl.setDirty(proto.getIsDirty());
return impl;
}
}
// End ConnectionPropertiesImpl.java