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

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.geom.Geometry;
35
import org.slf4j.Logger;
36
import org.slf4j.LoggerFactory;
37

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

    
53
    protected class ColumnDescriptorBuilderBase implements ColumnDescriptorBuilder {
54

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
236
    public class TableNameBuilderBase implements TableNameBuilder {
237

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

    
242
        public TableNameBuilderBase() {
243
        }
244

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

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

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

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

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

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

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

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

    
317
    }
318

    
319
    public class CountBuilderBase extends AbstractValue implements CountBuilder {
320

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

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

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

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

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

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

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

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

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

    
419
    }
420

    
421
    public class SelectColumnBuilderBase implements SelectColumnBuilder {
422

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
769
        }
770
    }
771

    
772
    public class DropTableBuilderBase implements DropTableBuilder {
773

    
774
        protected TableNameBuilder table;
775

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1129
    public class DeleteBuilderBase implements DeleteBuilder {
1130

    
1131
        protected ExpressionBuilder where;
1132
        protected TableNameBuilder table;
1133

    
1134
        public DeleteBuilderBase() {
1135
        }
1136

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

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

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

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

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

    
1194
    public class AlterTableBuilderBase implements AlterTableBuilder {
1195

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

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

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

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

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

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

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

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

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

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

1288
             where action is one of:
1289

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

1325
             and table_constraint_using_index is:
1326

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

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

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

    
1428
            return sqls;
1429
        }
1430

    
1431
    }
1432

    
1433
    public class CreateTableBuilderBase implements CreateTableBuilder {
1434

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1729
        }
1730
    }
1731

    
1732
    public class UpdateTableStatisticsBuilderBase implements UpdateTableStatisticsBuilder {
1733

    
1734
        protected TableNameBuilder table;
1735

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2200
}