001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.ecm.core.storage.sql; 020 021import java.io.Serializable; 022 023import org.nuxeo.ecm.core.schema.types.Field; 024import org.nuxeo.ecm.core.schema.types.SimpleTypeImpl; 025import org.nuxeo.ecm.core.schema.types.Type; 026import org.nuxeo.ecm.core.schema.types.primitives.BinaryType; 027import org.nuxeo.ecm.core.schema.types.primitives.BooleanType; 028import org.nuxeo.ecm.core.schema.types.primitives.DateType; 029import org.nuxeo.ecm.core.schema.types.primitives.DoubleType; 030import org.nuxeo.ecm.core.schema.types.primitives.IntegerType; 031import org.nuxeo.ecm.core.schema.types.primitives.LongType; 032import org.nuxeo.ecm.core.schema.types.primitives.StringType; 033 034/** 035 * The database-level column types, including per-type parameters like length. 036 */ 037public class ColumnType implements Serializable { 038 039 private static final long serialVersionUID = 1L; 040 041 /** Length used internally to flag a string to use CLOB. */ 042 public static final int CLOB_LENGTH = 999999999; 043 044 public static final ColumnType STRING = new ColumnType(ColumnSpec.STRING); 045 046 public static final ColumnType CLOB = new ColumnType(ColumnSpec.STRING, CLOB_LENGTH); 047 048 public static final ColumnType BOOLEAN = new ColumnType(ColumnSpec.BOOLEAN); 049 050 public static final ColumnType LONG = new ColumnType(ColumnSpec.LONG); 051 052 public static final ColumnType DOUBLE = new ColumnType(ColumnSpec.DOUBLE); 053 054 public static final ColumnType TIMESTAMP = new ColumnType(ColumnSpec.TIMESTAMP); 055 056 public static final ColumnType BLOBID = new ColumnType(ColumnSpec.BLOBID); 057 058 public static final ColumnType ARRAY_STRING = new ColumnType(ColumnSpec.ARRAY_STRING, -1, true); 059 060 public static final ColumnType ARRAY_CLOB = new ColumnType(ColumnSpec.ARRAY_STRING, CLOB_LENGTH, true); 061 062 public static final ColumnType ARRAY_BOOLEAN = new ColumnType(ColumnSpec.ARRAY_BOOLEAN, -1, true); 063 064 public static final ColumnType ARRAY_LONG = new ColumnType(ColumnSpec.ARRAY_LONG, -1, true); 065 066 public static final ColumnType ARRAY_DOUBLE = new ColumnType(ColumnSpec.ARRAY_DOUBLE, -1, true); 067 068 public static final ColumnType ARRAY_TIMESTAMP = new ColumnType(ColumnSpec.ARRAY_TIMESTAMP, -1, true); 069 070 public static final ColumnType ARRAY_BLOBID = new ColumnType(ColumnSpec.ARRAY_BLOBID, -1, true); 071 072 public static final ColumnType ARRAY_INTEGER = new ColumnType(ColumnSpec.ARRAY_INTEGER, -1, true); 073 074 public static final ColumnType NODEID = new ColumnType(ColumnSpec.NODEID); 075 076 public static final ColumnType NODEIDFK = new ColumnType(ColumnSpec.NODEIDFK); 077 078 public static final ColumnType NODEIDFKNP = new ColumnType(ColumnSpec.NODEIDFKNP); 079 080 public static final ColumnType NODEIDFKMUL = new ColumnType(ColumnSpec.NODEIDFKMUL); 081 082 public static final ColumnType NODEIDFKNULL = new ColumnType(ColumnSpec.NODEIDFKNULL); 083 084 public static final ColumnType NODEIDPK = new ColumnType(ColumnSpec.NODEIDPK); 085 086 public static final ColumnType NODEVAL = new ColumnType(ColumnSpec.NODEVAL); 087 088 public static final ColumnType NODEARRAY = new ColumnType(ColumnSpec.NODEARRAY, -1, true); 089 090 public static final ColumnType SYSNAME = new ColumnType(ColumnSpec.SYSNAME); 091 092 public static final ColumnType SYSNAMEARRAY = new ColumnType(ColumnSpec.SYSNAMEARRAY, -1, true); 093 094 public static final ColumnType TINYINT = new ColumnType(ColumnSpec.TINYINT); 095 096 public static final ColumnType INTEGER = new ColumnType(ColumnSpec.INTEGER); 097 098 public static final ColumnType AUTOINC = new ColumnType(ColumnSpec.AUTOINC); 099 100 public static final ColumnType FTINDEXED = new ColumnType(ColumnSpec.FTINDEXED); 101 102 public static final ColumnType FTSTORED = new ColumnType(ColumnSpec.FTSTORED); 103 104 public static final ColumnType CLUSTERNODE = new ColumnType(ColumnSpec.CLUSTERNODE); 105 106 public static final ColumnType CLUSTERFRAGS = new ColumnType(ColumnSpec.CLUSTERFRAGS); 107 108 public final ColumnSpec spec; 109 110 public final int length; 111 112 public final boolean array; 113 114 public ColumnType(ColumnSpec spec, int length, boolean array) { 115 this.spec = spec; 116 this.length = length; 117 this.array = array; 118 } 119 120 public ColumnType(ColumnSpec spec, int length) { 121 this(spec, length, false); 122 } 123 124 public ColumnType(ColumnSpec spec) { 125 this(spec, -1); 126 } 127 128 public boolean isUnconstrained() { 129 return length == -1; 130 } 131 132 public boolean isClob() { 133 return length == CLOB_LENGTH; 134 } 135 136 public boolean isArray() { 137 return array; 138 } 139 140 /** 141 * Checks if this column holds a Nuxeo unique id (usually UUID). 142 */ 143 public boolean isId() { 144 return spec.isId(); 145 } 146 147 /** 148 * Wraps a string that needs to be mapped to an id column in prepared statements. 149 * 150 * @since 5.7 151 */ 152 public static class WrappedId implements Serializable { 153 private static final long serialVersionUID = 1L; 154 155 public final String string; 156 157 public WrappedId(String string) { 158 this.string = string; 159 } 160 161 @Override 162 public String toString() { 163 return string; 164 } 165 } 166 167 @Override 168 public String toString() { 169 if (isUnconstrained()) { 170 return spec.toString(); 171 } else if (isClob()) { 172 return isArray() ? "ARRAY_CLOB" : "CLOB"; 173 } else { 174 return spec.toString() + '(' + length + ')'; 175 } 176 } 177 178 /** 179 * Gets the column type from a Nuxeo Schema field, including its constrained length if any. 180 */ 181 public static ColumnType fromField(Field field) { 182 return fromFieldType(field.getType(), field.getMaxLength()); 183 } 184 185 /** 186 * Gets the column type from a Nuxeo Schema field type (unconstrained). 187 */ 188 public static ColumnType fromFieldType(Type type) { 189 return fromFieldType(type, -1); 190 } 191 192 /** 193 * Gets the column type from a Nuxeo Schema field type (unconstrained) with array {@code true} if an array type is 194 * required 195 */ 196 public static ColumnType fromFieldType(Type type, boolean array) { 197 return fromFieldType(type, -1, array); 198 } 199 200 protected static ColumnType fromFieldType(Type type, int maxLength) { 201 return fromFieldType(type, maxLength, false); 202 } 203 204 protected static ColumnType fromFieldType(Type type, int maxLength, boolean array) { 205 if (type instanceof StringType) { 206 if (maxLength == -1) { 207 return array ? ARRAY_STRING : STRING; // unconstrained 208 } else { 209 return new ColumnType(ColumnSpec.STRING, maxLength, array); 210 } 211 } else if (type instanceof BooleanType) { 212 return array ? ARRAY_BOOLEAN : BOOLEAN; 213 } else if (type instanceof LongType) { 214 return array ? ARRAY_LONG : LONG; 215 } else if (type instanceof DoubleType) { 216 return array ? ARRAY_DOUBLE : DOUBLE; 217 } else if (type instanceof DateType) { 218 return array ? ARRAY_TIMESTAMP : TIMESTAMP; 219 } else if (type instanceof BinaryType) { 220 return array ? ARRAY_BLOBID : BLOBID; 221 } else if (type instanceof IntegerType) { 222 return array ? ARRAY_INTEGER : INTEGER; 223 } else if (type instanceof SimpleTypeImpl) { 224 // comes from a constraint 225 return fromFieldType(type.getSuperType(), maxLength); 226 } else { 227 throw new RuntimeException("Invalid primitive type: " + type.getClass().getName()); 228 } 229 } 230 231}