1 package edu.internet2.middleware.grouper.ext.org.apache.ddlutils.platform.postgresql;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.sql.Connection;
23 import java.sql.DriverManager;
24 import java.sql.PreparedStatement;
25 import java.sql.SQLException;
26 import java.sql.Statement;
27 import java.sql.Types;
28 import java.util.Iterator;
29 import java.util.Map;
30
31 import org.apache.commons.beanutils.DynaBean;
32 import edu.internet2.middleware.grouper.ext.org.apache.ddlutils.DatabaseOperationException;
33 import edu.internet2.middleware.grouper.ext.org.apache.ddlutils.PlatformInfo;
34 import edu.internet2.middleware.grouper.ext.org.apache.ddlutils.dynabean.SqlDynaProperty;
35 import edu.internet2.middleware.grouper.ext.org.apache.ddlutils.platform.PlatformImplBase;
36
37
38
39
40
41
42 public class PostgreSqlPlatform extends PlatformImplBase
43 {
44
45 public static final String DATABASENAME = "PostgreSql";
46
47 public static final String JDBC_DRIVER = "org.postgresql.Driver";
48
49 public static final String JDBC_SUBPROTOCOL = "postgresql";
50
51
52
53
54 public PostgreSqlPlatform()
55 {
56 PlatformInfo info = getPlatformInfo();
57
58
59
60 info.setMaxIdentifierLength(31);
61
62 info.addNativeTypeMapping(Types.ARRAY, "BYTEA", Types.LONGVARBINARY);
63 info.addNativeTypeMapping(Types.BINARY, "BYTEA", Types.LONGVARBINARY);
64 info.addNativeTypeMapping(Types.BIT, "BOOLEAN");
65 info.addNativeTypeMapping(Types.BLOB, "BYTEA", Types.LONGVARBINARY);
66 info.addNativeTypeMapping(Types.CLOB, "TEXT", Types.LONGVARCHAR);
67 info.addNativeTypeMapping(Types.DECIMAL, "NUMERIC", Types.NUMERIC);
68 info.addNativeTypeMapping(Types.DISTINCT, "BYTEA", Types.LONGVARBINARY);
69 info.addNativeTypeMapping(Types.DOUBLE, "DOUBLE PRECISION");
70 info.addNativeTypeMapping(Types.FLOAT, "DOUBLE PRECISION", Types.DOUBLE);
71 info.addNativeTypeMapping(Types.JAVA_OBJECT, "BYTEA", Types.LONGVARBINARY);
72 info.addNativeTypeMapping(Types.LONGVARBINARY, "BYTEA");
73 info.addNativeTypeMapping(Types.LONGVARCHAR, "TEXT", Types.LONGVARCHAR);
74 info.addNativeTypeMapping(Types.NULL, "BYTEA", Types.LONGVARBINARY);
75 info.addNativeTypeMapping(Types.OTHER, "BYTEA", Types.LONGVARBINARY);
76 info.addNativeTypeMapping(Types.REF, "BYTEA", Types.LONGVARBINARY);
77 info.addNativeTypeMapping(Types.STRUCT, "BYTEA", Types.LONGVARBINARY);
78 info.addNativeTypeMapping(Types.TINYINT, "SMALLINT", Types.SMALLINT);
79 info.addNativeTypeMapping(Types.VARBINARY, "BYTEA", Types.LONGVARBINARY);
80 info.addNativeTypeMapping("BOOLEAN", "BOOLEAN", "BIT");
81 info.addNativeTypeMapping("DATALINK", "BYTEA", "LONGVARBINARY");
82
83 info.setDefaultSize(Types.CHAR, 254);
84 info.setDefaultSize(Types.VARCHAR, 254);
85
86
87
88 info.setHasSize(Types.BINARY, false);
89 info.setHasSize(Types.VARBINARY, false);
90
91 setSqlBuilder(new PostgreSqlBuilder(this));
92 setModelReader(new PostgreSqlModelReader(this));
93 }
94
95
96
97
98 public String getName()
99 {
100 return DATABASENAME;
101 }
102
103
104
105
106
107
108
109
110
111
112
113 private void createOrDropDatabase(String jdbcDriverClassName, String connectionUrl, String username, String password, Map parameters, boolean createDb) throws DatabaseOperationException, UnsupportedOperationException
114 {
115 if (JDBC_DRIVER.equals(jdbcDriverClassName))
116 {
117 int slashPos = connectionUrl.lastIndexOf('/');
118
119 if (slashPos < 0)
120 {
121 throw new DatabaseOperationException("Cannot parse the given connection url "+connectionUrl);
122 }
123
124 int paramPos = connectionUrl.lastIndexOf('?');
125 String baseDb = connectionUrl.substring(0, slashPos + 1) + "template1";
126 String dbName = (paramPos > slashPos ? connectionUrl.substring(slashPos + 1, paramPos) : connectionUrl.substring(slashPos + 1));
127 Connection connection = null;
128 Statement stmt = null;
129 StringBuffer sql = new StringBuffer();
130
131 sql.append(createDb ? "CREATE" : "DROP");
132 sql.append(" DATABASE ");
133 sql.append(dbName);
134 if ((parameters != null) && !parameters.isEmpty())
135 {
136 for (Iterator it = parameters.entrySet().iterator(); it.hasNext();)
137 {
138 Map.Entry entry = (Map.Entry)it.next();
139
140 sql.append(" ");
141 sql.append(entry.getKey().toString());
142 if (entry.getValue() != null)
143 {
144 sql.append(" ");
145 sql.append(entry.getValue().toString());
146 }
147 }
148 }
149 if (getLog().isDebugEnabled())
150 {
151 getLog().debug("About to create database via "+baseDb+" using this SQL: "+sql.toString());
152 }
153 try
154 {
155 Class.forName(jdbcDriverClassName);
156
157 connection = DriverManager.getConnection(baseDb, username, password);
158 stmt = connection.createStatement();
159 stmt.execute(sql.toString());
160 logWarnings(connection);
161 }
162 catch (Exception ex)
163 {
164 throw new DatabaseOperationException("Error while trying to " + (createDb ? "create" : "drop") + " a database: "+ex.getLocalizedMessage(), ex);
165 }
166 finally
167 {
168 if (stmt != null)
169 {
170 try
171 {
172 stmt.close();
173 }
174 catch (SQLException ex)
175 {}
176 }
177 if (connection != null)
178 {
179 try
180 {
181 connection.close();
182 }
183 catch (SQLException ex)
184 {}
185 }
186 }
187 }
188 else
189 {
190 throw new UnsupportedOperationException("Unable to " + (createDb ? "create" : "drop") + " a PostgreSQL database via the driver "+jdbcDriverClassName);
191 }
192 }
193
194
195
196
197 public void createDatabase(String jdbcDriverClassName, String connectionUrl, String username, String password, Map parameters) throws DatabaseOperationException, UnsupportedOperationException
198 {
199
200
201 createOrDropDatabase(jdbcDriverClassName, connectionUrl, username, password, parameters, true);
202 }
203
204
205
206
207 public void dropDatabase(String jdbcDriverClassName, String connectionUrl, String username, String password) throws DatabaseOperationException, UnsupportedOperationException
208 {
209
210
211 createOrDropDatabase(jdbcDriverClassName, connectionUrl, username, password, null, false);
212 }
213
214
215
216
217 protected void setObject(PreparedStatement statement, int sqlIndex, DynaBean dynaBean, SqlDynaProperty property) throws SQLException
218 {
219 int typeCode = property.getColumn().getTypeCode();
220 Object value = dynaBean.get(property.getName());
221
222
223 if (value == null)
224 {
225 switch (typeCode)
226 {
227 case Types.BINARY:
228 case Types.VARBINARY:
229 case Types.LONGVARBINARY:
230 case Types.BLOB:
231 statement.setBytes(sqlIndex, null);
232 break;
233 default:
234 statement.setNull(sqlIndex, typeCode);
235 break;
236 }
237 }
238 else
239 {
240 super.setObject(statement, sqlIndex, dynaBean, property);
241 }
242 }
243 }