All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cassandra.cql3.functions.types.UserType Maven / Gradle / Ivy

Go to download

The Apache Cassandra Project develops a highly scalable second-generation distributed database, bringing together Dynamo's fully distributed design and Bigtable's ColumnFamily-based data model.

There is a newer version: 5.0-rc1
Show 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 org.apache.cassandra.cql3.functions.types;

import java.util.*;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterators;

import org.apache.cassandra.transport.ProtocolVersion;

/**
 * A User Defined Type (UDT).
 *
 * 

A UDT is a essentially a named collection of fields (with a name and a type). */ public class UserType extends DataType implements Iterable { private final String keyspace; private final String typeName; private final boolean frozen; private final ProtocolVersion protocolVersion; // can be null, if this object is being constructed from a response message // see Responses.Result.Rows.Metadata.decode() private final CodecRegistry codecRegistry; // Note that we don't expose the order of fields, from an API perspective this is a map // of String->Field, but internally we care about the order because the serialization format // of UDT expects a particular order. final Field[] byIdx; // For a given name, we can only have one field with that name, so we don't need a int[] in // practice. However, storing one element arrays save allocations in UDTValue.getAllIndexesOf // implementation. final Map byName; private UserType( Name name, String keyspace, String typeName, boolean frozen, ProtocolVersion protocolVersion, CodecRegistry codecRegistry, Field[] byIdx, Map byName) { super(name); this.keyspace = keyspace; this.typeName = typeName; this.frozen = frozen; this.protocolVersion = protocolVersion; this.codecRegistry = codecRegistry; this.byIdx = byIdx; this.byName = byName; } UserType( String keyspace, String typeName, boolean frozen, Collection fields, ProtocolVersion protocolVersion, CodecRegistry codecRegistry) { this( DataType.Name.UDT, keyspace, typeName, frozen, protocolVersion, codecRegistry, fields.toArray(new Field[fields.size()]), mapByName(fields)); } private static ImmutableMap mapByName(Collection fields) { ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); int i = 0; for (Field field : fields) { builder.put(field.getName(), new int[]{ i }); i += 1; } return builder.build(); } /** * Returns a new empty value for this user type definition. * * @return an empty value for this user type definition. */ public UDTValue newValue() { return new UDTValue(this); } /** * The name of the keyspace this UDT is part of. * * @return the name of the keyspace this UDT is part of. */ public String getKeyspace() { return keyspace; } /** * The name of this user type. * * @return the name of this user type. */ public String getTypeName() { return typeName; } /** * Returns the number of fields in this UDT. * * @return the number of fields in this UDT. */ public int size() { return byIdx.length; } /** * Returns whether this UDT contains a given field. * * @param name the name to check. Note that {@code name} obey the usual CQL identifier rules: it * should be quoted if it denotes a case sensitive identifier (you can use {@link * Metadata#quote} for the quoting). * @return {@code true} if this UDT contains a field named {@code name}, {@code false} otherwise. */ public boolean contains(String name) { return byName.containsKey(Metadata.handleId(name)); } /** * Returns an iterator over the fields of this UDT. * * @return an iterator over the fields of this UDT. */ @Override public Iterator iterator() { return Iterators.forArray(byIdx); } /** * Returns the type of a given field. * * @param name the name of the field. Note that {@code name} obey the usual CQL identifier rules: * it should be quoted if it denotes a case sensitive identifier (you can use {@link * Metadata#quote} for the quoting). * @return the type of field {@code name} if this UDT has a field of this name, {@code null} * otherwise. * @throws IllegalArgumentException if {@code name} is not a field of this UDT definition. */ DataType getFieldType(String name) { int[] idx = byName.get(Metadata.handleId(name)); if (idx == null) throw new IllegalArgumentException(name + " is not a field defined in this definition"); return byIdx[idx[0]].getType(); } @Override public boolean isFrozen() { return frozen; } public UserType copy(boolean newFrozen) { if (newFrozen == frozen) { return this; } else { return new UserType( name, keyspace, typeName, newFrozen, protocolVersion, codecRegistry, byIdx, byName); } } @Override public int hashCode() { int result = name.hashCode(); result = 31 * result + keyspace.hashCode(); result = 31 * result + typeName.hashCode(); result = 31 * result + Arrays.hashCode(byIdx); return result; } @Override public boolean equals(Object o) { if (!(o instanceof UserType)) return false; UserType other = (UserType) o; // Note: we don't test byName because it's redundant with byIdx in practice, // but also because the map holds 'int[]' which don't have proper equal. return name.equals(other.name) && keyspace.equals(other.keyspace) && typeName.equals(other.typeName) && Arrays.equals(byIdx, other.byIdx); } /** * Return the protocol version that has been used to deserialize this UDT, or that will be used to * serialize it. In most cases this should be the version currently in use by the cluster instance * that this UDT belongs to, as reported by {@code ProtocolOptions#getProtocolVersion()}. * * @return the protocol version that has been used to deserialize this UDT, or that will be used * to serialize it. */ ProtocolVersion getProtocolVersion() { return protocolVersion; } CodecRegistry getCodecRegistry() { return codecRegistry; } @Override public String toString() { String str = Metadata.quoteIfNecessary(getKeyspace()) + '.' + Metadata.quoteIfNecessary(getTypeName()); return isFrozen() ? "frozen<" + str + '>' : str; } @Override public String asFunctionParameterString() { return Metadata.quoteIfNecessary(getTypeName()); } /** * A UDT field. */ public static class Field { private final String name; private final DataType type; Field(String name, DataType type) { this.name = name; this.type = type; } /** * Returns the name of the field. * * @return the name of the field. */ public String getName() { return name; } /** * Returns the type of the field. * * @return the type of the field. */ public DataType getType() { return type; } @Override public final int hashCode() { return Arrays.hashCode(new Object[]{ name, type }); } @Override public final boolean equals(Object o) { if (!(o instanceof Field)) return false; Field other = (Field) o; return name.equals(other.name) && type.equals(other.type); } @Override public String toString() { return Metadata.quoteIfNecessary(name) + ' ' + type; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy