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

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

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

    
54
    protected class ColumnDescriptorBuilderBase implements ColumnDescriptorBuilder {
55

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

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

    
84
        public ColumnDescriptorBuilderBase(String name, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, 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
            this._isIndexed = isIndexed;
97
        }
98
        
99
        public ColumnDescriptorBuilderBase(String name, int geom_type, int geom_subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
100
            this.name = name;
101
            this.type = DataTypes.GEOMETRY;
102
            this.type_p = 0;
103
            this.type_s = 0;
104
            this.isPk = false;
105
            this._allowNulls = allowNulls;
106
            this._isAutomatic = false;
107
            this.defaultValue = null;
108
            this.geom_type = geom_type;
109
            this.geom_subtype = geom_subtype;
110
            this.geom_srsid = getSRSId(proj);
111
            this._isIndexed = isIndexed;
112
        }
113
        
114
        @Override
115
        public String getName() {
116
            return this.name;
117
        }
118
        
119
        @Override
120
        public void setName(String name) {
121
            this.name = name;
122
        }
123

    
124
        @Override
125
        public int getType() {
126
            return this.type;
127
        }
128

    
129
        @Override
130
        public void setType(int type) {
131
            this.type = type;
132
        }
133

    
134
        @Override
135
        public int getPrecision() {
136
            return type_p;
137
        }
138

    
139
        @Override
140
        public void setPrecision(int precision) {
141
            this.type_p = precision;
142
        }
143

    
144
        @Override
145
        public int getSize() {
146
            return type_s;
147
        }
148

    
149
        @Override
150
        public void setSize(int size) {
151
            this.type_s = size;
152
        }
153

    
154
        @Override
155
        public boolean isPrimaryKey() {
156
            return isPk;
157
        }
158

    
159
        @Override
160
        public void setIsPrimaryKey(boolean isPk) {
161
            this.isPk = isPk;
162
        }
163

    
164
        @Override
165
        public boolean allowNulls() {
166
            return _allowNulls;
167
        }
168

    
169
        @Override
170
        public void setAllowNulls(boolean allowNulls) {
171
            this._allowNulls = allowNulls;
172
        }
173

    
174
        @Override
175
        public boolean isAutomatic() {
176
            return _isAutomatic;
177
        }
178

    
179
        @Override
180
        public boolean isIndexed() {
181
            return _isIndexed;
182
        }
183

    
184
        @Override
185
        public void setIsAutomatic(boolean isAutomatic) {
186
            this._isAutomatic = isAutomatic;
187
        }
188

    
189
        @Override
190
        public Object getDefaultValue() {
191
            return defaultValue;
192
        }
193

    
194
        @Override
195
        public void setDefaultValue(Object defaultValue) {
196
            this.defaultValue = defaultValue;
197
        }
198

    
199
        @Override
200
        public int getGeometryType() {
201
            return geom_type;
202
        }
203

    
204
        @Override
205
        public void setGeometryType(int geom_type) {
206
            this.geom_type = geom_type;
207
        }
208

    
209
        @Override
210
        public int getGeometrySubtype() {
211
            return geom_subtype;
212
        }
213

    
214
        @Override
215
        public void setGeometrySubtype(int geom_subtype) {
216
            this.geom_subtype = geom_subtype;
217
        }
218

    
219
        @Override
220
        public int getGeometrySRSId() {
221
            return geom_srsid;
222
        }
223

    
224
        @Override
225
        public void setGeometrySRSId(int geom_srsid) {
226
            this.geom_srsid = geom_srsid;
227
        }        
228

    
229
        @Override
230
        public boolean isGeometry() {
231
            return this.type == DataTypes.GEOMETRY;
232
        }
233
                
234
    }
235
    
236

    
237
    public class TableNameBuilderBase implements TableNameBuilder {
238

    
239
        public String tableName;
240
        public String schemaName;
241
        private String databaseName;
242

    
243
        public TableNameBuilderBase() {
244
        }
245

    
246
        @Override
247
        public void accept(Visitor visitor, VisitorFilter filter) {
248
            if( filter.accept(this) ) {
249
                visitor.visit(this);
250
            }
251
        }
252

    
253
        @Override
254
        public TableNameBuilder database(String name) {
255
            this.databaseName = name;
256
            return this;
257
        }
258

    
259
        @Override
260
        public TableNameBuilder schema(String name) {
261
            if( supportSchemas() ) {
262
                this.schemaName = name;
263
            }
264
            return this;
265
        }
266

    
267
        @Override
268
        public TableNameBuilder name(String name) {
269
            this.tableName = name;
270
            return this;
271
        }
272

    
273
        @Override
274
        public String getDatabase() {
275
            return this.databaseName;
276
        }
277

    
278
        @Override
279
        public String getSchema() {
280
            return this.schemaName;
281
        }
282

    
283
        @Override
284
        public String getName() {
285
            return this.tableName;
286
        }
287
        
288
        @Override
289
        public boolean has_schema() {
290
            if( !supportSchemas() ) {
291
                return false;
292
            }
293
            return !StringUtils.isEmpty(this.schemaName);
294
        }
295

    
296
        @Override
297
        public boolean has_database() {
298
            return !StringUtils.isEmpty(this.databaseName);
299
        }
300
        
301
        @Override
302
        public String toString() {
303
            if( this.has_database()) {
304
                if( this.has_schema()) {
305
                    return identifier(this.databaseName) + "." + 
306
                           identifier(this.schemaName) + "." + 
307
                           identifier(this.tableName);
308
                }
309
            } else {
310
                if( this.has_schema()) {
311
                    return identifier(this.schemaName) + "." + 
312
                           identifier(this.tableName);
313
                }                
314
            }
315
            return identifier(this.tableName);
316
        }
317

    
318
    }
319

    
320
    public class CountBuilderBase extends AbstractValue implements CountBuilder {
321

    
322
        protected Value value;
323
        protected boolean distinct;
324
        protected boolean all ;
325
        
326
        public CountBuilderBase() {
327
            this.value = null;
328
            this.distinct = false;
329
            this.all = false;
330
        }
331
        
332
        @Override
333
        public CountBuilder all() {
334
            this.all = true;
335
            return this;
336
        }
337

    
338
        @Override
339
        public CountBuilder column(Value value) {
340
            this.value = value;
341
            return this;
342
        }
343

    
344
        @Override
345
        public CountBuilder distinct() {
346
            this.distinct = true;
347
            return this;
348
        }
349

    
350
        @Override
351
        public String toString() {
352
            if( this.all ) {
353
                return MessageFormat.format(
354
                    config.getString(SQLConfig.count),
355
                    "*"
356
                );
357
            }
358
            if( this.distinct ) {
359
                return MessageFormat.format(
360
                    config.getString(SQLConfig.count_distinct),
361
                    value.toString()
362
                );
363
            }
364
            return MessageFormat.format(
365
                config.getString(SQLConfig.count),
366
                value.toString()
367
            );
368
        }
369
        
370
        
371
    }
372
    
373
    public class FromBuilderBase implements FromBuilder {
374

    
375
        protected TableNameBuilder tableName= null;
376
        private String subquery = null;
377
        private String passthrough = null;
378

    
379
        @Override
380
        public TableNameBuilder table() {
381
            if( tableName == null ) {
382
                this.tableName = createTableNameBuilder();
383
            }
384
            return this.tableName;
385
        }
386

    
387
        @Override
388
        public void accept(Visitor visitor, VisitorFilter filter) {
389
            if( filter.accept(this) ) {
390
                visitor.visit(this);
391
            }
392
            if( this.tableName != null ) {
393
                this.tableName.accept(visitor, filter);
394
            }
395
        }
396

    
397
        @Override
398
        public FromBuilder custom(String passthrough) {
399
            this.passthrough = passthrough;
400
            return this;
401
        }
402

    
403
        @Override
404
        public FromBuilder subquery(String subquery) {
405
            this.subquery = subquery;
406
            return this;
407
        }
408
        
409
        @Override
410
        public String toString() {
411
            if( ! StringUtils.isEmpty(passthrough) ) {
412
                return passthrough;
413
            }
414
            if( ! StringUtils.isEmpty(subquery) ) {
415
                return "( " + this.subquery + ") as _subquery_alias_ ";
416
            }
417
            return this.tableName.toString();
418
        }
419

    
420
    }
421

    
422
    public class SelectColumnBuilderBase implements SelectColumnBuilder {
423

    
424
        private Variable name = null;
425
        private String alias = null;
426
        private Value value = null;
427
        private boolean asGeometry = false;
428
        
429
        @Override
430
        public void accept(Visitor visitor, VisitorFilter filter) {
431
            if( filter.accept(this) ) {
432
                visitor.visit(this);
433
            }
434
            if( this.name != null ) {
435
                this.name.accept(visitor, filter);
436
            }
437
            if( this.value != null ) {
438
                this.value.accept(visitor, filter);
439
            }
440
        }
441

    
442
        @Override
443
        public SelectColumnBuilder name(String name) {
444
            String quote = config.getString(Config.quote_for_identifiers);
445
            if (name.startsWith(quote)) {
446
                // Remove quotes
447
                name = name.substring(1, name.length() - 1);
448
            }
449
            this.name = variable(name);
450
            this.value = null;
451
            this.asGeometry = false;
452
            return this;
453
        }
454

    
455
        @Override
456
        public SelectColumnBuilder all() {
457
            this.name = null;
458
            this.value = custom("*");
459
            this.asGeometry = false;
460
            return this;
461
        }
462
        
463
        @Override
464
        public SelectColumnBuilder as_geometry() {
465
            this.asGeometry = true;
466
            return this;
467
        }
468
       
469
        @Override
470
        public SelectColumnBuilder value(Value value) {
471
            this.value = value;
472
            this.name = null;
473
            return this;
474
        }
475

    
476
        @Override
477
        public SelectColumnBuilder as(String alias) {
478
            this.alias = alias;
479
            return this;
480
        }
481

    
482
        @Override
483
        public String getName() {
484
            return this.name.getName();
485
        }
486
        
487
        @Override
488
        public String getAlias() {
489
            return this.alias;
490
        }
491
        
492
        @Override
493
        public String getValue() {
494
            return this.alias;
495
        }
496

    
497
        @Override
498
        public String toString() {
499
            StringBuilder builder = new StringBuilder();
500
            if( this.asGeometry ) {
501
                builder.append(getAsGeometry(this.name).toString());
502
            } else {
503
                if( this.name != null ) {
504
                    builder.append(this.name.toString());
505
                } else {
506
                    builder.append(this.value.toString());
507
                }
508
            }
509
            if( this.alias != null ) {
510
                builder.append(" AS ");
511
                builder.append(identifier(this.alias));
512
            }
513
            return builder.toString();
514
        }
515
    }
516

    
517
    public class OrderByBuilderBase implements OrderByBuilder {
518
        protected String value;
519
        protected String custom;
520
        protected boolean ascending;
521
        
522
        public OrderByBuilderBase() {
523
            this.ascending = true;
524
        }
525

    
526
        @Override
527
        public void accept(Visitor visitor, VisitorFilter filter) {
528
            if( filter.accept(this) ) {
529
                visitor.visit(this);
530
            }
531
        }
532

    
533
        @Override
534
        public OrderByBuilder column(String name) {
535
            this.value = name;
536
            return this;
537
        }
538

    
539
        @Override
540
        public OrderByBuilder custom(String order) {
541
            this.custom = order;
542
            return this;
543
        }
544

    
545
        @Override
546
        public OrderByBuilder ascending() {
547
            this.ascending = true;
548
            return this;
549
        }
550

    
551
        @Override
552
        public OrderByBuilder ascending(boolean asc) {
553
            this.ascending = asc;
554
            return this;
555
        }
556

    
557
        @Override
558
        public OrderByBuilder descending() {
559
            this.ascending = false;
560
            return this;
561
        }
562

    
563
        @Override
564
        public String toString() {
565
            if( !StringUtils.isEmpty(this.custom) ) {
566
                return this.custom;
567
            }
568
            if( this.ascending ) {
569
                return this.value + " ASC";
570
            }
571
            return this.value + " DESC";
572
        }
573
    }
574
    
575
    public class SelectBuilderBase implements SelectBuilder {
576

    
577
        protected FromBuilder from;
578
        protected ExpressionBuilder where;
579
        protected long limit = -1;
580
        protected long offset = -1;
581
        protected List<SelectColumnBuilder> columns;
582
        protected List<OrderByBuilder> order_by;
583
        protected boolean distinct;
584

    
585
        public SelectBuilderBase() {
586
            this.columns = new ArrayList<>();
587
            this.distinct = false;
588
        }
589

    
590
        @Override
591
        public void accept(Visitor visitor, VisitorFilter filter) {
592
            if( filter.accept(this) ) {
593
                visitor.visit(this);
594
            }
595
            for (SelectColumnBuilder column : columns) {
596
                column.accept(visitor,filter);
597
            }
598
            if( this.has_from() ) {
599
                this.from.accept(visitor,filter);
600
            }
601
            if( this.has_where() ) {
602
                this.where.accept(visitor,filter);
603
            }
604
            if( this.has_order_by() ) {
605
                for (OrderByBuilder order : order_by) {
606
                    order.accept(visitor,filter);
607
                }
608
            }
609
        }
610

    
611
        @Override
612
        public SelectBuilder distinct() {
613
            this.distinct = true;
614
            return this;
615
        }
616
        
617
        @Override
618
        public SelectColumnBuilder column() {
619
            SelectColumnBuilder builder = createSelectColumnBuilder();
620
            this.columns.add(builder);
621
            return builder;
622
        }
623

    
624
        @Override
625
        public boolean has_column(String name) {
626
            for (SelectColumnBuilder column : columns) {
627
                if( name.equals(column.getName()) ) {
628
                    return true;
629
                }
630
            }
631
            return false;
632
        }
633

    
634
        @Override
635
        public FromBuilder from() {
636
            if (this.from == null) {
637
                this.from = createFromBuilder();
638
            }
639
            return this.from;
640
        }
641

    
642
        @Override
643
        public boolean has_from() {
644
            return this.from != null;
645
        }
646
        
647
        @Override
648
        public ExpressionBuilder where() {
649
            if (this.where == null) {
650
                this.where = createExpressionBuilder();
651
            }
652
            return this.where;
653
        }
654

    
655
        @Override
656
        public boolean has_where() {
657
            if( this.where == null ) {
658
                return false;
659
            }
660
            return this.where.getValue() != null;
661
        }
662
        
663
        @Override
664
        public SelectBuilder limit(long limit) {
665
            this.limit = limit;
666
            return this;
667
        }
668

    
669
        @Override
670
        public boolean has_limit() {
671
            return this.limit > 0;
672
        }
673

    
674
        @Override
675
        public SelectBuilder offset(long offset) {
676
            this.offset = offset;
677
            return this;
678
        }
679

    
680
        @Override
681
        public boolean has_offset() {
682
            return this.offset > 0;
683
        }
684

    
685
        @Override
686
        public OrderByBuilder order_by() {
687
            if( this.order_by == null ) {
688
                this.order_by = new ArrayList<>();
689
            }
690
            OrderByBuilder order = createOrderByBuilder();
691
            this.order_by.add(order);
692
            return order;
693
        }
694

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

    
738
            if ( this.has_from() ) {
739
                builder.append(" FROM ");
740
                builder.append(this.from.toString());
741
            }
742
            if ( this.has_where() ) {
743
                builder.append(" WHERE ");
744
                builder.append(this.where.toString());
745
            }
746
            
747
            if( this.has_order_by() ) {
748
                builder.append(" ORDER BY ");
749
                first = true;
750
                for (OrderByBuilder item : this.order_by) {
751
                    if (first) {
752
                        first = false;
753
                    } else {
754
                        builder.append(", ");
755
                    }
756
                    builder.append(item.toString());                    
757
                }   
758
            }
759
            
760
            if ( this.has_limit() ) {
761
                builder.append(" LIMIT ");
762
                builder.append(this.limit);
763
            }
764
            if ( this.has_offset() ) {
765
                builder.append(" OFFSET ");
766
                builder.append(this.offset);
767
            }
768
            return builder.toString();
769

    
770
        }
771
    }
772

    
773
    public class DropTableBuilderBase implements DropTableBuilder {
774

    
775
        protected TableNameBuilder table;
776

    
777
        @Override
778
        public TableNameBuilder table() {
779
            if( table == null ) {
780
                table = createTableNameBuilder();
781
            }
782
            return table;
783
        }
784

    
785
        @Override
786
        public void accept(Visitor visitor, VisitorFilter filter) {
787
            if( filter.accept(this) ) {
788
                visitor.visit(this);
789
            }
790
            this.table.accept(visitor,filter);
791
        }
792
        
793
        @Override
794
        public String toString() {
795
            StringBuilder builder = new StringBuilder();
796
            boolean first = true;
797
            for (String sql : toStrings()) {
798
                if( StringUtils.isEmpty(sql) ) {
799
                    continue;
800
                }
801
                if (first) {
802
                    first = false;
803
                } else {
804
                    builder.append("; ");
805
                }
806
                builder.append(sql);
807
            }
808
            return builder.toString();
809
        }
810

    
811
        @Override
812
        public List<String> toStrings() {
813
            List<String> sqls = new ArrayList<>();
814

    
815
            sqls.add(
816
                    MessageFormat.format(
817
                            config.getString(SQLConfig.DROP_TABLE_table),
818
                            this.table.toString()
819
                    )
820
            );
821
            String sql;
822
            if( config.has_functionality(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table) ) {
823
                if (this.table.has_schema()) {
824
                    sql = MessageFormat.format(
825
                            config.getString(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table),
826
                            string(this.table.getSchema()),
827
                            string(this.table.getName())
828
                    );
829
                } else {
830
                    sql = MessageFormat.format(
831
                            config.getString(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table),
832
                            identifier(this.table.getName())
833
                    );
834
                }
835
                if( !StringUtils.isEmpty(sql) ) {
836
                    sqls.add(sql);
837
                }
838
            }
839
            return sqls;
840
        }
841
    }
842

    
843
    public class GrantRoleBuilderBase implements GrantRoleBuilder {
844
        protected TableNameBuilder table;
845
        protected String role;
846
        protected Set<Privilege> privileges;
847

    
848
        public GrantRoleBuilderBase(TableNameBuilder table, String role) {
849
            this.table = table;
850
            this.role = role;
851
            this.privileges = new HashSet<>();
852
        }
853

    
854
        @Override
855
        public GrantRoleBuilder privilege(Privilege privilege) {
856
            privileges.add(privilege);
857
            return this;
858
        }
859
        
860
        @Override
861
        public GrantRoleBuilder select() {
862
             privileges.add(Privilege.SELECT);
863
            return this;
864
        }
865

    
866
        @Override
867
        public GrantRoleBuilder update() {
868
             privileges.add(Privilege.UPDATE);
869
            return this;
870
        }
871

    
872
        @Override
873
        public GrantRoleBuilder insert() {
874
            privileges.add(Privilege.INSERT);
875
            return this;
876
        }
877

    
878
        @Override
879
        public GrantRoleBuilder delete() {
880
            privileges.add(Privilege.DELETE);
881
            return this;
882
        }
883

    
884
        @Override
885
        public GrantRoleBuilder truncate() {
886
            privileges.add(Privilege.TRUNCATE);
887
            return this;
888
        }
889

    
890
        @Override
891
        public GrantRoleBuilder reference() {
892
            privileges.add(Privilege.REFERENCE);
893
            return this;
894
        }
895

    
896
        @Override
897
        public GrantRoleBuilder trigger() {
898
            privileges.add(Privilege.TRIGGER);
899
            return this;
900
        }
901

    
902
        @Override
903
        public GrantRoleBuilder all() {
904
            privileges.add(Privilege.ALL);
905
            return this;
906
        }
907

    
908
        protected String getPrivilegeName(Privilege privilege) {
909
            switch(privilege) {
910
                case DELETE:
911
                    return "DELETE";
912
                case INSERT:
913
                    return "INSERT";
914
                case REFERENCE:
915
                    return "REFERENCE";
916
                case SELECT:
917
                    return "SELECT";
918
                case TRIGGER:
919
                    return "TRIGGER";
920
                case TRUNCATE:
921
                    return "TRUNCATE";
922
                case UPDATE:
923
                    return "UPDATE";
924
                case ALL:
925
                default:
926
                    return "ALL";
927
            }
928
        }
929
        
930
        @Override
931
        public String toString() {
932
            StringBuilder builder = new StringBuilder();
933
            boolean first = true;
934
            for (Privilege privilege : privileges) {
935
                if (first) {
936
                    first = false;
937
                } else {
938
                    builder.append(", ");
939
                }
940
                builder.append( this.getPrivilegeName(privilege));
941
            }
942
            String sql = MessageFormat.format(
943
                    config.getString(SQLConfig.GRANT_privileges_ON_table_TO_role),
944
                    builder.toString(),
945
                    table.toString(),
946
                    role
947
            );
948
            return sql;
949
        }
950
    }
951
    
952
    public class GrantBuilderBase implements GrantBuilder {
953

    
954
        protected TableNameBuilder table;
955
        protected Map<String, GrantRoleBuilder> roles;
956

    
957
        public GrantBuilderBase() {
958
            this.roles = new HashMap<>();
959
        }
960
        
961
        @Override
962
        public TableNameBuilder table() {
963
            if( table == null ) {
964
                table = createTableNameBuilder();
965
            }
966
            return table;
967
        }
968

    
969
        @Override
970
        public void accept(Visitor visitor, VisitorFilter filter) {
971
            if( filter.accept(this) ) {
972
                visitor.visit(this);
973
            }
974
            if( this.table!= null ) {
975
                this.table.accept(visitor,filter);
976
            }
977
        }
978
        
979
        @Override
980
        public GrantRoleBuilder role(String role) {
981
            GrantRoleBuilder roleBuilder = this.roles.get(role);
982
            if( roleBuilder == null ) {
983
                roleBuilder = createGrantRoleBuilder(this.table(), role);
984
                this.roles.put(role, roleBuilder);
985
            }
986
            return roleBuilder;
987
        }
988

    
989
        @Override
990
        public String toString() {
991
            StringBuilder builder = new StringBuilder();
992
            boolean first = true;
993
            for (String sql : toStrings()) {
994
                if( StringUtils.isEmpty(sql) ) {
995
                    continue;
996
                }
997
                if (first) {
998
                    first = false;
999
                } else {
1000
                    builder.append("; ");
1001
                }
1002
                builder.append(sql);
1003
            }
1004
            return builder.toString();
1005
        }
1006

    
1007
        @Override
1008
        public List<String> toStrings() {
1009
            List<String> sqls = new ArrayList<>();
1010
            for (GrantRoleBuilder role : roles.values()) {
1011
                sqls.add(role.toString());
1012
            }
1013
            return sqls;
1014
        }
1015
    }
1016

    
1017
    public class UpdateColumnBuilderBase extends InsertColumnBuilderBase implements UpdateColumnBuilder {
1018
        
1019
        public UpdateColumnBuilderBase() {
1020
            super();
1021
        }
1022

    
1023
        @Override
1024
        public UpdateColumnBuilder name(String name) {
1025
            return (UpdateColumnBuilder) super.name(name);
1026
        }
1027

    
1028
        @Override
1029
        public UpdateColumnBuilder with_value(Value value) {
1030
            return (UpdateColumnBuilder) super.with_value(value);
1031
        }
1032
        
1033
    }
1034
    
1035
    public class UpdateBuilderBase implements UpdateBuilder {
1036

    
1037
        protected ExpressionBuilder where;
1038
        protected List<UpdateColumnBuilder> columns;
1039
        protected TableNameBuilder table;
1040

    
1041
        public UpdateBuilderBase() {
1042
            this.columns = new ArrayList<>();
1043
        }
1044

    
1045
        @Override
1046
        public void accept(Visitor visitor, VisitorFilter filter) {
1047
            if( filter.accept(this) ) {
1048
                visitor.visit(this);
1049
            }
1050
            if( this.table != null ) {
1051
                this.table.accept(visitor, filter);
1052
            }
1053
            for (UpdateColumnBuilder column : columns) {
1054
                column.accept(visitor, filter);
1055
            }
1056
            if( this.has_where() ) {
1057
                this.where.accept(visitor, filter);
1058
            }
1059
        }
1060

    
1061
        @Override
1062
        public ExpressionBuilder where() {
1063
            if (this.where == null) {
1064
                this.where = createExpressionBuilder();
1065
            }
1066
            return this.where;
1067
        }
1068

    
1069
        @Override
1070
        public TableNameBuilder table() {
1071
            if( table == null ) {
1072
                table = createTableNameBuilder();
1073
            }
1074
            return table;
1075
        }
1076

    
1077
        @Override
1078
        public UpdateColumnBuilder column() {
1079
            UpdateColumnBuilder column = createUpdateColumnBuilder();
1080
            this.columns.add(column);
1081
            return column;
1082
        }
1083
        
1084
        @Override
1085
        public boolean has_where() {
1086
            return this.where != null;
1087
        }
1088

    
1089
        @Override
1090
        public String toString() {
1091
            /*
1092
             * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
1093
             * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
1094
             * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
1095
             * output_expression [ AS output_name ] [, ...] ]
1096
             */
1097
            StringBuilder columnsAndValues = new StringBuilder();
1098

    
1099
            boolean first = true;
1100
            for (UpdateColumnBuilder column : columns) {
1101
                if (first) {
1102
                    first = false;
1103
                } else {
1104
                    columnsAndValues.append(", ");
1105
                }
1106
                columnsAndValues.append(identifier(column.getName()));
1107
                columnsAndValues.append(" = ");
1108
                columnsAndValues.append(column.getValue().toString());
1109
            }
1110
            
1111
            String sql;
1112
            if ( this.has_where() ) {
1113
                sql = MessageFormat.format(
1114
                        config.getString(SQLConfig.UPDATE_table_SET_columnsAndValues_WHERE_expresion),
1115
                        this.table.toString(),
1116
                        columnsAndValues.toString(),
1117
                        this.where.toString()
1118
                );
1119
            } else {
1120
                sql = MessageFormat.format(
1121
                        config.getString(SQLConfig.UPDATE_table_SET_columnsAndValues),
1122
                        this.table.toString(),
1123
                        columnsAndValues.toString()
1124
                );
1125
            }
1126
            return sql;
1127
        }
1128
    }
1129

    
1130
    public class DeleteBuilderBase implements DeleteBuilder {
1131

    
1132
        protected ExpressionBuilder where;
1133
        protected TableNameBuilder table;
1134

    
1135
        public DeleteBuilderBase() {
1136
        }
1137

    
1138
        @Override
1139
        public void accept(Visitor visitor, VisitorFilter filter) {
1140
            if( filter.accept(this) ) {
1141
                visitor.visit(this);
1142
            }
1143
            if( this.table != null ) {
1144
                this.table.accept(visitor, filter);
1145
            }
1146
            if( this.has_where() ) {
1147
                this.where.accept(visitor, filter);
1148
            }
1149
        }
1150

    
1151
        @Override
1152
        public ExpressionBuilder where() {
1153
            if (this.where == null) {
1154
                this.where = createExpressionBuilder();
1155
            }
1156
            return this.where;
1157
        }
1158

    
1159
        @Override
1160
        public TableNameBuilder table() {
1161
            if( table == null ) {
1162
                table = createTableNameBuilder();
1163
            }
1164
            return table;
1165
        }
1166

    
1167
        @Override
1168
        public boolean has_where() {
1169
            return this.where != null;
1170
        }
1171

    
1172
        @Override
1173
        public String toString() {
1174
            /*
1175
             * DELETE FROM table_name
1176
             * WHERE some_column=some_value; 
1177
             */
1178
            String sql;
1179
            if( this.has_where() ) {
1180
                sql = MessageFormat.format(
1181
                        config.getString(SQLConfig.DELETE_FROM_table_WHERE_expresion),
1182
                        this.table.toString(),
1183
                        this.where.toString()
1184
                );
1185
            } else {
1186
                sql = MessageFormat.format(
1187
                        config.getString(SQLConfig.DELETE_FROM_table),
1188
                        this.table.toString()
1189
                );
1190
            }
1191
            return sql;
1192
        }
1193
    }
1194

    
1195
    public class AlterTableBuilderBase implements AlterTableBuilder {
1196

    
1197
        protected TableNameBuilder table;
1198
        protected List<String> drops;
1199
        protected List<ColumnDescriptorBuilderBase> adds;
1200
        protected List<ColumnDescriptorBuilderBase> alters;
1201
        protected List<Pair> renames;
1202

    
1203
        public AlterTableBuilderBase() {
1204
            this.drops = new ArrayList<>();
1205
            this.adds = new ArrayList<>();
1206
            this.alters = new ArrayList<>();
1207
            this.renames = new ArrayList<>();
1208
        }
1209

    
1210
        @Override
1211
        public void accept(Visitor visitor, VisitorFilter filter) {
1212
            if( filter.accept(this) ) {
1213
                visitor.visit(this);
1214
            }
1215
            if( this.table != null ) {
1216
                this.table.accept(visitor, filter);
1217
            }
1218
        }
1219

    
1220
        @Override
1221
        public TableNameBuilder table() {
1222
            if( table == null ) {
1223
                table = createTableNameBuilder();
1224
            }
1225
            return table;
1226
        }
1227

    
1228
        @Override
1229
        public AlterTableBuilder drop_column(String columnName) {
1230
            this.drops.add(columnName);
1231
            return this;
1232
        }
1233

    
1234
        @Override
1235
        public AlterTableBuilder add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1236
            if (isPk || isAutomatic) {
1237
                allowNulls = false;
1238
            }
1239
            this.adds.add(new ColumnDescriptorBuilderBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
1240
            return this;
1241
        }
1242

    
1243
        @Override
1244
        public AlterTableBuilder alter_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1245
            if (isPk || isAutomatic) {
1246
                allowNulls = false;
1247
            }
1248
            this.alters.add(new ColumnDescriptorBuilderBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
1249
            return this;
1250
        }
1251

    
1252
        @Override
1253
        public AlterTableBuilder rename_column(String source, String target) {
1254
            this.renames.add(new ImmutablePair(source, target));
1255
            return this;
1256
        }
1257

    
1258
        @Override
1259
        public String toString() {
1260
            StringBuilder builder = new StringBuilder();
1261
            boolean first = true;
1262
            for (String sql : toStrings()) {
1263
                if( StringUtils.isEmpty(sql) ) {
1264
                    continue;
1265
                }
1266
                if (first) {
1267
                    first = false;
1268
                } else {
1269
                    builder.append("; ");
1270
                }
1271
                builder.append(sql);
1272
            }
1273
            return builder.toString();
1274
        }
1275

    
1276
        @Override
1277
        public List<String> toStrings() {
1278
            List<String> sqls = new ArrayList<>();
1279
            /*
1280
             ALTER TABLE [ ONLY ] name [ * ]
1281
             action [, ... ]
1282
             ALTER TABLE [ ONLY ] name [ * ]
1283
             RENAME [ COLUMN ] column TO new_column
1284
             ALTER TABLE name
1285
             RENAME TO new_name
1286
             ALTER TABLE name
1287
             SET SCHEMA new_schema
1288

1289
             where action is one of:
1290

1291
             ADD [ COLUMN ] column data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
1292
             DROP [ COLUMN ] [ IF EXISTS ] column [ RESTRICT | CASCADE ]
1293
             ALTER [ COLUMN ] column [ SET DATA ] TYPE data_type [ COLLATE collation ] [ USING expression ]
1294
             ALTER [ COLUMN ] column SET DEFAULT expression
1295
             ALTER [ COLUMN ] column DROP DEFAULT
1296
             ALTER [ COLUMN ] column { SET | DROP } NOT NULL
1297
             ALTER [ COLUMN ] column SET STATISTICS integer
1298
             ALTER [ COLUMN ] column SET ( attribute_option = value [, ... ] )
1299
             ALTER [ COLUMN ] column RESET ( attribute_option [, ... ] )
1300
             ALTER [ COLUMN ] column SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
1301
             ADD table_constraint [ NOT VALID ]
1302
             ADD table_constraint_using_index
1303
             VALIDATE CONSTRAINT constraint_name
1304
             DROP CONSTRAINT [ IF EXISTS ]  constraint_name [ RESTRICT | CASCADE ]
1305
             DISABLE TRIGGER [ trigger_name | ALL | USER ]
1306
             ENABLE TRIGGER [ trigger_name | ALL | USER ]
1307
             ENABLE REPLICA TRIGGER trigger_name
1308
             ENABLE ALWAYS TRIGGER trigger_name
1309
             DISABLE RULE rewrite_rule_name
1310
             ENABLE RULE rewrite_rule_name
1311
             ENABLE REPLICA RULE rewrite_rule_name
1312
             ENABLE ALWAYS RULE rewrite_rule_name
1313
             CLUSTER ON index_name
1314
             SET WITHOUT CLUSTER
1315
             SET WITH OIDS
1316
             SET WITHOUT OIDS
1317
             SET ( storage_parameter = value [, ... ] )
1318
             RESET ( storage_parameter [, ... ] )
1319
             INHERIT parent_table
1320
             NO INHERIT parent_table
1321
             OF type_name
1322
             NOT OF
1323
             OWNER TO new_owner
1324
             SET TABLESPACE new_tablespace
1325

1326
             and table_constraint_using_index is:
1327

1328
             [ CONSTRAINT constraint_name ]
1329
             { UNIQUE | PRIMARY KEY } USING INDEX index_name
1330
             [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1331

1332
             */
1333
            StringBuilder builder = new StringBuilder();
1334

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

    
1429
            return sqls;
1430
        }
1431

    
1432
    }
