Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_daldb / src / org / gvsig / fmap / dal / store / jdbc / JDBCHelper.java @ 28948

History | View | Annotate | Download (26.2 KB)

1
/* 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
import org.gvsig.fmap.dal.NewDataStoreParameters;
47
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
import org.gvsig.fmap.dal.feature.FeatureType;
57
import org.gvsig.fmap.dal.feature.exception.UnsupportedDataTypeException;
58
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
59
import org.gvsig.fmap.dal.resource.exception.ResourceBeginException;
60
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
61
import org.gvsig.fmap.dal.resource.spi.ResourceManagerProviderServices;
62
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
63
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCException;
64
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
65
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
66
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCTransactionCommitException;
67
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCTransactionRollbackException;
68
import org.gvsig.fmap.geom.Geometry;
69
import org.gvsig.fmap.geom.GeometryLocator;
70
import org.gvsig.fmap.geom.operation.fromwkb.FromWKB;
71
import org.gvsig.fmap.geom.operation.fromwkb.FromWKBGeometryOperationContext;
72
import org.gvsig.fmap.geom.operation.towkb.ToWKB;
73
import org.gvsig.fmap.geom.operation.towkb.ToWKBOperationContext;
74
import org.gvsig.fmap.geom.primitive.Envelope;
75
import org.gvsig.tools.exception.BaseException;
76
import org.slf4j.Logger;
77
import org.slf4j.LoggerFactory;
78

    
79
/**
80
 * @author jmvivo
81
 *
82
 */
83
public class JDBCHelper implements ResourceConsumer {
84

    
85
        private static Logger logger = LoggerFactory.getLogger(JDBCHelper.class);
86

    
87
        protected JDBCHelperUser user;
88
        protected boolean isOpen;
89
        protected String name;
90
        protected String defaultSchema;
91
        protected JDBCConnectionParameters params;
92
        private JDBCResource resource;
93

    
94
        protected FromWKB fromWKB = null;
95
        protected FromWKBGeometryOperationContext fromWKBContext = null;
96
        protected ToWKBOperationContext toWKBContext = new ToWKBOperationContext();
97

    
98
        private Boolean allowAutomaticValues;
99

    
100
        protected JDBCHelper(JDBCHelperUser consumer,
101
                        JDBCConnectionParameters params) throws InitializeException {
102

    
103
                this.user = consumer;
104
                this.name = user.getName();
105
                this.params = params;
106
                initializeResource();
107

    
108
        }
109

    
110
        protected void initializeResource() throws InitializeException {
111
                ResourceManagerProviderServices manager = (ResourceManagerProviderServices) DALLocator
112
                                .getResourceManager();
113
                JDBCResource resource = (JDBCResource) manager
114
                                .createResource(
115
                                JDBCResource.NAME, new Object[] { params.getUrl(),
116
                                                params.getHost(), params.getPort(), params.getDBName(),
117
                                                params.getUser(), params.getPassword(),
118
                                                params.getJDBCDriverClassName() });
119
                this.setResource(resource);
120

    
121
        }
122

    
123
        protected final void setResource(JDBCResource resource) {
124
                this.resource = resource;
125
                this.resource.addConsumer(this);
126
        }
127

    
128
        public boolean closeResourceRequested(ResourceProvider resource) {
129
                return user.closeResourceRequested(resource);
130
        }
131

    
132
        public void resourceChanged(ResourceProvider resource) {
133
                user.resourceChanged(resource);
134

    
135
        }
136

    
137
        /**
138
         * open the resource
139
         *
140
         * @return true if the resourse was open in this call
141
         * @throws OpenException
142
         */
143
        public boolean open() throws OpenException {
144
                if (isOpen) {
145
                        return false;
146
                }
147
                try {
148
                        begin();
149
                } catch (ResourceBeginException e1) {
150
                        throw new OpenException(name, e1);
151
                }
152
                try {
153
                        resource.connect();
154
                        resource.notifyOpen();
155

    
156
                        this.user.opendDone();
157

    
158
                        isOpen = true;
159

    
160
                        return true;
161
                } catch (DataException e) {
162
                        throw new OpenException(name, e);
163
                } finally {
164
                        end();
165
                }
166

    
167
        }
168

    
169
        public void close() throws CloseException {
170
                if (!isOpen) {
171
                        return;
172
                }
173
                try {
174
                        begin();
175
                } catch (ResourceBeginException e) {
176
                        throw new CloseException(name, e);
177
                }
178
                try {
179

    
180
                        isOpen = false;
181

    
182
                        resource.notifyClose();
183
                        this.user.closeDone();
184
                } catch (DataException e) {
185
                        throw new CloseException(this.name, e);
186
                } finally {
187
                        end();
188
                }
189
        }
190

    
191
        public void end() {
192
                resource.end();
193
        }
194

    
195
        public void begin() throws ResourceBeginException {
196
                this.resource.begin();
197
        }
198

    
199
        public Connection getConnection() throws AccessResourceException {
200
                return resource.getJDBCConnection();
201

    
202
        }
203

    
204
        public void dispose() {
205
                resource.removeConsumer(this);
206
        }
207

    
208
        public boolean isOpen() {
209
                return isOpen;
210
        }
211

    
212
        /**
213
         * Executes an atomic action that uses an DB Connection.<br>
214
         *
215
         * This methos prepares a connection and close it at the end of execution of
216
         * action.<br>
217
         *
218
         * if <code>action</code> is an instance of {@link TransactionalAction} the
219
         * action will be execute inside of a DB transaction.
220
         *
221
         *
222
         * @param action
223
         * @throws Exception
224
         */
225
        public Object doConnectionAction(ConnectionAction action) throws Exception {
226
                Object result = null;
227
                Connection conn = null;
228
                boolean beginTrans = false;
229
                this.open();
230
                this.begin();
231
                try {
232

    
233
                        conn = this.getConnection();
234
                        if (action instanceof TransactionalAction) {
235
                                // XXX OJO esta condicion NO ES FIABLE
236
                                if (!conn.getAutoCommit()) {
237
                                        if (!((TransactionalAction) action)
238
                                                        .continueTransactionAllowed()) {
239
                                                // FIXME exception
240
                                                throw new Exception();
241
                                        }
242
                                }
243
                                try {
244
                                        conn.setAutoCommit(false);
245
                                } catch (SQLException e) {
246
                                        throw new JDBCSQLException(e);
247
                                }
248
                                beginTrans = true;
249
                        }
250

    
251
                        result = action.action(conn);
252

    
253
                        if (beginTrans) {
254
                                try {
255
                                        conn.commit();
256
                                } catch (SQLException e) {
257
                                        throw new JDBCTransactionCommitException(e);
258
                                }
259
                        }
260

    
261
                        return result;
262

    
263
                } catch (Exception e) {
264

    
265
                        if (beginTrans) {
266
                                try {
267
                                        conn.rollback();
268
                                } catch (Exception e1) {
269
                                        throw new JDBCTransactionRollbackException(e1, e);
270
                                }
271
                        }
272
                        throw e;
273

    
274
                } finally {
275
                        try {
276
                                conn.close();
277
                        } catch (Exception e1) {
278
                                logger.error("Exception on close connection", e1);
279
                        }
280
                        this.end();
281
                }
282

    
283
        }
284

    
285
        protected String getDefaultSchema(Connection conn) throws JDBCException {
286
                return defaultSchema;
287
        }
288

    
289
        protected EditableFeatureAttributeDescriptor createAttributeFromJDBC(
290
                        EditableFeatureType fType, Connection conn,
291
                        ResultSetMetaData rsMetadata, int colIndex)
292
                        throws java.sql.SQLException {
293

    
294
                EditableFeatureAttributeDescriptor column;
295
                switch (rsMetadata.getColumnType(colIndex)) {
296
                case java.sql.Types.INTEGER:
297
                        column = fType.add(rsMetadata.getColumnName(colIndex),
298
                                        DataTypes.INT);
299
                        break;
300
                case java.sql.Types.BIGINT:
301
                        column = fType.add(rsMetadata.getColumnName(colIndex),
302
                                        DataTypes.LONG);
303
                        break;
304
                case java.sql.Types.REAL:
305
                        column = fType.add(rsMetadata.getColumnName(colIndex),
306
                                        DataTypes.DOUBLE);
307
                        break;
308
                case java.sql.Types.DOUBLE:
309
                        column = fType.add(rsMetadata.getColumnName(colIndex),
310
                                        DataTypes.DOUBLE);
311
                        break;
312
                case java.sql.Types.CHAR:
313
                        column = fType.add(rsMetadata.getColumnName(colIndex),
314
                                        DataTypes.STRING);
315
                        break;
316
                case java.sql.Types.VARCHAR:
317
                case java.sql.Types.LONGVARCHAR:
318
                        column = fType.add(rsMetadata.getColumnName(colIndex),
319
                                        DataTypes.STRING);
320
                        break;
321
                case java.sql.Types.FLOAT:
322
                        column = fType.add(rsMetadata.getColumnName(colIndex),
323
                                        DataTypes.FLOAT);
324
                        break;
325
                case java.sql.Types.DECIMAL:
326
                        column = fType.add(rsMetadata.getColumnName(colIndex),
327
                                        DataTypes.FLOAT);
328
                        break;
329
                case java.sql.Types.DATE:
330
                        column = fType.add(rsMetadata.getColumnName(colIndex),
331
                                        DataTypes.DATE);
332
                        break;
333
                case java.sql.Types.TIME:
334
                        column = fType.add(rsMetadata.getColumnName(colIndex),
335
                                        DataTypes.TIME);
336
                        break;
337
                case java.sql.Types.TIMESTAMP:
338
                        column = fType.add(rsMetadata.getColumnName(colIndex),
339
                                        DataTypes.TIMESTAMP);
340
                        break;
341
                case java.sql.Types.BOOLEAN:
342
                        column = fType.add(rsMetadata.getColumnName(colIndex),
343
                                        DataTypes.BOOLEAN);
344
                        break;
345
                case java.sql.Types.BLOB:
346
                case java.sql.Types.BINARY:
347
                case java.sql.Types.LONGVARBINARY:
348
                        column = fType.add(rsMetadata.getColumnName(colIndex),
349
                                        DataTypes.BYTEARRAY);
350
                        break;
351

    
352
                default:
353
                        column = fType.add(rsMetadata.getColumnName(colIndex),
354
                                        DataTypes.OBJECT);
355
                        column.setAdditionalInfo("SQLType", new Integer(rsMetadata
356
                                        .getColumnType(colIndex)));
357
                        column.setAdditionalInfo("SQLTypeName", rsMetadata
358
                                        .getColumnTypeName(colIndex));
359

    
360
                        break;
361
                }
362

    
363
                return column;
364

    
365
        }
366

    
367
        protected EditableFeatureAttributeDescriptor getAttributeFromJDBC(
368
                        EditableFeatureType fType, Connection conn,
369
                        ResultSetMetaData rsMetadata, int colIndex) throws JDBCException {
370
                EditableFeatureAttributeDescriptor column;
371
                try {
372

    
373
                        column = createAttributeFromJDBC(fType, conn, rsMetadata, colIndex);
374
                        // column.setCaseSensitive(rsMetadata.isCaseSensitive(colIndex));
375
                        // column.setSqlType(rsMetadata.getColumnType(colIndex));
376
                        column.setAllowNull(
377
                                        rsMetadata.isNullable(colIndex) == ResultSetMetaData.columnNullable);
378
                        column.setIsAutomatic(rsMetadata.isAutoIncrement(colIndex));
379
                        column.setIsReadOnly(rsMetadata.isReadOnly(colIndex));
380
                        // column.setWritable(rsMetadata.isWritable(colIndex));
381
                        // column.setClassName(rsMetadata.getColumnClassName(colIndex));
382
                        // column.setCatalogName(rsMetadata.getCatalogName(colIndex));
383
                        // column.setDefinitelyWritable(rsMetadata
384
                        // .isDefinitelyWritable(colIndex));
385
                        // column.setLabel(rsMetadata.getColumnLabel(colIndex));
386
                        // column.setSchemaName(rsMetadata.getSchemaName(colIndex));
387
                        // column.setTableName(rsMetadata.getTableName(colIndex));
388
                        // column.setCatalogName(rsMetadata.getCatalogName(colIndex));
389
                        // column.setSqlTypeName();
390
                        // column.setSearchable(rsMetadata.isSearchable(colIndex));
391
                        // column.setSigned(rsMetadata.isSigned(colIndex));
392
                        // column.setCurrency(rsMetadata.isCurrency(colIndex));
393
                        column.setPrecision(rsMetadata.getPrecision(colIndex));
394
                        column.setSize(rsMetadata.getColumnDisplaySize(colIndex));
395

    
396
                } catch (java.sql.SQLException e) {
397
                        throw new JDBCSQLException(e);
398
                }
399

    
400
                return column;
401

    
402
        }
403

    
404
        /**
405
         * Fill <code>featureType</code> geometry attributes with SRS and ShapeType
406
         * information
407
         *
408
         * <b>Override this if provider has native eometry support</b>
409
         *
410
         * @param conn
411
         * @param rsMetadata
412
         * @param featureType
413
         * @throws ReadException
414
         */
415
        protected void loadSRS_and_shapeType(Connection conn,
416
                        ResultSetMetaData rsMetadata, EditableFeatureType featureType,
417
                        String baseSchema, String baseTable) throws JDBCException {
418

    
419
                // Nothing to do
420

    
421
        }
422

    
423
        public void loadFeatureType(EditableFeatureType featureType,
424
                        JDBCStoreParameters storeParams) throws DataException {
425
                if (storeParams.getSQL() != null
426
                                && storeParams.getSQL().trim().length() == 0) {
427
                        loadFeatureType(featureType, storeParams, storeParams.getSQL(),
428
                                        null, null);
429
                } else {
430
                        String sql = "Select * from " + storeParams.tableID()
431
                                        + " where false";
432
                        loadFeatureType(featureType, storeParams, sql, storeParams
433
                                        .getSchema(), storeParams.getTable());
434
                }
435
        }
436

    
437
        public void loadFeatureType(EditableFeatureType featureType,
438
                        JDBCStoreParameters storeParams, String sql, String schema,
439
                        String table) throws DataException {
440
                Connection conn = null;
441
                this.open();
442
                this.begin();
443
                try {
444
                        conn = getConnection();
445

    
446
                        String[] pks = storeParams.getPkFields();
447
                        if (pks == null || pks.length < 1) {
448
                                if (storeParams.getTable() != null
449
                                                && storeParams.getTable().trim().length() > 0) {
450
                                        pks = getPksFrom(conn, storeParams);
451

    
452
                                }
453
                        }
454

    
455
                        loadFeatureType(conn, featureType, sql, pks, storeParams
456
                                        .getDefaultGeometry(), schema, table);
457

    
458
                } finally {
459
                        try {
460
                                conn.close();
461
                        } catch (Exception e) {
462
                        }
463
                        ;
464
                        this.end();
465
                }
466
        }
467

    
468
        protected String[] getPksFrom(Connection conn, JDBCStoreParameters params)
469
                throws JDBCException {
470
                try{
471
                        DatabaseMetaData metadata = conn.getMetaData();
472
                        ResultSet rsPrimaryKeys = null;
473
                        ResultSet rs = null;
474
                        String catalog = params.getCatalog();
475
                        String schema = params.getSchema();
476

    
477
                        try{
478
                                rs = metadata.getTables(catalog,
479
                                                schema, params.getTable(), null);
480

    
481
                                if (!rs.next()) {
482
                                        // No tables found with default values, ignoring catalog
483
                                        rs.close();
484
                                        catalog = null;
485
                                        schema = null;
486
                                        rs = metadata
487
                                                        .getTables(catalog, schema, params.getTable(), null);
488

    
489
                                        if (!rs.next()) {
490
                                                // table not found
491
                                                return null;
492
                                        } else if (rs.next()){
493
                                                // More that one, cant identify
494
                                                return null;
495
                                        }
496

    
497
                                } else if (rs.next()) {
498
                                        // More that one, cant identify
499
                                        return null;
500
                                }
501
                                rsPrimaryKeys = metadata.getPrimaryKeys(catalog, schema, params
502
                                                .getTable());
503
                                List pks = new ArrayList();
504
                                while (rsPrimaryKeys.next()){
505
                                        pks.add(rsPrimaryKeys.getString("COLUMN_NAME"));
506
                                }
507
                                return (String[]) pks.toArray(new String[pks.size()]);
508

    
509

    
510
                        } finally {
511
                                try{if (rs != null) {
512
                                        rs.close();
513
                                }} catch (SQLException ex) {logger.warn("Exception closing tables rs", ex);};
514
                                try{if (rsPrimaryKeys != null) {
515
                                        rsPrimaryKeys.close();
516
                                }} catch (SQLException ex) {logger.warn("Exception closing pk rs", ex);};
517
                        }
518

    
519

    
520
                } catch (SQLException e) {
521
                        logger.warn("Unable to get pk from DatabaseMetada", e);
522
                        return getPksFromInformationSchema(conn, params);
523
                }
524

    
525
        }
526

    
527
        protected String[] getPksFromInformationSchema(Connection conn,
528
                        JDBCStoreParameters params)
529
                        throws JDBCException {
530
                Statement st;
531
                StringBuffer sql = new StringBuffer();
532
                ResultSet rs;
533
                ArrayList list = new ArrayList();
534

    
535
                /*
536
                 select column_name as primary_key
537
                        from information_schema.table_constraints t_cons
538
                                inner join information_schema.key_column_usage c on
539
                                        c.constraint_catalog = t_cons.table_catalog and
540
                                    c.table_schema = t_cons.table_schema and
541
                                    c.table_name = t_cons.table_name and
542
                                        c.constraint_name = t_cons.constraint_name
543
                                where t_cons.table_schema = <schema>
544
                                and t_cons.constraint_catalog = <catalog>
545
                                 and t_cons.table_name = <table>
546
                                 and constraint_type = 'PRIMARY KEY'
547
                 */
548
                /*
549
                 * SELECT column_name FROM INFORMATION_SCHEMA.constraint_column_usage
550
                 * left join INFORMATION_SCHEMA.table_constraints on
551
                 * (INFORMATION_SCHEMA.table_constraints.constraint_name =
552
                 * INFORMATION_SCHEMA.constraint_column_usage.constraint_name and
553
                 * INFORMATION_SCHEMA.table_constraints.table_name =
554
                 * INFORMATION_SCHEMA.constraint_column_usage.table_name and
555
                 * INFORMATION_SCHEMA.table_constraints.table_schema =
556
                 * INFORMATION_SCHEMA.constraint_column_usage.table_schema) WHERE
557
                 * INFORMATION_SCHEMA.constraint_column_usage.table_name like
558
                 * 'muni10000_peq' AND
559
                 * INFORMATION_SCHEMA.constraint_column_usage.table_schema like 'public'
560
                 * AND INFORMATION_SCHEMA.constraint_column_usage.table_catalog like
561
                 * 'gis' AND constraint_type='PRIMARY KEY'
562
                 */
563

    
564
                sql.append("select column_name as primary_key ");
565
                sql.append("from information_schema.table_constraints t_cons ");
566
                sql.append("inner join information_schema.key_column_usage c on ");
567
                sql.append("c.constraint_catalog = t_cons.constraint_catalog and ");
568
                sql.append("c.table_schema = t_cons.table_schema and ");
569
                sql.append("c.table_name = t_cons.table_name and ");
570
                sql.append("c.constraint_name = t_cons.constraint_name ");
571
                sql.append("WHERE t_cons.table_name like '");
572

    
573
                sql.append(params.getTable());
574
                sql.append("' ");
575
                String schema = null;
576

    
577

    
578
                if (params.getSchema() == null || params.getSchema() == "") {
579
                        schema = getDefaultSchema(conn);
580
                } else {
581
                        schema = params.getSchema();
582
                }
583
                if (schema != null) {
584
                        sql.append(" and t_cons.table_schema like '");
585
                        sql.append(schema);
586
                        sql.append("' ");
587
                }
588

    
589
                if (params.getCatalog() != null && params.getCatalog() != "") {
590
                        sql
591
                                        .append(" and t_cons.constraint_catalog like '");
592
                        sql.append(params.getCatalog());
593
                        sql.append("' ");
594
                }
595

    
596
                sql.append("' and constraint_type = 'PRIMARY KEY'");
597

    
598
                // System.out.println(sql.toString());
599
                try {
600
                        st = conn.createStatement();
601
                        try {
602
                                rs = st.executeQuery(sql.toString());
603
                        } catch (java.sql.SQLException e) {
604
                                throw new JDBCExecuteSQLException(sql.toString(), e);
605
                        }
606
                        while (rs.next()) {
607
                                list.add(rs.getString(1));
608
                        }
609
                        rs.close();
610
                        st.close();
611

    
612
                } catch (java.sql.SQLException e) {
613
                        throw new JDBCSQLException(e);
614
                }
615
                if (list.size() == 0) {
616
                        return null;
617
                }
618

    
619
                return (String[]) list.toArray(new String[0]);
620

    
621
        }
622

    
623
        protected void loadFeatureType(Connection conn,
624
                        EditableFeatureType featureType, String sql, String[] pks,
625
                        String defGeomName, String schema, String table)
626
                        throws DataException {
627

    
628
                Statement stAux = null;
629
                ResultSet rs = null;
630
                try {
631

    
632
                        stAux = conn.createStatement();
633
                        stAux.setFetchSize(1);
634

    
635
                        try {
636
                                rs = stAux.executeQuery(sql);
637
                        } catch (SQLException e) {
638
                                throw new JDBCExecuteSQLException(sql, e);
639
                        }
640
                        ResultSetMetaData rsMetadata = rs.getMetaData();
641

    
642
                        List pksList = null;
643
                        if (pks != null) {
644
                                pksList = Arrays.asList(pks);
645

    
646
                        }
647

    
648
                        int i;
649
                        int geometriesColumns = 0;
650
                        String lastGeometry = null;
651

    
652
                        EditableFeatureAttributeDescriptor attr;
653
                        for (i = 1; i <= rsMetadata.getColumnCount(); i++) {
654
                                attr = getAttributeFromJDBC(featureType, conn, rsMetadata, i);
655
                                if (pksList != null && pksList.contains(attr.getName())) {
656
                                        attr.setIsPrimaryKey(true);
657
                                }
658
                                if (attr.getDataType() == DataTypes.GEOMETRY) {
659
                                        geometriesColumns++;
660
                                        lastGeometry = attr.getName();
661
                                        if (lastGeometry.equals(defGeomName)) {
662
                                                featureType
663
                                                                .setDefaultGeometryAttributeName(defGeomName);
664
                                        }
665

    
666
                                }
667

    
668
                        }
669

    
670
                        if (geometriesColumns > 0) {
671
                                loadSRS_and_shapeType(conn, rsMetadata, featureType, schema,
672
                                                table);
673
                        }
674

    
675
                        if (defGeomName == null && geometriesColumns == 1) {
676
                                featureType.setDefaultGeometryAttributeName(lastGeometry);
677
                                defGeomName = lastGeometry;
678
                        }
679

    
680
                } catch (java.sql.SQLException e) {
681
                        throw new JDBCSQLException(e); // FIXME exception
682
                } finally {
683
                        try {
684
                                rs.close();
685
                        } catch (Exception e) {
686
                        }
687
                        try {
688
                                stAux.close();
689
                        } catch (Exception e) {
690
                        }
691

    
692
                }
693

    
694
        }
695

    
696
        /**
697
         * Override if provider has geometry support
698
         *
699
         * @param storeParams
700
         * @param geometryAttrName
701
         * @param limit
702
         * @return
703
         * @throws DataException
704
         */
705
        public Envelope getFullEnvelopeOfField(JDBCStoreParameters storeParams,
706
                        String geometryAttrName, Envelope limit) throws DataException {
707

    
708
                // TODO
709
                return null;
710

    
711
        }
712

    
713
        protected void initializeFromWKBOperation() throws BaseException {
714
                if (fromWKB == null) {
715
                        fromWKB = (FromWKB) GeometryLocator.getGeometryManager()
716
                                        .getGeometryOperation(FromWKB.CODE,
717
                                                        Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2D);
718
                        fromWKBContext = new FromWKBGeometryOperationContext();
719

    
720
                }
721
        }
722

    
723
        public Geometry getGeometry(byte[] buffer) throws BaseException {
724
                if (buffer == null) {
725
                        return null;
726
                }
727
                initializeFromWKBOperation();
728
                Geometry geom;
729
                try {
730
                        fromWKBContext.setData(buffer);
731

    
732
                        geom = (Geometry) fromWKB.invoke(null, fromWKBContext);
733
                } finally {
734
                        fromWKBContext.setData(null);
735
                }
736
                return geom;
737
        }
738

    
739
        public String escapeFieldName(String field) {
740
                return field;
741
        }
742

    
743
        public Object dalValueToJDBC(
744
                        FeatureAttributeDescriptor attributeDescriptor, Object object)
745
                        throws WriteException {
746
                if (object == null) {
747
                        return null;
748
                }
749

    
750
                if (attributeDescriptor.getDataType() != DataTypes.GEOMETRY) {
751
                        return object;
752
                }
753
                try {
754
                        Geometry geom = (Geometry) object;
755

    
756
                        toWKBContext.setSrID(-1);
757
                        IProjection srs = attributeDescriptor.getSRS();
758
                        if (srs != null) {
759
                                toWKBContext.setSrID(getProviderSRID(srs));
760
                        }
761

    
762
                        // TODO optimize this
763
                        // byte[] wkb = (byte[])
764
                        // geom.invokeOperation(ToWKBNative.CODE,toWKBContext);
765
                        byte[] wkb = (byte[]) geom.invokeOperation(ToWKB.CODE,
766
                                        toWKBContext);
767
                        if (wkb == null) {
768
                                // FIXME excpetion
769
                                throw new IllegalArgumentException();
770
                        }
771

    
772
                        return wkb;
773
                } catch (Exception e) {
774
                        throw new WriteException(this.name, e);
775
                }
776
        }
777

    
778
        public String getSqlColumnTypeDescription(FeatureAttributeDescriptor attr) {
779
                switch (attr.getDataType()) {
780
                case DataTypes.STRING:
781
                        if (attr.getSize() < 1 || attr.getSize() > 255) {
782
                                return "text";
783
                        } else {
784
                                return "varchar(" + attr.getSize() + ")";
785
                        }
786
                case DataTypes.BOOLEAN:
787
                        return "bool";
788

    
789
                case DataTypes.BYTE:
790
                        return "smallint";
791

    
792
                case DataTypes.DATE:
793
                        return "date";
794

    
795
                case DataTypes.TIMESTAMP:
796
                        return "timestamp";
797

    
798
                case DataTypes.TIME:
799
                        return "time";
800

    
801
                case DataTypes.BYTEARRAY:
802
                case DataTypes.GEOMETRY:
803
                        return "blob";
804

    
805
                case DataTypes.DOUBLE:
806
                        // if (attr.getPrecision() > 0) {
807
                        // return "double precision(" + attr.getPrecision() + ')';
808
                        // } else {
809
                        return "double";
810
                        // }
811
                case DataTypes.FLOAT:
812
                        return "real";
813

    
814
                case DataTypes.INT:
815
                        if (attr.isAutomatic() && allowAutomaticValues()) {
816
                                return "serial";
817
                        } else {
818
                                return "integer";
819
                        }
820
                case DataTypes.LONG:
821
                        if (attr.isAutomatic()) {
822
                                return "bigserial";
823
                        } else {
824
                                return "bigint";
825
                        }
826

    
827
                default:
828
                        String typeName = (String) attr.getAdditionalInfo("SQLTypeName");
829
                        if (typeName != null) {
830
                                return typeName;
831
                        }
832

    
833
                        throw new UnsupportedDataTypeException(attr.getDataTypeName(), attr
834
                                        .getDataType());
835
                }
836
        }
837

    
838
        public int getProviderSRID(String srs) {
839
                return -1;
840
        }
841

    
842
        public int getProviderSRID(IProjection srs) {
843
                return -1;
844
        }
845

    
846
        public String getSqlFieldName(FeatureAttributeDescriptor attribute) {
847
                return escapeFieldName(attribute.getName());
848
        }
849

    
850
        public String getSqlFieldDescription(FeatureAttributeDescriptor attr)
851
                        throws DataException {
852

    
853
                /**
854
                 * column_name data_type [ DEFAULT default_expr ] [ column_constraint [
855
                 * ... ] ]
856
                 *
857
                 * where column_constraint is:
858
                 *
859
                 * [ CONSTRAINT constraint_name ] { NOT NULL | NULL | UNIQUE | PRIMARY
860
                 * KEY | CHECK (expression) | REFERENCES reftable [ ( refcolumn ) ] [
861
                 * MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE action ] [ ON
862
                 * UPDATE action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY
863
                 * DEFERRED | INITIALLY IMMEDIATE ]
864
                 */
865

    
866
                StringBuilder strb = new StringBuilder();
867
                // name
868
                strb.append(escapeFieldName(attr.getName()));
869
                strb.append(" ");
870

    
871
                // Type
872
                strb.append(this.getSqlColumnTypeDescription(attr));
873
                strb.append(" ");
874

    
875
                boolean allowNull = attr.allowNull()
876
                                && !(attr.isPrimaryKey() || attr.isAutomatic());
877
                // Default
878
                if (attr.getDefaultValue() == null) {
879
                        if (allowNull) {
880
                                strb.append("DEFAULT NULL ");
881
                        }
882
                } else {
883
                        String value = getDefaltFieldValueString(attr);
884
                        strb.append("DEFAULT '");
885
                        strb.append(value);
886
                        strb.append("' ");
887
                }
888

    
889
                // Null
890
                if (allowNull) {
891
                        strb.append("NULL ");
892
                } else {
893
                        strb.append("NOT NULL ");
894
                }
895

    
896
                // Primery key
897
                if (attr.isPrimaryKey()) {
898
                        strb.append("PRIMARY KEY ");
899
                }
900
                return strb.toString();
901
        }
902

    
903
        protected String getDefaltFieldValueString(FeatureAttributeDescriptor attr)
904
                        throws WriteException {
905
                return dalValueToJDBC(attr, attr.getDefaultValue()).toString();
906
        }
907

    
908
        public String compoundLimitAndOffset(long limit, long offset) {
909
                StringBuilder sql = new StringBuilder();
910
                // limit
911
                if (limit >= 1) {
912
                        sql.append(" limit ");
913
                        sql.append(limit);
914
                        sql.append(' ');
915
                }
916

    
917
                // offset
918
                if (offset >= 1) {
919
                        sql.append(" offset ");
920
                        sql.append(offset);
921
                        sql.append(' ');
922
                }
923
                return sql.toString();
924
        }
925

    
926
        public boolean supportOffset() {
927
                return true;
928
        }
929

    
930
        public List getAdditionalSqlToCreate(NewDataStoreParameters ndsp,
931
                        FeatureType fType) {
932
                // TODO Auto-generated method stub
933
                return null;
934
        }
935

    
936

    
937
        public String stringJoin(List listToJoin,String sep){
938
                StringBuilder strb = new StringBuilder();
939
                stringJoin(listToJoin,sep,strb);
940
                return strb.toString();
941
        }
942

    
943
        public void stringJoin(List listToJoin, String sep, StringBuilder strb) {
944
                if (listToJoin.size() < 1) {
945
                        return;
946
                }
947
                if (listToJoin.size() > 1) {
948
                        for (int i = 0; i < listToJoin.size() - 1; i++) {
949
                                strb.append(listToJoin.get(i));
950
                                strb.append(sep);
951
                        }
952
                }
953
                strb.append(listToJoin.get(listToJoin.size() - 1));
954
        }
955
        /**
956
         * Inform that provider has supports for geometry store and operations
957
         * natively
958
         *
959
         * @return
960
         */
961
        boolean hasGeometrySupport() {
962
                return false;
963
        }
964

    
965
        public boolean allowAutomaticValues() {
966
                if (allowAutomaticValues == null) {
967
                        ConnectionAction action = new ConnectionAction(){
968

    
969
                                public Object action(Connection conn) throws DataException {
970

    
971
                                        ResultSet rs;
972
                                        try {
973
                                                DatabaseMetaData meta = conn.getMetaData();
974
                                                rs = meta.getTypeInfo();
975
                                                try{
976
                                                        while (rs.next()) {
977
                                                                if (rs.getInt("DATA_TYPE") == java.sql.Types.INTEGER) {
978
                                                                        if (rs.getBoolean("AUTO_INCREMENT")) {
979
                                                                                return Boolean.TRUE;
980
                                                                        } else {
981
                                                                                return Boolean.FALSE;
982
                                                                        }
983
                                                                }
984
                                                        }
985
                                                }finally{
986
                                                        try{ rs.close();} catch (SQLException ex) {logger.error("Exception closing resulset", ex);};
987
                                                }
988
                                        } catch (SQLException e) {
989
                                                throw new JDBCSQLException(e);
990
                                        }
991
                                        return Boolean.FALSE;
992
                                }
993

    
994
                        };
995

    
996

    
997

    
998
                        try {
999
                                allowAutomaticValues = (Boolean) doConnectionAction(action);
1000
                        } catch (Exception e) {
1001
                                logger.error("Exception checking for automatic integers", e);
1002
                                allowAutomaticValues = Boolean.FALSE;
1003
                        }
1004
                }
1005
                return allowAutomaticValues.booleanValue();
1006
        }
1007
}