001package com.avaje.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 DbType {
010
011  /**
012   * DB native UUID type (H2 and Postgres).
013   */
014  public static final int UUID = 5010;
015
016  /**
017   * Type to map Map content to Postgres HSTORE.
018   */
019  public static final int HSTORE = 5000;
020
021  /**
022   * Type to map JSON content to Clob or Postgres JSON type.
023   */
024  public static final int JSON = 5001;
025
026  /**
027   * Type to map JSON content to Clob or Postgres JSONB type.
028   */
029  public static final int JSONB = 5002;
030
031  /**
032   * Type to map JSON content to VARCHAR.
033   */
034  public static final int JSONVarchar = 5003;
035
036  /**
037   * Type to map JSON content to Clob.
038   */
039  public static final int JSONClob = 5004;
040
041  /**
042   * Type to map JSON content to Blob.
043   */
044  public static final int JSONBlob = 5005;
045
046  /**
047   * The data type name (VARCHAR, INTEGER ...)
048   */
049  private final String name;
050
051  /**
052   * The default length or precision.
053   */
054  private final int defaultLength;
055
056  /**
057   * The default scale (decimal).
058   */
059  private final int defaultScale;
060
061  /**
062   * Set to true if the type should never have a length or scale.
063   */
064  private final boolean canHaveLength;
065
066  /**
067   * Construct with no length or scale.
068   */
069  public DbType(String name) {
070    this(name, 0, 0);
071  }
072
073  /**
074   * Construct with a given length.
075   */
076  public DbType(String name, int defaultLength) {
077    this(name, defaultLength, 0);
078  }
079
080  /**
081   * Construct for Decimal with precision and scale.
082   */
083  public DbType(String name, int defaultPrecision, int defaultScale) {
084    this.name = name;
085    this.defaultLength = defaultPrecision;
086    this.defaultScale = defaultScale;
087    this.canHaveLength = true;
088  }
089
090  /**
091   * Use with canHaveLength=false for types that should never have a length.
092   * 
093   * @param name
094   *          the type name
095   * @param canHaveLength
096   *          set this to false for type that should never have a length
097   */
098  public DbType(String name, boolean canHaveLength) {
099    this.name = name;
100    this.defaultLength = 0;
101    this.defaultScale = 0;
102    this.canHaveLength = canHaveLength;
103  }
104
105  /**
106   * Return the type for a specific property that incorporates the name, length,
107   * precision and scale.
108   * <p>
109   * The deployLength and deployScale are for the property we are rendering the
110   * DB type for.
111   * </p>
112   * 
113   * @param deployLength
114   *          the length or precision defined by deployment on a specific
115   *          property.
116   * @param deployScale
117   *          the scale defined by deployment on a specific property.
118   */
119  public String renderType(int deployLength, int deployScale) {
120    return renderType(deployLength, deployScale, true);
121  }
122
123  /**
124   * Render the type defining strict mode.
125   * <p>
126   * If strict mode if OFF then this will render with a scale value even if
127   * that is not strictly supported. The reason for supporting this is to enable
128   * use to use types like jsonb(200) as a "logical" type that maps to JSONB for
129   * Postgres and VARCHAR(200) for other databases.
130   * </p>
131   */
132  public String renderType(int deployLength, int deployScale, boolean strict) {
133
134    StringBuilder sb = new StringBuilder();
135    sb.append(name);
136
137    if (canHaveLength || !strict) {
138      // see if there is a precision/scale to add (or not)
139      int len = deployLength != 0 ? deployLength : defaultLength;
140      if (len > 0) {
141        sb.append("(");
142        sb.append(len);
143        int scale = deployScale != 0 ? deployScale : defaultScale;
144        if (scale > 0) {
145          sb.append(",");
146          sb.append(scale);
147        }
148        sb.append(")");
149      }
150    }
151
152    return sb.toString();
153  }
154
155  /**
156   * Create a copy of the type with a new default length.
157   */
158  public DbType withLength(int defaultLength) {
159    return new DbType(name, defaultLength);
160  }
161}