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

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