Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.spi / src / main / java / org / gvsig / fmap / dal / feature / spi / SQLBuilderBase.java @ 47456

History | View | Annotate | Download (138 KB)

1 43020 jjdelcerro
package org.gvsig.fmap.dal.feature.spi;
2
3
import java.text.MessageFormat;
4
import java.util.ArrayList;
5 44042 jjdelcerro
import java.util.Collections;
6 43020 jjdelcerro
import java.util.HashMap;
7
import java.util.HashSet;
8
import java.util.List;
9
import java.util.Map;
10 44042 jjdelcerro
import java.util.Objects;
11 43020 jjdelcerro
import java.util.Set;
12
import org.apache.commons.lang3.StringUtils;
13
import org.apache.commons.lang3.tuple.ImmutablePair;
14
import org.apache.commons.lang3.tuple.Pair;
15 43114 jjdelcerro
import org.cresques.cts.IProjection;
16 45969 fdiaz
import org.gvsig.expressionevaluator.ExpressionBuilder;
17 44198 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionBuilder.AbstractValue;
18
import org.gvsig.expressionevaluator.ExpressionBuilder.ClassVisitorFilter;
19 44644 jjdelcerro
import static org.gvsig.expressionevaluator.ExpressionBuilder.PARAMETER_TYPE_CONSTANT;
20
import static org.gvsig.expressionevaluator.ExpressionBuilder.PARAMETER_TYPE_VARIABLE;
21 44198 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionBuilder.Parameter;
22 46505 fdiaz
import static org.gvsig.expressionevaluator.ExpressionBuilder.VALUE_NULL;
23 44198 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionBuilder.Value;
24
import org.gvsig.expressionevaluator.ExpressionBuilder.Variable;
25
import org.gvsig.expressionevaluator.ExpressionBuilder.Visitable;
26
import org.gvsig.expressionevaluator.ExpressionBuilder.Visitor;
27
import org.gvsig.expressionevaluator.ExpressionBuilder.VisitorFilter;
28
import org.gvsig.expressionevaluator.Formatter;
29 44644 jjdelcerro
import org.gvsig.expressionevaluator.GeometryExpressionBuilder;
30
import org.gvsig.expressionevaluator.GeometryExpressionBuilderHelper.GeometrySupportType;
31
import org.gvsig.expressionevaluator.GeometryExpressionEvaluatorLocator;
32 46015 jjdelcerro
import org.gvsig.fmap.dal.DataManager;
33 44042 jjdelcerro
import org.gvsig.fmap.dal.DataStoreParameters;
34 43020 jjdelcerro
import org.gvsig.fmap.dal.DataTypes;
35
import org.gvsig.fmap.dal.SQLBuilder;
36
import org.gvsig.fmap.dal.SQLBuilder.AlterTableBuilder;
37
import org.gvsig.fmap.dal.SQLBuilder.CreateTableBuilder;
38
import org.gvsig.fmap.dal.SQLBuilder.DeleteBuilder;
39
import org.gvsig.fmap.dal.SQLBuilder.DropTableBuilder;
40
import org.gvsig.fmap.dal.SQLBuilder.FromBuilder;
41
import org.gvsig.fmap.dal.SQLBuilder.GrantBuilder;
42
import org.gvsig.fmap.dal.SQLBuilder.InsertBuilder;
43
import org.gvsig.fmap.dal.SQLBuilder.InsertColumnBuilder;
44
import org.gvsig.fmap.dal.SQLBuilder.OrderByBuilder;
45
import org.gvsig.fmap.dal.SQLBuilder.Privilege;
46
import org.gvsig.fmap.dal.SQLBuilder.SelectBuilder;
47
import org.gvsig.fmap.dal.SQLBuilder.SelectColumnBuilder;
48
import org.gvsig.fmap.dal.SQLBuilder.TableNameBuilder;
49
import org.gvsig.fmap.dal.SQLBuilder.UpdateBuilder;
50
import org.gvsig.fmap.dal.SQLBuilder.UpdateColumnBuilder;
51
import org.gvsig.fmap.dal.SQLBuilder.UpdateTableStatisticsBuilder;
52 43739 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
53 43114 jjdelcerro
import org.gvsig.fmap.geom.Geometry;
54 46493 jjdelcerro
import org.gvsig.fmap.geom.GeometryUtils;
55
import org.gvsig.fmap.geom.primitive.Envelope;
56 44678 jjdelcerro
import org.gvsig.tools.dataTypes.DataType;
57 46493 jjdelcerro
import org.gvsig.tools.dynobject.Tags;
58 46507 jjdelcerro
import org.gvsig.tools.lang.CloneableUtils;
59 46806 jjdelcerro
import org.gvsig.tools.util.Bitmask;
60 46505 fdiaz
import org.gvsig.tools.util.PropertiesSupport;
61 43020 jjdelcerro
import org.slf4j.Logger;
62
import org.slf4j.LoggerFactory;
63
64 44198 jjdelcerro
@SuppressWarnings("UseSpecificCatch")
65 44042 jjdelcerro
public class SQLBuilderBase implements SQLBuilder {
66 44198 jjdelcerro
67
    protected static final Logger LOGGER = LoggerFactory.getLogger(SQLBuilderBase.class);
68
69 43020 jjdelcerro
    protected SelectBuilder select;
70
    protected UpdateBuilder update;
71
    protected InsertBuilder insert;
72
    protected DeleteBuilder delete;
73
    protected AlterTableBuilder alter_table;
74
    protected CreateTableBuilder create_table;
75
    protected GrantBuilder grant;
76
    protected DropTableBuilder drop_table;
77
    protected UpdateTableStatisticsBuilder update_table_statistics;
78 43687 jjdelcerro
    protected CreateIndexBuilder create_index;
79 46099 jjdelcerro
    protected DropIndexBuilder drop_index;
80 44329 jjdelcerro
    protected TableNameBuilder table_name;
81 43020 jjdelcerro
82 44198 jjdelcerro
    protected abstract class AbstractStatementPart extends AbstractValue {
83 46105 omartinez
84 44042 jjdelcerro
    }
85
86 44198 jjdelcerro
    protected abstract class AbstractStatement extends AbstractStatementPart {
87 46105 omartinez
        @Override
88
        public Value clone() throws CloneNotSupportedException {
89
            throw new CloneNotSupportedException();
90
        }
91 44042 jjdelcerro
    }
92
93
    protected class ColumnDescriptorBase implements ColumnDescriptor {
94
95
        private String name;
96
        private int type;
97 44669 jjdelcerro
        private int size;
98
        private int precision;
99
        private int scale;
100 44042 jjdelcerro
        private boolean isPk;
101
        private boolean _allowNulls;
102 47211 jjdelcerro
        private boolean _allowIndexDuplicateds;
103 44042 jjdelcerro
        private boolean _isAutomatic;
104
        private Object defaultValue;
105
        private int geom_type;
106
        private int geom_subtype;
107
        private Object geom_srsdbcode;
108 46493 jjdelcerro
        private Envelope tablebbox;
109 44042 jjdelcerro
        private boolean _isIndexed;
110
        private DataStoreParameters parameters = null;
111
112
        public ColumnDescriptorBase(String name, int type, Object defaultValue) {
113
            this.name = name;
114
            this.type = type;
115 44669 jjdelcerro
            this.size = -1;
116
            this.precision = -1;
117
            this.scale = -1;
118 44042 jjdelcerro
            this.isPk = false;
119
            this._allowNulls = true;
120
            this._isAutomatic = false;
121
            this.defaultValue = defaultValue;
122
            this.geom_type = Geometry.TYPES.GEOMETRY;
123
            this.geom_subtype = Geometry.SUBTYPES.GEOM2D;
124
            this.geom_srsdbcode = null;
125 46493 jjdelcerro
            this.tablebbox = null;
126 44042 jjdelcerro
            this._isIndexed = false;
127 47211 jjdelcerro
            this._allowIndexDuplicateds = true;
128 44042 jjdelcerro
        }
129
130 44669 jjdelcerro
        public ColumnDescriptorBase(String name, int type, int size, int precision, int scale, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
131 47211 jjdelcerro
            this(name, type, size, precision, scale, isPk, isIndexed, allowNulls, isAutomatic, defaultValue, true);
132
        }
133
134
        public ColumnDescriptorBase(String name, int type, int size, int precision, int scale, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue, boolean allowIndexDuplicateds) {
135 44042 jjdelcerro
            this.name = name;
136
            this.type = type;
137 44669 jjdelcerro
            this.size = size;
138
            this.precision = precision;
139
            this.scale = scale;
140 44042 jjdelcerro
            this.isPk = isPk;
141
            this._allowNulls = allowNulls;
142
            this._isAutomatic = isAutomatic;
143
            this.defaultValue = defaultValue;
144
            this.geom_type = Geometry.TYPES.GEOMETRY;
145
            this.geom_subtype = Geometry.SUBTYPES.GEOM2D;
146
            this.geom_srsdbcode = null;
147 46493 jjdelcerro
            this.tablebbox = null;
148 44042 jjdelcerro
            this._isIndexed = isIndexed;
149 47211 jjdelcerro
            this._allowIndexDuplicateds = allowIndexDuplicateds;
150 44042 jjdelcerro
        }
151 44198 jjdelcerro
152 44042 jjdelcerro
        public ColumnDescriptorBase(String name, int geom_type, int geom_subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
153
            this.name = name;
154
            this.type = DataTypes.GEOMETRY;
155 44669 jjdelcerro
            this.size = 0;
156
            this.precision = 0;
157
            this.scale = 0;
158 44042 jjdelcerro
            this.isPk = false;
159
            this._allowNulls = allowNulls;
160
            this._isAutomatic = false;
161
            this.defaultValue = null;
162
            this.geom_type = geom_type;
163
            this.geom_subtype = geom_subtype;
164 44198 jjdelcerro
            this.geom_srsdbcode = srs_id(proj);
165 46493 jjdelcerro
            this.tablebbox = null;
166 44042 jjdelcerro
            this._isIndexed = isIndexed;
167 47211 jjdelcerro
            this._allowIndexDuplicateds = true;
168 44042 jjdelcerro
        }
169 44198 jjdelcerro
170 44042 jjdelcerro
        public ColumnDescriptorBase(String name, int geom_type, int geom_subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
171
            this.name = name;
172
            this.type = DataTypes.GEOMETRY;
173 44669 jjdelcerro
            this.size = 0;
174
            this.precision = 0;
175
            this.scale = 0;
176 44042 jjdelcerro
            this.isPk = false;
177
            this._allowNulls = allowNulls;
178
            this._isAutomatic = false;
179
            this.defaultValue = null;
180
            this.geom_type = geom_type;
181
            this.geom_subtype = geom_subtype;
182
            this.geom_srsdbcode = srsdbcode;
183 46493 jjdelcerro
            this.tablebbox = null;
184 44042 jjdelcerro
            this._isIndexed = isIndexed;
185 47211 jjdelcerro
            this._allowIndexDuplicateds = true;
186 44042 jjdelcerro
        }
187 44198 jjdelcerro
188
        private ColumnDescriptorBase(FeatureAttributeDescriptor fad) {
189
            this(fad.getName(), fad.getType(), fad.getDefaultValue());
190 44669 jjdelcerro
            this.precision = fad.getPrecision();
191
            this.size = fad.getSize();
192
            this.scale = fad.getScale();
193 44198 jjdelcerro
            this.isPk = fad.isPrimaryKey();
194
            this._allowNulls = fad.allowNull();
195
            this._isAutomatic = fad.isAutomatic();
196
            this._isIndexed = fad.isIndexed();
197 47211 jjdelcerro
            this._allowIndexDuplicateds = fad.allowIndexDuplicateds();
198 44198 jjdelcerro
199
            if (fad.getType() == org.gvsig.fmap.geom.DataTypes.GEOMETRY) {
200
                this.geom_type = fad.getGeomType().getType();
201
                this.geom_subtype = fad.getGeomType().getSubType();
202 46493 jjdelcerro
                this.geom_srsdbcode =  srs_id(fad.getSRS());
203
                this.tablebbox = null;
204
                Tags tags = fad.getTags();
205
                String s = tags.getString("tablebbox", null);
206
                if( StringUtils.isNotBlank(s) ) {
207
                    try {
208
                        Geometry g = GeometryUtils.createFrom(s);
209
                        if( g!=null ) {
210
                            this.tablebbox = g.getEnvelope();
211
                        }
212
                    } catch(Exception ex) {
213
                        LOGGER.warn("Can't parse tablebbox for column '"+s+"'.",ex);
214
                    }
215
                }
216 44198 jjdelcerro
            }
217
        }
218
219
220 44042 jjdelcerro
        @Override
221
        public String getName() {
222
            return this.name;
223
        }
224 44198 jjdelcerro
225 44042 jjdelcerro
        @Override
226
        public void setName(String name) {
227
            this.name = name;
228
        }
229
230
        @Override
231
        public int getType() {
232
            return this.type;
233
        }
234
235
        @Override
236
        public void setType(int type) {
237
            this.type = type;
238
        }
239
240
        @Override
241
        public int getPrecision() {
242 44669 jjdelcerro
            return precision;
243 44042 jjdelcerro
        }
244
245
        @Override
246
        public void setPrecision(int precision) {
247 44669 jjdelcerro
            this.precision = precision;
248 44042 jjdelcerro
        }
249
250
        @Override
251 44669 jjdelcerro
        public int getScale() {
252
            return scale;
253
        }
254
255
        @Override
256
        public void setScale(int scale) {
257
            this.scale = scale;
258
        }
259
260
        @Override
261 44042 jjdelcerro
        public int getSize() {
262 44669 jjdelcerro
            return size;
263 44042 jjdelcerro
        }
264
265
        @Override
266
        public void setSize(int size) {
267 44669 jjdelcerro
            this.size = size;
268 44042 jjdelcerro
        }
269
270
        @Override
271
        public boolean isPrimaryKey() {
272
            return isPk;
273
        }
274
275
        @Override
276
        public void setIsPrimaryKey(boolean isPk) {
277
            this.isPk = isPk;
278
        }
279
280
        @Override
281
        public boolean allowNulls() {
282
            return _allowNulls;
283
        }
284
285
        @Override
286
        public void setAllowNulls(boolean allowNulls) {
287
            this._allowNulls = allowNulls;
288
        }
289
290
        @Override
291
        public boolean isAutomatic() {
292
            return _isAutomatic;
293
        }
294
295
        @Override
296
        public boolean isIndexed() {
297
            return _isIndexed;
298
        }
299
300
        @Override
301
        public void setIsAutomatic(boolean isAutomatic) {
302
            this._isAutomatic = isAutomatic;
303
        }
304
305
        @Override
306
        public Object getDefaultValue() {
307
            return defaultValue;
308
        }
309
310
        @Override
311
        public void setDefaultValue(Object defaultValue) {
312
            this.defaultValue = defaultValue;
313
        }
314
315
        @Override
316
        public int getGeometryType() {
317
            return geom_type;
318
        }
319
320
        @Override
321
        public void setGeometryType(int geom_type) {
322
            this.geom_type = geom_type;
323
        }
324
325
        @Override
326
        public int getGeometrySubtype() {
327
            return geom_subtype;
328
        }
329
330
        @Override
331
        public void setGeometrySubtype(int geom_subtype) {
332
            this.geom_subtype = geom_subtype;
333
        }
334
335
        @Override
336
        public Object getGeometrySRSId() {
337
            return geom_srsdbcode;
338
        }
339
340
        @Override
341
        public void setGeometrySRSId(Object geom_srsid) {
342
            this.geom_srsdbcode = geom_srsid;
343 44198 jjdelcerro
        }
344 44042 jjdelcerro
345
        @Override
346
        public boolean isGeometry() {
347
            return this.type == DataTypes.GEOMETRY;
348
        }
349
350
        private void setStoreParameters(DataStoreParameters parameters) {
351
            this.parameters = parameters;
352
        }
353
354
        @Override
355
        public DataStoreParameters getStoreParameters() {
356
            return this.parameters;
357
        }
358 46493 jjdelcerro
359
        public Envelope getTableBBox() {
360
            return this.tablebbox;
361
        }
362
363
        public void setTableBBox(Envelope bbox) {
364
            this.tablebbox = bbox;
365
        }
366 47211 jjdelcerro
367
        @Override
368
        public boolean allowIndexDuplicateds() {
369
            return this._allowIndexDuplicateds;
370
        }
371
372
        @Override
373
        public void setAllowIndexDuplicateds(boolean allowIndexDuplicateds) {
374
            this._allowIndexDuplicateds = allowIndexDuplicateds;
375
        }
376
377 44042 jjdelcerro
    }
378
379 44376 jjdelcerro
    public class ColumnBase extends AbstractValue implements Column {
380
381 44644 jjdelcerro
        private final String name;
382 44376 jjdelcerro
        private TableNameBuilder table;
383
384
        public ColumnBase(TableNameBuilder table, String name) {
385
            this.name = name;
386
            this.table = table;
387
        }
388 46105 omartinez
389
        @Override
390
        public ColumnBase clone() throws CloneNotSupportedException {
391
            ColumnBase other = (ColumnBase) super.clone();
392
            other.table = (TableNameBuilder) org.gvsig.tools.lang.Cloneable.cloneQuietly(table);
393
            return other;
394
        }
395 44376 jjdelcerro
396 46105 omartinez
397 44376 jjdelcerro
        @Override
398
        public String name() {
399
            return this.name;
400
        }
401
402
        @Override
403
        public TableNameBuilder table() {
404
            return this.table;
405
        }
406
407
        @Override
408
        public TableNameBuilder table(TableNameBuilder table) {
409
            this.table = table;
410
            return this.table;
411
        }
412
413
        @Override
414
        public String toString() {
415 44769 jjdelcerro
            return this.toString(formatter());
416 44376 jjdelcerro
        }
417
418
        @Override
419
        public String toString(Formatter<Value> formatter) {
420
            if( formatter!=null && formatter.canApply(this) ) {
421
                return formatter.format(this);
422
            }
423
            if( this.table==null ) {
424
                return as_identifier(this.name);
425
            }
426
            return this.table.toString(formatter) + "." + as_identifier(this.name);
427
        }
428
429
        @Override
430
        public int compareTo(Variable o) {
431
            return this.name.compareTo(o.name());
432
        }
433
434
        @Override
435
        public boolean equals(Object obj) {
436
            if (!(obj instanceof Variable)) {
437
                return false;
438
            }
439
            return StringUtils.equals(this.toString(), ((Variable) obj).toString());
440
        }
441
442
        @Override
443
        public int hashCode() {
444
            int hash = 7;
445
            hash = 37 * hash + Objects.hashCode(this.toString());
446
            return hash;
447
        }
448 46518 fdiaz
449
        @Override
450
        public void setProperty(String name, Object value) {
451
            super.setProperty(name, value);
452
            if(this.table != null){
453
                this.table.setProperty(name, value);
454
            }
455
        }
456
457
458 44376 jjdelcerro
    }
459
460 44198 jjdelcerro
    public class TableNameBuilderBase
461
            extends AbstractStatementPart
462
            implements TableNameBuilder {
463 44042 jjdelcerro
464 43020 jjdelcerro
        public String tableName;
465
        public String schemaName;
466
        private String databaseName;
467
468
        public TableNameBuilderBase() {
469
        }
470 46105 omartinez
471 43020 jjdelcerro
        @Override
472
        public void accept(Visitor visitor, VisitorFilter filter) {
473 45155 omartinez
            if (filter==null || filter.accept(this)) {
474 43020 jjdelcerro
                visitor.visit(this);
475
            }
476
        }
477
478
        @Override
479
        public TableNameBuilder database(String name) {
480
            this.databaseName = name;
481
            return this;
482
        }
483
484
        @Override
485
        public TableNameBuilder schema(String name) {
486 44198 jjdelcerro
            if (support_schemas()) {
487 43355 jjdelcerro
                this.schemaName = name;
488
            }
489 43020 jjdelcerro
            return this;
490
        }
491
492
        @Override
493
        public TableNameBuilder name(String name) {
494
            this.tableName = name;
495
            return this;
496
        }
497
498
        @Override
499
        public String getDatabase() {
500
            return this.databaseName;
501
        }
502
503
        @Override
504
        public String getSchema() {
505
            return this.schemaName;
506
        }
507
508
        @Override
509
        public String getName() {
510
            return this.tableName;
511
        }
512 44198 jjdelcerro
513 43020 jjdelcerro
        @Override
514
        public boolean has_schema() {
515 44198 jjdelcerro
            if (!support_schemas()) {
516 43355 jjdelcerro
                return false;
517
            }
518 46510 jjdelcerro
            return StringUtils.isNotBlank(this.schemaName);
519 43020 jjdelcerro
        }
520
521
        @Override
522 46505 fdiaz
        public boolean has_name() {
523 46510 jjdelcerro
            return StringUtils.isNotBlank(this.tableName);
524 46505 fdiaz
        }
525
526
        @Override
527 43020 jjdelcerro
        public boolean has_database() {
528 46510 jjdelcerro
            return StringUtils.isNotBlank(this.databaseName);
529 43020 jjdelcerro
        }
530 44198 jjdelcerro
531 43020 jjdelcerro
        @Override
532 46507 jjdelcerro
        public boolean isEmpty() {
533
            return !this.has_database() && !this.has_schema() && !this.has_name();
534
        }
535
536
        @Override
537 43020 jjdelcerro
        public String toString() {
538 44198 jjdelcerro
            return this.toString(formatter());
539
        }
540
541
        @Override
542
        public String toString(Formatter<Value> formatter) {
543 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
544 44198 jjdelcerro
                return formatter.format(this);
545
            }
546
            if (this.has_database()) {
547
                if (this.has_schema()) {
548
                    return as_identifier(this.databaseName) + "."
549
                            + as_identifier(this.schemaName) + "."
550
                            + as_identifier(this.tableName);
551 43020 jjdelcerro
                }
552 46517 fdiaz
//                return as_identifier(this.databaseName) + "."
553
//                        + as_identifier(this.tableName);
554 43020 jjdelcerro
            } else {
555 44198 jjdelcerro
                if (this.has_schema()) {
556
                    return as_identifier(this.schemaName) + "."
557
                            + as_identifier(this.tableName);
558
                }
559 43020 jjdelcerro
            }
560 44198 jjdelcerro
            return as_identifier(this.tableName);
561 43020 jjdelcerro
        }
562
563 44329 jjdelcerro
        @Override
564
        public boolean equals(Object obj) {
565
            if( obj==null || !(obj instanceof TableNameBuilder) ) {
566
                return false;
567
            }
568
            TableNameBuilder other = (TableNameBuilder) obj;
569 45664 fdiaz
570
            if (this.has_database() != other.has_database()) {
571
                return false;
572
            }
573
            String thisSchema = null;
574
            String otherSchema = null;
575
            if(support_schemas()) {
576
                thisSchema = this.schemaName;
577
                if (StringUtils.isBlank(thisSchema)) {
578
                    thisSchema = default_schema();
579 44329 jjdelcerro
                }
580 45664 fdiaz
                otherSchema = other.getSchema();
581
                if (StringUtils.isBlank(otherSchema)) {
582
                    otherSchema = default_schema();
583 44329 jjdelcerro
                }
584
            }
585 45664 fdiaz
            if (this.has_database()) {
586
                    return StringUtils.equals(this.databaseName,other.getDatabase()) &&
587
                           StringUtils.equals(thisSchema, otherSchema) &&
588
                           StringUtils.equals(this.tableName,other.getName());
589
            } else {
590
                    return StringUtils.equals(thisSchema, otherSchema) &&
591
                           StringUtils.equals(this.tableName,other.getName());
592
            }
593 44329 jjdelcerro
        }
594
595 44376 jjdelcerro
        @Override
596
        public int hashCode() {
597
            int hash = 7;
598
            hash = 37 * hash + Objects.hashCode(this.toString());
599
            return hash;
600
        }
601
602 43020 jjdelcerro
    }
603
604 44198 jjdelcerro
    public class CountBuilderBase
605
            extends AbstractStatementPart
606
            implements CountBuilder {
607 43020 jjdelcerro
608
        protected Value value;
609
        protected boolean distinct;
610 44198 jjdelcerro
        protected boolean all;
611
612 43020 jjdelcerro
        public CountBuilderBase() {
613
            this.value = null;
614
            this.distinct = false;
615
            this.all = false;
616
        }
617 46105 omartinez
618 43020 jjdelcerro
        @Override
619 46105 omartinez
        public CountBuilderBase clone() throws CloneNotSupportedException {
620
            CountBuilderBase other = (CountBuilderBase) super.clone();
621
            other.value = (Value) org.gvsig.tools.lang.Cloneable.cloneQuietly(value);
622
            return other;
623
        }
624
625
        @Override
626 43020 jjdelcerro
        public CountBuilder all() {
627
            this.all = true;
628
            return this;
629
        }
630
631
        @Override
632
        public CountBuilder column(Value value) {
633
            this.value = value;
634
            return this;
635
        }
636
637
        @Override
638
        public CountBuilder distinct() {
639
            this.distinct = true;
640
            return this;
641
        }
642
643
        @Override
644
        public String toString() {
645 44198 jjdelcerro
            return this.toString(formatter());
646
        }
647
648
        @Override
649
        public String toString(Formatter formatter) {
650 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
651 44198 jjdelcerro
                return formatter.format(this);
652 43020 jjdelcerro
            }
653 44198 jjdelcerro
            if (this.all) {
654
                return "COUNT(*)";
655
            }
656
            if (this.distinct) {
657 43020 jjdelcerro
                return MessageFormat.format(
658 44198 jjdelcerro
                        "COUNT(DISTINCT {0})",
659
                        value.toString(formatter)
660 43020 jjdelcerro
                );
661
            }
662
            return MessageFormat.format(
663 44198 jjdelcerro
                    "COUNT({0})",
664
                    value.toString(formatter)
665 43020 jjdelcerro
            );
666
        }
667 44198 jjdelcerro
668 43020 jjdelcerro
    }
669
670 44376 jjdelcerro
    protected class JoinBase
671
            extends AbstractStatementPart
672 46517 fdiaz
            implements JoinBuilder
673 44376 jjdelcerro
        {
674
        protected String type;
675
        protected TableNameBuilder table;
676
        protected Value expression;
677
678
        public JoinBase(String type, TableNameBuilder table, Value expression) {
679
            this.type = type;
680
            this.table = table;
681
            this.expression = expression;
682
        }
683 46105 omartinez
684
        @Override
685
        public JoinBase clone() throws CloneNotSupportedException {
686
            JoinBase other = (JoinBase) super.clone();
687
            other.table = (TableNameBuilder) org.gvsig.tools.lang.Cloneable.cloneQuietly(table);
688
            other.expression = (Value) org.gvsig.tools.lang.Cloneable.cloneQuietly(expression);
689
            return other;
690
        }
691 44376 jjdelcerro
692
        @Override
693
        public String toString() {
694
            return this.toString(formatter());
695
        }
696
697
        @Override
698
        public String toString(Formatter<Value> formatter) {
699
            if (formatter!=null && formatter.canApply(this)) {
700
                return formatter.format(this);
701
            }
702
            StringBuilder builder = new StringBuilder();
703
            // INNER JOIN Customers ON Orders.CustomerID = Customers.CustomerID
704
            builder.append(this.type.toUpperCase());
705
            builder.append(" JOIN ");
706
            builder.append(this.table.toString(formatter));
707
            builder.append(" ON ");
708
            builder.append(this.expression.toString(formatter));
709
            return builder.toString();
710
        }
711
712 46517 fdiaz
        @Override
713
        public TableNameBuilder getTable() {
714
            return this.table;
715
        }
716 44376 jjdelcerro
717 46517 fdiaz
        @Override
718
        public String getType() {
719
            return this.type;
720
        }
721
722
        @Override
723
        public Value getCondition() {
724
            return this.expression;
725
        }
726 47318 fdiaz
727
        @Override
728
        public void accept(Visitor visitor, VisitorFilter filter) {
729
            boolean visitChildren = true;
730
            if (filter==null || filter.accept(this)) {
731
                visitor.visit(this);
732
            } else {
733
                visitChildren = !filter.skipChildren();
734
            }
735
            if(visitChildren){
736
                if (this.expression != null) {
737
                    this.expression.accept(visitor, filter);
738
                }
739
            }
740
        }
741
742 44376 jjdelcerro
    }
743
744 44198 jjdelcerro
    public class FromBuilderBase
745
            extends AbstractStatementPart
746
            implements FromBuilder {
747
748 44376 jjdelcerro
        protected TableNameBuilder tableName;
749 45131 fdiaz
        protected String subquery;
750
        protected String passthrough;
751 46517 fdiaz
        protected List<JoinBuilder> joins;
752 43020 jjdelcerro
753 44376 jjdelcerro
        public FromBuilderBase() {
754
            this.tableName = null;
755
            this.subquery = null;
756
            this.passthrough = null;
757
            this.joins = null;
758
        }
759 46105 omartinez
760
        @Override
761
        public FromBuilderBase clone() throws CloneNotSupportedException {
762
            FromBuilderBase other = (FromBuilderBase) super.clone();
763
            other.tableName = (TableNameBuilder) org.gvsig.tools.lang.Cloneable.cloneQuietly(tableName);
764
            if (joins!=null) {
765
                for (int i = 0; i < joins.size(); i++) {
766
                    other.joins.set(i, (JoinBase) joins.get(i).clone());
767
                }
768
            }
769
            return other;
770
        }
771 44376 jjdelcerro
772 43020 jjdelcerro
        @Override
773 44376 jjdelcerro
        public FromBuilder left_join(TableNameBuilder table, Value expression) {
774
            JoinBase join = createJoin("LEFT", table, expression);
775
            if( this.joins==null ) {
776
                this.joins = new ArrayList<>();
777
            }
778
            this.joins.add(join);
779
            return this;
780
        }
781
782
        @Override
783 43020 jjdelcerro
        public TableNameBuilder table() {
784 44198 jjdelcerro
            if (tableName == null) {
785 43114 jjdelcerro
                this.tableName = createTableNameBuilder();
786 43020 jjdelcerro
            }
787
            return this.tableName;
788
        }
789
790
        @Override
791
        public void accept(Visitor visitor, VisitorFilter filter) {
792 46505 fdiaz
            boolean visitChildren = true;
793 45155 omartinez
            if (filter==null || filter.accept(this)) {
794 43020 jjdelcerro
                visitor.visit(this);
795 46505 fdiaz
            } else {
796
                visitChildren = !filter.skipChildren();
797 43020 jjdelcerro
            }
798 46505 fdiaz
            if(visitChildren){
799
                if (this.tableName != null) {
800
                    this.tableName.accept(visitor, filter);
801
                }
802 47318 fdiaz
                if(this.joins != null) {
803
                    for (JoinBuilder join : joins) {
804
                        join.accept(visitor, filter);
805
                    }
806
                }
807 43020 jjdelcerro
            }
808
        }
809
810
        @Override
811
        public FromBuilder custom(String passthrough) {
812
            this.passthrough = passthrough;
813
            return this;
814
        }
815
816
        @Override
817
        public FromBuilder subquery(String subquery) {
818
            this.subquery = subquery;
819
            return this;
820
        }
821 44198 jjdelcerro
822 43020 jjdelcerro
        @Override
823
        public String toString() {
824 44198 jjdelcerro
            return this.toString(formatter());
825
        }
826
827
        @Override
828
        public String toString(Formatter<Value> formatter) {
829 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
830 44198 jjdelcerro
                return formatter.format(this);
831
            }
832
            if (!StringUtils.isEmpty(passthrough)) {
833 43020 jjdelcerro
                return passthrough;
834
            }
835 44198 jjdelcerro
            if (!StringUtils.isEmpty(subquery)) {
836 46507 jjdelcerro
                return "( " + this.subquery + ") AS _subquery_alias_ ";
837 43020 jjdelcerro
            }
838 44376 jjdelcerro
            if( this.joins==null || this.joins.isEmpty() ) {
839
                return this.tableName.toString(formatter);
840
            }
841
            StringBuilder builder = new StringBuilder();
842
            builder.append(this.tableName.toString(formatter));
843 46517 fdiaz
            for (JoinBuilder join : this.joins) {
844 44376 jjdelcerro
                builder.append(" ");
845
                builder.append(join.toString(formatter));
846
            }
847
            return builder.toString();
848 43020 jjdelcerro
        }
849
850 46517 fdiaz
        @Override
851
        public List<JoinBuilder> getJoins() {
852
            return this.joins;
853
        }
854
855 43020 jjdelcerro
    }
856
857 44198 jjdelcerro
    public class SelectColumnBuilderBase
858
            extends AbstractStatementPart
859
            implements SelectColumnBuilder {
860 43020 jjdelcerro
861 46505 fdiaz
        protected Column name = null;
862 45131 fdiaz
        protected String alias = null;
863
        protected Value value = null;
864
        protected boolean asGeometry = false;
865
        protected TableNameBuilder table;
866 46258 jjdelcerro
        protected SQLBuilder sqlbuilder;
867 46105 omartinez
868 46258 jjdelcerro
        public SelectColumnBuilderBase(SQLBuilder sqlbuilder) {
869
            this.sqlbuilder = sqlbuilder;
870
        }
871
872 46105 omartinez
        @Override
873
        public SelectColumnBuilderBase clone() throws CloneNotSupportedException {
874
            SelectColumnBuilderBase other = (SelectColumnBuilderBase) super.clone();
875
            other.value = (Value) org.gvsig.tools.lang.Cloneable.cloneQuietly(value);
876 46505 fdiaz
            other.name = (Column) org.gvsig.tools.lang.Cloneable.cloneQuietly(name);
877 46105 omartinez
            other.table = (TableNameBuilder) org.gvsig.tools.lang.Cloneable.cloneQuietly(table);
878
            return other;
879
        }
880 44198 jjdelcerro
881 43020 jjdelcerro
        @Override
882
        public void accept(Visitor visitor, VisitorFilter filter) {
883 46505 fdiaz
            boolean visitChildren = true;
884 45155 omartinez
            if (filter==null || filter.accept(this)) {
885 43020 jjdelcerro
                visitor.visit(this);
886 46505 fdiaz
            } else {
887
                visitChildren = !filter.skipChildren();
888 43020 jjdelcerro
            }
889 46505 fdiaz
            if(visitChildren){
890
                if (this.value != null) {
891
                    this.value.accept(visitor, filter);
892
                } else if (this.name != null) {
893
                    this.name.accept(visitor, filter);
894
                }
895 43020 jjdelcerro
            }
896
        }
897
898
        @Override
899 44376 jjdelcerro
        public void replace(Value target, Value replacement) {
900
            if (this.name!=null ) {
901
                if( this.name == target) {
902 46505 fdiaz
                    if(replacement == null){
903
                        this.name = null;
904
                    } else if(replacement instanceof Column){
905
                        this.name = (Column) replacement;
906
                    } else if(replacement instanceof Variable){
907
                        this.name = new ColumnBase(this.table, ((Variable) replacement).name());
908
                    } else {
909
                        this.value = replacement;
910
                    }
911 44376 jjdelcerro
                }
912
            }
913
            if( this.value!=null ) {
914
                if (this.value == target) {
915
                    this.value = replacement;
916
                } else {
917
                    this.value.replace(target, replacement);
918
                }
919
            }
920
        }
921 44712 jjdelcerro
922 44376 jjdelcerro
        @Override
923 43020 jjdelcerro
        public SelectColumnBuilder name(String name) {
924 46507 jjdelcerro
            return this.name(this.table, name);
925 44376 jjdelcerro
        }
926
927
        @Override
928
        public SelectColumnBuilder name(TableNameBuilder table, String name) {
929 44198 jjdelcerro
            String quote = quote_for_identifiers();
930 43020 jjdelcerro
            if (name.startsWith(quote)) {
931
                // Remove quotes
932
                name = name.substring(1, name.length() - 1);
933
            }
934 44376 jjdelcerro
            this.table = table;
935 46505 fdiaz
            this.name = new ColumnBase(this.table, name);
936 43020 jjdelcerro
            this.value = null;
937
            this.asGeometry = false;
938
            return this;
939
        }
940 46507 jjdelcerro
941
        public SelectColumnBuilder table(TableNameBuilder table) {
942
            this.table = table;
943 46517 fdiaz
            if(this.name != null){
944
                this.name.table(table);
945
            }
946 46507 jjdelcerro
            return this;
947
        }
948
949 43020 jjdelcerro
        @Override
950
        public SelectColumnBuilder all() {
951
            this.name = null;
952 44198 jjdelcerro
            this.value = expression().custom("*");
953 43020 jjdelcerro
            this.asGeometry = false;
954
            return this;
955
        }
956 44198 jjdelcerro
957 43020 jjdelcerro
        @Override
958
        public SelectColumnBuilder as_geometry() {
959
            this.asGeometry = true;
960
            return this;
961
        }
962 44198 jjdelcerro
963 43020 jjdelcerro
        @Override
964
        public SelectColumnBuilder value(Value value) {
965
            this.value = value;
966
            return this;
967
        }
968
969
        @Override
970
        public SelectColumnBuilder as(String alias) {
971
            this.alias = alias;
972
            return this;
973
        }
974
975
        @Override
976
        public String getName() {
977 45166 omartinez
            if (this.name==null) {
978
                return null;
979
            }
980 44198 jjdelcerro
            return this.name.name();
981 43020 jjdelcerro
        }
982 44198 jjdelcerro
983 43020 jjdelcerro
        @Override
984
        public String getAlias() {
985
            return this.alias;
986
        }
987 44198 jjdelcerro
988 43020 jjdelcerro
        @Override
989 46505 fdiaz
        public Value getValue() {
990
            return this.value;
991 43020 jjdelcerro
        }
992
993
        @Override
994
        public String toString() {
995 44198 jjdelcerro
            return this.toString(formatter());
996
        }
997
998
        @Override
999
        public String toString(Formatter<Value> formatter) {
1000 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
1001 44198 jjdelcerro
                return formatter.format(this);
1002
            }
1003 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
1004 44198 jjdelcerro
            if (this.asGeometry) {
1005 46505 fdiaz
                if(this.value == VALUE_NULL){
1006
                    builder.append(this.value.toString(formatter));
1007
                } else {
1008 47456 jjdelcerro
                    switch(expression().geometry_support_type()) {
1009
                        case WKB:
1010
                            builder.append(expression().ST_AsBinary(this.name).toString(formatter));
1011
                            break;
1012
                        case EWKB:
1013
                            builder.append(expression().ST_AsEWKB(this.name).toString(formatter));
1014
                            break;
1015
                        case WKT:
1016
                            builder.append(expression().ST_AsText(this.name).toString(formatter));
1017
                            break;
1018
                        case NATIVE:
1019
                            builder.append(as_identifier(this.name.toString(formatter)));
1020
                            break;
1021
                    }
1022 46505 fdiaz
                }
1023 43020 jjdelcerro
            } else {
1024 46505 fdiaz
                if (this.value == null) {
1025
                    builder.append(this.name.toString(formatter));
1026 43020 jjdelcerro
                } else {
1027 44198 jjdelcerro
                    builder.append(this.value.toString(formatter));
1028 43020 jjdelcerro
                }
1029
            }
1030 44198 jjdelcerro
            if (this.alias != null) {
1031 43020 jjdelcerro
                builder.append(" AS ");
1032 44198 jjdelcerro
                builder.append(as_identifier(this.alias));
1033 43020 jjdelcerro
            }
1034
            return builder.toString();
1035
        }
1036 46258 jjdelcerro
1037
        @Override
1038 45008 omartinez
        public boolean isGeometry() {
1039
            return this.asGeometry;
1040
        }
1041
1042 46258 jjdelcerro
        @Override
1043 45008 omartinez
        public TableNameBuilder getTable() {
1044
            return this.table;
1045
        }
1046 46258 jjdelcerro
1047
        @Override
1048
        public boolean isAggregateFunction() {
1049
            if( this.value == null ) {
1050
                return false;
1051
            }
1052
            if( !(this.value instanceof ExpressionBuilder.Function) ) {
1053
                return false;
1054
            }
1055
            String funcname = ((ExpressionBuilder.Function)this.value).name();
1056
            return this.sqlbuilder.isAggregateFunction(funcname);
1057
        }
1058 43020 jjdelcerro
    }
1059
1060 44198 jjdelcerro
    public class OrderByBuilderBase
1061
            extends AbstractStatementPart
1062
            implements OrderByBuilder {
1063
1064 45162 omartinez
        protected Value value;
1065 43020 jjdelcerro
        protected String custom;
1066
        protected boolean ascending;
1067 46401 jjdelcerro
        protected int nullsMode;
1068 44198 jjdelcerro
1069 43020 jjdelcerro
        public OrderByBuilderBase() {
1070 43114 jjdelcerro
            this.ascending = true;
1071 46401 jjdelcerro
            this.nullsMode = MODE_NULLS_LAST;
1072 43020 jjdelcerro
        }
1073 46105 omartinez
1074 43020 jjdelcerro
        @Override
1075 46105 omartinez
        public OrderByBuilderBase clone() throws CloneNotSupportedException {
1076
            OrderByBuilderBase other = (OrderByBuilderBase) super.clone();
1077
            other.value = (Value) org.gvsig.tools.lang.Cloneable.cloneQuietly(value);
1078
            return other;
1079
        }
1080
1081
        @Override
1082 43020 jjdelcerro
        public void accept(Visitor visitor, VisitorFilter filter) {
1083 46505 fdiaz
            boolean visitChildren = true;
1084 45155 omartinez
            if (filter==null || filter.accept(this)) {
1085 43020 jjdelcerro
                visitor.visit(this);
1086 46505 fdiaz
            } else {
1087
                visitChildren = !filter.skipChildren();
1088 43020 jjdelcerro
            }
1089 46505 fdiaz
            if(visitChildren){
1090
                if (this.value!=null) {
1091
                    this.value.accept(visitor, filter);
1092
                }
1093 45162 omartinez
            }
1094 43020 jjdelcerro
        }
1095
1096
        @Override
1097
        public OrderByBuilder column(String name) {
1098 45162 omartinez
            this.value = expression().variable(name);
1099
            return this;
1100
        }
1101
1102
        @Override
1103 45969 fdiaz
        public boolean isColumn(String name) {
1104
            if(this.value instanceof ExpressionBuilder.Variable){
1105
                return StringUtils.equalsIgnoreCase(((ExpressionBuilder.Variable)this.value).name(), name);
1106
            }
1107
            return false;
1108
        }
1109
1110
        @Override
1111 46105 omartinez
        public boolean isColumn(Value value) {
1112
            if(value instanceof ExpressionBuilder.Variable){
1113
                return isColumn(((ExpressionBuilder.Variable)value).name());
1114
            }
1115
            return this.value == value;
1116
        }
1117
1118
        @Override
1119 45538 fdiaz
        public OrderByBuilder value(Value expression) {
1120
            this.value = expression;
1121 43020 jjdelcerro
            return this;
1122
        }
1123 45162 omartinez
1124 43020 jjdelcerro
        @Override
1125
        public OrderByBuilder custom(String order) {
1126
            this.custom = order;
1127
            return this;
1128
        }
1129
1130
        @Override
1131
        public OrderByBuilder ascending() {
1132
            this.ascending = true;
1133
            return this;
1134
        }
1135
1136
        @Override
1137
        public OrderByBuilder ascending(boolean asc) {
1138
            this.ascending = asc;
1139
            return this;
1140
        }
1141
1142
        @Override
1143
        public OrderByBuilder descending() {
1144
            this.ascending = false;
1145
            return this;
1146
        }
1147
1148
        @Override
1149 46401 jjdelcerro
        public OrderByBuilder nulls(int mode) {
1150
            this.nullsMode = mode;
1151
            return this;
1152
        }
1153
1154
        @Override
1155
        public int getNullsMode() {
1156
            return this.nullsMode;
1157
        }
1158
1159
        @Override
1160 43020 jjdelcerro
        public String toString() {
1161 44198 jjdelcerro
            return this.toString(formatter());
1162
        }
1163
1164
        @Override
1165
        public String toString(Formatter<Value> formatter) {
1166 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
1167 44198 jjdelcerro
                return formatter.format(this);
1168
            }
1169
            if (!StringUtils.isEmpty(this.custom)) {
1170 43020 jjdelcerro
                return this.custom;
1171
            }
1172 46401 jjdelcerro
            String order_s = this.value.toString(formatter);
1173 44198 jjdelcerro
            if (this.ascending) {
1174 46401 jjdelcerro
                order_s += " ASC";
1175
            } else {
1176
                order_s += " DESC";
1177 43020 jjdelcerro
            }
1178 46401 jjdelcerro
            switch(this.nullsMode) {
1179
                case MODE_NULLS_NOT_SPECIFIED:
1180
                    break;
1181
                case MODE_NULLS_FIRST:
1182
                    order_s += " NULLS FIRST";
1183
                    break;
1184
                case MODE_NULLS_LAST:
1185
                default:
1186
                    order_s += " NULLS LAST";
1187
                    break;
1188
            }
1189
            return order_s;
1190 43020 jjdelcerro
        }
1191 46505 fdiaz
1192
        @Override
1193
        public void replace(Value target, Value replacement) {
1194
            super.replace(target, replacement);
1195
            if(target == this.value){
1196
                this.value = replacement;
1197
                return;
1198
            }
1199
            if(this.value == null){
1200
                return;
1201
            }
1202
            this.value.replace(target, replacement);
1203
        }
1204
1205
1206 43020 jjdelcerro
    }
1207
1208 44198 jjdelcerro
    public class SelectBuilderBase
1209
            extends AbstractStatement
1210
            implements SelectBuilder {
1211
1212 43020 jjdelcerro
        protected FromBuilder from;
1213 44644 jjdelcerro
        protected GeometryExpressionBuilder where;
1214 43020 jjdelcerro
        protected long limit = -1;
1215
        protected long offset = -1;
1216
        protected List<SelectColumnBuilder> columns;
1217
        protected List<OrderByBuilder> order_by;
1218
        protected boolean distinct;
1219 45155 omartinez
        protected List<Value> groupColumn;
1220 44687 jjdelcerro
        protected boolean check_order_and_offset = true;
1221 43020 jjdelcerro
1222
        public SelectBuilderBase() {
1223
            this.columns = new ArrayList<>();
1224
            this.distinct = false;
1225
        }
1226 45162 omartinez
        @Override
1227
        public List<Value> getGroups() {
1228
            return this.groupColumn;
1229
        }
1230 45385 omartinez
1231 46258 jjdelcerro
        @Override
1232 45385 omartinez
        public List<SelectColumnBuilder> getColumns() {
1233
            return Collections.unmodifiableList(this.columns);
1234
    }
1235 46104 omartinez
1236 46258 jjdelcerro
        @Override
1237 46104 omartinez
        public void remove_column(String columnName) {
1238
            SelectColumnBuilder found = null;
1239
            for (SelectColumnBuilder column : columns) {
1240
                if(column.getAlias().equalsIgnoreCase(columnName)) {
1241
                    found = column;
1242
                    break;
1243
                }
1244
1245
            }
1246
            if(found!=null) {
1247
                columns.remove(found);
1248
            }
1249
        }
1250 43020 jjdelcerro
1251
        @Override
1252 45155 omartinez
        public SelectBuilder group_by(Value... columns) {
1253 44349 jjdelcerro
            if( this.groupColumn==null ) {
1254
                this.groupColumn = new ArrayList<>();
1255
            }
1256 45155 omartinez
            for (Value column : columns) {
1257 44349 jjdelcerro
                this.groupColumn.add(column);
1258
            }
1259
            return this;
1260
        }
1261
1262
        @Override
1263 43020 jjdelcerro
        public void accept(Visitor visitor, VisitorFilter filter) {
1264 46505 fdiaz
            boolean visitChildren = true;
1265 45155 omartinez
            if (filter==null || filter.accept(this)) {
1266 43020 jjdelcerro
                visitor.visit(this);
1267 46505 fdiaz
            } else {
1268
                visitChildren = !filter.skipChildren();
1269 43020 jjdelcerro
            }
1270 46505 fdiaz
            if(visitChildren){
1271
                for (SelectColumnBuilder column : columns) {
1272
                    column.accept(visitor, filter);
1273 43020 jjdelcerro
                }
1274 46505 fdiaz
                if (this.has_from()) {
1275
                    this.from.accept(visitor, filter);
1276 45155 omartinez
                }
1277 46505 fdiaz
                if (this.has_where()) {
1278
                    this.where.accept(visitor, filter);
1279
                }
1280
                if (this.has_order_by()) {
1281
                    for (OrderByBuilder order : order_by) {
1282
                        order.accept(visitor, filter);
1283
                    }
1284
                }
1285
                if (this.has_group_by()) {
1286
                    for (Value group : groupColumn) {
1287
                        group.accept(visitor, filter);
1288
                    }
1289
                }
1290 45155 omartinez
            }
1291 43020 jjdelcerro
        }
1292
1293
        @Override
1294 44376 jjdelcerro
        public void replace(Value target, Value replacement) {
1295
            if( this.columns!=null ) {
1296
                for (int i = 0; i < columns.size(); i++) {
1297
                    SelectColumnBuilder column = columns.get(i);
1298
                    if( column == target ) {
1299
                        columns.set(i, (SelectColumnBuilder) replacement);
1300
                    } else {
1301
                        column.replace(target, replacement);
1302
                    }
1303
                }
1304
            }
1305
            if (this.has_from()) {
1306
                if( this.from == target ) {
1307
                    this.from = (FromBuilder) replacement;
1308
                } else {
1309
                    this.from.replace(target, replacement);
1310
                }
1311
            }
1312
            if (this.has_where()) {
1313
                if( this.where == target ) {
1314 44644 jjdelcerro
                    this.where = (GeometryExpressionBuilder) replacement;
1315 44376 jjdelcerro
                } else if( this.where.value() == target ) {
1316
                    this.where.value(replacement);
1317
                } else {
1318
                    this.where.value().replace(target, replacement);
1319
                }
1320
            }
1321
            if (this.has_order_by()) {
1322
                for (int i = 0; i < order_by.size(); i++) {
1323
                    OrderByBuilder order = order_by.get(i);
1324
                    if( order == target ) {
1325
                        order_by.set(i, (OrderByBuilder) replacement);
1326
                    } else {
1327
                        order.replace(target, replacement);
1328
                    }
1329
                }
1330
            }
1331 45155 omartinez
            if (this.has_group_by()) {
1332
                for (int i = 0; i < groupColumn.size(); i++) {
1333
                    Value group = groupColumn.get(i);
1334
                    if( group == target ) {
1335
                        groupColumn.set(i, replacement);
1336
                    } else {
1337
                        group.replace(target, replacement);
1338
                    }
1339
                }
1340
            }
1341 44376 jjdelcerro
        }
1342
1343
        @Override
1344 43020 jjdelcerro
        public SelectBuilder distinct() {
1345
            this.distinct = true;
1346
            return this;
1347
        }
1348 44198 jjdelcerro
1349 43020 jjdelcerro
        @Override
1350
        public SelectColumnBuilder column() {
1351 46507 jjdelcerro
            return column(createSelectColumnBuilder());
1352 43020 jjdelcerro
        }
1353
1354
        @Override
1355 46507 jjdelcerro
        public SelectColumnBuilder column(SelectColumnBuilder columnBuilder) {
1356
            this.columns.add(columnBuilder);
1357
            if( this.has_from() && !this.from().table().isEmpty() ) {
1358
                TableNameBuilder table = (TableNameBuilder) CloneableUtils.cloneQuietly(this.from().table());
1359
                columnBuilder.table(table);
1360
            }
1361
            return columnBuilder;
1362
        }
1363
1364
        @Override
1365 46505 fdiaz
        public SelectColumnBuilder column(String name) {
1366
            for (SelectColumnBuilder column : columns) {
1367
                if (StringUtils.equals(name, column.getName())) {
1368
                    return column;
1369
                }
1370
            }
1371 46507 jjdelcerro
            return column(createSelectColumnBuilder()).name(name);
1372 46505 fdiaz
        }
1373
1374
        @Override
1375 46507 jjdelcerro
        public SelectColumnBuilder getColumn(String name) {
1376
            for (SelectColumnBuilder column : columns) {
1377
                if (StringUtils.equals(name, column.getName())) {
1378
                    return column;
1379
                }
1380
            }
1381
            return null;
1382
        }
1383
1384
        @Override
1385 44385 jjdelcerro
        public SelectBuilder remove_all_columns() {
1386
            this.columns = new ArrayList<>();
1387
            return this;
1388
        }
1389
1390
        @Override
1391 43020 jjdelcerro
        public boolean has_column(String name) {
1392
            for (SelectColumnBuilder column : columns) {
1393 45166 omartinez
                if (StringUtils.equals(name, column.getName())) {
1394 43020 jjdelcerro
                    return true;
1395
                }
1396 45166 omartinez
                if (StringUtils.equals(name, column.getAlias())) {
1397
                    return true;
1398
                }
1399 43020 jjdelcerro
            }
1400
            return false;
1401
        }
1402
1403
        @Override
1404
        public FromBuilder from() {
1405
            if (this.from == null) {
1406
                this.from = createFromBuilder();
1407
            }
1408
            return this.from;
1409
        }
1410
1411
        @Override
1412
        public boolean has_from() {
1413
            return this.from != null;
1414
        }
1415 44198 jjdelcerro
1416 43020 jjdelcerro
        @Override
1417 44644 jjdelcerro
        public GeometryExpressionBuilder where() {
1418 43020 jjdelcerro
            if (this.where == null) {
1419
                this.where = createExpressionBuilder();
1420
            }
1421
            return this.where;
1422
        }
1423
1424
        @Override
1425
        public boolean has_where() {
1426 44198 jjdelcerro
            if (this.where == null) {
1427 43020 jjdelcerro
                return false;
1428
            }
1429 44198 jjdelcerro
            return this.where.value() != null;
1430 43020 jjdelcerro
        }
1431 44198 jjdelcerro
1432 43020 jjdelcerro
        @Override
1433
        public SelectBuilder limit(long limit) {
1434
            this.limit = limit;
1435
            return this;
1436
        }
1437
1438
        @Override
1439 44058 jjdelcerro
        public SelectBuilder limit(Long limit) {
1440 44198 jjdelcerro
            if (limit == null) {
1441 46277 jjdelcerro
                this.limit = -1;
1442 44058 jjdelcerro
            } else {
1443
                this.limit = limit;
1444
            }
1445
            return this;
1446
        }
1447
1448
        @Override
1449 43020 jjdelcerro
        public boolean has_limit() {
1450 46277 jjdelcerro
            return this.limit >= 0;
1451 43020 jjdelcerro
        }
1452
1453
        @Override
1454
        public SelectBuilder offset(long offset) {
1455
            this.offset = offset;
1456
            return this;
1457
        }
1458
1459
        @Override
1460
        public boolean has_offset() {
1461
            return this.offset > 0;
1462
        }
1463
1464
        @Override
1465
        public OrderByBuilder order_by() {
1466 44198 jjdelcerro
            if (this.order_by == null) {
1467 43093 jjdelcerro
                this.order_by = new ArrayList<>();
1468
            }
1469 43020 jjdelcerro
            OrderByBuilder order = createOrderByBuilder();
1470
            this.order_by.add(order);
1471
            return order;
1472
        }
1473 45969 fdiaz
1474 46258 jjdelcerro
        @Override
1475 46105 omartinez
        public OrderByBuilder getOrderBy(Value column) {
1476
            if(this.order_by == null){
1477
                return null;
1478
            }
1479
            for (OrderByBuilder orderByBuilder : this.order_by) {
1480
                if(orderByBuilder.isColumn(column)){
1481
                    return orderByBuilder;
1482
                }
1483
            }
1484
            return null;
1485
        }
1486
1487 46258 jjdelcerro
        @Override
1488 45969 fdiaz
        public OrderByBuilder getOrderBy(String column) {
1489
            if(this.order_by == null){
1490
                return null;
1491
            }
1492
            for (OrderByBuilder orderByBuilder : this.order_by) {
1493
                if(orderByBuilder.isColumn(column)){
1494
                    return orderByBuilder;
1495
                }
1496
            }
1497
            return null;
1498
        }
1499 46505 fdiaz
1500
        @Override
1501
        public boolean isGroupBy(String column) {
1502
            if(this.groupColumn == null){
1503
                return false;
1504
            }
1505
            for (Value group : this.groupColumn) {
1506
                if(group instanceof Variable){
1507
                    if(StringUtils.equalsIgnoreCase(((Variable)group).name(), column)){
1508
                        return true;
1509
                    }
1510
                }
1511
            }
1512
            return false;
1513
        }
1514 43020 jjdelcerro
1515
        @Override
1516
        public boolean has_order_by() {
1517 44198 jjdelcerro
            if (this.order_by == null) {
1518 43020 jjdelcerro
                return false;
1519
            }
1520
            return !this.order_by.isEmpty();
1521
        }
1522 44349 jjdelcerro
1523
        @Override
1524
        public boolean has_group_by() {
1525
            if (this.groupColumn == null) {
1526
                return false;
1527
            }
1528
            return !this.groupColumn.isEmpty();
1529
        }
1530
1531 44687 jjdelcerro
        @Override
1532 46258 jjdelcerro
        public boolean has_aggregate_functions() {
1533
            if (this.columns == null || this.columns.isEmpty() ) {
1534
                return false;
1535
            }
1536
            for (SelectColumnBuilder column : this.columns) {
1537
                if( column.isAggregateFunction() ) {
1538
                    return true;
1539
                }
1540
            }
1541
            return false;
1542
        }
1543
1544
        @Override
1545 44687 jjdelcerro
        public void disable_check_order_and_offset() {
1546
          this.check_order_and_offset = false;
1547
        }
1548
1549 43093 jjdelcerro
        protected boolean isValid(StringBuilder message) {
1550 44198 jjdelcerro
            if (message == null) {
1551 43093 jjdelcerro
                message = new StringBuilder();
1552
            }
1553 44687 jjdelcerro
            if( this.check_order_and_offset ) {
1554
              if (this.has_offset() && !this.has_order_by()) {
1555
                  // Algunos gestores de BBDD requieren que se especifique un
1556
                  // orden para poder usar OFFSET. Como eso parece buena idea para
1557 45969 fdiaz
                  // asegurar que siempre tengamos los mismo resultados, lo exigimos
1558 44687 jjdelcerro
                  // siempre.
1559
                  message.append("Can't use OFFSET without an ORDER BY.");
1560
                  return false;
1561
              }
1562 43093 jjdelcerro
            }
1563
            return true;
1564
        }
1565 44198 jjdelcerro
1566 43020 jjdelcerro
        @Override
1567
        public String toString() {
1568 44198 jjdelcerro
            return this.toString(formatter());
1569
        }
1570
1571
        @Override
1572
        public String toString(Formatter<Value> formatter) {
1573 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
1574 44198 jjdelcerro
                return formatter.format(this);
1575
            }
1576 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
1577 44198 jjdelcerro
            if (!this.isValid(builder)) {
1578 43093 jjdelcerro
                throw new IllegalStateException(builder.toString());
1579
            }
1580 43020 jjdelcerro
            builder.append("SELECT ");
1581 44198 jjdelcerro
            if (this.distinct) {
1582 43020 jjdelcerro
                builder.append("DISTINCT ");
1583
            }
1584
            boolean first = true;
1585
            for (SelectColumnBuilder column : columns) {
1586
                if (first) {
1587
                    first = false;
1588
                } else {
1589
                    builder.append(", ");
1590
                }
1591 44198 jjdelcerro
                builder.append(column.toString(formatter));
1592 43020 jjdelcerro
            }
1593
1594 44198 jjdelcerro
            if (this.has_from()) {
1595 43020 jjdelcerro
                builder.append(" FROM ");
1596 44198 jjdelcerro
                builder.append(this.from.toString(formatter));
1597 43020 jjdelcerro
            }
1598 44732 jjdelcerro
            if (this.has_where()) {
1599
                builder.append(" WHERE ");
1600
                builder.append(this.where.toString(formatter));
1601
            }
1602 44349 jjdelcerro
            if( this.has_group_by() ) {
1603
                builder.append(" GROUP BY ");
1604 44378 jjdelcerro
                builder.append(this.groupColumn.get(0).toString(formatter));
1605 44349 jjdelcerro
                for (int i = 1; i < groupColumn.size(); i++) {
1606
                    builder.append(", ");
1607 44378 jjdelcerro
                    builder.append(this.groupColumn.get(i).toString(formatter));
1608 44349 jjdelcerro
                }
1609
            }
1610 44198 jjdelcerro
            if (this.has_order_by()) {
1611 43020 jjdelcerro
                builder.append(" ORDER BY ");
1612
                first = true;
1613
                for (OrderByBuilder item : this.order_by) {
1614
                    if (first) {
1615
                        first = false;
1616
                    } else {
1617
                        builder.append(", ");
1618
                    }
1619 44198 jjdelcerro
                    builder.append(item.toString(formatter));
1620
                }
1621 43020 jjdelcerro
            }
1622 44198 jjdelcerro
1623
            if (this.has_limit()) {
1624 43020 jjdelcerro
                builder.append(" LIMIT ");
1625
                builder.append(this.limit);
1626
            }
1627 44198 jjdelcerro
            if (this.has_offset()) {
1628 43020 jjdelcerro
                builder.append(" OFFSET ");
1629
                builder.append(this.offset);
1630
            }
1631
            return builder.toString();
1632
1633
        }
1634
    }
1635
1636 44198 jjdelcerro
    public class DropTableBuilderBase
1637
            extends AbstractStatement
1638
            implements DropTableBuilder {
1639 43020 jjdelcerro
1640
        protected TableNameBuilder table;
1641
1642
        @Override
1643
        public TableNameBuilder table() {
1644 44198 jjdelcerro
            if (table == null) {
1645 43114 jjdelcerro
                table = createTableNameBuilder();
1646 43020 jjdelcerro
            }
1647
            return table;
1648
        }
1649
1650
        @Override
1651
        public void accept(Visitor visitor, VisitorFilter filter) {
1652 46505 fdiaz
            boolean visitChildren = true;
1653 45155 omartinez
            if (filter==null || filter.accept(this)) {
1654 43020 jjdelcerro
                visitor.visit(this);
1655 46505 fdiaz
            } else {
1656
                visitChildren = !filter.skipChildren();
1657 43020 jjdelcerro
            }
1658 46505 fdiaz
            if(visitChildren){
1659
                this.table.accept(visitor, filter);
1660
            }
1661 43020 jjdelcerro
        }
1662 44198 jjdelcerro
1663 43020 jjdelcerro
        @Override
1664
        public String toString() {
1665 44198 jjdelcerro
            return this.toString(formatter());
1666
        }
1667
1668
        @Override
1669
        public String toString(Formatter<Value> formatter) {
1670 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
1671 44198 jjdelcerro
                return formatter.format(this);
1672
            }
1673 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
1674
            boolean first = true;
1675 44198 jjdelcerro
            for (String sql : toStrings(formatter)) {
1676
                if (StringUtils.isEmpty(sql)) {
1677 43020 jjdelcerro
                    continue;
1678
                }
1679
                if (first) {
1680
                    first = false;
1681
                } else {
1682
                    builder.append("; ");
1683
                }
1684
                builder.append(sql);
1685
            }
1686
            return builder.toString();
1687
        }
1688
1689
        @Override
1690
        public List<String> toStrings() {
1691 44198 jjdelcerro
            return this.toStrings(formatter());
1692
        }
1693
1694
        @Override
1695
        public List<String> toStrings(Formatter formatter) {
1696 43020 jjdelcerro
            List<String> sqls = new ArrayList<>();
1697
1698
            sqls.add(
1699
                    MessageFormat.format(
1700 44198 jjdelcerro
                            STMT_DROP_TABLE_table,
1701
                            this.table.toString(formatter)
1702 43020 jjdelcerro
                    )
1703
            );
1704
            String sql;
1705 44198 jjdelcerro
            if (!StringUtils.isBlank(STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table)) {
1706 43020 jjdelcerro
                if (this.table.has_schema()) {
1707
                    sql = MessageFormat.format(
1708 44198 jjdelcerro
                            STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table,
1709
                            as_string(this.table.getSchema()),
1710
                            as_string(this.table.getName())
1711 43020 jjdelcerro
                    );
1712
                } else {
1713
                    sql = MessageFormat.format(
1714 44198 jjdelcerro
                            STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_table,
1715
                            as_identifier(this.table.getName())
1716 43020 jjdelcerro
                    );
1717
                }
1718 44198 jjdelcerro
                if (!StringUtils.isEmpty(sql)) {
1719 43020 jjdelcerro
                    sqls.add(sql);
1720
                }
1721
            }
1722
            return sqls;
1723
        }
1724
    }
1725
1726 44198 jjdelcerro
    public class GrantRoleBuilderBase
1727
            extends AbstractStatementPart
1728
            implements GrantRoleBuilder {
1729
1730 43020 jjdelcerro
        protected TableNameBuilder table;
1731
        protected String role;
1732
        protected Set<Privilege> privileges;
1733
1734
        public GrantRoleBuilderBase(TableNameBuilder table, String role) {
1735
            this.table = table;
1736
            this.role = role;
1737
            this.privileges = new HashSet<>();
1738
        }
1739 46105 omartinez
1740
        @Override
1741
        public GrantRoleBuilderBase clone() throws CloneNotSupportedException {
1742
            GrantRoleBuilderBase other = (GrantRoleBuilderBase) super.clone();
1743
            other.table = (TableNameBuilder) org.gvsig.tools.lang.Cloneable.cloneQuietly(table);
1744
            other.privileges = (Set<Privilege>) org.gvsig.tools.lang.Cloneable.cloneQuietly(privileges);
1745
1746
            return other;
1747
        }
1748 43020 jjdelcerro
1749
        @Override
1750
        public GrantRoleBuilder privilege(Privilege privilege) {
1751
            privileges.add(privilege);
1752
            return this;
1753
        }
1754 44198 jjdelcerro
1755 43020 jjdelcerro
        @Override
1756
        public GrantRoleBuilder select() {
1757 44198 jjdelcerro
            privileges.add(Privilege.SELECT);
1758 43020 jjdelcerro
            return this;
1759
        }
1760
1761
        @Override
1762
        public GrantRoleBuilder update() {
1763 44198 jjdelcerro
            privileges.add(Privilege.UPDATE);
1764 43020 jjdelcerro
            return this;
1765
        }
1766
1767
        @Override
1768
        public GrantRoleBuilder insert() {
1769
            privileges.add(Privilege.INSERT);
1770
            return this;
1771
        }
1772
1773
        @Override
1774
        public GrantRoleBuilder delete() {
1775
            privileges.add(Privilege.DELETE);
1776
            return this;
1777
        }
1778
1779
        @Override
1780
        public GrantRoleBuilder truncate() {
1781
            privileges.add(Privilege.TRUNCATE);
1782
            return this;
1783
        }
1784
1785
        @Override
1786
        public GrantRoleBuilder reference() {
1787
            privileges.add(Privilege.REFERENCE);
1788
            return this;
1789
        }
1790
1791
        @Override
1792
        public GrantRoleBuilder trigger() {
1793
            privileges.add(Privilege.TRIGGER);
1794
            return this;
1795
        }
1796
1797
        @Override
1798
        public GrantRoleBuilder all() {
1799
            privileges.add(Privilege.ALL);
1800
            return this;
1801
        }
1802
1803
        protected String getPrivilegeName(Privilege privilege) {
1804 44198 jjdelcerro
            switch (privilege) {
1805 43020 jjdelcerro
                case DELETE:
1806
                    return "DELETE";
1807
                case INSERT:
1808
                    return "INSERT";
1809
                case REFERENCE:
1810
                    return "REFERENCE";
1811
                case SELECT:
1812
                    return "SELECT";
1813
                case TRIGGER:
1814
                    return "TRIGGER";
1815
                case TRUNCATE:
1816
                    return "TRUNCATE";
1817
                case UPDATE:
1818
                    return "UPDATE";
1819
                case ALL:
1820
                default:
1821
                    return "ALL";
1822
            }
1823
        }
1824 44198 jjdelcerro
1825 43020 jjdelcerro
        @Override
1826
        public String toString() {
1827 44198 jjdelcerro
            return this.toString(formatter());
1828
        }
1829
1830
        @Override
1831
        public String toString(Formatter<Value> formatter) {
1832 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
1833 44198 jjdelcerro
                return formatter.format(this);
1834
            }
1835 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
1836
            boolean first = true;
1837
            for (Privilege privilege : privileges) {
1838
                if (first) {
1839
                    first = false;
1840
                } else {
1841
                    builder.append(", ");
1842
                }
1843 44198 jjdelcerro
                builder.append(this.getPrivilegeName(privilege));
1844 43020 jjdelcerro
            }
1845
            String sql = MessageFormat.format(
1846 44198 jjdelcerro
                    STMT_GRANT_privileges_ON_table_TO_role,
1847 43020 jjdelcerro
                    builder.toString(),
1848 44198 jjdelcerro
                    table.toString(formatter),
1849 43020 jjdelcerro
                    role
1850
            );
1851
            return sql;
1852
        }
1853
    }
1854
1855 44198 jjdelcerro
    public class GrantBuilderBase
1856
            extends AbstractStatement
1857
            implements GrantBuilder {
1858
1859 43020 jjdelcerro
        protected TableNameBuilder table;
1860
        protected Map<String, GrantRoleBuilder> roles;
1861
1862
        public GrantBuilderBase() {
1863
            this.roles = new HashMap<>();
1864
        }
1865 44198 jjdelcerro
1866 43020 jjdelcerro
        @Override
1867
        public TableNameBuilder table() {
1868 44198 jjdelcerro
            if (table == null) {
1869 43114 jjdelcerro
                table = createTableNameBuilder();
1870 43020 jjdelcerro
            }
1871
            return table;
1872
        }
1873
1874
        @Override
1875
        public void accept(Visitor visitor, VisitorFilter filter) {
1876 46505 fdiaz
            boolean visitChildren = true;
1877 45155 omartinez
            if (filter==null || filter.accept(this)) {
1878 43020 jjdelcerro
                visitor.visit(this);
1879 46505 fdiaz
            } else {
1880
                visitChildren = !filter.skipChildren();
1881 43020 jjdelcerro
            }
1882 46505 fdiaz
            if(visitChildren){
1883
                if (this.table != null) {
1884
                    this.table.accept(visitor, filter);
1885
                }
1886 43020 jjdelcerro
            }
1887
        }
1888 44198 jjdelcerro
1889 43020 jjdelcerro
        @Override
1890
        public GrantRoleBuilder role(String role) {
1891
            GrantRoleBuilder roleBuilder = this.roles.get(role);
1892 44198 jjdelcerro
            if (roleBuilder == null) {
1893 43020 jjdelcerro
                roleBuilder = createGrantRoleBuilder(this.table(), role);
1894
                this.roles.put(role, roleBuilder);
1895
            }
1896
            return roleBuilder;
1897
        }
1898
1899
        @Override
1900
        public String toString() {
1901 44198 jjdelcerro
            return this.toString(formatter());
1902
        }
1903
1904
        @Override
1905
        public String toString(Formatter<Value> formatter) {
1906 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
1907 44198 jjdelcerro
                return formatter.format(this);
1908
            }
1909 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
1910
            boolean first = true;
1911 44198 jjdelcerro
            for (String sql : toStrings(formatter)) {
1912
                if (StringUtils.isEmpty(sql)) {
1913 43020 jjdelcerro
                    continue;
1914
                }
1915
                if (first) {
1916
                    first = false;
1917
                } else {
1918
                    builder.append("; ");
1919
                }
1920
                builder.append(sql);
1921
            }
1922
            return builder.toString();
1923
        }
1924
1925
        @Override
1926
        public List<String> toStrings() {
1927 44198 jjdelcerro
            return this.toStrings(formatter());
1928
        }
1929
1930
        @Override
1931
        public List<String> toStrings(Formatter formatter) {
1932 43020 jjdelcerro
            List<String> sqls = new ArrayList<>();
1933
            for (GrantRoleBuilder role : roles.values()) {
1934 44198 jjdelcerro
                sqls.add(role.toString(formatter));
1935 43020 jjdelcerro
            }
1936
            return sqls;
1937
        }
1938
    }
1939
1940 44198 jjdelcerro
    public class UpdateColumnBuilderBase
1941
            extends InsertColumnBuilderBase
1942
            implements UpdateColumnBuilder {
1943
1944 43020 jjdelcerro
        public UpdateColumnBuilderBase() {
1945
            super();
1946
        }
1947
1948
        @Override
1949
        public UpdateColumnBuilder name(String name) {
1950
            return (UpdateColumnBuilder) super.name(name);
1951
        }
1952
1953
        @Override
1954
        public UpdateColumnBuilder with_value(Value value) {
1955
            return (UpdateColumnBuilder) super.with_value(value);
1956
        }
1957 44198 jjdelcerro
1958 43020 jjdelcerro
    }
1959
1960 44198 jjdelcerro
    public class UpdateBuilderBase
1961
            extends AbstractStatement
1962
            implements UpdateBuilder {
1963
1964 44644 jjdelcerro
        protected GeometryExpressionBuilder where;
1965 43020 jjdelcerro
        protected List<UpdateColumnBuilder> columns;
1966
        protected TableNameBuilder table;
1967
1968
        public UpdateBuilderBase() {
1969
            this.columns = new ArrayList<>();
1970
        }
1971
1972
        @Override
1973
        public void accept(Visitor visitor, VisitorFilter filter) {
1974 46505 fdiaz
            boolean visitChildren = true;
1975 45155 omartinez
            if (filter==null || filter.accept(this)) {
1976 43020 jjdelcerro
                visitor.visit(this);
1977 46505 fdiaz
            } else {
1978
                visitChildren = !filter.skipChildren();
1979 43020 jjdelcerro
            }
1980 46505 fdiaz
            if(visitChildren){
1981
                if (this.table != null) {
1982
                    this.table.accept(visitor, filter);
1983
                }
1984
                for (UpdateColumnBuilder column : columns) {
1985
                    column.accept(visitor, filter);
1986
                }
1987
                if (this.has_where()) {
1988
                    this.where.accept(visitor, filter);
1989
                }
1990 43020 jjdelcerro
            }
1991
        }
1992
1993
        @Override
1994 44644 jjdelcerro
        public GeometryExpressionBuilder where() {
1995 43020 jjdelcerro
            if (this.where == null) {
1996
                this.where = createExpressionBuilder();
1997
            }
1998
            return this.where;
1999
        }
2000
2001
        @Override
2002
        public TableNameBuilder table() {
2003 44198 jjdelcerro
            if (table == null) {
2004 43114 jjdelcerro
                table = createTableNameBuilder();
2005 43020 jjdelcerro
            }
2006
            return table;
2007
        }
2008
2009
        @Override
2010
        public UpdateColumnBuilder column() {
2011
            UpdateColumnBuilder column = createUpdateColumnBuilder();
2012
            this.columns.add(column);
2013
            return column;
2014
        }
2015 44198 jjdelcerro
2016 43020 jjdelcerro
        @Override
2017
        public boolean has_where() {
2018
            return this.where != null;
2019
        }
2020
2021
        @Override
2022
        public String toString() {
2023 44198 jjdelcerro
            return this.toString(formatter());
2024
        }
2025
2026
        @Override
2027
        public String toString(Formatter<Value> formatter) {
2028 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
2029 44198 jjdelcerro
                return formatter.format(this);
2030
            }
2031 43020 jjdelcerro
            /*
2032
             * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
2033
             * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
2034
             * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
2035
             * output_expression [ AS output_name ] [, ...] ]
2036
             */
2037
            StringBuilder columnsAndValues = new StringBuilder();
2038
2039
            boolean first = true;
2040
            for (UpdateColumnBuilder column : columns) {
2041
                if (first) {
2042
                    first = false;
2043
                } else {
2044
                    columnsAndValues.append(", ");
2045
                }
2046 44198 jjdelcerro
                columnsAndValues.append(as_identifier(column.getName()));
2047 43020 jjdelcerro
                columnsAndValues.append(" = ");
2048 44198 jjdelcerro
                columnsAndValues.append(column.getValue().toString(formatter));
2049 43020 jjdelcerro
            }
2050 44198 jjdelcerro
2051 43020 jjdelcerro
            String sql;
2052 44198 jjdelcerro
            if (this.has_where()) {
2053 43020 jjdelcerro
                sql = MessageFormat.format(
2054 44198 jjdelcerro
                        STMT_UPDATE_table_SET_columnsAndValues_WHERE_expresion,
2055
                        this.table.toString(formatter),
2056 43020 jjdelcerro
                        columnsAndValues.toString(),
2057 44198 jjdelcerro
                        this.where.toString(formatter)
2058 43020 jjdelcerro
                );
2059
            } else {
2060
                sql = MessageFormat.format(
2061 44198 jjdelcerro
                        STMT_UPDATE_table_SET_columnsAndValues,
2062
                        this.table.toString(formatter),
2063 43020 jjdelcerro
                        columnsAndValues.toString()
2064
                );
2065
            }
2066
            return sql;
2067
        }
2068
    }
2069
2070 44198 jjdelcerro
    public class DeleteBuilderBase
2071
            extends AbstractStatement
2072
            implements DeleteBuilder {
2073 43020 jjdelcerro
2074 44644 jjdelcerro
        protected GeometryExpressionBuilder where;
2075 43020 jjdelcerro
        protected TableNameBuilder table;
2076
2077
        public DeleteBuilderBase() {
2078
        }
2079
2080
        @Override
2081
        public void accept(Visitor visitor, VisitorFilter filter) {
2082 46505 fdiaz
            boolean visitChildren = true;
2083 45155 omartinez
            if (filter==null || filter.accept(this)) {
2084 43020 jjdelcerro
                visitor.visit(this);
2085 46505 fdiaz
            } else {
2086
                visitChildren = !filter.skipChildren();
2087 43020 jjdelcerro
            }
2088 46505 fdiaz
            if(visitChildren){
2089
                if (this.table != null) {
2090
                    this.table.accept(visitor, filter);
2091
                }
2092
                if (this.has_where()) {
2093
                    this.where.accept(visitor, filter);
2094
                }
2095 43020 jjdelcerro
            }
2096
        }
2097
2098
        @Override
2099 44644 jjdelcerro
        public GeometryExpressionBuilder where() {
2100 43020 jjdelcerro
            if (this.where == null) {
2101
                this.where = createExpressionBuilder();
2102
            }
2103
            return this.where;
2104
        }
2105
2106
        @Override
2107
        public TableNameBuilder table() {
2108 44198 jjdelcerro
            if (table == null) {
2109 43114 jjdelcerro
                table = createTableNameBuilder();
2110 43020 jjdelcerro
            }
2111
            return table;
2112
        }
2113
2114
        @Override
2115
        public boolean has_where() {
2116
            return this.where != null;
2117
        }
2118
2119
        @Override
2120
        public String toString() {
2121 44198 jjdelcerro
            return this.toString(formatter());
2122
        }
2123
2124
        @Override
2125
        public String toString(Formatter<Value> formatter) {
2126 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
2127 44198 jjdelcerro
                return formatter.format(this);
2128
            }
2129 43020 jjdelcerro
            /*
2130
             * DELETE FROM table_name
2131
             * WHERE some_column=some_value;
2132
             */
2133
            String sql;
2134 44198 jjdelcerro
            if (this.has_where()) {
2135 43020 jjdelcerro
                sql = MessageFormat.format(
2136 44198 jjdelcerro
                        STMT_DELETE_FROM_table_WHERE_expresion,
2137
                        this.table.toString(formatter),
2138
                        this.where.toString(formatter)
2139 43020 jjdelcerro
                );
2140
            } else {
2141
                sql = MessageFormat.format(
2142 44198 jjdelcerro
                        STMT_DELETE_FROM_table,
2143
                        this.table.toString(formatter)
2144 43020 jjdelcerro
                );
2145
            }
2146
            return sql;
2147
        }
2148
    }
2149
2150 44198 jjdelcerro
    public class CreateIndexBuilderBase
2151
            extends AbstractStatement
2152
            implements CreateIndexBuilder {
2153 43687 jjdelcerro
2154
        protected boolean ifNotExist = false;
2155
        protected boolean isUnique = false;
2156
        protected String indexName;
2157
        protected boolean isSpatial = false;
2158
        protected TableNameBuilder table;
2159
        protected final List<String> columns;
2160 44198 jjdelcerro
2161 43687 jjdelcerro
        public CreateIndexBuilderBase() {
2162
            this.columns = new ArrayList<>();
2163
        }
2164 44198 jjdelcerro
2165 43687 jjdelcerro
        @Override
2166
        public CreateIndexBuilder unique() {
2167
            this.isUnique = true;
2168
            return this;
2169
        }
2170
2171
        @Override
2172
        public CreateIndexBuilder if_not_exist() {
2173
            this.ifNotExist = true;
2174
            return this;
2175
        }
2176
2177
        @Override
2178
        public CreateIndexBuilder name(String name) {
2179
            this.indexName = name;
2180
            return this;
2181
        }
2182
2183
        @Override
2184 46099 jjdelcerro
        public CreateIndexBuilder name(String tableName, String columnName) {
2185
            this.indexName = tableName + "_IDX_" + columnName;
2186
            return this;
2187
        }
2188
2189
        @Override
2190 43687 jjdelcerro
        public CreateIndexBuilder spatial() {
2191
            this.isSpatial = true;
2192
            return this;
2193
        }
2194
2195
        @Override
2196
        public CreateIndexBuilder column(String name) {
2197
            this.columns.add(name);
2198
            return this;
2199
        }
2200
2201
        @Override
2202
        public TableNameBuilder table() {
2203 44198 jjdelcerro
            if (table == null) {
2204 43687 jjdelcerro
                table = createTableNameBuilder();
2205
            }
2206
            return table;
2207
        }
2208
2209
        @Override
2210
        public void accept(Visitor visitor, VisitorFilter filter) {
2211 46505 fdiaz
            boolean visitChildren = true;
2212 45155 omartinez
            if (filter==null || filter.accept(this)) {
2213 43687 jjdelcerro
                visitor.visit(this);
2214 46505 fdiaz
            } else {
2215
                visitChildren = !filter.skipChildren();
2216 43687 jjdelcerro
            }
2217 46505 fdiaz
            if(visitChildren){
2218
                if (this.table != null) {
2219
                    this.table.accept(visitor, filter);
2220
                }
2221 43687 jjdelcerro
            }
2222
        }
2223 44198 jjdelcerro
2224 43687 jjdelcerro
        @Override
2225 44198 jjdelcerro
        public String toString() {
2226
            return this.toString(formatter());
2227
        }
2228
2229
        @Override
2230
        public String toString(Formatter<Value> formatter) {
2231 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
2232 44198 jjdelcerro
                return formatter.format(this);
2233
            }
2234
            StringBuilder builder = new StringBuilder();
2235
            boolean first = true;
2236
            for (String sql : toStrings(formatter)) {
2237
                if (StringUtils.isEmpty(sql)) {
2238
                    continue;
2239
                }
2240
                if (first) {
2241
                    first = false;
2242
                } else {
2243
                    builder.append("; ");
2244
                }
2245
                builder.append(sql);
2246
            }
2247
            return builder.toString();
2248
        }
2249
2250
        @Override
2251 43687 jjdelcerro
        public List<String> toStrings() {
2252 44198 jjdelcerro
            return this.toStrings(formatter());
2253
        }
2254
2255
        @Override
2256
        public List<String> toStrings(Formatter formatter) {
2257 43687 jjdelcerro
            StringBuilder builder = new StringBuilder();
2258
            builder.append("CREATE ");
2259 44198 jjdelcerro
            if (this.isUnique) {
2260 43687 jjdelcerro
                builder.append("UNIQUE ");
2261
            }
2262
            builder.append("INDEX ");
2263 44198 jjdelcerro
            if (this.ifNotExist) {
2264 43687 jjdelcerro
                builder.append("IF NOT EXISTS ");
2265
            }
2266 44198 jjdelcerro
            builder.append(as_identifier(this.indexName));
2267 43687 jjdelcerro
            builder.append(" ON ");
2268 44198 jjdelcerro
            builder.append(this.table.toString(formatter));
2269
            if (this.isSpatial) {
2270 43687 jjdelcerro
                builder.append(" USING GIST ");
2271
            }
2272
            builder.append(" ( ");
2273
            boolean is_first_column = true;
2274 44198 jjdelcerro
            for (String column : this.columns) {
2275
                if (is_first_column) {
2276 43687 jjdelcerro
                    is_first_column = false;
2277
                } else {
2278
                    builder.append(", ");
2279
                }
2280
                builder.append(column);
2281
            }
2282
            builder.append(" )");
2283 44198 jjdelcerro
2284 43687 jjdelcerro
            List<String> sqls = new ArrayList<>();
2285
            sqls.add(builder.toString());
2286
            return sqls;
2287
        }
2288
2289
    }
2290 43020 jjdelcerro
2291 46099 jjdelcerro
    public class DropIndexBuilderBase
2292
            extends AbstractStatement
2293
            implements DropIndexBuilder {
2294
2295 47211 jjdelcerro
        protected boolean ifExist = false;
2296 46099 jjdelcerro
        protected String indexName;
2297
2298
        public DropIndexBuilderBase() {
2299
        }
2300
2301
        @Override
2302 47211 jjdelcerro
        public DropIndexBuilder if_exist() {
2303
            this.ifExist = true;
2304 46099 jjdelcerro
            return this;
2305
        }
2306
2307
        @Override
2308
        public DropIndexBuilder name(String name) {
2309
            this.indexName = name;
2310
            return this;
2311
        }
2312
2313
        @Override
2314
        public DropIndexBuilder name(String tableName, String columnName) {
2315
            this.indexName = tableName + "_IDX_" + columnName;
2316
            return this;
2317
        }
2318
2319
        @Override
2320
        public String toString() {
2321
            return this.toString(formatter());
2322
        }
2323
2324
        @Override
2325
        public String toString(Formatter<Value> formatter) {
2326
            if (formatter!=null && formatter.canApply(this)) {
2327
                return formatter.format(this);
2328
            }
2329
            StringBuilder builder = new StringBuilder();
2330
            boolean first = true;
2331
            for (String sql : toStrings(formatter)) {
2332
                if (StringUtils.isEmpty(sql)) {
2333
                    continue;
2334
                }
2335
                if (first) {
2336
                    first = false;
2337
                } else {
2338
                    builder.append("; ");
2339
                }
2340
                builder.append(sql);
2341
            }
2342
            return builder.toString();
2343
        }
2344
2345
        @Override
2346
        public List<String> toStrings() {
2347
            return this.toStrings(formatter());
2348
        }
2349
2350
        @Override
2351
        public List<String> toStrings(Formatter formatter) {
2352
            StringBuilder builder = new StringBuilder();
2353
            builder.append("DROP INDEX ");
2354 47211 jjdelcerro
            if (this.ifExist) {
2355
                builder.append("IF EXISTS ");
2356 46099 jjdelcerro
            }
2357
            builder.append(as_identifier(this.indexName));
2358
            List<String> sqls = new ArrayList<>();
2359
            sqls.add(builder.toString());
2360
            return sqls;
2361
        }
2362
2363
    }
2364
2365 44198 jjdelcerro
    public class AlterTableBuilderBase
2366
            extends AbstractStatement
2367
            implements AlterTableBuilder {
2368 46806 jjdelcerro
2369 43020 jjdelcerro
        protected TableNameBuilder table;
2370
        protected List<String> drops;
2371 43739 jjdelcerro
        protected List<ColumnDescriptor> adds;
2372 46806 jjdelcerro
2373
        // alters debera dejarse de usar en fabor de operation_alters
2374
        @Deprecated
2375 43739 jjdelcerro
        protected List<ColumnDescriptor> alters;
2376 46806 jjdelcerro
        protected List<Pair<Bitmask,ColumnDescriptor>> operations;
2377
2378 44198 jjdelcerro
        protected List<Pair<String, String>> renames;
2379 46099 jjdelcerro
        protected String drop_primary_key_column;
2380 47211 jjdelcerro
        private final SQLBuilderBase sqlbuilder;
2381 43020 jjdelcerro
2382 47211 jjdelcerro
        public AlterTableBuilderBase(SQLBuilderBase sqlbuilder) {
2383
            this.sqlbuilder = sqlbuilder;
2384 43020 jjdelcerro
            this.drops = new ArrayList<>();
2385
            this.adds = new ArrayList<>();
2386
            this.alters = new ArrayList<>();
2387 46806 jjdelcerro
            this.operations = new ArrayList<>();
2388 43020 jjdelcerro
            this.renames = new ArrayList<>();
2389
        }
2390
2391 46806 jjdelcerro
        public List<Pair<Bitmask,ColumnDescriptor>> getOperations() {
2392
            return this.operations;
2393
        }
2394
2395 43020 jjdelcerro
        @Override
2396 43687 jjdelcerro
        public boolean isEmpty() {
2397 44198 jjdelcerro
            return this.drops.isEmpty()
2398
                    && this.adds.isEmpty()
2399
                    && this.alters.isEmpty()
2400 46806 jjdelcerro
                    && this.operations.isEmpty()
2401 44198 jjdelcerro
                    && this.renames.isEmpty();
2402 43687 jjdelcerro
        }
2403 44198 jjdelcerro
2404 43687 jjdelcerro
        @Override
2405 43020 jjdelcerro
        public void accept(Visitor visitor, VisitorFilter filter) {
2406 46505 fdiaz
            boolean visitChildren = true;
2407 45155 omartinez
            if (filter==null || filter.accept(this)) {
2408 43020 jjdelcerro
                visitor.visit(this);
2409 46505 fdiaz
            } else {
2410
                visitChildren = !filter.skipChildren();
2411 43020 jjdelcerro
            }
2412 46505 fdiaz
            if(visitChildren){
2413
                if (this.table != null) {
2414
                    this.table.accept(visitor, filter);
2415
                }
2416 43020 jjdelcerro
            }
2417
        }
2418
2419
        @Override
2420
        public TableNameBuilder table() {
2421 44198 jjdelcerro
            if (table == null) {
2422 43114 jjdelcerro
                table = createTableNameBuilder();
2423 43020 jjdelcerro
            }
2424
            return table;
2425
        }
2426
2427
        @Override
2428
        public AlterTableBuilder drop_column(String columnName) {
2429
            this.drops.add(columnName);
2430
            return this;
2431
        }
2432 44198 jjdelcerro
2433 43739 jjdelcerro
        @Override
2434 46099 jjdelcerro
        public AlterTableBuilder drop_primary_key(String columnName) {
2435
            this.drop_primary_key_column = columnName;
2436
            return this;
2437
        }
2438
2439
        @Override
2440 43739 jjdelcerro
        public AlterTableBuilder add_column(FeatureAttributeDescriptor fad) {
2441 44198 jjdelcerro
            this.adds.add(new ColumnDescriptorBase(fad));
2442
            return this;
2443 43739 jjdelcerro
        }
2444 43020 jjdelcerro
2445
        @Override
2446 47211 jjdelcerro
        public AlterTableBuilder add_column(String columnName, int type, int size, int precision, int scale, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue, boolean allowIndexDuplicateds) {
2447 43020 jjdelcerro
            if (isPk || isAutomatic) {
2448
                allowNulls = false;
2449
            }
2450 47211 jjdelcerro
            this.adds.add(new ColumnDescriptorBase(columnName, type, size, precision, scale, isPk, isIndexed, allowNulls, isAutomatic, defaultValue, allowIndexDuplicateds));
2451 43020 jjdelcerro
            return this;
2452
        }
2453
2454
        @Override
2455 43650 jjdelcerro
        public AlterTableBuilder add_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
2456 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
2457 43650 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2458
            }
2459 43739 jjdelcerro
            this.adds.add(new ColumnDescriptorBase(columnName, type, subtype, proj, isIndexed, allowNulls));
2460 43650 jjdelcerro
            return this;
2461
        }
2462
2463
        @Override
2464 43687 jjdelcerro
        public AlterTableBuilder add_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
2465 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
2466 43687 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2467
            }
2468 43739 jjdelcerro
            this.adds.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
2469 43687 jjdelcerro
            return this;
2470
        }
2471 44198 jjdelcerro
2472 46806 jjdelcerro
        private void update_or_add_alters(ColumnDescriptorBase column) {
2473
            int i = 0;
2474
            for (; i < alters.size(); i++) {
2475
                ColumnDescriptor prevColumn = alters.get(i);
2476
                if( prevColumn.getName().equalsIgnoreCase(column.getName()) ) {
2477
                    // Si ya existia la actualizamos
2478
                    alters.set(i, column);
2479
                    break;
2480
                }
2481
2482
            }
2483
            if( i >= alters.size() ) {
2484
                // Si no existis la a?adimos
2485
                this.alters.add(column);
2486
            }
2487
        }
2488
2489 43687 jjdelcerro
        @Override
2490 47208 jjdelcerro
        public AlterTableBuilder alter_column(Bitmask operation, FeatureAttributeDescriptor fad) {
2491 46806 jjdelcerro
            ColumnDescriptorBase column = new ColumnDescriptorBase(fad);
2492
            update_or_add_alters(column);
2493 47208 jjdelcerro
            if( operation==null ) {
2494
                operation = Bitmask.createBitmask(0);
2495 43020 jjdelcerro
            }
2496 47211 jjdelcerro
            if( operation.isEmpty() ) {
2497
                operation.setBit(ALTER_COLUMN_ALL);
2498
            }
2499 46806 jjdelcerro
            this.operations.add(new ImmutablePair<>(operation,column));
2500 43020 jjdelcerro
            return this;
2501
        }
2502
2503
        @Override
2504 47211 jjdelcerro
        public AlterTableBuilder alter_column(Bitmask operation, String columnName, int type, int size, int precision, int scale, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue, boolean allowIndexDuplicateds) {
2505 46806 jjdelcerro
            if ( (isPk || isAutomatic) && allowNulls) {
2506
                allowNulls = false;
2507
                operation.setBit(ALTER_COLUMN_SET_NULL);
2508
            }
2509 47211 jjdelcerro
            ColumnDescriptorBase column = new ColumnDescriptorBase(columnName, type, size, precision, scale, isPk, isIndexed, allowNulls, isAutomatic, defaultValue, allowIndexDuplicateds);
2510 46806 jjdelcerro
            update_or_add_alters(column);
2511 47208 jjdelcerro
            if( operation == null ) {
2512
                operation = Bitmask.createBitmask(0);
2513
            }
2514 47211 jjdelcerro
            if( operation.isEmpty() ) {
2515
                operation.setBit(ALTER_COLUMN_ALL);
2516
            }
2517 46806 jjdelcerro
            this.operations.add(new ImmutablePair<>(operation,column));
2518
            return this;
2519
        }
2520
2521 47208 jjdelcerro
//        @Override
2522
//        public AlterTableBuilder alter_column(Bitmask operation,String columnName, int type, int size, int precision, int scale, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
2523
//            if ( (isPk || isAutomatic) && allowNulls) {
2524
//                allowNulls = false;
2525
//                operation.setBit(ALTER_COLUMN_SET_NULL);
2526
//            }
2527
//            ColumnDescriptorBase column = new ColumnDescriptorBase(columnName, type, size, precision, scale, isPk, isIndexed, allowNulls, isAutomatic, defaultValue);
2528
//            update_or_add_alters(column);
2529
//            this.operations.add(new ImmutablePair<>(operation,column));
2530
//            return this;
2531
//        }
2532
2533 46806 jjdelcerro
        @Override
2534 47208 jjdelcerro
        public AlterTableBuilder alter_geometry_column(Bitmask operation, String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
2535 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
2536 43650 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2537
            }
2538 46806 jjdelcerro
            ColumnDescriptorBase column = new ColumnDescriptorBase(columnName, type, subtype, proj, isIndexed, allowNulls);
2539
            update_or_add_alters(column);
2540 47208 jjdelcerro
            if( operation == null ) {
2541
                operation = Bitmask.createBitmask(0);
2542
            }
2543 47211 jjdelcerro
            if( operation.isEmpty() ) {
2544
                operation.setBit(ALTER_COLUMN_ALL);
2545
            }
2546 46806 jjdelcerro
            operation.setBit(ALTER_COLUMN_GEOMETRY);
2547
            this.operations.add(new ImmutablePair<>(operation,column));
2548 43650 jjdelcerro
            return this;
2549
        }
2550
2551
        @Override
2552 47208 jjdelcerro
        public AlterTableBuilder alter_geometry_column(Bitmask operation, String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
2553 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
2554 43687 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2555
            }
2556 46806 jjdelcerro
            ColumnDescriptorBase column = new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls);
2557
            update_or_add_alters(column);
2558 47208 jjdelcerro
            if( operation == null ) {
2559
                operation = Bitmask.createBitmask(0);
2560
            }
2561 46806 jjdelcerro
            operation.setBit(ALTER_COLUMN_GEOMETRY);
2562
            this.operations.add(new ImmutablePair<>(operation,column));
2563 43687 jjdelcerro
            return this;
2564
        }
2565
2566
        @Override
2567 43020 jjdelcerro
        public AlterTableBuilder rename_column(String source, String target) {
2568
            this.renames.add(new ImmutablePair(source, target));
2569
            return this;
2570
        }
2571
2572 46099 jjdelcerro
        protected String getConstrainName(String constrainType, String columnName) {
2573 47261 jjdelcerro
            return this.sqlbuilder.getConstrainName(table, columnName, constrainType);
2574 46099 jjdelcerro
        }
2575
2576 46806 jjdelcerro
        protected List<String> alter_table_add_primarykey_sqls(Formatter<Value> formatter, ColumnDescriptor column) {
2577
            // ALTER TABLE table_name ADD CONSTRAINT IF NOT EXISTS constraint_name PRIMARY KEY(column_name)
2578
            List<String> sqls = new ArrayList<>();
2579
            StringBuilder builder = new StringBuilder();
2580
            builder.append("ALTER TABLE ");
2581
            builder.append(this.table.toString(formatter));
2582
            builder.append(" ADD CONSTRAINT ");
2583
            builder.append("IF NOT EXISTS ");
2584
            builder.append(as_identifier(getConstrainName("PK",column.getName())));
2585
            builder.append(" PRIMARY KEY( ");
2586
            builder.append(as_identifier(column.getName()));
2587
            builder.append(" )");
2588
            sqls.add(builder.toString());
2589
            return sqls;
2590
        }
2591
2592
        protected List<String> alter_table_drop_primarykey_sqls(Formatter<Value> formatter, ColumnDescriptor column) {
2593
            // ALTER TABLE table_name DROP CONSTRAINT constraint_name
2594
            StringBuilder builder = new StringBuilder();
2595
            builder.append("ALTER TABLE ");
2596
            builder.append(this.table.toString(formatter));
2597
            builder.append(" DROP CONSTRAINT ");
2598
            builder.append("IF EXISTS ");
2599
            builder.append(as_identifier(getConstrainName("PK",column.getName())));
2600
            return Collections.singletonList(builder.toString());
2601
        }
2602
2603
        protected List<String> create_index_sqls(Formatter<Value> formatter, ColumnDescriptor column) {
2604 47211 jjdelcerro
            CreateIndexBuilder createIndex = this.sqlbuilder.createCreateIndexBuilder();
2605
            if( column.isGeometry() ) {
2606
                createIndex.spatial();
2607
            }
2608
            createIndex.if_not_exist();
2609
            createIndex.name(as_identifier(getConstrainName("IDX",column.getName())));
2610
            createIndex.column(column.getName());
2611
            createIndex.table()
2612
                    .database(this.table.getDatabase())
2613
                    .schema(this.table.getSchema())
2614
                    .name(this.table.getName()
2615
            );
2616
            if(!column.allowIndexDuplicateds()){
2617
                createIndex.unique();
2618
            }
2619
            return createIndex.toStrings();
2620 46806 jjdelcerro
        }
2621
2622
        protected List<String> drop_index_sqls(Formatter<Value> formatter, ColumnDescriptor column) {
2623 47211 jjdelcerro
            DropIndexBuilder dropIndex = this.sqlbuilder.createDropIndexBuilder();
2624
            dropIndex.if_exist();
2625
            dropIndex.name(as_identifier(getConstrainName("IDX",column.getName())));
2626
            return dropIndex.toStrings();
2627 46806 jjdelcerro
        }
2628
2629
        protected List<String> alter_table_alter_column_set_data_type_sqls(Formatter<Value> formatter, ColumnDescriptor column) {
2630
            StringBuilder builder = new StringBuilder();
2631
            builder.append("ALTER TABLE ");
2632
            builder.append(this.table.toString(formatter));
2633
            builder.append(" ALTER COLUMN ");
2634
            builder.append(as_identifier(column.getName()));
2635
            builder.append(" SET DATA TYPE ");
2636
            if (column.getType() == DataTypes.INT && column.isAutomatic()) {
2637
                builder.append(" SERIAL");
2638
            } else {
2639
                builder.append(
2640
                        sqltype(
2641
                                column.getType(),
2642
                                column.getSize(),
2643
                                column.getPrecision(),
2644
                                column.getScale(),
2645
                                column.getGeometryType(),
2646
                                column.getGeometrySubtype()
2647
                        )
2648
                );
2649
            }
2650
            return Collections.singletonList(builder.toString());
2651
        }
2652
2653
        protected List<String> alter_table_alter_column_set_default_sqls(Formatter<Value> formatter, ColumnDescriptor column) {
2654
            StringBuilder builder = new StringBuilder();
2655
            builder.append("ALTER TABLE ");
2656
            builder.append(this.table.toString(formatter));
2657
            builder.append(" ALTER COLUMN ");
2658
            builder.append(as_identifier(column.getName()));
2659
            if (column.getDefaultValue() == null) {
2660
                if (column.allowNulls()) {
2661
                    builder.append(" SET DEFAULT NULL");
2662
                } else {
2663
                    builder.append(" DROP DEFAULT");
2664
                }
2665
            } else {
2666
                builder.append(" SET DEFAULT '");
2667
                builder.append(column.getDefaultValue().toString());
2668
                builder.append("'");
2669
            }
2670
            return Collections.singletonList(builder.toString());
2671
        }
2672
2673
        protected List<String> alter_table_alter_column_set_null_sqls(Formatter<Value> formatter, ColumnDescriptor column) {
2674
            StringBuilder builder = new StringBuilder();
2675
            builder.append("ALTER TABLE ");
2676
            builder.append(this.table.toString(formatter));
2677
            builder.append(" ALTER COLUMN ");
2678
            builder.append(as_identifier(column.getName()));
2679
            if (column.allowNulls()) {
2680
                builder.append(" SET NULL");
2681
            } else {
2682
                builder.append(" SET NOT NULL");
2683
            }
2684
            return Collections.singletonList(builder.toString());
2685
        }
2686
2687
        protected List<String> alter_table_drop_column_sqls(Formatter<Value> formatter, String columnName) {
2688
            StringBuilder builder = new StringBuilder();
2689
            builder.append("ALTER TABLE ");
2690
            builder.append(this.table.toString(formatter));
2691
            builder.append(" DROP COLUMN ");
2692
            builder.append(" IF EXISTS ");
2693
            builder.append(as_identifier(columnName));
2694
            return Collections.singletonList(builder.toString());
2695
        }
2696
2697
        protected List<String> alter_table_add_column_sqls(Formatter<Value> formatter, ColumnDescriptor column) {
2698
            List<String> sqls = new ArrayList<>();
2699
            StringBuilder builder = new StringBuilder();
2700
            builder.append("ALTER TABLE ");
2701
            builder.append(this.table.toString(formatter));
2702
            builder.append(" ADD COLUMN ");
2703
            builder.append(as_identifier(column.getName()));
2704
            builder.append(" ");
2705
            if (column.getType() == DataTypes.INT && column.isAutomatic()) {
2706
                builder.append(" SERIAL");
2707
            } else {
2708
                builder.append(
2709
                        sqltype(
2710
                                column.getType(),
2711
                                column.getSize(),
2712
                                column.getPrecision(),
2713
                                column.getScale(),
2714
                                column.getGeometryType(),
2715
                                column.getGeometrySubtype()
2716
                        )
2717
                );
2718
            }
2719
            if (column.getDefaultValue() == null) {
2720
                if (column.allowNulls()) {
2721
                    builder.append(" DEFAULT NULL");
2722
                }
2723
            } else {
2724
                builder.append(" DEFAULT '");
2725
                builder.append(Objects.toString(column.getDefaultValue(),""));
2726
                builder.append("'");
2727
            }
2728
            if (column.allowNulls()) {
2729
                builder.append(" NULL");
2730
            } else {
2731
                builder.append(" NOT NULL");
2732
            }
2733
            if (column.isPrimaryKey()) {
2734
                builder.append(" PRIMARY KEY");
2735
            }
2736
            sqls.add(builder.toString());
2737
2738
            if( column.isGeometry() ) {
2739
                sqls.addAll(alter_column_add_geometry_constraint_sqls(formatter, column));
2740
            }
2741
            if( column.isIndexed() ) {
2742
                sqls.addAll(create_index_sqls(formatter, column));
2743
            }
2744
            return sqls;
2745
        }
2746
2747
        protected List<String> alter_table_alter_column_rename_sqls(Formatter<Value> formatter, String oldName, String newName) {
2748
            StringBuilder builder = new StringBuilder();
2749
            builder.append("ALTER TABLE ");
2750
            builder.append(this.table.toString(formatter));
2751
            builder.append(" ALTER COLUMN ");
2752
            builder.append(as_identifier(oldName));
2753
            builder.append(" RENAME TO ");
2754
            builder.append(as_identifier(newName));
2755
            return Collections.singletonList(builder.toString());
2756
        }
2757
2758
        protected List<String> alter_column_add_geometry_constraint_sqls(Formatter<ExpressionBuilder.Value> formatter, ColumnDescriptor column) {
2759
            return Collections.EMPTY_LIST;
2760
        }
2761
2762 43020 jjdelcerro
        @Override
2763
        public String toString() {
2764 44198 jjdelcerro
            return this.toString(formatter());
2765
        }
2766
2767
        @Override
2768
        public String toString(Formatter<Value> formatter) {
2769 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
2770 44198 jjdelcerro
                return formatter.format(this);
2771
            }
2772 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
2773
            boolean first = true;
2774 44198 jjdelcerro
            for (String sql : toStrings(formatter)) {
2775
                if (StringUtils.isEmpty(sql)) {
2776 43020 jjdelcerro
                    continue;
2777
                }
2778
                if (first) {
2779
                    first = false;
2780
                } else {
2781
                    builder.append("; ");
2782
                }
2783
                builder.append(sql);
2784
            }
2785
            return builder.toString();
2786
        }
2787
2788
        @Override
2789
        public List<String> toStrings() {
2790 44198 jjdelcerro
            return this.toStrings(formatter());
2791
        }
2792
2793
        @Override
2794
        public List<String> toStrings(Formatter formatter) {
2795 43020 jjdelcerro
            List<String> sqls = new ArrayList<>();
2796 44198 jjdelcerro
            if (this.isEmpty()) {
2797 43687 jjdelcerro
                return sqls;
2798
            }
2799 43020 jjdelcerro
            for (String column : drops) {
2800 46806 jjdelcerro
                sqls.addAll(alter_table_drop_column_sqls(formatter, column));
2801 43020 jjdelcerro
            }
2802 43739 jjdelcerro
            for (ColumnDescriptor column : adds) {
2803 46806 jjdelcerro
                sqls.addAll(alter_table_add_column_sqls(formatter, column));
2804 43020 jjdelcerro
            }
2805 46806 jjdelcerro
            for (Pair<Bitmask,ColumnDescriptor> operationAndColumn : this.getOperations()) {
2806
                Bitmask operation = operationAndColumn.getLeft();
2807
                ColumnDescriptor column = operationAndColumn.getRight();
2808
                if( operation.isSetBit(ALTER_COLUMN_ALL) ) {
2809
                    if( column.isPrimaryKey() ) {
2810
                        sqls.addAll(alter_table_add_primarykey_sqls(formatter, column));
2811 43020 jjdelcerro
                    } else {
2812 46806 jjdelcerro
                        sqls.addAll(alter_table_drop_primarykey_sqls(formatter, column));
2813
                        if( column.isIndexed() ) {
2814
                            sqls.addAll(create_index_sqls(formatter, column));
2815
                        }
2816 43020 jjdelcerro
                    }
2817 46806 jjdelcerro
                    sqls.addAll(alter_table_alter_column_set_data_type_sqls(formatter, column));
2818
                    sqls.addAll(alter_table_alter_column_set_default_sqls(formatter, column));
2819
                    sqls.addAll(alter_table_alter_column_set_null_sqls(formatter, column));
2820
                    if( column.isGeometry() ) {
2821
                        sqls.addAll(alter_column_add_geometry_constraint_sqls(formatter, column));
2822
                    }
2823 43020 jjdelcerro
                } else {
2824 46806 jjdelcerro
                    if( operation.isSetBit(ALTER_COLUMN_SET_NULL) ) { // Debe ir antes del "add primary key"
2825
                        sqls.addAll(alter_table_alter_column_set_null_sqls(formatter, column));
2826
                    }
2827
2828
                    if( operation.isSetBit(ALTER_COLUMN_SET_DATA_TYPE) ) {
2829
                        sqls.addAll(alter_table_alter_column_set_data_type_sqls(formatter, column));
2830
                    }
2831
2832
                    if( operation.isSetBit(ALTER_COLUMN_ADD_PRIMARY_KEY) ) {
2833
                        sqls.addAll(alter_table_add_primarykey_sqls(formatter, column));
2834
                    }
2835
2836
                    if( operation.isSetBit(ALTER_COLUMN_DROP_PRIMARY_KEY) ) {
2837
                        sqls.addAll(alter_table_drop_primarykey_sqls(formatter, column));
2838
                    }
2839
2840
                    if( operation.isSetBit(ALTER_COLUMN_SET_DEFAULT) ) {
2841
                        sqls.addAll(alter_table_alter_column_set_default_sqls(formatter, column));
2842
                    }
2843
2844
                    if( operation.isSetBit(ALTER_COLUMN_CREATE_INDEX) ) {
2845
                        sqls.addAll(create_index_sqls(formatter, column));
2846
                    }
2847
2848
                    if( operation.isSetBit(ALTER_COLUMN_DROP_INDEX) ) {
2849
                        sqls.addAll(drop_index_sqls(formatter, column));
2850
                    }
2851
2852
                    if( operation.isSetBit(ALTER_COLUMN_GEOMETRY) ) {
2853
                        if( column.isGeometry() ) {
2854
                            sqls.addAll(alter_column_add_geometry_constraint_sqls(formatter, column));
2855
                        }
2856
                    }
2857
2858 43020 jjdelcerro
                }
2859
            }
2860 46806 jjdelcerro
2861 44198 jjdelcerro
            for (Pair<String, String> pair : renames) {
2862 46806 jjdelcerro
                sqls.addAll(alter_table_alter_column_rename_sqls(formatter, pair.getLeft(), pair.getRight()));
2863 43020 jjdelcerro
            }
2864
            return sqls;
2865
        }
2866
2867
    }
2868
2869 44198 jjdelcerro
    public class CreateTableBuilderBase
2870
            extends AbstractStatement
2871
            implements CreateTableBuilder {
2872 43020 jjdelcerro
2873
        protected TableNameBuilder table;
2874 43739 jjdelcerro
        protected List<ColumnDescriptor> columns;
2875 43020 jjdelcerro
2876
        public CreateTableBuilderBase() {
2877
            this.columns = new ArrayList<>();
2878
        }
2879
2880
        @Override
2881
        public void accept(Visitor visitor, VisitorFilter filter) {
2882 46505 fdiaz
            boolean visitChildren = true;
2883 45155 omartinez
            if (filter==null || filter.accept(this)) {
2884 43020 jjdelcerro
                visitor.visit(this);
2885 46505 fdiaz
            } else {
2886
                visitChildren = !filter.skipChildren();
2887 43020 jjdelcerro
            }
2888 46505 fdiaz
            if(visitChildren){
2889
                if (this.table != null) {
2890
                    this.table.accept(visitor, filter);
2891
                }
2892 43020 jjdelcerro
            }
2893
        }
2894
2895
        @Override
2896
        public TableNameBuilder table() {
2897 44198 jjdelcerro
            if (table == null) {
2898 43114 jjdelcerro
                table = createTableNameBuilder();
2899 43020 jjdelcerro
            }
2900
            return table;
2901
        }
2902
2903
        @Override
2904 43739 jjdelcerro
        public CreateTableBuilderBase add_column(FeatureAttributeDescriptor fad) {
2905 44198 jjdelcerro
            this.columns.add(new ColumnDescriptorBase(fad));
2906
            return this;
2907 43739 jjdelcerro
        }
2908
2909
        @Override
2910 44669 jjdelcerro
        public CreateTableBuilderBase add_column(String columnName, int type, int size, int precision, int scale, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
2911 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
2912 43114 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2913
            }
2914 43020 jjdelcerro
            if (isPk || isAutomatic) {
2915
                allowNulls = false;
2916
            }
2917 44669 jjdelcerro
            this.columns.add(new ColumnDescriptorBase(columnName, type, size, precision, scale, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
2918 43020 jjdelcerro
            return this;
2919
        }
2920
2921
        @Override
2922 43355 jjdelcerro
        public CreateTableBuilder add_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
2923 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
2924 43114 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2925
            }
2926 43739 jjdelcerro
            this.columns.add(new ColumnDescriptorBase(columnName, type, subtype, proj, isIndexed, allowNulls));
2927 43114 jjdelcerro
            return this;
2928
        }
2929
2930
        @Override
2931 43687 jjdelcerro
        public CreateTableBuilder add_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
2932 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
2933 43687 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2934
            }
2935 43739 jjdelcerro
            this.columns.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
2936 43687 jjdelcerro
            return this;
2937
        }
2938
2939
        @Override
2940 43739 jjdelcerro
        public ColumnDescriptor getColumnDescriptor(String columnName) {
2941 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
2942 43114 jjdelcerro
                return null;
2943
            }
2944 43739 jjdelcerro
            for (ColumnDescriptor column : columns) {
2945 44198 jjdelcerro
                if (columnName.equals(column.getName())) {
2946 43114 jjdelcerro
                    return column;
2947
                }
2948
            }
2949
            return null;
2950
        }
2951 44198 jjdelcerro
2952 43114 jjdelcerro
        @Override
2953 43020 jjdelcerro
        public String toString() {
2954 44198 jjdelcerro
            return this.toString(formatter());
2955
        }
2956
2957
        @Override
2958
        public String toString(Formatter<Value> formatter) {
2959 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
2960 44198 jjdelcerro
                return formatter.format(this);
2961
            }
2962 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
2963
            boolean first = true;
2964 44198 jjdelcerro
            for (String sql : toStrings(formatter)) {
2965
                if (StringUtils.isEmpty(sql)) {
2966 43020 jjdelcerro
                    continue;
2967
                }
2968
                if (first) {
2969
                    first = false;
2970
                } else {
2971
                    builder.append("; ");
2972
                }
2973
                builder.append(sql);
2974
            }
2975
            return builder.toString();
2976
        }
2977
2978
        @Override
2979
        public List<String> toStrings() {
2980 44198 jjdelcerro
            return this.toStrings(formatter());
2981
        }
2982
2983
        @Override
2984 46340 jjdelcerro
        /*
2985
        Debe crear la tabla, y las clave primaria, pero "no" los indices.
2986
        */
2987 44198 jjdelcerro
        public List<String> toStrings(Formatter formatter) {
2988 43020 jjdelcerro
            List<String> sqls = new ArrayList<>();
2989
            /**
2990
             * CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE
2991
             * table_name ( { column_name data_type [ DEFAULT default_expr ] [
2992
             * column_constraint [ ... ] ] | table_constraint | LIKE
2993
             * parent_table [ { INCLUDING | EXCLUDING } DEFAULTS ] } [, ... ] )
2994
             * [ INHERITS ( parent_table [, ... ] ) ] [ WITH OIDS | WITHOUT OIDS
2995
             * ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
2996
             *
2997
             * where column_constraint is:
2998
             *
2999
             * [ CONSTRAINT constraint_name ] { NOT NULL | NULL | UNIQUE |
3000
             * PRIMARY KEY | CHECK (expression) | REFERENCES reftable [ (
3001
             * refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON
3002
             * DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE | NOT
3003
             * DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
3004
             *
3005
             * and table_constraint is:
3006
             *
3007
             * [ CONSTRAINT constraint_name ] { UNIQUE ( column_name [, ... ] )
3008
             * | PRIMARY KEY ( column_name [, ... ] ) | CHECK ( expression ) |
3009
             * FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ (
3010
             * refcolumn [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH
3011
             * SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE
3012
             * | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
3013
             */
3014 46340 jjdelcerro
3015 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
3016
3017
            builder.append("CREATE TABLE ");
3018 44198 jjdelcerro
            builder.append(this.table.toString(formatter));
3019 43020 jjdelcerro
            builder.append(" (");
3020
            boolean first = true;
3021 43739 jjdelcerro
            for (ColumnDescriptor column : columns) {
3022 43020 jjdelcerro
                if (first) {
3023
                    first = false;
3024
                } else {
3025
                    builder.append(", ");
3026
                }
3027 44198 jjdelcerro
                builder.append(as_identifier(column.getName()));
3028 43020 jjdelcerro
                builder.append(" ");
3029 44198 jjdelcerro
                if (column.isAutomatic() && column.getType() == DataTypes.INT) {
3030 43020 jjdelcerro
                    builder.append("SERIAL");
3031 44198 jjdelcerro
                } else if (column.isAutomatic() && column.getType() == DataTypes.LONG) {
3032 43020 jjdelcerro
                    builder.append("BIGSERIAL");
3033
                } else {
3034 44198 jjdelcerro
                    builder.append(sqltype(
3035
                            column.getType(),
3036 44669 jjdelcerro
                            column.getSize(),
3037 44198 jjdelcerro
                            column.getPrecision(),
3038 44669 jjdelcerro
                            column.getScale(),
3039 44198 jjdelcerro
                            column.getGeometryType(),
3040
                            column.getGeometrySubtype()
3041
                    )
3042
                    );
3043 43020 jjdelcerro
                }
3044 43114 jjdelcerro
                if (column.getDefaultValue() == null) {
3045
                    if (column.allowNulls()) {
3046 43020 jjdelcerro
                        builder.append(" DEFAULT NULL");
3047
                    }
3048
                } else {
3049
                    builder.append(" DEFAULT '");
3050 44296 jjdelcerro
                    builder.append(Objects.toString(column.getDefaultValue(),""));
3051 43020 jjdelcerro
                    builder.append("'");
3052
                }
3053 46806 jjdelcerro
                if (column.isPrimaryKey()) {
3054 43020 jjdelcerro
                    builder.append(" NOT NULL");
3055
                    builder.append(" PRIMARY KEY");
3056 46806 jjdelcerro
                } else {
3057
                    if (column.allowNulls()) {
3058
                        builder.append(" NULL");
3059
                    } else {
3060
                        builder.append(" NOT NULL");
3061
                    }
3062 43020 jjdelcerro
                }
3063
            }
3064
            builder.append(" )");
3065
            sqls.add(builder.toString());
3066
            return sqls;
3067
        }
3068
    }
3069
3070 44198 jjdelcerro
    public class InsertColumnBuilderBase
3071
            extends AbstractStatement
