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

com.datastax.driver.core.ColumnDefinitions Maven / Gradle / Ivy

The newest version!
/*
 * Copyright DataStax, Inc.
 *
 * 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.
 */
package com.datastax.driver.core;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Metadata describing the columns returned in a {@link ResultSet} or a {@link PreparedStatement}.
 *
 * 

A {@code columnDefinitions}} instance is mainly a list of {@code * ColumnsDefinitions.Definition}. The definitions or metadata for a column can be accessed either * by: * *

    *
  • index (indexed from 0) *
  • name *
* *

When accessed by name, column selection is case insensitive. In case multiple columns only * differ by the case of their name, then the column returned with be the first column that has been * defined in CQL without forcing case sensitivity (that is, it has either been defined without * quotes or is fully lowercase). If none of the columns have been defined in this manner, the first * column matching (with case insensitivity) is returned. You can force the case of a selection by * double quoting the name. * *

For example: * *

    *
  • If {@code cd} contains column {@code fOO}, then {@code cd.contains("foo")}, {@code * cd.contains("fOO")} and {@code cd.contains("Foo")} will return {@code true}. *
  • If {@code cd} contains both {@code foo} and {@code FOO} then: *
      *
    • {@code cd.getType("foo")}, {@code cd.getType("fOO")} and {@code cd.getType("FOO")} * will all match column {@code foo}. *
    • {@code cd.getType("\"FOO\"")} will match column {@code FOO} *
    *
* * Note that the preceding rules mean that if a {@code ColumnDefinitions} object contains multiple * occurrences of the exact same name (be it the same column multiple times or columns from * different tables with the same name), you will have to use selection by index to disambiguate. */ public class ColumnDefinitions implements Iterable { static final ColumnDefinitions EMPTY = new ColumnDefinitions(new Definition[0], CodecRegistry.DEFAULT_INSTANCE); private final Definition[] byIdx; private final Map byName; final CodecRegistry codecRegistry; ColumnDefinitions(Definition[] defs, CodecRegistry codecRegistry) { this.byIdx = defs; this.codecRegistry = codecRegistry; this.byName = new HashMap(defs.length); for (int i = 0; i < defs.length; i++) { // Be optimistic, 99% of the time, previous will be null. int[] previous = this.byName.put(defs[i].name.toLowerCase(), new int[] {i}); if (previous != null) { int[] indexes = new int[previous.length + 1]; System.arraycopy(previous, 0, indexes, 0, previous.length); indexes[indexes.length - 1] = i; this.byName.put(defs[i].name.toLowerCase(), indexes); } } } /** * Returns the number of columns described by this {@code Columns} instance. * * @return the number of columns described by this metadata. */ public int size() { return byIdx.length; } /** * Returns whether this metadata contains a given name. * * @param name the name to check. * @return {@code true} if this metadata contains the column named {@code name}, {@code false} * otherwise. */ public boolean contains(String name) { return findAllIdx(name) != null; } /** * The first index in this metadata of the provided name, if present. * * @param name the name of the column. * @return the index of the first occurrence of {@code name} in this metadata if {@code * contains(name)}, -1 otherwise. */ public int getIndexOf(String name) { return findFirstIdx(name); } /** * Returns an iterator over the {@link Definition} contained in this metadata. * *

The order of the iterator will be the one of this metadata. * * @return an iterator over the {@link Definition} contained in this metadata. */ @Override public Iterator iterator() { return Arrays.asList(byIdx).iterator(); } /** * Returns a list containing all the definitions of this metadata in order. * * @return a list of the {@link Definition} contained in this metadata. */ public List asList() { return Arrays.asList(byIdx); } /** * Returns the name of the {@code i}th column in this metadata. * * @param i the index in this metadata. * @return the name of the {@code i}th column in this metadata. * @throws IndexOutOfBoundsException if {@code i < 0} or {@code i >= size()} */ public String getName(int i) { return byIdx[i].name; } /** * Returns the type of the {@code i}th column in this metadata. * *

Note that this method does not set the {@link DataType#isFrozen()} flag on the returned * object, it will always default to {@code false}. Use {@link Cluster#getMetadata()} to determine * if a column is frozen. * * @param i the index in this metadata. * @return the type of the {@code i}th column in this metadata. * @throws IndexOutOfBoundsException if {@code i < 0} or {@code i >= size()} */ public DataType getType(int i) { return byIdx[i].type; } /** * Returns the type of the first occurrence of {@code name} in this metadata. * *

Note that this method does not set the {@link DataType#isFrozen()} flag on the returned * object, it will always default to {@code false}. Use {@link Cluster#getMetadata()} to determine * if a column is frozen. * * @param name the name of the column. * @return the type of (the first occurrence of) {@code name} in this metadata. * @throws IllegalArgumentException if {@code name} is not in this metadata. */ public DataType getType(String name) { return getType(getFirstIdx(name)); } /** * Returns the keyspace of the {@code i}th column in this metadata. * * @param i the index in this metadata. * @return the keyspace of the {@code i}th column in this metadata. * @throws IndexOutOfBoundsException if {@code i < 0} or {@code i >= size()} */ public String getKeyspace(int i) { return byIdx[i].keyspace; } /** * Returns the keyspace of the first occurrence of {@code name} in this metadata. * * @param name the name of the column. * @return the keyspace of (the first occurrence of) column {@code name} in this metadata. * @throws IllegalArgumentException if {@code name} is not in this metadata. */ public String getKeyspace(String name) { return getKeyspace(getFirstIdx(name)); } /** * Returns the table of the {@code i}th column in this metadata. * * @param i the index in this metadata. * @return the table of the {@code i}th column in this metadata. * @throws IndexOutOfBoundsException if {@code i < 0} or {@code i >= size()} */ public String getTable(int i) { return byIdx[i].table; } /** * Returns the table of first occurrence of {@code name} in this metadata. * * @param name the name of the column. * @return the table of (the first occurrence of) column {@code name} in this metadata. * @throws IllegalArgumentException if {@code name} is not in this metadata. */ public String getTable(String name) { return getTable(getFirstIdx(name)); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Columns["); for (int i = 0; i < size(); i++) { if (i != 0) sb.append(", "); Definition def = byIdx[i]; sb.append(def.name).append('(').append(def.type).append(')'); } sb.append(']'); return sb.toString(); } int findFirstIdx(String name) { int[] indexes = findAllIdx(name); return indexes == null ? -1 : indexes[0]; } int[] findAllIdx(String name) { boolean caseSensitive = false; if (name.length() >= 2 && name.charAt(0) == '"' && name.charAt(name.length() - 1) == '"') { name = name.substring(1, name.length() - 1); caseSensitive = true; } int[] indexes = byName.get(name.toLowerCase()); if (!caseSensitive || indexes == null) return indexes; // First, optimistic and assume all are matching int nbMatch = 0; for (int i = 0; i < indexes.length; i++) if (name.equals(byIdx[indexes[i]].name)) nbMatch++; if (nbMatch == indexes.length) return indexes; int[] result = new int[nbMatch]; int j = 0; for (int i = 0; i < indexes.length; i++) { int idx = indexes[i]; if (name.equals(byIdx[idx].name)) result[j++] = idx; } return result; } int[] getAllIdx(String name) { int[] indexes = findAllIdx(name); if (indexes == null) throw new IllegalArgumentException(name + " is not a column defined in this metadata"); return indexes; } int getFirstIdx(String name) { return getAllIdx(name)[0]; } /** A column definition. */ public static class Definition { private final String keyspace; private final String table; private final String name; private final DataType type; Definition(String keyspace, String table, String name, DataType type) { this.keyspace = keyspace; this.table = table; this.name = name; this.type = type; } /** * The name of the keyspace this column is part of. * * @return the name of the keyspace this column is part of. */ public String getKeyspace() { return keyspace; } /** * Returns the name of the table this column is part of. * * @return the name of the table this column is part of. */ public String getTable() { return table; } /** * Returns the name of the column. * * @return the name of the column. */ public String getName() { return name; } /** * Returns the type of the column. * * @return the type of the column. */ public DataType getType() { return type; } @Override public final int hashCode() { return Arrays.hashCode(new Object[] {keyspace, table, name, type}); } @Override public final boolean equals(Object o) { if (!(o instanceof Definition)) return false; Definition other = (Definition) o; return keyspace.equals(other.keyspace) && table.equals(other.table) && name.equals(other.name) && type.equals(other.type); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy