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

History | View | Annotate | Download (72.5 KB)

1
package org.gvsig.fmap.dal.feature.spi;
2

    
3
import java.text.MessageFormat;
4
import java.util.ArrayList;
5
import java.util.HashMap;
6
import java.util.HashSet;
7
import java.util.List;
8
import java.util.Map;
9
import java.util.Set;
10
import org.apache.commons.lang3.StringUtils;
11
import org.apache.commons.lang3.tuple.ImmutablePair;
12
import org.apache.commons.lang3.tuple.Pair;
13
import org.cresques.cts.IProjection;
14
import org.gvsig.fmap.dal.DataTypes;
15
import org.gvsig.fmap.dal.ExpressionBuilder;
16
import org.gvsig.fmap.dal.SQLBuilder;
17
import org.gvsig.fmap.dal.SQLBuilder.AlterTableBuilder;
18
import org.gvsig.fmap.dal.SQLBuilder.CreateTableBuilder;
19
import org.gvsig.fmap.dal.SQLBuilder.DeleteBuilder;
20
import org.gvsig.fmap.dal.SQLBuilder.DropTableBuilder;
21
import org.gvsig.fmap.dal.SQLBuilder.FromBuilder;
22
import org.gvsig.fmap.dal.SQLBuilder.GrantBuilder;
23
import org.gvsig.fmap.dal.SQLBuilder.InsertBuilder;
24
import org.gvsig.fmap.dal.SQLBuilder.InsertColumnBuilder;
25
import org.gvsig.fmap.dal.SQLBuilder.OrderByBuilder;
26
import org.gvsig.fmap.dal.SQLBuilder.Privilege;
27
import org.gvsig.fmap.dal.SQLBuilder.SQLConfig;
28
import org.gvsig.fmap.dal.SQLBuilder.SelectBuilder;
29
import org.gvsig.fmap.dal.SQLBuilder.SelectColumnBuilder;
30
import org.gvsig.fmap.dal.SQLBuilder.TableNameBuilder;
31
import org.gvsig.fmap.dal.SQLBuilder.UpdateBuilder;
32
import org.gvsig.fmap.dal.SQLBuilder.UpdateColumnBuilder;
33
import org.gvsig.fmap.dal.SQLBuilder.UpdateTableStatisticsBuilder;
34
import org.gvsig.fmap.geom.Geometry;
35
import org.gvsig.fmap.geom.GeometryLocator;
36
import org.gvsig.fmap.geom.GeometryManager;
37
import org.gvsig.fmap.geom.type.GeometryType;
38
import org.slf4j.Logger;
39
import org.slf4j.LoggerFactory;
40

    
41
public class SQLBuilderBase extends ExpressionEvaluatorBase implements SQLBuilder {
42
    
43
    protected static final Logger logger = LoggerFactory.getLogger(SQLBuilderBase.class);
44
    
45
    protected SelectBuilder select;
46
    protected UpdateBuilder update;
47
    protected InsertBuilder insert;
48
    protected DeleteBuilder delete;
49
    protected AlterTableBuilder alter_table;
50
    protected CreateTableBuilder create_table;
51
    protected GrantBuilder grant;
52
    protected DropTableBuilder drop_table;
53
    protected UpdateTableStatisticsBuilder update_table_statistics;
54
    protected List<Parameter> parameters;
55

    
56
    protected class ColumnDescriptorBuilderBase implements ColumnDescriptorBuilder {
57

    
58
        private String name;
59
        private int type;
60
        private int type_p;
61
        private int type_s;
62
        private boolean isPk;
63
        private boolean _allowNulls;
64
        private boolean _isAutomatic;
65
        private Object defaultValue;
66
        private int geom_type;
67
        private int geom_subtype;
68
        private int geom_srsid;
69

    
70
        public ColumnDescriptorBuilderBase(String name, int type, Object defaultValue) {
71
            this.name = name;
72
            this.type = type;
73
            this.type_p = -1;
74
            this.type_s = -1;
75
            this.isPk = false;
76
            this._allowNulls = true;
77
            this._isAutomatic = false;
78
            this.defaultValue = defaultValue;
79
            this.geom_type = Geometry.TYPES.GEOMETRY;
80
            this.geom_subtype = Geometry.SUBTYPES.GEOM2D;
81
            this.geom_srsid = -1;
82
        }
83

    
84
        public ColumnDescriptorBuilderBase(String name, int type, int type_p, int type_s, boolean isPk, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
85
            this.name = name;
86
            this.type = type;
87
            this.type_p = type_p;
88
            this.type_s = type_s;
89
            this.isPk = isPk;
90
            this._allowNulls = allowNulls;
91
            this._isAutomatic = isAutomatic;
92
            this.defaultValue = defaultValue;
93
            this.geom_type = Geometry.TYPES.GEOMETRY;
94
            this.geom_subtype = Geometry.SUBTYPES.GEOM2D;
95
            this.geom_srsid = -1;
96
        }
97
        
98
        public ColumnDescriptorBuilderBase(String name, int geom_type, int geom_subtype, IProjection proj, boolean allowNulls) {
99
            this.name = name;
100
            this.type_p = 0;
101
            this.type_s = 0;
102
            this.isPk = false;
103
            this._allowNulls = allowNulls;
104
            this._isAutomatic = false;
105
            this.defaultValue = null;
106
            this.geom_type = geom_type;
107
            this.geom_subtype = geom_subtype;
108
            this.geom_srsid = getSRSId(proj);
109
        }
110
        
111
        @Override
112
        public String getName() {
113
            return this.name;
114
        }
115
        
116
        @Override
117
        public void setName(String name) {
118
            this.name = name;
119
        }
120

    
121
        @Override
122
        public int getType() {
123
            return this.type;
124
        }
125

    
126
        @Override
127
        public void setType(int type) {
128
            this.type = type;
129
        }
130

    
131
        @Override
132
        public int getPrecision() {
133
            return type_p;
134
        }
135

    
136
        @Override
137
        public void setPrecision(int precision) {
138
            this.type_p = precision;
139
        }
140

    
141
        @Override
142
        public int getSize() {
143
            return type_s;
144
        }
145

    
146
        @Override
147
        public void setSize(int size) {
148
            this.type_s = size;
149
        }
150

    
151
        @Override
152
        public boolean isPrimaryKey() {
153
            return isPk;
154
        }
155

    
156
        @Override
157
        public void setIsPrimaryKey(boolean isPk) {
158
            this.isPk = isPk;
159
        }
160

    
161
        @Override
162
        public boolean allowNulls() {
163
            return _allowNulls;
164
        }
165

    
166
        @Override
167
        public void setAllowNulls(boolean allowNulls) {
168
            this._allowNulls = allowNulls;
169
        }
170

    
171
        @Override
172
        public boolean isAutomatic() {
173
            return _isAutomatic;
174
        }
175

    
176
        @Override
177
        public void setIsAutomatic(boolean isAutomatic) {
178
            this._isAutomatic = isAutomatic;
179
        }
180

    
181
        @Override
182
        public Object getDefaultValue() {
183
            return defaultValue;
184
        }
185

    
186
        @Override
187
        public void setDefaultValue(Object defaultValue) {
188
            this.defaultValue = defaultValue;
189
        }
190

    
191
        @Override
192
        public int getGeometryType() {
193
            return geom_type;
194
        }
195

    
196
        @Override
197
        public void setGeometryType(int geom_type) {
198
            this.geom_type = geom_type;
199
        }
200

    
201
        @Override
202
        public int getGeometrySubtype() {
203
            return geom_subtype;
204
        }
205

    
206
        @Override
207
        public void setGeometrySubtype(int geom_subtype) {
208
            this.geom_subtype = geom_subtype;
209
        }
210

    
211
        @Override
212
        public int getGeometrySRSId() {
213
            return geom_srsid;
214
        }
215

    
216
        @Override
217
        public void setGeometrySRSId(int geom_srsid) {
218
            this.geom_srsid = geom_srsid;
219
        }        
220

    
221
        @Override
222
        public boolean isGeometry() {
223
            return this.type == DataTypes.GEOMETRY;
224
        }
225
                
226
    }
227
    
228

    
229
    public class TableNameBuilderBase implements TableNameBuilder {
230

    
231
        public String tableName;
232
        public String schemaName;
233
        private String databaseName;
234

    
235
        public TableNameBuilderBase() {
236
        }
237

    
238
        @Override
239
        public void accept(Visitor visitor, VisitorFilter filter) {
240
            if( filter.accept(this) ) {
241
                visitor.visit(this);
242
            }
243
        }
244

    
245
        @Override
246
        public TableNameBuilder database(String name) {
247
            this.databaseName = name;
248
            return this;
249
        }
250

    
251
        @Override
252
        public TableNameBuilder schema(String name) {
253
            this.schemaName = name;
254
            return this;
255
        }
256

    
257
        @Override
258
        public TableNameBuilder name(String name) {
259
            this.tableName = name;
260
            return this;
261
        }
262

    
263
        @Override
264
        public String getDatabase() {
265
            return this.databaseName;
266
        }
267

    
268
        @Override
269
        public String getSchema() {
270
            return this.schemaName;
271
        }
272

    
273
        @Override
274
        public String getName() {
275
            return this.tableName;
276
        }
277
        
278
        @Override
279
        public boolean has_schema() {
280
            return !StringUtils.isEmpty(this.schemaName);
281
        }
282

    
283
        @Override
284
        public boolean has_database() {
285
            return !StringUtils.isEmpty(this.databaseName);
286
        }
287
        
288
        @Override
289
        public String toString() {
290
            if( this.has_database()) {
291
                if( this.has_schema()) {
292
                    return identifier(this.databaseName) + "." + 
293
                           identifier(this.schemaName) + "." + 
294
                           identifier(this.tableName);
295
                }
296
            } else {
297
                if( this.has_schema()) {
298
                    return identifier(this.schemaName) + "." + 
299
                           identifier(this.tableName);
300
                }                
301
            }
302
            return identifier(this.tableName);
303
        }
304

    
305
    }
306

    
307
    public class CountBuilderBase extends AbstractValue implements CountBuilder {
308

    
309
        protected Value value;
310
        protected boolean distinct;
311
        protected boolean all ;
312
        
313
        public CountBuilderBase() {
314
            this.value = null;
315
            this.distinct = false;
316
            this.all = false;
317
        }
318
        
319
        @Override
320
        public CountBuilder all() {
321
            this.all = true;
322
            return this;
323
        }
324

    
325
        @Override
326
        public CountBuilder column(Value value) {
327
            this.value = value;
328
            return this;
329
        }
330

    
331
        @Override
332
        public CountBuilder distinct() {
333
            this.distinct = true;
334
            return this;
335
        }
336

    
337
        @Override
338
        public String toString() {
339
            if( this.all ) {
340
                return MessageFormat.format(
341
                    config.getString(SQLConfig.count),
342
                    "*"
343
                );
344
            }
345
            if( this.distinct ) {
346
                return MessageFormat.format(
347
                    config.getString(SQLConfig.count_distinct),
348
                    value.toString()
349
                );
350
            }
351
            return MessageFormat.format(
352
                config.getString(SQLConfig.count),
353
                value.toString()
354
            );
355
        }
356
        
357
        
358
    }
359
    
360
    public class FromBuilderBase implements FromBuilder {
361

    
362
        protected TableNameBuilder tableName= null;
363
        private String subquery = null;
364
        private String passthrough = null;
365

    
366
        @Override
367
        public TableNameBuilder table() {
368
            if( tableName == null ) {
369
                this.tableName = createTableNameBuilder();
370
            }
371
            return this.tableName;
372
        }
373

    
374
        @Override
375
        public void accept(Visitor visitor, VisitorFilter filter) {
376
            if( filter.accept(this) ) {
377
                visitor.visit(this);
378
            }
379
            if( this.tableName != null ) {
380
                this.tableName.accept(visitor, filter);
381
            }
382
        }
383

    
384
        @Override
385
        public FromBuilder custom(String passthrough) {
386
            this.passthrough = passthrough;
387
            return this;
388
        }
389

    
390
        @Override
391
        public FromBuilder subquery(String subquery) {
392
            this.subquery = subquery;
393
            return this;
394
        }
395
        
396
        @Override
397
        public String toString() {
398
            if( ! StringUtils.isEmpty(passthrough) ) {
399
                return passthrough;
400
            }
401
            if( ! StringUtils.isEmpty(subquery) ) {
402
                return "( " + this.subquery + ") as _subquery_alias_ ";
403
            }
404
            return this.tableName.toString();
405
        }
406

    
407
    }
408

    
409
    public class SelectColumnBuilderBase implements SelectColumnBuilder {
410

    
411
        private Variable name = null;
412
        private String alias = null;
413
        private Value value = null;
414
        private boolean asGeometry = false;
415
        
416
        @Override
417
        public void accept(Visitor visitor, VisitorFilter filter) {
418
            if( filter.accept(this) ) {
419
                visitor.visit(this);
420
            }
421
            if( this.name != null ) {
422
                this.name.accept(visitor, filter);
423
            }
424
            if( this.value != null ) {
425
                this.value.accept(visitor, filter);
426
            }
427
        }
428

    
429
        @Override
430
        public SelectColumnBuilder name(String name) {
431
            String quote = config.getString(Config.quote_for_identifiers);
432
            if (name.startsWith(quote)) {
433
                // Remove quotes
434
                name = name.substring(1, name.length() - 1);
435
            }
436
            this.name = variable(name);
437
            this.value = null;
438
            this.asGeometry = false;
439
            return this;
440
        }
441

    
442
        @Override
443
        public SelectColumnBuilder all() {
444
            this.name = null;
445
            this.value = custom("*");
446
            this.asGeometry = false;
447
            return this;
448
        }
449
        
450
        @Override
451
        public SelectColumnBuilder as_geometry() {
452
            this.asGeometry = true;
453
            return this;
454
        }
455
       
456
        @Override
457
        public SelectColumnBuilder value(Value value) {
458
            this.value = value;
459
            this.name = null;
460
            return this;
461
        }
462

    
463
        @Override
464
        public SelectColumnBuilder as(String alias) {
465
            this.alias = alias;
466
            return this;
467
        }
468

    
469
        @Override
470
        public String getName() {
471
            return this.name.getName();
472
        }
473
        
474
        @Override
475
        public String getAlias() {
476
            return this.alias;
477
        }
478
        
479
        @Override
480
        public String getValue() {
481
            return this.alias;
482
        }
483

    
484
        @Override
485
        public String toString() {
486
            StringBuilder builder = new StringBuilder();
487
            if( this.asGeometry ) {
488
                builder.append(getAsGeometry(this.name).toString());
489
            } else {
490
                if( this.name != null ) {
491
                    builder.append(this.name.toString());
492
                } else {
493
                    builder.append(this.value.toString());
494
                }
495
            }
496
            if( this.alias != null ) {
497
                builder.append(" AS ");
498
                builder.append(identifier(this.alias));
499
            }
500
            return builder.toString();
501
        }
502
    }
503

    
504
    public class OrderByBuilderBase implements OrderByBuilder {
505
        protected String value;
506
        protected String custom;
507
        protected boolean ascending;
508
        
509
        public OrderByBuilderBase() {
510
            this.ascending = true;
511
        }
512

    
513
        @Override
514
        public void accept(Visitor visitor, VisitorFilter filter) {
515
            if( filter.accept(this) ) {
516
                visitor.visit(this);
517
            }
518
        }
519

    
520
        @Override
521
        public OrderByBuilder column(String name) {
522
            this.value = name;
523
            return this;
524
        }
525

    
526
        @Override
527
        public OrderByBuilder custom(String order) {
528
            this.custom = order;
529
            return this;
530
        }
531

    
532
        @Override
533
        public OrderByBuilder ascending() {
534
            this.ascending = true;
535
            return this;
536
        }
537

    
538
        @Override
539
        public OrderByBuilder ascending(boolean asc) {
540
            this.ascending = asc;
541
            return this;
542
        }
543

    
544
        @Override
545
        public OrderByBuilder descending() {
546
            this.ascending = false;
547
            return this;
548
        }
549

    
550
        @Override
551
        public String toString() {
552
            if( !StringUtils.isEmpty(this.custom) ) {
553
                return this.custom;
554
            }
555
            if( this.ascending ) {
556
                return this.value + " ASC";
557
            }
558
            return this.value + " DESC";
559
        }
560
    }
561
    
562
    public class SelectBuilderBase implements SelectBuilder {
563

    
564
        protected FromBuilder from;
565
        protected ExpressionBuilder where;
566
        protected long limit = -1;
567
        protected long offset = -1;
568
        protected List<SelectColumnBuilder> columns;
569
        protected List<OrderByBuilder> order_by;
570
        protected boolean distinct;
571

    
572
        public SelectBuilderBase() {
573
            this.columns = new ArrayList<>();
574
            this.distinct = false;
575
        }
576

    
577
        @Override
578
        public void accept(Visitor visitor, VisitorFilter filter) {
579
            if( filter.accept(this) ) {
580
                visitor.visit(this);
581
            }
582
            for (SelectColumnBuilder column : columns) {
583
                column.accept(visitor,filter);
584
            }
585
            if( this.has_from() ) {
586
                this.from.accept(visitor,filter);
587
            }
588
            if( this.has_where() ) {
589
                this.where.accept(visitor,filter);
590
            }
591
            if( this.has_order_by() ) {
592
                for (OrderByBuilder order : order_by) {
593
                    order.accept(visitor,filter);
594
                }
595
            }
596
        }
597

    
598
        @Override
599
        public SelectBuilder distinct() {
600
            this.distinct = true;
601
            return this;
602
        }
603
        
604
        @Override
605
        public SelectColumnBuilder column() {
606
            SelectColumnBuilder builder = createSelectColumnBuilder();
607
            this.columns.add(builder);
608
            return builder;
609
        }
610

    
611
        @Override
612
        public boolean has_column(String name) {
613
            for (SelectColumnBuilder column : columns) {
614
                if( name.equals(column.getName()) ) {
615
                    return true;
616
                }
617
            }
618
            return false;
619
        }
620

    
621
        @Override
622
        public FromBuilder from() {
623
            if (this.from == null) {
624
                this.from = createFromBuilder();
625
            }
626
            return this.from;
627
        }
628

    
629
        @Override
630
        public boolean has_from() {
631
            return this.from != null;
632
        }
633
        
634
        @Override
635
        public ExpressionBuilder where() {
636
            if (this.where == null) {
637
                this.where = createExpressionBuilder();
638
            }
639
            return this.where;
640
        }
641

    
642
        @Override
643
        public boolean has_where() {
644
            if( this.where == null ) {
645
                return false;
646
            }
647
            return this.where.getValue() != null;
648
        }
649
        
650
        @Override
651
        public SelectBuilder limit(long limit) {
652
            this.limit = limit;
653
            return this;
654
        }
655

    
656
        @Override
657
        public boolean has_limit() {
658
            return this.limit > 0;
659
        }
660

    
661
        @Override
662
        public SelectBuilder offset(long offset) {
663
            this.offset = offset;
664
            return this;
665
        }
666

    
667
        @Override
668
        public boolean has_offset() {
669
            return this.offset > 0;
670
        }
671

    
672
        @Override
673
        public OrderByBuilder order_by() {
674
            if( this.order_by == null ) {
675
                this.order_by = new ArrayList<>();
676
            }
677
            OrderByBuilder order = createOrderByBuilder();
678
            this.order_by.add(order);
679
            return order;
680
        }
681

    
682
        @Override
683
        public boolean has_order_by() {
684
            if( this.order_by == null ) {
685
                return false;
686
            }
687
            return !this.order_by.isEmpty();
688
        }
689
        
690
        protected boolean isValid(StringBuilder message) {
691
            if( message == null ) {
692
                message = new StringBuilder();
693
            }
694
            if( this.has_offset() && !this.has_order_by() ) {
695
                // Algunos gestores de BBDD requieren que se especifique un
696
                // orden para poder usar OFFSET. Como eso parece buena idea para
697
                // asegurar que siempre tengamos los mismo resultados, lo exijimos
698
                // siempre.
699
                message.append("Can't use OFFSET without an ORDER BY.");
700
                return false;
701
            }
702
            return true;
703
        }
704
        
705
        @Override
706
        public String toString() {
707
            StringBuilder builder = new StringBuilder();
708
            if( !this.isValid(builder) ) {
709
                throw new IllegalStateException(builder.toString());
710
            }
711
            builder.append("SELECT ");
712
            if( this.distinct ) {
713
                builder.append("DISTINCT ");
714
            }
715
            boolean first = true;
716
            for (SelectColumnBuilder column : columns) {
717
                if (first) {
718
                    first = false;
719
                } else {
720
                    builder.append(", ");
721
                }
722
                builder.append(column.toString());
723
            }
724

    
725
            if ( this.has_from() ) {
726
                builder.append(" FROM ");
727
                builder.append(this.from.toString());
728
            }
729
            if ( this.has_where() ) {
730
                builder.append(" WHERE ");
731
                builder.append(this.where.toString());
732
            }
733
            
734
            if( this.has_order_by() ) {
735
                builder.append(" ORDER BY ");
736
                first = true;
737
                for (OrderByBuilder item : this.order_by) {
738
                    if (first) {
739
                        first = false;
740
                    } else {
741
                        builder.append(", ");
742
                    }
743
                    builder.append(item.toString());                    
744
                }   
745
            }
746
            
747
            if ( this.has_limit() ) {
748
                builder.append(" LIMIT ");
749
                builder.append(this.limit);
750
            }
751
            if ( this.has_offset() ) {
752
                builder.append(" OFFSET ");
753
                builder.append(this.offset);
754
            }
755
            return builder.toString();
756

    
757
        }
758
    }
759

    
760
    public class DropTableBuilderBase implements DropTableBuilder {
761

    
762
        protected TableNameBuilder table;
763

    
764
        @Override
765
        public TableNameBuilder table() {
766
            if( table == null ) {
767
                table = createTableNameBuilder();
768
            }
769
            return table;
770
        }
771

    
772
        @Override
773
        public void accept(Visitor visitor, VisitorFilter filter) {
774
            if( filter.accept(this) ) {
775
                visitor.visit(this);
776
            }
777
            this.table.accept(visitor,filter);
778
        }
779
        
780
        @Override
781
        public String toString() {
782
            StringBuilder builder = new StringBuilder();
783
            boolean first = true;
784
            for (String sql : toStrings()) {
785
                if( StringUtils.isEmpty(sql) ) {
786
                    continue;
787
                }
788
                if (first) {
789
                    first = false;
790
                } else {
791
                    builder.append("; ");
792
                }
793
                builder.append(sql);
794
            }
795
            return builder.toString();
796
        }
797

    
798
        @Override
799
        public List<String> toStrings() {
800
            List<String> sqls = new ArrayList<>();
801

    
802
            sqls.add(
803
                    MessageFormat.format(
804
                            config.getString(SQLConfig.DROP_TABLE_table),
805
                            this.table.toString()
806
                    )
807
            );
808
            String sql;
809
            if( config.has_functionality(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table) ) {
810
                if (this.table.has_schema()) {
811
                    sql = MessageFormat.format(
812
                            config.getString(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table),
813
                            string(this.table.getSchema()),
814
                            string(this.table.getName())
815
                    );
816
                } else {
817
                    sql = MessageFormat.format(
818
                            config.getString(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table),
819
                            identifier(this.table.getName())
820
                    );
821
                }
822
                if( !StringUtils.isEmpty(sql) ) {
823
                    sqls.add(sql);
824
                }
825
            }
826
            return sqls;
827
        }
828
    }
829

    
830
    public class GrantRoleBuilderBase implements GrantRoleBuilder {
831
        protected TableNameBuilder table;
832
        protected String role;
833
        protected Set<Privilege> privileges;
834

    
835
        public GrantRoleBuilderBase(TableNameBuilder table, String role) {
836
            this.table = table;
837
            this.role = role;
838
            this.privileges = new HashSet<>();
839
        }
840

    
841
        @Override
842
        public GrantRoleBuilder privilege(Privilege privilege) {
843
            privileges.add(privilege);
844
            return this;
845
        }
846
        
847
        @Override
848
        public GrantRoleBuilder select() {
849
             privileges.add(Privilege.SELECT);
850
            return this;
851
        }
852

    
853
        @Override
854
        public GrantRoleBuilder update() {
855
             privileges.add(Privilege.UPDATE);
856
            return this;
857
        }
858

    
859
        @Override
860
        public GrantRoleBuilder insert() {
861
            privileges.add(Privilege.INSERT);
862
            return this;
863
        }
864

    
865
        @Override
866
        public GrantRoleBuilder delete() {
867
            privileges.add(Privilege.DELETE);
868
            return this;
869
        }
870

    
871
        @Override
872
        public GrantRoleBuilder truncate() {
873
            privileges.add(Privilege.TRUNCATE);
874
            return this;
875
        }
876

    
877
        @Override
878
        public GrantRoleBuilder reference() {
879
            privileges.add(Privilege.REFERENCE);
880
            return this;
881
        }
882

    
883
        @Override
884
        public GrantRoleBuilder trigger() {
885
            privileges.add(Privilege.TRIGGER);
886
            return this;
887
        }
888

    
889
        @Override
890
        public GrantRoleBuilder all() {
891
            privileges.add(Privilege.ALL);
892
            return this;
893
        }
894

    
895
        protected String getPrivilegeName(Privilege privilege) {
896
            switch(privilege) {
897
                case DELETE:
898
                    return "DELETE";
899
                case INSERT:
900
                    return "INSERT";
901
                case REFERENCE:
902
                    return "REFERENCE";
903
                case SELECT:
904
                    return "SELECT";
905
                case TRIGGER:
906
                    return "TRIGGER";
907
                case TRUNCATE:
908
                    return "TRUNCATE";
909
                case UPDATE:
910
                    return "UPDATE";
911
                case ALL:
912
                default:
913
                    return "ALL";
914
            }
915
        }
916
        
917
        @Override
918
        public String toString() {
919
            StringBuilder builder = new StringBuilder();
920
            boolean first = true;
921
            for (Privilege privilege : privileges) {
922
                if (first) {
923
                    first = false;
924
                } else {
925
                    builder.append(", ");
926
                }
927
                builder.append( this.getPrivilegeName(privilege));
928
            }
929
            String sql = MessageFormat.format(
930
                    config.getString(SQLConfig.GRANT_privileges_ON_table_TO_role),
931
                    builder.toString(),
932
                    table.toString(),
933
                    role
934
            );
935
            return sql;
936
        }
937
    }
938
    
939
    public class GrantBuilderBase implements GrantBuilder {
940

    
941
        protected TableNameBuilder table;
942
        protected Map<String, GrantRoleBuilder> roles;
943

    
944
        public GrantBuilderBase() {
945
            this.roles = new HashMap<>();
946
        }
947
        
948
        @Override
949
        public TableNameBuilder table() {
950
            if( table == null ) {
951
                table = createTableNameBuilder();
952
            }
953
            return table;
954
        }
955

    
956
        @Override
957
        public void accept(Visitor visitor, VisitorFilter filter) {
958
            if( filter.accept(this) ) {
959
                visitor.visit(this);
960
            }
961
            if( this.table!= null ) {
962
                this.table.accept(visitor,filter);
963
            }
964
        }
965
        
966
        @Override
967
        public GrantRoleBuilder role(String role) {
968
            GrantRoleBuilder roleBuilder = this.roles.get(role);
969
            if( roleBuilder == null ) {
970
                roleBuilder = createGrantRoleBuilder(this.table(), role);
971
                this.roles.put(role, roleBuilder);
972
            }
973
            return roleBuilder;
974
        }
975

    
976
        @Override
977
        public String toString() {
978
            StringBuilder builder = new StringBuilder();
979
            boolean first = true;
980
            for (String sql : toStrings()) {
981
                if( StringUtils.isEmpty(sql) ) {
982
                    continue;
983
                }
984
                if (first) {
985
                    first = false;
986
                } else {
987
                    builder.append("; ");
988
                }
989
                builder.append(sql);
990
            }
991
            return builder.toString();
992
        }
993

    
994
        @Override
995
        public List<String> toStrings() {
996
            List<String> sqls = new ArrayList<>();
997
            for (GrantRoleBuilder role : roles.values()) {
998
                sqls.add(role.toString());
999
            }
1000
            return sqls;
1001
        }
1002
    }
1003

    
1004
    public class UpdateColumnBuilderBase extends InsertColumnBuilderBase implements UpdateColumnBuilder {
1005
        
1006
        public UpdateColumnBuilderBase() {
1007
            super();
1008
        }
1009

    
1010
        @Override
1011
        public UpdateColumnBuilder name(String name) {
1012
            return (UpdateColumnBuilder) super.name(name);
1013
        }
1014

    
1015
        @Override
1016
        public UpdateColumnBuilder with_value(Value value) {
1017
            return (UpdateColumnBuilder) super.with_value(value);
1018
        }
1019
        
1020
    }
1021
    
1022
    public class UpdateBuilderBase implements UpdateBuilder {
1023

    
1024
        protected ExpressionBuilder where;
1025
        protected List<UpdateColumnBuilder> columns;
1026
        protected TableNameBuilder table;
1027

    
1028
        public UpdateBuilderBase() {
1029
            this.columns = new ArrayList<>();
1030
        }
1031

    
1032
        @Override
1033
        public void accept(Visitor visitor, VisitorFilter filter) {
1034
            if( filter.accept(this) ) {
1035
                visitor.visit(this);
1036
            }
1037
            if( this.table != null ) {
1038
                this.table.accept(visitor, filter);
1039
            }
1040
            for (UpdateColumnBuilder column : columns) {
1041
                column.accept(visitor, filter);
1042
            }
1043
            if( this.has_where() ) {
1044
                this.where.accept(visitor, filter);
1045
            }
1046
        }
1047

    
1048
        @Override
1049
        public ExpressionBuilder where() {
1050
            if (this.where == null) {
1051
                this.where = createExpressionBuilder();
1052
            }
1053
            return this.where;
1054
        }
1055

    
1056
        @Override
1057
        public TableNameBuilder table() {
1058
            if( table == null ) {
1059
                table = createTableNameBuilder();
1060
            }
1061
            return table;
1062
        }
1063

    
1064
        @Override
1065
        public UpdateColumnBuilder column() {
1066
            UpdateColumnBuilder column = createUpdateColumnBuilder();
1067
            this.columns.add(column);
1068
            return column;
1069
        }
1070
        
1071
        @Override
1072
        public boolean has_where() {
1073
            return this.where != null;
1074
        }
1075

    
1076
        @Override
1077
        public String toString() {
1078
            /*
1079
             * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
1080
             * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
1081
             * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
1082
             * output_expression [ AS output_name ] [, ...] ]
1083
             */
1084
            StringBuilder columnsAndValues = new StringBuilder();
1085

    
1086
            boolean first = true;
1087
            for (UpdateColumnBuilder column : columns) {
1088
                if (first) {
1089
                    first = false;
1090
                } else {
1091
                    columnsAndValues.append(", ");
1092
                }
1093
                columnsAndValues.append(identifier(column.getName()));
1094
                columnsAndValues.append(" = ");
1095
                columnsAndValues.append(column.getValue().toString());
1096
            }
1097
            
1098
            String sql;
1099
            if ( this.has_where() ) {
1100
                sql = MessageFormat.format(
1101
                        config.getString(SQLConfig.UPDATE_table_SET_columnsAndValues_WHERE_expresion),
1102
                        this.table.toString(),
1103
                        columnsAndValues.toString(),
1104
                        this.where.toString()
1105
                );
1106
            } else {
1107
                sql = MessageFormat.format(
1108
                        config.getString(SQLConfig.UPDATE_table_SET_columnsAndValues),
1109
                        this.table.toString(),
1110
                        columnsAndValues.toString()
1111
                );
1112
            }
1113
            return sql;
1114
        }
1115
    }
1116

    
1117
    public class DeleteBuilderBase implements DeleteBuilder {
1118

    
1119
        protected ExpressionBuilder where;
1120
        protected TableNameBuilder table;
1121

    
1122
        public DeleteBuilderBase() {
1123
        }
1124

    
1125
        @Override
1126
        public void accept(Visitor visitor, VisitorFilter filter) {
1127
            if( filter.accept(this) ) {
1128
                visitor.visit(this);
1129
            }
1130
            if( this.table != null ) {
1131
                this.table.accept(visitor, filter);
1132
            }
1133
            if( this.has_where() ) {
1134
                this.where.accept(visitor, filter);
1135
            }
1136
        }
1137

    
1138
        @Override
1139
        public ExpressionBuilder where() {
1140
            if (this.where == null) {
1141
                this.where = createExpressionBuilder();
1142
            }
1143
            return this.where;
1144
        }
1145

    
1146
        @Override
1147
        public TableNameBuilder table() {
1148
            if( table == null ) {
1149
                table = createTableNameBuilder();
1150
            }
1151
            return table;
1152
        }
1153

    
1154
        @Override
1155
        public boolean has_where() {
1156
            return this.where != null;
1157
        }
1158

    
1159
        @Override
1160
        public String toString() {
1161
            /*
1162
             * DELETE FROM table_name
1163
             * WHERE some_column=some_value; 
1164
             */
1165
            String sql;
1166
            if( this.has_where() ) {
1167
                sql = MessageFormat.format(
1168
                        config.getString(SQLConfig.DELETE_FROM_table_WHERE_expresion),
1169
                        this.table.toString(),
1170
                        this.where.toString()
1171
                );
1172
            } else {
1173
                sql = MessageFormat.format(
1174
                        config.getString(SQLConfig.DELETE_FROM_table),
1175
                        this.table.toString()
1176
                );
1177
            }
1178
            return sql;
1179
        }
1180
    }
1181

    
1182
    public class AlterTableBuilderBase implements AlterTableBuilder {
1183

    
1184
        protected TableNameBuilder table;
1185
        protected List<String> drops;
1186
        protected List<ColumnDescriptorBuilderBase> adds;
1187
        protected List<ColumnDescriptorBuilderBase> alters;
1188
        protected List<Pair> renames;
1189

    
1190
        public AlterTableBuilderBase() {
1191
            this.drops = new ArrayList<>();
1192
            this.adds = new ArrayList<>();
1193
            this.alters = new ArrayList<>();
1194
            this.renames = new ArrayList<>();
1195
        }
1196

    
1197
        @Override
1198
        public void accept(Visitor visitor, VisitorFilter filter) {
1199
            if( filter.accept(this) ) {
1200
                visitor.visit(this);
1201
            }
1202
            if( this.table != null ) {
1203
                this.table.accept(visitor, filter);
1204
            }
1205
        }
1206

    
1207
        @Override
1208
        public TableNameBuilder table() {
1209
            if( table == null ) {
1210
                table = createTableNameBuilder();
1211
            }
1212
            return table;
1213
        }
1214

    
1215
        @Override
1216
        public AlterTableBuilder drop_column(String columnName) {
1217
            this.drops.add(columnName);
1218
            return this;
1219
        }
1220

    
1221
        @Override
1222
        public AlterTableBuilder add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1223
            if (isPk || isAutomatic) {
1224
                allowNulls = false;
1225
            }
1226
            this.adds.add(new ColumnDescriptorBuilderBase(columnName, type, type_p, type_s, isPk, allowNulls, isAutomatic, defaultValue));
1227
            return this;
1228
        }
1229

    
1230
        @Override
1231
        public AlterTableBuilder alter_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1232
            if (isPk || isAutomatic) {
1233
                allowNulls = false;
1234
            }
1235
            this.alters.add(new ColumnDescriptorBuilderBase(columnName, type, type_p, type_s, isPk, allowNulls, isAutomatic, defaultValue));
1236
            return this;
1237
        }
1238

    
1239
        @Override
1240
        public AlterTableBuilder rename_column(String source, String target) {
1241
            this.renames.add(new ImmutablePair(source, target));
1242
            return this;
1243
        }
1244

    
1245
        @Override
1246
        public String toString() {
1247
            StringBuilder builder = new StringBuilder();
1248
            boolean first = true;
1249
            for (String sql : toStrings()) {
1250
                if( StringUtils.isEmpty(sql) ) {
1251
                    continue;
1252
                }
1253
                if (first) {
1254
                    first = false;
1255
                } else {
1256
                    builder.append("; ");
1257
                }
1258
                builder.append(sql);
1259
            }
1260
            return builder.toString();
1261
        }
1262

    
1263
        @Override
1264
        public List<String> toStrings() {
1265
            List<String> sqls = new ArrayList<>();
1266
            /*
1267
             ALTER TABLE [ ONLY ] name [ * ]
1268
             action [, ... ]
1269
             ALTER TABLE [ ONLY ] name [ * ]
1270
             RENAME [ COLUMN ] column TO new_column
1271
             ALTER TABLE name
1272
             RENAME TO new_name
1273
             ALTER TABLE name
1274
             SET SCHEMA new_schema
1275

1276
             where action is one of:
1277

1278
             ADD [ COLUMN ] column data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
1279
             DROP [ COLUMN ] [ IF EXISTS ] column [ RESTRICT | CASCADE ]
1280
             ALTER [ COLUMN ] column [ SET DATA ] TYPE data_type [ COLLATE collation ] [ USING expression ]
1281
             ALTER [ COLUMN ] column SET DEFAULT expression
1282
             ALTER [ COLUMN ] column DROP DEFAULT
1283
             ALTER [ COLUMN ] column { SET | DROP } NOT NULL
1284
             ALTER [ COLUMN ] column SET STATISTICS integer
1285
             ALTER [ COLUMN ] column SET ( attribute_option = value [, ... ] )
1286
             ALTER [ COLUMN ] column RESET ( attribute_option [, ... ] )
1287
             ALTER [ COLUMN ] column SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
1288
             ADD table_constraint [ NOT VALID ]
1289
             ADD table_constraint_using_index
1290
             VALIDATE CONSTRAINT constraint_name
1291
             DROP CONSTRAINT [ IF EXISTS ]  constraint_name [ RESTRICT | CASCADE ]
1292
             DISABLE TRIGGER [ trigger_name | ALL | USER ]
1293
             ENABLE TRIGGER [ trigger_name | ALL | USER ]
1294
             ENABLE REPLICA TRIGGER trigger_name
1295
             ENABLE ALWAYS TRIGGER trigger_name
1296
             DISABLE RULE rewrite_rule_name
1297
             ENABLE RULE rewrite_rule_name
1298
             ENABLE REPLICA RULE rewrite_rule_name
1299
             ENABLE ALWAYS RULE rewrite_rule_name
1300
             CLUSTER ON index_name
1301
             SET WITHOUT CLUSTER
1302
             SET WITH OIDS
1303
             SET WITHOUT OIDS
1304
             SET ( storage_parameter = value [, ... ] )
1305
             RESET ( storage_parameter [, ... ] )
1306
             INHERIT parent_table
1307
             NO INHERIT parent_table
1308
             OF type_name
1309
             NOT OF
1310
             OWNER TO new_owner
1311
             SET TABLESPACE new_tablespace
1312

1313
             and table_constraint_using_index is:
1314

1315
             [ CONSTRAINT constraint_name ]
1316
             { UNIQUE | PRIMARY KEY } USING INDEX index_name
1317
             [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1318

1319
             */
1320
            StringBuilder builder = new StringBuilder();
1321

    
1322
            builder.append("ALTER TABLE");
1323
            builder.append(this.table.toString());
1324
            builder.append(" ");
1325
            boolean first = true;
1326
            for (String column : drops) {
1327
                if (first) {
1328
                    first = false;
1329
                } else {
1330
                    builder.append(", ");
1331
                }
1332
                builder.append("DROP COLUMN IF EXISTS ");
1333
                builder.append(column);
1334
            }
1335
            first = drops.isEmpty();
1336
            for (ColumnDescriptorBuilderBase column : adds) {
1337
                if (first) {
1338
                    first = false;
1339
                } else {
1340
                    builder.append(", ");
1341
                }
1342
                builder.append("ADD COLUMN ");
1343
                builder.append(column.getName());
1344
                builder.append(" ");
1345
                if( column.getType() == DataTypes.INT && column.isAutomatic() ) {
1346
                    builder.append(" SERIAL");
1347
                } else {
1348
                    builder.append(sqltype(column.getType(), column.getPrecision(), column.getSize()));
1349
                }
1350
                if (column.getDefaultValue() == null) {
1351
                    if (column.allowNulls()) {
1352
                        builder.append(" DEFAULT NULL");
1353
                    }
1354
                } else {
1355
                    builder.append(" DEFAULT '");
1356
                    builder.append(column.getDefaultValue().toString());
1357
                    builder.append("'");
1358
                }
1359
                if (column.allowNulls()) {
1360
                    builder.append(" NULL");
1361
                } else {
1362
                    builder.append(" NOT NULL");
1363
                }
1364
                if (column.isPrimaryKey()) {
1365
                    builder.append(" PRIMARY KEY");
1366
                }
1367
            }
1368
            first = drops.isEmpty() && adds.isEmpty();
1369
            for (ColumnDescriptorBuilderBase column : alters) {
1370
                if (first) {
1371
                    first = false;
1372
                } else {
1373
                    builder.append(", ");
1374
                }
1375
                builder.append("ALTER COLUMN ");
1376
                builder.append(column.getName());
1377
                builder.append("SET DATA TYPE ");
1378
                if( column.getType() == DataTypes.INT && column.isAutomatic() ) {
1379
                    builder.append(" SERIAL");
1380
                } else {
1381
                    builder.append(sqltype(column.getType(), column.getPrecision(), column.getSize()));
1382
                }
1383
                builder.append(", ");
1384
                if (column.getDefaultValue() == null) {
1385
                    if (column.allowNulls()) {
1386
                        builder.append("ALTER COLUMN ");
1387
                        builder.append(column.getName());
1388
                        builder.append(" SET DEFAULT NULL");
1389
                    } else {
1390
                        builder.append("ALTER COLUMN ");
1391
                        builder.append(column.getName());
1392
                        builder.append(" DROP DEFAULT");
1393
                    }
1394
                } else {
1395
                    builder.append("ALTER COLUMN ");
1396
                    builder.append(column.getName());
1397
                    builder.append(" SET DEFAULT '");
1398
                    builder.append(column.getDefaultValue().toString());
1399
                    builder.append("'");
1400
                }
1401
            }
1402
            first = drops.isEmpty() && adds.isEmpty() && alters.isEmpty();
1403
            for (Pair pair : renames) {
1404
                if (first) {
1405
                    first = false;
1406
                } else {
1407
                    builder.append(", ");
1408
                }
1409
                builder.append("RENAME COLUMN ");
1410
                builder.append(pair.getLeft());
1411
                builder.append(" TO ");
1412
                builder.append(pair.getRight());
1413
            }
1414
            sqls.add(builder.toString());
1415

    
1416
            return sqls;
1417
        }
1418

    
1419
    }
1420

    
1421
    public class CreateTableBuilderBase implements CreateTableBuilder {
1422

    
1423
        protected TableNameBuilder table;
1424
        protected List<ColumnDescriptorBuilderBase> columns;
1425

    
1426
        public CreateTableBuilderBase() {
1427
            this.columns = new ArrayList<>();
1428
        }
1429

    
1430
        @Override
1431
        public void accept(Visitor visitor, VisitorFilter filter) {
1432
            if( filter.accept(this) ) {
1433
                visitor.visit(this);
1434
            }
1435
            if( this.table != null ) {
1436
                this.table.accept(visitor, filter);
1437
            }
1438
        }
1439

    
1440
        @Override
1441
        public TableNameBuilder table() {
1442
            if( table == null ) {
1443
                table = createTableNameBuilder();
1444
            }
1445
            return table;
1446
        }
1447

    
1448
        @Override
1449
        public CreateTableBuilderBase add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1450
            if( StringUtils.isEmpty(columnName) ) {
1451
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1452
            }
1453
            if (isPk || isAutomatic) {
1454
                allowNulls = false;
1455
            }
1456
            this.columns.add(new ColumnDescriptorBuilderBase(columnName, type, type_p, type_s, isPk, allowNulls, isAutomatic, defaultValue));
1457
            return this;
1458
        }
1459

    
1460
        @Override
1461
        public CreateTableBuilder add_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean allowNulls) {
1462
            if( StringUtils.isEmpty(columnName) ) {
1463
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1464
            }
1465
            this.columns.add(new ColumnDescriptorBuilderBase(columnName, type, subtype, proj, allowNulls));
1466
            return this;
1467
        }
1468

    
1469
        @Override
1470
        public ColumnDescriptorBuilder getColumnDescriptor(String columnName) {
1471
            if( StringUtils.isEmpty(columnName) ) {
1472
                return null;
1473
            }
1474
            for (ColumnDescriptorBuilderBase column : columns) {
1475
                if( columnName.equals(column.getName()) ) {
1476
                    return column;
1477
                }
1478
            }
1479
            return null;
1480
        }
1481
                
1482
        @Override
1483
        public String toString() {
1484
            StringBuilder builder = new StringBuilder();
1485
            boolean first = true;
1486
            for (String sql : toStrings()) {
1487
                if( StringUtils.isEmpty(sql) ) {
1488
                    continue;
1489
                }
1490
                if (first) {
1491
                    first = false;
1492
                } else {
1493
                    builder.append("; ");
1494
                }
1495
                builder.append(sql);
1496
            }
1497
            return builder.toString();
1498
        }
1499

    
1500
        @Override
1501
        public List<String> toStrings() {
1502
            List<String> sqls = new ArrayList<>();
1503
            /**
1504
             * CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE
1505
             * table_name ( { column_name data_type [ DEFAULT default_expr ] [
1506
             * column_constraint [ ... ] ] | table_constraint | LIKE
1507
             * parent_table [ { INCLUDING | EXCLUDING } DEFAULTS ] } [, ... ] )
1508
             * [ INHERITS ( parent_table [, ... ] ) ] [ WITH OIDS | WITHOUT OIDS
1509
             * ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
1510
             *
1511
             * where column_constraint is:
1512
             *
1513
             * [ CONSTRAINT constraint_name ] { NOT NULL | NULL | UNIQUE |
1514
             * PRIMARY KEY | CHECK (expression) | REFERENCES reftable [ (
1515
             * refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON
1516
             * DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE | NOT
1517
             * DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1518
             *
1519
             * and table_constraint is:
1520
             *
1521
             * [ CONSTRAINT constraint_name ] { UNIQUE ( column_name [, ... ] )
1522
             * | PRIMARY KEY ( column_name [, ... ] ) | CHECK ( expression ) |
1523
             * FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ (
1524
             * refcolumn [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH
1525
             * SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE
1526
             * | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1527
             */
1528
            StringBuilder builder = new StringBuilder();
1529

    
1530
            builder.append("CREATE TABLE ");
1531
            builder.append(this.table.toString());
1532
            builder.append(" (");
1533
            boolean first = true;
1534
            for (ColumnDescriptorBuilderBase column : columns) {
1535
                if (first) {
1536
                    first = false;
1537
                } else {
1538
                    builder.append(", ");
1539
                }
1540
                builder.append(identifier(column.getName()));
1541
                builder.append(" ");
1542
                if( column.isAutomatic() && column.getType() == DataTypes.INT ) {
1543
                    builder.append("SERIAL");
1544
                } else if( column.isAutomatic() && column.getType() == DataTypes.LONG ) {
1545
                    builder.append("BIGSERIAL");
1546
                } else {
1547
                    builder.append(sqltype(column.getType(), column.getPrecision(), column.getSize()));
1548
                }
1549
                if (column.getDefaultValue() == null) {
1550
                    if (column.allowNulls()) {
1551
                        builder.append(" DEFAULT NULL");
1552
                    }
1553
                } else {
1554
                    builder.append(" DEFAULT '");
1555
                    builder.append(column.getDefaultValue().toString());
1556
                    builder.append("'");
1557
                }
1558
                if (column.allowNulls()) {
1559
                    builder.append(" NULL");
1560
                } else {
1561
                    builder.append(" NOT NULL");
1562
                }
1563
                if (column.isPrimaryKey()) {
1564
                    builder.append(" PRIMARY KEY");
1565
                }
1566
            }
1567
            builder.append(" )");
1568
            sqls.add(builder.toString());
1569

    
1570
            return sqls;
1571
        }
1572
    }
1573

    
1574
    public class InsertColumnBuilderBase implements InsertColumnBuilder {
1575
        protected Variable name;
1576
        protected Value value;
1577
        
1578
        public InsertColumnBuilderBase() {
1579
        }
1580

    
1581
        @Override
1582
        public void accept(Visitor visitor, VisitorFilter filter) {
1583
            if( filter.accept(this) ) {
1584
                visitor.visit(this);
1585
            }
1586
            if( this.name != null ) {
1587
                this.name.accept(visitor, filter);
1588
            }
1589
            if( this.value != null ) {
1590
                this.value.accept(visitor, filter);
1591
            }
1592
        }
1593

    
1594
        @Override
1595
        public InsertColumnBuilder name(String name) {
1596
            this.name = variable(name);
1597
            return this;
1598
        }
1599

    
1600
        @Override
1601
        public InsertColumnBuilder with_value(Value value) {
1602
            this.value = value;
1603
            return this;
1604
        }
1605
        
1606
        @Override
1607
        public String getName() {
1608
            return this.name.getName();
1609
        }
1610
        
1611
        @Override
1612
        public Value getValue() {
1613
            return this.value;
1614
        }
1615
        
1616
        @Override
1617
        public String toString() {
1618
            return this.value.toString();
1619
        }
1620
    }
1621
    
1622
    public class InsertBuilderBase implements InsertBuilder {
1623

    
1624
        protected List<InsertColumnBuilder> columns;
1625
        protected TableNameBuilder table;
1626

    
1627
        public InsertBuilderBase() {
1628
            this.columns = new ArrayList<>();
1629
        }
1630

    
1631
        @Override
1632
        public void accept(Visitor visitor, VisitorFilter filter) {
1633
            if( filter.accept(this) ) {
1634
                visitor.visit(this);
1635
            }
1636
            if( this.table != null ) {
1637
                this.table.accept(visitor, filter);
1638
            }
1639
            for (InsertColumnBuilder column : columns) {
1640
                column.accept(visitor, filter);
1641
            }
1642
        }
1643

    
1644
        @Override
1645
        public TableNameBuilder table() {
1646
            if( table == null ) {
1647
                table = createTableNameBuilder();
1648
            }
1649
            return table;
1650
        }
1651

    
1652
        @Override
1653
        public InsertColumnBuilder column() {
1654
            InsertColumnBuilder column = createInsertColumnBuilder();
1655
            this.columns.add(column);
1656
            return column;
1657
        }
1658

    
1659
        @Override
1660
        public String toString() {
1661
            /*
1662
             * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
1663
             * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
1664
             * output_expression [ AS output_name ] [, ...] ]
1665
             */
1666
            StringBuilder builderColumns = new StringBuilder();
1667
            StringBuilder builderValues = new StringBuilder();
1668
            
1669
            boolean first = true;
1670
            for (InsertColumnBuilder column : columns) {
1671
                if (first) {
1672
                    first = false;
1673
                } else {
1674
                    builderColumns.append(", ");
1675
                }
1676
                builderColumns.append(identifier(column.getName()));
1677
            }
1678
            first = true;
1679
            for (InsertColumnBuilder column : columns) {
1680
                if (first) {
1681
                    first = false;
1682
                } else {
1683
                    builderValues.append(", ");
1684
                }
1685
                builderValues.append(column.toString());
1686
            }
1687
            
1688
            String sql = MessageFormat.format(
1689
                    config.getString(SQLConfig.INSERT_INTO_table_columns_VALUES_values),
1690
                    this.table.toString(),
1691
                    builderColumns.toString(),
1692
                    builderValues.toString()
1693
            );
1694
            return sql;
1695

    
1696
        }
1697
    }
1698

    
1699
    public class UpdateTableStatisticsBuilderBase implements UpdateTableStatisticsBuilder {
1700

    
1701
        protected TableNameBuilder table;
1702

    
1703
        @Override
1704
        public void accept(Visitor visitor, VisitorFilter filter) {
1705
            if( filter.accept(this) ) {
1706
                visitor.visit(this);
1707
            }
1708
            if( this.table != null ) {
1709
                this.table.accept(visitor, filter);
1710
            }
1711
        }
1712

    
1713
        @Override
1714
        public TableNameBuilder table() {
1715
            if( table == null ) {
1716
                table = createTableNameBuilder();
1717
            }
1718
            return table;
1719
        }
1720

    
1721
        @Override
1722
        public String toString() {
1723
            StringBuilder builder = new StringBuilder();
1724
            boolean first = true;
1725
            for (String sql : toStrings()) {
1726
                if( StringUtils.isEmpty(sql) ) {
1727
                    continue;
1728
                }
1729
                if (first) {
1730
                    first = false;
1731
                } else {
1732
                    builder.append("; ");
1733
                }
1734
                builder.append(sql);
1735
            }
1736
            return builder.toString();
1737
        }
1738

    
1739
        @Override
1740
        public List<String> toStrings() {
1741
            List<String> sqls = new ArrayList<>();
1742
            
1743
            if( config.has_functionality(SQLConfig.UPDATE_TABLE_STATISTICS_table) ) {
1744
                String sql = MessageFormat.format(
1745
                        config.getString(SQLConfig.UPDATE_TABLE_STATISTICS_table),
1746
                        table.toString()
1747
                    );
1748
                if( !StringUtils.isEmpty(sql) ) {
1749
                    sqls.add(sql);
1750
                }
1751
            }
1752
            return sqls;
1753
        }
1754
    }
1755
    
1756
    public SQLBuilderBase() {
1757
        super();
1758
        config.set(SQLConfig.default_schema, "public");
1759
        config.set(SQLConfig.allowAutomaticValues, true);
1760
        
1761
        config.set(SQLConfig.ST_ExtentAggregate, "ST_Extent({0})");
1762
        config.set(SQLConfig.ST_UnionAggregate, "ST_Union({0})");
1763
        config.set(SQLConfig.count, "COUNT({0})");
1764
        config.set(SQLConfig.count_distinct, "COUNT(DISTINCT {0})");
1765

    
1766
        config.set(SQLConfig.type_boolean, "BOOLEAN");
1767
        config.set(SQLConfig.type_byte, "TINYINT");
1768
        config.set(SQLConfig.type_bytearray, "BYTEA");
1769
        config.set(SQLConfig.type_geometry, "TEXT");
1770
        config.set(SQLConfig.type_char, "CHARACTER(1)");
1771
        config.set(SQLConfig.type_date, "DATE");
1772
        config.set(SQLConfig.type_double, "DOUBLE PRECISION"); //float con 53 bits de mantisa, float(54)
1773
        config.set(SQLConfig.type_numeric_p, "NUMERIC({0})");
1774
        config.set(SQLConfig.type_numeric_ps, "NUMERIC({0},{1})");
1775
        config.set(SQLConfig.type_bigdecimal, "NUMERIC({0},{1})");
1776
        config.set(SQLConfig.type_float, "REAL"); //float con 24 bits de mantisa, float(24)
1777
        config.set(SQLConfig.type_int, "INT");
1778
        config.set(SQLConfig.type_long, "BIGINT");
1779
        config.set(SQLConfig.type_string, "TEXT");
1780
        config.set(SQLConfig.type_string_p, "VARCHAR({0})");
1781
        config.set(SQLConfig.type_time, "TIME");
1782
        config.set(SQLConfig.type_timestamp, "TIMESTAMP");
1783
        config.set(SQLConfig.type_version, "VARCHAR(30)");
1784
        config.set(SQLConfig.type_URI, "TEXT");
1785
        config.set(SQLConfig.type_URL, "TEXT");
1786
        config.set(SQLConfig.type_FILE, "TEXT");
1787
        config.set(SQLConfig.type_FOLDER, "TEXT");
1788

    
1789
        config.set(SQLConfig.DELETE_FROM_table_WHERE_expresion, "DELETE FROM {0} WHERE {1}");
1790
        config.set(SQLConfig.DELETE_FROM_table, "DELETE FROM {0}");
1791
        config.set(SQLConfig.INSERT_INTO_table_columns_VALUES_values, "INSERT INTO {0} ( {1} ) VALUES ( {2} )");
1792
        config.set(SQLConfig.UPDATE_TABLE_STATISTICS_table, "VACUUM ANALYZE {0}");
1793
        config.set(SQLConfig.DROP_TABLE_table, "DROP TABLE {0}");
1794
        config.set(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table, "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_schema = {0} AND f_table_name = {1}");
1795
        config.set(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table, "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_name, {0}");
1796
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues_WHERE_expresion, "UPDATE {0} SET {1} WHERE {2}");
1797
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues, "UPDATE {0} SET {1}");
1798
        config.set(SQLConfig.GRANT_privileges_ON_table_TO_role, "GRANT {0} ON {1} TO {2}");
1799
    }
1800
    
1801
    @Override
1802
    public String default_schema() {
1803
        return config.getString(SQLConfig.default_schema);
1804
    }
1805
    
1806
    @Override
1807
    public String sqltype(int type, int p, int s) {
1808
        switch (type) {
1809
            case DataTypes.BOOLEAN:
1810
                return config.getString(SQLConfig.type_boolean);
1811
            case DataTypes.BYTE:
1812
                return config.getString(SQLConfig.type_byte);
1813
            case DataTypes.BYTEARRAY:
1814
                return config.getString(SQLConfig.type_bytearray);
1815
            case DataTypes.GEOMETRY:
1816
                return config.getString(SQLConfig.type_geometry);
1817
            case DataTypes.CHAR:
1818
                return config.getString(SQLConfig.type_char);
1819
            case DataTypes.DATE:
1820
                return config.getString(SQLConfig.type_date);
1821
            case DataTypes.DOUBLE:
1822
                  // FIXME: Si cargamos la capa "country" al exportarla a
1823
                  // SQLServer falla por:
1824
                  //  Error de desbordamiento aritm?tico al convertir float al tipo de datos numeric.
1825
                  // Al parecer la capa declara la columna sqkm_ctry como Numeric(12,6) y para 
1826
                  // Algeria intenta asignarle un valor de 2320972.0 y falla.
1827
                  // Habria que repasar el proveedor de shape.
1828
                
1829
//                if (p > 1) {
1830
//                    if (s < 0) {
1831
//                        return MessageFormat.format(config.getString(SQLConfig.type_numeric_p), p);
1832
//                    }
1833
//                    return MessageFormat.format(config.getString(SQLConfig.type_numeric_ps), p,s);
1834
//                }
1835
                return MessageFormat.format(config.getString(SQLConfig.type_double),p,s);
1836
            case DataTypes.BIGDECIMAL:
1837
                if (p < 1) {
1838
                    p = 20;
1839
                }
1840
                if (s < 0) {
1841
                    s = 10;
1842
                }
1843
                return MessageFormat.format(config.getString(SQLConfig.type_bigdecimal), p,s);
1844
            case DataTypes.FLOAT:
1845
                return MessageFormat.format(config.getString(SQLConfig.type_float), p,s);
1846
            case DataTypes.INT:
1847
                return MessageFormat.format(config.getString(SQLConfig.type_int), p,s);
1848
            case DataTypes.LONG:
1849
                return MessageFormat.format(config.getString(SQLConfig.type_long), p,s);
1850
            case DataTypes.STRING:
1851
                if (p < 0) {
1852
                    return config.getString(SQLConfig.type_string);
1853
                } else if (p < 4096) {
1854
                    return MessageFormat.format(config.getString(SQLConfig.type_string_p),p);
1855
                }
1856
                return config.getString(SQLConfig.type_string);
1857
            case DataTypes.TIME:
1858
                return config.getString(SQLConfig.type_time);
1859
            case DataTypes.TIMESTAMP:
1860
                return config.getString(SQLConfig.type_timestamp);
1861
            case DataTypes.VERSION:
1862
                return config.getString(SQLConfig.type_version);
1863
            case DataTypes.URI:
1864
                return config.getString(SQLConfig.type_URI);
1865
            case DataTypes.URL:
1866
                return config.getString(SQLConfig.type_URL);
1867
            case DataTypes.FILE:
1868
                return config.getString(SQLConfig.type_FILE);
1869
            case DataTypes.FOLDER:
1870
                return config.getString(SQLConfig.type_FOLDER);
1871
            default:
1872
                return null;
1873
        }
1874
    }
1875

    
1876
    private static Map<Pair<Integer,Integer>,String> sqlgeometrytypes = null;
1877
    
1878
    @Override
1879
    public Object sqlgeometrytype(int type, int subtype) {
1880
        // Devuelve un Object por que algunos gestores de BBDD utilizan
1881
        // identificadores numericos para el tipo y otros strings.
1882
        // Por defecto vamos a devolver strings.
1883
        if( sqlgeometrytypes==null ) {
1884
            sqlgeometrytypes = new HashMap<>();
1885
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM2D), "POINT");
1886
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM3D), "POINTZ");
1887
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM2DM), "POINTM");
1888
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM3DM), "POINTZM");
1889

    
1890
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM2D), "LINESTRING");
1891
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM3D), "LINESTRINGZ");
1892
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM2DM), "LINESTRINGM");
1893
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM3DM), "LINESTRINGZM");
1894

    
1895
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM2D), "POLYGON");
1896
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM3D), "POLYGONZ");
1897
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM2DM), "POLYGONM");
1898
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM3DM), "POLYGONZM");
1899

    
1900
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM2D), "MULTIPOINT");
1901
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM3D), "MULTIPOINTZ");
1902
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM2DM), "MULTIPOINTM");
1903
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM3DM), "MULTIPOINTZM");
1904

    
1905
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM2D), "MULTILINESTRING");
1906
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM3D), "MULTILINESTRINGZ");
1907
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM2DM), "MULTILINESTRINGM");
1908
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM3DM), "MULTILINESTRINGZM");
1909

    
1910
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM2D), "MULTIPOLYGON");
1911
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM3D), "MULTIPOLYGONZ");
1912
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM2DM), "MULTIPOLYGONM");
1913
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM3DM), "MULTIPOLYGONZM");
1914

    
1915
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2D), "GEOMETRY");
1916
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3D), "GEOMETRYZ");
1917
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2DM), "GEOMETRYM");
1918
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3DM), "GEOMETRYZM");
1919
        }
1920
        return sqlgeometrytypes.get(new ImmutablePair<>(type,subtype));
1921
    }
1922

    
1923
    @Override
1924
    public Object sqlgeometrydimension(int type, int subtype) {
1925
        // Devuelve un Object por que algunos gestortes de BBDD utilizan
1926
        // identificadores numericos para las dimensiones y otros strings.
1927
        // Por defecto vamos a devolver enteros.
1928
        switch(subtype) {
1929
            case Geometry.SUBTYPES.GEOM3D:
1930
                return 3;
1931
            case Geometry.SUBTYPES.GEOM2DM:
1932
                return 3;
1933
            case Geometry.SUBTYPES.GEOM3DM:
1934
                return 4;
1935
            case Geometry.SUBTYPES.GEOM2D:
1936
            default:
1937
                return 2;
1938
        }
1939
    }
1940
    
1941
    protected TableNameBuilder createTableNameBuilder() {
1942
        return new TableNameBuilderBase();
1943
    }
1944
    
1945
    protected SelectColumnBuilder createSelectColumnBuilder() {
1946
        return new SelectColumnBuilderBase();
1947
    }
1948
    
1949
    protected UpdateColumnBuilder createUpdateColumnBuilder() {
1950
        return new UpdateColumnBuilderBase();
1951
    }
1952
    
1953
    protected InsertColumnBuilder createInsertColumnBuilder() {
1954
        return new InsertColumnBuilderBase();
1955
    }
1956
    
1957
    protected OrderByBuilder createOrderByBuilder() {
1958
        return new OrderByBuilderBase();
1959
    }
1960

    
1961
    protected FromBuilder createFromBuilder() {
1962
        return new FromBuilderBase();
1963
    }
1964

    
1965
    protected SelectBuilder createSelectBuilder() {
1966
        return new SelectBuilderBase();
1967
    }
1968

    
1969
    protected UpdateBuilder createUpdateBuilder() {
1970
        return new UpdateBuilderBase();
1971
    }
1972

    
1973
    protected DeleteBuilder createDeleteBuilder() {
1974
        return new DeleteBuilderBase();
1975
    }
1976

    
1977
    protected GrantBuilder createGrantBuilder() {
1978
        return new GrantBuilderBase();
1979
    }
1980

    
1981
    protected GrantRoleBuilder createGrantRoleBuilder(TableNameBuilder table, String role) {
1982
        return new GrantRoleBuilderBase(table, role);
1983
    }
1984
    
1985
    protected DropTableBuilder createDropTableBuilder() {
1986
        return new DropTableBuilderBase();
1987
    }
1988

    
1989
    protected CreateTableBuilder createCreateTableBuilder() {
1990
        return new CreateTableBuilderBase();
1991
    }
1992

    
1993
    protected AlterTableBuilder createAlterTableBuilder() {
1994
        return new AlterTableBuilderBase();
1995
    }
1996

    
1997
    protected InsertBuilder createInsertBuilder() {
1998
        return new InsertBuilderBase();
1999
    }
2000

    
2001
    protected UpdateTableStatisticsBuilder createUpdateTableStatisticsBuilder() {
2002
        return new UpdateTableStatisticsBuilderBase();
2003
    }
2004

    
2005
    @Override
2006
    public SelectBuilder select() {
2007
        if (this.select == null) {
2008
            this.select = this.createSelectBuilder();
2009
        }
2010
        return this.select;
2011
    }
2012

    
2013
    @Override
2014
    public UpdateBuilder update() {
2015
        if (this.update == null) {
2016
            this.update = this.createUpdateBuilder();
2017
        }
2018
        return this.update;
2019
    }
2020

    
2021
    @Override
2022
    public UpdateTableStatisticsBuilder update_table_statistics() {
2023
        if (this.update_table_statistics == null) {
2024
            this.update_table_statistics = this.createUpdateTableStatisticsBuilder();
2025
        }
2026
        return this.update_table_statistics;
2027
    }
2028

    
2029
    @Override
2030
    public DropTableBuilder drop_table() {
2031
        if (this.drop_table == null) {
2032
            this.drop_table = this.createDropTableBuilder();
2033
        }
2034
        return this.drop_table;
2035
    }
2036

    
2037
    @Override
2038
    public DeleteBuilder delete() {
2039
        if (this.delete == null) {
2040
            this.delete = this.createDeleteBuilder();
2041
        }
2042
        return this.delete;
2043
    }
2044

    
2045
    @Override
2046
    public InsertBuilder insert() {
2047
        if (this.insert == null) {
2048
            this.insert = this.createInsertBuilder();
2049
        }
2050
        return this.insert;
2051
    }
2052

    
2053
    @Override
2054
    public AlterTableBuilder alter_table() {
2055
        if (this.alter_table == null) {
2056
            this.alter_table = this.createAlterTableBuilder();
2057
        }
2058
        return this.alter_table;
2059
    }
2060

    
2061
    @Override
2062
    public CreateTableBuilder create_table() {
2063
        if (this.create_table == null) {
2064
            this.create_table = this.createCreateTableBuilder();
2065
        }
2066
        return this.create_table;
2067
    }
2068

    
2069
    @Override
2070
    public GrantBuilder grant() {
2071
        if (this.grant == null) {
2072
            this.grant = this.createGrantBuilder();
2073
        }
2074
        return this.grant;
2075
    }
2076

    
2077
    @Override
2078
    public void accept(Visitor visitor, VisitorFilter filter) {
2079
        if (this.select != null) {
2080
            this.select.accept(visitor, filter);
2081
        }
2082
        if (this.update != null) {
2083
            this.update.accept(visitor, filter);
2084
        }
2085
        if (this.insert != null) {
2086
            this.insert.accept(visitor, filter);
2087
        }
2088
        if (this.delete != null) {
2089
            this.delete.accept(visitor, filter);
2090
        }
2091
        if (this.alter_table != null) {
2092
            this.alter_table.accept(visitor, filter);
2093
        }
2094
        if (this.create_table != null) {
2095
            this.create_table.accept(visitor, filter);
2096
        }
2097
        if (this.drop_table != null) {
2098
            this.drop_table.accept(visitor, filter);
2099
        }
2100
    }
2101

    
2102
    
2103
    @Override
2104
    public String toString() {
2105
        if (this.select != null) {
2106
            return this.select.toString();
2107
        }
2108
        if (this.update != null) {
2109
            return this.update.toString();
2110
        }
2111
        if (this.insert != null) {
2112
            return this.insert.toString();
2113
        }
2114
        if (this.delete != null) {
2115
            return this.delete.toString();
2116
        }
2117
        if (this.alter_table != null) {
2118
            return this.alter_table.toString();
2119
        }
2120
        if (this.create_table != null) {
2121
            return this.create_table.toString();
2122
        }
2123
        if (this.drop_table != null) {
2124
            return this.drop_table.toString();
2125
        }
2126
        if (this.update_table_statistics != null) {
2127
            return this.update_table_statistics.toString();
2128
        }
2129
        if ( this.value != null ) {
2130
            return this.value.toString();
2131
        }
2132
        return ""; 
2133
    }
2134

    
2135
    @Override
2136
    public Function ST_UnionAggregate(Value geom) {
2137
        return function("ST_UnionAggregate", config.getString(SQLConfig.ST_UnionAggregate), geom);
2138
    }
2139

    
2140
    @Override
2141
    public Function ST_ExtentAggregate(Value geom) {
2142
        return function("ST_ExtentAggregate", config.getString(SQLConfig.ST_ExtentAggregate), geom);
2143
    }
2144

    
2145
    @Override
2146
    public CountBuilder count() {
2147
        return new CountBuilderBase();
2148
    }
2149

    
2150
}