Revision 20029 trunk/libraries/libDataSourceDBBaseDrivers/src/org/gvsig/data/datastores/vectorial/db/jdbc/postgresql/PostgresqlStoreUtils.java
PostgresqlStoreUtils.java | ||
---|---|---|
1 | 1 |
package org.gvsig.data.datastores.vectorial.db.jdbc.postgresql; |
2 | 2 |
|
3 |
import java.math.BigDecimal; |
|
4 |
import java.nio.ByteBuffer; |
|
5 | 3 |
import java.sql.Connection; |
6 |
import java.sql.Date; |
|
7 | 4 |
import java.sql.DriverManager; |
8 | 5 |
import java.sql.ResultSet; |
9 | 6 |
import java.sql.ResultSetMetaData; |
10 | 7 |
import java.sql.Statement; |
11 |
import java.sql.Timestamp; |
|
12 |
import java.sql.Types; |
|
8 |
import java.util.ArrayList; |
|
13 | 9 |
import java.util.Iterator; |
14 | 10 |
|
15 | 11 |
import org.gvsig.data.datastores.vectorial.db.DBFeatureType; |
... | ... | |
18 | 14 |
import org.gvsig.data.datastores.vectorial.db.jdbc.JDBCStore; |
19 | 15 |
import org.gvsig.data.datastores.vectorial.db.jdbc.exception.JDBCDriverNotFoundException; |
20 | 16 |
import org.gvsig.data.datastores.vectorial.db.jdbc.exception.SQLException; |
21 |
import org.gvsig.data.datastores.vectorial.db.jdbc.h2.H2Store; |
|
22 | 17 |
import org.gvsig.data.exception.InitializeException; |
23 | 18 |
import org.gvsig.data.exception.ReadException; |
24 | 19 |
import org.gvsig.data.vectorial.DefaultAttributeDescriptor; |
25 | 20 |
import org.gvsig.data.vectorial.IFeature; |
26 | 21 |
import org.gvsig.data.vectorial.IFeatureAttributeDescriptor; |
22 |
import org.postgis.PGgeometry; |
|
27 | 23 |
|
28 | 24 |
import com.iver.cit.gvsig.fmap.core.IGeometry; |
25 |
import com.iver.cit.gvsig.fmap.core.ShapeFactory; |
|
29 | 26 |
import com.iver.cit.gvsig.fmap.drivers.WKBParser2; |
30 |
import com.iver.cit.gvsig.fmap.drivers.XTypes; |
|
31 |
import com.vividsolutions.jts.io.WKBWriter; |
|
32 | 27 |
|
33 | 28 |
public class PostgresqlStoreUtils { |
34 | 29 |
|
35 |
private static WKBParser2 wkbParser = new WKBParser2(); |
|
36 |
private static WKBWriter wkbWriter = new WKBWriter(); |
|
37 |
|
|
38 |
|
|
39 | 30 |
static String getJDBCUrl(String host, String db, String port) { |
40 | 31 |
String url; |
41 | 32 |
url = "jdbc:postgresql://"+host+":" + port +"/"+db; |
... | ... | |
43 | 34 |
return url; |
44 | 35 |
} |
45 | 36 |
|
37 |
private static void addConditionForSerialField(JDBCAttributeDescriptor attr,StringBuffer sqlSeq){ |
|
38 |
sqlSeq.append(" ("); |
|
39 |
sqlSeq.append(" column_name = '" + attr.getName() +"'"); |
|
40 |
sqlSeq.append(" and table_name = '" + attr.getTableName()+ "'"); |
|
41 |
if (attr.getSchemaName() != null && attr.getSchemaName().length() > 0){ |
|
42 |
sqlSeq.append(" and table_schema = '" + attr.getSchemaName() +"'"); |
|
43 |
} |
|
44 |
|
|
45 |
sqlSeq.append(" and table_catalog = '" + attr.getCatalogName()+ "'"); |
|
46 |
sqlSeq.append(")"); |
|
47 |
|
|
48 |
} |
|
49 |
|
|
50 |
private static void initializeSerialFields(Connection connection,DBFeatureType featureType) throws java.sql.SQLException{ |
|
51 |
JDBCAttributeDescriptor attr; |
|
52 |
|
|
53 |
ArrayList serialCandidates= new ArrayList(); |
|
54 |
Iterator iter = featureType.iterator(); |
|
55 |
while(iter.hasNext()){ |
|
56 |
attr = (JDBCAttributeDescriptor)iter.next(); |
|
57 |
if (attr.getSqlTypeName().equals("int4") && |
|
58 |
attr.getTableName() != null && |
|
59 |
attr.getTableName().length() > 0){ |
|
60 |
serialCandidates.add(attr); |
|
61 |
} |
|
62 |
} |
|
63 |
if (serialCandidates.size() == 0){ |
|
64 |
return; |
|
65 |
} |
|
66 |
Statement st = connection.createStatement(); |
|
67 |
StringBuffer sqlSeq= new StringBuffer("select table_catalog,table_schema,table_name,column_name from information_schema.columns where column_default like 'nextval(%' and ( "); |
|
68 |
iter = serialCandidates.iterator(); |
|
69 |
String sql; |
|
70 |
int i; |
|
71 |
for (i=0;i<serialCandidates.size()-1;i++){ |
|
72 |
attr = (JDBCAttributeDescriptor)serialCandidates.get(i); |
|
73 |
addConditionForSerialField(attr,sqlSeq); |
|
74 |
sqlSeq.append(" or "); |
|
75 |
} |
|
76 |
attr = (JDBCAttributeDescriptor)serialCandidates.get(i); |
|
77 |
addConditionForSerialField(attr,sqlSeq); |
|
78 |
|
|
79 |
|
|
80 |
sqlSeq.append(")"); |
|
81 |
sql=sqlSeq.toString(); |
|
82 |
ResultSet rs = st.executeQuery(sql); |
|
83 |
while (rs.next()){ |
|
84 |
iter = serialCandidates.iterator(); |
|
85 |
while (iter.hasNext()){ |
|
86 |
attr = (JDBCAttributeDescriptor)iter.next(); |
|
87 |
if (rs.getString("column_name").equals(attr.getName())){ |
|
88 |
attr.setAutoIncrement(true); |
|
89 |
serialCandidates.remove(attr); |
|
90 |
break; |
|
91 |
} |
|
92 |
} |
|
93 |
|
|
94 |
} |
|
95 |
|
|
96 |
|
|
97 |
} |
|
98 |
|
|
99 |
|
|
46 | 100 |
static DBFeatureType getFeatureType(Connection connection, PostgresqlStoreParameters params) throws ReadException{ |
47 | 101 |
DBFeatureType featureType = new DBFeatureType(); |
102 |
String[] ids =params.getFieldsId(); |
|
103 |
int i; |
|
48 | 104 |
|
49 | 105 |
|
50 | 106 |
loadFieldsToFeatureType(connection, params, featureType); |
51 | 107 |
|
52 | 108 |
|
53 |
featureType.setFieldsId(params.getFieldsId()); |
|
109 |
//Inicializamos los IDs |
|
110 |
JDBCAttributeDescriptor attr; |
|
111 |
for (i=0;i<ids.length;i++){ |
|
112 |
try { |
|
113 |
attr = (JDBCAttributeDescriptor)featureType.get(ids[i]); |
|
114 |
} catch (IndexOutOfBoundsException e){ |
|
115 |
throw new InitializeException( |
|
116 |
PostgresqlStore.DATASTORE_NAME, |
|
117 |
new Exception("Id Field '"+ ids[i] +"' not Found")); |
|
54 | 118 |
|
119 |
} |
|
120 |
attr.setPrimaryKey(true); |
|
121 |
} |
|
122 |
featureType.setFieldsId(ids); |
|
123 |
|
|
124 |
//Inicializamos los 'serial' ya que en postgres el |
|
125 |
//'isAutonumeric' devuelve false |
|
126 |
// try{ |
|
127 |
// initializeSerialFields(connection,featureType); |
|
128 |
// } catch (java.sql.SQLException e) { |
|
129 |
// throw new InitializeException(PostgresqlStore.DATASTORE_NAME,e); |
|
130 |
// |
|
131 |
// } |
|
132 |
// |
|
133 |
|
|
134 |
|
|
135 |
|
|
136 |
|
|
137 |
//Inicializar campos geometricos si los hubiese |
|
138 |
//TODO Datos geometricos |
|
139 |
|
|
140 |
|
|
141 |
//Inicializar la geometria por defecto |
|
55 | 142 |
if (params.getDefaultGeometryField() != null && params.getDefaultGeometryField() != ""){ |
56 | 143 |
if (featureType.getFieldIndex(params.getDefaultGeometryField())< 0){ |
57 |
// FIXME: crear una nueva excepcion?? |
|
58 | 144 |
throw new InitializeException( |
59 | 145 |
PostgresqlStore.DATASTORE_NAME, |
60 | 146 |
new Exception("Geometry Field '"+ params.getDefaultGeometryField() +"' not Found")); |
61 | 147 |
|
62 | 148 |
} |
149 |
attr = (JDBCAttributeDescriptor)featureType.get(params.getDefaultGeometryField()); |
|
150 |
if (attr.getDataType() != IFeatureAttributeDescriptor.TYPE_GEOMETRY){ |
|
151 |
throw new InitializeException( |
|
152 |
PostgresqlStore.DATASTORE_NAME, |
|
153 |
new Exception("Field '"+ params.getDefaultGeometryField() +"' isn't a geometry")); |
|
63 | 154 |
|
155 |
} |
|
156 |
|
|
64 | 157 |
featureType.setDefaultGeometry(params.getDefaultGeometryField()); |
65 | 158 |
} |
66 | 159 |
|
160 |
|
|
67 | 161 |
return featureType; |
68 | 162 |
|
69 | 163 |
} |
... | ... | |
71 | 165 |
private static void loadFieldsToFeatureType(Connection conn,PostgresqlStoreParameters params,DBFeatureType featureType) throws ReadException{ |
72 | 166 |
String sql=""; |
73 | 167 |
String columns=params.getFieldsString(); |
168 |
boolean fillTableData; |
|
74 | 169 |
|
75 | 170 |
if (params.getSqlSoure() != null){ |
76 | 171 |
sql = params.getSqlSoure(); |
172 |
fillTableData = false; |
|
77 | 173 |
} else { |
78 |
sql = "Select "+columns+" from " + params.tableID() + " limit 1;"; |
|
174 |
sql = "Select "+columns+" from " + params.tableID(); |
|
175 |
fillTableData = true; |
|
79 | 176 |
} |
80 | 177 |
|
81 | 178 |
try { |
82 | 179 |
|
83 | 180 |
Statement stAux = conn.createStatement(); |
181 |
stAux.setFetchSize(1); |
|
84 | 182 |
ResultSet rs = stAux.executeQuery(sql); |
85 | 183 |
ResultSetMetaData rsMetadata = rs.getMetaData(); |
86 | 184 |
|
87 | 185 |
int i; |
88 | 186 |
|
89 | 187 |
featureType.setTableID(params.tableID()); |
90 |
DefaultAttributeDescriptor attr;
|
|
188 |
JDBCAttributeDescriptor attr;
|
|
91 | 189 |
for (i=1;i<=rsMetadata.getColumnCount();i++){ |
92 | 190 |
attr = getAttributeFromJDBC(conn,rsMetadata,i); |
93 | 191 |
featureType.add(attr); |
94 | 192 |
attr.setOrdinal(i-1); |
193 |
attr.setCatalogName(params.getDb()); |
|
194 |
if (fillTableData){ |
|
195 |
attr.setSchemaName(params.getSchema()); |
|
196 |
attr.setTableName(params.getTableName()); |
|
197 |
|
|
198 |
} |
|
95 | 199 |
} |
96 | 200 |
rs.close(); |
201 |
stAux.close(); |
|
202 |
|
|
203 |
|
|
204 |
|
|
97 | 205 |
} catch (java.sql.SQLException e) { |
98 |
// TODO Auto-generated catch block |
|
99 | 206 |
throw new SQLException(sql,"getFeatureType",e); |
100 | 207 |
} |
101 | 208 |
|
102 | 209 |
} |
103 | 210 |
|
104 |
private static DefaultAttributeDescriptor getAttributeFromJDBC(Connection conn,ResultSetMetaData rsMetadata,int colIndex) throws SQLException{
|
|
211 |
private static JDBCAttributeDescriptor getAttributeFromJDBC(Connection conn,ResultSetMetaData rsMetadata,int colIndex) throws SQLException{
|
|
105 | 212 |
JDBCAttributeDescriptor column= new JDBCAttributeDescriptor(); |
106 | 213 |
try { |
107 | 214 |
column.setName(rsMetadata.getColumnName(colIndex)); |
215 |
column.setCaseSensitive(rsMetadata.isCaseSensitive(colIndex)); |
|
108 | 216 |
column.setSqlType(rsMetadata.getColumnType(colIndex)); |
109 | 217 |
column.setAllowNull(rsMetadata.isNullable(colIndex) == ResultSetMetaData.columnNullable); |
110 | 218 |
column.setAutoIncrement(rsMetadata.isAutoIncrement(colIndex)); |
111 | 219 |
column.setReadOnly(rsMetadata.isReadOnly(colIndex)); |
220 |
column.setWritable(rsMetadata.isWritable(colIndex)); |
|
221 |
column.setClassName(rsMetadata.getColumnClassName(colIndex)); |
|
222 |
column.setCatalogName(rsMetadata.getCatalogName(colIndex)); |
|
223 |
column.setDefinitelyWritable(rsMetadata.isDefinitelyWritable(colIndex)); |
|
224 |
column.setLabel(rsMetadata.getColumnLabel(colIndex)); |
|
225 |
column.setSchemaName(rsMetadata.getSchemaName(colIndex)); |
|
226 |
column.setTableName(rsMetadata.getTableName(colIndex)); |
|
227 |
column.setCatalogName(rsMetadata.getCatalogName(colIndex)); |
|
228 |
column.setSqlTypeName(rsMetadata.getColumnTypeName(colIndex)); |
|
229 |
column.setSearchable(rsMetadata.isSearchable(colIndex)); |
|
230 |
column.setSigned(rsMetadata.isSigned(colIndex)); |
|
231 |
column.setCurrency(rsMetadata.isCurrency(colIndex)); |
|
232 |
column.setPrecision(rsMetadata.getPrecision(colIndex)); |
|
233 |
column.setSize(rsMetadata.getColumnDisplaySize(colIndex)); |
|
112 | 234 |
|
235 |
|
|
113 | 236 |
switch (rsMetadata.getColumnType(colIndex)) { |
114 | 237 |
case java.sql.Types.INTEGER: |
115 | 238 |
column.setType(IFeatureAttributeDescriptor.TYPE_INT); |
... | ... | |
119 | 242 |
break; |
120 | 243 |
case java.sql.Types.REAL: |
121 | 244 |
column.setType(IFeatureAttributeDescriptor.TYPE_DOUBLE); |
122 |
column.setPrecision(rsMetadata.getPrecision(colIndex)); |
|
123 | 245 |
break; |
124 | 246 |
case java.sql.Types.DOUBLE: |
125 | 247 |
column.setType(IFeatureAttributeDescriptor.TYPE_DOUBLE); |
126 |
column.setPrecision(rsMetadata.getPrecision(colIndex)); |
|
127 | 248 |
break; |
128 | 249 |
case java.sql.Types.CHAR: |
129 | 250 |
column.setType(IFeatureAttributeDescriptor.TYPE_STRING); |
130 |
column.setSize(rsMetadata.getColumnDisplaySize(colIndex)); |
|
131 | 251 |
break; |
132 | 252 |
case java.sql.Types.VARCHAR: |
133 | 253 |
column.setType(IFeatureAttributeDescriptor.TYPE_STRING); |
134 |
column.setSize(rsMetadata.getColumnDisplaySize(colIndex)); |
|
135 | 254 |
break; |
136 | 255 |
case java.sql.Types.FLOAT: |
137 | 256 |
column.setType(IFeatureAttributeDescriptor.TYPE_FLOAT); |
138 |
column.setSize(rsMetadata.getColumnDisplaySize(colIndex)); |
|
139 |
column.setPrecision(rsMetadata.getPrecision(colIndex)); |
|
140 | 257 |
break; |
141 | 258 |
case java.sql.Types.DECIMAL: |
142 | 259 |
column.setType(IFeatureAttributeDescriptor.TYPE_FLOAT); |
143 |
column.setSize(rsMetadata.getColumnDisplaySize(colIndex)); |
|
144 |
column.setPrecision(rsMetadata.getPrecision(colIndex)); |
|
145 | 260 |
break; |
146 | 261 |
case java.sql.Types.DATE: |
147 | 262 |
column.setType(IFeatureAttributeDescriptor.TYPE_DATE); |
... | ... | |
149 | 264 |
case java.sql.Types.BOOLEAN: |
150 | 265 |
column.setType(IFeatureAttributeDescriptor.TYPE_BOOLEAN); |
151 | 266 |
break; |
267 |
case java.sql.Types.OTHER: |
|
268 |
if (column.getSqlTypeName().equalsIgnoreCase("geometry")){ |
|
269 |
column.setType(IFeatureAttributeDescriptor.TYPE_GEOMETRY); |
|
270 |
break; |
|
271 |
} |
|
272 |
//No hacemos break para que se quede en default |
|
273 |
|
|
152 | 274 |
default: |
153 | 275 |
column.setType(IFeatureAttributeDescriptor.TYPE_OBJECT); |
154 | 276 |
break; |
... | ... | |
162 | 284 |
} |
163 | 285 |
|
164 | 286 |
|
165 |
static String getFliterForID(DBFeatureType featureType, Object[] featureKey) { |
|
166 |
// TODO Auto-generated method stub |
|
167 |
return null; |
|
287 |
static String getFilterForID(DBFeatureType fType, IFeature feature){ |
|
288 |
return getFilterForID(fType, getPkFromFeature(feature,fType)); |
|
168 | 289 |
} |
169 | 290 |
|
291 |
static String getFilterForID(DBFeatureType fType, Object[] featureKey){ |
|
292 |
//TODO: Ojo para los multiples |
|
293 |
if (fType.getFieldsId().length != 1) |
|
294 |
throw new UnsupportedOperationException("ID fields > 1"); |
|
295 |
String id =fType.getFieldsId()[0]; |
|
296 |
return id + " = " + objectToSqlString(featureKey[0]); |
|
297 |
} |
|
298 |
|
|
299 |
static String objectToSqlString(Object obj){ |
|
300 |
if (obj instanceof String){ |
|
301 |
return "'"+ scapeString((String)obj) +"'"; |
|
302 |
} else if (obj == null){ |
|
303 |
return "null"; |
|
304 |
}else{ |
|
305 |
// OJO con otros tipos!! |
|
306 |
return obj.toString(); |
|
307 |
} |
|
308 |
|
|
309 |
} |
|
310 |
|
|
311 |
static String scapeString(String str){ |
|
312 |
return str.replace("'", "''"); |
|
313 |
} |
|
314 |
|
|
315 |
|
|
316 |
|
|
170 | 317 |
static Connection getConnection(String dbUrl, String dbUser, String dbPass) throws InitializeException { |
171 | 318 |
//TODO: Aqu? habria que implementar la llamada |
172 | 319 |
// al Resource Manager para comprobar si ya hay |
... | ... | |
202 | 349 |
} |
203 | 350 |
|
204 | 351 |
|
205 |
protected static String getFliterForID(DBFeatureType fType, IFeature feature){ |
|
206 |
return getFliterForID(fType, getPkFromFeature(feature,fType)); |
|
207 |
} |
|
208 | 352 |
|
209 |
|
|
210 | 353 |
protected static Object[] getPkFromResulset(ResultSet rs, DBFeatureType featureType) throws java.sql.SQLException{ |
211 | 354 |
String[] fieldsId = featureType.getFieldsId(); |
212 | 355 |
Object[] result = new Object[fieldsId.length]; |
... | ... | |
245 | 388 |
while (iter.hasNext()) { |
246 | 389 |
IFeatureAttributeDescriptor fad=(IFeatureAttributeDescriptor)iter.next(); |
247 | 390 |
if (fad.getDataType().equals(IFeatureAttributeDescriptor.TYPE_GEOMETRY)) { |
248 |
byte[] data = rs.getBytes(fad.getName()); |
|
249 | 391 |
|
392 |
PGgeometry data =(PGgeometry)rs.getObject(fad.getName()); |
|
250 | 393 |
if (data == null) { |
251 | 394 |
geom = null; |
252 | 395 |
} else{ |
253 |
geom = wkbParser.parse(data);
|
|
396 |
geom = PostGIS2Geometry.getGeneralPath(data);
|
|
254 | 397 |
} |
255 | 398 |
feature.setGeometry(fad.getName(),geom); |
256 | 399 |
} else { |
Also available in: Unified diff