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

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