1433

    
1434
    public class CreateTableBuilderBase implements CreateTableBuilder {
1435

    
1436
        protected TableNameBuilder table;
1437
        protected List<ColumnDescriptorBuilderBase> columns;
1438

    
1439
        public CreateTableBuilderBase() {
1440
            this.columns = new ArrayList<>();
1441
        }
1442

    
1443
        @Override
1444
        public void accept(Visitor visitor, VisitorFilter filter) {
1445
            if( filter.accept(this) ) {
1446
                visitor.visit(this);
1447
            }
1448
            if( this.table != null ) {
1449
                this.table.accept(visitor, filter);
1450
            }
1451
        }
1452

    
1453
        @Override
1454
        public TableNameBuilder table() {
1455
            if( table == null ) {
1456
                table = createTableNameBuilder();
1457
            }
1458
            return table;
1459
        }
1460

    
1461
        @Override
1462
        public CreateTableBuilderBase add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1463
            if( StringUtils.isEmpty(columnName) ) {
1464
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1465
            }
1466
            if (isPk || isAutomatic) {
1467
                allowNulls = false;
1468
            }
1469
            this.columns.add(new ColumnDescriptorBuilderBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
1470
            return this;
1471
        }
1472

    
1473
        @Override
1474
        public CreateTableBuilder add_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
1475
            if( StringUtils.isEmpty(columnName) ) {
1476
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
1477
            }
1478
            this.columns.add(new ColumnDescriptorBuilderBase(columnName, type, subtype, proj, isIndexed, allowNulls));
1479
            return this;
1480
        }
1481

    
1482
        @Override
1483
        public ColumnDescriptorBuilder getColumnDescriptor(String columnName) {
1484
            if( StringUtils.isEmpty(columnName) ) {
1485
                return null;
1486
            }
1487
            for (ColumnDescriptorBuilderBase column : columns) {
1488
                if( columnName.equals(column.getName()) ) {
1489
                    return column;
1490
                }
1491
            }
1492
            return null;
1493
        }
1494
                
1495
        @Override
1496
        public String toString() {
1497
            StringBuilder builder = new StringBuilder();
1498
            boolean first = true;
1499
            for (String sql : toStrings()) {
1500
                if( StringUtils.isEmpty(sql) ) {
1501
                    continue;
1502
                }
1503
                if (first) {
1504
                    first = false;
1505
                } else {
1506
                    builder.append("; ");
1507
                }
1508
                builder.append(sql);
1509
            }
1510
            return builder.toString();
1511
        }
1512

    
1513
        @Override
1514
        public List<String> toStrings() {
1515
            List<String> sqls = new ArrayList<>();
1516
            /**
1517
             * CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE
1518
             * table_name ( { column_name data_type [ DEFAULT default_expr ] [
1519
             * column_constraint [ ... ] ] | table_constraint | LIKE
1520
             * parent_table [ { INCLUDING | EXCLUDING } DEFAULTS ] } [, ... ] )
1521
             * [ INHERITS ( parent_table [, ... ] ) ] [ WITH OIDS | WITHOUT OIDS
1522
             * ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
1523
             *
1524
             * where column_constraint is:
1525
             *
1526
             * [ CONSTRAINT constraint_name ] { NOT NULL | NULL | UNIQUE |
1527
             * PRIMARY KEY | CHECK (expression) | REFERENCES reftable [ (
1528
             * refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON
1529
             * DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE | NOT
1530
             * DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1531
             *
1532
             * and table_constraint is:
1533
             *
1534
             * [ CONSTRAINT constraint_name ] { UNIQUE ( column_name [, ... ] )
1535
             * | PRIMARY KEY ( column_name [, ... ] ) | CHECK ( expression ) |
1536
             * FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ (
1537
             * refcolumn [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH
1538
             * SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE
1539
             * | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1540
             */
1541
            StringBuilder builder = new StringBuilder();
1542

    
1543
            builder.append("CREATE TABLE ");
1544
            builder.append(this.table.toString());
1545
            builder.append(" (");
1546
            boolean first = true;
1547
            for (ColumnDescriptorBuilderBase column : columns) {
1548
                if (first) {
1549
                    first = false;
1550
                } else {
1551
                    builder.append(", ");
1552
                }
1553
                builder.append(identifier(column.getName()));
1554
                builder.append(" ");
1555
                if( column.isAutomatic() && column.getType() == DataTypes.INT ) {
1556
                    builder.append("SERIAL");
1557
                } else if( column.isAutomatic() && column.getType() == DataTypes.LONG ) {
1558
                    builder.append("BIGSERIAL");
1559
                } else {
1560
                    builder.append(sqltype(column.getType(), column.getPrecision(), column.getSize()));
1561
                }
1562
                if (column.getDefaultValue() == null) {
1563
                    if (column.allowNulls()) {
1564
                        builder.append(" DEFAULT NULL");
1565
                    }
1566
                } else {
1567
                    builder.append(" DEFAULT '");
1568
                    builder.append(column.getDefaultValue().toString());
1569
                    builder.append("'");
1570
                }
1571
                if (column.allowNulls()) {
1572
                    builder.append(" NULL");
1573
                } else {
1574
                    builder.append(" NOT NULL");
1575
                }
1576
                if (column.isPrimaryKey()) {
1577
                    builder.append(" PRIMARY KEY");
1578
                }
1579
            }
1580
            builder.append(" )");
1581
            sqls.add(builder.toString());
1582
            for (ColumnDescriptorBuilderBase column : columns) {
1583
                if( column.isIndexed() ) {
1584
                    String sql;
1585
                    String name = "idx_" + this.table().getName() + column.getName();
1586
                    if( column.isGeometry() ) {
1587
                        sql = MessageFormat.format(
1588
                            config.getString(SQLConfig.CREATE_INDEX_name_ON_table_USING_GIST_column),
1589
                            name,
1590
                            this.table().toString(),
1591
                            column.getName()
1592
                        );
1593
                    } else {
1594
                        sql = MessageFormat.format(
1595
                            config.getString(SQLConfig.CREATE_INDEX_name_ON_table_column),
1596
                            name,
1597
                            this.table().toString(),
1598
                            column.getName()
1599
                        );
1600
                    }
1601
                    sqls.add(sql);
1602
                }
1603
            }            
1604
            return sqls;
1605
        }
1606
    }
1607

    
1608
    public class InsertColumnBuilderBase implements InsertColumnBuilder {
1609
        protected Variable name;
1610
        protected Value value;
1611
        
1612
        public InsertColumnBuilderBase() {
1613
        }
1614

    
1615
        @Override
1616
        public void accept(Visitor visitor, VisitorFilter filter) {
1617
            if( filter.accept(this) ) {
1618
                visitor.visit(this);
1619
            }
1620
            if( this.name != null ) {
1621
                this.name.accept(visitor, filter);
1622
            }
1623
            if( this.value != null ) {
1624
                this.value.accept(visitor, filter);
1625
            }
1626
        }
1627

    
1628
        @Override
1629
        public InsertColumnBuilder name(String name) {
1630
            this.name = variable(name);
1631
            return this;
1632
        }
1633

    
1634
        @Override
1635
        public InsertColumnBuilder with_value(Value value) {
1636
            this.value = value;
1637
            return this;
1638
        }
1639
        
1640
        @Override
1641
        public String getName() {
1642
            return this.name.getName();
1643
        }
1644
        
1645
        @Override
1646
        public Value getValue() {
1647
            return this.value;
1648
        }
1649
        
1650
        @Override
1651
        public String toString() {
1652
            return this.value.toString();
1653
        }
1654
    }
1655
    
1656
    public class InsertBuilderBase implements InsertBuilder {
1657

    
1658
        protected List<InsertColumnBuilder> columns;
1659
        protected TableNameBuilder table;
1660

    
1661
        public InsertBuilderBase() {
1662
            this.columns = new ArrayList<>();
1663
        }
1664

    
1665
        @Override
1666
        public void accept(Visitor visitor, VisitorFilter filter) {
1667
            if( filter.accept(this) ) {
1668
                visitor.visit(this);
1669
            }
1670
            if( this.table != null ) {
1671
                this.table.accept(visitor, filter);
1672
            }
1673
            for (InsertColumnBuilder column : columns) {
1674
                column.accept(visitor, filter);
1675
            }
1676
        }
1677

    
1678
        @Override
1679
        public TableNameBuilder table() {
1680
            if( table == null ) {
1681
                table = createTableNameBuilder();
1682
            }
1683
            return table;
1684
        }
1685

    
1686
        @Override
1687
        public InsertColumnBuilder column() {
1688
            InsertColumnBuilder column = createInsertColumnBuilder();
1689
            this.columns.add(column);
1690
            return column;
1691
        }
1692

    
1693
        @Override
1694
        public String toString() {
1695
            /*
1696
             * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
1697
             * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
1698
             * output_expression [ AS output_name ] [, ...] ]
1699
             */
1700
            StringBuilder builderColumns = new StringBuilder();
1701
            StringBuilder builderValues = new StringBuilder();
1702
            
1703
            boolean first = true;
1704
            for (InsertColumnBuilder column : columns) {
1705
                if (first) {
1706
                    first = false;
1707
                } else {
1708
                    builderColumns.append(", ");
1709
                }
1710
                builderColumns.append(identifier(column.getName()));
1711
            }
1712
            first = true;
1713
            for (InsertColumnBuilder column : columns) {
1714
                if (first) {
1715
                    first = false;
1716
                } else {
1717
                    builderValues.append(", ");
1718
                }
1719
                builderValues.append(column.toString());
1720
            }
1721
            
1722
            String sql = MessageFormat.format(
1723
                    config.getString(SQLConfig.INSERT_INTO_table_columns_VALUES_values),
1724
                    this.table.toString(),
1725
                    builderColumns.toString(),
1726
                    builderValues.toString()
1727
            );
1728
            return sql;
1729

    
1730
        }
1731
    }
1732

    
1733
    public class UpdateTableStatisticsBuilderBase implements UpdateTableStatisticsBuilder {
1734

    
1735
        protected TableNameBuilder table;
1736

    
1737
        @Override
1738
        public void accept(Visitor visitor, VisitorFilter filter) {
1739
            if( filter.accept(this) ) {
1740
                visitor.visit(this);
1741
            }
1742
            if( this.table != null ) {
1743
                this.table.accept(visitor, filter);
1744
            }
1745
        }
1746

    
1747
        @Override
1748
        public TableNameBuilder table() {
1749
            if( table == null ) {
1750
                table = createTableNameBuilder();
1751
            }
1752
            return table;
1753
        }
1754

    
1755
        @Override
1756
        public String toString() {
1757
            StringBuilder builder = new StringBuilder();
1758
            boolean first = true;
1759
            for (String sql : toStrings()) {
1760
                if( StringUtils.isEmpty(sql) ) {
1761
                    continue;
1762
                }
1763
                if (first) {
1764
                    first = false;
1765
                } else {
1766
                    builder.append("; ");
1767
                }
1768
                builder.append(sql);
1769
            }
1770
            return builder.toString();
1771
        }
1772

    
1773
        @Override
1774
        public List<String> toStrings() {
1775
            List<String> sqls = new ArrayList<>();
1776
            
1777
            if( config.has_functionality(SQLConfig.UPDATE_TABLE_STATISTICS_table) ) {
1778
                String sql = MessageFormat.format(
1779
                        config.getString(SQLConfig.UPDATE_TABLE_STATISTICS_table),
1780
                        table.toString()
1781
                    );
1782
                if( !StringUtils.isEmpty(sql) ) {
1783
                    sqls.add(sql);
1784
                }
1785
            }
1786
            return sqls;
1787
        }
1788
    }
1789
    
1790
    public SQLBuilderBase() {
1791
        super();
1792
        config.set(SQLConfig.default_schema, "public");
1793
        config.set(SQLConfig.allowAutomaticValues, true);
1794
        
1795
        config.set(SQLConfig.ST_ExtentAggregate, "ST_Extent({0})");
1796
        config.set(SQLConfig.ST_UnionAggregate, "ST_Union({0})");
1797
        config.set(SQLConfig.count, "COUNT({0})");
1798
        config.set(SQLConfig.count_distinct, "COUNT(DISTINCT {0})");
1799

    
1800
        config.set(SQLConfig.type_boolean, "BOOLEAN");
1801
        config.set(SQLConfig.type_byte, "TINYINT");
1802
        config.set(SQLConfig.type_bytearray, "BYTEA");
1803
        config.set(SQLConfig.type_geometry, "TEXT");
1804
        config.set(SQLConfig.type_char, "CHARACTER(1)");
1805
        config.set(SQLConfig.type_date, "DATE");
1806
        config.set(SQLConfig.type_double, "DOUBLE PRECISION"); //float con 53 bits de mantisa, float(54)
1807
        config.set(SQLConfig.type_numeric_p, "NUMERIC({0})");
1808
        config.set(SQLConfig.type_numeric_ps, "NUMERIC({0},{1})");
1809
        config.set(SQLConfig.type_bigdecimal, "NUMERIC({0},{1})");
1810
        config.set(SQLConfig.type_float, "REAL"); //float con 24 bits de mantisa, float(24)
1811
        config.set(SQLConfig.type_int, "INT");
1812
        config.set(SQLConfig.type_long, "BIGINT");
1813
        config.set(SQLConfig.type_string, "TEXT");
1814
        config.set(SQLConfig.type_string_p, "VARCHAR({0})");
1815
        config.set(SQLConfig.type_time, "TIME");
1816
        config.set(SQLConfig.type_timestamp, "TIMESTAMP");
1817
        config.set(SQLConfig.type_version, "VARCHAR(30)");
1818
        config.set(SQLConfig.type_URI, "TEXT");
1819
        config.set(SQLConfig.type_URL, "TEXT");
1820
        config.set(SQLConfig.type_FILE, "TEXT");
1821
        config.set(SQLConfig.type_FOLDER, "TEXT");
1822

    
1823
        config.set(SQLConfig.DELETE_FROM_table_WHERE_expresion, "DELETE FROM {0} WHERE {1}");
1824
        config.set(SQLConfig.DELETE_FROM_table, "DELETE FROM {0}");
1825
        config.set(SQLConfig.INSERT_INTO_table_columns_VALUES_values, "INSERT INTO {0} ( {1} ) VALUES ( {2} )");
1826
        config.set(SQLConfig.UPDATE_TABLE_STATISTICS_table, "VACUUM ANALYZE {0}");
1827
        config.set(SQLConfig.DROP_TABLE_table, "DROP TABLE {0}");
1828
        config.set(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table, "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_schema = {0} AND f_table_name = {1}");
1829
        config.set(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table, "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_name = {0}");
1830
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues_WHERE_expresion, "UPDATE {0} SET {1} WHERE {2}");
1831
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues, "UPDATE {0} SET {1}");
1832
        config.set(SQLConfig.GRANT_privileges_ON_table_TO_role, "GRANT {0} ON {1} TO {2}");        
1833
        config.set(SQLConfig.CREATE_INDEX_name_ON_table_column, "CREATE INDEX {0} ON {1} ({2})");
1834
        config.set(SQLConfig.CREATE_INDEX_name_ON_table_USING_GIST_column, "CREATE INDEX {0} ON {1} USING GIST ({2})");
1835
    }
1836
    
1837
    @Override
1838
    public String default_schema() {
1839
        return config.getString(SQLConfig.default_schema);
1840
    }
1841

    
1842
    @Override
1843
    public boolean supportSchemas() {
1844
        return config.getBoolean(Config.support_schemas);
1845
    }
1846
    
1847
    @Override
1848
    public String sqltype(int type, int p, int s) {
1849
        switch (type) {
1850
            case DataTypes.BOOLEAN:
1851
                return config.getString(SQLConfig.type_boolean);
1852
            case DataTypes.BYTE:
1853
                return config.getString(SQLConfig.type_byte);
1854
            case DataTypes.BYTEARRAY:
1855
                return config.getString(SQLConfig.type_bytearray);
1856
            case DataTypes.GEOMETRY:
1857
                return config.getString(SQLConfig.type_geometry);
1858
            case DataTypes.CHAR:
1859
                return config.getString(SQLConfig.type_char);
1860
            case DataTypes.DATE:
1861
                return config.getString(SQLConfig.type_date);
1862
            case DataTypes.DOUBLE:
1863
                  // FIXME: Si cargamos la capa "country" al exportarla a
1864
                  // SQLServer falla por:
1865
                  //  Error de desbordamiento aritm?tico al convertir float al tipo de datos numeric.
1866
                  // Al parecer la capa declara la columna sqkm_ctry como Numeric(12,6) y para 
1867
                  // Algeria intenta asignarle un valor de 2320972.0 y falla.
1868
                  // Habria que repasar el proveedor de shape.
1869
                
1870
//                if (p > 1) {
1871
//                    if (s < 0) {
1872
//                        return MessageFormat.format(config.getString(SQLConfig.type_numeric_p), p);
1873
//                    }
1874
//                    return MessageFormat.format(config.getString(SQLConfig.type_numeric_ps), p,s);
1875
//                }
1876
                return MessageFormat.format(config.getString(SQLConfig.type_double),p,s);
1877
            case DataTypes.BIGDECIMAL:
1878
                if (p < 1) {
1879
                    p = 20;
1880
                }
1881
                if (s < 0) {
1882
                    s = 10;
1883
                }
1884
                return MessageFormat.format(config.getString(SQLConfig.type_bigdecimal), p,s);
1885
            case DataTypes.FLOAT:
1886
                return MessageFormat.format(config.getString(SQLConfig.type_float), p,s);
1887
            case DataTypes.INT:
1888
                return MessageFormat.format(config.getString(SQLConfig.type_int), p,s);
1889
            case DataTypes.LONG:
1890
                return MessageFormat.format(config.getString(SQLConfig.type_long), p,s);
1891
            case DataTypes.STRING:
1892
                if (p < 0) {
1893
                    return config.getString(SQLConfig.type_string);
1894
                } else if (p < 4096) {
1895
                    return MessageFormat.format(config.getString(SQLConfig.type_string_p),p);
1896
                }
1897
                return config.getString(SQLConfig.type_string);
1898
            case DataTypes.TIME:
1899
                return config.getString(SQLConfig.type_time);
1900
            case DataTypes.TIMESTAMP:
1901
                return config.getString(SQLConfig.type_timestamp);
1902
            case DataTypes.VERSION:
1903
                return config.getString(SQLConfig.type_version);
1904
            case DataTypes.URI:
1905
                return config.getString(SQLConfig.type_URI);
1906
            case DataTypes.URL:
1907
                return config.getString(SQLConfig.type_URL);
1908
            case DataTypes.FILE:
1909
                return config.getString(SQLConfig.type_FILE);
1910
            case DataTypes.FOLDER:
1911
                return config.getString(SQLConfig.type_FOLDER);
1912
            default:
1913
                return null;
1914
        }
1915
    }
1916

    
1917
    private static Map<Pair<Integer,Integer>,String> sqlgeometrytypes = null;
1918
    
1919
    @Override
1920
    public Object sqlgeometrytype(int type, int subtype) {
1921
        // Devuelve un Object por que algunos gestores de BBDD utilizan
1922
        // identificadores numericos para el tipo y otros strings.
1923
        // Por defecto vamos a devolver strings.
1924
        if( sqlgeometrytypes==null ) {
1925
            sqlgeometrytypes = new HashMap<>();
1926
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM2D), "POINT");
1927
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM3D), "POINTZ");
1928
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM2DM), "POINTM");
1929
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM3DM), "POINTZM");
1930

    
1931
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM2D), "LINESTRING");
1932
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM3D), "LINESTRINGZ");
1933
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM2DM), "LINESTRINGM");
1934
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM3DM), "LINESTRINGZM");
1935

    
1936
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM2D), "POLYGON");
1937
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM3D), "POLYGONZ");
1938
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM2DM), "POLYGONM");
1939
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM3DM), "POLYGONZM");
1940

    
1941
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM2D), "MULTIPOINT");
1942
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM3D), "MULTIPOINTZ");
1943
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM2DM), "MULTIPOINTM");
1944
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM3DM), "MULTIPOINTZM");
1945

    
1946
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM2D), "MULTILINESTRING");
1947
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM3D), "MULTILINESTRINGZ");
1948
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM2DM), "MULTILINESTRINGM");
1949
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM3DM), "MULTILINESTRINGZM");
1950

    
1951
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM2D), "MULTILINESTRING");
1952
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM3D), "MULTILINESTRINGZ");
1953
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM2DM), "MULTILINESTRINGM");
1954
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM3DM), "MULTILINESTRINGZM");
1955

    
1956
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM2D), "MULTIPOLYGON");
1957
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM3D), "MULTIPOLYGONZ");
1958
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM2DM), "MULTIPOLYGONM");
1959
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM3DM), "MULTIPOLYGONZM");
1960

    
1961
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM2D), "MULTIPOLYGON");
1962
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM3D), "MULTIPOLYGONZ");
1963
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM2DM), "MULTIPOLYGONM");
1964
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM3DM), "MULTIPOLYGONZM");
1965

    
1966
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2D), "GEOMETRY");
1967
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3D), "GEOMETRYZ");
1968
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2DM), "GEOMETRYM");
1969
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3DM), "GEOMETRYZM");
1970
        }
1971
        return sqlgeometrytypes.get(new ImmutablePair<>(type,subtype));
1972
    }
1973

    
1974
    @Override
1975
    public Object sqlgeometrydimension(int type, int subtype) {
1976
        // Devuelve un Object por que algunos gestortes de BBDD utilizan
1977
        // identificadores numericos para las dimensiones y otros strings.
1978
        // Por defecto vamos a devolver enteros.
1979
        switch(subtype) {
1980
            case Geometry.SUBTYPES.GEOM3D:
1981
                return 3;
1982
            case Geometry.SUBTYPES.GEOM2DM:
1983
                return 3;
1984
            case Geometry.SUBTYPES.GEOM3DM:
1985
                return 4;
1986
            case Geometry.SUBTYPES.GEOM2D:
1987
            default:
1988
                return 2;
1989
        }
1990
    }
1991
    
1992
    protected TableNameBuilder createTableNameBuilder() {
1993
        return new TableNameBuilderBase();
1994
    }
1995
    
1996
    protected SelectColumnBuilder createSelectColumnBuilder() {
1997
        return new SelectColumnBuilderBase();
1998
    }
1999
    
2000
    protected UpdateColumnBuilder createUpdateColumnBuilder() {
2001
        return new UpdateColumnBuilderBase();
2002
    }
2003
    
2004
    protected InsertColumnBuilder createInsertColumnBuilder() {
2005
        return new InsertColumnBuilderBase();
2006
    }
2007
    
2008
    protected OrderByBuilder createOrderByBuilder() {
2009
        return new OrderByBuilderBase();
2010
    }
2011

    
2012
    protected FromBuilder createFromBuilder() {
2013
        return new FromBuilderBase();
2014
    }
2015

    
2016
    protected SelectBuilder createSelectBuilder() {
2017
        return new SelectBuilderBase();
2018
    }
2019

    
2020
    protected UpdateBuilder createUpdateBuilder() {
2021
        return new UpdateBuilderBase();
2022
    }
2023

    
2024
    protected DeleteBuilder createDeleteBuilder() {
2025
        return new DeleteBuilderBase();
2026
    }
2027

    
2028
    protected GrantBuilder createGrantBuilder() {
2029
        return new GrantBuilderBase();
2030
    }
2031

    
2032
    protected GrantRoleBuilder createGrantRoleBuilder(TableNameBuilder table, String role) {
2033
        return new GrantRoleBuilderBase(table, role);
2034
    }
2035
    
2036
    protected DropTableBuilder createDropTableBuilder() {
2037
        return new DropTableBuilderBase();
2038
    }
2039

    
2040
    protected CreateTableBuilder createCreateTableBuilder() {
2041
        return new CreateTableBuilderBase();
2042
    }
2043

    
2044
    protected AlterTableBuilder createAlterTableBuilder() {
2045
        return new AlterTableBuilderBase();
2046
    }
2047

    
2048
    protected InsertBuilder createInsertBuilder() {
2049
        return new InsertBuilderBase();
2050
    }
2051

    
2052
    protected UpdateTableStatisticsBuilder createUpdateTableStatisticsBuilder() {
2053
        return new UpdateTableStatisticsBuilderBase();
2054
    }
2055

    
2056
    @Override
2057
    public SelectBuilder select() {
2058
        if (this.select == null) {
2059
            this.select = this.createSelectBuilder();
2060
        }
2061
        return this.select;
2062
    }
2063

    
2064
    @Override
2065
    public UpdateBuilder update() {
2066
        if (this.update == null) {
2067
            this.update = this.createUpdateBuilder();
2068
        }
2069
        return this.update;
2070
    }
2071

    
2072
    @Override
2073
    public UpdateTableStatisticsBuilder update_table_statistics() {
2074
        if (this.update_table_statistics == null) {
2075
            this.update_table_statistics = this.createUpdateTableStatisticsBuilder();
2076
        }
2077
        return this.update_table_statistics;
2078
    }
2079

    
2080
    @Override
2081
    public DropTableBuilder drop_table() {
2082
        if (this.drop_table == null) {
2083
            this.drop_table = this.createDropTableBuilder();
2084
        }
2085
        return this.drop_table;
2086
    }
2087

    
2088
    @Override
2089
    public DeleteBuilder delete() {
2090
        if (this.delete == null) {
2091
            this.delete = this.createDeleteBuilder();
2092
        }
2093
        return this.delete;
2094
    }
2095

    
2096
    @Override
2097
    public InsertBuilder insert() {
2098
        if (this.insert == null) {
2099
            this.insert = this.createInsertBuilder();
2100
        }
2101
        return this.insert;
2102
    }
2103

    
2104
    @Override
2105
    public AlterTableBuilder alter_table() {
2106
        if (this.alter_table == null) {
2107
            this.alter_table = this.createAlterTableBuilder();
2108
        }
2109
        return this.alter_table;
2110
    }
2111

    
2112
    @Override
2113
    public CreateTableBuilder create_table() {
2114
        if (this.create_table == null) {
2115
            this.create_table = this.createCreateTableBuilder();
2116
        }
2117
        return this.create_table;
2118
    }
2119

    
2120
    @Override
2121
    public GrantBuilder grant() {
2122
        if (this.grant == null) {
2123
            this.grant = this.createGrantBuilder();
2124
        }
2125
        return this.grant;
2126
    }
2127

    
2128
    @Override
2129
    public void accept(Visitor visitor, VisitorFilter filter) {
2130
        if (this.select != null) {
2131
            this.select.accept(visitor, filter);
2132
        }
2133
        if (this.update != null) {
2134
            this.update.accept(visitor, filter);
2135
        }
2136
        if (this.insert != null) {
2137
            this.insert.accept(visitor, filter);
2138
        }
2139
        if (this.delete != null) {
2140
            this.delete.accept(visitor, filter);
2141
        }
2142
        if (this.alter_table != null) {
2143
            this.alter_table.accept(visitor, filter);
2144
        }
2145
        if (this.create_table != null) {
2146
            this.create_table.accept(visitor, filter);
2147
        }
2148
        if (this.drop_table != null) {
2149
            this.drop_table.accept(visitor, filter);
2150
        }
2151
    }
2152

    
2153
    
2154
    @Override
2155
    public String toString() {
2156
        if (this.select != null) {
2157
            return this.select.toString();
2158
        }
2159
        if (this.update != null) {
2160
            return this.update.toString();
2161
        }
2162
        if (this.insert != null) {
2163
            return this.insert.toString();
2164
        }
2165
        if (this.delete != null) {
2166
            return this.delete.toString();
2167
        }
2168
        if (this.alter_table != null) {
2169
            return this.alter_table.toString();
2170
        }
2171
        if (this.create_table != null) {
2172
            return this.create_table.toString();
2173
        }
2174
        if (this.drop_table != null) {
2175
            return this.drop_table.toString();
2176
        }
2177
        if (this.update_table_statistics != null) {
2178
            return this.update_table_statistics.toString();
2179
        }
2180
        if ( this.value != null ) {
2181
            return this.value.toString();
2182
        }
2183
        return ""; 
2184
    }
2185

    
2186
    @Override
2187
    public Function ST_UnionAggregate(Value geom) {
2188
        return function("ST_UnionAggregate", config.getString(SQLConfig.ST_UnionAggregate), geom);
2189
    }
2190

    
2191
    @Override
2192
    public Function ST_ExtentAggregate(Value geom) {
2193
        return function("ST_ExtentAggregate", config.getString(SQLConfig.ST_ExtentAggregate), geom);
2194
    }
2195

    
2196
    @Override
2197
    public CountBuilder count() {
2198
        return new CountBuilderBase();
2199
    }
2200

    
2201
}