Statistics
| Revision:

gvsig-oracle / org.gvsig.oracle / trunk / org.gvsig.oracle / org.gvsig.oracle.provider / src / main / java / org / gvsig / oracle / dal / OracleSQLBuilder.java @ 63

History | View | Annotate | Download (15.9 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
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 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.oracle.dal;
25

    
26
import java.text.MessageFormat;
27
import java.util.ArrayList;
28
import java.util.List;
29
import org.apache.commons.lang3.StringUtils;
30
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
31
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
32

    
33
public class OracleSQLBuilder extends JDBCSQLBuilderBase {
34

    
35
    private final JDBCHelper helper;
36

    
37
    public OracleSQLBuilder(JDBCHelper helper) {
38
        super();
39

    
40
        this.helper = helper;
41
        
42
        config.set(SQLConfig.default_schema, "");
43
        config.set(SQLConfig.allowAutomaticValues, true);
44
        config.set(SQLConfig.geometry_type_support, this.helper.getGeometrySupportType());
45
        config.set(SQLConfig.has_spatial_functions, this.helper.hasSpatialFunctions());
46
        config.set(SQLConfig.constant_true, "TRUE");
47
        config.set(SQLConfig.constant_false, "FALSE");
48
        config.set(SQLConfig.quote_for_identifiers, "\"");
49
        config.set(SQLConfig.quote_for_strings, "\'");
50
        config.set(SQLConfig.group, "( {0} )");
51

    
52
        config.set(SQLConfig.ST_SRID, "(({0}).SDO_SRID)");
53
        config.set(SQLConfig.ST_AsText, "({0}).Get_WKT()");
54
        config.set(SQLConfig.ST_AsBinary, "({0}).Get_WKB()");
55
        config.set(SQLConfig.ST_AsEWKB, "({0}).Get_WKB()");
56
        config.set(SQLConfig.ST_Contains, "(SDO_RELATE(({1}), ({0}), ''mask=CONTAINS+COVER'') = ''TRUE'')");
57
        config.remove_functionality(SQLConfig.ST_Crosses);
58
        config.set(SQLConfig.ST_Disjoint, "(SDO_RELATE(({1}), ({0}), ''mask=ANYINTERACT'') = ''FALSE'')");
59
        config.set(SQLConfig.ST_Equals, "(SDO_RELATE(({1}), ({0}), ''mask=EQUAL'') = ''TRUE'')");
60
        config.set(SQLConfig.ST_IsClosed, "ST_IsClosed({0})");
61
        config.set(SQLConfig.ST_Overlaps, "SDO_OVERLAPS(({0}))");
62
        config.set(SQLConfig.ST_Touches, "(SDO_RELATE(({0}), ''mask=TOUCH'') = ''TRUE'')");
63
        config.set(SQLConfig.ST_Within, "(SDO_RELATE(({1}), ({0}), ''mask=INSIDE+COVERERBY'') = ''TRUE'')");
64
        config.set(SQLConfig.ST_Envelope, "SDO_MBR({0})");
65
        config.set(SQLConfig.ST_Intersects, "(SDO_RELATE({1}, {0}, ''mask=ANYINTERACT'') = ''TRUE'')");
66
        config.set(SQLConfig.ST_GeomFromText, "SDO_GEOMETRY({0},{1})");
67
        config.set(SQLConfig.ST_GeomFromWKB, "SDO_GEOMETRY(TO_BLOB({0}),{1})");
68
        config.set(SQLConfig.ST_GeomFromEWKB, "SDO_GEOMETRY(TO_BLOB({0}),{1})");
69
        config.set(SQLConfig.lcase, "LOWER({0})");
70
        config.set(SQLConfig.ucase, "UPPER({0})");
71
        config.set(SQLConfig.isNull, "( ({0}) IS NULL)");
72
        config.set(SQLConfig.notIsNull, "( (({0}) IS NOT NULL) )");
73
        config.set(SQLConfig.operator_not, "( NOT ({0}) )");
74

    
75
        config.set(SQLConfig.operator_AND,"( ({0}) AND ({1}) )");
76
        config.set(SQLConfig.operator_OR, "( ({0}) OR ({1}) )");
77
        config.set(SQLConfig.operator_EQ, "( ({0}) = ({1}) )");
78
        config.set(SQLConfig.operator_NE, "( ({0}) != ({1}) )");
79
        config.set(SQLConfig.operator_GT, "( ({0}) > ({1}) )");
80
        config.set(SQLConfig.operator_GE, "( ({0}) >= ({1}) )");
81
        config.set(SQLConfig.operator_LT, "( ({0}) < ({1}) )");
82
        config.set(SQLConfig.operator_LE, "( ({0}) <= ({1}) )");
83
        config.set(SQLConfig.operator_LIKE, "( ({0}) LIKE ({1}) )");
84
        config.set(SQLConfig.operator_ILIKE, "( LOWER({0}) LIKE LOWER({1}) )");
85

    
86
        config.set(SQLConfig.operator_add, "{0} + {1}");
87
        config.set(SQLConfig.operator_subst, "{0} - {1}");
88
        config.set(SQLConfig.operator_mult, "{0} * {1}");
89
        config.set(SQLConfig.operator_div, "{0} / {1}");
90
        config.set(SQLConfig.operator_concat, "{0} + {1}");
91

    
92
        config.set(SQLConfig.ST_ExtentAggregate, "SDO_AGGR_MBR({0})");
93
        config.set(SQLConfig.ST_UnionAggregate, "SDO_AGGR_UNION({0})");
94
        config.set(SQLConfig.count, "COUNT({0})");
95
        config.set(SQLConfig.count_distinct, "COUNT(DISTINCT {0})");
96

    
97
        config.set(SQLConfig.type_boolean, "BYTE");
98
        config.set(SQLConfig.type_byte, "BYTE");
99
        config.set(SQLConfig.type_bytearray, "VARBINARY");
100
        config.set(SQLConfig.type_geometry, "SDO_GEOMETRY");
101
        config.set(SQLConfig.type_char, "CHARACTER(1)");
102
        config.set(SQLConfig.type_date, "TIMESTAMP");
103
        config.set(SQLConfig.type_double, "BINARY_DOUBLE"); //float con 53 bits de mantisa, float(54)
104
        config.set(SQLConfig.type_numeric_p, "NUMBER({0})");
105
        config.set(SQLConfig.type_numeric_ps, "NUMBER({0},{1})");
106
        config.set(SQLConfig.type_bigdecimal, "NUMBER({0},{1})");
107
        config.set(SQLConfig.type_float, "BINARY_FLOAT"); //float con 24 bits de mantisa, float(24)
108
        config.set(SQLConfig.type_int, "NUMBER(10,0)");
109
        config.set(SQLConfig.type_long, "NUMBER(*,0)");
110
        config.set(SQLConfig.type_string, "VARCHAR");
111
        config.set(SQLConfig.type_string_p, "VARCHAR({0})");
112
        config.set(SQLConfig.type_time, "TIME");
113
        config.set(SQLConfig.type_timestamp, "TIMESTAMP");
114
        config.set(SQLConfig.type_version, "VARCHAR(30)");
115
        config.set(SQLConfig.type_URI, "VARCHAR");
116
        config.set(SQLConfig.type_URL, "VARCHAR");
117
        config.set(SQLConfig.type_FILE, "VARCHAR");
118
        config.set(SQLConfig.type_FOLDER, "VARCHAR");
119

    
120
        config.set(SQLConfig.DELETE_FROM_table_WHERE_expresion, "DELETE FROM {0} WHERE {1}");
121
        config.set(SQLConfig.DELETE_FROM_table, "DELETE FROM {0}");
122
        config.set(SQLConfig.INSERT_INTO_table_columns_VALUES_values, "INSERT INTO {0} ( {1} ) VALUES ( {2} )");
123
        config.set(SQLConfig.UPDATE_TABLE_STATISTICS_table, "VACUUM ANALYZE {0}");
124
        config.set(SQLConfig.DROP_TABLE_table, "DROP TABLE {0}");
125
        config.remove_functionality(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table);
126
        config.remove_functionality(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table);
127
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues_WHERE_expresion, "UPDATE {0} SET {1} WHERE {2}");
128
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues, "UPDATE {0} SET {1}");
129
        config.set(SQLConfig.GRANT_privileges_ON_table_TO_role, "GRANT {0} ON {1} TO {2}");
130
        config.set(SQLConfig.CREATE_INDEX_name_ON_table_column, "CREATE INDEX {0} ON {1} ({2})");
131
        config.set(SQLConfig.CREATE_INDEX_name_ON_table_USING_GIST_column, "CREATE INDEX {0} ON {1}({2}) INDEXTYPE IS MDSYS.SPATIAL_INDEX");
132
        
133
        config.remove_functionality(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table);
134
        config.remove_functionality(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table);
135

    
136
    }
137
    
138
    @Override
139
    public String default_schema() {
140
        if( this.helper.getConnectionParameters()!=null && 
141
            !StringUtils.isEmpty(this.helper.getConnectionParameters().getUser())
142
            ) {
143
            return this.helper.getConnectionParameters().getUser();
144
        }
145
        return config.getString(SQLConfig.default_schema);
146
    }
147
    
148
    public class OracleUpdateTableStatisticsBuilderBase extends UpdateTableStatisticsBuilderBase {
149

    
150
        @Override
151
        public List<String> toStrings() {
152
            List<String> sqls = new ArrayList<>();
153

    
154
            if( config.has_functionality(SQLConfig.UPDATE_TABLE_STATISTICS_table) ) {
155
                String name = identifier(this.table.getName());
156
                if( table.has_schema() ) {
157
                    name = identifier(this.table.getSchema()) + "." + name;
158
                }
159
                String sql = MessageFormat.format(
160
                    config.getString(SQLConfig.UPDATE_TABLE_STATISTICS_table),
161
                    name
162
                );
163
                if( !StringUtils.isEmpty(sql) ) {
164
                    sqls.add(sql);
165
                }
166
            }
167
            return sqls;
168
        }
169
    }
170

    
171
    protected class OracleCreateTableBuilder extends CreateTableBuilderBase {
172

    
173
        @Override
174
        public List<String> toStrings() {
175

    
176
            List<String> sqls = new ArrayList<>();
177
            StringBuilder builder = new StringBuilder();
178

    
179
            builder.append("CREATE TABLE ");
180
            builder.append(this.table.toString());
181
            builder.append(" (");
182
            boolean first = true;
183
            for( ColumnDescriptorBuilder column : columns ) {
184
                if( column.isGeometry() ) {
185
                    continue;
186
                }
187
                if( first ) {
188
                    first = false;
189
                } else {
190
                    builder.append(", ");
191
                }
192
                builder.append(identifier(column.getName()));
193
                builder.append(" ");
194
                if( column.isAutomatic() ) {
195
                    builder.append(" SERIAL");
196
                } else {
197
                    builder.append(sqltype(column.getType(), column.getPrecision(), column.getSize()));
198
                    if( column.getDefaultValue() == null ) {
199
                        if( column.allowNulls() ) {
200
                            builder.append(" DEFAULT NULL");
201
                        }
202
                    } else {
203
                        builder.append(" DEFAULT '");
204
                        builder.append(column.getDefaultValue().toString());
205
                        builder.append("'");
206
                    }
207
                    if( column.allowNulls() ) {
208
                        builder.append(" NULL");
209
                    } else {
210
                        builder.append(" NOT NULL");
211
                    }
212
                }
213
                if( column.isPrimaryKey() ) {
214
                    builder.append(" PRIMARY KEY");
215
                }
216
            }
217
            builder.append(" )");
218
            sqls.add(builder.toString());
219

    
220
            String AddGeometryColumn1 = "ALTER TABLE {0} ADD {1} MDSYS.SDO_GEOMETRY";
221
//            String AddGeometryColumn2 = "INSERT INTO USER_SDO_GEOM_METADATA  VALUES ('{0}', '{1}', MDSYS.SDO_DIM_ARRAY(MDSYS.SDO_DIM_ELEMENT('X', 0, 20, 0.005),    MDSYS.SDO_DIM_ELEMENT('Y', 0, 20, 0.005)), the_srid )";
222
            for( ColumnDescriptorBuilderBase column : columns ) {
223
                if( column.isGeometry() ) {
224
                    String sql = MessageFormat.format(
225
                        AddGeometryColumn1,
226
                        this.table.toString(),
227
                        column.getName()
228
                    );
229
                    sqls.add(sql);
230
                }
231
            }
232
            for( ColumnDescriptorBuilderBase column : columns ) {
233
                if( column.isIndexed() ) {
234
                    String sql;
235
                    String name = "idx_" + this.table().getName() + column.getName();
236
                    if( column.isGeometry() ) {
237
//                        sql = MessageFormat.format(
238
//                            config.getString(SQLConfig.CREATE_INDEX_name_ON_table_USING_GIST_column),
239
//                            name,
240
//                            this.table().toString(),
241
//                            column.getName()
242
//                        );
243
//                        sqls.add(sql);
244
                    } else {
245
                        sql = MessageFormat.format(
246
                            config.getString(SQLConfig.CREATE_INDEX_name_ON_table_column),
247
                            name,
248
                            this.table().toString(),
249
                            column.getName()
250
                        );
251
                        sqls.add(sql);
252
                    }
253
                }
254
            }
255
            return sqls;
256
        }
257
    }
258

    
259
    public class OracleSelectBuilderBase extends SelectBuilderBase {
260

    
261
        protected StringBuilder appendMainClause(StringBuilder builder) {
262
            builder.append("SELECT ");
263
            if( this.distinct ) {
264
                builder.append("DISTINCT ");
265
            }
266
            boolean first = true;
267
            for( SelectColumnBuilder column : columns ) {
268
                if( first ) {
269
                    first = false;
270
                } else {
271
                    builder.append(", ");
272
                }
273
                builder.append(column.toString());
274
            }
275

    
276
            if( this.has_from() ) {
277
                builder.append(" FROM ");
278
                builder.append(this.from.toString());
279
            }
280
            if( this.has_where() ) {
281
                builder.append(" WHERE ");
282
                builder.append(this.where.toString());
283
            }
284

    
285
            if( this.has_order_by() ) {
286
                builder.append(" ORDER BY ");
287
                first = true;
288
                for( OrderByBuilder item : this.order_by ) {
289
                    if( first ) {
290
                        first = false;
291
                    } else {
292
                        builder.append(", ");
293
                    }
294
                    builder.append(item.toString());
295
                }
296
            }
297
            return builder;
298
        }
299

    
300
        @Override
301
        public String toString() {
302
            StringBuilder builder = new StringBuilder();
303
            if( !isValid(builder) ) {
304
                throw new IllegalStateException(builder.toString());
305
            }
306
            if (this.has_offset() || this.has_limit()) {
307
                    /**
308
                     *  Using ROWNUM for limit & offset, compatible with any Oracle version
309
                                 *        This requires wrapping the original query as shown in the example:
310
                         *     select * from (
311
                         *              select a.*, ROWNUM rnum from (
312
                                 *                  <select statement with order by clause>
313
                                 *              ) a where ROWNUM <= MAX_ROW
314
                                 *     ) where rnum >= MIN_ROW
315
                                 *  because ROWNUM is considered before applying order by and group by
316
                     */
317
                builder.append("SELECT * FROM ( ");
318
                if (this.has_offset()) {
319
                        builder.append("SELECT a.*, ROWNUM rnum FROM (");
320
                }
321
                    this.appendMainClause(builder);
322
                    builder.append(") a");
323
                    if (this.has_limit()) {
324
                            builder.append(" WHERE ROWNUM <= ");
325
                            builder.append(this.limit);
326
                    }
327
                    if (this.has_offset()) {
328
                            builder.append(" )");
329
                            builder.append(" WHERE rnum >= ");
330
                        builder.append(this.offset);
331
                    }
332
            }
333
            else {
334
                    this.appendMainClause(builder);
335
            }
336
            return builder.toString();
337
        }
338
    }
339

    
340
    protected TableNameBuilder createTableNameBuilder() {
341
        return new OracleTableNameBuilder();
342
    }
343
    
344
    @Override
345
    public String bytearray(byte[] data) {
346
            return new StringBuilder("HEXTORAW('").append(bytearray_hex(data)).append("')").toString();
347
    }
348

    
349
    @Override
350
    protected CreateTableBuilder createCreateTableBuilder() {
351
        return new OracleCreateTableBuilder();
352
    }
353

    
354
    @Override
355
    protected SelectBuilder createSelectBuilder() {
356
        return new OracleSelectBuilderBase();
357
    }
358

    
359
    @Override
360
    protected UpdateTableStatisticsBuilder createUpdateTableStatisticsBuilder() {
361
        return new OracleUpdateTableStatisticsBuilderBase();
362
    }
363
    
364
    protected class OracleTableNameBuilder extends TableNameBuilderBase {
365
        @Override
366
        public String toString() {
367
            if( this.has_schema()) {
368
                return identifier(this.schemaName) + "." + 
369
                       identifier(this.tableName);
370
            }
371
            return identifier(this.tableName);
372
        }
373
    }
374

    
375
}