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

oracle.kv.impl.api.table.TableEvolver Maven / Gradle / Ivy

/*-
 * Copyright (C) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle NoSQL
 * Database made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/nosqldb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle NoSQL Database for a copy of the license and
 * additional information.
 */

package oracle.kv.impl.api.table;

import oracle.kv.table.Table;

/**
 * TableEvolver is a class used to evolve existing tables.  It has accessors
 * and modifiers for valid evolution operations and double checks them against
 * the current state of the class.
 * 

* The general usage pattern is: * TableEvolver evolver = TableEvolver.createTableEvolver(Table); * ...do things... * Table newTable = evolver.evolveTable(); * The resulting table can be passed to the TableMetadata.evolveTable() * method. *

* Schema evolution on tables allows the following transformations: *

    *
  • Add a non-key field to a table *
  • Remove a non-key field from a table (the system creates Avro defaults * for all fields which makes this possible) *
* These operations *should* be added, but aren't yet allowed: *
    *
  • Change the nullable and default value of a field, probably restricted * to non-key (primary or index) fields. *
  • Change the description of a field. *
  • Direct field rename (implemented as remove, re-create with same type). *
  • Add values to enum (at the end) *
  • Change the table description. *
* These operations are not possible: *
    *
  • Modify/remove/add a field that is part of the primary key *
  • Remove an indexed field or modify it in an incompatible manner. *
  • Change the type or name of any field (rename maybe allowed, see above) *
  • NOTE: at some point it may be useful to allow some changes to * primary key fields, such as description, default value. Primary * key fields cannot be nullable. *
*/ public class TableEvolver extends TableBuilderBase { private final TableImpl table; private final int evolvedVersion; private String description; private TableEvolver(TableImpl table) { super(table.getFieldMap().clone()); this.table = table; ttl = table.getDefaultTTL(); description = table.getDescription(); evolvedVersion = table.getTableVersion(); if (evolvedVersion != table.numTableVersions()) { throw new IllegalArgumentException ("Table evolution must be performed on the latest version"); } } public static TableEvolver createTableEvolver(Table table) { return new TableEvolver(((TableImpl)table).clone()); } @Override public String getBuilderType() { return "Evolver"; } /** * Accessors */ public TableImpl getTable() { return table; } public int getTableVersion() { return evolvedVersion; } public RecordDefImpl getRecord(String fieldName) { return (RecordDefImpl) getField(fieldName); } public MapDefImpl getMap(String fieldName) { return (MapDefImpl) getField(fieldName); } public ArrayDefImpl getArray(String fieldName) { return (ArrayDefImpl) getField(fieldName); } public RecordEvolver createRecordEvolver(RecordDefImpl record) { if (record == null) { throw new IllegalArgumentException ("Null record passed to createRecordEvolver"); } return new RecordEvolver(record); } @Override public TableBuilderBase setDescription(String description) { this.description = description; return this; } /** * Do the evolution. Reset the fields member to avoid accidental * updates to the live version of the table just evolved. This way * this instance can be reused, which is helpful in testing. */ public TableImpl evolveTable() { if (hasSetIdentity) { table.evolve(fields, ttl, description, getIdentityColumnInfo(), sequenceDef); } else { if (table.hasIdentityColumn()) { String idColName = table.getFieldMap().getFieldName( table.getIdentityColumn()); if (!fields.exists(idColName)) { /* column with IDENTITY was dropped */ table.evolve(fields, ttl, description, null, null); } else { /* column with IDENTITY still exists but index might have changed */ table.evolve(fields, ttl, description, new IdentityColumnInfo(fields.getFieldPos(idColName), table.getIdentityColumnInfo().isIdentityGeneratedAlways(), table.getIdentityColumnInfo().isIdentityOnNull()), null); } } else { table.evolve(fields, ttl, description, null, null); } } /* * Reset the fields member to avoid accidental updates to the * live version of the table just evolved. */ fields = fields.clone(); return table; } /** * Show the current state of the table. */ public String toJsonString(boolean pretty) { TableImpl t = table.clone(); t.evolve(fields, ttl, description, getIdentityColumnInfo(), sequenceDef); return t.toJsonString(pretty); } @Override void validateFieldAddition(final String fieldName, final String pathName, final FieldMapEntry field) { super.validateFieldAddition(fieldName, pathName, field); table.validateFieldAddition(pathName, field); } /** * Fields cannot be removed if they are part of the primary * key or participate in an index. */ @Override void validateFieldRemoval(TablePath tablePath) { if (table.isKeyComponent(tablePath.getPathName())) { throw new IllegalArgumentException( "Cannot remove a primary key field: " + tablePath.getPathName()); } if (table.isIndexKeyComponent(tablePath)) { throw new IllegalArgumentException( "Cannot remove an index key field: " + tablePath.getPathName()); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy