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

io.ebeaninternal.dbmigration.ddlgeneration.platform.PostgresDdl Maven / Gradle / Ivy

There is a newer version: 15.8.0
Show newest version
package io.ebeaninternal.dbmigration.ddlgeneration.platform;

import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
import io.ebeaninternal.dbmigration.ddlgeneration.DdlWrite;
import io.ebeaninternal.dbmigration.migration.AlterColumn;
import io.ebeaninternal.dbmigration.migration.Column;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

import static java.util.stream.Collectors.toList;

/**
 * Postgres specific DDL.
 */
public class PostgresDdl extends PlatformDdl {

  private static final Pattern PLAIN_VARCHAR = Pattern.compile("(varchar\\()(\\d+)(\\))");

  private static final String dropIndexConcurrentlyIfExists = "drop index concurrently if exists ";

  public PostgresDdl(DatabasePlatform platform) {
    super(platform);
    this.historyDdl = new PostgresHistoryDdl();
    this.createSchemaSupport = true;
    this.dropTableCascade = " cascade";
    this.columnSetType = "type ";
    this.alterTableIfExists = "if exists ";
    this.createIndexIfNotExists = "if not exists ";
    this.columnSetNull = "drop not null";
    this.addForeignKeySkipCheck = " not valid";
    this.indexConcurrent = "concurrently ";
    this.addColumn = "add column if not exists";
  }

  @Override
  public boolean addPartitionColumnToPrimaryKey() {
    return true;
  }

  @Override
  public String setLockTimeout(int lockTimeoutSeconds) {
    return "set lock_timeout = " + (lockTimeoutSeconds * 1000);
  }

  @Override
  protected String convertArrayType(String logicalArrayType) {
    return NativeDbArray.logicalToNative(logicalArrayType);
  }

  @Override
  public void addTablePartition(DdlBuffer apply, String partitionMode, String partitionColumn) {
    apply.append(" partition by range (").append(partitionColumn).append(")");
  }

  @Override
  public void addDefaultTablePartition(DdlBuffer apply, String tableName) {
    apply.append("create table ").append(tableName).append("_default partition of ").append(tableName).append(" default");
  }

  @Override
  public String dropIndex(String indexName, String tableName, boolean concurrent) {
    return (concurrent ? dropIndexConcurrentlyIfExists : dropIndexIfExists) + maxConstraintName(indexName);
  }

  /**
   * Modify and return the column definition for autoincrement or identity definition.
   */
  @Override
  public String asIdentityColumn(String columnDefn, DdlIdentity identity) {
    return asIdentityStandardOptions(columnDefn, identity);
  }

  @Override
  protected void alterColumnType(DdlWrite writer, AlterColumn alter) {
    String type = convert(alter.getType());
    var alterTable = alterTable(writer, alter.getTableName())
      .append(alterColumn, alter.getColumnName())
      .append(columnSetType).append(type);
    if (useCast(type, alter.getCurrentType())) {
      alterTable.append(" using ").append(alter.getColumnName()).append("::").append(type);
    }
  }

  static boolean useCast(String newType, String currentType) {
    return currentType == null || !isPlainVarchar(newType) || !isPlainVarchar(currentType);
  }

  static boolean isPlainVarchar(String type) {
    return PLAIN_VARCHAR.matcher(type).matches();
  }

  @Override
  protected List sortColumns(List columns) {
    List sorting = new ArrayList<>(columns.size());
    for (int i = 0, end = columns.size(); i < end; i++) {
      Column column = columns.get(i);
      sorting.add(new DDLColumnSort(column, ddlColumnOrdering(i, column)));
    }
    Collections.sort(sorting);
    return sorting.stream().map(it -> it.column).collect(toList());
  }

  private int ddlColumnOrdering(int i, Column column) {
    String type = column.getType().toLowerCase();
    if (type.startsWith("decimal")) {
      return i + 1_000;
    }
    if (isVariableLength(type) || isLob(type)) {
      return i + 10_000;
    }
    return i;
  }

  private boolean isLob(String type) {
    return type.startsWith("clob") || type.startsWith("longvarchar") || type.startsWith("blob") || type.startsWith("longvarbinary");
  }

  private boolean isVariableLength(String type) {
    return type.startsWith("varchar") || type.startsWith("varbinary") || type.startsWith("json");
  }

  static final class DDLColumnSort implements Comparable {

    private final Column column;
    private final int ordering;

    DDLColumnSort(Column column, int ordering) {
      this.column = column;
      this.ordering = ordering;
    }

    @Override
    public int compareTo(DDLColumnSort o) {
      return Integer.compare(ordering, o.ordering);
    }
  }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy