Statistics
| Revision:

svn-gvsig-desktop / tags / v2_0_0_Build_2020 / libraries / libFMap_daldb / src / org / gvsig / fmap / dal / store / jdbc / JDBCHelper.java @ 33950

History | View | Annotate | Download (28.7 KB)

1 28784 jmvivo
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
* MA  02110-1301, USA.
20
*
21
*/
22
23
/*
24
* AUTHORS (In addition to CIT):
25
* 2009 IVER T.I   {{Task}}
26
*/
27
28
/**
29
 *
30
 */
31
package org.gvsig.fmap.dal.store.jdbc;
32
33
import java.sql.Connection;
34
import java.sql.DatabaseMetaData;
35
import java.sql.ResultSet;
36
import java.sql.ResultSetMetaData;
37
import java.sql.SQLException;
38
import java.sql.Statement;
39
import java.util.ArrayList;
40
import java.util.Arrays;
41
import java.util.List;
42
43
import org.cresques.cts.IProjection;
44
import org.gvsig.fmap.dal.DALLocator;
45
import org.gvsig.fmap.dal.DataTypes;
46 28909 jmvivo
import org.gvsig.fmap.dal.NewDataStoreParameters;
47 28784 jmvivo
import org.gvsig.fmap.dal.exception.CloseException;
48
import org.gvsig.fmap.dal.exception.DataException;
49
import org.gvsig.fmap.dal.exception.InitializeException;
50
import org.gvsig.fmap.dal.exception.OpenException;
51
import org.gvsig.fmap.dal.exception.ReadException;
52
import org.gvsig.fmap.dal.exception.WriteException;
53
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
54
import org.gvsig.fmap.dal.feature.EditableFeatureType;
55
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
56 28909 jmvivo
import org.gvsig.fmap.dal.feature.FeatureType;
57 28784 jmvivo
import org.gvsig.fmap.dal.feature.exception.UnsupportedDataTypeException;
58 31022 cordinyana
import org.gvsig.fmap.dal.resource.ResourceAction;
59 28784 jmvivo
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
60 31022 cordinyana
import org.gvsig.fmap.dal.resource.exception.ResourceExecuteException;
61 28784 jmvivo
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
62
import org.gvsig.fmap.dal.resource.spi.ResourceManagerProviderServices;
63
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
64 28785 jmvivo
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCException;
65
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
66
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
67
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCTransactionCommitException;
68
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCTransactionRollbackException;
69 28784 jmvivo
import org.gvsig.fmap.geom.Geometry;
70
import org.gvsig.fmap.geom.GeometryLocator;
71
import org.gvsig.fmap.geom.operation.fromwkb.FromWKB;
72
import org.gvsig.fmap.geom.operation.fromwkb.FromWKBGeometryOperationContext;
73
import org.gvsig.fmap.geom.operation.towkb.ToWKB;
74
import org.gvsig.fmap.geom.operation.towkb.ToWKBOperationContext;
75
import org.gvsig.fmap.geom.primitive.Envelope;
76 31284 cordinyana
import org.gvsig.tools.dispose.impl.AbstractDisposable;
77 28784 jmvivo
import org.gvsig.tools.exception.BaseException;
78
import org.slf4j.Logger;
79
import org.slf4j.LoggerFactory;
80
81
/**
82
 * @author jmvivo
83
 *
84
 */
85 31284 cordinyana
public class JDBCHelper extends AbstractDisposable implements ResourceConsumer {
86 28784 jmvivo
87
        private static Logger logger = LoggerFactory.getLogger(JDBCHelper.class);
88
89
        protected JDBCHelperUser user;
90
        protected boolean isOpen;
91
        protected String name;
92
        protected String defaultSchema;
93
        protected JDBCConnectionParameters params;
94
        private JDBCResource resource;
95
96
        protected FromWKB fromWKB = null;
97
        protected FromWKBGeometryOperationContext fromWKBContext = null;
98
        protected ToWKBOperationContext toWKBContext = new ToWKBOperationContext();
99
100 28967 jmvivo
        private Boolean allowAutomaticValues = null;
101
        private Boolean supportsUnions = null;
102 28948 jmvivo
103 29123 jmvivo
        private String identifierQuoteString;
104
105 28784 jmvivo
        protected JDBCHelper(JDBCHelperUser consumer,
106
                        JDBCConnectionParameters params) throws InitializeException {
107
108
                this.user = consumer;
109 33717 jjdelcerro
                this.name = user.getProviderName();
110 28784 jmvivo
                this.params = params;
111
                initializeResource();
112
113
        }
114
115
        protected void initializeResource() throws InitializeException {
116
                ResourceManagerProviderServices manager = (ResourceManagerProviderServices) DALLocator
117
                                .getResourceManager();
118
                JDBCResource resource = (JDBCResource) manager
119 31022 cordinyana
                                .createAddResource(
120 28784 jmvivo
                                JDBCResource.NAME, new Object[] { params.getUrl(),
121
                                                params.getHost(), params.getPort(), params.getDBName(),
122
                                                params.getUser(), params.getPassword(),
123
                                                params.getJDBCDriverClassName() });
124
                this.setResource(resource);
125
126
        }
127
128
        protected final void setResource(JDBCResource resource) {
129
                this.resource = resource;
130
                this.resource.addConsumer(this);
131
        }
132
133
        public boolean closeResourceRequested(ResourceProvider resource) {
134
                return user.closeResourceRequested(resource);
135
        }
136
137
        public void resourceChanged(ResourceProvider resource) {
138
                user.resourceChanged(resource);
139
140
        }
141
142
        /**
143
         * open the resource
144
         *
145
         * @return true if the resourse was open in this call
146
         * @throws OpenException
147
         */
148
        public boolean open() throws OpenException {
149
                if (isOpen) {
150
                        return false;
151
                }
152 31022 cordinyana
                // try {
153
                // begin();
154
                // } catch (ResourceExecuteException e1) {
155
                // throw new OpenException(name, e1);
156
                // }
157 28784 jmvivo
                try {
158 31022 cordinyana
                        getResource().execute(new ResourceAction() {
159
                                public Object run() throws Exception {
160
                                        getResource().connect();
161
                                        getResource().notifyOpen();
162 28784 jmvivo
163 31022 cordinyana
                                        user.opendDone();
164 28784 jmvivo
165 31022 cordinyana
                                        isOpen = true;
166
                                        return null;
167
                                }
168
                        });
169 28784 jmvivo
                        return true;
170 31022 cordinyana
                } catch (ResourceExecuteException e) {
171 28784 jmvivo
                        throw new OpenException(name, e);
172 31022 cordinyana
                        // } finally {
173
                        // end();
174 28784 jmvivo
                }
175
176
        }
177
178 31022 cordinyana
        public JDBCResource getResource() {
179
                return resource;
180
        }
181
182 28784 jmvivo
        public void close() throws CloseException {
183
                if (!isOpen) {
184
                        return;
185
                }
186 31022 cordinyana
                // try {
187
                // begin();
188
                // } catch (ResourceExecuteException e) {
189
                // throw new CloseException(name, e);
190
                // }
191 28784 jmvivo
                try {
192 31022 cordinyana
                        getResource().execute(new ResourceAction() {
193
                                public Object run() throws Exception {
194
                                        isOpen = false;
195 28784 jmvivo
196 31022 cordinyana
                                        resource.notifyClose();
197
                                        user.closeDone();
198
                                        return null;
199
                                }
200
                        });
201
                } catch (ResourceExecuteException e) {
202 28784 jmvivo
                        throw new CloseException(this.name, e);
203 31022 cordinyana
                        // } finally {
204
                        // end();
205 28784 jmvivo
                }
206
        }
207
208 31022 cordinyana
        // public void end() {
209
        // resource.end();
210
        // }
211
        //
212
        // public void begin() throws ResourceExecuteException {
213
        // this.resource.begin();
214
        // }
215 28784 jmvivo
216
        public Connection getConnection() throws AccessResourceException {
217
                return resource.getJDBCConnection();
218
219
        }
220
221 31284 cordinyana
        @Override
222
        protected void doDispose() throws BaseException {
223 28784 jmvivo
                resource.removeConsumer(this);
224
        }
225
226
        public boolean isOpen() {
227
                return isOpen;
228
        }
229
230
        /**
231
         * Executes an atomic action that uses an DB Connection.<br>
232
         *
233
         * This methos prepares a connection and close it at the end of execution of
234
         * action.<br>
235
         *
236
         * if <code>action</code> is an instance of {@link TransactionalAction} the
237
         * action will be execute inside of a DB transaction.
238
         *
239
         *
240
         * @param action
241
         * @throws Exception
242
         */
243 31022 cordinyana
        public Object doConnectionAction(final ConnectionAction action)
244
                        throws Exception {
245 28784 jmvivo
                this.open();
246 31022 cordinyana
//                this.begin();
247
                return getResource().execute(new ResourceAction() {
248
                        public Object run() throws Exception {
249
                                Object result = null;
250
                                Connection conn = null;
251
                                boolean beginTrans = false;
252
                                try {
253
                                        conn = getConnection();
254
                                        if (action instanceof TransactionalAction) {
255
                                                // XXX OJO esta condicion NO ES FIABLE
256
                                                if (!conn.getAutoCommit()) {
257
                                                        if (!((TransactionalAction) action)
258
                                                                        .continueTransactionAllowed()) {
259
                                                                // FIXME exception
260
                                                                throw new Exception();
261
                                                        }
262
                                                }
263
                                                try {
264
                                                        conn.setAutoCommit(false);
265
                                                } catch (SQLException e) {
266
                                                        throw new JDBCSQLException(e);
267
                                                }
268
                                                beginTrans = true;
269
                                        }
270 28784 jmvivo
271 31022 cordinyana
                                        result = action.action(conn);
272
273
                                        if (beginTrans) {
274
                                                try {
275
                                                        conn.commit();
276
                                                } catch (SQLException e) {
277
                                                        throw new JDBCTransactionCommitException(e);
278
                                                }
279 28784 jmvivo
                                        }
280
281 31022 cordinyana
                                        return result;
282 28784 jmvivo
283 31022 cordinyana
                                } catch (Exception e) {
284 28784 jmvivo
285 31022 cordinyana
                                        if (beginTrans) {
286
                                                try {
287
                                                        conn.rollback();
288
                                                } catch (Exception e1) {
289
                                                        throw new JDBCTransactionRollbackException(e1, e);
290
                                                }
291
                                        }
292
                                        throw e;
293 28784 jmvivo
294 31022 cordinyana
                                } finally {
295
                                        try {
296
                                                conn.close();
297
                                        } catch (Exception e1) {
298
                                                logger.error("Exception on close connection", e1);
299
                                        }
300
                                        // this.end();
301 28784 jmvivo
                                }
302
                        }
303 31022 cordinyana
                });
304 28784 jmvivo
305
        }
306
307
        protected String getDefaultSchema(Connection conn) throws JDBCException {
308
                return defaultSchema;
309
        }
310
311
        protected EditableFeatureAttributeDescriptor createAttributeFromJDBC(
312
                        EditableFeatureType fType, Connection conn,
313
                        ResultSetMetaData rsMetadata, int colIndex)
314
                        throws java.sql.SQLException {
315
316
                EditableFeatureAttributeDescriptor column;
317
                switch (rsMetadata.getColumnType(colIndex)) {
318
                case java.sql.Types.INTEGER:
319
                        column = fType.add(rsMetadata.getColumnName(colIndex),
320
                                        DataTypes.INT);
321
                        break;
322
                case java.sql.Types.BIGINT:
323
                        column = fType.add(rsMetadata.getColumnName(colIndex),
324
                                        DataTypes.LONG);
325
                        break;
326
                case java.sql.Types.REAL:
327
                        column = fType.add(rsMetadata.getColumnName(colIndex),
328
                                        DataTypes.DOUBLE);
329
                        break;
330
                case java.sql.Types.DOUBLE:
331
                        column = fType.add(rsMetadata.getColumnName(colIndex),
332
                                        DataTypes.DOUBLE);
333
                        break;
334
                case java.sql.Types.CHAR:
335
                        column = fType.add(rsMetadata.getColumnName(colIndex),
336
                                        DataTypes.STRING);
337
                        break;
338
                case java.sql.Types.VARCHAR:
339 28909 jmvivo
                case java.sql.Types.LONGVARCHAR:
340 28784 jmvivo
                        column = fType.add(rsMetadata.getColumnName(colIndex),
341
                                        DataTypes.STRING);
342
                        break;
343
                case java.sql.Types.FLOAT:
344
                        column = fType.add(rsMetadata.getColumnName(colIndex),
345
                                        DataTypes.FLOAT);
346
                        break;
347
                case java.sql.Types.DECIMAL:
348
                        column = fType.add(rsMetadata.getColumnName(colIndex),
349
                                        DataTypes.FLOAT);
350
                        break;
351
                case java.sql.Types.DATE:
352
                        column = fType.add(rsMetadata.getColumnName(colIndex),
353
                                        DataTypes.DATE);
354
                        break;
355
                case java.sql.Types.TIME:
356
                        column = fType.add(rsMetadata.getColumnName(colIndex),
357
                                        DataTypes.TIME);
358
                        break;
359
                case java.sql.Types.TIMESTAMP:
360
                        column = fType.add(rsMetadata.getColumnName(colIndex),
361
                                        DataTypes.TIMESTAMP);
362
                        break;
363
                case java.sql.Types.BOOLEAN:
364
                        column = fType.add(rsMetadata.getColumnName(colIndex),
365
                                        DataTypes.BOOLEAN);
366
                        break;
367
                case java.sql.Types.BLOB:
368 28909 jmvivo
                case java.sql.Types.BINARY:
369
                case java.sql.Types.LONGVARBINARY:
370 28784 jmvivo
                        column = fType.add(rsMetadata.getColumnName(colIndex),
371
                                        DataTypes.BYTEARRAY);
372
                        break;
373
374
                default:
375
                        column = fType.add(rsMetadata.getColumnName(colIndex),
376
                                        DataTypes.OBJECT);
377 28909 jmvivo
                        column.setAdditionalInfo("SQLType", new Integer(rsMetadata
378
                                        .getColumnType(colIndex)));
379
                        column.setAdditionalInfo("SQLTypeName", rsMetadata
380
                                        .getColumnTypeName(colIndex));
381
382 28784 jmvivo
                        break;
383
                }
384
385
                return column;
386
387
        }
388
389
        protected EditableFeatureAttributeDescriptor getAttributeFromJDBC(
390
                        EditableFeatureType fType, Connection conn,
391
                        ResultSetMetaData rsMetadata, int colIndex) throws JDBCException {
392
                EditableFeatureAttributeDescriptor column;
393
                try {
394
395
                        column = createAttributeFromJDBC(fType, conn, rsMetadata, colIndex);
396
                        // column.setCaseSensitive(rsMetadata.isCaseSensitive(colIndex));
397
                        // column.setSqlType(rsMetadata.getColumnType(colIndex));
398
                        column.setAllowNull(
399
                                        rsMetadata.isNullable(colIndex) == ResultSetMetaData.columnNullable);
400
                        column.setIsAutomatic(rsMetadata.isAutoIncrement(colIndex));
401
                        column.setIsReadOnly(rsMetadata.isReadOnly(colIndex));
402
                        // column.setWritable(rsMetadata.isWritable(colIndex));
403
                        // column.setClassName(rsMetadata.getColumnClassName(colIndex));
404
                        // column.setCatalogName(rsMetadata.getCatalogName(colIndex));
405
                        // column.setDefinitelyWritable(rsMetadata
406
                        // .isDefinitelyWritable(colIndex));
407
                        // column.setLabel(rsMetadata.getColumnLabel(colIndex));
408
                        // column.setSchemaName(rsMetadata.getSchemaName(colIndex));
409
                        // column.setTableName(rsMetadata.getTableName(colIndex));
410
                        // column.setCatalogName(rsMetadata.getCatalogName(colIndex));
411
                        // column.setSqlTypeName();
412
                        // column.setSearchable(rsMetadata.isSearchable(colIndex));
413
                        // column.setSigned(rsMetadata.isSigned(colIndex));
414
                        // column.setCurrency(rsMetadata.isCurrency(colIndex));
415
                        column.setPrecision(rsMetadata.getPrecision(colIndex));
416
                        column.setSize(rsMetadata.getColumnDisplaySize(colIndex));
417
418
                } catch (java.sql.SQLException e) {
419
                        throw new JDBCSQLException(e);
420
                }
421
422
                return column;
423
424
        }
425
426
        /**
427
         * Fill <code>featureType</code> geometry attributes with SRS and ShapeType
428
         * information
429
         *
430
         * <b>Override this if provider has native eometry support</b>
431
         *
432
         * @param conn
433
         * @param rsMetadata
434
         * @param featureType
435
         * @throws ReadException
436
         */
437
        protected void loadSRS_and_shapeType(Connection conn,
438
                        ResultSetMetaData rsMetadata, EditableFeatureType featureType,
439
                        String baseSchema, String baseTable) throws JDBCException {
440
441
                // Nothing to do
442
443
        }
444
445
        public void loadFeatureType(EditableFeatureType featureType,
446
                        JDBCStoreParameters storeParams) throws DataException {
447
                if (storeParams.getSQL() != null
448
                                && storeParams.getSQL().trim().length() == 0) {
449
                        loadFeatureType(featureType, storeParams, storeParams.getSQL(),
450
                                        null, null);
451
                } else {
452
                        String sql = "Select * from " + storeParams.tableID()
453
                                        + " where false";
454
                        loadFeatureType(featureType, storeParams, sql, storeParams
455
                                        .getSchema(), storeParams.getTable());
456
                }
457
        }
458
459 31022 cordinyana
        public void loadFeatureType(final EditableFeatureType featureType,
460
                        final JDBCStoreParameters storeParams, final String sql,
461
                        final String schema, final String table) throws DataException {
462 28784 jmvivo
                this.open();
463 31022 cordinyana
//                this.begin();
464
                getResource().execute(new ResourceAction() {
465
                        public Object run() throws Exception {
466
                                Connection conn = null;
467
                                try {
468
                                        conn = getConnection();
469
470
                                        String[] pks = storeParams.getPkFields();
471
                                        if (pks == null || pks.length < 1) {
472
                                                if (storeParams.getTable() != null
473
                                                                && storeParams.getTable().trim().length() > 0) {
474
                                                        pks = getPksFrom(conn, storeParams);
475
476
                                                }
477
                                        }
478
479
                                        loadFeatureType(conn, featureType, sql, pks, storeParams
480 32880 jjdelcerro
                                                        .getDefaultGeometryField(), schema, table);
481 31022 cordinyana
482
                                } finally {
483
                                        try {
484
                                                conn.close();
485
                                        } catch (Exception e) {
486
                                        }
487
//                        this.end();
488 28784 jmvivo
                                }
489 31022 cordinyana
                                return null;
490 28784 jmvivo
                        }
491 31022 cordinyana
                });
492 28784 jmvivo
        }
493
494
        protected String[] getPksFrom(Connection conn, JDBCStoreParameters params)
495
                throws JDBCException {
496
                try{
497
                        DatabaseMetaData metadata = conn.getMetaData();
498
                        ResultSet rsPrimaryKeys = null;
499
                        ResultSet rs = null;
500
                        String catalog = params.getCatalog();
501
                        String schema = params.getSchema();
502 28909 jmvivo
503 28784 jmvivo
                        try{
504
                                rs = metadata.getTables(catalog,
505
                                                schema, params.getTable(), null);
506 28909 jmvivo
507 28784 jmvivo
                                if (!rs.next()) {
508
                                        // No tables found with default values, ignoring catalog
509
                                        rs.close();
510
                                        catalog = null;
511
                                        schema = null;
512
                                        rs = metadata
513
                                                        .getTables(catalog, schema, params.getTable(), null);
514
515
                                        if (!rs.next()) {
516
                                                // table not found
517
                                                return null;
518
                                        } else if (rs.next()){
519
                                                // More that one, cant identify
520
                                                return null;
521
                                        }
522
523
                                } else if (rs.next()) {
524
                                        // More that one, cant identify
525
                                        return null;
526
                                }
527
                                rsPrimaryKeys = metadata.getPrimaryKeys(catalog, schema, params
528
                                                .getTable());
529
                                List pks = new ArrayList();
530
                                while (rsPrimaryKeys.next()){
531
                                        pks.add(rsPrimaryKeys.getString("COLUMN_NAME"));
532
                                }
533
                                return (String[]) pks.toArray(new String[pks.size()]);
534
535 28909 jmvivo
536 28784 jmvivo
                        } finally {
537 28909 jmvivo
                                try{if (rs != null) {
538
                                        rs.close();
539
                                }} catch (SQLException ex) {logger.warn("Exception closing tables rs", ex);};
540
                                try{if (rsPrimaryKeys != null) {
541
                                        rsPrimaryKeys.close();
542
                                }} catch (SQLException ex) {logger.warn("Exception closing pk rs", ex);};
543 28784 jmvivo
                        }
544
545
546
                } catch (SQLException e) {
547
                        logger.warn("Unable to get pk from DatabaseMetada", e);
548
                        return getPksFromInformationSchema(conn, params);
549
                }
550
551
        }
552
553
        protected String[] getPksFromInformationSchema(Connection conn,
554
                        JDBCStoreParameters params)
555
                        throws JDBCException {
556
                Statement st;
557
                StringBuffer sql = new StringBuffer();
558
                ResultSet rs;
559
                ArrayList list = new ArrayList();
560
561
                /*
562
                 select column_name as primary_key
563
                        from information_schema.table_constraints t_cons
564
                                inner join information_schema.key_column_usage c on
565
                                        c.constraint_catalog = t_cons.table_catalog and
566
                                    c.table_schema = t_cons.table_schema and
567
                                    c.table_name = t_cons.table_name and
568
                                        c.constraint_name = t_cons.constraint_name
569
                                where t_cons.table_schema = <schema>
570
                                and t_cons.constraint_catalog = <catalog>
571
                                 and t_cons.table_name = <table>
572
                                 and constraint_type = 'PRIMARY KEY'
573
                 */
574
                /*
575
                 * SELECT column_name FROM INFORMATION_SCHEMA.constraint_column_usage
576
                 * left join INFORMATION_SCHEMA.table_constraints on
577
                 * (INFORMATION_SCHEMA.table_constraints.constraint_name =
578
                 * INFORMATION_SCHEMA.constraint_column_usage.constraint_name and
579
                 * INFORMATION_SCHEMA.table_constraints.table_name =
580
                 * INFORMATION_SCHEMA.constraint_column_usage.table_name and
581
                 * INFORMATION_SCHEMA.table_constraints.table_schema =
582
                 * INFORMATION_SCHEMA.constraint_column_usage.table_schema) WHERE
583
                 * INFORMATION_SCHEMA.constraint_column_usage.table_name like
584
                 * 'muni10000_peq' AND
585
                 * INFORMATION_SCHEMA.constraint_column_usage.table_schema like 'public'
586
                 * AND INFORMATION_SCHEMA.constraint_column_usage.table_catalog like
587
                 * 'gis' AND constraint_type='PRIMARY KEY'
588
                 */
589
590
                sql.append("select column_name as primary_key ");
591
                sql.append("from information_schema.table_constraints t_cons ");
592
                sql.append("inner join information_schema.key_column_usage c on ");
593
                sql.append("c.constraint_catalog = t_cons.constraint_catalog and ");
594
                sql.append("c.table_schema = t_cons.table_schema and ");
595
                sql.append("c.table_name = t_cons.table_name and ");
596
                sql.append("c.constraint_name = t_cons.constraint_name ");
597
                sql.append("WHERE t_cons.table_name like '");
598
599
                sql.append(params.getTable());
600
                sql.append("' ");
601
                String schema = null;
602
603
604
                if (params.getSchema() == null || params.getSchema() == "") {
605
                        schema = getDefaultSchema(conn);
606
                } else {
607
                        schema = params.getSchema();
608
                }
609
                if (schema != null) {
610
                        sql.append(" and t_cons.table_schema like '");
611
                        sql.append(schema);
612
                        sql.append("' ");
613
                }
614
615
                if (params.getCatalog() != null && params.getCatalog() != "") {
616
                        sql
617
                                        .append(" and t_cons.constraint_catalog like '");
618
                        sql.append(params.getCatalog());
619
                        sql.append("' ");
620
                }
621
622
                sql.append("' and constraint_type = 'PRIMARY KEY'");
623
624
                // System.out.println(sql.toString());
625
                try {
626
                        st = conn.createStatement();
627
                        try {
628
                                rs = st.executeQuery(sql.toString());
629
                        } catch (java.sql.SQLException e) {
630
                                throw new JDBCExecuteSQLException(sql.toString(), e);
631
                        }
632
                        while (rs.next()) {
633
                                list.add(rs.getString(1));
634
                        }
635
                        rs.close();
636
                        st.close();
637
638
                } catch (java.sql.SQLException e) {
639
                        throw new JDBCSQLException(e);
640
                }
641
                if (list.size() == 0) {
642
                        return null;
643
                }
644
645
                return (String[]) list.toArray(new String[0]);
646
647
        }
648
649
        protected void loadFeatureType(Connection conn,
650
                        EditableFeatureType featureType, String sql, String[] pks,
651
                        String defGeomName, String schema, String table)
652
                        throws DataException {
653
654
                Statement stAux = null;
655
                ResultSet rs = null;
656
                try {
657
658
                        stAux = conn.createStatement();
659
                        stAux.setFetchSize(1);
660
661
                        try {
662
                                rs = stAux.executeQuery(sql);
663
                        } catch (SQLException e) {
664
                                throw new JDBCExecuteSQLException(sql, e);
665
                        }
666
                        ResultSetMetaData rsMetadata = rs.getMetaData();
667
668
                        List pksList = null;
669
                        if (pks != null) {
670
                                pksList = Arrays.asList(pks);
671
672
                        }
673
674
                        int i;
675
                        int geometriesColumns = 0;
676
                        String lastGeometry = null;
677
678
                        EditableFeatureAttributeDescriptor attr;
679
                        for (i = 1; i <= rsMetadata.getColumnCount(); i++) {
680
                                attr = getAttributeFromJDBC(featureType, conn, rsMetadata, i);
681
                                if (pksList != null && pksList.contains(attr.getName())) {
682
                                        attr.setIsPrimaryKey(true);
683
                                }
684 33331 jjdelcerro
                                if (attr.getType() == DataTypes.GEOMETRY) {
685 28784 jmvivo
                                        geometriesColumns++;
686
                                        lastGeometry = attr.getName();
687
                                        if (lastGeometry.equals(defGeomName)) {
688
                                                featureType
689
                                                                .setDefaultGeometryAttributeName(defGeomName);
690
                                        }
691
692
                                }
693
694
                        }
695
696
                        if (geometriesColumns > 0) {
697
                                loadSRS_and_shapeType(conn, rsMetadata, featureType, schema,
698
                                                table);
699
                        }
700
701
                        if (defGeomName == null && geometriesColumns == 1) {
702
                                featureType.setDefaultGeometryAttributeName(lastGeometry);
703
                                defGeomName = lastGeometry;
704
                        }
705
706
                } catch (java.sql.SQLException e) {
707
                        throw new JDBCSQLException(e); // FIXME exception
708
                } finally {
709
                        try {
710
                                rs.close();
711
                        } catch (Exception e) {
712
                        }
713
                        try {
714
                                stAux.close();
715
                        } catch (Exception e) {
716
                        }
717
718
                }
719
720
        }
721
722
        /**
723
         * Override if provider has geometry support
724
         *
725
         * @param storeParams
726
         * @param geometryAttrName
727
         * @param limit
728
         * @return
729
         * @throws DataException
730
         */
731
        public Envelope getFullEnvelopeOfField(JDBCStoreParameters storeParams,
732
                        String geometryAttrName, Envelope limit) throws DataException {
733
734
                // TODO
735
                return null;
736
737
        }
738
739
        protected void initializeFromWKBOperation() throws BaseException {
740
                if (fromWKB == null) {
741
                        fromWKB = (FromWKB) GeometryLocator.getGeometryManager()
742
                                        .getGeometryOperation(FromWKB.CODE,
743
                                                        Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2D);
744
                        fromWKBContext = new FromWKBGeometryOperationContext();
745
746
                }
747
        }
748
749
        public Geometry getGeometry(byte[] buffer) throws BaseException {
750
                if (buffer == null) {
751
                        return null;
752
                }
753
                initializeFromWKBOperation();
754
                Geometry geom;
755
                try {
756
                        fromWKBContext.setData(buffer);
757
758
                        geom = (Geometry) fromWKB.invoke(null, fromWKBContext);
759
                } finally {
760
                        fromWKBContext.setData(null);
761
                }
762
                return geom;
763
        }
764
765
        public String escapeFieldName(String field) {
766 29123 jmvivo
                if (field.matches("[a-z][a-z0-9_]*")) {
767
                        return field;
768
                }
769
                String quote = getIdentifierQuoteString();
770
                return quote + field + quote;
771 28784 jmvivo
        }
772
773
        public Object dalValueToJDBC(
774
                        FeatureAttributeDescriptor attributeDescriptor, Object object)
775
                        throws WriteException {
776
                if (object == null) {
777
                        return null;
778
                }
779
780 33331 jjdelcerro
                if (attributeDescriptor.getType() != DataTypes.GEOMETRY) {
781 28784 jmvivo
                        return object;
782
                }
783
                try {
784
                        Geometry geom = (Geometry) object;
785
786
                        toWKBContext.setSrID(-1);
787
                        IProjection srs = attributeDescriptor.getSRS();
788
                        if (srs != null) {
789
                                toWKBContext.setSrID(getProviderSRID(srs));
790
                        }
791
792
                        // TODO optimize this
793
                        // byte[] wkb = (byte[])
794
                        // geom.invokeOperation(ToWKBNative.CODE,toWKBContext);
795
                        byte[] wkb = (byte[]) geom.invokeOperation(ToWKB.CODE,
796
                                        toWKBContext);
797
                        if (wkb == null) {
798
                                // FIXME excpetion
799
                                throw new IllegalArgumentException();
800
                        }
801
802
                        return wkb;
803
                } catch (Exception e) {
804
                        throw new WriteException(this.name, e);
805
                }
806
        }
807
808
        public String getSqlColumnTypeDescription(FeatureAttributeDescriptor attr) {
809 33331 jjdelcerro
                switch (attr.getType()) {
810 28784 jmvivo
                case DataTypes.STRING:
811
                        if (attr.getSize() < 1 || attr.getSize() > 255) {
812
                                return "text";
813
                        } else {
814
                                return "varchar(" + attr.getSize() + ")";
815
                        }
816
                case DataTypes.BOOLEAN:
817
                        return "bool";
818
819
                case DataTypes.BYTE:
820
                        return "smallint";
821
822
                case DataTypes.DATE:
823
                        return "date";
824
825
                case DataTypes.TIMESTAMP:
826
                        return "timestamp";
827
828
                case DataTypes.TIME:
829
                        return "time";
830
831
                case DataTypes.BYTEARRAY:
832 28948 jmvivo
                case DataTypes.GEOMETRY:
833 28784 jmvivo
                        return "blob";
834
835
                case DataTypes.DOUBLE:
836 28909 jmvivo
                        // if (attr.getPrecision() > 0) {
837
                        // return "double precision(" + attr.getPrecision() + ')';
838
                        // } else {
839
                        return "double";
840
                        // }
841 28784 jmvivo
                case DataTypes.FLOAT:
842
                        return "real";
843
844
                case DataTypes.INT:
845 28948 jmvivo
                        if (attr.isAutomatic() && allowAutomaticValues()) {
846 28784 jmvivo
                                return "serial";
847
                        } else {
848
                                return "integer";
849
                        }
850
                case DataTypes.LONG:
851
                        if (attr.isAutomatic()) {
852
                                return "bigserial";
853
                        } else {
854
                                return "bigint";
855
                        }
856
857
                default:
858 28909 jmvivo
                        String typeName = (String) attr.getAdditionalInfo("SQLTypeName");
859
                        if (typeName != null) {
860
                                return typeName;
861
                        }
862
863 28784 jmvivo
                        throw new UnsupportedDataTypeException(attr.getDataTypeName(), attr
864 33331 jjdelcerro
                                        .getType());
865 28784 jmvivo
                }
866
        }
867
868
        public int getProviderSRID(String srs) {
869
                return -1;
870
        }
871
872
        public int getProviderSRID(IProjection srs) {
873
                return -1;
874
        }
875
876
        public String getSqlFieldName(FeatureAttributeDescriptor attribute) {
877
                return escapeFieldName(attribute.getName());
878
        }
879
880 28909 jmvivo
        public String getSqlFieldDescription(FeatureAttributeDescriptor attr)
881
                        throws DataException {
882 28784 jmvivo
883
                /**
884
                 * column_name data_type [ DEFAULT default_expr ] [ column_constraint [
885
                 * ... ] ]
886
                 *
887
                 * where column_constraint is:
888
                 *
889
                 * [ CONSTRAINT constraint_name ] { NOT NULL | NULL | UNIQUE | PRIMARY
890
                 * KEY | CHECK (expression) | REFERENCES reftable [ ( refcolumn ) ] [
891
                 * MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE action ] [ ON
892
                 * UPDATE action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY
893
                 * DEFERRED | INITIALLY IMMEDIATE ]
894
                 */
895
896 28909 jmvivo
                StringBuilder strb = new StringBuilder();
897 28784 jmvivo
                // name
898 28909 jmvivo
                strb.append(escapeFieldName(attr.getName()));
899 28784 jmvivo
                strb.append(" ");
900
901
                // Type
902
                strb.append(this.getSqlColumnTypeDescription(attr));
903
                strb.append(" ");
904
905 28909 jmvivo
                boolean allowNull = attr.allowNull()
906
                                && !(attr.isPrimaryKey() || attr.isAutomatic());
907 28784 jmvivo
                // Default
908
                if (attr.getDefaultValue() == null) {
909 28909 jmvivo
                        if (allowNull) {
910 28784 jmvivo
                                strb.append("DEFAULT NULL ");
911
                        }
912
                } else {
913 28909 jmvivo
                        String value = getDefaltFieldValueString(attr);
914 28784 jmvivo
                        strb.append("DEFAULT '");
915
                        strb.append(value);
916
                        strb.append("' ");
917
                }
918
919
                // Null
920 28909 jmvivo
                if (allowNull) {
921
                        strb.append("NULL ");
922
                } else {
923 28784 jmvivo
                        strb.append("NOT NULL ");
924
                }
925
926
                // Primery key
927
                if (attr.isPrimaryKey()) {
928
                        strb.append("PRIMARY KEY ");
929
                }
930 28909 jmvivo
                return strb.toString();
931 28784 jmvivo
        }
932
933 28909 jmvivo
        protected String getDefaltFieldValueString(FeatureAttributeDescriptor attr)
934
                        throws WriteException {
935
                return dalValueToJDBC(attr, attr.getDefaultValue()).toString();
936
        }
937
938 28784 jmvivo
        public String compoundLimitAndOffset(long limit, long offset) {
939
                StringBuilder sql = new StringBuilder();
940
                // limit
941 31128 cordinyana
                if (limit > 0) {
942 28784 jmvivo
                        sql.append(" limit ");
943
                        sql.append(limit);
944
                        sql.append(' ');
945
                }
946
947
                // offset
948 31128 cordinyana
                if (offset > 0) {
949 28784 jmvivo
                        sql.append(" offset ");
950
                        sql.append(offset);
951
                        sql.append(' ');
952
                }
953
                return sql.toString();
954
        }
955
956
        public boolean supportOffset() {
957
                return true;
958
        }
959
960 28909 jmvivo
        public List getAdditionalSqlToCreate(NewDataStoreParameters ndsp,
961
                        FeatureType fType) {
962
                // TODO Auto-generated method stub
963
                return null;
964
        }
965
966
967
        public String stringJoin(List listToJoin,String sep){
968
                StringBuilder strb = new StringBuilder();
969
                stringJoin(listToJoin,sep,strb);
970
                return strb.toString();
971
        }
972
973
        public void stringJoin(List listToJoin, String sep, StringBuilder strb) {
974
                if (listToJoin.size() < 1) {
975
                        return;
976
                }
977
                if (listToJoin.size() > 1) {
978
                        for (int i = 0; i < listToJoin.size() - 1; i++) {
979
                                strb.append(listToJoin.get(i));
980
                                strb.append(sep);
981
                        }
982
                }
983
                strb.append(listToJoin.get(listToJoin.size() - 1));
984
        }
985 33196 cordinyana
986 28909 jmvivo
        /**
987
         * Inform that provider has supports for geometry store and operations
988
         * natively
989
         *
990
         * @return
991
         */
992 33196 cordinyana
        protected boolean supportsGeometry() {
993 28909 jmvivo
                return false;
994
        }
995 28948 jmvivo
996
        public boolean allowAutomaticValues() {
997
                if (allowAutomaticValues == null) {
998
                        ConnectionAction action = new ConnectionAction(){
999
1000
                                public Object action(Connection conn) throws DataException {
1001
1002
                                        ResultSet rs;
1003
                                        try {
1004
                                                DatabaseMetaData meta = conn.getMetaData();
1005
                                                rs = meta.getTypeInfo();
1006
                                                try{
1007
                                                        while (rs.next()) {
1008
                                                                if (rs.getInt("DATA_TYPE") == java.sql.Types.INTEGER) {
1009
                                                                        if (rs.getBoolean("AUTO_INCREMENT")) {
1010
                                                                                return Boolean.TRUE;
1011
                                                                        } else {
1012
                                                                                return Boolean.FALSE;
1013
                                                                        }
1014
                                                                }
1015
                                                        }
1016
                                                }finally{
1017
                                                        try{ rs.close();} catch (SQLException ex) {logger.error("Exception closing resulset", ex);};
1018
                                                }
1019
                                        } catch (SQLException e) {
1020
                                                throw new JDBCSQLException(e);
1021
                                        }
1022
                                        return Boolean.FALSE;
1023
                                }
1024
1025
                        };
1026
1027
1028
1029
                        try {
1030
                                allowAutomaticValues = (Boolean) doConnectionAction(action);
1031
                        } catch (Exception e) {
1032
                                logger.error("Exception checking for automatic integers", e);
1033
                                allowAutomaticValues = Boolean.FALSE;
1034
                        }
1035
                }
1036
                return allowAutomaticValues.booleanValue();
1037
        }
1038 28967 jmvivo
1039
        public boolean supportsUnion() {
1040
                if (supportsUnions == null) {
1041
                        ConnectionAction action = new ConnectionAction() {
1042
1043
                                public Object action(Connection conn) throws DataException {
1044
1045
                                        try {
1046
                                                DatabaseMetaData meta = conn.getMetaData();
1047
                                                return new Boolean(meta.supportsUnion());
1048
                                        } catch (SQLException e) {
1049
                                                throw new JDBCSQLException(e);
1050
                                        }
1051
                                }
1052
1053
                        };
1054
1055
                        try {
1056
                                supportsUnions = (Boolean) doConnectionAction(action);
1057
                        } catch (Exception e) {
1058
                                logger.error("Exception checking for unions support", e);
1059
                                supportsUnions = Boolean.FALSE;
1060
                        }
1061
                }
1062
                return supportsUnions.booleanValue();
1063
        }
1064 29123 jmvivo
1065
        protected String getIdentifierQuoteString() {
1066
                if (identifierQuoteString == null) {
1067
                ConnectionAction action = new ConnectionAction() {
1068
1069
                        public Object action(Connection conn) throws DataException {
1070
1071
                                try {
1072
                                        DatabaseMetaData meta = conn.getMetaData();
1073
                                        return meta.getIdentifierQuoteString();
1074
                                } catch (SQLException e) {
1075
                                        throw new JDBCSQLException(e);
1076
                                }
1077
                        }
1078
1079
                };
1080
1081
                try {
1082
                        identifierQuoteString = (String) doConnectionAction(action);
1083
                } catch (Exception e) {
1084
                        logger.error("Exception checking for unions support", e);
1085
                        identifierQuoteString = " ";
1086
                        }
1087
                }
1088
                return identifierQuoteString;
1089
        }
1090
1091
        protected boolean isReservedWord(String field) {
1092
                // TODO
1093
                return false;
1094
        }
1095
1096 28784 jmvivo
}