1 56 package org.objectstyle.cayenne.dba.postgres; 57 58 import java.sql.PreparedStatement ; 59 import java.sql.SQLException ; 60 import java.sql.Types ; 61 import java.util.Iterator ; 62 63 import org.objectstyle.cayenne.CayenneRuntimeException; 64 import org.objectstyle.cayenne.access.DataNode; 65 import org.objectstyle.cayenne.access.trans.QualifierTranslator; 66 import org.objectstyle.cayenne.access.trans.QueryAssembler; 67 import org.objectstyle.cayenne.access.types.ByteArrayType; 68 import org.objectstyle.cayenne.access.types.CharType; 69 import org.objectstyle.cayenne.access.types.ExtendedTypeMap; 70 import org.objectstyle.cayenne.dba.JdbcAdapter; 71 import org.objectstyle.cayenne.dba.PkGenerator; 72 import org.objectstyle.cayenne.dba.TypesMapping; 73 import org.objectstyle.cayenne.map.DbAttribute; 74 import org.objectstyle.cayenne.map.DbEntity; 75 import org.objectstyle.cayenne.map.DerivedDbEntity; 76 import org.objectstyle.cayenne.query.Query; 77 import org.objectstyle.cayenne.query.SQLAction; 78 79 99 public class PostgresAdapter extends JdbcAdapter { 100 101 106 public SQLAction getAction(Query query, DataNode node) { 107 return query 108 .createSQLAction(new PostgresActionBuilder(this, node.getEntityResolver())); 109 } 110 111 115 protected void configureExtendedTypes(ExtendedTypeMap map) { 116 super.configureExtendedTypes(map); 117 118 map.registerType(new CharType(true, false)); 120 121 map.registerType(new PostgresByteArrayType(true, false)); 123 } 124 125 public DbAttribute buildAttribute( 126 String name, 127 String typeName, 128 int type, 129 int size, 130 int precision, 131 boolean allowNulls) { 132 133 if ("bytea".equalsIgnoreCase(typeName)) { 137 type = Types.LONGVARBINARY; 138 } 139 else if ("text".equalsIgnoreCase(typeName)) { 141 type = Types.CLOB; 142 } 143 144 return super.buildAttribute(name, typeName, type, size, precision, allowNulls); 145 } 146 147 154 public String createTable(DbEntity ent) { 155 156 if (ent instanceof DerivedDbEntity) { 159 throw new CayenneRuntimeException("Can't create table for derived DbEntity '" 160 + ent.getName() 161 + "'."); 162 } 163 164 StringBuffer buf = new StringBuffer (); 165 buf.append("CREATE TABLE ").append(ent.getFullyQualifiedName()).append(" ("); 166 167 Iterator it = ent.getAttributes().iterator(); 169 boolean first = true; 170 while (it.hasNext()) { 171 if (first) { 172 first = false; 173 } 174 else { 175 buf.append(", "); 176 } 177 178 DbAttribute at = (DbAttribute) it.next(); 179 180 if (at.getType() == TypesMapping.NOT_DEFINED) { 182 throw new CayenneRuntimeException("Undefined type for attribute '" 183 + ent.getFullyQualifiedName() 184 + "." 185 + at.getName() 186 + "'."); 187 } 188 189 String [] types = externalTypesForJdbcType(at.getType()); 190 if (types == null || types.length == 0) { 191 throw new CayenneRuntimeException("Undefined type for attribute '" 192 + ent.getFullyQualifiedName() 193 + "." 194 + at.getName() 195 + "': " 196 + at.getType()); 197 } 198 199 String type = types[0]; 200 buf.append(at.getName()).append(' ').append(type); 201 202 if (typeSupportsLength(at.getType())) { 204 int len = at.getMaxLength(); 205 int prec = TypesMapping.isDecimal(at.getType()) ? at.getPrecision() : -1; 206 207 if (prec > len) { 209 prec = -1; 210 } 211 212 if (len > 0) { 213 buf.append('(').append(len); 214 215 if (prec >= 0) { 216 buf.append(", ").append(prec); 217 } 218 219 buf.append(')'); 220 } 221 } 222 223 if (at.isMandatory()) { 224 buf.append(" NOT NULL"); 225 } 226 else { 227 buf.append(" NULL"); 228 } 229 } 230 231 Iterator pkit = ent.getPrimaryKey().iterator(); 233 if (pkit.hasNext()) { 234 if (first) 235 first = false; 236 else 237 buf.append(", "); 238 239 buf.append("PRIMARY KEY ("); 240 boolean firstPk = true; 241 while (pkit.hasNext()) { 242 if (firstPk) 243 firstPk = false; 244 else 245 buf.append(", "); 246 247 DbAttribute at = (DbAttribute) pkit.next(); 248 buf.append(at.getName()); 249 } 250 buf.append(')'); 251 } 252 buf.append(')'); 253 return buf.toString(); 254 } 255 256 private boolean typeSupportsLength(int type) { 257 String [] externalTypes = externalTypesForJdbcType(type); 259 if (externalTypes != null && externalTypes.length > 0) { 260 for (int i = 0; i < externalTypes.length; i++) { 261 if ("bytea".equalsIgnoreCase(externalTypes[i])) { 262 return false; 263 } 264 } 265 } 266 267 return TypesMapping.supportsLength(type); 268 } 269 270 275 public String dropTable(DbEntity ent) { 276 return super.dropTable(ent) + " CASCADE"; 277 } 278 279 282 public QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler) { 283 return new PostgresQualifierTranslator(queryAssembler); 284 } 285 286 289 protected PkGenerator createPkGenerator() { 290 return new PostgresPkGenerator(); 291 } 292 293 300 class PostgresByteArrayType extends ByteArrayType { 301 302 public PostgresByteArrayType(boolean trimmingBytes, boolean usingBlobs) { 303 super(trimmingBytes, usingBlobs); 304 } 305 306 public void setJdbcObject( 307 PreparedStatement st, 308 Object val, 309 int pos, 310 int type, 311 int precision) throws Exception { 312 313 if (type == Types.LONGVARBINARY) { 315 type = Types.VARBINARY; 316 } 317 318 super.setJdbcObject(st, val, pos, type, precision); 319 } 320 } 321 322 public void bindParameter( 323 PreparedStatement statement, 324 Object object, 325 int pos, 326 int sqlType, 327 int precision) throws SQLException , Exception { 328 329 if (object == null) { 332 if (sqlType == Types.BLOB) { 333 sqlType = Types.VARBINARY; 334 } 335 else if (sqlType == Types.CLOB) { 336 sqlType = Types.VARCHAR; 337 } 338 } 339 340 super.bindParameter(statement, object, pos, sqlType, precision); 341 } 342 } 343 | Popular Tags |