001package io.ebeaninternal.dbmigration.ddlgeneration.platform; 002 003import io.ebean.annotation.ConstraintMode; 004import io.ebean.config.dbplatform.DatabasePlatform; 005 006/** 007 * Oracle platform specific DDL. 008 */ 009public class OracleDdl extends PlatformDdl { 010 011 public OracleDdl(DatabasePlatform platform) { 012 super(platform); 013 this.dropTableIfExists = "drop table "; 014 this.dropSequenceIfExists = "drop sequence "; 015 this.dropConstraintIfExists = "drop constraint"; 016 this.dropIndexIfExists = "drop index "; 017 this.dropTableCascade = " cascade constraints purge"; 018 this.addColumn = "add"; 019 this.alterColumn = "modify"; 020 this.columnSetNotnull = "not null"; 021 this.columnSetNull = "null"; 022 this.columnSetDefault = "default"; 023 this.columnDropDefault = "default null"; // dropping default is not supported. See: 024 // https://stackoverflow.com/questions/8481532/how-do-i-remove-the-default-value-from-a-column-in-oracle 025 this.identitySuffix = " generated by default as identity"; 026 } 027 028 @Override 029 public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns, String[] nullableColumns) { 030 if (nullableColumns == null || nullableColumns.length == 0) { 031 return super.alterTableAddUniqueConstraint(tableName, uqName, columns, nullableColumns); 032 } else { 033 // Hmm: https://stackoverflow.com/questions/11893134/oracle-create-unique-index-but-ignore-nulls 034 return "-- NOT YET IMPLEMENTED: " + super.alterTableAddUniqueConstraint(tableName, uqName, columns, nullableColumns); 035 } 036 } 037 038 @Override 039 public String dropSequence(String sequenceName) { 040 return ignoreError(-2289, super.dropSequence(sequenceName)); 041 } 042 043 @Override 044 public String alterTableDropConstraint(String tableName, String constraintName) { 045 return ignoreError(-2443, super.alterTableDropConstraint(tableName, constraintName)); 046 } 047 048 @Override 049 public String alterTableDropUniqueConstraint(String tableName, String uniqueConstraintName) { 050 return ignoreError(-2443, super.alterTableDropUniqueConstraint(tableName, uniqueConstraintName)); 051 } 052 053 @Override 054 protected void appendForeignKeyOnUpdate(StringBuilder buffer, ConstraintMode mode) { 055 // do nothing, no on update clause for oracle 056 } 057 058 @Override 059 protected void appendForeignKeyMode(StringBuilder buffer, String onMode, ConstraintMode mode) { 060 switch (mode) { 061 case SET_NULL: 062 case CASCADE: 063 super.appendForeignKeyMode(buffer, onMode, mode); 064 default: 065 // do nothing, defaults to RESTRICT effectively 066 } 067 } 068 069 /** 070 * Modify and return the column definition for autoincrement or identity definition. 071 */ 072 @Override 073 public String asIdentityColumn(String columnDefn, DdlIdentity identity) { 074 return asIdentityStandardOptions(columnDefn, identity); 075 } 076 077 /** 078 * generates anonymous pl/sql block that catches expected error so that we can 079 * effectively do a 'drop if exists' 080 */ 081 private String ignoreError(int errorNr, String statement) { 082 StringBuilder sb = new StringBuilder(); 083 sb.append("delimiter $$\n") 084 .append("declare\n") 085 .append(" expected_error exception;\n") 086 .append(" pragma exception_init(expected_error, ").append(errorNr).append(");\n") 087 .append("begin\n") 088 .append(" execute immediate '").append(statement).append("';\n") 089 .append("exception\n") 090 .append(" when expected_error then null;\n") 091 .append("end;\n$$"); 092 return sb.toString(); 093 } 094}