001package io.ebean.config.dbplatform;
002
003/**
004 * Represents a DB type with name, length, precision, and scale.
005 * <p>
006 * The length is for VARCHAR types and precision/scale for DECIMAL types.
007 * </p>
008 */
009public class DbPlatformType implements ExtraDbTypes {
010
011  /**
012   * The data type name (VARCHAR, INTEGER ...)
013   */
014  private final String name;
015
016  /**
017   * The default length or precision.
018   */
019  private final int defaultLength;
020
021  /**
022   * The default scale (decimal).
023   */
024  private final int defaultScale;
025
026  /**
027   * Set to true if the type should never have a length or scale.
028   */
029  private final boolean canHaveLength;
030
031  /**
032   * Parse a type definition into a DbPlatformType.
033   * <p>
034   * e.g. "decimal(18,6)"
035   * e.g. "text"
036   * </p>
037   */
038  public static DbPlatformType parse(String columnDefinition) {
039    return DbPlatformTypeParser.parse(columnDefinition);
040  }
041
042  /**
043   * Construct with no length or scale.
044   */
045  public DbPlatformType(String name) {
046    this(name, 0, 0);
047  }
048
049  /**
050   * Construct with a given length.
051   */
052  public DbPlatformType(String name, int defaultLength) {
053    this(name, defaultLength, 0);
054  }
055
056  /**
057   * Construct for Decimal with precision and scale.
058   */
059  public DbPlatformType(String name, int defaultPrecision, int defaultScale) {
060    this.name = name;
061    this.defaultLength = defaultPrecision;
062    this.defaultScale = defaultScale;
063    this.canHaveLength = true;
064  }
065
066  /**
067   * Use with canHaveLength=false for types that should never have a length.
068   *
069   * @param name          the type name
070   * @param canHaveLength set this to false for type that should never have a length
071   */
072  public DbPlatformType(String name, boolean canHaveLength) {
073    this.name = name;
074    this.defaultLength = 0;
075    this.defaultScale = 0;
076    this.canHaveLength = canHaveLength;
077  }
078
079  /**
080   * Return the type name.
081   */
082  public String getName() {
083    return name;
084  }
085
086  /**
087   * Return the default length/precision.
088   */
089  public int getDefaultLength() {
090    return defaultLength;
091  }
092
093  /**
094   * Return the default scale.
095   */
096  public int getDefaultScale() {
097    return defaultScale;
098  }
099
100  /**
101   * Return the type for a specific property that incorporates the name, length,
102   * precision and scale.
103   * <p>
104   * The deployLength and deployScale are for the property we are rendering the
105   * DB type for.
106   * </p>
107   *
108   * @param deployLength the length or precision defined by deployment on a specific
109   *                     property.
110   * @param deployScale  the scale defined by deployment on a specific property.
111   */
112  public String renderType(int deployLength, int deployScale) {
113    return renderType(deployLength, deployScale, true);
114  }
115
116  /**
117   * Render the type defining strict mode.
118   * <p>
119   * If strict mode if OFF then this will render with a scale value even if
120   * that is not strictly supported. The reason for supporting this is to enable
121   * use to use types like jsonb(200) as a "logical" type that maps to JSONB for
122   * Postgres and VARCHAR(200) for other databases.
123   * </p>
124   */
125  public String renderType(int deployLength, int deployScale, boolean strict) {
126
127    StringBuilder sb = new StringBuilder();
128    sb.append(name);
129    if (canHaveLength || !strict) {
130      renderLengthScale(deployLength, deployScale, sb);
131    }
132
133    return sb.toString();
134  }
135
136  /**
137   * Render the length and scale part of the column definition.
138   */
139  protected void renderLengthScale(int deployLength, int deployScale, StringBuilder sb) {
140    // see if there is a precision/scale to add (or not)
141    int len = deployLength != 0 ? deployLength : defaultLength;
142    if (len == Integer.MAX_VALUE) {
143      sb.append("(max)"); // TODO: this is sqlserver specific
144    } else if (len > 0) {
145      sb.append("(");
146      sb.append(len);
147      int scale = deployScale != 0 ? deployScale : defaultScale;
148      if (scale > 0) {
149        sb.append(",");
150        sb.append(scale);
151      }
152      sb.append(")");
153    }
154  }
155
156  /**
157   * Create a copy of the type with a new default length.
158   */
159  public DbPlatformType withLength(int defaultLength) {
160    return new DbPlatformType(name, defaultLength);
161  }
162}