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 @ 44198

History | View | Annotate | Download (93.1 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 44042 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionBuilder;
17 44198 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionBuilder.AbstractValue;
18
import org.gvsig.expressionevaluator.ExpressionBuilder.ClassVisitorFilter;
19
import org.gvsig.expressionevaluator.ExpressionBuilder.GeometrySupportType;
20
import org.gvsig.expressionevaluator.ExpressionBuilder.Parameter;
21
import org.gvsig.expressionevaluator.ExpressionBuilder.Value;
22
import org.gvsig.expressionevaluator.ExpressionBuilder.Variable;
23
import org.gvsig.expressionevaluator.ExpressionBuilder.Visitable;
24
import org.gvsig.expressionevaluator.ExpressionBuilder.Visitor;
25
import org.gvsig.expressionevaluator.ExpressionBuilder.VisitorFilter;
26 44042 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
27 44198 jjdelcerro
import org.gvsig.expressionevaluator.Formatter;
28 44042 jjdelcerro
import org.gvsig.fmap.dal.DataStoreParameters;
29 43020 jjdelcerro
import org.gvsig.fmap.dal.DataTypes;
30
import org.gvsig.fmap.dal.SQLBuilder;
31
import org.gvsig.fmap.dal.SQLBuilder.AlterTableBuilder;
32
import org.gvsig.fmap.dal.SQLBuilder.CreateTableBuilder;
33
import org.gvsig.fmap.dal.SQLBuilder.DeleteBuilder;
34
import org.gvsig.fmap.dal.SQLBuilder.DropTableBuilder;
35
import org.gvsig.fmap.dal.SQLBuilder.FromBuilder;
36
import org.gvsig.fmap.dal.SQLBuilder.GrantBuilder;
37
import org.gvsig.fmap.dal.SQLBuilder.InsertBuilder;
38
import org.gvsig.fmap.dal.SQLBuilder.InsertColumnBuilder;
39
import org.gvsig.fmap.dal.SQLBuilder.OrderByBuilder;
40
import org.gvsig.fmap.dal.SQLBuilder.Privilege;
41
import org.gvsig.fmap.dal.SQLBuilder.SelectBuilder;
42
import org.gvsig.fmap.dal.SQLBuilder.SelectColumnBuilder;
43
import org.gvsig.fmap.dal.SQLBuilder.TableNameBuilder;
44
import org.gvsig.fmap.dal.SQLBuilder.UpdateBuilder;
45
import org.gvsig.fmap.dal.SQLBuilder.UpdateColumnBuilder;
46
import org.gvsig.fmap.dal.SQLBuilder.UpdateTableStatisticsBuilder;
47 43739 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
48 43114 jjdelcerro
import org.gvsig.fmap.geom.Geometry;
49 43020 jjdelcerro
import org.slf4j.Logger;
50
import org.slf4j.LoggerFactory;
51
52 44198 jjdelcerro
@SuppressWarnings("UseSpecificCatch")
53 44042 jjdelcerro
public class SQLBuilderBase implements SQLBuilder {
54 44198 jjdelcerro
55
    protected static final Logger LOGGER = LoggerFactory.getLogger(SQLBuilderBase.class);
56
57 43020 jjdelcerro
    protected SelectBuilder select;
58
    protected UpdateBuilder update;
59
    protected InsertBuilder insert;
60
    protected DeleteBuilder delete;
61
    protected AlterTableBuilder alter_table;
62
    protected CreateTableBuilder create_table;
63
    protected GrantBuilder grant;
64
    protected DropTableBuilder drop_table;
65
    protected UpdateTableStatisticsBuilder update_table_statistics;
66 43687 jjdelcerro
    protected CreateIndexBuilder create_index;
67 43020 jjdelcerro
68 44198 jjdelcerro
    protected abstract class AbstractStatementPart extends AbstractValue {
69 44042 jjdelcerro
70
    }
71
72 44198 jjdelcerro
    protected abstract class AbstractStatement extends AbstractStatementPart {
73 44042 jjdelcerro
74
    }
75
76
    protected class ColumnDescriptorBase implements ColumnDescriptor {
77
78
        private String name;
79
        private int type;
80
        private int type_p;
81
        private int type_s;
82
        private boolean isPk;
83
        private boolean _allowNulls;
84
        private boolean _isAutomatic;
85
        private Object defaultValue;
86
        private int geom_type;
87
        private int geom_subtype;
88
        private Object geom_srsdbcode;
89
        private boolean _isIndexed;
90
        private DataStoreParameters parameters = null;
91
92
        public ColumnDescriptorBase(String name, int type, Object defaultValue) {
93
            this.name = name;
94
            this.type = type;
95
            this.type_p = -1;
96
            this.type_s = -1;
97
            this.isPk = false;
98
            this._allowNulls = true;
99
            this._isAutomatic = false;
100
            this.defaultValue = defaultValue;
101
            this.geom_type = Geometry.TYPES.GEOMETRY;
102
            this.geom_subtype = Geometry.SUBTYPES.GEOM2D;
103
            this.geom_srsdbcode = null;
104
            this._isIndexed = false;
105
        }
106
107
        public ColumnDescriptorBase(String name, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
108
            this.name = name;
109
            this.type = type;
110
            this.type_p = type_p;
111
            this.type_s = type_s;
112
            this.isPk = isPk;
113
            this._allowNulls = allowNulls;
114
            this._isAutomatic = isAutomatic;
115
            this.defaultValue = defaultValue;
116
            this.geom_type = Geometry.TYPES.GEOMETRY;
117
            this.geom_subtype = Geometry.SUBTYPES.GEOM2D;
118
            this.geom_srsdbcode = null;
119
            this._isIndexed = isIndexed;
120
        }
121 44198 jjdelcerro
122 44042 jjdelcerro
        public ColumnDescriptorBase(String name, int geom_type, int geom_subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
123
            this.name = name;
124
            this.type = DataTypes.GEOMETRY;
125
            this.type_p = 0;
126
            this.type_s = 0;
127
            this.isPk = false;
128
            this._allowNulls = allowNulls;
129
            this._isAutomatic = false;
130
            this.defaultValue = null;
131
            this.geom_type = geom_type;
132
            this.geom_subtype = geom_subtype;
133 44198 jjdelcerro
            this.geom_srsdbcode = srs_id(proj);
134 44042 jjdelcerro
            this._isIndexed = isIndexed;
135
        }
136 44198 jjdelcerro
137 44042 jjdelcerro
        public ColumnDescriptorBase(String name, int geom_type, int geom_subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
138
            this.name = name;
139
            this.type = DataTypes.GEOMETRY;
140
            this.type_p = 0;
141
            this.type_s = 0;
142
            this.isPk = false;
143
            this._allowNulls = allowNulls;
144
            this._isAutomatic = false;
145
            this.defaultValue = null;
146
            this.geom_type = geom_type;
147
            this.geom_subtype = geom_subtype;
148
            this.geom_srsdbcode = srsdbcode;
149
            this._isIndexed = isIndexed;
150
        }
151 44198 jjdelcerro
152
        private ColumnDescriptorBase(FeatureAttributeDescriptor fad) {
153
            this(fad.getName(), fad.getType(), fad.getDefaultValue());
154
            this.type_p = fad.getPrecision();
155
            this.type_s = fad.getSize();
156
            this.isPk = fad.isPrimaryKey();
157
            this._allowNulls = fad.allowNull();
158
            this._isAutomatic = fad.isAutomatic();
159
            this._isIndexed = fad.isIndexed();
160
161
            if (fad.getType() == org.gvsig.fmap.geom.DataTypes.GEOMETRY) {
162
                this.geom_type = fad.getGeomType().getType();
163
                this.geom_subtype = fad.getGeomType().getSubType();
164
                this.geom_srsdbcode = fad.getSRS();
165
            }
166
        }
167
168
169 44042 jjdelcerro
        @Override
170
        public String getName() {
171
            return this.name;
172
        }
173 44198 jjdelcerro
174 44042 jjdelcerro
        @Override
175
        public void setName(String name) {
176
            this.name = name;
177
        }
178
179
        @Override
180
        public int getType() {
181
            return this.type;
182
        }
183
184
        @Override
185
        public void setType(int type) {
186
            this.type = type;
187
        }
188
189
        @Override
190
        public int getPrecision() {
191
            return type_p;
192
        }
193
194
        @Override
195
        public void setPrecision(int precision) {
196
            this.type_p = precision;
197
        }
198
199
        @Override
200
        public int getSize() {
201
            return type_s;
202
        }
203
204
        @Override
205
        public void setSize(int size) {
206
            this.type_s = size;
207
        }
208
209
        @Override
210
        public boolean isPrimaryKey() {
211
            return isPk;
212
        }
213
214
        @Override
215
        public void setIsPrimaryKey(boolean isPk) {
216
            this.isPk = isPk;
217
        }
218
219
        @Override
220
        public boolean allowNulls() {
221
            return _allowNulls;
222
        }
223
224
        @Override
225
        public void setAllowNulls(boolean allowNulls) {
226
            this._allowNulls = allowNulls;
227
        }
228
229
        @Override
230
        public boolean isAutomatic() {
231
            return _isAutomatic;
232
        }
233
234
        @Override
235
        public boolean isIndexed() {
236
            return _isIndexed;
237
        }
238
239
        @Override
240
        public void setIsAutomatic(boolean isAutomatic) {
241
            this._isAutomatic = isAutomatic;
242
        }
243
244
        @Override
245
        public Object getDefaultValue() {
246
            return defaultValue;
247
        }
248
249
        @Override
250
        public void setDefaultValue(Object defaultValue) {
251
            this.defaultValue = defaultValue;
252
        }
253
254
        @Override
255
        public int getGeometryType() {
256
            return geom_type;
257
        }
258
259
        @Override
260
        public void setGeometryType(int geom_type) {
261
            this.geom_type = geom_type;
262
        }
263
264
        @Override
265
        public int getGeometrySubtype() {
266
            return geom_subtype;
267
        }
268
269
        @Override
270
        public void setGeometrySubtype(int geom_subtype) {
271
            this.geom_subtype = geom_subtype;
272
        }
273
274
        @Override
275
        public Object getGeometrySRSId() {
276
            return geom_srsdbcode;
277
        }
278
279
        @Override
280
        public void setGeometrySRSId(Object geom_srsid) {
281
            this.geom_srsdbcode = geom_srsid;
282 44198 jjdelcerro
        }
283 44042 jjdelcerro
284
        @Override
285
        public boolean isGeometry() {
286
            return this.type == DataTypes.GEOMETRY;
287
        }
288
289
        private void setStoreParameters(DataStoreParameters parameters) {
290
            this.parameters = parameters;
291
        }
292
293
        @Override
294
        public DataStoreParameters getStoreParameters() {
295
            return this.parameters;
296
        }
297
    }
298 44198 jjdelcerro
//
299
//    public class ColumnBase extends AbstractValue implements Column {
300
//
301
//        protected ColumnDescriptor descriptor;
302
//        protected String name;
303
//
304
//        public ColumnBase(ColumnDescriptor descriptor) {
305
//            this.name = descriptor.getName();
306
//            this.descriptor = descriptor;
307
//        }
308
//
309
//        public ColumnBase(String name) {
310
//            this.name = name;
311
//            this.descriptor = null;
312
//        }
313
//
314
//        @Override
315
//        public ColumnDescriptor getDescriptor() {
316
//            return descriptor;
317
//        }
318
//
319
//        @Override
320
//        public String name() {
321
//            return this.name;
322
//        }
323
//
324
//        @Override
325
//        public String toString() {
326
//            return this.toString(formatter());
327
//        }
328
//
329
//        @Override
330
//        public String toString(Formatter<Value> formatter) {
331
//            if (formatter.canApply(this)) {
332
//                return formatter.format(this);
333
//            }
334
//            return as_identifier(this.name);
335
//        }
336
//
337
//        @Override
338
//        public int compareTo(ExpressionBuilder.Variable o) {
339
//            return this.name.compareTo(o.name());
340
//        }
341
//
342
//        @Override
343
//        public boolean equals(Object obj) {
344
//            if (!(obj instanceof ExpressionBuilder.Variable)) {
345
//                return false;
346
//            }
347
//            return this.name.equals(((ExpressionBuilder.Variable) obj).name());
348
//        }
349
//
350
//        @Override
351
//        public int hashCode() {
352
//            int hash = 7;
353
//            hash = 37 * hash + Objects.hashCode(this.name);
354
//            return hash;
355
//        }
356
//
357
//    }
358 44042 jjdelcerro
359 44198 jjdelcerro
    public class TableNameBuilderBase
360
            extends AbstractStatementPart
361
            implements TableNameBuilder {
362 44042 jjdelcerro
363 43020 jjdelcerro
        public String tableName;
364
        public String schemaName;
365
        private String databaseName;
366
367
        public TableNameBuilderBase() {
368
        }
369
370
        @Override
371
        public void accept(Visitor visitor, VisitorFilter filter) {
372 44198 jjdelcerro
            if (filter.accept(this)) {
373 43020 jjdelcerro
                visitor.visit(this);
374
            }
375
        }
376
377
        @Override
378
        public TableNameBuilder database(String name) {
379
            this.databaseName = name;
380
            return this;
381
        }
382
383
        @Override
384
        public TableNameBuilder schema(String name) {
385 44198 jjdelcerro
            if (support_schemas()) {
386 43355 jjdelcerro
                this.schemaName = name;
387
            }
388 43020 jjdelcerro
            return this;
389
        }
390
391
        @Override
392
        public TableNameBuilder name(String name) {
393
            this.tableName = name;
394
            return this;
395
        }
396
397
        @Override
398
        public String getDatabase() {
399
            return this.databaseName;
400
        }
401
402
        @Override
403
        public String getSchema() {
404
            return this.schemaName;
405
        }
406
407
        @Override
408
        public String getName() {
409
            return this.tableName;
410
        }
411 44198 jjdelcerro
412 43020 jjdelcerro
        @Override
413
        public boolean has_schema() {
414 44198 jjdelcerro
            if (!support_schemas()) {
415 43355 jjdelcerro
                return false;
416
            }
417 43020 jjdelcerro
            return !StringUtils.isEmpty(this.schemaName);
418
        }
419
420
        @Override
421
        public boolean has_database() {
422
            return !StringUtils.isEmpty(this.databaseName);
423
        }
424 44198 jjdelcerro
425 43020 jjdelcerro
        @Override
426
        public String toString() {
427 44198 jjdelcerro
            return this.toString(formatter());
428
        }
429
430
        @Override
431
        public String toString(Formatter<Value> formatter) {
432
            if (formatter.canApply(this)) {
433
                return formatter.format(this);
434
            }
435
            if (this.has_database()) {
436
                if (this.has_schema()) {
437
                    return as_identifier(this.databaseName) + "."
438
                            + as_identifier(this.schemaName) + "."
439
                            + as_identifier(this.tableName);
440 43020 jjdelcerro
                }
441
            } else {
442 44198 jjdelcerro
                if (this.has_schema()) {
443
                    return as_identifier(this.schemaName) + "."
444
                            + as_identifier(this.tableName);
445
                }
446 43020 jjdelcerro
            }
447 44198 jjdelcerro
            return as_identifier(this.tableName);
448 43020 jjdelcerro
        }
449
450
    }
451
452 44198 jjdelcerro
    public class CountBuilderBase
453
            extends AbstractStatementPart
454
            implements CountBuilder {
455 43020 jjdelcerro
456
        protected Value value;
457
        protected boolean distinct;
458 44198 jjdelcerro
        protected boolean all;
459
460 43020 jjdelcerro
        public CountBuilderBase() {
461
            this.value = null;
462
            this.distinct = false;
463
            this.all = false;
464
        }
465 44198 jjdelcerro
466 43020 jjdelcerro
        @Override
467
        public CountBuilder all() {
468
            this.all = true;
469
            return this;
470
        }
471
472
        @Override
473
        public CountBuilder column(Value value) {
474
            this.value = value;
475
            return this;
476
        }
477
478
        @Override
479
        public CountBuilder distinct() {
480
            this.distinct = true;
481
            return this;
482
        }
483
484
        @Override
485
        public String toString() {
486 44198 jjdelcerro
            return this.toString(formatter());
487
        }
488
489
        @Override
490
        public String toString(Formatter formatter) {
491
            if (formatter.canApply(this)) {
492
                return formatter.format(this);
493 43020 jjdelcerro
            }
494 44198 jjdelcerro
            if (this.all) {
495
                return "COUNT(*)";
496
            }
497
            if (this.distinct) {
498 43020 jjdelcerro
                return MessageFormat.format(
499 44198 jjdelcerro
                        "COUNT(DISTINCT {0})",
500
                        value.toString(formatter)
501 43020 jjdelcerro
                );
502
            }
503
            return MessageFormat.format(
504 44198 jjdelcerro
                    "COUNT({0})",
505
                    value.toString(formatter)
506 43020 jjdelcerro
            );
507
        }
508 44198 jjdelcerro
509 43020 jjdelcerro
    }
510
511 44198 jjdelcerro
    public class FromBuilderBase
512
            extends AbstractStatementPart
513
            implements FromBuilder {
514
515
        protected TableNameBuilder tableName = null;
516 43020 jjdelcerro
        private String subquery = null;
517
        private String passthrough = null;
518
519
        @Override
520
        public TableNameBuilder table() {
521 44198 jjdelcerro
            if (tableName == null) {
522 43114 jjdelcerro
                this.tableName = createTableNameBuilder();
523 43020 jjdelcerro
            }
524
            return this.tableName;
525
        }
526
527
        @Override
528
        public void accept(Visitor visitor, VisitorFilter filter) {
529 44198 jjdelcerro
            if (filter.accept(this)) {
530 43020 jjdelcerro
                visitor.visit(this);
531
            }
532 44198 jjdelcerro
            if (this.tableName != null) {
533 43020 jjdelcerro
                this.tableName.accept(visitor, filter);
534
            }
535
        }
536
537
        @Override
538
        public FromBuilder custom(String passthrough) {
539
            this.passthrough = passthrough;
540
            return this;
541
        }
542
543
        @Override
544
        public FromBuilder subquery(String subquery) {
545
            this.subquery = subquery;
546
            return this;
547
        }
548 44198 jjdelcerro
549 43020 jjdelcerro
        @Override
550
        public String toString() {
551 44198 jjdelcerro
            return this.toString(formatter());
552
        }
553
554
        @Override
555
        public String toString(Formatter<Value> formatter) {
556
            if (formatter.canApply(this)) {
557
                return formatter.format(this);
558
            }
559
            if (!StringUtils.isEmpty(passthrough)) {
560 43020 jjdelcerro
                return passthrough;
561
            }
562 44198 jjdelcerro
            if (!StringUtils.isEmpty(subquery)) {
563 43020 jjdelcerro
                return "( " + this.subquery + ") as _subquery_alias_ ";
564
            }
565 44198 jjdelcerro
            return this.tableName.toString(formatter);
566 43020 jjdelcerro
        }
567
568
    }
569
570 44198 jjdelcerro
    public class SelectColumnBuilderBase
571
            extends AbstractStatementPart
572
            implements SelectColumnBuilder {
573 43020 jjdelcerro
574
        private Variable name = null;
575
        private String alias = null;
576
        private Value value = null;
577
        private boolean asGeometry = false;
578 44198 jjdelcerro
579 43020 jjdelcerro
        @Override
580
        public void accept(Visitor visitor, VisitorFilter filter) {
581 44198 jjdelcerro
            if (filter.accept(this)) {
582 43020 jjdelcerro
                visitor.visit(this);
583
            }
584 44198 jjdelcerro
            if (this.name != null) {
585 43020 jjdelcerro
                this.name.accept(visitor, filter);
586
            }
587 44198 jjdelcerro
            if (this.value != null) {
588 43020 jjdelcerro
                this.value.accept(visitor, filter);
589
            }
590
        }
591
592
        @Override
593
        public SelectColumnBuilder name(String name) {
594 44198 jjdelcerro
            String quote = quote_for_identifiers();
595 43020 jjdelcerro
            if (name.startsWith(quote)) {
596
                // Remove quotes
597
                name = name.substring(1, name.length() - 1);
598
            }
599 44198 jjdelcerro
            this.name = expression().variable(name);
600 43020 jjdelcerro
            this.value = null;
601
            this.asGeometry = false;
602
            return this;
603
        }
604
605
        @Override
606
        public SelectColumnBuilder all() {
607
            this.name = null;
608 44198 jjdelcerro
            this.value = expression().custom("*");
609 43020 jjdelcerro
            this.asGeometry = false;
610
            return this;
611
        }
612 44198 jjdelcerro
613 43020 jjdelcerro
        @Override
614
        public SelectColumnBuilder as_geometry() {
615
            this.asGeometry = true;
616
            return this;
617
        }
618 44198 jjdelcerro
619 43020 jjdelcerro
        @Override
620
        public SelectColumnBuilder value(Value value) {
621
            this.value = value;
622
            this.name = null;
623
            return this;
624
        }
625
626
        @Override
627
        public SelectColumnBuilder as(String alias) {
628
            this.alias = alias;
629
            return this;
630
        }
631
632
        @Override
633
        public String getName() {
634 44198 jjdelcerro
            return this.name.name();
635 43020 jjdelcerro
        }
636 44198 jjdelcerro
637 43020 jjdelcerro
        @Override
638
        public String getAlias() {
639
            return this.alias;
640
        }
641 44198 jjdelcerro
642 43020 jjdelcerro
        @Override
643
        public String getValue() {
644
            return this.alias;
645
        }
646
647
        @Override
648
        public String toString() {
649 44198 jjdelcerro
            return this.toString(formatter());
650
        }
651
652
        @Override
653
        public String toString(Formatter<Value> formatter) {
654
            if (formatter.canApply(this)) {
655
                return formatter.format(this);
656
            }
657 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
658 44198 jjdelcerro
            if (this.asGeometry) {
659
                builder.append(expression().ST_AsBinary(this.name).toString(formatter));
660 43020 jjdelcerro
            } else {
661 44198 jjdelcerro
                if (this.name != null) {
662
                    builder.append(this.name.toString(formatter));
663 43020 jjdelcerro
                } else {
664 44198 jjdelcerro
                    builder.append(this.value.toString(formatter));
665 43020 jjdelcerro
                }
666
            }
667 44198 jjdelcerro
            if (this.alias != null) {
668 43020 jjdelcerro
                builder.append(" AS ");
669 44198 jjdelcerro
                builder.append(as_identifier(this.alias));
670 43020 jjdelcerro
            }
671
            return builder.toString();
672
        }
673
    }
674
675 44198 jjdelcerro
    public class OrderByBuilderBase
676
            extends AbstractStatementPart
677
            implements OrderByBuilder {
678
679 43020 jjdelcerro
        protected String value;
680
        protected String custom;
681
        protected boolean ascending;
682 44198 jjdelcerro
683 43020 jjdelcerro
        public OrderByBuilderBase() {
684 43114 jjdelcerro
            this.ascending = true;
685 43020 jjdelcerro
        }
686
687
        @Override
688
        public void accept(Visitor visitor, VisitorFilter filter) {
689 44198 jjdelcerro
            if (filter.accept(this)) {
690 43020 jjdelcerro
                visitor.visit(this);
691
            }
692
        }
693
694
        @Override
695
        public OrderByBuilder column(String name) {
696
            this.value = name;
697
            return this;
698
        }
699
700
        @Override
701
        public OrderByBuilder custom(String order) {
702
            this.custom = order;
703
            return this;
704
        }
705
706
        @Override
707
        public OrderByBuilder ascending() {
708
            this.ascending = true;
709
            return this;
710
        }
711
712
        @Override
713
        public OrderByBuilder ascending(boolean asc) {
714
            this.ascending = asc;
715
            return this;
716
        }
717
718
        @Override
719
        public OrderByBuilder descending() {
720
            this.ascending = false;
721
            return this;
722
        }
723
724
        @Override
725
        public String toString() {
726 44198 jjdelcerro
            return this.toString(formatter());
727
        }
728
729
        @Override
730
        public String toString(Formatter<Value> formatter) {
731
            if (formatter.canApply(this)) {
732
                return formatter.format(this);
733
            }
734
            if (!StringUtils.isEmpty(this.custom)) {
735 43020 jjdelcerro
                return this.custom;
736
            }
737 44198 jjdelcerro
            if (this.ascending) {
738
                return as_identifier(this.value) + " ASC";
739 43020 jjdelcerro
            }
740 44198 jjdelcerro
            return as_identifier(this.value) + " DESC";
741 43020 jjdelcerro
        }
742
    }
743
744 44198 jjdelcerro
    public class SelectBuilderBase
745
            extends AbstractStatement
746
            implements SelectBuilder {
747
748 43020 jjdelcerro
        protected FromBuilder from;
749
        protected ExpressionBuilder where;
750
        protected long limit = -1;
751
        protected long offset = -1;
752
        protected List<SelectColumnBuilder> columns;
753
        protected List<OrderByBuilder> order_by;
754
        protected boolean distinct;
755
756
        public SelectBuilderBase() {
757
            this.columns = new ArrayList<>();
758
            this.distinct = false;
759
        }
760
761
        @Override
762
        public void accept(Visitor visitor, VisitorFilter filter) {
763 44198 jjdelcerro
            if (filter.accept(this)) {
764 43020 jjdelcerro
                visitor.visit(this);
765
            }
766
            for (SelectColumnBuilder column : columns) {
767 44198 jjdelcerro
                column.accept(visitor, filter);
768 43020 jjdelcerro
            }
769 44198 jjdelcerro
            if (this.has_from()) {
770
                this.from.accept(visitor, filter);
771 43020 jjdelcerro
            }
772 44198 jjdelcerro
            if (this.has_where()) {
773
                this.where.accept(visitor, filter);
774 43020 jjdelcerro
            }
775 44198 jjdelcerro
            if (this.has_order_by()) {
776 43020 jjdelcerro
                for (OrderByBuilder order : order_by) {
777 44198 jjdelcerro
                    order.accept(visitor, filter);
778 43020 jjdelcerro
                }
779
            }
780
        }
781
782
        @Override
783
        public SelectBuilder distinct() {
784
            this.distinct = true;
785
            return this;
786
        }
787 44198 jjdelcerro
788 43020 jjdelcerro
        @Override
789
        public SelectColumnBuilder column() {
790
            SelectColumnBuilder builder = createSelectColumnBuilder();
791
            this.columns.add(builder);
792
            return builder;
793
        }
794
795
        @Override
796
        public boolean has_column(String name) {
797
            for (SelectColumnBuilder column : columns) {
798 44198 jjdelcerro
                if (name.equals(column.getName())) {
799 43020 jjdelcerro
                    return true;
800
                }
801
            }
802
            return false;
803
        }
804
805
        @Override
806
        public FromBuilder from() {
807
            if (this.from == null) {
808
                this.from = createFromBuilder();
809
            }
810
            return this.from;
811
        }
812
813
        @Override
814
        public boolean has_from() {
815
            return this.from != null;
816
        }
817 44198 jjdelcerro
818 43020 jjdelcerro
        @Override
819
        public ExpressionBuilder where() {
820
            if (this.where == null) {
821
                this.where = createExpressionBuilder();
822
            }
823
            return this.where;
824
        }
825
826
        @Override
827
        public boolean has_where() {
828 44198 jjdelcerro
            if (this.where == null) {
829 43020 jjdelcerro
                return false;
830
            }
831 44198 jjdelcerro
            return this.where.value() != null;
832 43020 jjdelcerro
        }
833 44198 jjdelcerro
834 43020 jjdelcerro
        @Override
835
        public SelectBuilder limit(long limit) {
836
            this.limit = limit;
837
            return this;
838
        }
839
840
        @Override
841 44058 jjdelcerro
        public SelectBuilder limit(Long limit) {
842 44198 jjdelcerro
            if (limit == null) {
843 44058 jjdelcerro
                this.limit = 0;
844
            } else {
845
                this.limit = limit;
846
            }
847
            return this;
848
        }
849
850
        @Override
851 43020 jjdelcerro
        public boolean has_limit() {
852
            return this.limit > 0;
853
        }
854
855
        @Override
856
        public SelectBuilder offset(long offset) {
857
            this.offset = offset;
858
            return this;
859
        }
860
861
        @Override
862
        public boolean has_offset() {
863
            return this.offset > 0;
864
        }
865
866
        @Override
867
        public OrderByBuilder order_by() {
868 44198 jjdelcerro
            if (this.order_by == null) {
869 43093 jjdelcerro
                this.order_by = new ArrayList<>();
870
            }
871 43020 jjdelcerro
            OrderByBuilder order = createOrderByBuilder();
872
            this.order_by.add(order);
873
            return order;
874
        }
875
876
        @Override
877
        public boolean has_order_by() {
878 44198 jjdelcerro
            if (this.order_by == null) {
879 43020 jjdelcerro
                return false;
880
            }
881
            return !this.order_by.isEmpty();
882
        }
883 44198 jjdelcerro
884 43093 jjdelcerro
        protected boolean isValid(StringBuilder message) {
885 44198 jjdelcerro
            if (message == null) {
886 43093 jjdelcerro
                message = new StringBuilder();
887
            }
888 44198 jjdelcerro
            if (this.has_offset() && !this.has_order_by()) {
889 43093 jjdelcerro
                // Algunos gestores de BBDD requieren que se especifique un
890
                // orden para poder usar OFFSET. Como eso parece buena idea para
891
                // asegurar que siempre tengamos los mismo resultados, lo exijimos
892
                // siempre.
893
                message.append("Can't use OFFSET without an ORDER BY.");
894
                return false;
895
            }
896
            return true;
897
        }
898 44198 jjdelcerro
899 43020 jjdelcerro
        @Override
900
        public String toString() {
901 44198 jjdelcerro
            return this.toString(formatter());
902
        }
903
904
        @Override
905
        public String toString(Formatter<Value> formatter) {
906
            if (formatter.canApply(this)) {
907
                return formatter.format(this);
908
            }
909 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
910 44198 jjdelcerro
            if (!this.isValid(builder)) {
911 43093 jjdelcerro
                throw new IllegalStateException(builder.toString());
912
            }
913 43020 jjdelcerro
            builder.append("SELECT ");
914 44198 jjdelcerro
            if (this.distinct) {
915 43020 jjdelcerro
                builder.append("DISTINCT ");
916
            }
917
            boolean first = true;
918
            for (SelectColumnBuilder column : columns) {
919
                if (first) {
920
                    first = false;
921
                } else {
922
                    builder.append(", ");
923
                }
924 44198 jjdelcerro
                builder.append(column.toString(formatter));
925 43020 jjdelcerro
            }
926
927 44198 jjdelcerro
            if (this.has_from()) {
928 43020 jjdelcerro
                builder.append(" FROM ");
929 44198 jjdelcerro
                builder.append(this.from.toString(formatter));
930 43020 jjdelcerro
            }
931 44198 jjdelcerro
            if (this.has_where()) {
932 43020 jjdelcerro
                builder.append(" WHERE ");
933 44198 jjdelcerro
                builder.append(this.where.toString(formatter));
934 43020 jjdelcerro
            }
935 44198 jjdelcerro
936
            if (this.has_order_by()) {
937 43020 jjdelcerro
                builder.append(" ORDER BY ");
938
                first = true;
939
                for (OrderByBuilder item : this.order_by) {
940
                    if (first) {
941
                        first = false;
942
                    } else {
943
                        builder.append(", ");
944
                    }
945 44198 jjdelcerro
                    builder.append(item.toString(formatter));
946
                }
947 43020 jjdelcerro
            }
948 44198 jjdelcerro
949
            if (this.has_limit()) {
950 43020 jjdelcerro
                builder.append(" LIMIT ");
951
                builder.append(this.limit);
952
            }
953 44198 jjdelcerro
            if (this.has_offset()) {
954 43020 jjdelcerro
                builder.append(" OFFSET ");
955
                builder.append(this.offset);
956
            }
957
            return builder.toString();
958
959
        }
960
    }
961
962 44198 jjdelcerro
    public class DropTableBuilderBase
963
            extends AbstractStatement
964
            implements DropTableBuilder {
965 43020 jjdelcerro
966
        protected TableNameBuilder table;
967
968
        @Override
969
        public TableNameBuilder table() {
970 44198 jjdelcerro
            if (table == null) {
971 43114 jjdelcerro
                table = createTableNameBuilder();
972 43020 jjdelcerro
            }
973
            return table;
974
        }
975
976
        @Override
977
        public void accept(Visitor visitor, VisitorFilter filter) {
978 44198 jjdelcerro
            if (filter.accept(this)) {
979 43020 jjdelcerro
                visitor.visit(this);
980
            }
981 44198 jjdelcerro
            this.table.accept(visitor, filter);
982 43020 jjdelcerro
        }
983 44198 jjdelcerro
984 43020 jjdelcerro
        @Override
985
        public String toString() {
986 44198 jjdelcerro
            return this.toString(formatter());
987
        }
988
989
        @Override
990
        public String toString(Formatter<Value> formatter) {
991
            if (formatter.canApply(this)) {
992
                return formatter.format(this);
993
            }
994 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
995
            boolean first = true;
996 44198 jjdelcerro
            for (String sql : toStrings(formatter)) {
997
                if (StringUtils.isEmpty(sql)) {
998 43020 jjdelcerro
                    continue;
999
                }
1000
                if (first) {
1001
                    first = false;
1002
                } else {
1003
                    builder.append("; ");
1004
                }
1005
                builder.append(sql);
1006
            }
1007
            return builder.toString();
1008
        }
1009
1010
        @Override
1011
        public List<String> toStrings() {
1012 44198 jjdelcerro
            return this.toStrings(formatter());
1013
        }
1014
1015
        @Override
1016
        public List<String> toStrings(Formatter formatter) {
1017 43020 jjdelcerro
            List<String> sqls = new ArrayList<>();
1018
1019
            sqls.add(
1020
                    MessageFormat.format(
1021 44198 jjdelcerro
                            STMT_DROP_TABLE_table,
1022
                            this.table.toString(formatter)
1023 43020 jjdelcerro
                    )
1024
            );
1025
            String sql;
1026 44198 jjdelcerro
            if (!StringUtils.isBlank(STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table)) {
1027 43020 jjdelcerro
                if (this.table.has_schema()) {
1028
                    sql = MessageFormat.format(
1029 44198 jjdelcerro
                            STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table,
1030
                            as_string(this.table.getSchema()),
1031
                            as_string(this.table.getName())
1032 43020 jjdelcerro
                    );
1033
                } else {
1034
                    sql = MessageFormat.format(
1035 44198 jjdelcerro
                            STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_table,
1036
                            as_identifier(this.table.getName())
1037 43020 jjdelcerro
                    );
1038
                }
1039 44198 jjdelcerro
                if (!StringUtils.isEmpty(sql)) {
1040 43020 jjdelcerro
                    sqls.add(sql);
1041
                }
1042
            }
1043
            return sqls;
1044
        }
1045
    }
1046
1047 44198 jjdelcerro
    public class GrantRoleBuilderBase
1048
            extends AbstractStatementPart
1049
            implements GrantRoleBuilder {
1050
1051 43020 jjdelcerro
        protected TableNameBuilder table;
1052
        protected String role;
1053
        protected Set<Privilege> privileges;
1054
1055
        public GrantRoleBuilderBase(TableNameBuilder table, String role) {
1056
            this.table = table;
1057
            this.role = role;
1058
            this.privileges = new HashSet<>();
1059
        }
1060
1061
        @Override
1062
        public GrantRoleBuilder privilege(Privilege privilege) {
1063
            privileges.add(privilege);
1064
            return this;
1065
        }
1066 44198 jjdelcerro
1067 43020 jjdelcerro
        @Override
1068
        public GrantRoleBuilder select() {
1069 44198 jjdelcerro
            privileges.add(Privilege.SELECT);
1070 43020 jjdelcerro
            return this;
1071
        }
1072
1073
        @Override
1074
        public GrantRoleBuilder update() {
1075 44198 jjdelcerro
            privileges.add(Privilege.UPDATE);
1076 43020 jjdelcerro
            return this;
1077
        }
1078
1079
        @Override
1080
        public GrantRoleBuilder insert() {
1081
            privileges.add(Privilege.INSERT);
1082
            return this;
1083
        }
1084
1085
        @Override
1086
        public GrantRoleBuilder delete() {
1087
            privileges.add(Privilege.DELETE);
1088
            return this;
1089
        }
1090
1091
        @Override
1092
        public GrantRoleBuilder truncate() {
1093
            privileges.add(Privilege.TRUNCATE);
1094
            return this;
1095
        }
1096
1097
        @Override
1098
        public GrantRoleBuilder reference() {
1099
            privileges.add(Privilege.REFERENCE);
1100
            return this;
1101
        }
1102
1103
        @Override
1104
        public GrantRoleBuilder trigger() {
1105
            privileges.add(Privilege.TRIGGER);
1106
            return this;
1107
        }
1108
1109
        @Override
1110
        public GrantRoleBuilder all() {
1111
            privileges.add(Privilege.ALL);
1112
            return this;
1113
        }
1114
1115
        protected String getPrivilegeName(Privilege privilege) {
1116 44198 jjdelcerro
            switch (privilege) {
1117 43020 jjdelcerro
                case DELETE:
1118
                    return "DELETE";
1119
                case INSERT:
1120
                    return "INSERT";
1121
                case REFERENCE:
1122
                    return "REFERENCE";
1123
                case SELECT:
1124
                    return "SELECT";
1125
                case TRIGGER:
1126
                    return "TRIGGER";
1127
                case TRUNCATE:
1128
                    return "TRUNCATE";
1129
                case UPDATE:
1130
                    return "UPDATE";
1131
                case ALL:
1132
                default:
1133
                    return "ALL";
1134
            }
1135
        }
1136 44198 jjdelcerro
1137 43020 jjdelcerro
        @Override
1138
        public String toString() {
1139 44198 jjdelcerro
            return this.toString(formatter());
1140
        }
1141
1142
        @Override
1143
        public String toString(Formatter<Value> formatter) {
1144
            if (formatter.canApply(this)) {
1145
                return formatter.format(this);
1146
            }
1147 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
1148
            boolean first = true;
1149
            for (Privilege privilege : privileges) {
1150
                if (first) {
1151
                    first = false;
1152
                } else {
1153
                    builder.append(", ");
1154
                }
1155 44198 jjdelcerro
                builder.append(this.getPrivilegeName(privilege));
1156 43020 jjdelcerro
            }
1157
            String sql = MessageFormat.format(
1158 44198 jjdelcerro
                    STMT_GRANT_privileges_ON_table_TO_role,
1159 43020 jjdelcerro
                    builder.toString(),
1160 44198 jjdelcerro
                    table.toString(formatter),
1161 43020 jjdelcerro
                    role
1162
            );
1163
            return sql;
1164
        }
1165
    }
1166
1167 44198 jjdelcerro
    public class GrantBuilderBase
1168
            extends AbstractStatement
1169
            implements GrantBuilder {
1170
1171 43020 jjdelcerro
        protected TableNameBuilder table;
1172
        protected Map<String, GrantRoleBuilder> roles;
1173
1174
        public GrantBuilderBase() {
1175
            this.roles = new HashMap<>();
1176
        }
1177 44198 jjdelcerro
1178 43020 jjdelcerro
        @Override
1179
        public TableNameBuilder table() {
1180 44198 jjdelcerro
            if (table == null) {
1181 43114 jjdelcerro
                table = createTableNameBuilder();
1182 43020 jjdelcerro
            }
1183
            return table;
1184
        }
1185
1186
        @Override
1187
        public void accept(Visitor visitor, VisitorFilter filter) {
1188 44198 jjdelcerro
            if (filter.accept(this)) {
1189 43020 jjdelcerro
                visitor.visit(this);
1190
            }
1191 44198 jjdelcerro
            if (this.table != null) {
1192
                this.table.accept(visitor, filter);
1193 43020 jjdelcerro
            }
1194
        }
1195 44198 jjdelcerro
1196 43020 jjdelcerro
        @Override
1197
        public GrantRoleBuilder role(String role) {
1198
            GrantRoleBuilder roleBuilder = this.roles.get(role);
1199 44198 jjdelcerro
            if (roleBuilder == null) {
1200 43020 jjdelcerro
                roleBuilder = createGrantRoleBuilder(this.table(), role);
1201
                this.roles.put(role, roleBuilder);
1202
            }
1203
            return roleBuilder;
1204
        }
1205
1206
        @Override
1207
        public String toString() {
1208 44198 jjdelcerro
            return this.toString(formatter());
1209
        }
1210
1211
        @Override
1212
        public String toString(Formatter<Value> formatter) {
1213
            if (formatter.canApply(this)) {
1214
                return formatter.format(this);
1215
            }
1216 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
1217
            boolean first = true;
1218 44198 jjdelcerro
            for (String sql : toStrings(formatter)) {
1219
                if (StringUtils.isEmpty(sql)) {
1220 43020 jjdelcerro
                    continue;
1221
                }
1222
                if (first) {
1223
                    first = false;
1224
                } else {
1225
                    builder.append("; ");
1226
                }
1227
                builder.append(sql);
1228
            }
1229
            return builder.toString();
1230
        }
1231
1232
        @Override
1233
        public List<String> toStrings() {
1234 44198 jjdelcerro
            return this.toStrings(formatter());
1235
        }
1236
1237
        @Override
1238
        public List<String> toStrings(Formatter formatter) {
1239 43020 jjdelcerro
            List<String> sqls = new ArrayList<>();
1240
            for (GrantRoleBuilder role : roles.values()) {
1241 44198 jjdelcerro
                sqls.add(role.toString(formatter));
1242 43020 jjdelcerro
            }
1243
            return sqls;
1244
        }
1245
    }
1246
1247 44198 jjdelcerro
    public class UpdateColumnBuilderBase
1248
            extends InsertColumnBuilderBase
1249
            implements UpdateColumnBuilder {
1250
1251 43020 jjdelcerro
        public UpdateColumnBuilderBase() {
1252
            super();
1253
        }
1254
1255
        @Override
1256
        public UpdateColumnBuilder name(String name) {
1257
            return (UpdateColumnBuilder) super.name(name);
1258
        }
1259
1260
        @Override
1261
        public UpdateColumnBuilder with_value(Value value) {
1262
            return (UpdateColumnBuilder) super.with_value(value);
1263
        }
1264 44198 jjdelcerro
1265 43020 jjdelcerro
    }
1266
1267 44198 jjdelcerro
    public class UpdateBuilderBase
1268
            extends AbstractStatement
1269
            implements UpdateBuilder {
1270
1271 43020 jjdelcerro
        protected ExpressionBuilder where;
1272
        protected List<UpdateColumnBuilder> columns;
1273
        protected TableNameBuilder table;
1274
1275
        public UpdateBuilderBase() {
1276
            this.columns = new ArrayList<>();
1277
        }
1278
1279
        @Override
1280
        public void accept(Visitor visitor, VisitorFilter filter) {
1281 44198 jjdelcerro
            if (filter.accept(this)) {
1282 43020 jjdelcerro
                visitor.visit(this);
1283
            }
1284 44198 jjdelcerro
            if (this.table != null) {
1285 43020 jjdelcerro
                this.table.accept(visitor, filter);
1286
            }
1287
            for (UpdateColumnBuilder column : columns) {
1288
                column.accept(visitor, filter);
1289
            }
1290 44198 jjdelcerro
            if (this.has_where()) {
1291 43020 jjdelcerro
                this.where.accept(visitor, filter);
1292
            }
1293
        }
1294
1295
        @Override
1296
        public ExpressionBuilder where() {
1297
            if (this.where == null) {
1298
                this.where = createExpressionBuilder();
1299
            }
1300
            return this.where;
1301
        }
1302
1303
        @Override
1304
        public TableNameBuilder table() {
1305 44198 jjdelcerro
            if (table == null) {
1306 43114 jjdelcerro
                table = createTableNameBuilder();
1307 43020 jjdelcerro
            }
1308
            return table;
1309
        }
1310
1311
        @Override
1312
        public UpdateColumnBuilder column() {
1313
            UpdateColumnBuilder column = createUpdateColumnBuilder();
1314
            this.columns.add(column);
1315
            return column;
1316
        }
1317 44198 jjdelcerro
1318 43020 jjdelcerro
        @Override
1319
        public boolean has_where() {
1320
            return this.where != null;
1321
        }
1322
1323
        @Override
1324
        public String toString() {
1325 44198 jjdelcerro
            return this.toString(formatter());
1326
        }
1327
1328
        @Override
1329
        public String toString(Formatter<Value> formatter) {
1330
            if (formatter.canApply(this)) {
1331
                return formatter.format(this);
1332
            }
1333 43020 jjdelcerro
            /*
1334
             * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
1335
             * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
1336
             * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
1337
             * output_expression [ AS output_name ] [, ...] ]
1338
             */
1339
            StringBuilder columnsAndValues = new StringBuilder();
1340
1341
            boolean first = true;
1342
            for (UpdateColumnBuilder column : columns) {
1343
                if (first) {
1344
                    first = false;
1345
                } else {
1346
                    columnsAndValues.append(", ");
1347
                }
1348 44198 jjdelcerro
                columnsAndValues.append(as_identifier(column.getName()));
1349 43020 jjdelcerro
                columnsAndValues.append(" = ");
1350 44198 jjdelcerro
                columnsAndValues.append(column.getValue().toString(formatter));
1351 43020 jjdelcerro
            }
1352 44198 jjdelcerro
1353 43020 jjdelcerro
            String sql;
1354 44198 jjdelcerro
            if (this.has_where()) {
1355 43020 jjdelcerro
                sql = MessageFormat.format(
1356 44198 jjdelcerro
                        STMT_UPDATE_table_SET_columnsAndValues_WHERE_expresion,
1357
                        this.table.toString(formatter),
1358 43020 jjdelcerro
                        columnsAndValues.toString(),
1359 44198 jjdelcerro
                        this.where.toString(formatter)
1360 43020 jjdelcerro
                );
1361
            } else {
1362
                sql = MessageFormat.format(
1363 44198 jjdelcerro
                        STMT_UPDATE_table_SET_columnsAndValues,
1364
                        this.table.toString(formatter),
1365 43020 jjdelcerro
                        columnsAndValues.toString()
1366
                );
1367
            }
1368
            return sql;
1369
        }
1370
    }
1371
1372 44198 jjdelcerro
    public class DeleteBuilderBase
1373
            extends AbstractStatement
1374
            implements DeleteBuilder {
1375 43020 jjdelcerro
1376
        protected ExpressionBuilder where;
1377
        protected TableNameBuilder table;
1378
1379
        public DeleteBuilderBase() {
1380
        }
1381
1382
        @Override
1383
        public void accept(Visitor visitor, VisitorFilter filter) {
1384 44198 jjdelcerro
            if (filter.accept(this)) {
1385 43020 jjdelcerro
                visitor.visit(this);
1386
            }
1387 44198 jjdelcerro
            if (this.table != null) {
1388 43020 jjdelcerro
                this.table.accept(visitor, filter);
1389
            }
1390 44198 jjdelcerro
            if (this.has_where()) {
1391 43020 jjdelcerro
                this.where.accept(visitor, filter);
1392
            }
1393
        }
1394
1395
        @Override
1396
        public ExpressionBuilder where() {
1397
            if (this.where == null) {
1398
                this.where = createExpressionBuilder();
1399
            }
1400
            return this.where;
1401
        }
1402
1403
        @Override
1404
        public TableNameBuilder table() {
1405 44198 jjdelcerro
            if (table == null) {
1406 43114 jjdelcerro
                table = createTableNameBuilder();
1407 43020 jjdelcerro
            }
1408
            return table;
1409
        }
1410
1411
        @Override
1412
        public boolean has_where() {
1413
            return this.where != null;
1414
        }
1415
1416
        @Override
1417
        public String toString() {
1418 44198 jjdelcerro
            return this.toString(formatter());
1419
        }
1420
1421
        @Override
1422
        public String toString(Formatter<Value> formatter) {
1423
            if (formatter.canApply(this)) {
1424
                return formatter.format(this);
1425
            }
1426 43020 jjdelcerro
            /*
1427
             * DELETE FROM table_name
1428
             * WHERE some_column=some_value;
1429
             */
1430
            String sql;
1431 44198 jjdelcerro
            if (this.has_where()) {
1432 43020 jjdelcerro
                sql = MessageFormat.format(
1433 44198 jjdelcerro
                        STMT_DELETE_FROM_table_WHERE_expresion,
1434
                        this.table.toString(formatter),
1435
                        this.where.toString(formatter)
1436 43020 jjdelcerro
                );
1437
            } else {
1438
                sql = MessageFormat.format(
1439 44198 jjdelcerro
                        STMT_DELETE_FROM_table,
1440
                        this.table.toString(formatter)
1441 43020 jjdelcerro
                );
1442
            }
1443
            return sql;
1444
        }
1445
    }
1446
1447 44198 jjdelcerro
    public class CreateIndexBuilderBase
1448
            extends AbstractStatement
1449
            implements CreateIndexBuilder {
1450 43687 jjdelcerro
1451
        protected boolean ifNotExist = false;
1452
        protected boolean isUnique = false;
1453
        protected String indexName;
1454
        protected boolean isSpatial = false;
1455
        protected TableNameBuilder table;
1456
        protected final List<String> columns;
1457 44198 jjdelcerro
1458 43687 jjdelcerro
        public CreateIndexBuilderBase() {
1459
            this.columns = new ArrayList<>();
1460
        }
1461 44198 jjdelcerro
1462 43687 jjdelcerro
        @Override
1463
        public CreateIndexBuilder unique() {
1464
            this.isUnique = true;
1465
            return this;
1466
        }
1467
1468
        @Override
1469
        public CreateIndexBuilder if_not_exist() {
1470
            this.ifNotExist = true;
1471
            return this;
1472
        }
1473
1474
        @Override
1475
        public CreateIndexBuilder name(String name) {
1476
            this.indexName = name;
1477
            return this;
1478
        }
1479
1480
        @Override
1481
        public CreateIndexBuilder spatial() {
1482
            this.isSpatial = true;
1483
            return this;
1484
        }
1485
1486
        @Override
1487
        public CreateIndexBuilder column(String name) {
1488
            this.columns.add(name);
1489
            return this;
1490
        }
1491
1492
        @Override
1493
        public TableNameBuilder table() {
1494 44198 jjdelcerro
            if (table == null) {
1495 43687 jjdelcerro
                table = createTableNameBuilder();
1496
            }
1497
            return table;
1498
        }
1499
1500
        @Override
1501
        public void accept(Visitor visitor, VisitorFilter filter) {
1502 44198 jjdelcerro
            if (filter.accept(this)) {
1503 43687 jjdelcerro
                visitor.visit(this);
1504
            }
1505 44198 jjdelcerro
            if (this.table != null) {
1506 43687 jjdelcerro
                this.table.accept(visitor, filter);
1507
            }
1508
        }
1509 44198 jjdelcerro
1510 43687 jjdelcerro
        @Override
1511 44198 jjdelcerro
        public String toString() {
1512
            return this.toString(formatter());
1513
        }
1514
1515
        @Override
1516
        public String toString(Formatter<Value> formatter) {
1517
            if (formatter.canApply(this)) {
1518
                return formatter.format(this);
1519
            }
1520
            StringBuilder builder = new StringBuilder();
1521
            boolean first = true;
1522
            for (String sql : toStrings(formatter)) {
1523
                if (StringUtils.isEmpty(sql)) {
1524
                    continue;
1525
                }
1526
                if (first) {
1527
                    first = false;
1528
                } else {
1529
                    builder.append("; ");
1530
                }
1531
                builder.append(sql);
1532
            }
1533
            return builder.toString();
1534
        }
1535
1536
        @Override
1537 43687 jjdelcerro
        public List<String> toStrings() {
1538 44198 jjdelcerro
            return this.toStrings(formatter());
1539
        }
1540
1541
        @Override
1542
        public List<String> toStrings(Formatter formatter) {
1543 43687 jjdelcerro
            StringBuilder builder = new StringBuilder();
1544
            builder.append("CREATE ");
1545 44198 jjdelcerro
            if (this.isUnique) {
1546 43687 jjdelcerro
                builder.append("UNIQUE ");
1547
            }
1548
            builder.append("INDEX ");
1549 44198 jjdelcerro
            if (this.ifNotExist) {
1550 43687 jjdelcerro
                builder.append("IF NOT EXISTS ");
1551
            }
1552 44198 jjdelcerro
            builder.append(as_identifier(this.indexName));
1553 43687 jjdelcerro
            builder.append(" ON ");
1554 44198 jjdelcerro
            builder.append(this.table.toString(formatter));
1555
            if (this.isSpatial) {
1556 43687 jjdelcerro
                builder.append(" USING GIST ");
1557
            }
1558
            builder.append(" ( ");
1559
            boolean is_first_column = true;
1560 44198 jjdelcerro
            for (String column : this.columns) {
1561
                if (is_first_column) {
1562 43687 jjdelcerro
                    is_first_column = false;
1563
                } else {
1564
                    builder.append(", ");
1565
                }
1566
                builder.append(column);
1567
            }
1568
            builder.append(" )");
1569 44198 jjdelcerro
1570 43687 jjdelcerro
            List<String> sqls = new ArrayList<>();
1571
            sqls.add(builder.toString());
1572
            return sqls;
1573
        }
1574
1575
    }
1576 43020 jjdelcerro
1577 44198 jjdelcerro
    public class AlterTableBuilderBase
1578
            extends AbstractStatement
1579
            implements AlterTableBuilder {
1580
1581 43020 jjdelcerro
        protected TableNameBuilder table;
1582
        protected List<String> drops;
1583 43739 jjdelcerro
        protected List<ColumnDescriptor> adds;
1584
        protected List<ColumnDescriptor> alters;
1585 44198 jjdelcerro
        protected List<Pair<String, String>> renames;
1586 43020 jjdelcerro
1587
        public AlterTableBuilderBase() {
1588
            this.drops = new ArrayList<>();
1589
            this.adds = new ArrayList<>();
1590
            this.alters = new ArrayList<>();
1591
            this.renames = new ArrayList<>();
1592
        }
1593
1594
        @Override
1595 43687 jjdelcerro
        public boolean isEmpty() {
1596 44198 jjdelcerro
            return this.drops.isEmpty()
1597
                    && this.adds.isEmpty()
1598
                    && this.alters.isEmpty()
1599
                    && this.renames.isEmpty();
1600 43687 jjdelcerro
        }
1601 44198 jjdelcerro
1602 43687 jjdelcerro
        @Override
1603 43020 jjdelcerro
        public void accept(Visitor visitor, VisitorFilter filter) {
1604 44198 jjdelcerro
            if (filter.accept(this)) {
1605 43020 jjdelcerro
                visitor.visit(this);
1606
            }
1607 44198 jjdelcerro
            if (this.table != null) {
1608 43020 jjdelcerro
                this.table.accept(visitor, filter);
1609
            }
1610
        }
1611
1612
        @Override
1613
        public TableNameBuilder table() {
1614 44198 jjdelcerro
            if (table == null) {
1615 43114 jjdelcerro
                table = createTableNameBuilder();
1616 43020 jjdelcerro
            }
1617
            return table;
1618
        }
1619
1620
        @Override
1621
        public AlterTableBuilder drop_column(String columnName) {
1622
            this.drops.add(columnName);
1623
            return this;
1624
        }
1625 44198 jjdelcerro
1626 43739 jjdelcerro
        @Override
1627
        public AlterTableBuilder add_column(FeatureAttributeDescriptor fad) {
1628 44198 jjdelcerro
            this.adds.add(new ColumnDescriptorBase(fad));
1629
            return this;
1630 43739 jjdelcerro
        }
1631 43020 jjdelcerro
1632
        @Override
1633 43355 jjdelcerro
        public AlterTableBuilder add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1634 43020 jjdelcerro
            if (isPk || isAutomatic) {
1635
                allowNulls = false;
1636
            }
1637 43739 jjdelcerro
            this.adds.add(new ColumnDescriptorBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
1638 43020 jjdelcerro
            return this;
1639
        }
1640
1641
        @Override
1642 43650 jjdelcerro
        public AlterTableBuilder add_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
1643 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
1644 43650 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1645
            }
1646 43739 jjdelcerro
            this.adds.add(new ColumnDescriptorBase(columnName, type, subtype, proj, isIndexed, allowNulls));
1647 43650 jjdelcerro
            return this;
1648
        }
1649
1650
        @Override
1651 43687 jjdelcerro
        public AlterTableBuilder add_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
1652 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
1653 43687 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1654
            }
1655 43739 jjdelcerro
            this.adds.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
1656 43687 jjdelcerro
            return this;
1657
        }
1658 44198 jjdelcerro
1659 43687 jjdelcerro
        @Override
1660 43739 jjdelcerro
        public AlterTableBuilder alter_column(FeatureAttributeDescriptor fad) {
1661 44198 jjdelcerro
            this.alters.add(new ColumnDescriptorBase(fad));
1662
            return this;
1663 43739 jjdelcerro
        }
1664 44198 jjdelcerro
1665 43739 jjdelcerro
        @Override
1666 43355 jjdelcerro
        public AlterTableBuilder alter_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1667 43020 jjdelcerro
            if (isPk || isAutomatic) {
1668
                allowNulls = false;
1669
            }
1670 43739 jjdelcerro
            this.alters.add(new ColumnDescriptorBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
1671 43020 jjdelcerro
            return this;
1672
        }
1673
1674
        @Override
1675 43650 jjdelcerro
        public AlterTableBuilder alter_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
1676 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
1677 43650 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1678
            }
1679 43739 jjdelcerro
            this.alters.add(new ColumnDescriptorBase(columnName, type, subtype, proj, isIndexed, allowNulls));
1680 43650 jjdelcerro
            return this;
1681
        }
1682
1683
        @Override
1684 43687 jjdelcerro
        public AlterTableBuilder alter_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
1685 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
1686 43687 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1687
            }
1688 43739 jjdelcerro
            this.alters.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
1689 43687 jjdelcerro
            return this;
1690
        }
1691
1692
        @Override
1693 43020 jjdelcerro
        public AlterTableBuilder rename_column(String source, String target) {
1694
            this.renames.add(new ImmutablePair(source, target));
1695
            return this;
1696
        }
1697
1698
        @Override
1699
        public String toString() {
1700 44198 jjdelcerro
            return this.toString(formatter());
1701
        }
1702
1703
        @Override
1704
        public String toString(Formatter<Value> formatter) {
1705
            if (formatter.canApply(this)) {
1706
                return formatter.format(this);
1707
            }
1708 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
1709
            boolean first = true;
1710 44198 jjdelcerro
            for (String sql : toStrings(formatter)) {
1711
                if (StringUtils.isEmpty(sql)) {
1712 43020 jjdelcerro
                    continue;
1713
                }
1714
                if (first) {
1715
                    first = false;
1716
                } else {
1717
                    builder.append("; ");
1718
                }
1719
                builder.append(sql);
1720
            }
1721
            return builder.toString();
1722
        }
1723
1724
        @Override
1725
        public List<String> toStrings() {
1726 44198 jjdelcerro
            return this.toStrings(formatter());
1727
        }
1728
1729
        @Override
1730
        public List<String> toStrings(Formatter formatter) {
1731 43020 jjdelcerro
            List<String> sqls = new ArrayList<>();
1732 44198 jjdelcerro
            if (this.isEmpty()) {
1733 43687 jjdelcerro
                return sqls;
1734
            }
1735 43020 jjdelcerro
            for (String column : drops) {
1736 43650 jjdelcerro
                StringBuilder builder = new StringBuilder();
1737
                builder.append("ALTER TABLE ");
1738 44198 jjdelcerro
                builder.append(this.table.toString(formatter));
1739 43650 jjdelcerro
                builder.append(" DROP COLUMN IF EXISTS ");
1740 44198 jjdelcerro
                builder.append(as_identifier(column));
1741 43650 jjdelcerro
                sqls.add(builder.toString());
1742 43020 jjdelcerro
            }
1743 43739 jjdelcerro
            for (ColumnDescriptor column : adds) {
1744 43650 jjdelcerro
                StringBuilder builder = new StringBuilder();
1745
                builder.append("ALTER TABLE ");
1746 44198 jjdelcerro
                builder.append(this.table.toString(formatter));
1747 43650 jjdelcerro
                builder.append(" ADD COLUMN ");
1748 44198 jjdelcerro
                builder.append(as_identifier(column.getName()));
1749 43020 jjdelcerro
                builder.append(" ");
1750 44198 jjdelcerro
                if (column.getType() == DataTypes.INT && column.isAutomatic()) {
1751 43020 jjdelcerro
                    builder.append(" SERIAL");
1752
                } else {
1753 43687 jjdelcerro
                    builder.append(
1754 44198 jjdelcerro
                            sqltype(
1755
                                    column.getType(),
1756
                                    column.getPrecision(),
1757
                                    column.getSize(),
1758
                                    column.getGeometryType(),
1759
                                    column.getGeometrySubtype()
1760
                            )
1761 43687 jjdelcerro
                    );
1762 43020 jjdelcerro
                }
1763 43114 jjdelcerro
                if (column.getDefaultValue() == null) {
1764
                    if (column.allowNulls()) {
1765 43020 jjdelcerro
                        builder.append(" DEFAULT NULL");
1766
                    }
1767
                } else {
1768
                    builder.append(" DEFAULT '");
1769 43114 jjdelcerro
                    builder.append(column.getDefaultValue().toString());
1770 43020 jjdelcerro
                    builder.append("'");
1771
                }
1772 43114 jjdelcerro
                if (column.allowNulls()) {
1773 43020 jjdelcerro
                    builder.append(" NULL");
1774
                } else {
1775
                    builder.append(" NOT NULL");
1776
                }
1777 43114 jjdelcerro
                if (column.isPrimaryKey()) {
1778 43020 jjdelcerro
                    builder.append(" PRIMARY KEY");
1779
                }
1780 43650 jjdelcerro
                sqls.add(builder.toString());
1781 43020 jjdelcerro
            }
1782 43739 jjdelcerro
            for (ColumnDescriptor column : alters) {
1783 43650 jjdelcerro
                StringBuilder builder = new StringBuilder();
1784
                builder.append("ALTER TABLE ");
1785 44198 jjdelcerro
                builder.append(this.table.toString(formatter));
1786 43650 jjdelcerro
                builder.append(" ALTER COLUMN ");
1787 44198 jjdelcerro
                builder.append(as_identifier(column.getName()));
1788 43650 jjdelcerro
                builder.append(" SET DATA TYPE ");
1789 44198 jjdelcerro
                if (column.getType() == DataTypes.INT && column.isAutomatic()) {
1790 43020 jjdelcerro
                    builder.append(" SERIAL");
1791
                } else {
1792 43687 jjdelcerro
                    builder.append(
1793 44198 jjdelcerro
                            sqltype(
1794
                                    column.getType(),
1795
                                    column.getPrecision(),
1796
                                    column.getSize(),
1797
                                    column.getGeometryType(),
1798
                                    column.getGeometrySubtype()
1799
                            )
1800 43687 jjdelcerro
                    );
1801 43020 jjdelcerro
                }
1802 43114 jjdelcerro
                if (column.getDefaultValue() == null) {
1803
                    if (column.allowNulls()) {
1804 43650 jjdelcerro
                        builder.append(" DEFAULT NULL");
1805 43020 jjdelcerro
                    } else {
1806
                        builder.append(" DROP DEFAULT");
1807
                    }
1808
                } else {
1809 43650 jjdelcerro
                    builder.append(" DEFAULT '");
1810 43114 jjdelcerro
                    builder.append(column.getDefaultValue().toString());
1811 43020 jjdelcerro
                    builder.append("'");
1812
                }
1813 43650 jjdelcerro
                sqls.add(builder.toString());
1814 43020 jjdelcerro
            }
1815 44198 jjdelcerro
            for (Pair<String, String> pair : renames) {
1816 43650 jjdelcerro
                StringBuilder builder = new StringBuilder();
1817
                builder.append("ALTER TABLE ");
1818 44198 jjdelcerro
                builder.append(this.table.toString(formatter));
1819 43650 jjdelcerro
                builder.append(" RENAME COLUMN ");
1820 44198 jjdelcerro
                builder.append(as_identifier(pair.getLeft()));
1821 43020 jjdelcerro
                builder.append(" TO ");
1822 44198 jjdelcerro
                builder.append(as_identifier(pair.getRight()));
1823 43650 jjdelcerro
                sqls.add(builder.toString());
1824 43020 jjdelcerro
            }
1825
            return sqls;
1826
        }
1827
1828
    }
1829
1830 44198 jjdelcerro
    public class CreateTableBuilderBase
1831
            extends AbstractStatement
1832
            implements CreateTableBuilder {
1833 43020 jjdelcerro
1834
        protected TableNameBuilder table;
1835 43739 jjdelcerro
        protected List<ColumnDescriptor> columns;
1836 43020 jjdelcerro
1837
        public CreateTableBuilderBase() {
1838
            this.columns = new ArrayList<>();
1839
        }
1840
1841
        @Override
1842
        public void accept(Visitor visitor, VisitorFilter filter) {
1843 44198 jjdelcerro
            if (filter.accept(this)) {
1844 43020 jjdelcerro
                visitor.visit(this);
1845
            }
1846 44198 jjdelcerro
            if (this.table != null) {
1847 43020 jjdelcerro
                this.table.accept(visitor, filter);
1848
            }
1849
        }
1850
1851
        @Override
1852
        public TableNameBuilder table() {
1853 44198 jjdelcerro
            if (table == null) {
1854 43114 jjdelcerro
                table = createTableNameBuilder();
1855 43020 jjdelcerro
            }
1856
            return table;
1857
        }
1858
1859
        @Override
1860 43739 jjdelcerro
        public CreateTableBuilderBase add_column(FeatureAttributeDescriptor fad) {
1861 44198 jjdelcerro
            this.columns.add(new ColumnDescriptorBase(fad));
1862
            return this;
1863 43739 jjdelcerro
        }
1864
1865
        @Override
1866 43355 jjdelcerro
        public CreateTableBuilderBase add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1867 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
1868 43114 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1869
            }
1870 43020 jjdelcerro
            if (isPk || isAutomatic) {
1871
                allowNulls = false;
1872
            }
1873 43739 jjdelcerro
            this.columns.add(new ColumnDescriptorBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
1874 43020 jjdelcerro
            return this;
1875
        }
1876
1877
        @Override
1878 43355 jjdelcerro
        public CreateTableBuilder add_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
1879 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
1880 43114 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1881
            }
1882 43739 jjdelcerro
            this.columns.add(new ColumnDescriptorBase(columnName, type, subtype, proj, isIndexed, allowNulls));
1883 43114 jjdelcerro
            return this;
1884
        }
1885
1886
        @Override
1887 43687 jjdelcerro
        public CreateTableBuilder add_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
1888 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
1889 43687 jjdelcerro
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1890
            }
1891 43739 jjdelcerro
            this.columns.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
1892 43687 jjdelcerro
            return this;
1893
        }
1894
1895
        @Override
1896 43739 jjdelcerro
        public ColumnDescriptor getColumnDescriptor(String columnName) {
1897 44198 jjdelcerro
            if (StringUtils.isEmpty(columnName)) {
1898 43114 jjdelcerro
                return null;
1899
            }
1900 43739 jjdelcerro
            for (ColumnDescriptor column : columns) {
1901 44198 jjdelcerro
                if (columnName.equals(column.getName())) {
1902 43114 jjdelcerro
                    return column;
1903
                }
1904
            }
1905
            return null;
1906
        }
1907 44198 jjdelcerro
1908 43114 jjdelcerro
        @Override
1909 43020 jjdelcerro
        public String toString() {
1910 44198 jjdelcerro
            return this.toString(formatter());
1911
        }
1912
1913
        @Override
1914
        public String toString(Formatter<Value> formatter) {
1915
            if (formatter.canApply(this)) {
1916
                return formatter.format(this);
1917
            }
1918 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
1919
            boolean first = true;
1920 44198 jjdelcerro
            for (String sql : toStrings(formatter)) {
1921
                if (StringUtils.isEmpty(sql)) {
1922 43020 jjdelcerro
                    continue;
1923
                }
1924
                if (first) {
1925
                    first = false;
1926
                } else {
1927
                    builder.append("; ");
1928
                }
1929
                builder.append(sql);
1930
            }
1931
            return builder.toString();
1932
        }
1933
1934
        @Override
1935
        public List<String> toStrings() {
1936 44198 jjdelcerro
            return this.toStrings(formatter());
1937
        }
1938
1939
        @Override
1940
        public List<String> toStrings(Formatter formatter) {
1941 43020 jjdelcerro
            List<String> sqls = new ArrayList<>();
1942
            /**
1943
             * CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE
1944
             * table_name ( { column_name data_type [ DEFAULT default_expr ] [
1945
             * column_constraint [ ... ] ] | table_constraint | LIKE
1946
             * parent_table [ { INCLUDING | EXCLUDING } DEFAULTS ] } [, ... ] )
1947
             * [ INHERITS ( parent_table [, ... ] ) ] [ WITH OIDS | WITHOUT OIDS
1948
             * ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
1949
             *
1950
             * where column_constraint is:
1951
             *
1952
             * [ CONSTRAINT constraint_name ] { NOT NULL | NULL | UNIQUE |
1953
             * PRIMARY KEY | CHECK (expression) | REFERENCES reftable [ (
1954
             * refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON
1955
             * DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE | NOT
1956
             * DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1957
             *
1958
             * and table_constraint is:
1959
             *
1960
             * [ CONSTRAINT constraint_name ] { UNIQUE ( column_name [, ... ] )
1961
             * | PRIMARY KEY ( column_name [, ... ] ) | CHECK ( expression ) |
1962
             * FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ (
1963
             * refcolumn [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH
1964
             * SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE
1965
             * | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1966
             */
1967
            StringBuilder builder = new StringBuilder();
1968
1969
            builder.append("CREATE TABLE ");
1970 44198 jjdelcerro
            builder.append(this.table.toString(formatter));
1971 43020 jjdelcerro
            builder.append(" (");
1972
            boolean first = true;
1973 43739 jjdelcerro
            for (ColumnDescriptor column : columns) {
1974 43020 jjdelcerro
                if (first) {
1975
                    first = false;
1976
                } else {
1977
                    builder.append(", ");
1978
                }
1979 44198 jjdelcerro
                builder.append(as_identifier(column.getName()));
1980 43020 jjdelcerro
                builder.append(" ");
1981 44198 jjdelcerro
                if (column.isAutomatic() && column.getType() == DataTypes.INT) {
1982 43020 jjdelcerro
                    builder.append("SERIAL");
1983 44198 jjdelcerro
                } else if (column.isAutomatic() && column.getType() == DataTypes.LONG) {
1984 43020 jjdelcerro
                    builder.append("BIGSERIAL");
1985
                } else {
1986 44198 jjdelcerro
                    builder.append(sqltype(
1987
                            column.getType(),
1988
                            column.getPrecision(),
1989
                            column.getSize(),
1990
                            column.getGeometryType(),
1991
                            column.getGeometrySubtype()
1992
                    )
1993
                    );
1994 43020 jjdelcerro
                }
1995 43114 jjdelcerro
                if (column.getDefaultValue() == null) {
1996
                    if (column.allowNulls()) {
1997 43020 jjdelcerro
                        builder.append(" DEFAULT NULL");
1998
                    }
1999
                } else {
2000
                    builder.append(" DEFAULT '");
2001 43114 jjdelcerro
                    builder.append(column.getDefaultValue().toString());
2002 43020 jjdelcerro
                    builder.append("'");
2003
                }
2004 43114 jjdelcerro
                if (column.allowNulls()) {
2005 43020 jjdelcerro
                    builder.append(" NULL");
2006
                } else {
2007
                    builder.append(" NOT NULL");
2008
                }
2009 43114 jjdelcerro
                if (column.isPrimaryKey()) {
2010 43020 jjdelcerro
                    builder.append(" PRIMARY KEY");
2011
                }
2012
            }
2013
            builder.append(" )");
2014
            sqls.add(builder.toString());
2015
            return sqls;
2016
        }
2017
    }
2018
2019 44198 jjdelcerro
    public class InsertColumnBuilderBase
2020
            extends AbstractStatement
2021
            implements InsertColumnBuilder {
2022
2023 43020 jjdelcerro
        protected Variable name;
2024
        protected Value value;
2025 44198 jjdelcerro
2026 43020 jjdelcerro
        public InsertColumnBuilderBase() {
2027
        }
2028
2029
        @Override
2030
        public void accept(Visitor visitor, VisitorFilter filter) {
2031 44198 jjdelcerro
            if (filter.accept(this)) {
2032 43020 jjdelcerro
                visitor.visit(this);
2033
            }
2034 44198 jjdelcerro
            if (this.name != null) {
2035 43020 jjdelcerro
                this.name.accept(visitor, filter);
2036
            }
2037 44198 jjdelcerro
            if (this.value != null) {
2038 43020 jjdelcerro
                this.value.accept(visitor, filter);
2039
            }
2040
        }
2041
2042
        @Override
2043
        public InsertColumnBuilder name(String name) {
2044 44198 jjdelcerro
            this.name = expression().variable(name);
2045 43020 jjdelcerro
            return this;
2046
        }
2047
2048
        @Override
2049
        public InsertColumnBuilder with_value(Value value) {
2050
            this.value = value;
2051
            return this;
2052
        }
2053 44198 jjdelcerro
2054 43020 jjdelcerro
        @Override
2055
        public String getName() {
2056 44198 jjdelcerro
            return this.name.name();
2057 43020 jjdelcerro
        }
2058 44198 jjdelcerro
2059 43020 jjdelcerro
        @Override
2060
        public Value getValue() {
2061
            return this.value;
2062
        }
2063 44198 jjdelcerro
2064 43020 jjdelcerro
        @Override
2065
        public String toString() {
2066 44198 jjdelcerro
            return this.toString(formatter());
2067 43020 jjdelcerro
        }
2068 44198 jjdelcerro
2069
        @Override
2070
        public String toString(Formatter<Value> formatter) {
2071
            if (formatter.canApply(this)) {
2072
                return formatter.format(this);
2073
            }
2074
            return this.value.toString(formatter);
2075
        }
2076 43020 jjdelcerro
    }
2077
2078 44198 jjdelcerro
    public class InsertBuilderBase
2079
            extends AbstractStatement
2080
            implements InsertBuilder {
2081
2082 43020 jjdelcerro
        protected List<InsertColumnBuilder> columns;
2083
        protected TableNameBuilder table;
2084
2085
        public InsertBuilderBase() {
2086
            this.columns = new ArrayList<>();
2087
        }
2088
2089
        @Override
2090
        public void accept(Visitor visitor, VisitorFilter filter) {
2091 44198 jjdelcerro
            if (filter.accept(this)) {
2092 43020 jjdelcerro
                visitor.visit(this);
2093
            }
2094 44198 jjdelcerro
            if (this.table != null) {
2095 43020 jjdelcerro
                this.table.accept(visitor, filter);
2096
            }
2097
            for (InsertColumnBuilder column : columns) {
2098
                column.accept(visitor, filter);
2099
            }
2100
        }
2101
2102
        @Override
2103
        public TableNameBuilder table() {
2104 44198 jjdelcerro
            if (table == null) {
2105 43114 jjdelcerro
                table = createTableNameBuilder();
2106 43020 jjdelcerro
            }
2107
            return table;
2108
        }
2109
2110
        @Override
2111
        public InsertColumnBuilder column() {
2112
            InsertColumnBuilder column = createInsertColumnBuilder();
2113
            this.columns.add(column);
2114
            return column;
2115
        }
2116
2117
        @Override
2118
        public String toString() {
2119 44198 jjdelcerro
            return this.toString(formatter());
2120
        }
2121
2122
        @Override
2123
        public String toString(Formatter<Value> formatter) {
2124
            if (formatter.canApply(this)) {
2125
                return formatter.format(this);
2126
            }
2127 43020 jjdelcerro
            /*
2128
             * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
2129
             * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
2130
             * output_expression [ AS output_name ] [, ...] ]
2131
             */
2132
            StringBuilder builderColumns = new StringBuilder();
2133
            StringBuilder builderValues = new StringBuilder();
2134 44198 jjdelcerro
2135 43020 jjdelcerro
            boolean first = true;
2136
            for (InsertColumnBuilder column : columns) {
2137
                if (first) {
2138
                    first = false;
2139
                } else {
2140
                    builderColumns.append(", ");
2141
                }
2142 44198 jjdelcerro
                builderColumns.append(as_identifier(column.getName()));
2143 43020 jjdelcerro
            }
2144
            first = true;
2145
            for (InsertColumnBuilder column : columns) {
2146
                if (first) {
2147
                    first = false;
2148
                } else {
2149
                    builderValues.append(", ");
2150
                }
2151 44198 jjdelcerro
                builderValues.append(column.toString(formatter));
2152 43020 jjdelcerro
            }
2153 44198 jjdelcerro
2154 43020 jjdelcerro
            String sql = MessageFormat.format(
2155 44198 jjdelcerro
                    STMT_INSERT_INTO_table_columns_VALUES_values,
2156
                    this.table.toString(formatter),
2157 43020 jjdelcerro
                    builderColumns.toString(),
2158
                    builderValues.toString()
2159
            );
2160
            return sql;
2161
2162
        }
2163
    }
2164
2165 44198 jjdelcerro
    public class UpdateTableStatisticsBuilderBase
2166
            extends AbstractStatement
2167
            implements UpdateTableStatisticsBuilder {
2168 43020 jjdelcerro
2169
        protected TableNameBuilder table;
2170
2171
        @Override
2172
        public void accept(Visitor visitor, VisitorFilter filter) {
2173 44198 jjdelcerro
            if (filter.accept(this)) {
2174 43020 jjdelcerro
                visitor.visit(this);
2175
            }
2176 44198 jjdelcerro
            if (this.table != null) {
2177 43020 jjdelcerro
                this.table.accept(visitor, filter);
2178
            }
2179
        }
2180
2181
        @Override
2182
        public TableNameBuilder table() {
2183 44198 jjdelcerro
            if (table == null) {
2184 43114 jjdelcerro
                table = createTableNameBuilder();
2185 43020 jjdelcerro
            }
2186
            return table;
2187
        }
2188
2189
        @Override
2190
        public String toString() {
2191 44198 jjdelcerro
            return this.toString(formatter());
2192
        }
2193
2194
        @Override
2195
        public String toString(Formatter<Value> formatter) {
2196
            if (formatter.canApply(this)) {
2197
                return formatter.format(this);
2198
            }
2199 43020 jjdelcerro
            StringBuilder builder = new StringBuilder();
2200
            boolean first = true;
2201 44198 jjdelcerro
            for (String sql : toStrings(formatter)) {
2202
                if (StringUtils.isEmpty(sql)) {
2203 43020 jjdelcerro
                    continue;
2204
                }
2205
                if (first) {
2206
                    first = false;
2207
                } else {
2208
                    builder.append("; ");
2209
                }
2210
                builder.append(sql);
2211
            }
2212
            return builder.toString();
2213
        }
2214
2215
        @Override
2216
        public List<String> toStrings() {
2217 44198 jjdelcerro
            return this.toStrings(formatter());
2218
        }
2219
2220
        @Override
2221
        public List<String> toStrings(Formatter formatter) {
2222 43020 jjdelcerro
            List<String> sqls = new ArrayList<>();
2223 44198 jjdelcerro
2224
            if (!StringUtils.isBlank(STMT_UPDATE_TABLE_STATISTICS_table)) {
2225 43020 jjdelcerro
                String sql = MessageFormat.format(
2226 44198 jjdelcerro
                        STMT_UPDATE_TABLE_STATISTICS_table,
2227
                        table.toString(formatter)
2228
                );
2229
                if (!StringUtils.isEmpty(sql)) {
2230 43020 jjdelcerro
                    sqls.add(sql);
2231
                }
2232
            }
2233
            return sqls;
2234
        }
2235
    }
2236 44042 jjdelcerro
2237 44198 jjdelcerro
    protected ExpressionBuilder expressionBuilder;
2238 44042 jjdelcerro
2239 44198 jjdelcerro
    protected String defaultSchema;
2240
    protected boolean supportSchemas;
2241
    protected boolean hasSpatialFunctions;
2242
    protected GeometrySupportType geometrySupportType;
2243
    protected boolean allowAutomaticValues;
2244 44042 jjdelcerro
2245 44198 jjdelcerro
    private static Map<Pair<Integer, Integer>, String> sqlgeometrytypes = null;
2246 44042 jjdelcerro
2247 44198 jjdelcerro
    protected String constant_true = "(1=1)";
2248
    protected String constant_false = "(1=1)";
2249 44042 jjdelcerro
2250 44198 jjdelcerro
    protected String type_boolean = "BOOLEAN";
2251
    protected String type_byte = "TINYINT";
2252
    protected String type_bytearray = "BYTEA";
2253
    protected String type_geometry = "TEXT";
2254
    protected String type_char = "CHARACTER(1)";
2255
    protected String type_date = "DATE";
2256
    protected String type_double = "DOUBLE PRECISION"; //float con 53 bits de mantisa, float(54)
2257
    protected String type_numeric_p = "NUMERIC({0})";
2258
    protected String type_numeric_ps = "NUMERIC({0},{1})";
2259
    protected String type_bigdecimal = "NUMERIC({0},{1})";
2260
    protected String type_float = "REAL"; //float con 24 bits de mantisa, float(24)
2261
    protected String type_int = "INT";
2262
    protected String type_long = "BIGINT";
2263
    protected String type_string = "TEXT";
2264
    protected String type_string_p = "VARCHAR({0})";
2265
    protected String type_time = "TIME";
2266
    protected String type_timestamp = "TIMESTAMP";
2267
    protected String type_version = "VARCHAR(30)";
2268
    protected String type_URI = "TEXT";
2269
    protected String type_URL = "TEXT";
2270
    protected String type_FILE = "TEXT";
2271
    protected String type_FOLDER = "TEXT";
2272 44042 jjdelcerro
2273 44198 jjdelcerro
    protected String STMT_DELETE_FROM_table_WHERE_expresion = "DELETE FROM {0} WHERE {1}";
2274
    protected String STMT_DELETE_FROM_table = "DELETE FROM {0}";
2275
    protected String STMT_INSERT_INTO_table_columns_VALUES_values = "INSERT INTO {0} ( {1} ) VALUES ( {2} )";
2276
    protected String STMT_UPDATE_TABLE_STATISTICS_table = "VACUUM ANALYZE {0}";
2277
    protected String STMT_DROP_TABLE_table = "DROP TABLE {0}";
2278
    protected String STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table = "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_schema = {0} AND f_table_name = {1}";
2279
    protected String STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_table = "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_name = {0}";
2280
    protected String STMT_UPDATE_table_SET_columnsAndValues_WHERE_expresion = "UPDATE {0} SET {1} WHERE {2}";
2281
    protected String STMT_UPDATE_table_SET_columnsAndValues = "UPDATE {0} SET {1}";
2282
    protected String STMT_GRANT_privileges_ON_table_TO_role = "GRANT {0} ON {1} TO {2}";
2283 44042 jjdelcerro
2284 43020 jjdelcerro
    public SQLBuilderBase() {
2285 44198 jjdelcerro
        this.expressionBuilder = ExpressionEvaluatorLocator.getManager().createExpressionBuilder();
2286 44042 jjdelcerro
2287 44198 jjdelcerro
        this.hasSpatialFunctions = false;
2288
        this.supportSchemas = true;
2289
        this.geometrySupportType = GeometrySupportType.WKT;
2290 44042 jjdelcerro
2291 44198 jjdelcerro
        this.defaultSchema = "public";
2292
        this.allowAutomaticValues = true;
2293 44042 jjdelcerro
2294 43020 jjdelcerro
    }
2295 44198 jjdelcerro
2296 44042 jjdelcerro
    @Override
2297 44198 jjdelcerro
    public void setProperties(Class filter, final Object... values) {
2298
        this.accept(new Visitor() {
2299
            @Override
2300
            public void visit(Visitable v) {
2301
                for (int i = 0; i < values.length; i+=2) {
2302
                    ((Value)v).setProperty((String) values[i], values[i+1]);
2303
                }
2304
            }
2305
        }, new ClassVisitorFilter(filter) );
2306 44042 jjdelcerro
    }
2307
2308 44198 jjdelcerro
    public String quote_for_identifiers() {
2309
        return "\"";
2310 44042 jjdelcerro
    }
2311
2312 44198 jjdelcerro
    public String quote_for_strings() {
2313
        return "'";
2314 44042 jjdelcerro
    }
2315
2316
    @Override
2317 44198 jjdelcerro
    public String as_identifier(String id) {
2318
        String quote = this.quote_for_identifiers();
2319
//        No se porque no esta disponible wrapIfMissing
2320
//        return StringUtils.wrapIfMissing(id,quote);
2321
        if (id.startsWith(quote)) {
2322
            return id;
2323
        }
2324
        return quote + id + quote;
2325 44042 jjdelcerro
2326
    }
2327
2328
    @Override
2329 44198 jjdelcerro
    public String as_string(String s) {
2330
        String quote = this.quote_for_strings();
2331 44042 jjdelcerro
//        No se porque no esta disponible wrapIfMissing
2332 44198 jjdelcerro
//        return StringUtils.wrapIfMissing(id,quote);
2333 44042 jjdelcerro
        if (s.startsWith(quote)) {
2334
            return s;
2335
        }
2336
        return quote + s + quote;
2337
2338
    }
2339
2340
    @Override
2341 44198 jjdelcerro
    public String as_string(byte[] data) {
2342
        return this.expressionBuilder.bytearray_0x(data);
2343
//        return this.expressionBuilder.bytearray_hex(data);
2344
//        return this.expressionBuilder.bytearray_x(data);
2345 44042 jjdelcerro
    }
2346 43020 jjdelcerro
2347
    @Override
2348 44198 jjdelcerro
    public String as_string(boolean value) {
2349
        return value? "TRUE" : "FALSE";
2350 44042 jjdelcerro
    }
2351
2352
    @Override
2353 44198 jjdelcerro
    public String as_string(Number value) {
2354
        return Objects.toString(value);
2355 44042 jjdelcerro
    }
2356
2357
    @Override
2358 44198 jjdelcerro
    public String as_string(Object value) {
2359
        if( value == null ) {
2360
            return "NULL";
2361 44042 jjdelcerro
        }
2362 44198 jjdelcerro
        if( value instanceof CharSequence ) {
2363
            return as_string(value.toString());
2364 44042 jjdelcerro
        }
2365 44198 jjdelcerro
        if( value instanceof Number ) {
2366
            return as_string((Number)value);
2367 44042 jjdelcerro
        }
2368 44198 jjdelcerro
        if( value instanceof Boolean ) {
2369
            return as_string((boolean)value);
2370 44042 jjdelcerro
        }
2371 44198 jjdelcerro
        if( value instanceof byte[] ) {
2372
            return as_string((byte[])value);
2373 44042 jjdelcerro
        }
2374 44198 jjdelcerro
        throw new IllegalArgumentException("Can't support type of value '"+value.getClass().getName()+"'.");
2375 44042 jjdelcerro
    }
2376 44198 jjdelcerro
2377 44042 jjdelcerro
    @Override
2378 44198 jjdelcerro
    public ExpressionBuilder expression() {
2379
        return this.expressionBuilder;
2380 44042 jjdelcerro
    }
2381
2382
    @Override
2383 44198 jjdelcerro
    public boolean has_spatial_functions() {
2384
        return this.hasSpatialFunctions;
2385 44042 jjdelcerro
    }
2386
2387
    @Override
2388 44198 jjdelcerro
    public GeometrySupportType geometry_support_type() {
2389
        return this.geometrySupportType;
2390 44042 jjdelcerro
    }
2391
2392 44198 jjdelcerro
    protected ExpressionBuilder createExpressionBuilder() {
2393
        return ExpressionEvaluatorLocator.getManager().createExpressionBuilder();
2394 44042 jjdelcerro
    }
2395
2396
    @Override
2397 44198 jjdelcerro
    public Object srs_id(IProjection projection) {
2398
        String abrev = projection.getAbrev();
2399
        return abrev.split(":")[1].trim();
2400 44042 jjdelcerro
    }
2401
2402
    @Override
2403 43020 jjdelcerro
    public String default_schema() {
2404 44198 jjdelcerro
        return this.defaultSchema;
2405 43020 jjdelcerro
    }
2406 43355 jjdelcerro
2407
    @Override
2408 44198 jjdelcerro
    public boolean support_schemas() {
2409
        return this.supportSchemas;
2410 43355 jjdelcerro
    }
2411 43650 jjdelcerro
2412
    @Override
2413
    public String sqltype(int type, int p, int s, int geomType, int geomSubtype) {
2414 43020 jjdelcerro
        switch (type) {
2415
            case DataTypes.BOOLEAN:
2416 44198 jjdelcerro
                return type_boolean;
2417 43020 jjdelcerro
            case DataTypes.BYTE:
2418 44198 jjdelcerro
                return type_byte;
2419 43020 jjdelcerro
            case DataTypes.BYTEARRAY:
2420 44198 jjdelcerro
                return type_bytearray;
2421 43020 jjdelcerro
            case DataTypes.GEOMETRY:
2422 44198 jjdelcerro
                return type_geometry;
2423 43020 jjdelcerro
            case DataTypes.CHAR:
2424 44198 jjdelcerro
                return type_char;
2425 43020 jjdelcerro
            case DataTypes.DATE:
2426 44198 jjdelcerro
                return type_date;
2427 43020 jjdelcerro
            case DataTypes.DOUBLE:
2428 44198 jjdelcerro
                // FIXME: Si cargamos la capa "country" al exportarla a
2429
                // SQLServer falla por:
2430
                //  Error de desbordamiento aritm?tico al convertir float al tipo de datos numeric.
2431
                // Al parecer la capa declara la columna sqkm_ctry como Numeric(12,6) y para
2432
                // Algeria intenta asignarle un valor de 2320972.0 y falla.
2433
                // Habria que repasar el proveedor de shape.
2434
2435 43020 jjdelcerro
//                if (p > 1) {
2436
//                    if (s < 0) {
2437
//                        return MessageFormat.format(config.getString(SQLConfig.type_numeric_p), p);
2438
//                    }
2439
//                    return MessageFormat.format(config.getString(SQLConfig.type_numeric_ps), p,s);
2440
//                }
2441 44198 jjdelcerro
                return MessageFormat.format(type_double, p, s);
2442 43020 jjdelcerro
            case DataTypes.BIGDECIMAL:
2443
                if (p < 1) {
2444
                    p = 20;
2445
                }
2446
                if (s < 0) {
2447
                    s = 10;
2448
                }
2449 44198 jjdelcerro
                return MessageFormat.format(type_bigdecimal, p, s);
2450 43020 jjdelcerro
            case DataTypes.FLOAT:
2451 44198 jjdelcerro
                return MessageFormat.format(type_float, p, s);
2452 43020 jjdelcerro
            case DataTypes.INT:
2453 44198 jjdelcerro
                return MessageFormat.format(type_int, p, s);
2454 43020 jjdelcerro
            case DataTypes.LONG:
2455 44198 jjdelcerro
                return MessageFormat.format(type_long, p, s);
2456 43020 jjdelcerro
            case DataTypes.STRING:
2457
                if (p < 0) {
2458 44198 jjdelcerro
                    return type_string;
2459 43020 jjdelcerro
                } else if (p < 4096) {
2460 44198 jjdelcerro
                    return MessageFormat.format(type_string_p, p);
2461 43020 jjdelcerro
                }
2462 44198 jjdelcerro
                return type_string;
2463 43020 jjdelcerro
            case DataTypes.TIME:
2464 44198 jjdelcerro
                return type_time;
2465 43020 jjdelcerro
            case DataTypes.TIMESTAMP:
2466 44198 jjdelcerro
                return type_timestamp;
2467 43020 jjdelcerro
            case DataTypes.VERSION:
2468 44198 jjdelcerro
                return type_version;
2469 43020 jjdelcerro
            case DataTypes.URI:
2470 44198 jjdelcerro
                return type_URI;
2471 43020 jjdelcerro
            case DataTypes.URL:
2472 44198 jjdelcerro
                return type_URL;
2473 43020 jjdelcerro
            case DataTypes.FILE:
2474 44198 jjdelcerro
                return type_FILE;
2475 43020 jjdelcerro
            case DataTypes.FOLDER:
2476 44198 jjdelcerro
                return type_FOLDER;
2477 43020 jjdelcerro
            default:
2478
                return null;
2479
        }
2480
    }
2481
2482 43114 jjdelcerro
    @Override
2483
    public Object sqlgeometrytype(int type, int subtype) {
2484
        // Devuelve un Object por que algunos gestores de BBDD utilizan
2485
        // identificadores numericos para el tipo y otros strings.
2486
        // Por defecto vamos a devolver strings.
2487 44198 jjdelcerro
        if (sqlgeometrytypes == null) {
2488 43114 jjdelcerro
            sqlgeometrytypes = new HashMap<>();
2489 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2D), "POINT");
2490
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM3D), "POINTZ");
2491
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM), "POINTM");
2492
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM3DM), "POINTZM");
2493 43114 jjdelcerro
2494 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2D), "LINESTRING");
2495
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM3D), "LINESTRINGZ");
2496
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM), "LINESTRINGM");
2497
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM3DM), "LINESTRINGZM");
2498 43114 jjdelcerro
2499 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POLYGON, Geometry.SUBTYPES.GEOM2D), "POLYGON");
2500
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POLYGON, Geometry.SUBTYPES.GEOM3D), "POLYGONZ");
2501
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POLYGON, Geometry.SUBTYPES.GEOM2DM), "POLYGONM");
2502
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.POLYGON, Geometry.SUBTYPES.GEOM3DM), "POLYGONZM");
2503 43114 jjdelcerro
2504 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOINT, Geometry.SUBTYPES.GEOM2D), "MULTIPOINT");
2505
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOINT, Geometry.SUBTYPES.GEOM3D), "MULTIPOINTZ");
2506
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOINT, Geometry.SUBTYPES.GEOM2DM), "MULTIPOINTM");
2507
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOINT, Geometry.SUBTYPES.GEOM3DM), "MULTIPOINTZM");
2508 43114 jjdelcerro
2509 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM2D), "MULTILINESTRING");
2510
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM3D), "MULTILINESTRINGZ");
2511
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM2DM), "MULTILINESTRINGM");
2512
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM3DM), "MULTILINESTRINGZM");
2513 43114 jjdelcerro
2514 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTICURVE, Geometry.SUBTYPES.GEOM2D), "MULTILINESTRING");
2515
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTICURVE, Geometry.SUBTYPES.GEOM3D), "MULTILINESTRINGZ");
2516
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTICURVE, Geometry.SUBTYPES.GEOM2DM), "MULTILINESTRINGM");
2517
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTICURVE, Geometry.SUBTYPES.GEOM3DM), "MULTILINESTRINGZM");
2518 43355 jjdelcerro
2519 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON, Geometry.SUBTYPES.GEOM2D), "MULTIPOLYGON");
2520
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON, Geometry.SUBTYPES.GEOM3D), "MULTIPOLYGONZ");
2521
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON, Geometry.SUBTYPES.GEOM2DM), "MULTIPOLYGONM");
2522
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON, Geometry.SUBTYPES.GEOM3DM), "MULTIPOLYGONZM");
2523 43114 jjdelcerro
2524 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTISURFACE, Geometry.SUBTYPES.GEOM2D), "MULTIPOLYGON");
2525
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTISURFACE, Geometry.SUBTYPES.GEOM3D), "MULTIPOLYGONZ");
2526
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTISURFACE, Geometry.SUBTYPES.GEOM2DM), "MULTIPOLYGONM");
2527
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.MULTISURFACE, Geometry.SUBTYPES.GEOM3DM), "MULTIPOLYGONZM");
2528 43355 jjdelcerro
2529 44198 jjdelcerro
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2D), "GEOMETRY");
2530
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM3D), "GEOMETRYZ");
2531
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2DM), "GEOMETRYM");
2532
            sqlgeometrytypes.put(new ImmutablePair<>(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM3DM), "GEOMETRYZM");
2533 43114 jjdelcerro
        }
2534 44198 jjdelcerro
        return sqlgeometrytypes.get(new ImmutablePair<>(type, subtype));
2535 43114 jjdelcerro
    }
2536
2537
    @Override
2538
    public Object sqlgeometrydimension(int type, int subtype) {
2539
        // Devuelve un Object por que algunos gestortes de BBDD utilizan
2540
        // identificadores numericos para las dimensiones y otros strings.
2541
        // Por defecto vamos a devolver enteros.
2542 44198 jjdelcerro
        switch (subtype) {
2543 43114 jjdelcerro
            case Geometry.SUBTYPES.GEOM3D:
2544
                return 3;
2545
            case Geometry.SUBTYPES.GEOM2DM:
2546
                return 3;
2547
            case Geometry.SUBTYPES.GEOM3DM:
2548
                return 4;
2549
            case Geometry.SUBTYPES.GEOM2D:
2550
            default:
2551
                return 2;
2552
        }
2553
    }
2554 44198 jjdelcerro
2555 43114 jjdelcerro
    protected TableNameBuilder createTableNameBuilder() {
2556
        return new TableNameBuilderBase();
2557
    }
2558 44198 jjdelcerro
2559 43020 jjdelcerro
    protected SelectColumnBuilder createSelectColumnBuilder() {
2560
        return new SelectColumnBuilderBase();
2561
    }
2562 44198 jjdelcerro
2563 43020 jjdelcerro
    protected UpdateColumnBuilder createUpdateColumnBuilder() {
2564
        return new UpdateColumnBuilderBase();
2565
    }
2566 44198 jjdelcerro
2567 43020 jjdelcerro
    protected InsertColumnBuilder createInsertColumnBuilder() {
2568
        return new InsertColumnBuilderBase();
2569
    }
2570 44198 jjdelcerro
2571 43020 jjdelcerro
    protected OrderByBuilder createOrderByBuilder() {
2572
        return new OrderByBuilderBase();
2573
    }
2574
2575
    protected FromBuilder createFromBuilder() {
2576
        return new FromBuilderBase();
2577
    }
2578
2579
    protected SelectBuilder createSelectBuilder() {
2580
        return new SelectBuilderBase();
2581
    }
2582
2583
    protected UpdateBuilder createUpdateBuilder() {
2584
        return new UpdateBuilderBase();
2585
    }
2586
2587
    protected DeleteBuilder createDeleteBuilder() {
2588
        return new DeleteBuilderBase();
2589
    }
2590
2591
    protected GrantBuilder createGrantBuilder() {
2592
        return new GrantBuilderBase();
2593
    }
2594
2595
    protected GrantRoleBuilder createGrantRoleBuilder(TableNameBuilder table, String role) {
2596
        return new GrantRoleBuilderBase(table, role);
2597
    }
2598 44198 jjdelcerro
2599 43020 jjdelcerro
    protected DropTableBuilder createDropTableBuilder() {
2600
        return new DropTableBuilderBase();
2601
    }
2602
2603
    protected CreateTableBuilder createCreateTableBuilder() {
2604
        return new CreateTableBuilderBase();
2605
    }
2606
2607
    protected AlterTableBuilder createAlterTableBuilder() {
2608
        return new AlterTableBuilderBase();
2609
    }
2610
2611
    protected InsertBuilder createInsertBuilder() {
2612
        return new InsertBuilderBase();
2613
    }
2614
2615
    protected UpdateTableStatisticsBuilder createUpdateTableStatisticsBuilder() {
2616
        return new UpdateTableStatisticsBuilderBase();
2617
    }
2618
2619 43687 jjdelcerro
    protected CreateIndexBuilder createCreateIndexBuilder() {
2620
        return new CreateIndexBuilderBase();
2621
    }
2622 44198 jjdelcerro
2623 43020 jjdelcerro
    @Override
2624
    public SelectBuilder select() {
2625
        if (this.select == null) {
2626
            this.select = this.createSelectBuilder();
2627
        }
2628
        return this.select;
2629
    }
2630
2631
    @Override
2632
    public UpdateBuilder update() {
2633
        if (this.update == null) {
2634
            this.update = this.createUpdateBuilder();
2635
        }
2636
        return this.update;
2637
    }
2638
2639
    @Override
2640
    public UpdateTableStatisticsBuilder update_table_statistics() {
2641
        if (this.update_table_statistics == null) {
2642
            this.update_table_statistics = this.createUpdateTableStatisticsBuilder();
2643
        }
2644
        return this.update_table_statistics;
2645
    }
2646
2647
    @Override
2648
    public DropTableBuilder drop_table() {
2649
        if (this.drop_table == null) {
2650
            this.drop_table = this.createDropTableBuilder();
2651
        }
2652
        return this.drop_table;
2653
    }
2654
2655
    @Override
2656 43687 jjdelcerro
    public CreateIndexBuilder create_index() {
2657
        if (this.create_index == null) {
2658
            this.create_index = this.createCreateIndexBuilder();
2659
        }
2660
        return this.create_index;
2661
    }
2662
2663
    @Override
2664 43020 jjdelcerro
    public DeleteBuilder delete() {
2665
        if (this.delete == null) {
2666
            this.delete = this.createDeleteBuilder();
2667
        }
2668
        return this.delete;
2669
    }
2670
2671
    @Override
2672
    public InsertBuilder insert() {
2673
        if (this.insert == null) {
2674
            this.insert = this.createInsertBuilder();
2675
        }
2676
        return this.insert;
2677
    }
2678
2679
    @Override
2680
    public AlterTableBuilder alter_table() {
2681
        if (this.alter_table == null) {
2682
            this.alter_table = this.createAlterTableBuilder();
2683
        }
2684
        return this.alter_table;
2685
    }
2686
2687
    @Override
2688
    public CreateTableBuilder create_table() {
2689
        if (this.create_table == null) {
2690
            this.create_table = this.createCreateTableBuilder();
2691
        }
2692
        return this.create_table;
2693
    }
2694
2695
    @Override
2696
    public GrantBuilder grant() {
2697
        if (this.grant == null) {
2698
            this.grant = this.createGrantBuilder();
2699
        }
2700
        return this.grant;
2701
    }
2702
2703
    public void accept(Visitor visitor, VisitorFilter filter) {
2704
        if (this.select != null) {
2705
            this.select.accept(visitor, filter);
2706
        }
2707
        if (this.update != null) {
2708
            this.update.accept(visitor, filter);
2709
        }
2710
        if (this.insert != null) {
2711
            this.insert.accept(visitor, filter);
2712
        }
2713
        if (this.delete != null) {
2714
            this.delete.accept(visitor, filter);
2715
        }
2716
        if (this.alter_table != null) {
2717
            this.alter_table.accept(visitor, filter);
2718
        }
2719
        if (this.create_table != null) {
2720
            this.create_table.accept(visitor, filter);
2721
        }
2722
        if (this.drop_table != null) {
2723
            this.drop_table.accept(visitor, filter);
2724
        }
2725
    }
2726
2727 44198 jjdelcerro
    protected Formatter formatter() {
2728
        return ExpressionBuilder.EMPTY_FORMATTER;
2729
    }
2730
2731 43020 jjdelcerro
    @Override
2732
    public String toString() {
2733 44198 jjdelcerro
        return this.toString(formatter());
2734
    }
2735
2736
    @Override
2737
    public String toString(Formatter formatter) {
2738 43020 jjdelcerro
        if (this.select != null) {
2739 44198 jjdelcerro
            return this.select.toString(formatter);
2740 43020 jjdelcerro
        }
2741
        if (this.update != null) {
2742 44198 jjdelcerro
            return this.update.toString(formatter);
2743 43020 jjdelcerro
        }
2744
        if (this.insert != null) {
2745 44198 jjdelcerro
            return this.insert.toString(formatter);
2746 43020 jjdelcerro
        }
2747
        if (this.delete != null) {
2748 44198 jjdelcerro
            return this.delete.toString(formatter);
2749 43020 jjdelcerro
        }
2750
        if (this.alter_table != null) {
2751 44198 jjdelcerro
            return this.alter_table.toString(formatter);
2752 43020 jjdelcerro
        }
2753
        if (this.create_table != null) {
2754 44198 jjdelcerro
            return this.create_table.toString(formatter);
2755 43020 jjdelcerro
        }
2756
        if (this.drop_table != null) {
2757 44198 jjdelcerro
            return this.drop_table.toString(formatter);
2758 43020 jjdelcerro
        }
2759
        if (this.update_table_statistics != null) {
2760 44198 jjdelcerro
            return this.update_table_statistics.toString(formatter);
2761 43020 jjdelcerro
        }
2762 44198 jjdelcerro
        return "";
2763 43020 jjdelcerro
    }
2764
2765
    @Override
2766 44198 jjdelcerro
    public CountBuilder count() {
2767
        return new CountBuilderBase();
2768 43020 jjdelcerro
    }
2769
2770
    @Override
2771 44198 jjdelcerro
    public List<Parameter> parameters() {
2772
        final List<Parameter> params = new ArrayList<>();
2773
        this.accept(new Visitor() {
2774
            @Override
2775
            public void visit(Visitable value) {
2776
                params.add((Parameter) value);
2777
            }
2778
        }, new ClassVisitorFilter(Parameter.class));
2779
        return params;
2780 43020 jjdelcerro
    }
2781
2782
    @Override
2783 44198 jjdelcerro
    public List<Variable> variables() {
2784
        final List<Variable> vars = new ArrayList<>();
2785
        this.accept(new Visitor() {
2786
            @Override
2787
            public void visit(Visitable value) {
2788
                if (!vars.contains((Variable) value)) {
2789
                    vars.add((Variable) value);
2790
                }
2791
            }
2792
        }, new ClassVisitorFilter(Variable.class));
2793
        return vars;
2794 43020 jjdelcerro
    }
2795
2796 44042 jjdelcerro
    @Override
2797 44198 jjdelcerro
    public List<String> parameters_names() {
2798
        List<String> params = new ArrayList<>();
2799
        for (Parameter param : parameters()) {
2800
            String s;
2801
            switch (param.type()) {
2802
                case Constant:
2803
                    Object theValue = param.value();
2804
                    if (theValue == null) {
2805
                        s = "null";
2806
                    } else if (theValue instanceof String) {
2807
                        s = "'" + (String) theValue + "'";
2808
                    } else {
2809
                        s = theValue.toString();
2810
                    }
2811
                    break;
2812
                case Geometry:
2813
                case Variable:
2814
                default:
2815
                    s = "\"" + param.name() + "\"";
2816
            }
2817
            params.add(s);
2818 44042 jjdelcerro
        }
2819 44198 jjdelcerro
        return params;
2820 44042 jjdelcerro
    }
2821
2822 44051 omartinez
    @Override
2823 44198 jjdelcerro
    public List<String> variables_names() {
2824
        List<String> vars = new ArrayList<>();
2825
        for (Variable var : this.variables()) {
2826
            vars.add(var.name());
2827
        }
2828
        Collections.sort(vars);
2829
        return vars;
2830 44051 omartinez
    }
2831 43020 jjdelcerro
}