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

com.google.cloud.spanner.KeyRange Maven / Gradle / Ivy

There is a newer version: 6.81.1
Show newest version
/*
 * Copyright 2017 Google LLC
 *
 * 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.google.cloud.spanner;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import java.io.Serializable;
import java.util.Objects;

/**
 * Represents a range of rows in a table or index.
 *
 * 

A range has a start key and an end key. These keys can be open or closed, indicating if the * range includes rows with that key. * *

For example, consider the following table definition: * *

 *     CREATE TABLE UserEvents (
 *       UserName STRING(MAX),
 *       EventDate STRING(10),
 *     ) PRIMARY KEY(UserName, EventDate);
 * 
* * The following keys name rows in this table: * *
    *
  • {@code Key.of("Bob", "2014-09-23")} *
  • {@code Key.of("Alfred", "2015-06-12")} *
* * Since the {@code UserEvents} table's {@code PRIMARY KEY} clause names two columns, each {@code * UserEvents} key has two elements; the first is the {@code UserName}, and the second is the {@code * EventDate}. * *

Key ranges with multiple components are interpreted lexicographically by component using the * table or index key's declared sort order. For example, the following range returns all events for * user "Bob" that occurred in the year 2015: * *

 *     KeyRange.closedClosed(
 *         Key.of("Bob", "2015-01-01"),
 *         Key.of("Bob", "2015-12-31"))
 * 
* * Start and end keys can omit trailing key components. This affects the inclusion and exclusion of * rows that exactly match the provided key components: if the key is closed, then rows that exactly * match the provided components are included; if the key is open, then rows that exactly match are * not included. * *

For example, the following range includes all events for "Bob" that occurred during and after * the year 2000: * *

 *     KeyRange.closedClosed(
 *         Key.of("Bob", "2000-01-01"),
 *         Key.of("Bob"))
 * 
* * The next example retrieves all events for "Bob": * *
 *     KeyRange.prefix(Key.of("Bob"))
 * 
* * To retrieve events before the year 2000: * *
 *     KeyRange.closedOpen(
 *         Key.of("Bob"),
 *         Key.of("Bob", "2000-01-01"))
 * 
* * The following range includes all rows in the table: * *
 *     KeyRange.all()
 * 
* * This range returns all users whose {@code UserName} begins with any character from A to C: * *
 *     KeyRange.closedOpen(Key.of("A"), Key.of("D"))
 * 
* * This range returns all users whose {@code UserName} begins with B: * *
 *     KeyRange.closedOpen(Key.of("B"), Key.of("C"))
 * 
* * Key ranges honor column sort order. For example, suppose a table is defined as follows: * *
 *     CREATE TABLE DescendingSortedTable {
 *       Key INT64,
 *       ...
 *     ) PRIMARY KEY(Key DESC);
 * 
* * The following range retrieves all rows with key values between 1 and 100 inclusive: * *
 *     KeyRange.closedClosed(Key.of(100), Key.of(1))
 * 
* * Note that 100 is passed as the start, and 1 is passed as the end, because {@code Key} is a * descending column in the schema. * *

{@code KeyRange} instances are immutable. */ public final class KeyRange implements Serializable { private static final long serialVersionUID = 100894273141111331L; /** Defines whether a range includes or excludes its endpoint keys. */ public enum Endpoint { /** Ranges include the endpoint key. */ CLOSED, /** Ranges exclude the endpoint key. */ OPEN } private final Key start; private final Endpoint startType; private final Key end; private final Endpoint endType; private KeyRange(Key start, Endpoint startType, Key end, Endpoint endType) { this.start = start; this.startType = startType; this.end = end; this.endType = endType; } /** Returns a key range from {@code start} inclusive to {@code end} exclusive. */ public static KeyRange closedOpen(Key start, Key end) { return new KeyRange(checkNotNull(start), Endpoint.CLOSED, checkNotNull(end), Endpoint.OPEN); } /** Returns a key range from {@code start} inclusive to {@code end} inclusive. */ public static KeyRange closedClosed(Key start, Key end) { return new KeyRange(checkNotNull(start), Endpoint.CLOSED, checkNotNull(end), Endpoint.CLOSED); } /** Returns a key range from {@code start} exclusive to {@code end} exclusive. */ public static KeyRange openOpen(Key start, Key end) { return new KeyRange(checkNotNull(start), Endpoint.OPEN, checkNotNull(end), Endpoint.OPEN); } /** Returns a key range from {@code start} exclusive to {@code end} inclusive. */ public static KeyRange openClosed(Key start, Key end) { return new KeyRange(checkNotNull(start), Endpoint.OPEN, checkNotNull(end), Endpoint.CLOSED); } /** * Returns a key range that covers all keys where the first {@code prefix.size()} components match * {@code prefix} exactly. */ public static KeyRange prefix(Key prefix) { return closedClosed(prefix, prefix); } /** Returns a new builder for constructing a range. */ public static Builder newBuilder() { return new Builder(); } /** Builder for {@link KeyRange} instances. */ public static class Builder { private Key start; private Endpoint startType = Endpoint.CLOSED; private Key end; private Endpoint endType = Endpoint.OPEN; private Builder() {} private Builder(KeyRange r) { start = r.start; startType = r.startType; end = r.end; endType = r.endType; } /** Sets the start key of the range. This must be set before {@link #build()} is called. */ public Builder setStart(Key key) { start = checkNotNull(key); return this; } /** * Sets whether the start key is inclusive ({@code CLOSED}) or exclusive ({@code OPEN}). The * default is {@code CLOSED}. */ public Builder setStartType(Endpoint type) { startType = checkNotNull(type); return this; } /** Sets the end key of the range. This must be set before {@link #build()} is called. */ public Builder setEnd(Key key) { end = checkNotNull(key); return this; } /** * Sets whether the end key is inclusive ({@code CLOSED}) or exclusive ({@code OPEN}). The * default is {@code OPEN}. */ public Builder setEndType(Endpoint type) { endType = checkNotNull(type); return this; } public KeyRange build() { checkState(start != null, "Missing required call to start(Key)"); checkState(end != null, "Missing required call to end(Key)"); return new KeyRange(start, startType, end, endType); } } /** Returns the start key of the range. */ public Key getStart() { return start; } /** Indicates whether the start key is inclusive ({@code CLOSED}) or exclusive ({@code OPEN}). */ public Endpoint getStartType() { return startType; } /** Returns the end key of the range. */ public Key getEnd() { return end; } /** Indicates whether the end key is inclusive ({@code CLOSED}) or exclusive ({@code OPEN}). */ public Endpoint geEndType() { return endType; } /** Returns a builder initialized with the value of this range. */ public Builder toBuilder() { return new Builder(this); } void toString(StringBuilder b) { b.append(startType == Endpoint.CLOSED ? '[' : '('); start.toString(b); b.append(','); end.toString(b); b.append(endType == Endpoint.CLOSED ? ']' : ')'); } @Override public String toString() { StringBuilder b = new StringBuilder(); toString(b); return b.toString(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } KeyRange that = (KeyRange) o; return startType == that.startType && endType == that.endType && start.equals(that.start) && end.equals(that.end); } @Override public int hashCode() { return Objects.hash(start, startType, end, endType); } com.google.spanner.v1.KeyRange toProto() { com.google.spanner.v1.KeyRange.Builder builder = com.google.spanner.v1.KeyRange.newBuilder(); if (startType == Endpoint.CLOSED) { builder.setStartClosed(start.toProto()); } else { builder.setStartOpen(start.toProto()); } if (endType == Endpoint.CLOSED) { builder.setEndClosed(end.toProto()); } else { builder.setEndOpen(end.toProto()); } return builder.build(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy