gvsig-oracle / org.gvsig.oracle / trunk / org.gvsig.oracle / org.gvsig.oracle.provider / src / main / java / org / gvsig / oracle / dal / OracleSQLBuilder.java @ 915
History | View | Annotate | Download (51.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.io.ByteArrayInputStream; |
27 |
import java.io.IOException; |
28 |
import java.io.InputStream; |
29 |
import java.io.OutputStream; |
30 |
import java.sql.Connection; |
31 |
import java.sql.PreparedStatement; |
32 |
import java.sql.SQLException; |
33 |
import java.sql.Time; |
34 |
import java.sql.Timestamp; |
35 |
import java.text.MessageFormat; |
36 |
import java.util.ArrayList; |
37 |
import java.util.List; |
38 |
import java.util.Objects; |
39 |
import oracle.sql.BLOB; |
40 |
import org.apache.commons.dbcp.DelegatingConnection; |
41 |
import org.apache.commons.lang3.BooleanUtils; |
42 |
import org.apache.commons.lang3.StringUtils; |
43 |
import org.apache.commons.lang3.tuple.Pair; |
44 |
import org.gvsig.expressionevaluator.DelegatedGeometryExpressionBuilder; |
45 |
import org.gvsig.expressionevaluator.ExpressionBuilder; |
46 |
import static org.gvsig.expressionevaluator.ExpressionBuilder.PARAMETER_TYPE_CONSTANT; |
47 |
import static org.gvsig.expressionevaluator.ExpressionBuilder.PARAMETER_TYPE_VARIABLE; |
48 |
import static org.gvsig.expressionevaluator.ExpressionBuilder.VALUE_NULL; |
49 |
import org.gvsig.expressionevaluator.ExpressionUtils; |
50 |
import org.gvsig.expressionevaluator.Formatter; |
51 |
import org.gvsig.expressionevaluator.GeometryExpressionBuilder; |
52 |
import org.gvsig.expressionevaluator.GeometryExpressionBuilderHelper.GeometrySupportType; |
53 |
import static org.gvsig.expressionevaluator.GeometryExpressionBuilderHelper.GeometrySupportType.WKT; |
54 |
import org.gvsig.fmap.dal.DataTypes; |
55 |
import org.gvsig.fmap.dal.SQLBuilder; |
56 |
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
57 |
import org.gvsig.fmap.dal.feature.FeatureType; |
58 |
import org.gvsig.fmap.dal.feature.spi.FeatureProvider; |
59 |
import org.gvsig.fmap.dal.feature.spi.SQLBuilderBase; |
60 |
import org.gvsig.fmap.dal.store.jdbc.JDBCConnectionParameters; |
61 |
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper; |
62 |
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase; |
63 |
import org.gvsig.fmap.geom.Geometry; |
64 |
import org.gvsig.fmap.geom.GeometryUtils; |
65 |
import org.gvsig.fmap.geom.primitive.Envelope; |
66 |
import org.gvsig.oracle.dal.expressionbuilderformatter.OracleFormatter; |
67 |
import static org.gvsig.oracle.dal.expressionbuilderformatter.OracleGeometryParameter.ORACLE_GEOMETRY_PARAMETER; |
68 |
import org.gvsig.tools.ToolsLocator; |
69 |
import org.gvsig.tools.dataTypes.Coercion; |
70 |
import org.gvsig.tools.dataTypes.DataType; |
71 |
import org.gvsig.tools.dataTypes.DataTypeUtils; |
72 |
import org.gvsig.tools.dataTypes.DataTypesManager; |
73 |
import org.gvsig.tools.dispose.Disposable; |
74 |
|
75 |
public class OracleSQLBuilder extends JDBCSQLBuilderBase { |
76 |
|
77 |
protected static final String ADD_SERIAL_COLUMN_SEQUENCE_QUERY = "CREATE SEQUENCE \"{0}\""; |
78 |
protected static final String ADD_SERIAL_COLUMN_TRIGGER_QUERY = "CREATE OR REPLACE TRIGGER \"{0}\" BEFORE INSERT ON {1} FOR EACH ROW " |
79 |
+ "BEGIN SELECT \"{3}\".NEXTVAL INTO :new.\"{2}\" FROM dual; END;";
|
80 |
protected static final String DELETE_FROM_OGIS_GEOMETRY_COLUMNS_QUERY = "DELETE FROM MDSYS.OGIS_GEOMETRY_COLUMNS " |
81 |
+ "WHERE F_TABLE_SCHEMA = ''{0}'' AND F_TABLE_NAME = ''{1}'' AND F_GEOMETRY_COLUMN = ''{2}''";
|
82 |
protected static final String INSERT_OGIS_GEOMETRY_COLUMNS_QUERY = "INSERT INTO MDSYS.OGIS_GEOMETRY_COLUMNS " |
83 |
+ "(F_TABLE_SCHEMA, F_TABLE_NAME, F_GEOMETRY_COLUMN, GEOMETRY_TYPE) VALUES "
|
84 |
+ "(''{0}'', ''{1}'', ''{2}'', {3})";
|
85 |
private final String quote_for_identifiers; |
86 |
private final String quote_for_strings; |
87 |
public static final String ST_GEOMFROMTEXT = "SDO_GEOMETRY(({0}), ({1}))"; |
88 |
public static final String ST_GEOMFROMWKB = "SDO_GEOMETRY(({0}), ({1}))"; |
89 |
public static final String ST_GEOMFROMEWKB = "SDO_GEOMETRY(({0}), ({1}))"; |
90 |
public static final String FORMAT_OPERATOR_NOTISNULL = "( (({0}) IS NOT NULL) )"; |
91 |
public static final String FORMAT_OPERATOR_AND = "( ({0}) AND ({1}) )"; |
92 |
public static final String FORMAT_OPERATOR_OR = "( ({0}) OR ({1}) )"; |
93 |
public static final String FORMAT_OPERATOR_NE = "( ({0}) != ({1}) )"; |
94 |
public static final String FORMAT_OPERATOR_ILIKE = "( LOWER({0}) LIKE LOWER({1}) )"; |
95 |
public static final String FORMAT_OPERATOR_CONCAT = "{0} + {1}"; |
96 |
|
97 |
public static final int BOOLEAN_STRING_DEFAULT_LENGTH = 1; |
98 |
|
99 |
private static final Geometry EMPTY_POINT = GeometryUtils.createPoint(0, 0); |
100 |
|
101 |
protected Formatter formatter = null; |
102 |
|
103 |
public OracleSQLBuilder(JDBCHelper helper) {
|
104 |
super(helper);
|
105 |
|
106 |
this.defaultSchema = ""; |
107 |
this.allowAutomaticValues = true; |
108 |
this.geometrySupportType = this.helper.getGeometrySupportType(); |
109 |
this.hasSpatialFunctions = this.helper.hasSpatialFunctions(); |
110 |
this.constant_true = "TRUE"; |
111 |
this.constant_false = "FALSE"; |
112 |
this.quote_for_identifiers = "\""; |
113 |
this.quote_for_strings = "\'"; |
114 |
|
115 |
this.type_boolean = "CHAR(1)"; |
116 |
this.type_byte = "NUMBER(" + (DataType.BYTE_MAX_PRECISION) + ",0)"; |
117 |
this.type_bytearray = "BLOB"; |
118 |
this.type_geometry = "SDO_GEOMETRY"; |
119 |
this.type_char = "CHAR(1)"; |
120 |
this.type_date = "DATE"; |
121 |
this.type_double = "BINARY_DOUBLE"; //float con 53 bits de mantisa = float(54) |
122 |
this.type_decimal_p = "NUMBER({0})"; |
123 |
this.type_decimal_ps = "NUMBER({0},{1})"; |
124 |
// this.type_bigdecimal = "NUMBER({0},{1})";
|
125 |
this.type_float = "BINARY_FLOAT"; //float con 24 bits de mantisa = float(24) |
126 |
this.type_int = "NUMBER(" + (DataType.INT_MAX_PRECISION - 1) + ",0)"; |
127 |
this.type_long = "NUMBER(" + (DataType.LONG_MAX_PRECISION - 1) + ",0)"; |
128 |
this.type_string = "NCLOB"; |
129 |
this.type_string_p = "NVARCHAR2({0,Number,#######})"; |
130 |
this.type_time = "TIMESTAMP"; |
131 |
this.type_timestamp = "TIMESTAMP"; |
132 |
this.type_version = "VARCHAR2(30)"; |
133 |
this.type_URI = "NVARCHAR2(2048)"; |
134 |
this.type_URL = "NVARCHAR2(2048)"; |
135 |
this.type_FILE = "NVARCHAR2(2048)"; |
136 |
this.type_FOLDER = "NVARCHAR2(2048)"; |
137 |
|
138 |
STMT_DELETE_FROM_table_WHERE_expresion = "DELETE FROM {0} WHERE {1}";
|
139 |
STMT_DELETE_FROM_table = "DELETE FROM {0}";
|
140 |
STMT_INSERT_INTO_table_columns_VALUES_values = "INSERT INTO {0} ( {1} ) VALUES ( {2} )";
|
141 |
STMT_UPDATE_TABLE_STATISTICS_table = "VACUUM ANALYZE {0}"; // FIXME: ALTER INDEX [schema.]index REBUILD INDEXTYPE IS MDSYS.SPATIAL_INDEX PARAMETERS (''LAYER_GTYPE={3}''; |
142 |
// config.remove_functionality(SQLConfig.UPDATE_TABLE_STATISTICS_table; // FIXME
|
143 |
STMT_DROP_TABLE_table = "DROP TABLE {0}";
|
144 |
STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_table = null;
|
145 |
STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table = null;
|
146 |
STMT_UPDATE_table_SET_columnsAndValues_WHERE_expresion = "UPDATE {0} SET {1} WHERE {2}";
|
147 |
STMT_UPDATE_table_SET_columnsAndValues = "UPDATE {0} SET {1}";
|
148 |
STMT_GRANT_privileges_ON_table_TO_role = "GRANT {0} ON {1} TO {2}";
|
149 |
|
150 |
} |
151 |
|
152 |
public OracleHelper getHelper() {
|
153 |
return (OracleHelper) super.getHelper(); |
154 |
} |
155 |
|
156 |
@Override
|
157 |
public Formatter formatter() { |
158 |
if (this.formatter == null) { |
159 |
this.formatter = new OracleFormatter(this); |
160 |
} |
161 |
return this.formatter; |
162 |
} |
163 |
|
164 |
private class OracleGeometryExpressionBuilder extends DelegatedGeometryExpressionBuilder { |
165 |
|
166 |
public OracleGeometryExpressionBuilder(GeometryExpressionBuilder expressionBuilder) {
|
167 |
super(expressionBuilder);
|
168 |
} |
169 |
|
170 |
@Override
|
171 |
public Formatter<Value> formatter() { |
172 |
return OracleSQLBuilder.this.formatter();
|
173 |
} |
174 |
|
175 |
} |
176 |
|
177 |
private OracleGeometryExpressionBuilder oracleExpressionBuilder = null; |
178 |
|
179 |
@Override
|
180 |
public GeometryExpressionBuilder expression() {
|
181 |
if (this.oracleExpressionBuilder == null) { |
182 |
this.oracleExpressionBuilder = new OracleGeometryExpressionBuilder(super.expression()); |
183 |
} |
184 |
return this.oracleExpressionBuilder; |
185 |
} |
186 |
|
187 |
@Override
|
188 |
public String default_schema() { |
189 |
JDBCConnectionParameters params = this.helper.getConnectionParameters();
|
190 |
if (params != null) { |
191 |
if (StringUtils.isBlank(params.getSchema())) {
|
192 |
if ((StringUtils.isNotBlank(params.getUser()))) {
|
193 |
return params.getUser();
|
194 |
} |
195 |
} else {
|
196 |
return params.getSchema();
|
197 |
} |
198 |
} |
199 |
return this.defaultSchema; |
200 |
} |
201 |
|
202 |
public class OracleUpdateTableStatisticsBuilderBase extends UpdateTableStatisticsBuilderBase { |
203 |
|
204 |
@Override
|
205 |
public List<String> toStrings() { |
206 |
List<String> sqls = new ArrayList<>(); |
207 |
|
208 |
String name = as_identifier(this.table.getName()); |
209 |
if (table.has_schema()) {
|
210 |
name = as_identifier(this.table.getSchema()) + "." + name; |
211 |
} |
212 |
String sql = MessageFormat.format( |
213 |
"ANALYZE TABLE {0} COMPUTE STATISTICS",
|
214 |
name |
215 |
); |
216 |
if (!StringUtils.isEmpty(sql)) {
|
217 |
sqls.add(sql); |
218 |
} |
219 |
|
220 |
return sqls;
|
221 |
} |
222 |
} |
223 |
|
224 |
public String getSerialSequenceName(String tableName, String columnName) { |
225 |
return ("GVSEQ_" + tableName + "_" + columnName).toUpperCase(); |
226 |
} |
227 |
|
228 |
public String getSerialTriggerName(String tableName, String columnName) { |
229 |
return ("GVSER_" + tableName + "_" + columnName).toUpperCase(); |
230 |
} |
231 |
|
232 |
protected class OracleCreateTableBuilder extends CreateTableBuilderBase { |
233 |
|
234 |
@Override
|
235 |
public List<String> toStrings(Formatter formatter) { |
236 |
|
237 |
List<String> sqls = new ArrayList<>(); |
238 |
StringBuilder builder = new StringBuilder(); |
239 |
|
240 |
builder.append("CREATE TABLE ");
|
241 |
builder.append(this.table().toString());
|
242 |
builder.append(" (");
|
243 |
boolean first = true; |
244 |
|
245 |
ArrayList<String> pks = new ArrayList<>(); |
246 |
boolean automaticPrimaryKey = false; |
247 |
|
248 |
for (ColumnDescriptor column : columns) {
|
249 |
if (first) {
|
250 |
first = false;
|
251 |
} else {
|
252 |
builder.append(", ");
|
253 |
} |
254 |
if (column.isGeometry()) {
|
255 |
builder.append(as_identifier(column.getName())); //.toUpperCase()));
|
256 |
builder.append(" ");
|
257 |
builder.append(" SDO_GEOMETRY");
|
258 |
if (!column.allowNulls()) {
|
259 |
builder.append(" NOT NULL");
|
260 |
} |
261 |
} else {
|
262 |
builder.append(as_identifier(column.getName())); |
263 |
builder.append(" ");
|
264 |
builder.append(sqltype( |
265 |
column.getType(), |
266 |
column.getSize(), |
267 |
column.getPrecision(), |
268 |
column.getScale(), |
269 |
column.getGeometryType(), |
270 |
column.getGeometrySubtype())); |
271 |
|
272 |
// if (column.getDefaultValue() == null) {
|
273 |
// if (column.allowNulls()) {
|
274 |
// builder.append(" DEFAULT NULL");
|
275 |
// }
|
276 |
// } else {
|
277 |
// builder.append(" DEFAULT '");
|
278 |
// builder.append(column.getDefaultValue().toString());
|
279 |
// builder.append("'");
|
280 |
// }
|
281 |
// if (column.allowNulls()) {
|
282 |
// builder.append(" NULL");
|
283 |
// } else {
|
284 |
// builder.append(" NOT NULL");
|
285 |
// }
|
286 |
} |
287 |
if (column.isPrimaryKey()) {
|
288 |
if (column.isAutomatic()) {
|
289 |
// if the pk is automatic, ignore any other PK
|
290 |
automaticPrimaryKey = true;
|
291 |
pks.clear(); |
292 |
pks.add(column.getName()); |
293 |
} else if (!automaticPrimaryKey) { |
294 |
pks.add(column.getName()); |
295 |
} |
296 |
} else {
|
297 |
if (column.isAutomatic()) {
|
298 |
// builder.append(" AUTO_INCREMENT");
|
299 |
builder.append(" GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1)");
|
300 |
} |
301 |
if (column.getDefaultValue() == null |
302 |
|| ExpressionUtils.isDynamicText(Objects.toString(column.getDefaultValue(), null))) {
|
303 |
if (column.allowNulls()) {
|
304 |
builder.append(" DEFAULT NULL");
|
305 |
} |
306 |
} else {
|
307 |
switch (column.getType()) {
|
308 |
case DataTypes.TIMESTAMP:
|
309 |
builder.append(" DEFAULT ( TIMESTAMP '");
|
310 |
Timestamp dtimestamp = (Timestamp) DataTypeUtils.toTimestamp(column.getDefaultValue()); |
311 |
builder.append(MessageFormat.format("{0,date,yyyy-MM-dd HH:mm:ss.S}", dtimestamp)); |
312 |
builder.append("' )");
|
313 |
break;
|
314 |
case DataTypes.TIME:
|
315 |
builder.append(" DEFAULT ( TIME '");
|
316 |
Time dtime = (Time) DataTypeUtils.toTime(column.getDefaultValue()); |
317 |
builder.append(MessageFormat.format("{0,date,HH:mm:ss}", dtime)); |
318 |
builder.append("' )");
|
319 |
break;
|
320 |
case DataTypes.DATE:
|
321 |
builder.append(" DEFAULT ( DATE '");
|
322 |
java.sql.Date ddate = (java.sql.Date) DataTypeUtils.toDate(column.getDefaultValue()); |
323 |
builder.append(MessageFormat.format("{0,date,yyyy-MM-dd}", ddate)); |
324 |
builder.append("' )");
|
325 |
break;
|
326 |
default:
|
327 |
builder.append(" DEFAULT '");
|
328 |
builder.append(Objects.toString(column.getDefaultValue(), ""));
|
329 |
builder.append("'");
|
330 |
} |
331 |
} |
332 |
} |
333 |
} |
334 |
builder.append(" )");
|
335 |
sqls.add(builder.toString()); |
336 |
|
337 |
if (pks.size() > 0) { |
338 |
builder = new StringBuilder("ALTER TABLE "); |
339 |
builder.append(this.table().toString());
|
340 |
builder.append(" ADD PRIMARY KEY (");
|
341 |
for (int i = 0; i < pks.size(); i++) { |
342 |
if (i != 0) { |
343 |
builder.append(", ");
|
344 |
} |
345 |
builder.append(as_identifier(pks.get(i))); |
346 |
} |
347 |
builder.append(")");
|
348 |
sqls.add(builder.toString()); |
349 |
} |
350 |
|
351 |
for (ColumnDescriptor column : columns) {
|
352 |
if (column.isAutomatic()) {
|
353 |
String sequenceName = getSerialSequenceName(this.table.getName(), column.getName()); |
354 |
String sql = MessageFormat.format( |
355 |
ADD_SERIAL_COLUMN_SEQUENCE_QUERY, |
356 |
sequenceName |
357 |
); |
358 |
sqls.add(sql); |
359 |
String autoTriggerName = getSerialTriggerName(this.table.getName(), column.getName()); |
360 |
sql = MessageFormat.format(
|
361 |
ADD_SERIAL_COLUMN_TRIGGER_QUERY, |
362 |
autoTriggerName, |
363 |
this.table().toString(),
|
364 |
column.getName(), |
365 |
sequenceName |
366 |
); |
367 |
sqls.add(sql); |
368 |
} |
369 |
} |
370 |
|
371 |
for (ColumnDescriptor column : columns) {
|
372 |
if (column.isGeometry()) {
|
373 |
/**
|
374 |
* Inserting the geomtype and column on
|
375 |
* OGIS_GEOMETRY_COLUMNS.
|
376 |
*
|
377 |
* It is useful to retrieve the geometry type when the
|
378 |
* spatial index can't be defined (for instance users
|
379 |
* creating tables on a different schema).
|
380 |
*
|
381 |
* Note: We don't insert the SRID because it is unusable as
|
382 |
* defined on OGIS_GEOMETRY_COLUMNS, as it must reference an
|
383 |
* existing SRID on OGIS_SPATIAL_REFERENCE_SYSTEM.
|
384 |
* OGIS_SPATIAL_REFERENCE_SYSTEM is empty and it has a
|
385 |
* trigger that duplicates on SDO_COORD_REF_SYS any SRID
|
386 |
* inserted on OGIS_SPATIAL_REFERENCE_SYSTEM.
|
387 |
* SDO_COORD_REF_SYS is not empty and we don't want to
|
388 |
* duplicate the SRID definitions!!
|
389 |
*/
|
390 |
int gvsigType = column.getGeometryType();
|
391 |
int gvsigSubtype = column.getGeometrySubtype();
|
392 |
String sql = MessageFormat.format( // delete before inserting to avoid creating duplicates |
393 |
DELETE_FROM_OGIS_GEOMETRY_COLUMNS_QUERY, |
394 |
this.table().getSchema(),
|
395 |
this.table().getName().toUpperCase(),
|
396 |
column.getName() |
397 |
); |
398 |
sqls.add(sql); |
399 |
sql = MessageFormat.format(
|
400 |
INSERT_OGIS_GEOMETRY_COLUMNS_QUERY, |
401 |
this.table().getSchema(),
|
402 |
this.table().getName().toUpperCase(),
|
403 |
column.getName(), |
404 |
Integer.toString(GeometryTypeUtils.toSFSGeometryTypeCode(gvsigType, gvsigSubtype))
|
405 |
); |
406 |
sqls.add(sql); |
407 |
Envelope tablebbox = column.getTableBBox(); |
408 |
if (tablebbox != null) { |
409 |
sql = SpatialIndexUtils.getSQLDeleteUserMetadata( |
410 |
this.table().getSchema(),
|
411 |
this.table().getName(),
|
412 |
column.getName() |
413 |
); |
414 |
sqls.add(sql); |
415 |
sql = SpatialIndexUtils.getSQLInsertUserMetadata( |
416 |
this.table().getName(),
|
417 |
tablebbox, |
418 |
column.getName(), |
419 |
(int) column.getGeometrySRSId()
|
420 |
); |
421 |
sqls.add(sql); |
422 |
sql = SpatialIndexUtils.getSQLCreateSpatialIndex( |
423 |
this.table().getName(),
|
424 |
column.getName(), |
425 |
gvsigType, |
426 |
gvsigSubtype |
427 |
); |
428 |
sqls.add(sql); |
429 |
} |
430 |
} |
431 |
} |
432 |
return sqls;
|
433 |
} |
434 |
} |
435 |
|
436 |
public class OracleSelectBuilder extends SelectBuilderBase { |
437 |
|
438 |
@Override
|
439 |
public String toString(Formatter<ExpressionBuilder.Value> formatter) { |
440 |
StringBuilder builder = new StringBuilder(); |
441 |
if (!isValid(builder)) {
|
442 |
throw new IllegalStateException(builder.toString()); |
443 |
} |
444 |
boolean involveWithLimitOrOffset = ((this.has_offset() || this.has_limit()) |
445 |
&& (this.has_aggregate_functions() || this.has_group_by() || this.has_order_by())); |
446 |
|
447 |
if (involveWithLimitOrOffset) {
|
448 |
/**
|
449 |
* Using ROWNUM for limit & offset, compatible with any Oracle
|
450 |
* version This requires wrapping the original query as shown in
|
451 |
* the example: select * from ( select a.*, ROWNUM rnum from (
|
452 |
* <select statement with order by clause>
|
453 |
* ) a where ROWNUM <= MAX_ROW
|
454 |
* ) where rnum >= MIN_ROW because ROWNUM is considered before
|
455 |
* applying order by and group by
|
456 |
*/
|
457 |
builder.append("SELECT * FROM ( ");
|
458 |
if (this.has_offset()) { |
459 |
builder.append("SELECT a.*, ROWNUM rnum FROM ( ");
|
460 |
} |
461 |
} |
462 |
|
463 |
builder.append("SELECT ");
|
464 |
if (this.distinct) { |
465 |
builder.append("DISTINCT ");
|
466 |
} |
467 |
boolean first = true; |
468 |
for (SelectColumnBuilder column : columns) {
|
469 |
if (first) {
|
470 |
first = false;
|
471 |
} else {
|
472 |
builder.append(", ");
|
473 |
} |
474 |
builder.append(column.toString(formatter)); |
475 |
} |
476 |
|
477 |
if (this.has_from()) { |
478 |
builder.append(" FROM ");
|
479 |
builder.append(this.from.toString(formatter));
|
480 |
} |
481 |
if (this.has_where()) { |
482 |
builder.append(" WHERE ");
|
483 |
builder.append(this.where.toString(formatter));
|
484 |
} |
485 |
|
486 |
if (!involveWithLimitOrOffset) {
|
487 |
if (this.has_limit() || this.has_offset()) { |
488 |
if (this.has_where()) { |
489 |
builder.append(" AND ");
|
490 |
} else {
|
491 |
builder.append(" WHERE ");
|
492 |
} |
493 |
} |
494 |
|
495 |
if (this.has_limit()) { |
496 |
builder.append(" ROWNUM <= ");
|
497 |
if (this.has_offset()) { |
498 |
builder.append(this.offset + this.limit); |
499 |
} else {
|
500 |
builder.append(this.limit);
|
501 |
} |
502 |
} |
503 |
if (this.has_offset()) { |
504 |
builder.append(" AND rnum > ");
|
505 |
builder.append(this.offset);
|
506 |
} |
507 |
|
508 |
if (this.has_group_by()) { |
509 |
builder.append(" GROUP BY ");
|
510 |
builder.append(this.groupColumn.get(0).toString(formatter)); |
511 |
for (int i = 1; i < groupColumn.size(); i++) { |
512 |
builder.append(", ");
|
513 |
builder.append(this.groupColumn.get(i).toString(formatter));
|
514 |
} |
515 |
} |
516 |
|
517 |
if (this.has_order_by()) { |
518 |
builder.append(" ORDER BY ");
|
519 |
first = true;
|
520 |
for (OrderByBuilder item : this.order_by) { |
521 |
if (first) {
|
522 |
first = false;
|
523 |
} else {
|
524 |
builder.append(", ");
|
525 |
} |
526 |
builder.append(item.toString(formatter)); |
527 |
} |
528 |
} |
529 |
|
530 |
} |
531 |
|
532 |
if (involveWithLimitOrOffset) {
|
533 |
if (this.has_order_by()) { |
534 |
builder.append(" ORDER BY ");
|
535 |
first = true;
|
536 |
for (OrderByBuilder item : this.order_by) { |
537 |
if (first) {
|
538 |
first = false;
|
539 |
} else {
|
540 |
builder.append(", ");
|
541 |
} |
542 |
builder.append(item.toString(formatter)); |
543 |
} |
544 |
} |
545 |
builder.append(") a");
|
546 |
if (this.has_limit()) { |
547 |
builder.append(" WHERE ROWNUM <= ");
|
548 |
if (this.has_offset()) { |
549 |
builder.append(this.offset + this.limit); |
550 |
} else {
|
551 |
builder.append(this.limit);
|
552 |
} |
553 |
} |
554 |
if (this.has_offset()) { |
555 |
builder.append(" )");
|
556 |
builder.append(" WHERE rnum > ");
|
557 |
builder.append(this.offset);
|
558 |
} |
559 |
|
560 |
} |
561 |
return builder.toString();
|
562 |
} |
563 |
|
564 |
} |
565 |
|
566 |
@Override
|
567 |
public TableNameBuilder createTableNameBuilder() {
|
568 |
return new OracleTableNameBuilder(); |
569 |
} |
570 |
|
571 |
@Override
|
572 |
protected CreateTableBuilder createCreateTableBuilder() {
|
573 |
return new OracleCreateTableBuilder(); |
574 |
} |
575 |
|
576 |
@Override
|
577 |
public SelectBuilder createSelectBuilder() {
|
578 |
return new OracleSelectBuilder(); |
579 |
} |
580 |
|
581 |
@Override
|
582 |
protected FromBuilder createFromBuilder() {
|
583 |
return new OracleFromBuilder(); |
584 |
} |
585 |
|
586 |
@Override
|
587 |
protected UpdateTableStatisticsBuilder createUpdateTableStatisticsBuilder() {
|
588 |
return new OracleUpdateTableStatisticsBuilderBase(); |
589 |
} |
590 |
|
591 |
protected class OracleTableNameBuilder extends TableNameBuilderBase { |
592 |
|
593 |
@Override
|
594 |
public boolean has_database() { |
595 |
return false; |
596 |
} |
597 |
|
598 |
@Override
|
599 |
public String toString() { |
600 |
return this.toString(formatter()); |
601 |
} |
602 |
|
603 |
protected String databaseName2provider() { |
604 |
return null; |
605 |
} |
606 |
|
607 |
protected String schemaName2provider() { |
608 |
return this.schemaName; |
609 |
} |
610 |
|
611 |
protected String tableName2provider() { |
612 |
boolean forceUpperCase = true; |
613 |
OracleConnectionParameters params = getHelper().getConnectionParameters(); |
614 |
if (params != null) { |
615 |
forceUpperCase = params.getForceUppercaseInTableName(); |
616 |
} |
617 |
if( forceUpperCase ) {
|
618 |
return StringUtils.upperCase(this.tableName); |
619 |
} |
620 |
return this.tableName; |
621 |
} |
622 |
|
623 |
|
624 |
@Override
|
625 |
public String toString(Formatter<ExpressionBuilder.Value> formatter) { |
626 |
if (formatter != null && formatter.canApply(this)) { |
627 |
return formatter.format(this); |
628 |
} |
629 |
if (this.has_schema()) { |
630 |
return as_identifier(this.schemaName2provider()) + "." |
631 |
+ as_identifier(this.tableName2provider());
|
632 |
} |
633 |
|
634 |
OracleConnectionParameters params = getHelper().getConnectionParameters(); |
635 |
if (params != null) { |
636 |
if ((StringUtils.isNotBlank(params.getUser()))) {
|
637 |
return as_identifier(params.getUser()) + "." |
638 |
+ as_identifier(this.tableName2provider());
|
639 |
} |
640 |
} |
641 |
return as_identifier(this.tableName2provider()); |
642 |
} |
643 |
} |
644 |
|
645 |
public class OracleFromBuilder extends FromBuilderBase { |
646 |
|
647 |
@Override
|
648 |
public String toString(Formatter<ExpressionBuilder.Value> formatter) { |
649 |
if (formatter != null && formatter.canApply(this)) { |
650 |
return formatter.format(this); |
651 |
} |
652 |
if (!StringUtils.isEmpty(passthrough)) {
|
653 |
return passthrough;
|
654 |
} |
655 |
if (!StringUtils.isEmpty(subquery)) {
|
656 |
return "( " + this.subquery + ") " + quote_for_identifiers() + "_subquery_alias_" + quote_for_identifiers() + " "; |
657 |
} |
658 |
if (this.joins == null || this.joins.isEmpty()) { |
659 |
return this.tableName.toString(formatter); |
660 |
} |
661 |
StringBuilder builder = new StringBuilder(); |
662 |
builder.append(this.tableName.toString(formatter));
|
663 |
for (JoinBuilder join : this.joins) { |
664 |
builder.append(" ");
|
665 |
builder.append(join.toString(formatter)); |
666 |
} |
667 |
return builder.toString();
|
668 |
} |
669 |
} |
670 |
|
671 |
public class DisposableBlobs implements Disposable { |
672 |
|
673 |
private final ArrayList<BLOB> blobList = new ArrayList<>(); |
674 |
|
675 |
public void add(BLOB blob) { |
676 |
blobList.add(blob); |
677 |
} |
678 |
|
679 |
@Override
|
680 |
public void dispose() { |
681 |
blobList.forEach((blob) -> { |
682 |
try {
|
683 |
blob.freeTemporary(); |
684 |
} catch (SQLException ex) { |
685 |
LOGGER.warn("Can't dispose blob " + blob.toString(), ex);
|
686 |
} |
687 |
}); |
688 |
} |
689 |
|
690 |
} |
691 |
|
692 |
protected void setBlob(PreparedStatement st, int columnIndex, |
693 |
byte[] bytes, DisposableBlobs blobList) throws SQLException, IOException { |
694 |
Connection conn = st.getConnection();
|
695 |
if (conn instanceof DelegatingConnection) { |
696 |
conn = ((DelegatingConnection) conn).getInnermostDelegate(); |
697 |
} |
698 |
BLOB blob = BLOB.createTemporary(conn, false, BLOB.DURATION_SESSION);
|
699 |
blobList.add(blob); |
700 |
InputStream inputStream;
|
701 |
try (OutputStream outputStream = blob.setBinaryStream(0L)) { |
702 |
inputStream = new ByteArrayInputStream(bytes); |
703 |
byte[] buffer = new byte[blob.getBufferSize()]; |
704 |
int byteread;
|
705 |
while ((byteread = inputStream.read(buffer)) != -1) { |
706 |
outputStream.write(buffer, 0, byteread);
|
707 |
} |
708 |
} |
709 |
inputStream.close(); |
710 |
st.setBlob(columnIndex, blob); |
711 |
} |
712 |
|
713 |
@Override
|
714 |
public Disposable setStatementParameters(
|
715 |
PreparedStatement st,
|
716 |
List values,
|
717 |
List<Integer> types, //Can be null |
718 |
GeometrySupportType geometrySupportType) throws SQLException { |
719 |
|
720 |
DisposableBlobs blobList = new DisposableBlobs();
|
721 |
if (values == null) { |
722 |
return blobList;
|
723 |
} |
724 |
try {
|
725 |
byte[] bytes; |
726 |
int columnIndex = 1; |
727 |
for (Object value : values) { |
728 |
if (value instanceof Geometry) { |
729 |
switch (geometrySupportType) {
|
730 |
case WKT:
|
731 |
value = ((Geometry) value).convertToWKT(); |
732 |
st.setObject(columnIndex, value); |
733 |
break;
|
734 |
case NATIVE:
|
735 |
case WKB:
|
736 |
bytes = ((Geometry) value).convertToWKB(); |
737 |
setBlob(st, columnIndex, bytes, blobList); |
738 |
break;
|
739 |
case EWKB:
|
740 |
bytes = ((Geometry) value).convertToEWKB(); |
741 |
setBlob(st, columnIndex, bytes, blobList); |
742 |
break;
|
743 |
} |
744 |
} else {
|
745 |
if (types == null) { |
746 |
st.setObject(columnIndex, value); |
747 |
} else {
|
748 |
this.setStatementValue(st, columnIndex, types.get(columnIndex - 1), value); |
749 |
} |
750 |
} |
751 |
columnIndex++; |
752 |
} |
753 |
} catch (Exception ex) { |
754 |
throw new SQLException("Can't set values for the prepared statement.", ex); |
755 |
} |
756 |
return blobList;
|
757 |
} |
758 |
|
759 |
@Override
|
760 |
public List<Object> getParameters(FeatureProvider feature) { |
761 |
return getParameters(feature, null); |
762 |
} |
763 |
|
764 |
@Override
|
765 |
public List<Object> getParameters(FeatureProvider feature, List<Integer> types) { |
766 |
try {
|
767 |
FeatureType type = feature.getType(); |
768 |
FeatureType providerType = this.getHelper().getProviderFeatureType();
|
769 |
List<Object> values = new ArrayList<>(); |
770 |
Object value;
|
771 |
DataTypesManager dataTypesManager = ToolsLocator.getDataTypesManager(); |
772 |
for (ExpressionBuilder.Parameter parameter : this.parameters()) { |
773 |
if (parameter.is_constant()) {
|
774 |
value = parameter.value(); |
775 |
values.add(value); |
776 |
if (types != null) { |
777 |
if (value == null) { |
778 |
if (values.get(values.size() - 2) == EMPTY_POINT) { |
779 |
types.add(DataTypes.INTEGER); |
780 |
} else {
|
781 |
types.add(DataTypes.OBJECT); |
782 |
} |
783 |
} else {
|
784 |
DataType dataType = dataTypesManager.getDataType(value.getClass()); |
785 |
types.add(dataType.getType()); |
786 |
} |
787 |
} |
788 |
} else {
|
789 |
String name = parameter.name();
|
790 |
value = feature.get(name); |
791 |
FeatureAttributeDescriptor attrDesc = type.getAttributeDescriptor(name); |
792 |
Coercion convert = null;
|
793 |
if (providerType != null) { |
794 |
FeatureAttributeDescriptor attrDescProvider = providerType.getAttributeDescriptor(name); |
795 |
if (attrDescProvider != null && attrDescProvider.getType() != attrDesc.getType()) { |
796 |
convert = attrDescProvider.getDataType().getCoercion(); |
797 |
} |
798 |
} |
799 |
switch (attrDesc.getType()) {
|
800 |
case org.gvsig.fmap.dal.DataTypes.GEOMETRY:
|
801 |
Geometry geom = this.forceGeometryType(
|
802 |
attrDesc.getGeomType(), |
803 |
(Geometry) value |
804 |
); |
805 |
if (BooleanUtils.isTrue((Boolean) parameter.getProperty(ORACLE_GEOMETRY_PARAMETER))) { |
806 |
//Es muy guarro pero es para evitar un error de NullPointerException en Oracle
|
807 |
if (geom == null) { |
808 |
//NVL2((NULL),SDO_GEOMETRY((EMPTY_POINT), (?)),NULL)
|
809 |
values.add(null);
|
810 |
values.add(EMPTY_POINT); |
811 |
} else {
|
812 |
//NVL2((1),SDO_GEOMETRY((WKB), (?)),NULL)
|
813 |
values.add(1);
|
814 |
values.add(geom); |
815 |
} |
816 |
if (types != null) { |
817 |
types.add(DataTypes.INTEGER); |
818 |
types.add(DataTypes.GEOMETRY); |
819 |
} |
820 |
} |
821 |
break;
|
822 |
case org.gvsig.fmap.dal.DataTypes.BOOLEAN:
|
823 |
if (value == null) { |
824 |
values.add(null);
|
825 |
} else {
|
826 |
if (convert == null) { |
827 |
values.add(value); |
828 |
} else {
|
829 |
String s = (String) convert.coerce(value); |
830 |
values.add(s == null ? null : s.substring(0, 1)); |
831 |
} |
832 |
} |
833 |
if (types != null) { |
834 |
types.add(DataTypes.STRING); |
835 |
} |
836 |
break;
|
837 |
default:
|
838 |
if (convert == null) { |
839 |
values.add(value); |
840 |
} else {
|
841 |
values.add(convert.coerce(value)); |
842 |
} |
843 |
if (types != null) { |
844 |
int t = attrDesc.getDataType().getType();
|
845 |
types.add(t); |
846 |
if (t == DataTypes.INTEGER) {
|
847 |
Object x = values.get(values.size() - 1); |
848 |
if (x != null && !(x instanceof Integer)) { |
849 |
LOGGER.debug("Esto est? mal");
|
850 |
} |
851 |
} |
852 |
|
853 |
} |
854 |
break;
|
855 |
} |
856 |
} |
857 |
} |
858 |
|
859 |
return values;
|
860 |
} catch (Exception ex) { |
861 |
String f = "unknow"; |
862 |
try {
|
863 |
f = feature.toString(); |
864 |
} catch (Exception ex2) { |
865 |
// Do nothing
|
866 |
} |
867 |
throw new RuntimeException("Can't get parameters to prepared statement from the feature (" + f + ")", ex); |
868 |
} |
869 |
} |
870 |
|
871 |
@Override
|
872 |
public List<String> parameters_names() { |
873 |
List<String> params = new ArrayList<>(); |
874 |
for (ExpressionBuilder.Parameter param : parameters()) {
|
875 |
String s;
|
876 |
switch (param.type()) {
|
877 |
case PARAMETER_TYPE_CONSTANT:
|
878 |
Object theValue = param.value();
|
879 |
if (theValue == null) { |
880 |
s = "null";
|
881 |
} else if (theValue instanceof String) { |
882 |
s = "'" + (String) theValue + "'"; |
883 |
} else {
|
884 |
s = theValue.toString(); |
885 |
} |
886 |
break;
|
887 |
case PARAMETER_TYPE_VARIABLE:
|
888 |
default:
|
889 |
s = "\"" + param.name() + "\""; |
890 |
} |
891 |
params.add(s); |
892 |
if (BooleanUtils.isTrue((Boolean) param.getProperty(ORACLE_GEOMETRY_PARAMETER))) { |
893 |
params.add(s); |
894 |
} |
895 |
|
896 |
} |
897 |
return params;
|
898 |
} |
899 |
|
900 |
public String blob(byte[] data) { |
901 |
StringBuilder builder = new StringBuilder(); |
902 |
builder.append("TO_BLOB(HEXTORAW('");
|
903 |
for (byte abyte : data) { |
904 |
int v = abyte & 0xff; |
905 |
builder.append(String.format("%02x", v)); |
906 |
} |
907 |
builder.append("'))");
|
908 |
return builder.toString();
|
909 |
} |
910 |
|
911 |
@Override
|
912 |
public String as_clob(String s) { |
913 |
int chunkSize = 1024; |
914 |
StringBuilder builder = new StringBuilder(); |
915 |
builder.append("(TO_CLOB('");
|
916 |
for (int i = 0; i < s.length(); i += chunkSize) { |
917 |
String chunk = s.substring(i, Math.min(s.length(), i + chunkSize)); |
918 |
if( i>0 ) { |
919 |
builder.append("') || TO_CLOB('");
|
920 |
} |
921 |
builder.append(StringUtils.replace(chunk, "'", "''")); |
922 |
} |
923 |
builder.append("'))");
|
924 |
return builder.toString();
|
925 |
} |
926 |
|
927 |
public class OracleCreateIndexBuilder extends CreateIndexBuilderBase { |
928 |
|
929 |
@Override
|
930 |
public List<String> toStrings() { |
931 |
List<String> sqls = new ArrayList<>(); |
932 |
if (!this.isSpatial) { |
933 |
// Spatial index is created in a different way because it requires some queries based on the results of other queries
|
934 |
// See OracleUpdateSpatialIndexAndMetadata class
|
935 |
StringBuilder builder = new StringBuilder(); |
936 |
builder.append("CREATE ");
|
937 |
if (this.isUnique) { |
938 |
builder.append("UNIQUE ");
|
939 |
} |
940 |
builder.append("INDEX ");
|
941 |
// if (this.ifNotExist) {
|
942 |
// builder.append("IF NOT EXISTS ");
|
943 |
// }
|
944 |
builder.append(as_identifier(this.indexName));
|
945 |
builder.append(" ON ");
|
946 |
builder.append(this.table.toString());
|
947 |
builder.append(" ( ");
|
948 |
boolean is_first_column = true; |
949 |
for (String column : this.columns) { |
950 |
if (is_first_column) {
|
951 |
is_first_column = false;
|
952 |
} else {
|
953 |
builder.append(", ");
|
954 |
} |
955 |
builder.append(as_identifier(column)); |
956 |
} |
957 |
builder.append(" )");
|
958 |
sqls.add(builder.toString()); |
959 |
} |
960 |
return sqls;
|
961 |
} |
962 |
} |
963 |
|
964 |
public class OracleAlterTableBuilder extends AlterTableBuilderBase { |
965 |
|
966 |
public OracleAlterTableBuilder(SQLBuilderBase sqlbuilder) {
|
967 |
super(sqlbuilder);
|
968 |
} |
969 |
|
970 |
@Override
|
971 |
public List<String> toStrings() { |
972 |
List<String> sqls = new ArrayList<>(); |
973 |
List<String> pks = new ArrayList<>(); |
974 |
|
975 |
for (String column : drops) { |
976 |
StringBuilder builder = new StringBuilder(); |
977 |
builder.append("ALTER TABLE ");
|
978 |
builder.append(this.table.toString());
|
979 |
builder.append(" DROP COLUMN ");
|
980 |
builder.append(as_identifier(column)); |
981 |
sqls.add(builder.toString()); |
982 |
} |
983 |
for (ColumnDescriptor column : adds) {
|
984 |
StringBuilder builder = new StringBuilder(); |
985 |
builder.append("ALTER TABLE ");
|
986 |
builder.append(this.table.toString());
|
987 |
builder.append(" ADD "); //COLUMN "); |
988 |
builder.append(as_identifier(column.getName())); |
989 |
builder.append(" ");
|
990 |
builder.append(sqltype( |
991 |
column.getType(), |
992 |
column.getSize(), |
993 |
column.getPrecision(), |
994 |
column.getScale(), |
995 |
column.getGeometryType(), |
996 |
column.getGeometrySubtype() |
997 |
) |
998 |
); |
999 |
if (column.getDefaultValue() == null) { |
1000 |
if (column.allowNulls()) {
|
1001 |
builder.append(" DEFAULT NULL");
|
1002 |
} |
1003 |
} else {
|
1004 |
builder.append(" DEFAULT '");
|
1005 |
builder.append(column.getDefaultValue().toString()); |
1006 |
builder.append("'");
|
1007 |
} |
1008 |
if (column.allowNulls()) {
|
1009 |
builder.append(" NULL");
|
1010 |
} else {
|
1011 |
builder.append(" NOT NULL");
|
1012 |
} |
1013 |
if (column.isPrimaryKey()) {
|
1014 |
pks.add(column.getName()); |
1015 |
} |
1016 |
sqls.add(builder.toString()); |
1017 |
if (pks.size() > 0) { |
1018 |
builder = new StringBuilder("ALTER TABLE "); |
1019 |
builder.append(this.table.toString());
|
1020 |
builder.append(" ADD PRIMARY KEY (");
|
1021 |
for (int i = 0; i < pks.size(); i++) { |
1022 |
if (i != 0) { |
1023 |
builder.append(", ");
|
1024 |
} |
1025 |
builder.append(as_identifier(pks.get(i))); |
1026 |
} |
1027 |
builder.append(")");
|
1028 |
sqls.add(builder.toString()); |
1029 |
} |
1030 |
if (column.isAutomatic()) {
|
1031 |
String sequenceName = getSerialSequenceName(this.table.getName(), column.getName()); |
1032 |
String sql = MessageFormat.format( |
1033 |
ADD_SERIAL_COLUMN_SEQUENCE_QUERY, |
1034 |
sequenceName |
1035 |
); |
1036 |
sqls.add(sql); |
1037 |
String autoTriggerName = getSerialTriggerName(this.table.getName(), column.getName()); |
1038 |
sql = MessageFormat.format(
|
1039 |
ADD_SERIAL_COLUMN_TRIGGER_QUERY, |
1040 |
autoTriggerName, |
1041 |
this.table.toString(formatter),
|
1042 |
column.getName(), |
1043 |
sequenceName |
1044 |
); |
1045 |
sqls.add(sql); |
1046 |
} |
1047 |
|
1048 |
if (column.isGeometry()) {
|
1049 |
/**
|
1050 |
* Inserting the geomtype and column on
|
1051 |
* OGIS_GEOMETRY_COLUMNS.
|
1052 |
*
|
1053 |
* It is useful to retrieve the geometry type when the
|
1054 |
* spatial index can't be defined (for instance users
|
1055 |
* creating tables on a different schema).
|
1056 |
*
|
1057 |
* Note: We don't insert the SRID because it is unusable as
|
1058 |
* defined on OGIS_GEOMETRY_COLUMNS, as it must reference an
|
1059 |
* existing SRID on OGIS_SPATIAL_REFERENCE_SYSTEM.
|
1060 |
* OGIS_SPATIAL_REFERENCE_SYSTEM is empty and it has a
|
1061 |
* trigger that duplicates on SDO_COORD_REF_SYS any SRID
|
1062 |
* inserted on OGIS_SPATIAL_REFERENCE_SYSTEM.
|
1063 |
* SDO_COORD_REF_SYS is not empty and we don't want to
|
1064 |
* duplicate the SRID definitions!!
|
1065 |
*/
|
1066 |
int gvsigType = column.getGeometryType();
|
1067 |
int gvsigSubtype = column.getGeometryType();
|
1068 |
String sql = MessageFormat.format( // delete before inserting to avoid creating duplicates |
1069 |
DELETE_FROM_OGIS_GEOMETRY_COLUMNS_QUERY, |
1070 |
this.table().getSchema(),
|
1071 |
this.table().getName(),
|
1072 |
column.getName()); |
1073 |
sqls.add(sql); |
1074 |
sql = MessageFormat.format(
|
1075 |
INSERT_OGIS_GEOMETRY_COLUMNS_QUERY, |
1076 |
this.table().getSchema(),
|
1077 |
this.table().getName(),
|
1078 |
column.getName(), |
1079 |
Integer.toString(GeometryTypeUtils.toSFSGeometryTypeCode(gvsigType, gvsigSubtype)));
|
1080 |
sqls.add(sql); |
1081 |
// Note: The spatial index will be created after inserting/updating layer metadata.
|
1082 |
// See OracleUpdateSpatialIndexAndMetadata class
|
1083 |
} |
1084 |
} |
1085 |
for (ColumnDescriptor column : alters) {
|
1086 |
if (!column.isGeometry()) { // FIXME: can't modify geom column. It could be done by adding a temporary one, copying values and then droping and renaming |
1087 |
StringBuilder builder = new StringBuilder(); |
1088 |
builder.append("ALTER TABLE ");
|
1089 |
builder.append(this.table.toString());
|
1090 |
builder.append(" MODIFY (");
|
1091 |
builder.append(as_identifier(column.getName())); |
1092 |
builder.append(" ");
|
1093 |
builder.append(sqltype( |
1094 |
column.getType(), |
1095 |
column.getSize(), |
1096 |
column.getPrecision(), |
1097 |
column.getScale(), |
1098 |
column.getGeometryType(), |
1099 |
column.getGeometrySubtype() |
1100 |
) |
1101 |
); |
1102 |
if (column.getDefaultValue() == null) { |
1103 |
builder.append(" DEFAULT NULL");
|
1104 |
} else {
|
1105 |
builder.append(" DEFAULT '");
|
1106 |
builder.append(column.getDefaultValue().toString()); |
1107 |
builder.append("'");
|
1108 |
} |
1109 |
builder.append(")");
|
1110 |
sqls.add(builder.toString()); |
1111 |
} |
1112 |
} |
1113 |
for (Pair<String, String> pair : renames) { |
1114 |
StringBuilder builder = new StringBuilder(); |
1115 |
builder.append("ALTER TABLE ");
|
1116 |
builder.append(this.table.toString());
|
1117 |
builder.append(" RENAME COLUMN ");
|
1118 |
builder.append(as_identifier(pair.getLeft())); |
1119 |
builder.append(" TO ");
|
1120 |
builder.append(as_identifier(pair.getRight())); |
1121 |
sqls.add(builder.toString()); |
1122 |
} |
1123 |
return sqls;
|
1124 |
} |
1125 |
} |
1126 |
|
1127 |
@Override
|
1128 |
protected AlterTableBuilder createAlterTableBuilder() {
|
1129 |
return new OracleAlterTableBuilder(this); |
1130 |
} |
1131 |
|
1132 |
@Override
|
1133 |
public CreateIndexBuilder createCreateIndexBuilder() {
|
1134 |
return new OracleCreateIndexBuilder(); |
1135 |
} |
1136 |
|
1137 |
@Override
|
1138 |
public String quote_for_identifiers() { |
1139 |
return this.quote_for_identifiers; |
1140 |
} |
1141 |
|
1142 |
@Override
|
1143 |
public String quote_for_strings() { |
1144 |
return this.quote_for_strings; |
1145 |
} |
1146 |
|
1147 |
@Override
|
1148 |
protected SelectColumnBuilder createSelectColumnBuilder() {
|
1149 |
return new OracleSelectColumnBuilder(this); |
1150 |
} |
1151 |
|
1152 |
public class OracleSelectColumnBuilder extends SelectColumnBuilderBase { |
1153 |
|
1154 |
public OracleSelectColumnBuilder(SQLBuilder sqlbuilder) {
|
1155 |
super(sqlbuilder);
|
1156 |
} |
1157 |
|
1158 |
@Override
|
1159 |
public String toString(Formatter<ExpressionBuilder.Value> formatter) { |
1160 |
if (formatter != null && formatter.canApply(this)) { |
1161 |
return formatter.format(this); |
1162 |
} |
1163 |
StringBuilder builder = new StringBuilder(); |
1164 |
if (this.asGeometry) { |
1165 |
if(this.value == VALUE_NULL){ |
1166 |
builder.append(this.value.toString(formatter));
|
1167 |
} else {
|
1168 |
builder.append(expression().ST_AsBinary(this.name).toString(formatter));
|
1169 |
} |
1170 |
} else {
|
1171 |
if (this.value == null) { |
1172 |
builder.append(this.name.toString(formatter));
|
1173 |
} else {
|
1174 |
builder.append(this.value.toString(formatter));
|
1175 |
} |
1176 |
} |
1177 |
if (this.alias != null) { |
1178 |
builder.append(" ");
|
1179 |
builder.append(as_identifier(this.alias));
|
1180 |
} |
1181 |
return builder.toString();
|
1182 |
} |
1183 |
} |
1184 |
|
1185 |
@Override
|
1186 |
public SelectBuilder select() {
|
1187 |
if (this.select == null) { |
1188 |
this.select = this.createSelectBuilder(); |
1189 |
} |
1190 |
return this.select; |
1191 |
} |
1192 |
|
1193 |
@Override
|
1194 |
public UpdateBuilder update() {
|
1195 |
if (this.update == null) { |
1196 |
this.update = this.createUpdateBuilder(); |
1197 |
} |
1198 |
return this.update; |
1199 |
} |
1200 |
|
1201 |
@Override
|
1202 |
public UpdateTableStatisticsBuilder update_table_statistics() {
|
1203 |
if (this.update_table_statistics == null) { |
1204 |
this.update_table_statistics = this.createUpdateTableStatisticsBuilder(); |
1205 |
} |
1206 |
return this.update_table_statistics; |
1207 |
} |
1208 |
|
1209 |
@Override
|
1210 |
public DropTableBuilder drop_table() {
|
1211 |
if (this.drop_table == null) { |
1212 |
this.drop_table = this.createDropTableBuilder(); |
1213 |
} |
1214 |
return this.drop_table; |
1215 |
} |
1216 |
|
1217 |
@Override
|
1218 |
public CreateIndexBuilder create_index() {
|
1219 |
if (this.create_index == null) { |
1220 |
this.create_index = this.createCreateIndexBuilder(); |
1221 |
} |
1222 |
return this.create_index; |
1223 |
} |
1224 |
|
1225 |
@Override
|
1226 |
public DeleteBuilder delete() {
|
1227 |
if (this.delete == null) { |
1228 |
this.delete = this.createDeleteBuilder(); |
1229 |
} |
1230 |
return this.delete; |
1231 |
} |
1232 |
|
1233 |
@Override
|
1234 |
public InsertBuilder insert() {
|
1235 |
if (this.insert == null) { |
1236 |
this.insert = this.createInsertBuilder(); |
1237 |
} |
1238 |
return this.insert; |
1239 |
} |
1240 |
|
1241 |
@Override
|
1242 |
public TableNameBuilder table_name() {
|
1243 |
if (this.table_name == null) { |
1244 |
this.table_name = this.createTableNameBuilder(); |
1245 |
} |
1246 |
return this.table_name; |
1247 |
} |
1248 |
|
1249 |
@Override
|
1250 |
public AlterTableBuilder alter_table() {
|
1251 |
if (this.alter_table == null) { |
1252 |
this.alter_table = this.createAlterTableBuilder(); |
1253 |
} |
1254 |
return this.alter_table; |
1255 |
} |
1256 |
|
1257 |
@Override
|
1258 |
public CreateTableBuilder create_table() {
|
1259 |
if (this.create_table == null) { |
1260 |
this.create_table = this.createCreateTableBuilder(); |
1261 |
} |
1262 |
return this.create_table; |
1263 |
} |
1264 |
|
1265 |
@Override
|
1266 |
public GrantBuilder grant() {
|
1267 |
if (this.grant == null) { |
1268 |
this.grant = this.createGrantBuilder(); |
1269 |
} |
1270 |
return this.grant; |
1271 |
} |
1272 |
|
1273 |
@Override
|
1274 |
public String sqltype(int type, int size, int precision, int scale, int geomType, int geomSubtype) { |
1275 |
switch (type) {
|
1276 |
case DataTypes.DECIMAL:
|
1277 |
if (precision > 38 && scale < 0) { |
1278 |
if (precision > 126) { |
1279 |
precision = 126;
|
1280 |
} |
1281 |
return String.format("FLOAT(%d)", precision); |
1282 |
} |
1283 |
if (precision < 1) { |
1284 |
precision = DataType.DECIMAL_DEFAULT_PRECISION; |
1285 |
} |
1286 |
if (scale < 1) { |
1287 |
return MessageFormat.format(type_decimal_p, precision); |
1288 |
} |
1289 |
return MessageFormat.format(type_decimal_ps, precision, scale); |
1290 |
default:
|
1291 |
return super.sqltype(type, size, precision, scale, geomType, geomSubtype); |
1292 |
} |
1293 |
} |
1294 |
|
1295 |
@Override
|
1296 |
public int getMaxRecomendedSQLLength() { |
1297 |
return 2048; |
1298 |
} |
1299 |
|
1300 |
} |