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

io.datarouter.gcp.spanner.ddl.SpannerTableAlterSchemaService Maven / Gradle / Ivy

There is a newer version: 0.0.126
Show newest version
/*
 * Copyright © 2009 HotPads ([email protected])
 *
 * 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 io.datarouter.gcp.spanner.ddl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Singleton;

import com.google.cloud.spanner.ResultSet;

import io.datarouter.model.field.Field;
import io.datarouter.model.field.FieldKey;
import io.datarouter.scanner.Scanner;
import io.datarouter.storage.config.schema.SchemaUpdateOptions;

@Singleton
public class SpannerTableAlterSchemaService{

	@Inject
	private SpannerTableOperationsGenerator tableOperationsGenerator;
	@Inject
	private SchemaUpdateOptions updateOptions;

	public void generateUpdateStatementColumns(
			String tableName,
			List currentColumns,
			List currentPkColumns,
			ResultSet columnResult,
			ResultSet primaryKeyResult,
			SpannerUpdateStatements statements){
		List primaryKeyColumns = extractColumns(primaryKeyResult);
		if(!primaryKeyColumns.equals(currentPkColumns)){
			throw new RuntimeException("Cannot modify primary key columns in spanner tableName=" + tableName);
		}
		List columns = extractColumns(columnResult);
		List colToAdd = columnNameDifferences(currentColumns, columns);
		List colToRemove = columnNameDifferences(columns, currentColumns);
		List colToAlter = columnsToAlter(currentColumns, columns);
		if(!colToAdd.isEmpty()){
			colToAdd.forEach(col -> statements.updateFunction(
					tableOperationsGenerator.addColumns(tableName, col),
					updateOptions::getAddColumns,
					true));
		}
		if(!colToRemove.isEmpty()){
			colToRemove.forEach(col -> statements.updateFunction(
					tableOperationsGenerator.dropColumns(tableName, col),
					updateOptions::getDeleteColumns,
					false));
		}
		if(!colToAlter.isEmpty()){
			colToAlter.forEach(col -> statements.updateFunction(
					tableOperationsGenerator.alterColumns(tableName, col),
					updateOptions::getModifyColumns,
					false));
		}
	}

	public Set getIndexes(ResultSet rs){
		Set result = new HashSet<>();
		while(rs.next()){
			result.add(rs.getString("INDEX_NAME"));
		}
		result.remove("PRIMARY_KEY");
		return result;
	}

	public boolean indexEqual(SpannerIndex index, ResultSet rs){
		List indexKeyColumns = Scanner.of(index.getKeyFields())
				.map(Field::getKey)
				.map(FieldKey::getColumnName)
				.list();
		List nonKeyColumns = Scanner.of(index.getNonKeyFields())
				.map(Field::getKey)
				.map(FieldKey::getColumnName)
				.list();
		boolean runOnce = false;
		while(rs.next()){
			runOnce = true;
			String columnName = rs.getString("COLUMN_NAME");
			if(rs.isNull("ORDINAL_POSITION")){
				if(!nonKeyColumns.contains(columnName)){
					return false;
				}
			}else{
				if(!indexKeyColumns.contains(columnName)){
					return false;
				}
			}
		}
		return runOnce;
	}

	private List extractColumns(ResultSet rs){
		List columns = new ArrayList<>();
		while(rs.next()){
			String columnName = rs.getString("COLUMN_NAME");
			boolean isNullable = rs.getString("IS_NULLABLE").equalsIgnoreCase("YES");
			SpannerColumnType type = SpannerColumnType.fromSchemaString(rs.getString("SPANNER_TYPE"));
			columns.add(new SpannerColumn(columnName, type, isNullable));
		}
		return columns;
	}

	private List columnNameDifferences(List columns1, List columns2){
		Map col1Map = Scanner.of(columns1)
				.toMapSupplied(SpannerColumn::getName, LinkedHashMap::new);
		columns2.forEach(col -> col1Map.remove(col.getName()));
		return new ArrayList<>(col1Map.values());
	}

	private List columnsToAlter(List currentColumns, List existingColumns){
		Map columnMap = Scanner.of(existingColumns)
				.toMapSupplied(SpannerColumn::getName, LinkedHashMap::new);
		return Scanner.of(currentColumns)
				.include(col -> columnMap.containsKey(col.getName()))
				.exclude(col -> columnMap.get(col.getName()).getType() == col.getType())
				.list();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy