Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IGNITE-20620 Add index availability command to catalog #2680

Merged
merged 6 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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.ignite.internal.catalog;

import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;

/**
* This exception is thrown when an attempt is made to make an index available a second time
* ({@link CatalogIndexDescriptor#writeOnly() read-write} state).
*/
public class IndexAlreadyAvailableValidationException extends CatalogValidationException {
private static final long serialVersionUID = 5482919822886169473L;

/**
* Constructor.
*
* @param message Error message.
*/
public IndexAlreadyAvailableValidationException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
package org.apache.ignite.internal.catalog;

/**
* This exception is thrown when index that going to be deleted not found in the schema.
* This exception is thrown when an index is not found in the schema.
*
* <p>This exception is used to properly handle IF EXISTS flag in ddl command handler.
* <p>Example: This exception is used to properly handle IF EXISTS flag in ddl command handler.</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need that trailing </p> ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not? =)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the code that I recall we never use it. But this is not too important

*/
public class IndexNotFoundValidationException extends CatalogValidationException {
public IndexNotFoundValidationException(String message) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@
import java.util.Set;
import org.apache.ignite.internal.catalog.Catalog;
import org.apache.ignite.internal.catalog.CatalogValidationException;
import org.apache.ignite.internal.catalog.IndexNotFoundValidationException;
import org.apache.ignite.internal.catalog.TableNotFoundValidationException;
import org.apache.ignite.internal.catalog.descriptors.CatalogDataStorageDescriptor;
import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor;
import org.apache.ignite.internal.catalog.descriptors.CatalogTableColumnDescriptor;
import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor;
Expand Down Expand Up @@ -363,4 +365,22 @@ static CatalogZoneDescriptor zoneOrThrow(Catalog catalog, String name) throws Ca
public static String pkIndexName(String tableName) {
return tableName + "_PK";
}

/**
* Returns index with given name.
*
* @param schema Schema to look up index in.
* @param name Name of the index of interest.
* @return Table with given name.
* @throws IndexNotFoundValidationException If index with given name is not exists.
*/
static CatalogIndexDescriptor indexOrThrow(CatalogSchemaDescriptor schema, String name) throws IndexNotFoundValidationException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about moving this method to CatalogSchemaDescriptor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t think it’s worth it, this method is only used by teams, but CatalogSchemaDescriptor can be used by anyone.

CatalogIndexDescriptor index = schema.index(name);

if (index == null) {
throw new IndexNotFoundValidationException(format("Index with name '{}.{}' not found", schema.name(), name));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this method can be used not only in the context where we validate something, but it throws a validation exception. Can the exception type be generalized? Or the method renamed (or at least documented) that it's just for validation phase?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this class there were methods schemaOrThrow and tableOrThrow, I don’t think that at the moment there is a need to spoil the consistency in the naming, plus the semantics and documentation of the method indicate that it will be a validation exception that will be thrown.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the whole CatalogUtils is about validation stage, the class itself can be renamed. Or these methods might be extracted to a class that's about validation stage logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth fixing this outside of the current task.

}

return index;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@

package org.apache.ignite.internal.catalog.commands;

import static org.apache.ignite.internal.catalog.commands.CatalogUtils.indexOrThrow;
import static org.apache.ignite.internal.catalog.commands.CatalogUtils.schemaOrThrow;
import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;

import java.util.List;
import org.apache.ignite.internal.catalog.Catalog;
import org.apache.ignite.internal.catalog.CatalogCommand;
import org.apache.ignite.internal.catalog.CatalogValidationException;
import org.apache.ignite.internal.catalog.IndexNotFoundValidationException;
import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor;
import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor;
Expand Down Expand Up @@ -55,12 +55,7 @@ private DropIndexCommand(String schemaName, String indexName) throws CatalogVali
public List<UpdateEntry> get(Catalog catalog) {
CatalogSchemaDescriptor schema = schemaOrThrow(catalog, schemaName);

CatalogIndexDescriptor index = schema.index(indexName);

if (index == null) {
throw new IndexNotFoundValidationException(
format("Index with name '{}.{}' not found", schemaName, indexName));
}
CatalogIndexDescriptor index = indexOrThrow(schema, indexName);

CatalogTableDescriptor table = catalog.table(index.tableId());

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* 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.ignite.internal.catalog.commands;

import static org.apache.ignite.internal.catalog.commands.CatalogUtils.indexOrThrow;
import static org.apache.ignite.internal.catalog.commands.CatalogUtils.schemaOrThrow;
import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;

import java.util.List;
import org.apache.ignite.internal.catalog.Catalog;
import org.apache.ignite.internal.catalog.CatalogCommand;
import org.apache.ignite.internal.catalog.CatalogValidationException;
import org.apache.ignite.internal.catalog.IndexAlreadyAvailableValidationException;
import org.apache.ignite.internal.catalog.IndexNotFoundValidationException;
import org.apache.ignite.internal.catalog.descriptors.CatalogHashIndexDescriptor;
import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor;
import org.apache.ignite.internal.catalog.descriptors.CatalogSortedIndexDescriptor;
import org.apache.ignite.internal.catalog.storage.MakeIndexAvailableEntry;
import org.apache.ignite.internal.catalog.storage.UpdateEntry;

/**
* Makes the index available for read-write, switches from the write-only to the read-write state in the catalog.
*
* @see CatalogIndexDescriptor#writeOnly()
* @see IndexNotFoundValidationException
* @see IndexAlreadyAvailableValidationException
*/
public class MakeIndexAvailableCommand extends AbstractIndexCommand {
/** Returns builder to make an index available for read-write. */
public static MakeIndexAvailableCommandBuilder builder() {
return new Builder();
}

/**
* Constructor.
*
* @param schemaName Schema name.
* @param indexName Index name.
* @throws CatalogValidationException If any of the parameters fails validation.
*/
private MakeIndexAvailableCommand(String schemaName, String indexName) throws CatalogValidationException {
super(schemaName, indexName);
}

@Override
public List<UpdateEntry> get(Catalog catalog) {
CatalogSchemaDescriptor schema = schemaOrThrow(catalog, schemaName);

CatalogIndexDescriptor index = indexOrThrow(schema, indexName);

if (!index.writeOnly()) {
throw new IndexAlreadyAvailableValidationException(format("Index is already available '{}.{}'", schemaName, indexName));
}

CatalogIndexDescriptor updatedIndex;

if (index instanceof CatalogHashIndexDescriptor) {
updatedIndex = createReadWriteIndex((CatalogHashIndexDescriptor) index);
} else if (index instanceof CatalogSortedIndexDescriptor) {
updatedIndex = createReadWriteIndex((CatalogSortedIndexDescriptor) index);
} else {
throw new CatalogValidationException(format("Unsupported index type '{}.{}' {}", schemaName, indexName, index));
}

return List.of(new MakeIndexAvailableEntry(schemaName, updatedIndex));
}

private static CatalogIndexDescriptor createReadWriteIndex(CatalogHashIndexDescriptor index) {
return new CatalogHashIndexDescriptor(
index.id(),
index.name(),
index.tableId(),
index.unique(),
index.columns(),
false
);
}

private static CatalogIndexDescriptor createReadWriteIndex(CatalogSortedIndexDescriptor index) {
return new CatalogSortedIndexDescriptor(
index.id(),
index.name(),
index.tableId(),
index.unique(),
index.columns(),
false
);
}

private static class Builder implements MakeIndexAvailableCommandBuilder {
private String schemaName;

private String indexName;

@Override
public Builder schemaName(String schemaName) {
this.schemaName = schemaName;

return this;
}

@Override
public Builder indexName(String indexName) {
this.indexName = indexName;

return this;
}

@Override
public CatalogCommand build() {
return new MakeIndexAvailableCommand(schemaName, indexName);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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.ignite.internal.catalog.commands;

/** Builder for {@link MakeIndexAvailableCommand}. */
public interface MakeIndexAvailableCommandBuilder extends AbstractIndexCommandBuilder<MakeIndexAvailableCommandBuilder> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@
import java.util.Objects;
import org.apache.ignite.internal.tostring.S;

/**
* Hash index descriptor.
*/
/** Hash index descriptor. */
public class CatalogHashIndexDescriptor extends CatalogIndexDescriptor {
private static final long serialVersionUID = -6784028115063219759L;

private final List<String> columns;

/**
* Constructs a hash index descriptor.
* Constructs a hash index descriptor in write-only state.
*
* @param id Id of the index.
* @param name Name of the index.
Expand All @@ -40,7 +38,22 @@ public class CatalogHashIndexDescriptor extends CatalogIndexDescriptor {
* @throws IllegalArgumentException If columns list contains duplicates.
*/
public CatalogHashIndexDescriptor(int id, String name, int tableId, boolean unique, List<String> columns) {
super(id, name, tableId, unique);
this(id, name, tableId, unique, columns, true);
}

/**
* Constructs a hash index descriptor.
*
* @param id Id of the index.
* @param name Name of the index.
* @param tableId Id of the table index belongs to.
* @param unique Unique flag.
* @param columns A list of indexed columns. Must not contains duplicates.
* @param writeOnly State of the index, {@code true} when index is building, {@code false} when the index is built.
* @throws IllegalArgumentException If columns list contains duplicates.
*/
public CatalogHashIndexDescriptor(int id, String name, int tableId, boolean unique, List<String> columns, boolean writeOnly) {
super(id, name, tableId, unique, writeOnly);
tkalkirill marked this conversation as resolved.
Show resolved Hide resolved

this.columns = List.copyOf(Objects.requireNonNull(columns, "columns"));
}
Expand All @@ -50,13 +63,6 @@ public List<String> columns() {
return columns;
}

/** {@inheritDoc} */
@Override
public boolean hasColumn(String columnName) {
return columns.contains(columnName);
}

/** {@inheritDoc} */
@Override
public String toString() {
return S.toString(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@

import org.apache.ignite.internal.tostring.S;

/**
* Index descriptor base class.
*/
/** Index descriptor base class. */
public abstract class CatalogIndexDescriptor extends CatalogObjectDescriptor {
private static final long serialVersionUID = -8045949593661301287L;

Expand All @@ -33,13 +31,14 @@ public abstract class CatalogIndexDescriptor extends CatalogObjectDescriptor {
/** Unique constraint flag. */
private final boolean unique;

/** Write only flag. {@code True} when index is building. */
private boolean writeOnly;
/** Write only flag. {@code True} when the index is being built, {@code false} when it is built. */
private final boolean writeOnly;

CatalogIndexDescriptor(int id, String name, int tableId, boolean unique) {
CatalogIndexDescriptor(int id, String name, int tableId, boolean unique, boolean writeOnly) {
super(id, Type.INDEX, name, INITIAL_CAUSALITY_TOKEN);
this.tableId = tableId;
this.unique = unique;
this.writeOnly = writeOnly;
}

/** Gets table id. */
Expand All @@ -52,19 +51,11 @@ public boolean unique() {
return unique;
}

/** Returns the state of the index, {@code true} when the index is being built, {@code false} when it is built. */
public boolean writeOnly() {
return writeOnly;
}

/**
* Checks if a column with given name is indexed.
*
* @param columnName Column name to check.
* @return {@code true} if index contains the column, {@code false} otherwise.
*/
public abstract boolean hasColumn(String columnName);

/** {@inheritDoc} */
@Override
public String toString() {
return S.toString(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@
import org.apache.ignite.internal.tostring.S;
import org.jetbrains.annotations.Nullable;

/**
* Schema definition contains database schema objects.
*/
/** Schema definition contains database schema objects. */
public class CatalogSchemaDescriptor extends CatalogObjectDescriptor {
private static final long serialVersionUID = -233494425779955410L;

Expand Down Expand Up @@ -103,7 +101,6 @@ private void rebuildMaps() {
.collect(Collectors.toUnmodifiableMap(CatalogObjectDescriptor::name, Function.identity()));
}

/** {@inheritDoc} */
@Override
public String toString() {
return S.toString(this);
Expand Down
Loading