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

History | View | Annotate | Download (73.6 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.dal.feature.FeatureAttributeDescriptor;
35
import org.gvsig.fmap.dal.feature.spi.ExpressionBuilderBase.AbstractValue;
36
import org.gvsig.fmap.geom.Geometry;
37
import org.slf4j.Logger;
38
import org.slf4j.LoggerFactory;
39

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

    
56
    public class TableNameBuilderBase implements TableNameBuilder {
57

    
58
        public String tableName;
59
        public String schemaName;
60
        private String databaseName;
61

    
62
        public TableNameBuilderBase() {
63
        }
64

    
65
        @Override
66
        public void accept(Visitor visitor, VisitorFilter filter) {
67
            if( filter.accept(this) ) {
68
                visitor.visit(this);
69
            }
70
        }
71

    
72
        @Override
73
        public TableNameBuilder database(String name) {
74
            this.databaseName = name;
75
            return this;
76
        }
77

    
78
        @Override
79
        public TableNameBuilder schema(String name) {
80
            if( supportSchemas() ) {
81
                this.schemaName = name;
82
            }
83
            return this;
84
        }
85

    
86
        @Override
87
        public TableNameBuilder name(String name) {
88
            this.tableName = name;
89
            return this;
90
        }
91

    
92
        @Override
93
        public String getDatabase() {
94
            return this.databaseName;
95
        }
96

    
97
        @Override
98
        public String getSchema() {
99
            return this.schemaName;
100
        }
101

    
102
        @Override
103
        public String getName() {
104
            return this.tableName;
105
        }
106
        
107
        @Override
108
        public boolean has_schema() {
109
            if( !supportSchemas() ) {
110
                return false;
111
            }
112
            return !StringUtils.isEmpty(this.schemaName);
113
        }
114

    
115
        @Override
116
        public boolean has_database() {
117
            return !StringUtils.isEmpty(this.databaseName);
118
        }
119
        
120
        @Override
121
        public String toString() {
122
            if( this.has_database()) {
123
                if( this.has_schema()) {
124
                    return identifier(this.databaseName) + "." + 
125
                           identifier(this.schemaName) + "." + 
126
                           identifier(this.tableName);
127
                }
128
            } else {
129
                if( this.has_schema()) {
130
                    return identifier(this.schemaName) + "." + 
131
                           identifier(this.tableName);
132
                }                
133
            }
134
            return identifier(this.tableName);
135
        }
136

    
137
    }
138

    
139
    public class CountBuilderBase extends AbstractValue implements CountBuilder {
140

    
141
        protected Value value;
142
        protected boolean distinct;
143
        protected boolean all ;
144
        
145
        public CountBuilderBase() {
146
            this.value = null;
147
            this.distinct = false;
148
            this.all = false;
149
        }
150
        
151
        @Override
152
        public CountBuilder all() {
153
            this.all = true;
154
            return this;
155
        }
156

    
157
        @Override
158
        public CountBuilder column(Value value) {
159
            this.value = value;
160
            return this;
161
        }
162

    
163
        @Override
164
        public CountBuilder distinct() {
165
            this.distinct = true;
166
            return this;
167
        }
168

    
169
        @Override
170
        public String toString() {
171
            if( this.all ) {
172
                return MessageFormat.format(
173
                    config.getString(SQLConfig.count),
174
                    "*"
175
                );
176
            }
177
            if( this.distinct ) {
178
                return MessageFormat.format(
179
                    config.getString(SQLConfig.count_distinct),
180
                    value.toString()
181
                );
182
            }
183
            return MessageFormat.format(
184
                config.getString(SQLConfig.count),
185
                value.toString()
186
            );
187
        }
188
        
189
        
190
    }
191
    
192
    public class FromBuilderBase implements FromBuilder {
193

    
194
        protected TableNameBuilder tableName= null;
195
        private String subquery = null;
196
        private String passthrough = null;
197

    
198
        @Override
199
        public TableNameBuilder table() {
200
            if( tableName == null ) {
201
                this.tableName = createTableNameBuilder();
202
            }
203
            return this.tableName;
204
        }
205

    
206
        @Override
207
        public void accept(Visitor visitor, VisitorFilter filter) {
208
            if( filter.accept(this) ) {
209
                visitor.visit(this);
210
            }
211
            if( this.tableName != null ) {
212
                this.tableName.accept(visitor, filter);
213
            }
214
        }
215

    
216
        @Override
217
        public FromBuilder custom(String passthrough) {
218
            this.passthrough = passthrough;
219
            return this;
220
        }
221

    
222
        @Override
223
        public FromBuilder subquery(String subquery) {
224
            this.subquery = subquery;
225
            return this;
226
        }
227
        
228
        @Override
229
        public String toString() {
230
            if( ! StringUtils.isEmpty(passthrough) ) {
231
                return passthrough;
232
            }
233
            if( ! StringUtils.isEmpty(subquery) ) {
234
                return "( " + this.subquery + ") as _subquery_alias_ ";
235
            }
236
            return this.tableName.toString();
237
        }
238

    
239
    }
240

    
241
    public class SelectColumnBuilderBase implements SelectColumnBuilder {
242

    
243
        private Variable name = null;
244
        private String alias = null;
245
        private Value value = null;
246
        private boolean asGeometry = false;
247
        
248
        @Override
249
        public void accept(Visitor visitor, VisitorFilter filter) {
250
            if( filter.accept(this) ) {
251
                visitor.visit(this);
252
            }
253
            if( this.name != null ) {
254
                this.name.accept(visitor, filter);
255
            }
256
            if( this.value != null ) {
257
                this.value.accept(visitor, filter);
258
            }
259
        }
260

    
261
        @Override
262
        public SelectColumnBuilder name(String name) {
263
            String quote = config.getString(Config.quote_for_identifiers);
264
            if (name.startsWith(quote)) {
265
                // Remove quotes
266
                name = name.substring(1, name.length() - 1);
267
            }
268
            this.name = variable(name);
269
            this.value = null;
270
            this.asGeometry = false;
271
            return this;
272
        }
273

    
274
        @Override
275
        public SelectColumnBuilder all() {
276
            this.name = null;
277
            this.value = custom("*");
278
            this.asGeometry = false;
279
            return this;
280
        }
281
        
282
        @Override
283
        public SelectColumnBuilder as_geometry() {
284
            this.asGeometry = true;
285
            return this;
286
        }
287
       
288
        @Override
289
        public SelectColumnBuilder value(Value value) {
290
            this.value = value;
291
            this.name = null;
292
            return this;
293
        }
294

    
295
        @Override
296
        public SelectColumnBuilder as(String alias) {
297
            this.alias = alias;
298
            return this;
299
        }
300

    
301
        @Override
302
        public String getName() {
303
            return this.name.getName();
304
        }
305
        
306
        @Override
307
        public String getAlias() {
308
            return this.alias;
309
        }
310
        
311
        @Override
312
        public String getValue() {
313
            return this.alias;
314
        }
315

    
316
        @Override
317
        public String toString() {
318
            StringBuilder builder = new StringBuilder();
319
            if( this.asGeometry ) {
320
                builder.append(getAsGeometry(this.name).toString());
321
            } else {
322
                if( this.name != null ) {
323
                    builder.append(this.name.toString());
324
                } else {
325
                    builder.append(this.value.toString());
326
                }
327
            }
328
            if( this.alias != null ) {
329
                builder.append(" AS ");
330
                builder.append(identifier(this.alias));
331
            }
332
            return builder.toString();
333
        }
334
    }
335

    
336
    public class OrderByBuilderBase implements OrderByBuilder {
337
        protected String value;
338
        protected String custom;
339
        protected boolean ascending;
340
        
341
        public OrderByBuilderBase() {
342
            this.ascending = true;
343
        }
344

    
345
        @Override
346
        public void accept(Visitor visitor, VisitorFilter filter) {
347
            if( filter.accept(this) ) {
348
                visitor.visit(this);
349
            }
350
        }
351

    
352
        @Override
353
        public OrderByBuilder column(String name) {
354
            this.value = name;
355
            return this;
356
        }
357

    
358
        @Override
359
        public OrderByBuilder custom(String order) {
360
            this.custom = order;
361
            return this;
362
        }
363

    
364
        @Override
365
        public OrderByBuilder ascending() {
366
            this.ascending = true;
367
            return this;
368
        }
369

    
370
        @Override
371
        public OrderByBuilder ascending(boolean asc) {
372
            this.ascending = asc;
373
            return this;
374
        }
375

    
376
        @Override
377
        public OrderByBuilder descending() {
378
            this.ascending = false;
379
            return this;
380
        }
381

    
382
        @Override
383
        public String toString() {
384
            if( !StringUtils.isEmpty(this.custom) ) {
385
                return this.custom;
386
            }
387
            if( this.ascending ) {
388
                return identifier(this.value) + " ASC";
389
            }
390
            return identifier(this.value) + " DESC";
391
        }
392
    }
393
    
394
    public class SelectBuilderBase implements SelectBuilder {
395

    
396
        protected FromBuilder from;
397
        protected ExpressionBuilder where;
398
        protected long limit = -1;
399
        protected long offset = -1;
400
        protected List<SelectColumnBuilder> columns;
401
        protected List<OrderByBuilder> order_by;
402
        protected boolean distinct;
403

    
404
        public SelectBuilderBase() {
405
            this.columns = new ArrayList<>();
406
            this.distinct = false;
407
        }
408

    
409
        @Override
410
        public void accept(Visitor visitor, VisitorFilter filter) {
411
            if( filter.accept(this) ) {
412
                visitor.visit(this);
413
            }
414
            for (SelectColumnBuilder column : columns) {
415
                column.accept(visitor,filter);
416
            }
417
            if( this.has_from() ) {
418
                this.from.accept(visitor,filter);
419
            }
420
            if( this.has_where() ) {
421
                this.where.accept(visitor,filter);
422
            }
423
            if( this.has_order_by() ) {
424
                for (OrderByBuilder order : order_by) {
425
                    order.accept(visitor,filter);
426
                }
427
            }
428
        }
429

    
430
        @Override
431
        public SelectBuilder distinct() {
432
            this.distinct = true;
433
            return this;
434
        }
435
        
436
        @Override
437
        public SelectColumnBuilder column() {
438
            SelectColumnBuilder builder = createSelectColumnBuilder();
439
            this.columns.add(builder);
440
            return builder;
441
        }
442

    
443
        @Override
444
        public boolean has_column(String name) {
445
            for (SelectColumnBuilder column : columns) {
446
                if( name.equals(column.getName()) ) {
447
                    return true;
448
                }
449
            }
450
            return false;
451
        }
452

    
453
        @Override
454
        public FromBuilder from() {
455
            if (this.from == null) {
456
                this.from = createFromBuilder();
457
            }
458
            return this.from;
459
        }
460

    
461
        @Override
462
        public boolean has_from() {
463
            return this.from != null;
464
        }
465
        
466
        @Override
467
        public ExpressionBuilder where() {
468
            if (this.where == null) {
469
                this.where = createExpressionBuilder();
470
            }
471
            return this.where;
472
        }
473

    
474
        @Override
475
        public boolean has_where() {
476
            if( this.where == null ) {
477
                return false;
478
            }
479
            return this.where.getValue() != null;
480
        }
481
        
482
        @Override
483
        public SelectBuilder limit(long limit) {
484
            this.limit = limit;
485
            return this;
486
        }
487

    
488
        @Override
489
        public boolean has_limit() {
490
            return this.limit > 0;
491
        }
492

    
493
        @Override
494
        public SelectBuilder offset(long offset) {
495
            this.offset = offset;
496
            return this;
497
        }
498

    
499
        @Override
500
        public boolean has_offset() {
501
            return this.offset > 0;
502
        }
503

    
504
        @Override
505
        public OrderByBuilder order_by() {
506
            if( this.order_by == null ) {
507
                this.order_by = new ArrayList<>();
508
            }
509
            OrderByBuilder order = createOrderByBuilder();
510
            this.order_by.add(order);
511
            return order;
512
        }
513

    
514
        @Override
515
        public boolean has_order_by() {
516
            if( this.order_by == null ) {
517
                return false;
518
            }
519
            return !this.order_by.isEmpty();
520
        }
521
        
522
        protected boolean isValid(StringBuilder message) {
523
            if( message == null ) {
524
                message = new StringBuilder();
525
            }
526
            if( this.has_offset() && !this.has_order_by() ) {
527
                // Algunos gestores de BBDD requieren que se especifique un
528
                // orden para poder usar OFFSET. Como eso parece buena idea para
529
                // asegurar que siempre tengamos los mismo resultados, lo exijimos
530
                // siempre.
531
                message.append("Can't use OFFSET without an ORDER BY.");
532
                return false;
533
            }
534
            return true;
535
        }
536
        
537
        @Override
538
        public String toString() {
539
            StringBuilder builder = new StringBuilder();
540
            if( !this.isValid(builder) ) {
541
                throw new IllegalStateException(builder.toString());
542
            }
543
            builder.append("SELECT ");
544
            if( this.distinct ) {
545
                builder.append("DISTINCT ");
546
            }
547
            boolean first = true;
548
            for (SelectColumnBuilder column : columns) {
549
                if (first) {
550
                    first = false;
551
                } else {
552
                    builder.append(", ");
553
                }
554
                builder.append(column.toString());
555
            }
556

    
557
            if ( this.has_from() ) {
558
                builder.append(" FROM ");
559
                builder.append(this.from.toString());
560
            }
561
            if ( this.has_where() ) {
562
                builder.append(" WHERE ");
563
                builder.append(this.where.toString());
564
            }
565
            
566
            if( this.has_order_by() ) {
567
                builder.append(" ORDER BY ");
568
                first = true;
569
                for (OrderByBuilder item : this.order_by) {
570
                    if (first) {
571
                        first = false;
572
                    } else {
573
                        builder.append(", ");
574
                    }
575
                    builder.append(item.toString());                    
576
                }   
577
            }
578
            
579
            if ( this.has_limit() ) {
580
                builder.append(" LIMIT ");
581
                builder.append(this.limit);
582
            }
583
            if ( this.has_offset() ) {
584
                builder.append(" OFFSET ");
585
                builder.append(this.offset);
586
            }
587
            return builder.toString();
588

    
589
        }
590
    }
591

    
592
    public class DropTableBuilderBase implements DropTableBuilder {
593

    
594
        protected TableNameBuilder table;
595

    
596
        @Override
597
        public TableNameBuilder table() {
598
            if( table == null ) {
599
                table = createTableNameBuilder();
600
            }
601
            return table;
602
        }
603

    
604
        @Override
605
        public void accept(Visitor visitor, VisitorFilter filter) {
606
            if( filter.accept(this) ) {
607
                visitor.visit(this);
608
            }
609
            this.table.accept(visitor,filter);
610
        }
611
        
612
        @Override
613
        public String toString() {
614
            StringBuilder builder = new StringBuilder();
615
            boolean first = true;
616
            for (String sql : toStrings()) {
617
                if( StringUtils.isEmpty(sql) ) {
618
                    continue;
619
                }
620
                if (first) {
621
                    first = false;
622
                } else {
623
                    builder.append("; ");
624
                }
625
                builder.append(sql);
626
            }
627
            return builder.toString();
628
        }
629

    
630
        @Override
631
        public List<String> toStrings() {
632
            List<String> sqls = new ArrayList<>();
633

    
634
            sqls.add(
635
                    MessageFormat.format(
636
                            config.getString(SQLConfig.DROP_TABLE_table),
637
                            this.table.toString()
638
                    )
639
            );
640
            String sql;
641
            if( config.has_functionality(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table) ) {
642
                if (this.table.has_schema()) {
643
                    sql = MessageFormat.format(
644
                            config.getString(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table),
645
                            string(this.table.getSchema()),
646
                            string(this.table.getName())
647
                    );
648
                } else {
649
                    sql = MessageFormat.format(
650
                            config.getString(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table),
651
                            identifier(this.table.getName())
652
                    );
653
                }
654
                if( !StringUtils.isEmpty(sql) ) {
655
                    sqls.add(sql);
656
                }
657
            }
658
            return sqls;
659
        }
660
    }
661

    
662
    public class GrantRoleBuilderBase implements GrantRoleBuilder {
663
        protected TableNameBuilder table;
664
        protected String role;
665
        protected Set<Privilege> privileges;
666

    
667
        public GrantRoleBuilderBase(TableNameBuilder table, String role) {
668
            this.table = table;
669
            this.role = role;
670
            this.privileges = new HashSet<>();
671
        }
672

    
673
        @Override
674
        public GrantRoleBuilder privilege(Privilege privilege) {
675
            privileges.add(privilege);
676
            return this;
677
        }
678
        
679
        @Override
680
        public GrantRoleBuilder select() {
681
             privileges.add(Privilege.SELECT);
682
            return this;
683
        }
684

    
685
        @Override
686
        public GrantRoleBuilder update() {
687
             privileges.add(Privilege.UPDATE);
688
            return this;
689
        }
690

    
691
        @Override
692
        public GrantRoleBuilder insert() {
693
            privileges.add(Privilege.INSERT);
694
            return this;
695
        }
696

    
697
        @Override
698
        public GrantRoleBuilder delete() {
699
            privileges.add(Privilege.DELETE);
700
            return this;
701
        }
702

    
703
        @Override
704
        public GrantRoleBuilder truncate() {
705
            privileges.add(Privilege.TRUNCATE);
706
            return this;
707
        }
708

    
709
        @Override
710
        public GrantRoleBuilder reference() {
711
            privileges.add(Privilege.REFERENCE);
712
            return this;
713
        }
714

    
715
        @Override
716
        public GrantRoleBuilder trigger() {
717
            privileges.add(Privilege.TRIGGER);
718
            return this;
719
        }
720

    
721
        @Override
722
        public GrantRoleBuilder all() {
723
            privileges.add(Privilege.ALL);
724
            return this;
725
        }
726

    
727
        protected String getPrivilegeName(Privilege privilege) {
728
            switch(privilege) {
729
                case DELETE:
730
                    return "DELETE";
731
                case INSERT:
732
                    return "INSERT";
733
                case REFERENCE:
734
                    return "REFERENCE";
735
                case SELECT:
736
                    return "SELECT";
737
                case TRIGGER:
738
                    return "TRIGGER";
739
                case TRUNCATE:
740
                    return "TRUNCATE";
741
                case UPDATE:
742
                    return "UPDATE";
743
                case ALL:
744
                default:
745
                    return "ALL";
746
            }
747
        }
748
        
749
        @Override
750
        public String toString() {
751
            StringBuilder builder = new StringBuilder();
752
            boolean first = true;
753
            for (Privilege privilege : privileges) {
754
                if (first) {
755
                    first = false;
756
                } else {
757
                    builder.append(", ");
758
                }
759
                builder.append( this.getPrivilegeName(privilege));
760
            }
761
            String sql = MessageFormat.format(
762
                    config.getString(SQLConfig.GRANT_privileges_ON_table_TO_role),
763
                    builder.toString(),
764
                    table.toString(),
765
                    role
766
            );
767
            return sql;
768
        }
769
    }
770
    
771
    public class GrantBuilderBase implements GrantBuilder {
772

    
773
        protected TableNameBuilder table;
774
        protected Map<String, GrantRoleBuilder> roles;
775

    
776
        public GrantBuilderBase() {
777
            this.roles = new HashMap<>();
778
        }
779
        
780
        @Override
781
        public TableNameBuilder table() {
782
            if( table == null ) {
783
                table = createTableNameBuilder();
784
            }
785
            return table;
786
        }
787

    
788
        @Override
789
        public void accept(Visitor visitor, VisitorFilter filter) {
790
            if( filter.accept(this) ) {
791
                visitor.visit(this);
792
            }
793
            if( this.table!= null ) {
794
                this.table.accept(visitor,filter);
795
            }
796
        }
797
        
798
        @Override
799
        public GrantRoleBuilder role(String role) {
800
            GrantRoleBuilder roleBuilder = this.roles.get(role);
801
            if( roleBuilder == null ) {
802
                roleBuilder = createGrantRoleBuilder(this.table(), role);
803
                this.roles.put(role, roleBuilder);
804
            }
805
            return roleBuilder;
806
        }
807

    
808
        @Override
809
        public String toString() {
810
            StringBuilder builder = new StringBuilder();
811
            boolean first = true;
812
            for (String sql : toStrings()) {
813
                if( StringUtils.isEmpty(sql) ) {
814
                    continue;
815
                }
816
                if (first) {
817
                    first = false;
818
                } else {
819
                    builder.append("; ");
820
                }
821
                builder.append(sql);
822
            }
823
            return builder.toString();
824
        }
825

    
826
        @Override
827
        public List<String> toStrings() {
828
            List<String> sqls = new ArrayList<>();
829
            for (GrantRoleBuilder role : roles.values()) {
830
                sqls.add(role.toString());
831
            }
832
            return sqls;
833
        }
834
    }
835

    
836
    public class UpdateColumnBuilderBase extends InsertColumnBuilderBase implements UpdateColumnBuilder {
837
        
838
        public UpdateColumnBuilderBase() {
839
            super();
840
        }
841

    
842
        @Override
843
        public UpdateColumnBuilder name(String name) {
844
            return (UpdateColumnBuilder) super.name(name);
845
        }
846

    
847
        @Override
848
        public UpdateColumnBuilder with_value(Value value) {
849
            return (UpdateColumnBuilder) super.with_value(value);
850
        }
851
        
852
    }
853
    
854
    public class UpdateBuilderBase implements UpdateBuilder {
855

    
856
        protected ExpressionBuilder where;
857
        protected List<UpdateColumnBuilder> columns;
858
        protected TableNameBuilder table;
859

    
860
        public UpdateBuilderBase() {
861
            this.columns = new ArrayList<>();
862
        }
863

    
864
        @Override
865
        public void accept(Visitor visitor, VisitorFilter filter) {
866
            if( filter.accept(this) ) {
867
                visitor.visit(this);
868
            }
869
            if( this.table != null ) {
870
                this.table.accept(visitor, filter);
871
            }
872
            for (UpdateColumnBuilder column : columns) {
873
                column.accept(visitor, filter);
874
            }
875
            if( this.has_where() ) {
876
                this.where.accept(visitor, filter);
877
            }
878
        }
879

    
880
        @Override
881
        public ExpressionBuilder where() {
882
            if (this.where == null) {
883
                this.where = createExpressionBuilder();
884
            }
885
            return this.where;
886
        }
887

    
888
        @Override
889
        public TableNameBuilder table() {
890
            if( table == null ) {
891
                table = createTableNameBuilder();
892
            }
893
            return table;
894
        }
895

    
896
        @Override
897
        public UpdateColumnBuilder column() {
898
            UpdateColumnBuilder column = createUpdateColumnBuilder();
899
            this.columns.add(column);
900
            return column;
901
        }
902
        
903
        @Override
904
        public boolean has_where() {
905
            return this.where != null;
906
        }
907

    
908
        @Override
909
        public String toString() {
910
            /*
911
             * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
912
             * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
913
             * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
914
             * output_expression [ AS output_name ] [, ...] ]
915
             */
916
            StringBuilder columnsAndValues = new StringBuilder();
917

    
918
            boolean first = true;
919
            for (UpdateColumnBuilder column : columns) {
920
                if (first) {
921
                    first = false;
922
                } else {
923
                    columnsAndValues.append(", ");
924
                }
925
                columnsAndValues.append(identifier(column.getName()));
926
                columnsAndValues.append(" = ");
927
                columnsAndValues.append(column.getValue().toString());
928
            }
929
            
930
            String sql;
931
            if ( this.has_where() ) {
932
                sql = MessageFormat.format(
933
                        config.getString(SQLConfig.UPDATE_table_SET_columnsAndValues_WHERE_expresion),
934
                        this.table.toString(),
935
                        columnsAndValues.toString(),
936
                        this.where.toString()
937
                );
938
            } else {
939
                sql = MessageFormat.format(
940
                        config.getString(SQLConfig.UPDATE_table_SET_columnsAndValues),
941
                        this.table.toString(),
942
                        columnsAndValues.toString()
943
                );
944
            }
945
            return sql;
946
        }
947
    }
948

    
949
    public class DeleteBuilderBase implements DeleteBuilder {
950

    
951
        protected ExpressionBuilder where;
952
        protected TableNameBuilder table;
953

    
954
        public DeleteBuilderBase() {
955
        }
956

    
957
        @Override
958
        public void accept(Visitor visitor, VisitorFilter filter) {
959
            if( filter.accept(this) ) {
960
                visitor.visit(this);
961
            }
962
            if( this.table != null ) {
963
                this.table.accept(visitor, filter);
964
            }
965
            if( this.has_where() ) {
966
                this.where.accept(visitor, filter);
967
            }
968
        }
969

    
970
        @Override
971
        public ExpressionBuilder where() {
972
            if (this.where == null) {
973
                this.where = createExpressionBuilder();
974
            }
975
            return this.where;
976
        }
977

    
978
        @Override
979
        public TableNameBuilder table() {
980
            if( table == null ) {
981
                table = createTableNameBuilder();
982
            }
983
            return table;
984
        }
985

    
986
        @Override
987
        public boolean has_where() {
988
            return this.where != null;
989
        }
990

    
991
        @Override
992
        public String toString() {
993
            /*
994
             * DELETE FROM table_name
995
             * WHERE some_column=some_value; 
996
             */
997
            String sql;
998
            if( this.has_where() ) {
999
                sql = MessageFormat.format(
1000
                        config.getString(SQLConfig.DELETE_FROM_table_WHERE_expresion),
1001
                        this.table.toString(),
1002
                        this.where.toString()
1003
                );
1004
            } else {
1005
                sql = MessageFormat.format(
1006
                        config.getString(SQLConfig.DELETE_FROM_table),
1007
                        this.table.toString()
1008
                );
1009
            }
1010
            return sql;
1011
        }
1012
    }
1013

    
1014
    public class CreateIndexBuilderBase implements CreateIndexBuilder {
1015

    
1016
        protected boolean ifNotExist = false;
1017
        protected boolean isUnique = false;
1018
        protected String indexName;
1019
        protected boolean isSpatial = false;
1020
        protected TableNameBuilder table;
1021
        protected final List<String> columns;
1022
        
1023
        public CreateIndexBuilderBase() {
1024
            this.columns = new ArrayList<>();
1025
        }
1026
        
1027
        @Override
1028
        public CreateIndexBuilder unique() {
1029
            this.isUnique = true;
1030
            return this;
1031
        }
1032

    
1033
        @Override
1034
        public CreateIndexBuilder if_not_exist() {
1035
            this.ifNotExist = true;
1036
            return this;
1037
        }
1038

    
1039
        @Override
1040
        public CreateIndexBuilder name(String name) {
1041
            this.indexName = name;
1042
            return this;
1043
        }
1044

    
1045
        @Override
1046
        public CreateIndexBuilder spatial() {
1047
            this.isSpatial = true;
1048
            return this;
1049
        }
1050

    
1051
        @Override
1052
        public CreateIndexBuilder column(String name) {
1053
            this.columns.add(name);
1054
            return this;
1055
        }
1056

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

    
1065
        @Override
1066
        public void accept(Visitor visitor, VisitorFilter filter) {
1067
            if( filter.accept(this) ) {
1068
                visitor.visit(this);
1069
            }
1070
            if( this.table != null ) {
1071
                this.table.accept(visitor, filter);
1072
            }
1073
        }
1074
        
1075
        @Override
1076
        public List<String> toStrings() {
1077
            StringBuilder builder = new StringBuilder();
1078
            builder.append("CREATE ");
1079
            if( this.isUnique ) {
1080
                builder.append("UNIQUE ");
1081
            }
1082
            builder.append("INDEX ");
1083
            if( this.ifNotExist ) {
1084
                builder.append("IF NOT EXISTS ");
1085
            }
1086
            builder.append(identifier(this.indexName));
1087
            builder.append(" ON ");
1088
            builder.append(this.table.toString());
1089
            if( this.isSpatial ) {
1090
                builder.append(" USING GIST ");
1091
            }
1092
            builder.append(" ( ");
1093
            boolean is_first_column = true;
1094
            for( String column : this.columns) {
1095
                if( is_first_column ) {
1096
                    is_first_column = false;
1097
                } else {
1098
                    builder.append(", ");
1099
                }
1100
                builder.append(column);
1101
            }
1102
            builder.append(" )");
1103
            
1104
            List<String> sqls = new ArrayList<>();
1105
            sqls.add(builder.toString());
1106
            return sqls;
1107
        }
1108

    
1109
    }
1110
    
1111
    public class AlterTableBuilderBase implements AlterTableBuilder {
1112

    
1113
        protected TableNameBuilder table;
1114
        protected List<String> drops;
1115
        protected List<ColumnDescriptor> adds;
1116
        protected List<ColumnDescriptor> alters;
1117
        protected List<Pair<String,String>> renames;
1118

    
1119
        public AlterTableBuilderBase() {
1120
            this.drops = new ArrayList<>();
1121
            this.adds = new ArrayList<>();
1122
            this.alters = new ArrayList<>();
1123
            this.renames = new ArrayList<>();
1124
        }
1125

    
1126
        @Override
1127
        public boolean isEmpty() {
1128
            return this.drops.isEmpty() && 
1129
                this.adds.isEmpty() && 
1130
                this.alters.isEmpty() && 
1131
                this.renames.isEmpty();
1132
        }
1133
        
1134
        @Override
1135
        public void accept(Visitor visitor, VisitorFilter filter) {
1136
            if( filter.accept(this) ) {
1137
                visitor.visit(this);
1138
            }
1139
            if( this.table != null ) {
1140
                this.table.accept(visitor, filter);
1141
            }
1142
        }
1143

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

    
1152
        @Override
1153
        public AlterTableBuilder drop_column(String columnName) {
1154
            this.drops.add(columnName);
1155
            return this;
1156
        }
1157
        
1158
        @Override
1159
        public AlterTableBuilder add_column(FeatureAttributeDescriptor fad) {
1160
            this.adds.add(column(fad).getDescriptor());
1161
            return this;            
1162
        }
1163

    
1164
        @Override
1165
        public AlterTableBuilder add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1166
            if (isPk || isAutomatic) {
1167
                allowNulls = false;
1168
            }
1169
            this.adds.add(new ColumnDescriptorBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
1170
            return this;
1171
        }
1172

    
1173
        @Override
1174
        public AlterTableBuilder add_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
1175
            if( StringUtils.isEmpty(columnName) ) {
1176
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1177
            }
1178
            this.adds.add(new ColumnDescriptorBase(columnName, type, subtype, proj, isIndexed, allowNulls));
1179
            return this;
1180
        }
1181

    
1182
        @Override
1183
        public AlterTableBuilder add_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
1184
            if( StringUtils.isEmpty(columnName) ) {
1185
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1186
            }
1187
            this.adds.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
1188
            return this;
1189
        }
1190
        
1191
        @Override
1192
        public AlterTableBuilder alter_column(FeatureAttributeDescriptor fad) {
1193
            this.alters.add(column(fad).getDescriptor());
1194
            return this;            
1195
        }
1196
        
1197
        @Override
1198
        public AlterTableBuilder alter_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1199
            if (isPk || isAutomatic) {
1200
                allowNulls = false;
1201
            }
1202
            this.alters.add(new ColumnDescriptorBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
1203
            return this;
1204
        }
1205

    
1206
        @Override
1207
        public AlterTableBuilder alter_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
1208
            if( StringUtils.isEmpty(columnName) ) {
1209
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1210
            }
1211
            this.alters.add(new ColumnDescriptorBase(columnName, type, subtype, proj, isIndexed, allowNulls));
1212
            return this;
1213
        }
1214

    
1215
        @Override
1216
        public AlterTableBuilder alter_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
1217
            if( StringUtils.isEmpty(columnName) ) {
1218
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1219
            }
1220
            this.alters.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
1221
            return this;
1222
        }
1223

    
1224
        @Override
1225
        public AlterTableBuilder rename_column(String source, String target) {
1226
            this.renames.add(new ImmutablePair(source, target));
1227
            return this;
1228
        }
1229

    
1230
        @Override
1231
        public String toString() {
1232
            StringBuilder builder = new StringBuilder();
1233
            boolean first = true;
1234
            for (String sql : toStrings()) {
1235
                if( StringUtils.isEmpty(sql) ) {
1236
                    continue;
1237
                }
1238
                if (first) {
1239
                    first = false;
1240
                } else {
1241
                    builder.append("; ");
1242
                }
1243
                builder.append(sql);
1244
            }
1245
            return builder.toString();
1246
        }
1247

    
1248
        @Override
1249
        public List<String> toStrings() {
1250
            List<String> sqls = new ArrayList<>();
1251
            if( this.isEmpty() ) {
1252
                return sqls;
1253
            }
1254
            for (String column : drops) {
1255
                StringBuilder builder = new StringBuilder();
1256
                builder.append("ALTER TABLE ");
1257
                builder.append(this.table.toString());
1258
                builder.append(" DROP COLUMN IF EXISTS ");
1259
                builder.append(identifier(column)); 
1260
                sqls.add(builder.toString());
1261
            }
1262
            for (ColumnDescriptor column : adds) {
1263
                StringBuilder builder = new StringBuilder();
1264
                builder.append("ALTER TABLE ");
1265
                builder.append(this.table.toString());
1266
                builder.append(" ADD COLUMN ");
1267
                builder.append(identifier(column.getName())); 
1268
                builder.append(" ");
1269
                if( column.getType() == DataTypes.INT && column.isAutomatic() ) {
1270
                    builder.append(" SERIAL");
1271
                } else {
1272
                    builder.append(
1273
                        sqltype(
1274
                            column.getType(), 
1275
                            column.getPrecision(), 
1276
                            column.getSize(),
1277
                            column.getGeometryType(),
1278
                            column.getGeometrySubtype()
1279
                        )
1280
                    );
1281
                }
1282
                if (column.getDefaultValue() == null) {
1283
                    if (column.allowNulls()) {
1284
                        builder.append(" DEFAULT NULL");
1285
                    }
1286
                } else {
1287
                    builder.append(" DEFAULT '");
1288
                    builder.append(column.getDefaultValue().toString());
1289
                    builder.append("'");
1290
                }
1291
                if (column.allowNulls()) {
1292
                    builder.append(" NULL");
1293
                } else {
1294
                    builder.append(" NOT NULL");
1295
                }
1296
                if (column.isPrimaryKey()) {
1297
                    builder.append(" PRIMARY KEY");
1298
                }
1299
                sqls.add(builder.toString());
1300
            }
1301
            for (ColumnDescriptor column : alters) {
1302
                StringBuilder builder = new StringBuilder();
1303
                builder.append("ALTER TABLE ");
1304
                builder.append(this.table.toString());
1305
                builder.append(" ALTER COLUMN ");
1306
                builder.append(identifier(column.getName())); 
1307
                builder.append(" SET DATA TYPE ");
1308
                if( column.getType() == DataTypes.INT && column.isAutomatic() ) {
1309
                    builder.append(" SERIAL");
1310
                } else {
1311
                    builder.append(
1312
                        sqltype(
1313
                            column.getType(), 
1314
                            column.getPrecision(), 
1315
                            column.getSize(),
1316
                            column.getGeometryType(),
1317
                            column.getGeometrySubtype()
1318
                        )
1319
                    );
1320
                }
1321
                if (column.getDefaultValue() == null) {
1322
                    if (column.allowNulls()) {
1323
                        builder.append(" DEFAULT NULL");
1324
                    } else {
1325
                        builder.append(" DROP DEFAULT");
1326
                    }
1327
                } else {
1328
                    builder.append(" DEFAULT '");
1329
                    builder.append(column.getDefaultValue().toString());
1330
                    builder.append("'");
1331
                }
1332
                sqls.add(builder.toString());
1333
            }
1334
            for (Pair<String,String> pair : renames) {
1335
                StringBuilder builder = new StringBuilder();
1336
                builder.append("ALTER TABLE ");
1337
                builder.append(this.table.toString());
1338
                builder.append(" RENAME COLUMN ");
1339
                builder.append(identifier(pair.getLeft())); 
1340
                builder.append(" TO ");
1341
                builder.append(identifier(pair.getRight())); 
1342
                sqls.add(builder.toString());
1343
            }
1344
            return sqls;
1345
        }
1346

    
1347
    }
1348

    
1349
    public class CreateTableBuilderBase implements CreateTableBuilder {
1350

    
1351
        protected TableNameBuilder table;
1352
        protected List<ColumnDescriptor> columns;
1353

    
1354
        public CreateTableBuilderBase() {
1355
            this.columns = new ArrayList<>();
1356
        }
1357

    
1358
        @Override
1359
        public void accept(Visitor visitor, VisitorFilter filter) {
1360
            if( filter.accept(this) ) {
1361
                visitor.visit(this);
1362
            }
1363
            if( this.table != null ) {
1364
                this.table.accept(visitor, filter);
1365
            }
1366
        }
1367

    
1368
        @Override
1369
        public TableNameBuilder table() {
1370
            if( table == null ) {
1371
                table = createTableNameBuilder();
1372
            }
1373
            return table;
1374
        }
1375

    
1376
        @Override
1377
        public CreateTableBuilderBase add_column(FeatureAttributeDescriptor fad) {
1378
            this.columns.add(column(fad).getDescriptor());
1379
            return this;            
1380
        }
1381

    
1382
        @Override
1383
        public CreateTableBuilderBase add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1384
            if( StringUtils.isEmpty(columnName) ) {
1385
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1386
            }
1387
            if (isPk || isAutomatic) {
1388
                allowNulls = false;
1389
            }
1390
            this.columns.add(new ColumnDescriptorBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
1391
            return this;
1392
        }
1393

    
1394
        @Override
1395
        public CreateTableBuilder add_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
1396
            if( StringUtils.isEmpty(columnName) ) {
1397
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1398
            }
1399
            this.columns.add(new ColumnDescriptorBase(columnName, type, subtype, proj, isIndexed, allowNulls));
1400
            return this;
1401
        }
1402

    
1403
        @Override
1404
        public CreateTableBuilder add_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
1405
            if( StringUtils.isEmpty(columnName) ) {
1406
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1407
            }
1408
            this.columns.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
1409
            return this;
1410
        }
1411

    
1412
        @Override
1413
        public ColumnDescriptor getColumnDescriptor(String columnName) {
1414
            if( StringUtils.isEmpty(columnName) ) {
1415
                return null;
1416
            }
1417
            for (ColumnDescriptor column : columns) {
1418
                if( columnName.equals(column.getName()) ) {
1419
                    return column;
1420
                }
1421
            }
1422
            return null;
1423
        }
1424
                
1425
        @Override
1426
        public String toString() {
1427
            StringBuilder builder = new StringBuilder();
1428
            boolean first = true;
1429
            for (String sql : toStrings()) {
1430
                if( StringUtils.isEmpty(sql) ) {
1431
                    continue;
1432
                }
1433
                if (first) {
1434
                    first = false;
1435
                } else {
1436
                    builder.append("; ");
1437
                }
1438
                builder.append(sql);
1439
            }
1440
            return builder.toString();
1441
        }
1442

    
1443
        @Override
1444
        public List<String> toStrings() {
1445
            List<String> sqls = new ArrayList<>();
1446
            /**
1447
             * CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE
1448
             * table_name ( { column_name data_type [ DEFAULT default_expr ] [
1449
             * column_constraint [ ... ] ] | table_constraint | LIKE
1450
             * parent_table [ { INCLUDING | EXCLUDING } DEFAULTS ] } [, ... ] )
1451
             * [ INHERITS ( parent_table [, ... ] ) ] [ WITH OIDS | WITHOUT OIDS
1452
             * ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
1453
             *
1454
             * where column_constraint is:
1455
             *
1456
             * [ CONSTRAINT constraint_name ] { NOT NULL | NULL | UNIQUE |
1457
             * PRIMARY KEY | CHECK (expression) | REFERENCES reftable [ (
1458
             * refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON
1459
             * DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE | NOT
1460
             * DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1461
             *
1462
             * and table_constraint is:
1463
             *
1464
             * [ CONSTRAINT constraint_name ] { UNIQUE ( column_name [, ... ] )
1465
             * | PRIMARY KEY ( column_name [, ... ] ) | CHECK ( expression ) |
1466
             * FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ (
1467
             * refcolumn [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH
1468
             * SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE
1469
             * | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1470
             */
1471
            StringBuilder builder = new StringBuilder();
1472

    
1473
            builder.append("CREATE TABLE ");
1474
            builder.append(this.table.toString());
1475
            builder.append(" (");
1476
            boolean first = true;
1477
            for (ColumnDescriptor column : columns) {
1478
                if (first) {
1479
                    first = false;
1480
                } else {
1481
                    builder.append(", ");
1482
                }
1483
                builder.append(identifier(column.getName()));
1484
                builder.append(" ");
1485
                if( column.isAutomatic() && column.getType() == DataTypes.INT ) {
1486
                    builder.append("SERIAL");
1487
                } else if( column.isAutomatic() && column.getType() == DataTypes.LONG ) {
1488
                    builder.append("BIGSERIAL");
1489
                } else {
1490
                    builder.append(sqltype(column.getType(), column.getPrecision(), column.getSize()));
1491
                }
1492
                if (column.getDefaultValue() == null) {
1493
                    if (column.allowNulls()) {
1494
                        builder.append(" DEFAULT NULL");
1495
                    }
1496
                } else {
1497
                    builder.append(" DEFAULT '");
1498
                    builder.append(column.getDefaultValue().toString());
1499
                    builder.append("'");
1500
                }
1501
                if (column.allowNulls()) {
1502
                    builder.append(" NULL");
1503
                } else {
1504
                    builder.append(" NOT NULL");
1505
                }
1506
                if (column.isPrimaryKey()) {
1507
                    builder.append(" PRIMARY KEY");
1508
                }
1509
            }
1510
            builder.append(" )");
1511
            sqls.add(builder.toString());
1512
            return sqls;
1513
        }
1514
    }
1515

    
1516
    public class InsertColumnBuilderBase implements InsertColumnBuilder {
1517
        protected Variable name;
1518
        protected Value value;
1519
        
1520
        public InsertColumnBuilderBase() {
1521
        }
1522

    
1523
        @Override
1524
        public void accept(Visitor visitor, VisitorFilter filter) {
1525
            if( filter.accept(this) ) {
1526
                visitor.visit(this);
1527
            }
1528
            if( this.name != null ) {
1529
                this.name.accept(visitor, filter);
1530
            }
1531
            if( this.value != null ) {
1532
                this.value.accept(visitor, filter);
1533
            }
1534
        }
1535

    
1536
        @Override
1537
        public InsertColumnBuilder name(String name) {
1538
            this.name = variable(name);
1539
            return this;
1540
        }
1541

    
1542
        @Override
1543
        public InsertColumnBuilder with_value(Value value) {
1544
            this.value = value;
1545
            return this;
1546
        }
1547
        
1548
        @Override
1549
        public String getName() {
1550
            return this.name.getName();
1551
        }
1552
        
1553
        @Override
1554
        public Value getValue() {
1555
            return this.value;
1556
        }
1557
        
1558
        @Override
1559
        public String toString() {
1560
            return this.value.toString();
1561
        }
1562
    }
1563
    
1564
    public class InsertBuilderBase implements InsertBuilder {
1565

    
1566
        protected List<InsertColumnBuilder> columns;
1567
        protected TableNameBuilder table;
1568

    
1569
        public InsertBuilderBase() {
1570
            this.columns = new ArrayList<>();
1571
        }
1572

    
1573
        @Override
1574
        public void accept(Visitor visitor, VisitorFilter filter) {
1575
            if( filter.accept(this) ) {
1576
                visitor.visit(this);
1577
            }
1578
            if( this.table != null ) {
1579
                this.table.accept(visitor, filter);
1580
            }
1581
            for (InsertColumnBuilder column : columns) {
1582
                column.accept(visitor, filter);
1583
            }
1584
        }
1585

    
1586
        @Override
1587
        public TableNameBuilder table() {
1588
            if( table == null ) {
1589
                table = createTableNameBuilder();
1590
            }
1591
            return table;
1592
        }
1593

    
1594
        @Override
1595
        public InsertColumnBuilder column() {
1596
            InsertColumnBuilder column = createInsertColumnBuilder();
1597
            this.columns.add(column);
1598
            return column;
1599
        }
1600

    
1601
        @Override
1602
        public String toString() {
1603
            /*
1604
             * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
1605
             * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
1606
             * output_expression [ AS output_name ] [, ...] ]
1607
             */
1608
            StringBuilder builderColumns = new StringBuilder();
1609
            StringBuilder builderValues = new StringBuilder();
1610
            
1611
            boolean first = true;
1612
            for (InsertColumnBuilder column : columns) {
1613
                if (first) {
1614
                    first = false;
1615
                } else {
1616
                    builderColumns.append(", ");
1617
                }
1618
                builderColumns.append(identifier(column.getName()));
1619
            }
1620
            first = true;
1621
            for (InsertColumnBuilder column : columns) {
1622
                if (first) {
1623
                    first = false;
1624
                } else {
1625
                    builderValues.append(", ");
1626
                }
1627
                builderValues.append(column.toString());
1628
            }
1629
            
1630
            String sql = MessageFormat.format(
1631
                    config.getString(SQLConfig.INSERT_INTO_table_columns_VALUES_values),
1632
                    this.table.toString(),
1633
                    builderColumns.toString(),
1634
                    builderValues.toString()
1635
            );
1636
            return sql;
1637

    
1638
        }
1639
    }
1640

    
1641
    public class UpdateTableStatisticsBuilderBase implements UpdateTableStatisticsBuilder {
1642

    
1643
        protected TableNameBuilder table;
1644

    
1645
        @Override
1646
        public void accept(Visitor visitor, VisitorFilter filter) {
1647
            if( filter.accept(this) ) {
1648
                visitor.visit(this);
1649
            }
1650
            if( this.table != null ) {
1651
                this.table.accept(visitor, filter);
1652
            }
1653
        }
1654

    
1655
        @Override
1656
        public TableNameBuilder table() {
1657
            if( table == null ) {
1658
                table = createTableNameBuilder();
1659
            }
1660
            return table;
1661
        }
1662

    
1663
        @Override
1664
        public String toString() {
1665
            StringBuilder builder = new StringBuilder();
1666
            boolean first = true;
1667
            for (String sql : toStrings()) {
1668
                if( StringUtils.isEmpty(sql) ) {
1669
                    continue;
1670
                }
1671
                if (first) {
1672
                    first = false;
1673
                } else {
1674
                    builder.append("; ");
1675
                }
1676
                builder.append(sql);
1677
            }
1678
            return builder.toString();
1679
        }
1680

    
1681
        @Override
1682
        public List<String> toStrings() {
1683
            List<String> sqls = new ArrayList<>();
1684
            
1685
            if( config.has_functionality(SQLConfig.UPDATE_TABLE_STATISTICS_table) ) {
1686
                String sql = MessageFormat.format(
1687
                        config.getString(SQLConfig.UPDATE_TABLE_STATISTICS_table),
1688
                        table.toString()
1689
                    );
1690
                if( !StringUtils.isEmpty(sql) ) {
1691
                    sqls.add(sql);
1692
                }
1693
            }
1694
            return sqls;
1695
        }
1696
    }
1697
    
1698
    public SQLBuilderBase() {
1699
        super();
1700
        config.set(SQLConfig.default_schema, "public");
1701
        config.set(SQLConfig.allowAutomaticValues, true);
1702
        
1703
        config.set(SQLConfig.ST_ExtentAggregate, "ST_Extent({0})");
1704
        config.set(SQLConfig.ST_UnionAggregate, "ST_Union({0})");
1705
        config.set(SQLConfig.count, "COUNT({0})");
1706
        config.set(SQLConfig.count_distinct, "COUNT(DISTINCT {0})");
1707

    
1708
        config.set(SQLConfig.type_boolean, "BOOLEAN");
1709
        config.set(SQLConfig.type_byte, "TINYINT");
1710
        config.set(SQLConfig.type_bytearray, "BYTEA");
1711
        config.set(SQLConfig.type_geometry, "TEXT");
1712
        config.set(SQLConfig.type_char, "CHARACTER(1)");
1713
        config.set(SQLConfig.type_date, "DATE");
1714
        config.set(SQLConfig.type_double, "DOUBLE PRECISION"); //float con 53 bits de mantisa, float(54)
1715
        config.set(SQLConfig.type_numeric_p, "NUMERIC({0})");
1716
        config.set(SQLConfig.type_numeric_ps, "NUMERIC({0},{1})");
1717
        config.set(SQLConfig.type_bigdecimal, "NUMERIC({0},{1})");
1718
        config.set(SQLConfig.type_float, "REAL"); //float con 24 bits de mantisa, float(24)
1719
        config.set(SQLConfig.type_int, "INT");
1720
        config.set(SQLConfig.type_long, "BIGINT");
1721
        config.set(SQLConfig.type_string, "TEXT");
1722
        config.set(SQLConfig.type_string_p, "VARCHAR({0})");
1723
        config.set(SQLConfig.type_time, "TIME");
1724
        config.set(SQLConfig.type_timestamp, "TIMESTAMP");
1725
        config.set(SQLConfig.type_version, "VARCHAR(30)");
1726
        config.set(SQLConfig.type_URI, "TEXT");
1727
        config.set(SQLConfig.type_URL, "TEXT");
1728
        config.set(SQLConfig.type_FILE, "TEXT");
1729
        config.set(SQLConfig.type_FOLDER, "TEXT");
1730

    
1731
        config.set(SQLConfig.DELETE_FROM_table_WHERE_expresion, "DELETE FROM {0} WHERE {1}");
1732
        config.set(SQLConfig.DELETE_FROM_table, "DELETE FROM {0}");
1733
        config.set(SQLConfig.INSERT_INTO_table_columns_VALUES_values, "INSERT INTO {0} ( {1} ) VALUES ( {2} )");
1734
        config.set(SQLConfig.UPDATE_TABLE_STATISTICS_table, "VACUUM ANALYZE {0}");
1735
        config.set(SQLConfig.DROP_TABLE_table, "DROP TABLE {0}");
1736
        config.set(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table, "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_schema = {0} AND f_table_name = {1}");
1737
        config.set(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table, "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_name = {0}");
1738
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues_WHERE_expresion, "UPDATE {0} SET {1} WHERE {2}");
1739
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues, "UPDATE {0} SET {1}");
1740
        config.set(SQLConfig.GRANT_privileges_ON_table_TO_role, "GRANT {0} ON {1} TO {2}");        
1741
    }
1742
    
1743
    @Override
1744
    public String default_schema() {
1745
        return config.getString(SQLConfig.default_schema);
1746
    }
1747

    
1748
    @Override
1749
    public boolean supportSchemas() {
1750
        return config.getBoolean(Config.support_schemas);
1751
    }
1752
    
1753
    @Override
1754
    @Deprecated
1755
    public String sqltype(int type, int p, int s) {
1756
        return this.sqltype(type, p, s, Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.UNKNOWN);
1757
    }
1758

    
1759
    @Override
1760
    public String sqltype(int type, int p, int s, int geomType, int geomSubtype) {
1761
        switch (type) {
1762
            case DataTypes.BOOLEAN:
1763
                return config.getString(SQLConfig.type_boolean);
1764
            case DataTypes.BYTE:
1765
                return config.getString(SQLConfig.type_byte);
1766
            case DataTypes.BYTEARRAY:
1767
                return config.getString(SQLConfig.type_bytearray);
1768
            case DataTypes.GEOMETRY:
1769
                return config.getString(SQLConfig.type_geometry);
1770
            case DataTypes.CHAR:
1771
                return config.getString(SQLConfig.type_char);
1772
            case DataTypes.DATE:
1773
                return config.getString(SQLConfig.type_date);
1774
            case DataTypes.DOUBLE:
1775
                  // FIXME: Si cargamos la capa "country" al exportarla a
1776
                  // SQLServer falla por:
1777
                  //  Error de desbordamiento aritm?tico al convertir float al tipo de datos numeric.
1778
                  // Al parecer la capa declara la columna sqkm_ctry como Numeric(12,6) y para 
1779
                  // Algeria intenta asignarle un valor de 2320972.0 y falla.
1780
                  // Habria que repasar el proveedor de shape.
1781
                
1782
//                if (p > 1) {
1783
//                    if (s < 0) {
1784
//                        return MessageFormat.format(config.getString(SQLConfig.type_numeric_p), p);
1785
//                    }
1786
//                    return MessageFormat.format(config.getString(SQLConfig.type_numeric_ps), p,s);
1787
//                }
1788
                return MessageFormat.format(config.getString(SQLConfig.type_double),p,s);
1789
            case DataTypes.BIGDECIMAL:
1790
                if (p < 1) {
1791
                    p = 20;
1792
                }
1793
                if (s < 0) {
1794
                    s = 10;
1795
                }
1796
                return MessageFormat.format(config.getString(SQLConfig.type_bigdecimal), p,s);
1797
            case DataTypes.FLOAT:
1798
                return MessageFormat.format(config.getString(SQLConfig.type_float), p,s);
1799
            case DataTypes.INT:
1800
                return MessageFormat.format(config.getString(SQLConfig.type_int), p,s);
1801
            case DataTypes.LONG:
1802
                return MessageFormat.format(config.getString(SQLConfig.type_long), p,s);
1803
            case DataTypes.STRING:
1804
                if (p < 0) {
1805
                    return config.getString(SQLConfig.type_string);
1806
                } else if (p < 4096) {
1807
                    return MessageFormat.format(config.getString(SQLConfig.type_string_p),p);
1808
                }
1809
                return config.getString(SQLConfig.type_string);
1810
            case DataTypes.TIME:
1811
                return config.getString(SQLConfig.type_time);
1812
            case DataTypes.TIMESTAMP:
1813
                return config.getString(SQLConfig.type_timestamp);
1814
            case DataTypes.VERSION:
1815
                return config.getString(SQLConfig.type_version);
1816
            case DataTypes.URI:
1817
                return config.getString(SQLConfig.type_URI);
1818
            case DataTypes.URL:
1819
                return config.getString(SQLConfig.type_URL);
1820
            case DataTypes.FILE:
1821
                return config.getString(SQLConfig.type_FILE);
1822
            case DataTypes.FOLDER:
1823
                return config.getString(SQLConfig.type_FOLDER);
1824
            default:
1825
                return null;
1826
        }
1827
    }
1828

    
1829
    private static Map<Pair<Integer,Integer>,String> sqlgeometrytypes = null;
1830
    
1831
    @Override
1832
    public Object sqlgeometrytype(int type, int subtype) {
1833
        // Devuelve un Object por que algunos gestores de BBDD utilizan
1834
        // identificadores numericos para el tipo y otros strings.
1835
        // Por defecto vamos a devolver strings.
1836
        if( sqlgeometrytypes==null ) {
1837
            sqlgeometrytypes = new HashMap<>();
1838
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM2D), "POINT");
1839
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM3D), "POINTZ");
1840
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM2DM), "POINTM");
1841
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM3DM), "POINTZM");
1842

    
1843
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM2D), "LINESTRING");
1844
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM3D), "LINESTRINGZ");
1845
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM2DM), "LINESTRINGM");
1846
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM3DM), "LINESTRINGZM");
1847

    
1848
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM2D), "POLYGON");
1849
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM3D), "POLYGONZ");
1850
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM2DM), "POLYGONM");
1851
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM3DM), "POLYGONZM");
1852

    
1853
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM2D), "MULTIPOINT");
1854
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM3D), "MULTIPOINTZ");
1855
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM2DM), "MULTIPOINTM");
1856
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM3DM), "MULTIPOINTZM");
1857

    
1858
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM2D), "MULTILINESTRING");
1859
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM3D), "MULTILINESTRINGZ");
1860
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM2DM), "MULTILINESTRINGM");
1861
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM3DM), "MULTILINESTRINGZM");
1862

    
1863
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM2D), "MULTILINESTRING");
1864
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM3D), "MULTILINESTRINGZ");
1865
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM2DM), "MULTILINESTRINGM");
1866
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM3DM), "MULTILINESTRINGZM");
1867

    
1868
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM2D), "MULTIPOLYGON");
1869
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM3D), "MULTIPOLYGONZ");
1870
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM2DM), "MULTIPOLYGONM");
1871
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM3DM), "MULTIPOLYGONZM");
1872

    
1873
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM2D), "MULTIPOLYGON");
1874
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM3D), "MULTIPOLYGONZ");
1875
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM2DM), "MULTIPOLYGONM");
1876
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM3DM), "MULTIPOLYGONZM");
1877

    
1878
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2D), "GEOMETRY");
1879
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3D), "GEOMETRYZ");
1880
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2DM), "GEOMETRYM");
1881
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3DM), "GEOMETRYZM");
1882
        }
1883
        return sqlgeometrytypes.get(new ImmutablePair<>(type,subtype));
1884
    }
1885

    
1886
    @Override
1887
    public Object sqlgeometrydimension(int type, int subtype) {
1888
        // Devuelve un Object por que algunos gestortes de BBDD utilizan
1889
        // identificadores numericos para las dimensiones y otros strings.
1890
        // Por defecto vamos a devolver enteros.
1891
        switch(subtype) {
1892
            case Geometry.SUBTYPES.GEOM3D:
1893
                return 3;
1894
            case Geometry.SUBTYPES.GEOM2DM:
1895
                return 3;
1896
            case Geometry.SUBTYPES.GEOM3DM:
1897
                return 4;
1898
            case Geometry.SUBTYPES.GEOM2D:
1899
            default:
1900
                return 2;
1901
        }
1902
    }
1903
    
1904
    protected TableNameBuilder createTableNameBuilder() {
1905
        return new TableNameBuilderBase();
1906
    }
1907
    
1908
    protected SelectColumnBuilder createSelectColumnBuilder() {
1909
        return new SelectColumnBuilderBase();
1910
    }
1911
    
1912
    protected UpdateColumnBuilder createUpdateColumnBuilder() {
1913
        return new UpdateColumnBuilderBase();
1914
    }
1915
    
1916
    protected InsertColumnBuilder createInsertColumnBuilder() {
1917
        return new InsertColumnBuilderBase();
1918
    }
1919
    
1920
    protected OrderByBuilder createOrderByBuilder() {
1921
        return new OrderByBuilderBase();
1922
    }
1923

    
1924
    protected FromBuilder createFromBuilder() {
1925
        return new FromBuilderBase();
1926
    }
1927

    
1928
    protected SelectBuilder createSelectBuilder() {
1929
        return new SelectBuilderBase();
1930
    }
1931

    
1932
    protected UpdateBuilder createUpdateBuilder() {
1933
        return new UpdateBuilderBase();
1934
    }
1935

    
1936
    protected DeleteBuilder createDeleteBuilder() {
1937
        return new DeleteBuilderBase();
1938
    }
1939

    
1940
    protected GrantBuilder createGrantBuilder() {
1941
        return new GrantBuilderBase();
1942
    }
1943

    
1944
    protected GrantRoleBuilder createGrantRoleBuilder(TableNameBuilder table, String role) {
1945
        return new GrantRoleBuilderBase(table, role);
1946
    }
1947
    
1948
    protected DropTableBuilder createDropTableBuilder() {
1949
        return new DropTableBuilderBase();
1950
    }
1951

    
1952
    protected CreateTableBuilder createCreateTableBuilder() {
1953
        return new CreateTableBuilderBase();
1954
    }
1955

    
1956
    protected AlterTableBuilder createAlterTableBuilder() {
1957
        return new AlterTableBuilderBase();
1958
    }
1959

    
1960
    protected InsertBuilder createInsertBuilder() {
1961
        return new InsertBuilderBase();
1962
    }
1963

    
1964
    protected UpdateTableStatisticsBuilder createUpdateTableStatisticsBuilder() {
1965
        return new UpdateTableStatisticsBuilderBase();
1966
    }
1967

    
1968
    protected CreateIndexBuilder createCreateIndexBuilder() {
1969
        return new CreateIndexBuilderBase();
1970
    }
1971
    
1972
    @Override
1973
    public SelectBuilder select() {
1974
        if (this.select == null) {
1975
            this.select = this.createSelectBuilder();
1976
        }
1977
        return this.select;
1978
    }
1979

    
1980
    @Override
1981
    public UpdateBuilder update() {
1982
        if (this.update == null) {
1983
            this.update = this.createUpdateBuilder();
1984
        }
1985
        return this.update;
1986
    }
1987

    
1988
    @Override
1989
    public UpdateTableStatisticsBuilder update_table_statistics() {
1990
        if (this.update_table_statistics == null) {
1991
            this.update_table_statistics = this.createUpdateTableStatisticsBuilder();
1992
        }
1993
        return this.update_table_statistics;
1994
    }
1995

    
1996
    @Override
1997
    public DropTableBuilder drop_table() {
1998
        if (this.drop_table == null) {
1999
            this.drop_table = this.createDropTableBuilder();
2000
        }
2001
        return this.drop_table;
2002
    }
2003

    
2004
    @Override
2005
    public CreateIndexBuilder create_index() {
2006
        if (this.create_index == null) {
2007
            this.create_index = this.createCreateIndexBuilder();
2008
        }
2009
        return this.create_index;
2010
    }
2011

    
2012
    
2013
    @Override
2014
    public DeleteBuilder delete() {
2015
        if (this.delete == null) {
2016
            this.delete = this.createDeleteBuilder();
2017
        }
2018
        return this.delete;
2019
    }
2020

    
2021
    @Override
2022
    public InsertBuilder insert() {
2023
        if (this.insert == null) {
2024
            this.insert = this.createInsertBuilder();
2025
        }
2026
        return this.insert;
2027
    }
2028

    
2029
    @Override
2030
    public AlterTableBuilder alter_table() {
2031
        if (this.alter_table == null) {
2032
            this.alter_table = this.createAlterTableBuilder();
2033
        }
2034
        return this.alter_table;
2035
    }
2036

    
2037
    @Override
2038
    public CreateTableBuilder create_table() {
2039
        if (this.create_table == null) {
2040
            this.create_table = this.createCreateTableBuilder();
2041
        }
2042
        return this.create_table;
2043
    }
2044

    
2045
    @Override
2046
    public GrantBuilder grant() {
2047
        if (this.grant == null) {
2048
            this.grant = this.createGrantBuilder();
2049
        }
2050
        return this.grant;
2051
    }
2052

    
2053
    @Override
2054
    public void accept(Visitor visitor, VisitorFilter filter) {
2055
        if (this.select != null) {
2056
            this.select.accept(visitor, filter);
2057
        }
2058
        if (this.update != null) {
2059
            this.update.accept(visitor, filter);
2060
        }
2061
        if (this.insert != null) {
2062
            this.insert.accept(visitor, filter);
2063
        }
2064
        if (this.delete != null) {
2065
            this.delete.accept(visitor, filter);
2066
        }
2067
        if (this.alter_table != null) {
2068
            this.alter_table.accept(visitor, filter);
2069
        }
2070
        if (this.create_table != null) {
2071
            this.create_table.accept(visitor, filter);
2072
        }
2073
        if (this.drop_table != null) {
2074
            this.drop_table.accept(visitor, filter);
2075
        }
2076
    }
2077

    
2078
    
2079
    @Override
2080
    public String toString() {
2081
        if (this.select != null) {
2082
            return this.select.toString();
2083
        }
2084
        if (this.update != null) {
2085
            return this.update.toString();
2086
        }
2087
        if (this.insert != null) {
2088
            return this.insert.toString();
2089
        }
2090
        if (this.delete != null) {
2091
            return this.delete.toString();
2092
        }
2093
        if (this.alter_table != null) {
2094
            return this.alter_table.toString();
2095
        }
2096
        if (this.create_table != null) {
2097
            return this.create_table.toString();
2098
        }
2099
        if (this.drop_table != null) {
2100
            return this.drop_table.toString();
2101
        }
2102
        if (this.update_table_statistics != null) {
2103
            return this.update_table_statistics.toString();
2104
        }
2105
        if ( this.value != null ) {
2106
            return this.value.toString();
2107
        }
2108
        return ""; 
2109
    }
2110

    
2111
    @Override
2112
    public Function ST_UnionAggregate(Value geom) {
2113
        return function("ST_UnionAggregate", config.getString(SQLConfig.ST_UnionAggregate), geom);
2114
    }
2115

    
2116
    @Override
2117
    public Function ST_ExtentAggregate(Value geom) {
2118
        return function("ST_ExtentAggregate", config.getString(SQLConfig.ST_ExtentAggregate), geom);
2119
    }
2120

    
2121
    @Override
2122
    public CountBuilder count() {
2123
        return new CountBuilderBase();
2124
    }
2125

    
2126
}