1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.healthconnect.storage.request; 18 19 import android.annotation.NonNull; 20 import android.util.Pair; 21 import android.util.Slog; 22 23 import java.util.HashMap; 24 import java.util.List; 25 import java.util.Map; 26 27 /** 28 * Creates a alter table request and alter statements for it. 29 * 30 * @hide 31 */ 32 public final class AlterTableRequest { 33 public static final String TAG = "HealthConnectAlter"; 34 private static final String ALTER_TABLE_COMMAND = "ALTER TABLE "; 35 private static final String ADD_COLUMN_COMMAND = " ADD COLUMN "; 36 private final String mTableName; 37 private final List<Pair<String, String>> mColumnInfo; 38 39 private final Map<String, Pair<String, String>> mForeignKeyConstraints = new HashMap<>(); 40 AlterTableRequest(String tableName, List<Pair<String, String>> columnInfo)41 public AlterTableRequest(String tableName, List<Pair<String, String>> columnInfo) { 42 mTableName = tableName; 43 mColumnInfo = columnInfo; 44 } 45 46 /** 47 * Adds a foreign key constraint between one column and another. Deletion behavior is to set 48 * dangling references to null. 49 */ 50 @NonNull addForeignKeyConstraint( String column, String referencedTable, String referencedColumn)51 public AlterTableRequest addForeignKeyConstraint( 52 String column, String referencedTable, String referencedColumn) { 53 mForeignKeyConstraints.put(column, new Pair<>(referencedTable, referencedColumn)); 54 return this; 55 } 56 57 /** Returns command for alter table request to add new columns */ getAlterTableAddColumnsCommand()58 public String getAlterTableAddColumnsCommand() { 59 final StringBuilder builder = new StringBuilder(ALTER_TABLE_COMMAND); 60 builder.append(mTableName); 61 for (int i = 0; i < mColumnInfo.size(); i++) { 62 String columnName = mColumnInfo.get(i).first; 63 String columnType = mColumnInfo.get(i).second; 64 builder.append(ADD_COLUMN_COMMAND).append(columnName).append(" ").append(columnType); 65 if (mForeignKeyConstraints.containsKey(columnName)) { 66 builder.append(" "); 67 builder.append("REFERENCES "); 68 builder.append(mForeignKeyConstraints.get(columnName).first); 69 builder.append("("); 70 builder.append(mForeignKeyConstraints.get(columnName).second); 71 builder.append(")"); 72 builder.append(" ON DELETE SET NULL"); 73 } 74 builder.append(", "); 75 } 76 builder.setLength(builder.length() - 2); // Remove the last 2 char i.e. ", " 77 Slog.d(TAG, "Alter table: " + builder); 78 79 return builder.toString(); 80 } 81 getAlterTableCommandToAddGeneratedColumn( String tableName, CreateTableRequest.GeneratedColumnInfo generatedColumnInfo)82 public static String getAlterTableCommandToAddGeneratedColumn( 83 String tableName, CreateTableRequest.GeneratedColumnInfo generatedColumnInfo) { 84 String request = 85 ALTER_TABLE_COMMAND 86 + tableName 87 + ADD_COLUMN_COMMAND 88 + generatedColumnInfo.getColumnName() 89 + " " 90 + generatedColumnInfo.getColumnType() 91 + " GENERATED ALWAYS AS (" 92 + generatedColumnInfo.getExpression() 93 + ")"; 94 95 Slog.d(TAG, "Alter table generated: " + request); 96 return request; 97 } 98 } 99