3072
            implements InsertColumnBuilder {
3073
3074 43020 jjdelcerro
        protected Variable name;
3075
        protected Value value;
3076 44198 jjdelcerro
3077 43020 jjdelcerro
        public InsertColumnBuilderBase() {
3078
        }
3079
3080
        @Override
3081
        public void accept(Visitor visitor, VisitorFilter filter) {
3082 46505 fdiaz
            boolean visitChildren = true;
3083 45155 omartinez
            if (filter==null || filter.accept(this)) {
3084 43020 jjdelcerro
                visitor.visit(this);
3085 46505 fdiaz
            } else {
3086
                visitChildren = !filter.skipChildren();
3087 43020 jjdelcerro
            }
3088 46505 fdiaz
            if(visitChildren){
3089
                if (this.name != null) {
3090
                    this.name.accept(visitor, filter);
3091
                }
3092
                if (this.value != null) {
3093
                    this.value.accept(visitor, filter);
3094
                }
3095 43020 jjdelcerro
            }
3096
        }
3097
3098
        @Override
3099
        public InsertColumnBuilder name(String name) {
3100 44198 jjdelcerro
            this.name = expression().variable(name);
3101 43020 jjdelcerro
            return this;
3102
        }
3103
3104
        @Override
3105
        public InsertColumnBuilder with_value(Value value) {
3106
            this.value = value;
3107
            return this;
3108
        }
3109 44198 jjdelcerro
3110 43020 jjdelcerro
        @Override
3111
        public String getName() {
3112 44198 jjdelcerro
            return this.name.name();
3113 43020 jjdelcerro
        }
3114 44198 jjdelcerro
3115 43020 jjdelcerro
        @Override
3116
        public Value getValue() {
3117
            return this.value;
3118
        }
3119 44198 jjdelcerro
3120 43020 jjdelcerro
        @Override
3121
        public String toString() {
3122 44198 jjdelcerro
            return this.toString(formatter());
3123 43020 jjdelcerro
        }
3124 44198 jjdelcerro
3125
        @Override
3126
        public String toString(Formatter<Value> formatter) {
3127 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
3128 44198 jjdelcerro
                return formatter.format(this);
3129
            }
3130
            return this.value.toString(formatter);
3131
        }
3132 43020 jjdelcerro
    }
3133
3134 44198 jjdelcerro
    public class InsertBuilderBase
3135
            extends AbstractStatement
3136
            implements InsertBuilder {
3137
3138 43020 jjdelcerro
        protected List<InsertColumnBuilder> columns;
3139
        protected TableNameBuilder table;
3140
3141
        public InsertBuilderBase() {
3142
            this.columns = new ArrayList<>();
3143
        }
3144
3145
        @Override
3146
        public void accept(Visitor visitor, VisitorFilter filter) {
3147 46505 fdiaz
            boolean visitChildren = true;
3148 45155 omartinez
            if (filter==null || filter.accept(this)) {
3149 43020 jjdelcerro
                visitor.visit(this);
3150 46505 fdiaz
            } else {
3151
                visitChildren = !filter.skipChildren();
3152 43020 jjdelcerro
            }
3153 46505 fdiaz
            if(visitChildren){
3154
                if (this.table != null) {
3155
                    this.table.accept(visitor, filter);
3156
                }
3157
                for (InsertColumnBuilder column : columns) {
3158
                    column.accept(visitor, filter);
3159
                }
3160 43020 jjdelcerro
            }
3161
        }
3162
3163
        @Override
3164
        public TableNameBuilder table() {
3165 44198 jjdelcerro
            if (table == null) {
3166 43114 jjdelcerro
                table = createTableNameBuilder();
3167 43020 jjdelcerro
            }
3168
            return table;
3169
        }
3170
3171
        @Override
3172
        public InsertColumnBuilder column() {
3173
            InsertColumnBuilder column = createInsertColumnBuilder();
3174
            this.columns.add(column);
3175
            return column;
3176
        }
3177
3178
        @Override
3179
        public String toString() {
3180 44198 jjdelcerro
            return this.toString(formatter());
3181
        }
3182
3183
        @Override
3184
        public String toString(Formatter<Value> formatter) {
3185 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
3186 44198 jjdelcerro
                return formatter.format(this);
3187
            }
3188 43020 jjdelcerro
            /*
3189
             * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
3190
             * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
3191
             * output_expression [ AS output_name ] [, ...] ]
3192
             */
3193
            StringBuilder builderColumns = new StringBuilder();
3194
            StringBuilder builderValues = new StringBuilder();
3195 44198 jjdelcerro
3196 43020 jjdelcerro
            boolean first = true;
3197
            for (InsertColumnBuilder column : columns) {
3198
                if (first) {
3199
                    first = false;
3200
                } else {
3201
                    builderColumns.append(", ");
3202
                }
3203 44198 jjdelcerro
                builderColumns.append(as_identifier(column.getName()));
3204 43020 jjdelcerro
            }
3205
            first = true;
3206
            for (InsertColumnBuilder column : columns) {
3207
                if (first) {
3208
                    first = false;
3209
                } else {
3210
                    builderValues.append(", ");
3211
                }
3212 44198 jjdelcerro
                builderValues.append(column.toString(formatter));
3213 43020 jjdelcerro
            }
3214 44198 jjdelcerro
3215 43020 jjdelcerro
            String sql = MessageFormat.format(
3216 44198 jjdelcerro
                    STMT_INSERT_INTO_table_columns_VALUES_values,
3217
                    this.table.toString(formatter),
3218 43020 jjdelcerro
                    builderColumns.toString(),
3219
                    builderValues.toString()
3220
            );
3221
            return sql;
3222
3223
        }
3224
    }
3225
3226 44198 jjdelcerro
    public class UpdateTableStatisticsBuilderBase
3227
            extends AbstractStatement
3228
            implements UpdateTableStatisticsBuilder {
3229 43020 jjdelcerro
3230
        protected TableNameBuilder table;
3231
3232
        @Override
3233
        public void accept(Visitor visitor, VisitorFilter filter) {
3234 46505 fdiaz
            boolean visitChildren = true;
3235 45155 omartinez
            if (filter==null || filter.accept(this)) {
3236 43020 jjdelcerro
                visitor.visit(this);
3237 46505 fdiaz
            } else {
3238
                visitChildren = !filter.skipChildren();
3239 43020 jjdelcerro
            }
3240 46505 fdiaz
            if(visitChildren){
3241
                if (this.table != null) {
3242
                    this.table.accept(visitor, filter);
3243
                }
3244 43020 jjdelcerro
            }
3245
        }
3246
3247
        @Override
3248
        public TableNameBuilder table() {
3249 44198 jjdelcerro
            if (table == null) {
3250 43114 jjdelcerro
                table = createTableNameBuilder();
3251 43020 jjdelcerro
            }
3252
            return table;
3253
        }
3254
3255
        @Override
3256
        public String toString() {
3257 44198 jjdelcerro
            return this.toString(formatter());
3258
        }
3259
3260
        @Override
3261
        public String toString(Formatter<Value> formatter) {
3262 44296 jjdelcerro
            if (formatter!=null && formatter.canApply(this)) {
3263 44198 jjdelcerro
                return formatter.format(this);
3264
            }
3265 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
3266
            boolean first = true;
3267 44198 jjdelcerro
            for (String sql : toStrings(formatter)) {
3268
                if (StringUtils.isEmpty(sql)) {
3269 43020 jjdelcerro
                    continue;
3270
                }
3271
                if (first) {
3272
                    first = false;
3273
                } else {
3274
                    builder.append("; ");
3275
                }
3276
                builder.append(sql);
3277
            }
3278
            return builder.toString();
3279
        }
3280
3281
        @Override
3282
        public List<String> toStrings() {
3283 44198 jjdelcerro
            return this.toStrings(formatter());
3284
        }
3285
3286
        @Override
3287
        public List<String> toStrings(Formatter formatter) {
3288 43020 jjdelcerro
            List<String> sqls = new ArrayList<>();
3289 44198 jjdelcerro
3290
            if (!StringUtils.isBlank(STMT_UPDATE_TABLE_STATISTICS_table)) {
3291 43020 jjdelcerro
                String sql = MessageFormat.format(
3292 44198 jjdelcerro
                        STMT_UPDATE_TABLE_STATISTICS_table,
3293
                        table.toString(formatter)
3294
                );
3295
                if (!StringUtils.isEmpty(sql)) {
3296 43020 jjdelcerro
                    sqls.add(sql);
3297
                }
3298
            }
3299
            return sqls;
3300
        }
3301
    }
3302 44042 jjdelcerro
3303 44644 jjdelcerro
    protected GeometryExpressionBuilder expressionBuilder;
3304 44042 jjdelcerro
3305 44198 jjdelcerro
    protected String defaultSchema;
3306
    protected boolean supportSchemas;
3307
    protected boolean hasSpatialFunctions;
3308
    protected GeometrySupportType geometrySupportType;
3309
    protected boolean allowAutomaticValues;
3310 44042 jjdelcerro
3311 44198 jjdelcerro
    private static Map<Pair<Integer, Integer>, String> sqlgeometrytypes = null;
3312 44042 jjdelcerro
3313 44198 jjdelcerro
    protected String constant_true = "(1=1)";
3314 44214 omartinez
    protected String constant_false = "(1<>1)";
3315 44042 jjdelcerro
3316 44198 jjdelcerro
    protected String type_boolean = "BOOLEAN";
3317
    protected String type_byte = "TINYINT";
3318
    protected String type_bytearray = "BYTEA";
3319
    protected String type_geometry = "TEXT";
3320
    protected String type_char = "CHARACTER(1)";
3321
    protected String type_date = "DATE";
3322
    protected String type_double = "DOUBLE PRECISION"; //float con 53 bits de mantisa, float(54)
3323 44678 jjdelcerro
    protected String type_decimal_ps = "NUMERIC({0,Number,##########},{1,Number,##########})";
3324
    protected String type_decimal_p = "NUMERIC({0,Number,##########})";
3325 44198 jjdelcerro
    protected String type_float = "REAL"; //float con 24 bits de mantisa, float(24)
3326
    protected String type_int = "INT";
3327
    protected String type_long = "BIGINT";
3328
    protected String type_string = "TEXT";
3329 44320 jjdelcerro
    protected String type_string_p = "VARCHAR({0,Number,#######})";
3330 44198 jjdelcerro
    protected String type_time = "TIME";
3331
    protected String type_timestamp = "TIMESTAMP";
3332
    protected String type_version = "VARCHAR(30)";
3333
    protected String type_URI = "TEXT";
3334
    protected String type_URL = "TEXT";
3335
    protected String type_FILE = "TEXT";
3336
    protected String type_FOLDER = "TEXT";
3337 44042 jjdelcerro
3338 44198 jjdelcerro
    protected String STMT_DELETE_FROM_table_WHERE_expresion = "DELETE FROM {0} WHERE {1}";
3339
    protected String STMT_DELETE_FROM_table = "DELETE FROM {0}";
3340
    protected String STMT_INSERT_INTO_table_columns_VALUES_values = "INSERT INTO {0} ( {1} ) VALUES ( {2} )";
3341
    protected String STMT_UPDATE_TABLE_STATISTICS_table = "VACUUM ANALYZE {0}";
3342
    protected String STMT_DROP_TABLE_table = "DROP TABLE {0}";
3343
    protected String STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table = "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_schema = {0} AND f_table_name = {1}";
3344
    protected String STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_table = "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_name = {0}";
3345
    protected String STMT_UPDATE_table_SET_columnsAndValues_WHERE_expresion = "UPDATE {0} SET {1} WHERE {2}";
3346
    protected String STMT_UPDATE_table_SET_columnsAndValues = "UPDATE {0} SET {1}";
3347
    protected String STMT_GRANT_privileges_ON_table_TO_role = "GRANT {0} ON {1} TO {2}";
3348 44042 jjdelcerro
3349 43020 jjdelcerro
    public SQLBuilderBase() {
3350 44644 jjdelcerro
        this.expressionBuilder = GeometryExpressionEvaluatorLocator.getManager().createExpressionBuilder();
3351 46518 fdiaz
        this.expressionBuilder.setProperty(PROP_SQLBUILDER, this);
3352 44042 jjdelcerro
3353 44198 jjdelcerro
        this.hasSpatialFunctions = false;
3354
        this.supportSchemas = true;
3355
        this.geometrySupportType = GeometrySupportType.WKT;
3356 44042 jjdelcerro
3357 44198 jjdelcerro
        this.defaultSchema = "public";
3358
        this.allowAutomaticValues = true;
3359 44042 jjdelcerro
3360 43020 jjdelcerro
    }
3361 44198 jjdelcerro
3362 44042 jjdelcerro
    @Override
3363 44198 jjdelcerro
    public void setProperties(Class filter, final Object... values) {
3364 46050 omartinez
        this.expressionBuilder.setProperties(filter, values);
3365 46505 fdiaz
        setProperties(this, filter, values);
3366
    }
3367
3368
    @Override
3369
    public void setProperties(Visitable visitable, Class filter, final Object... values) {
3370
        if(visitable == null){
3371
            return;
3372
        }
3373
        if(visitable instanceof PropertiesSupport){
3374 46258 jjdelcerro
            for (int i = 0; i < values.length; i+=2) {
3375 46505 fdiaz
                ((PropertiesSupport)visitable).setProperty((String) values[i], values[i+1]);
3376 44198 jjdelcerro
            }
3377 46505 fdiaz
        }
3378
        visitable.accept((Visitable v) -> {
3379
            if(v instanceof PropertiesSupport){
3380
                for (int i = 0; i < values.length; i+=2) {
3381
                    ((PropertiesSupport)v).setProperty((String) values[i], values[i+1]);
3382
                }
3383
            }
3384 44198 jjdelcerro
        }, new ClassVisitorFilter(filter) );
3385 44042 jjdelcerro
    }
3386
3387 44198 jjdelcerro
    public String quote_for_identifiers() {
3388
        return "\"";
3389 44042 jjdelcerro
    }
3390
3391 44198 jjdelcerro
    public String quote_for_strings() {
3392
        return "'";
3393 44042 jjdelcerro
    }
3394
3395
    @Override
3396 44198 jjdelcerro
    public String as_identifier(String id) {
3397
        String quote = this.quote_for_identifiers();
3398
//        No se porque no esta disponible wrapIfMissing
3399
//        return StringUtils.wrapIfMissing(id,quote);
3400
        if (id.startsWith(quote)) {
3401
            return id;
3402
        }
3403
        return quote + id + quote;
3404 44042 jjdelcerro
3405
    }
3406 46727 jjdelcerro
3407
    @Override
3408
    public String as_clob(String s) {
3409
        int chunkSize = 1024;
3410
        StringBuilder builder = new StringBuilder();
3411
        builder.append("(CAST('");
3412
        for (int i = 0; i < s.length(); i += chunkSize) {
3413
            String chunk = s.substring(i, Math.min(s.length(), i + chunkSize));
3414
            if( i>0 ) {
3415
                builder.append("' AS NCLOB) || CAST('");
3416
            }
3417
            builder.append(StringUtils.replace(chunk, "'", "''"));
3418
        }
3419
        builder.append("' AS NCLOB))");
3420
        return builder.toString();
3421
    }
3422 44042 jjdelcerro
3423
    @Override
3424 44198 jjdelcerro
    public String as_string(String s) {
3425
        String quote = this.quote_for_strings();
3426 44042 jjdelcerro
//        No se porque no esta disponible wrapIfMissing
3427 44198 jjdelcerro
//        return StringUtils.wrapIfMissing(id,quote);
3428 44042 jjdelcerro
        if (s.startsWith(quote)) {
3429
            return s;
3430
        }
3431
        return quote + s + quote;
3432
3433
    }
3434
3435
    @Override
3436 44198 jjdelcerro
    public String as_string(byte[] data) {
3437
        return this.expressionBuilder.bytearray_0x(data);
3438
//        return this.expressionBuilder.bytearray_hex(data);
3439
//        return this.expressionBuilder.bytearray_x(data);
3440 44042 jjdelcerro
    }
3441 43020 jjdelcerro
3442
    @Override
3443 44198 jjdelcerro
    public String as_string(boolean value) {
3444
        return value? "TRUE" : "FALSE";
3445 44042 jjdelcerro
    }
3446
3447
    @Override
3448 44198 jjdelcerro
    public String as_string(Number value) {
3449
        return Objects.toString(value);
3450 44042 jjdelcerro
    }
3451
3452
    @Override
3453 44198 jjdelcerro
    public String as_string(Object value) {
3454
        if( value == null ) {
3455
            return "NULL";
3456 44042 jjdelcerro
        }
3457 44198 jjdelcerro
        if( value instanceof CharSequence ) {
3458
            return as_string(value.toString());
3459 44042 jjdelcerro
        }
3460 44198 jjdelcerro
        if( value instanceof Number ) {
3461
            return as_string((Number)value);
3462 44042 jjdelcerro
        }
3463 44198 jjdelcerro
        if( value instanceof Boolean ) {
3464
            return as_string((boolean)value);
3465 44042 jjdelcerro
        }
3466 44198 jjdelcerro
        if( value instanceof byte[] ) {
3467
            return as_string((byte[])value);
3468 44042 jjdelcerro
        }
3469 44198 jjdelcerro
        throw new IllegalArgumentException("Can't support type of value '"+value.getClass().getName()+"'.");
3470 44042 jjdelcerro
    }
3471 44198 jjdelcerro
3472 44042 jjdelcerro
    @Override
3473 44644 jjdelcerro
    public GeometryExpressionBuilder expression() {
3474 44198 jjdelcerro
        return this.expressionBuilder;
3475 44042 jjdelcerro
    }
3476
3477
    @Override
3478 44198 jjdelcerro
    public boolean has_spatial_functions() {
3479
        return this.hasSpatialFunctions;
3480 44042 jjdelcerro
    }
3481
3482
    @Override
3483 44198 jjdelcerro
    public GeometrySupportType geometry_support_type() {
3484
        return this.geometrySupportType;
3485 44042 jjdelcerro
    }
3486
3487 44644 jjdelcerro
    protected GeometryExpressionBuilder createExpressionBuilder() {
3488
        return GeometryExpressionEvaluatorLocator.getManager().createExpressionBuilder();
3489 44042 jjdelcerro
    }
3490
3491
    @Override
3492 44198 jjdelcerro
    public Object srs_id(IProjection projection) {
3493
        String abrev = projection.getAbrev();
3494
        return abrev.split(":")[1].trim();
3495 44042 jjdelcerro
    }
3496
3497
    @Override
3498 43020 jjdelcerro
    public String default_schema() {
3499 44198 jjdelcerro
        return this.defaultSchema;
3500 43020 jjdelcerro
    }
3501 43355 jjdelcerro
3502
    @Override
3503 44198 jjdelcerro
    public boolean support_schemas() {
3504
        return this.supportSchemas;
3505 43355 jjdelcerro
    }
3506 43650 jjdelcerro
3507
    @Override
3508 44669 jjdelcerro
    public String sqltype(int type, int size, int precision, int scale, int geomType, int geomSubtype) {
3509 43020 jjdelcerro
        switch (type) {
3510
            case DataTypes.BOOLEAN:
3511 44198 jjdelcerro
                return type_boolean;
3512 43020 jjdelcerro
            case DataTypes.CHAR:
3513 44198 jjdelcerro
                return type_char;
3514
3515 44678 jjdelcerro
3516
            case DataTypes.BYTE:
3517
                return type_byte;
3518
            case DataTypes.INT:
3519
                return type_int;
3520
            case DataTypes.LONG:
3521
                return type_long;
3522
3523
            case DataTypes.FLOAT:
3524
                return type_float;
3525
            case DataTypes.DOUBLE:
3526
                return type_double;
3527 44669 jjdelcerro
            case DataTypes.DECIMAL:
3528
                if (precision < 1) {
3529 44678 jjdelcerro
                    precision = DataType.DECIMAL_DEFAULT_PRECISION;
3530 43020 jjdelcerro
                }
3531 44678 jjdelcerro
                if (scale < 1) {
3532
                  return MessageFormat.format(type_decimal_p, precision);
3533 43020 jjdelcerro
                }
3534 44678 jjdelcerro
                return MessageFormat.format(type_decimal_ps, precision, scale);
3535
3536
3537 43020 jjdelcerro
            case DataTypes.STRING:
3538 44669 jjdelcerro
                if (size < 0) {
3539 44198 jjdelcerro
                    return type_string;
3540 46015 jjdelcerro
                } else if (size < DataManager.RECOMENDED_SIZE_FOR_CLOB) {
3541 44669 jjdelcerro
                    return MessageFormat.format(type_string_p, size);
3542 43020 jjdelcerro
                }
3543 44198 jjdelcerro
                return type_string;
3544 44678 jjdelcerro
3545
3546
            case DataTypes.DATE:
3547
                return type_date;
3548 43020 jjdelcerro
            case DataTypes.TIME:
3549 44198 jjdelcerro
                return type_time;
3550 43020 jjdelcerro
            case DataTypes.TIMESTAMP:
3551 44198 jjdelcerro
                return type_timestamp;
3552 44678 jjdelcerro
3553
            case DataTypes.BYTEARRAY:
3554
                return type_bytearray;
3555
3556
            case DataTypes.GEOMETRY:
3557
                return type_geometry;
3558
3559 43020 jjdelcerro
            case DataTypes.VERSION:
3560 44198 jjdelcerro
                return type_version;
3561 43020 jjdelcerro
            case DataTypes.URI:
3562 44198 jjdelcerro
                return type_URI;
3563 43020 jjdelcerro
            case DataTypes.URL:
3564 44198 jjdelcerro
                return type_URL;
3565 43020 jjdelcerro
            case DataTypes.FILE:
3566 44198 jjdelcerro
                return type_FILE;
3567 43020 jjdelcerro
            case DataTypes.FOLDER:
3568 44198 jjdelcerro
                return type_FOLDER;
3569 43020 jjdelcerro
            default:
3570
                return null;
3571
        }
3572
    }
3573
3574 43114 jjdelcerro
    @Override
3575
    public Object sqlgeometrytype(int type, int subtype) {
3576
        // Devuelve un Object por que algunos gestores de BBDD utilizan
3577
        // identificadores numericos para el tipo y otros strings.
3578
        // Por defecto vamos a devolver strings.
3579 44198 jjdelcerro
        if (sqlgeometrytypes == null) {
3580 43114 jjdelcerro
            sqlgeometrytypes = new HashMap<>();
3581 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2D), "POINT");
3582
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM3D), "POINTZ");
3583
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM), "POINTM");
3584
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM3DM), "POINTZM");
3585 43114 jjdelcerro
3586 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2D), "LINESTRING");
3587
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM3D), "LINESTRINGZ");
3588
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM), "LINESTRINGM");
3589
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM3DM), "LINESTRINGZM");
3590 43114 jjdelcerro
3591 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POLYGON, Geometry.SUBTYPES.GEOM2D), "POLYGON");
3592
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POLYGON, Geometry.SUBTYPES.GEOM3D), "POLYGONZ");
3593
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POLYGON, Geometry.SUBTYPES.GEOM2DM), "POLYGONM");
3594
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POLYGON, Geometry.SUBTYPES.GEOM3DM), "POLYGONZM");
3595 43114 jjdelcerro
3596 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOINT, Geometry.SUBTYPES.GEOM2D), "MULTIPOINT");
3597
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOINT, Geometry.SUBTYPES.GEOM3D), "MULTIPOINTZ");
3598
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOINT, Geometry.SUBTYPES.GEOM2DM), "MULTIPOINTM");
3599
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOINT, Geometry.SUBTYPES.GEOM3DM), "MULTIPOINTZM");
3600 43114 jjdelcerro
3601 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM2D), "MULTILINESTRING");
3602
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM3D), "MULTILINESTRINGZ");
3603
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM2DM), "MULTILINESTRINGM");
3604
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM3DM), "MULTILINESTRINGZM");
3605 43114 jjdelcerro
3606 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTICURVE, Geometry.SUBTYPES.GEOM2D), "MULTILINESTRING");
3607
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTICURVE, Geometry.SUBTYPES.GEOM3D), "MULTILINESTRINGZ");
3608
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTICURVE, Geometry.SUBTYPES.GEOM2DM), "MULTILINESTRINGM");
3609
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTICURVE, Geometry.SUBTYPES.GEOM3DM), "MULTILINESTRINGZM");
3610 43355 jjdelcerro
3611 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON, Geometry.SUBTYPES.GEOM2D), "MULTIPOLYGON");
3612
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON, Geometry.SUBTYPES.GEOM3D), "MULTIPOLYGONZ");
3613
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON, Geometry.SUBTYPES.GEOM2DM), "MULTIPOLYGONM");
3614
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON, Geometry.SUBTYPES.GEOM3DM), "MULTIPOLYGONZM");
3615 43114 jjdelcerro
3616 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTISURFACE, Geometry.SUBTYPES.GEOM2D), "MULTIPOLYGON");
3617
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTISURFACE, Geometry.SUBTYPES.GEOM3D), "MULTIPOLYGONZ");
3618
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTISURFACE, Geometry.SUBTYPES.GEOM2DM), "MULTIPOLYGONM");
3619
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTISURFACE, Geometry.SUBTYPES.GEOM3DM), "MULTIPOLYGONZM");
3620 43355 jjdelcerro
3621 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2D), "GEOMETRY");
3622
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM3D), "GEOMETRYZ");
3623
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2DM), "GEOMETRYM");
3624
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM3DM), "GEOMETRYZM");
3625 43114 jjdelcerro
        }
3626 44198 jjdelcerro
        return sqlgeometrytypes.get(new ImmutablePair<>(type, subtype));
3627 43114 jjdelcerro
    }
3628
3629
    @Override
3630
    public Object sqlgeometrydimension(int type, int subtype) {
3631
        // Devuelve un Object por que algunos gestortes de BBDD utilizan
3632
        // identificadores numericos para las dimensiones y otros strings.
3633
        // Por defecto vamos a devolver enteros.
3634 44198 jjdelcerro
        switch (subtype) {
3635 43114 jjdelcerro
            case Geometry.SUBTYPES.GEOM3D:
3636
                return 3;
3637
            case Geometry.SUBTYPES.GEOM2DM:
3638
                return 3;
3639
            case Geometry.SUBTYPES.GEOM3DM:
3640
                return 4;
3641
            case Geometry.SUBTYPES.GEOM2D:
3642
            default:
3643
                return 2;
3644
        }
3645
    }
3646 44198 jjdelcerro
3647 44329 jjdelcerro
    @Override
3648 46507 jjdelcerro
    public SelectColumnBuilder column() {
3649
        return createSelectColumnBuilder();
3650
    }
3651
3652
    @Override
3653 44329 jjdelcerro
    public TableNameBuilder createTableNameBuilder() {
3654 43114 jjdelcerro
        return new TableNameBuilderBase();
3655
    }
3656 44198 jjdelcerro
3657 43020 jjdelcerro
    protected SelectColumnBuilder createSelectColumnBuilder() {
3658 46258 jjdelcerro
        return new SelectColumnBuilderBase(this);
3659 43020 jjdelcerro
    }
3660 44198 jjdelcerro
3661 43020 jjdelcerro
    protected UpdateColumnBuilder createUpdateColumnBuilder() {
3662
        return new UpdateColumnBuilderBase();
3663
    }
3664 44198 jjdelcerro
3665 43020 jjdelcerro
    protected InsertColumnBuilder createInsertColumnBuilder() {
3666
        return new InsertColumnBuilderBase();
3667
    }
3668 44198 jjdelcerro
3669 43020 jjdelcerro
    protected OrderByBuilder createOrderByBuilder() {
3670
        return new OrderByBuilderBase();
3671
    }
3672
3673
    protected FromBuilder createFromBuilder() {
3674
        return new FromBuilderBase();
3675
    }
3676
3677 46505 fdiaz
    public SelectBuilder createSelectBuilder() {
3678 43020 jjdelcerro
        return new SelectBuilderBase();
3679
    }
3680
3681
    protected UpdateBuilder createUpdateBuilder() {
3682
        return new UpdateBuilderBase();
3683
    }
3684
3685
    protected DeleteBuilder createDeleteBuilder() {
3686
        return new DeleteBuilderBase();
3687
    }
3688
3689
    protected GrantBuilder createGrantBuilder() {
3690
        return new GrantBuilderBase();
3691
    }
3692
3693
    protected GrantRoleBuilder createGrantRoleBuilder(TableNameBuilder table, String role) {
3694
        return new GrantRoleBuilderBase(table, role);
3695
    }
3696 44198 jjdelcerro
3697 43020 jjdelcerro
    protected DropTableBuilder createDropTableBuilder() {
3698
        return new DropTableBuilderBase();
3699
    }
3700
3701
    protected CreateTableBuilder createCreateTableBuilder() {
3702
        return new CreateTableBuilderBase();
3703
    }
3704
3705
    protected AlterTableBuilder createAlterTableBuilder() {
3706 47211 jjdelcerro
        return new AlterTableBuilderBase(this);
3707 43020 jjdelcerro
    }
3708
3709
    protected InsertBuilder createInsertBuilder() {
3710
        return new InsertBuilderBase();
3711
    }
3712
3713
    protected UpdateTableStatisticsBuilder createUpdateTableStatisticsBuilder() {
3714
        return new UpdateTableStatisticsBuilderBase();
3715
    }
3716
3717 43687 jjdelcerro
    protected CreateIndexBuilder createCreateIndexBuilder() {
3718
        return new CreateIndexBuilderBase();
3719
    }
3720 44198 jjdelcerro
3721 46099 jjdelcerro
    protected DropIndexBuilder createDropIndexBuilder() {
3722
        return new DropIndexBuilderBase();
3723
    }
3724 46806 jjdelcerro
3725 43020 jjdelcerro
    @Override
3726
    public SelectBuilder select() {
3727
        if (this.select == null) {
3728
            this.select = this.createSelectBuilder();
3729
        }
3730
        return this.select;
3731
    }
3732
3733
    @Override
3734
    public UpdateBuilder update() {
3735
        if (this.update == null) {
3736
            this.update = this.createUpdateBuilder();
3737
        }
3738
        return this.update;
3739
    }
3740
3741
    @Override
3742
    public UpdateTableStatisticsBuilder update_table_statistics() {
3743
        if (this.update_table_statistics == null) {
3744
            this.update_table_statistics = this.createUpdateTableStatisticsBuilder();
3745
        }
3746
        return this.update_table_statistics;
3747
    }
3748
3749
    @Override
3750
    public DropTableBuilder drop_table() {
3751
        if (this.drop_table == null) {
3752
            this.drop_table = this.createDropTableBuilder();
3753
        }
3754
        return this.drop_table;
3755
    }
3756
3757
    @Override
3758 43687 jjdelcerro
    public CreateIndexBuilder create_index() {
3759
        if (this.create_index == null) {
3760
            this.create_index = this.createCreateIndexBuilder();
3761
        }
3762
        return this.create_index;
3763
    }
3764
3765
    @Override
3766 46099 jjdelcerro
    public DropIndexBuilder drop_index() {
3767
        if (this.drop_index == null) {
3768
            this.drop_index = this.createDropIndexBuilder();
3769
        }
3770
        return this.drop_index;
3771
    }
3772
3773
    @Override
3774 43020 jjdelcerro
    public DeleteBuilder delete() {
3775
        if (this.delete == null) {
3776
            this.delete = this.createDeleteBuilder();
3777
        }
3778
        return this.delete;
3779
    }
3780
3781
    @Override
3782
    public InsertBuilder insert() {
3783
        if (this.insert == null) {
3784
            this.insert = this.createInsertBuilder();
3785
        }
3786
        return this.insert;
3787
    }
3788
3789
    @Override
3790 44329 jjdelcerro
    public TableNameBuilder table_name() {
3791
        if (this.table_name == null) {
3792
            this.table_name = this.createTableNameBuilder();
3793
        }
3794
        return this.table_name;
3795
    }
3796
3797
3798
    @Override
3799 43020 jjdelcerro
    public AlterTableBuilder alter_table() {
3800
        if (this.alter_table == null) {
3801
            this.alter_table = this.createAlterTableBuilder();
3802
        }
3803
        return this.alter_table;
3804
    }
3805
3806
    @Override
3807
    public CreateTableBuilder create_table() {
3808
        if (this.create_table == null) {
3809
            this.create_table = this.createCreateTableBuilder();
3810
        }
3811
        return this.create_table;
3812
    }
3813
3814
    @Override
3815
    public GrantBuilder grant() {
3816
        if (this.grant == null) {
3817
            this.grant = this.createGrantBuilder();
3818
        }
3819
        return this.grant;
3820
    }
3821 44376 jjdelcerro
3822
    @Override
3823
    public Column column(String name) {
3824
        ColumnBase col = new ColumnBase(null, name);
3825
        return col;
3826
    }
3827 43020 jjdelcerro
3828 44376 jjdelcerro
    @Override
3829
    public Column column(TableNameBuilder table, String name) {
3830
        ColumnBase col = new ColumnBase(table, name);
3831
        return col;
3832
    }
3833
3834 46518 fdiaz
    public Column column_from(Variable variable) {
3835
        Column c = null;
3836
        if (variable instanceof Column) {
3837
            c = this.column(((Column) variable).table(), variable.name());
3838
        } else {
3839
            c = this.column(variable.name());
3840
        }
3841
        c.copyPropertiesFrom(variable);
3842
        return c;
3843
3844
    }
3845
3846
    public Column column_from(TableNameBuilder table, Variable variable) {
3847
        Column c = this.column(table, variable.name());
3848
        c.copyPropertiesFrom(variable);
3849
        return c;
3850
    }
3851
3852
3853
3854 44376 jjdelcerro
    protected JoinBase createJoin(String type, TableNameBuilder table, Value expression) {
3855
        return new JoinBase(type, table, expression);
3856
    }
3857
3858 46505 fdiaz
    @Override
3859 43020 jjdelcerro
    public void accept(Visitor visitor, VisitorFilter filter) {
3860
        if (this.select != null) {
3861
            this.select.accept(visitor, filter);
3862
        }
3863
        if (this.update != null) {
3864
            this.update.accept(visitor, filter);
3865
        }
3866
        if (this.insert != null) {
3867
            this.insert.accept(visitor, filter);
3868
        }
3869
        if (this.delete != null) {
3870
            this.delete.accept(visitor, filter);
3871
        }
3872
        if (this.alter_table != null) {
3873
            this.alter_table.accept(visitor, filter);
3874
        }
3875
        if (this.create_table != null) {
3876
            this.create_table.accept(visitor, filter);
3877
        }
3878
        if (this.drop_table != null) {
3879
            this.drop_table.accept(visitor, filter);
3880
        }
3881 44329 jjdelcerro
        if (this.table_name != null) {
3882
            this.table_name.accept(visitor, filter);
3883
        }
3884 43020 jjdelcerro
    }
3885
3886 46505 fdiaz
    @Override
3887 46104 omartinez
    public Formatter formatter() {
3888 44769 jjdelcerro
        return expression().formatter();
3889 44198 jjdelcerro
    }
3890
3891 43020 jjdelcerro
    @Override
3892
    public String toString() {
3893 44198 jjdelcerro
        return this.toString(formatter());
3894
    }
3895
3896
    @Override
3897
    public String toString(Formatter formatter) {
3898 43020 jjdelcerro
        if (this.select != null) {
3899 44198 jjdelcerro
            return this.select.toString(formatter);
3900 43020 jjdelcerro
        }
3901
        if (this.update != null) {
3902 44198 jjdelcerro
            return this.update.toString(formatter);
3903 43020 jjdelcerro
        }
3904
        if (this.insert != null) {
3905 44198 jjdelcerro
            return this.insert.toString(formatter);
3906 43020 jjdelcerro
        }
3907
        if (this.delete != null) {
3908 44198 jjdelcerro
            return this.delete.toString(formatter);
3909 43020 jjdelcerro
        }
3910
        if (this.alter_table != null) {
3911 44198 jjdelcerro
            return this.alter_table.toString(formatter);
3912 43020 jjdelcerro
        }
3913
        if (this.create_table != null) {
3914 44198 jjdelcerro
            return this.create_table.toString(formatter);
3915 43020 jjdelcerro
        }
3916
        if (this.drop_table != null) {
3917 44198 jjdelcerro
            return this.drop_table.toString(formatter);
3918 43020 jjdelcerro
        }
3919
        if (this.update_table_statistics != null) {
3920 44198 jjdelcerro
            return this.update_table_statistics.toString(formatter);
3921 43020 jjdelcerro
        }
3922 46099 jjdelcerro
        if (this.create_index != null) {
3923
            return this.create_index.toString(formatter);
3924
        }
3925
        if (this.drop_index != null) {
3926
            return this.drop_index.toString(formatter);
3927
        }
3928 44329 jjdelcerro
        if (this.table_name != null) {
3929
            return this.table_name.toString(formatter);
3930
        }
3931 44198 jjdelcerro
        return "";
3932 43020 jjdelcerro
    }
3933
3934
    @Override
3935 44198 jjdelcerro
    public CountBuilder count() {
3936
        return new CountBuilderBase();
3937 43020 jjdelcerro
    }
3938
3939
    @Override
3940 44198 jjdelcerro
    public List<Parameter> parameters() {
3941
        final List<Parameter> params = new ArrayList<>();
3942 46258 jjdelcerro
        this.accept((Visitable value) -> {
3943
            params.add((Parameter) value);
3944 44198 jjdelcerro
        }, new ClassVisitorFilter(Parameter.class));
3945
        return params;
3946 43020 jjdelcerro
    }
3947
3948
    @Override
3949 44198 jjdelcerro
    public List<Variable> variables() {
3950
        final List<Variable> vars = new ArrayList<>();
3951
        this.accept(new Visitor() {
3952
            @Override
3953
            public void visit(Visitable value) {
3954
                if (!vars.contains((Variable) value)) {
3955
                    vars.add((Variable) value);
3956
                }
3957
            }
3958
        }, new ClassVisitorFilter(Variable.class));
3959
        return vars;
3960 43020 jjdelcerro
    }
3961
3962 44042 jjdelcerro
    @Override
3963 44198 jjdelcerro
    public List<String> parameters_names() {
3964
        List<String> params = new ArrayList<>();
3965
        for (Parameter param : parameters()) {
3966
            String s;
3967
            switch (param.type()) {
3968 44644 jjdelcerro
                case PARAMETER_TYPE_CONSTANT:
3969 44198 jjdelcerro
                    Object theValue = param.value();
3970
                    if (theValue == null) {
3971
                        s = "null";
3972
                    } else if (theValue instanceof String) {
3973
                        s = "'" + (String) theValue + "'";
3974
                    } else {
3975
                        s = theValue.toString();
3976
                    }
3977
                    break;
3978 44644 jjdelcerro
                case PARAMETER_TYPE_VARIABLE:
3979 44198 jjdelcerro
                default:
3980
                    s = "\"" + param.name() + "\"";
3981
            }
3982
            params.add(s);
3983 44042 jjdelcerro
        }
3984 44198 jjdelcerro
        return params;
3985 44042 jjdelcerro
    }
3986
3987 44051 omartinez
    @Override
3988 44198 jjdelcerro
    public List<String> variables_names() {
3989
        List<String> vars = new ArrayList<>();
3990
        for (Variable var : this.variables()) {
3991
            vars.add(var.name());
3992
        }
3993
        Collections.sort(vars);
3994
        return vars;
3995 45385 omartinez
    }
3996 46258 jjdelcerro
3997
    protected String[] aggregateFunctionNames = new String[] {
3998
        "MAX",
3999
        "MIN",
4000
        "COUNT",
4001
        "SUM"
4002
    };
4003
4004
    @Override
4005
    public boolean isAggregateFunction(String funcname) {
4006
        for (String aggregateFunctionName : this.aggregateFunctionNames) {
4007
            if( StringUtils.equalsIgnoreCase(aggregateFunctionName, funcname)) {
4008
                return true;
4009
            }
4010
        }
4011
        return false;
4012
    }
4013 46309 jjdelcerro
4014
    @Override
4015
    public int getMaxRecomendedSQLLength() {
4016
        return DEFAULT_RECOMENDED_SQL_LENGTH;
4017
    }
4018
4019 47261 jjdelcerro
    public String getConstrainName(TableNameBuilder table, String columnName, String constrainType) {
4020
        // String constraint_name = "CSTR_" + this.table().getName() + "_" + constrainType + "_" + columnName;
4021
        String constraint_name = table.getName() + "_" + constrainType + "_" + columnName;
4022
        return constraint_name;
4023
    }
4024 43020 jjdelcerro
}