com.datastax.oss.driver.internal.core.metadata.schema.parsing.RelationParser Maven / Gradle / Ivy
The newest version!
/*
* 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 com.datastax.oss.driver.internal.core.metadata.schema.parsing;
import com.datastax.dse.driver.api.core.metadata.DseNodeProperties;
import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.Version;
import com.datastax.oss.driver.api.core.metadata.Node;
import com.datastax.oss.driver.api.core.metadata.schema.Describable;
import com.datastax.oss.driver.api.core.metadata.schema.RelationMetadata;
import com.datastax.oss.driver.api.core.type.codec.TypeCodec;
import com.datastax.oss.driver.api.core.type.codec.TypeCodecs;
import com.datastax.oss.driver.internal.core.adminrequest.AdminRow;
import com.datastax.oss.driver.internal.core.context.InternalDriverContext;
import com.datastax.oss.driver.internal.core.metadata.schema.ScriptBuilder;
import com.datastax.oss.driver.internal.core.metadata.schema.queries.SchemaRows;
import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap;
import java.nio.ByteBuffer;
import java.util.Map;
import net.jcip.annotations.ThreadSafe;
// Shared code for table and view parsing
@ThreadSafe
public abstract class RelationParser {
protected final SchemaRows rows;
protected final InternalDriverContext context;
protected final String logPrefix;
protected RelationParser(SchemaRows rows, InternalDriverContext context) {
this.rows = rows;
this.context = context;
this.logPrefix = context.getSessionName();
}
protected Map parseOptions(AdminRow row) {
ImmutableMap.Builder builder = ImmutableMap.builder();
for (Map.Entry> entry : OPTION_CODECS.entrySet()) {
String name = entry.getKey();
CqlIdentifier id = CqlIdentifier.fromInternal(name);
TypeCodec codec = entry.getValue();
if (name.equals("caching") && row.isString("caching")) {
// C* <=2.2, caching is stored as a string, and also appears as a string in the WITH clause.
builder.put(id, row.getString(name));
} else if (name.equals("compaction_strategy_class")) {
// C* <=2.2, compaction options split in two columns
String strategyClass = row.getString(name);
if (strategyClass != null) {
builder.put(
CqlIdentifier.fromInternal("compaction"),
ImmutableMap.builder()
.put("class", strategyClass)
.putAll(
SimpleJsonParser.parseStringMap(row.getString("compaction_strategy_options")))
.build());
}
} else if (name.equals("compression_parameters")) {
// C* <=2.2, compression stored as a string
String compressionParameters = row.getString(name);
if (compressionParameters != null) {
builder.put(
CqlIdentifier.fromInternal("compression"),
ImmutableMap.copyOf(SimpleJsonParser.parseStringMap(row.getString(name))));
}
} else if (!isDeprecatedInCassandra4(name)) {
// Default case, read the value in a generic fashion
Object value = row.get(name, codec);
if (value != null) {
builder.put(id, value);
}
}
}
return builder.build();
}
/**
* Handle a few oddities in Cassandra 4: some options still appear in system_schema.tables, but
* they are not valid in CREATE statements anymore. We need to exclude them from our metadata,
* otherwise {@link Describable#describe(boolean)} will generate invalid CQL.
*/
private boolean isDeprecatedInCassandra4(String name) {
return isCassandra4OrAbove()
&& (name.equals("read_repair_chance")
|| name.equals("dclocal_read_repair_chance")
// default_time_to_live is not allowed in CREATE MATERIALIZED VIEW statements
|| (name.equals("default_time_to_live") && (this instanceof ViewParser)));
}
private boolean isCassandra4OrAbove() {
Node node = rows.getNode();
return !node.getExtras().containsKey(DseNodeProperties.DSE_VERSION)
&& node.getCassandraVersion() != null
&& node.getCassandraVersion().nextStable().compareTo(Version.V4_0_0) >= 0;
}
public static void appendOptions(Map options, ScriptBuilder builder) {
for (Map.Entry entry : options.entrySet()) {
CqlIdentifier name = entry.getKey();
Object value = entry.getValue();
String formattedValue;
if (name.asInternal().equals("caching") && value instanceof String) {
formattedValue = TypeCodecs.TEXT.format((String) value);
} else {
@SuppressWarnings("unchecked")
TypeCodec