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

History | View | Annotate | Download (61.8 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.gvsig.fmap.dal.DataTypes;
14
import org.gvsig.fmap.dal.ExpressionBuilder;
15
import org.gvsig.fmap.dal.SQLBuilder;
16
import org.gvsig.fmap.dal.SQLBuilder.AlterTableBuilder;
17
import org.gvsig.fmap.dal.SQLBuilder.CreateTableBuilder;
18
import org.gvsig.fmap.dal.SQLBuilder.DeleteBuilder;
19
import org.gvsig.fmap.dal.SQLBuilder.DropTableBuilder;
20
import org.gvsig.fmap.dal.SQLBuilder.FromBuilder;
21
import org.gvsig.fmap.dal.SQLBuilder.GrantBuilder;
22
import org.gvsig.fmap.dal.SQLBuilder.InsertBuilder;
23
import org.gvsig.fmap.dal.SQLBuilder.InsertColumnBuilder;
24
import org.gvsig.fmap.dal.SQLBuilder.OrderByBuilder;
25
import org.gvsig.fmap.dal.SQLBuilder.Privilege;
26
import org.gvsig.fmap.dal.SQLBuilder.SQLConfig;
27
import org.gvsig.fmap.dal.SQLBuilder.SelectBuilder;
28
import org.gvsig.fmap.dal.SQLBuilder.SelectColumnBuilder;
29
import org.gvsig.fmap.dal.SQLBuilder.TableNameBuilder;
30
import org.gvsig.fmap.dal.SQLBuilder.UpdateBuilder;
31
import org.gvsig.fmap.dal.SQLBuilder.UpdateColumnBuilder;
32
import org.gvsig.fmap.dal.SQLBuilder.UpdateTableStatisticsBuilder;
33
import org.slf4j.Logger;
34
import org.slf4j.LoggerFactory;
35

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

    
51
    protected class ColumnInfo {
52

    
53
        public String name;
54
        public int type;
55
        public int type_p;
56
        public int type_s;
57
        public boolean isPk;
58
        public boolean allowNulls;
59
        public boolean isAutomatic;
60
        public Object defaultValue;
61

    
62
        public ColumnInfo(String name, int type, Object defaultValue) {
63
            this.name = name;
64
            this.type = type;
65
            this.type_p = -1;
66
            this.type_s = -1;
67
            this.isPk = false;
68
            this.allowNulls = true;
69
            this.isAutomatic = false;
70
            this.defaultValue = defaultValue;
71
        }
72

    
73
        public ColumnInfo(String name, int type, int type_p, int type_s, boolean isPk, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
74
            this.name = name;
75
            this.type = type;
76
            this.type_p = type_p;
77
            this.type_s = type_s;
78
            this.isPk = isPk;
79
            this.allowNulls = allowNulls;
80
            this.isAutomatic = isAutomatic;
81
            this.defaultValue = defaultValue;
82
        }
83
    }
84

    
85
    public class TableNameBuilderBase implements TableNameBuilder {
86

    
87
        public String tableName;
88
        public String schemaName;
89
        private String databaseName;
90

    
91
        public TableNameBuilderBase() {
92
        }
93

    
94
        @Override
95
        public void accept(Visitor visitor, VisitorFilter filter) {
96
            if( filter.accept(this) ) {
97
                visitor.visit(this);
98
            }
99
        }
100

    
101
        @Override
102
        public TableNameBuilder database(String name) {
103
            this.databaseName = name;
104
            return this;
105
        }
106

    
107
        @Override
108
        public TableNameBuilder schema(String name) {
109
            this.schemaName = name;
110
            return this;
111
        }
112

    
113
        @Override
114
        public TableNameBuilder name(String name) {
115
            this.tableName = name;
116
            return this;
117
        }
118

    
119
        @Override
120
        public String getDatabase() {
121
            return this.databaseName;
122
        }
123

    
124
        @Override
125
        public String getSchema() {
126
            return this.schemaName;
127
        }
128

    
129
        @Override
130
        public String getName() {
131
            return this.tableName;
132
        }
133
        
134
        @Override
135
        public boolean has_schema() {
136
            return !StringUtils.isEmpty(this.schemaName);
137
        }
138

    
139
        @Override
140
        public boolean has_database() {
141
            return !StringUtils.isEmpty(this.databaseName);
142
        }
143
        
144
        @Override
145
        public String toString() {
146
            if( this.has_database()) {
147
                if( this.has_schema()) {
148
                    return identifier(this.databaseName) + "." + 
149
                           identifier(this.schemaName) + "." + 
150
                           identifier(this.tableName);
151
                }
152
            } else {
153
                if( this.has_schema()) {
154
                    return identifier(this.schemaName) + "." + 
155
                           identifier(this.tableName);
156
                }                
157
            }
158
            return identifier(this.tableName);
159
        }
160

    
161
    }
162

    
163
    public class CountBuilderBase extends AbstractValue implements CountBuilder {
164

    
165
        protected Value value;
166
        protected boolean distinct;
167
        protected boolean all ;
168
        
169
        public CountBuilderBase() {
170
            this.value = null;
171
            this.distinct = false;
172
            this.all = false;
173
        }
174
        
175
        @Override
176
        public CountBuilder all() {
177
            this.all = true;
178
            return this;
179
        }
180

    
181
        @Override
182
        public CountBuilder column(Value value) {
183
            this.value = value;
184
            return this;
185
        }
186

    
187
        @Override
188
        public CountBuilder distinct() {
189
            this.distinct = true;
190
            return this;
191
        }
192

    
193
        @Override
194
        public String toString() {
195
            if( this.all ) {
196
                return MessageFormat.format(
197
                    config.getString(SQLConfig.count),
198
                    "*"
199
                );
200
            }
201
            if( this.distinct ) {
202
                return MessageFormat.format(
203
                    config.getString(SQLConfig.count_distinct),
204
                    value.toString()
205
                );
206
            }
207
            return MessageFormat.format(
208
                config.getString(SQLConfig.count),
209
                value.toString()
210
            );
211
        }
212
        
213
        
214
    }
215
    
216
    public class FromBuilderBase implements FromBuilder {
217

    
218
        protected TableNameBuilder tableName= null;
219
        private String subquery = null;
220
        private String passthrough = null;
221

    
222
        @Override
223
        public TableNameBuilder table() {
224
            if( tableName == null ) {
225
                this.tableName = new TableNameBuilderBase();
226
            }
227
            return this.tableName;
228
        }
229

    
230
        @Override
231
        public void accept(Visitor visitor, VisitorFilter filter) {
232
            if( filter.accept(this) ) {
233
                visitor.visit(this);
234
            }
235
            if( this.tableName != null ) {
236
                this.tableName.accept(visitor, filter);
237
            }
238
        }
239

    
240
        @Override
241
        public FromBuilder custom(String passthrough) {
242
            this.passthrough = passthrough;
243
            return this;
244
        }
245

    
246
        @Override
247
        public FromBuilder subquery(String subquery) {
248
            this.subquery = subquery;
249
            return this;
250
        }
251
        
252
        @Override
253
        public String toString() {
254
            if( ! StringUtils.isEmpty(passthrough) ) {
255
                return passthrough;
256
            }
257
            if( ! StringUtils.isEmpty(subquery) ) {
258
                return "( " + this.subquery + ") as _subquery_alias_ ";
259
            }
260
            return this.tableName.toString();
261
        }
262

    
263
    }
264

    
265
    public class SelectColumnBuilderBase implements SelectColumnBuilder {
266

    
267
        private Variable name = null;
268
        private String alias = null;
269
        private Value value = null;
270
        private boolean asGeometry = false;
271
        
272
        @Override
273
        public void accept(Visitor visitor, VisitorFilter filter) {
274
            if( filter.accept(this) ) {
275
                visitor.visit(this);
276
            }
277
            if( this.name != null ) {
278
                this.name.accept(visitor, filter);
279
            }
280
            if( this.value != null ) {
281
                this.value.accept(visitor, filter);
282
            }
283
        }
284

    
285
        @Override
286
        public SelectColumnBuilder name(String name) {
287
            String quote = config.getString(Config.quote_for_identifiers);
288
            if (name.startsWith(quote)) {
289
                // Remove quotes
290
                name = name.substring(1, name.length() - 1);
291
            }
292
            this.name = variable(name);
293
            this.value = null;
294
            this.asGeometry = false;
295
            return this;
296
        }
297

    
298
        @Override
299
        public SelectColumnBuilder all() {
300
            this.name = null;
301
            this.value = custom("*");
302
            this.asGeometry = false;
303
            return this;
304
        }
305
        
306
        @Override
307
        public SelectColumnBuilder as_geometry() {
308
            this.asGeometry = true;
309
            return this;
310
        }
311
       
312
        @Override
313
        public SelectColumnBuilder value(Value value) {
314
            this.value = value;
315
            this.name = null;
316
            return this;
317
        }
318

    
319
        @Override
320
        public SelectColumnBuilder as(String alias) {
321
            this.alias = alias;
322
            return this;
323
        }
324

    
325
        @Override
326
        public String getName() {
327
            return this.name.getName();
328
        }
329
        
330
        @Override
331
        public String getAlias() {
332
            return this.alias;
333
        }
334
        
335
        @Override
336
        public String getValue() {
337
            return this.alias;
338
        }
339

    
340
        @Override
341
        public String toString() {
342
            StringBuilder builder = new StringBuilder();
343
            if( this.asGeometry ) {
344
                builder.append(getAsGeometry(this.name).toString());
345
            } else {
346
                if( this.name != null ) {
347
                    builder.append(this.name.toString());
348
                } else {
349
                    builder.append(this.value.toString());
350
                }
351
            }
352
            if( this.alias != null ) {
353
                builder.append(" AS ");
354
                builder.append(identifier(this.alias));
355
            }
356
            return builder.toString();
357
        }
358
    }
359

    
360
    public class OrderByBuilderBase implements OrderByBuilder {
361
        protected String value;
362
        protected String custom;
363
        protected boolean ascending;
364
        
365
        public OrderByBuilderBase() {
366
            
367
        }
368

    
369
        @Override
370
        public void accept(Visitor visitor, VisitorFilter filter) {
371
            if( filter.accept(this) ) {
372
                visitor.visit(this);
373
            }
374
        }
375

    
376
        @Override
377
        public OrderByBuilder column(String name) {
378
            this.value = name;
379
            return this;
380
        }
381

    
382
        @Override
383
        public OrderByBuilder custom(String order) {
384
            this.custom = order;
385
            return this;
386
        }
387

    
388
        @Override
389
        public OrderByBuilder ascending() {
390
            this.ascending = true;
391
            return this;
392
        }
393

    
394
        @Override
395
        public OrderByBuilder ascending(boolean asc) {
396
            this.ascending = asc;
397
            return this;
398
        }
399

    
400
        @Override
401
        public OrderByBuilder descending() {
402
            this.ascending = false;
403
            return this;
404
        }
405

    
406
        @Override
407
        public String toString() {
408
            if( !StringUtils.isEmpty(this.custom) ) {
409
                return this.custom;
410
            }
411
            if( this.ascending ) {
412
                return this.value + "ASC";
413
            }
414
            return this.value + "DESC";
415
        }
416
    }
417
    
418
    public class SelectBuilderBase implements SelectBuilder {
419

    
420
        protected FromBuilder from;
421
        protected ExpressionBuilder where;
422
        protected long limit = -1;
423
        protected long offset = -1;
424
        protected List<SelectColumnBuilder> columns;
425
        protected List<OrderByBuilder> order_by;
426
        protected boolean distinct;
427

    
428
        public SelectBuilderBase() {
429
            this.columns = new ArrayList<>();
430
            this.distinct = false;
431
        }
432

    
433
        @Override
434
        public void accept(Visitor visitor, VisitorFilter filter) {
435
            if( filter.accept(this) ) {
436
                visitor.visit(this);
437
            }
438
            for (SelectColumnBuilder column : columns) {
439
                column.accept(visitor,filter);
440
            }
441
            if( this.has_from() ) {
442
                this.from.accept(visitor,filter);
443
            }
444
            if( this.has_where() ) {
445
                this.where.accept(visitor,filter);
446
            }
447
            if( this.has_order_by() ) {
448
                for (OrderByBuilder order : order_by) {
449
                    order.accept(visitor,filter);
450
                }
451
            }
452
        }
453

    
454
        @Override
455
        public SelectBuilder distinct() {
456
            this.distinct = true;
457
            return this;
458
        }
459
        
460
        @Override
461
        public SelectColumnBuilder column() {
462
            SelectColumnBuilder builder = createSelectColumnBuilder();
463
            this.columns.add(builder);
464
            return builder;
465
        }
466

    
467
        @Override
468
        public boolean has_column(String name) {
469
            for (SelectColumnBuilder column : columns) {
470
                if( name.equals(column.getName()) ) {
471
                    return true;
472
                }
473
            }
474
            return false;
475
        }
476

    
477
        @Override
478
        public FromBuilder from() {
479
            if (this.from == null) {
480
                this.from = createFromBuilder();
481
            }
482
            return this.from;
483
        }
484

    
485
        @Override
486
        public boolean has_from() {
487
            return this.from != null;
488
        }
489
        
490
        @Override
491
        public ExpressionBuilder where() {
492
            if (this.where == null) {
493
                this.where = createExpressionBuilder();
494
            }
495
            return this.where;
496
        }
497

    
498
        @Override
499
        public boolean has_where() {
500
            if( this.where == null ) {
501
                return false;
502
            }
503
            return this.where.getValue() != null;
504
        }
505
        
506
        @Override
507
        public SelectBuilder limit(long limit) {
508
            this.limit = limit;
509
            return this;
510
        }
511

    
512
        @Override
513
        public boolean has_limit() {
514
            return this.limit > 0;
515
        }
516

    
517
        @Override
518
        public SelectBuilder offset(long offset) {
519
            this.offset = offset;
520
            return this;
521
        }
522

    
523
        @Override
524
        public boolean has_offset() {
525
            return this.offset > 0;
526
        }
527

    
528
        @Override
529
        public OrderByBuilder order_by() {
530
            OrderByBuilder order = createOrderByBuilder();
531
            this.order_by.add(order);
532
            return order;
533
        }
534

    
535
        @Override
536
        public boolean has_order_by() {
537
            if( this.order_by == null ) {
538
                return false;
539
            }
540
            return !this.order_by.isEmpty();
541
        }
542
        
543
        @Override
544
        public String toString() {
545
            StringBuilder builder = new StringBuilder();
546

    
547
            builder.append("SELECT ");
548
            if( this.distinct ) {
549
                builder.append("DISTINCT ");
550
            }
551
            boolean first = true;
552
            for (SelectColumnBuilder column : columns) {
553
                if (first) {
554
                    first = false;
555
                } else {
556
                    builder.append(", ");
557
                }
558
                builder.append(column.toString());
559
            }
560

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

    
593
        }
594
    }
595

    
596
    public class DropTableBuilderBase implements DropTableBuilder {
597

    
598
        protected TableNameBuilder table;
599

    
600
        @Override
601
        public TableNameBuilder table() {
602
            if( table == null ) {
603
                table = new TableNameBuilderBase();
604
            }
605
            return table;
606
        }
607

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

    
634
        @Override
635
        public List<String> toStrings() {
636
            List<String> sqls = new ArrayList<>();
637

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

    
666
    public class GrantRoleBuilderBase implements GrantRoleBuilder {
667
        protected TableNameBuilder table;
668
        protected String role;
669
        protected Set<Privilege> privileges;
670

    
671
        public GrantRoleBuilderBase(TableNameBuilder table, String role) {
672
            this.table = table;
673
            this.role = role;
674
            this.privileges = new HashSet<>();
675
        }
676

    
677
        @Override
678
        public GrantRoleBuilder privilege(Privilege privilege) {
679
            privileges.add(privilege);
680
            return this;
681
        }
682
        
683
        @Override
684
        public GrantRoleBuilder select() {
685
             privileges.add(Privilege.SELECT);
686
            return this;
687
        }
688

    
689
        @Override
690
        public GrantRoleBuilder update() {
691
             privileges.add(Privilege.UPDATE);
692
            return this;
693
        }
694

    
695
        @Override
696
        public GrantRoleBuilder insert() {
697
            privileges.add(Privilege.INSERT);
698
            return this;
699
        }
700

    
701
        @Override
702
        public GrantRoleBuilder delete() {
703
            privileges.add(Privilege.DELETE);
704
            return this;
705
        }
706

    
707
        @Override
708
        public GrantRoleBuilder truncate() {
709
            privileges.add(Privilege.TRUNCATE);
710
            return this;
711
        }
712

    
713
        @Override
714
        public GrantRoleBuilder reference() {
715
            privileges.add(Privilege.REFERENCE);
716
            return this;
717
        }
718

    
719
        @Override
720
        public GrantRoleBuilder trigger() {
721
            privileges.add(Privilege.TRIGGER);
722
            return this;
723
        }
724

    
725
        @Override
726
        public GrantRoleBuilder all() {
727
            privileges.add(Privilege.ALL);
728
            return this;
729
        }
730

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

    
777
        protected TableNameBuilder table;
778
        protected Map<String, GrantRoleBuilder> roles;
779

    
780
        public GrantBuilderBase() {
781
            this.roles = new HashMap<>();
782
        }
783
        
784
        @Override
785
        public TableNameBuilder table() {
786
            if( table == null ) {
787
                table = new TableNameBuilderBase();
788
            }
789
            return table;
790
        }
791

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

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

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

    
840
    public class UpdateColumnBuilderBase extends InsertColumnBuilderBase implements UpdateColumnBuilder {
841
        
842
        public UpdateColumnBuilderBase() {
843
            super();
844
        }
845

    
846
        @Override
847
        public UpdateColumnBuilder name(String name) {
848
            return (UpdateColumnBuilder) super.name(name);
849
        }
850

    
851
        @Override
852
        public UpdateColumnBuilder with_value(Value value) {
853
            return (UpdateColumnBuilder) super.with_value(value);
854
        }
855
        
856
    }
857
    
858
    public class UpdateBuilderBase implements UpdateBuilder {
859

    
860
        protected ExpressionBuilder where;
861
        protected List<UpdateColumnBuilder> columns;
862
        protected TableNameBuilder table;
863

    
864
        public UpdateBuilderBase() {
865
            this.columns = new ArrayList<>();
866
        }
867

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

    
884
        @Override
885
        public ExpressionBuilder where() {
886
            if (this.where == null) {
887
                this.where = createExpressionBuilder();
888
            }
889
            return this.where;
890
        }
891

    
892
        @Override
893
        public TableNameBuilder table() {
894
            if( table == null ) {
895
                table = new TableNameBuilderBase();
896
            }
897
            return table;
898
        }
899

    
900
        @Override
901
        public UpdateColumnBuilder column() {
902
            UpdateColumnBuilder column = createUpdateColumnBuilder();
903
            this.columns.add(column);
904
            return column;
905
        }
906
        
907
        @Override
908
        public boolean has_where() {
909
            return this.where != null;
910
        }
911

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

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

    
953
    public class DeleteBuilderBase implements DeleteBuilder {
954

    
955
        protected ExpressionBuilder where;
956
        protected TableNameBuilder table;
957

    
958
        public DeleteBuilderBase() {
959
        }
960

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

    
974
        @Override
975
        public ExpressionBuilder where() {
976
            if (this.where == null) {
977
                this.where = createExpressionBuilder();
978
            }
979
            return this.where;
980
        }
981

    
982
        @Override
983
        public TableNameBuilder table() {
984
            if( table == null ) {
985
                table = new TableNameBuilderBase();
986
            }
987
            return table;
988
        }
989

    
990
        @Override
991
        public boolean has_where() {
992
            return this.where != null;
993
        }
994

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

    
1018
    public class AlterTableBuilderBase implements AlterTableBuilder {
1019

    
1020
        protected TableNameBuilder table;
1021
        protected List<String> drops;
1022
        protected List<ColumnInfo> adds;
1023
        protected List<ColumnInfo> alters;
1024
        protected List<Pair> renames;
1025

    
1026
        public AlterTableBuilderBase() {
1027
            this.drops = new ArrayList<>();
1028
            this.adds = new ArrayList<>();
1029
            this.alters = new ArrayList<>();
1030
            this.renames = new ArrayList<>();
1031
        }
1032

    
1033
        @Override
1034
        public void accept(Visitor visitor, VisitorFilter filter) {
1035
            if( filter.accept(this) ) {
1036
                visitor.visit(this);
1037
            }
1038
            if( this.table != null ) {
1039
                this.table.accept(visitor, filter);
1040
            }
1041
        }
1042

    
1043
        @Override
1044
        public TableNameBuilder table() {
1045
            if( table == null ) {
1046
                table = new TableNameBuilderBase();
1047
            }
1048
            return table;
1049
        }
1050

    
1051
        @Override
1052
        public AlterTableBuilder drop_column(String columnName) {
1053
            this.drops.add(columnName);
1054
            return this;
1055
        }
1056

    
1057
        @Override
1058
        public AlterTableBuilder add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1059
            if (isPk || isAutomatic) {
1060
                allowNulls = false;
1061
            }
1062
            this.adds.add(new ColumnInfo(columnName, type, type_p, type_s, isPk, allowNulls, isAutomatic, defaultValue));
1063
            return this;
1064
        }
1065

    
1066
        @Override
1067
        public AlterTableBuilder alter_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1068
            if (isPk || isAutomatic) {
1069
                allowNulls = false;
1070
            }
1071
            this.alters.add(new ColumnInfo(columnName, type, type_p, type_s, isPk, allowNulls, isAutomatic, defaultValue));
1072
            return this;
1073
        }
1074

    
1075
        @Override
1076
        public AlterTableBuilder rename_column(String source, String target) {
1077
            this.renames.add(new ImmutablePair(source, target));
1078
            return this;
1079
        }
1080

    
1081
        @Override
1082
        public String toString() {
1083
            StringBuilder builder = new StringBuilder();
1084
            boolean first = true;
1085
            for (String sql : toStrings()) {
1086
                if( StringUtils.isEmpty(sql) ) {
1087
                    continue;
1088
                }
1089
                if (first) {
1090
                    first = false;
1091
                } else {
1092
                    builder.append("; ");
1093
                }
1094
                builder.append(sql);
1095
            }
1096
            return builder.toString();
1097
        }
1098

    
1099
        @Override
1100
        public List<String> toStrings() {
1101
            List<String> sqls = new ArrayList<>();
1102
            /*
1103
             ALTER TABLE [ ONLY ] name [ * ]
1104
             action [, ... ]
1105
             ALTER TABLE [ ONLY ] name [ * ]
1106
             RENAME [ COLUMN ] column TO new_column
1107
             ALTER TABLE name
1108
             RENAME TO new_name
1109
             ALTER TABLE name
1110
             SET SCHEMA new_schema
1111

1112
             where action is one of:
1113

1114
             ADD [ COLUMN ] column data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
1115
             DROP [ COLUMN ] [ IF EXISTS ] column [ RESTRICT | CASCADE ]
1116
             ALTER [ COLUMN ] column [ SET DATA ] TYPE data_type [ COLLATE collation ] [ USING expression ]
1117
             ALTER [ COLUMN ] column SET DEFAULT expression
1118
             ALTER [ COLUMN ] column DROP DEFAULT
1119
             ALTER [ COLUMN ] column { SET | DROP } NOT NULL
1120
             ALTER [ COLUMN ] column SET STATISTICS integer
1121
             ALTER [ COLUMN ] column SET ( attribute_option = value [, ... ] )
1122
             ALTER [ COLUMN ] column RESET ( attribute_option [, ... ] )
1123
             ALTER [ COLUMN ] column SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
1124
             ADD table_constraint [ NOT VALID ]
1125
             ADD table_constraint_using_index
1126
             VALIDATE CONSTRAINT constraint_name
1127
             DROP CONSTRAINT [ IF EXISTS ]  constraint_name [ RESTRICT | CASCADE ]
1128
             DISABLE TRIGGER [ trigger_name | ALL | USER ]
1129
             ENABLE TRIGGER [ trigger_name | ALL | USER ]
1130
             ENABLE REPLICA TRIGGER trigger_name
1131
             ENABLE ALWAYS TRIGGER trigger_name
1132
             DISABLE RULE rewrite_rule_name
1133
             ENABLE RULE rewrite_rule_name
1134
             ENABLE REPLICA RULE rewrite_rule_name
1135
             ENABLE ALWAYS RULE rewrite_rule_name
1136
             CLUSTER ON index_name
1137
             SET WITHOUT CLUSTER
1138
             SET WITH OIDS
1139
             SET WITHOUT OIDS
1140
             SET ( storage_parameter = value [, ... ] )
1141
             RESET ( storage_parameter [, ... ] )
1142
             INHERIT parent_table
1143
             NO INHERIT parent_table
1144
             OF type_name
1145
             NOT OF
1146
             OWNER TO new_owner
1147
             SET TABLESPACE new_tablespace
1148

1149
             and table_constraint_using_index is:
1150

1151
             [ CONSTRAINT constraint_name ]
1152
             { UNIQUE | PRIMARY KEY } USING INDEX index_name
1153
             [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1154

1155
             */
1156
            StringBuilder builder = new StringBuilder();
1157

    
1158
            builder.append("ALTER TABLE");
1159
            builder.append(this.table.toString());
1160
            builder.append(" ");
1161
            boolean first = true;
1162
            for (String column : drops) {
1163
                if (first) {
1164
                    first = false;
1165
                } else {
1166
                    builder.append(", ");
1167
                }
1168
                builder.append("DROP COLUMN IF EXISTS ");
1169
                builder.append(column);
1170
            }
1171
            first = drops.isEmpty();
1172
            for (ColumnInfo column : adds) {
1173
                if (first) {
1174
                    first = false;
1175
                } else {
1176
                    builder.append(", ");
1177
                }
1178
                builder.append("ADD COLUMN ");
1179
                builder.append(column.name);
1180
                builder.append(" ");
1181
                if( column.type == DataTypes.INT && column.isAutomatic ) {
1182
                    builder.append(" SERIAL");
1183
                } else {
1184
                    builder.append(sqltype(column.type, column.type_p, column.type_s));
1185
                }
1186
                if (column.defaultValue == null) {
1187
                    if (column.allowNulls) {
1188
                        builder.append(" DEFAULT NULL");
1189
                    }
1190
                } else {
1191
                    builder.append(" DEFAULT '");
1192
                    builder.append(column.defaultValue.toString());
1193
                    builder.append("'");
1194
                }
1195
                if (column.allowNulls) {
1196
                    builder.append(" NULL");
1197
                } else {
1198
                    builder.append(" NOT NULL");
1199
                }
1200
                if (column.isPk) {
1201
                    builder.append(" PRIMARY KEY");
1202
                }
1203
            }
1204
            first = drops.isEmpty() && adds.isEmpty();
1205
            for (ColumnInfo column : alters) {
1206
                if (first) {
1207
                    first = false;
1208
                } else {
1209
                    builder.append(", ");
1210
                }
1211
                builder.append("ALTER COLUMN ");
1212
                builder.append(column.name);
1213
                builder.append("SET DATA TYPE ");
1214
                if( column.type == DataTypes.INT && column.isAutomatic ) {
1215
                    builder.append(" SERIAL");
1216
                } else {
1217
                    builder.append(sqltype(column.type, column.type_p, column.type_s));
1218
                }
1219
                builder.append(", ");
1220
                if (column.defaultValue == null) {
1221
                    if (column.allowNulls) {
1222
                        builder.append("ALTER COLUMN ");
1223
                        builder.append(column.name);
1224
                        builder.append(" SET DEFAULT NULL");
1225
                    } else {
1226
                        builder.append("ALTER COLUMN ");
1227
                        builder.append(column.name);
1228
                        builder.append(" DROP DEFAULT");
1229
                    }
1230
                } else {
1231
                    builder.append("ALTER COLUMN ");
1232
                    builder.append(column.name);
1233
                    builder.append(" SET DEFAULT '");
1234
                    builder.append(column.defaultValue.toString());
1235
                    builder.append("'");
1236
                }
1237
            }
1238
            first = drops.isEmpty() && adds.isEmpty() && alters.isEmpty();
1239
            for (Pair pair : renames) {
1240
                if (first) {
1241
                    first = false;
1242
                } else {
1243
                    builder.append(", ");
1244
                }
1245
                builder.append("RENAME COLUMN ");
1246
                builder.append(pair.getLeft());
1247
                builder.append(" TO ");
1248
                builder.append(pair.getRight());
1249
            }
1250
            sqls.add(builder.toString());
1251

    
1252
            return sqls;
1253
        }
1254

    
1255
    }
1256

    
1257
    public class CreateTableBuilderBase implements CreateTableBuilder {
1258

    
1259
        protected TableNameBuilder table;
1260
        protected List<ColumnInfo> columns;
1261

    
1262
        public CreateTableBuilderBase() {
1263
            this.columns = new ArrayList<>();
1264
        }
1265

    
1266
        @Override
1267
        public void accept(Visitor visitor, VisitorFilter filter) {
1268
            if( filter.accept(this) ) {
1269
                visitor.visit(this);
1270
            }
1271
            if( this.table != null ) {
1272
                this.table.accept(visitor, filter);
1273
            }
1274
        }
1275

    
1276
        @Override
1277
        public TableNameBuilder table() {
1278
            if( table == null ) {
1279
                table = new TableNameBuilderBase();
1280
            }
1281
            return table;
1282
        }
1283

    
1284
        @Override
1285
        public CreateTableBuilderBase add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1286
            if (isPk || isAutomatic) {
1287
                allowNulls = false;
1288
            }
1289
            this.columns.add(new ColumnInfo(columnName, type, type_p, type_s, isPk, allowNulls, isAutomatic, defaultValue));
1290
            return this;
1291
        }
1292

    
1293
        @Override
1294
        public String toString() {
1295
            StringBuilder builder = new StringBuilder();
1296
            boolean first = true;
1297
            for (String sql : toStrings()) {
1298
                if( StringUtils.isEmpty(sql) ) {
1299
                    continue;
1300
                }
1301
                if (first) {
1302
                    first = false;
1303
                } else {
1304
                    builder.append("; ");
1305
                }
1306
                builder.append(sql);
1307
            }
1308
            return builder.toString();
1309
        }
1310

    
1311
        @Override
1312
        public List<String> toStrings() {
1313
            List<String> sqls = new ArrayList<>();
1314
            /**
1315
             * CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE
1316
             * table_name ( { column_name data_type [ DEFAULT default_expr ] [
1317
             * column_constraint [ ... ] ] | table_constraint | LIKE
1318
             * parent_table [ { INCLUDING | EXCLUDING } DEFAULTS ] } [, ... ] )
1319
             * [ INHERITS ( parent_table [, ... ] ) ] [ WITH OIDS | WITHOUT OIDS
1320
             * ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
1321
             *
1322
             * where column_constraint is:
1323
             *
1324
             * [ CONSTRAINT constraint_name ] { NOT NULL | NULL | UNIQUE |
1325
             * PRIMARY KEY | CHECK (expression) | REFERENCES reftable [ (
1326
             * refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON
1327
             * DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE | NOT
1328
             * DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1329
             *
1330
             * and table_constraint is:
1331
             *
1332
             * [ CONSTRAINT constraint_name ] { UNIQUE ( column_name [, ... ] )
1333
             * | PRIMARY KEY ( column_name [, ... ] ) | CHECK ( expression ) |
1334
             * FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ (
1335
             * refcolumn [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH
1336
             * SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE
1337
             * | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1338
             */
1339
            StringBuilder builder = new StringBuilder();
1340

    
1341
            builder.append("CREATE TABLE ");
1342
            builder.append(this.table.toString());
1343
            builder.append(" (");
1344
            boolean first = true;
1345
            for (ColumnInfo column : columns) {
1346
                if (first) {
1347
                    first = false;
1348
                } else {
1349
                    builder.append(", ");
1350
                }
1351
                builder.append(identifier(column.name));
1352
                builder.append(" ");
1353
                if( column.isAutomatic && column.type == DataTypes.INT ) {
1354
                    builder.append("SERIAL");
1355
                } else if( column.isAutomatic && column.type == DataTypes.LONG ) {
1356
                    builder.append("BIGSERIAL");
1357
                } else {
1358
                    builder.append(sqltype(column.type, column.type_p, column.type_s));
1359
                }
1360
                if (column.defaultValue == null) {
1361
                    if (column.allowNulls) {
1362
                        builder.append(" DEFAULT NULL");
1363
                    }
1364
                } else {
1365
                    builder.append(" DEFAULT '");
1366
                    builder.append(column.defaultValue.toString());
1367
                    builder.append("'");
1368
                }
1369
                if (column.allowNulls) {
1370
                    builder.append(" NULL");
1371
                } else {
1372
                    builder.append(" NOT NULL");
1373
                }
1374
                if (column.isPk) {
1375
                    builder.append(" PRIMARY KEY");
1376
                }
1377
            }
1378
            builder.append(" )");
1379
            sqls.add(builder.toString());
1380

    
1381
            return sqls;
1382
        }
1383
    }
1384

    
1385
    public class InsertColumnBuilderBase implements InsertColumnBuilder {
1386
        protected Variable name;
1387
        protected Value value;
1388
        
1389
        public InsertColumnBuilderBase() {
1390
        }
1391

    
1392
        @Override
1393
        public void accept(Visitor visitor, VisitorFilter filter) {
1394
            if( filter.accept(this) ) {
1395
                visitor.visit(this);
1396
            }
1397
            if( this.name != null ) {
1398
                this.name.accept(visitor, filter);
1399
            }
1400
            if( this.value != null ) {
1401
                this.value.accept(visitor, filter);
1402
            }
1403
        }
1404

    
1405
        @Override
1406
        public InsertColumnBuilder name(String name) {
1407
            this.name = variable(name);
1408
            return this;
1409
        }
1410

    
1411
        @Override
1412
        public InsertColumnBuilder with_value(Value value) {
1413
            this.value = value;
1414
            return this;
1415
        }
1416
        
1417
        @Override
1418
        public String getName() {
1419
            return this.name.getName();
1420
        }
1421
        
1422
        @Override
1423
        public Value getValue() {
1424
            return this.value;
1425
        }
1426
        
1427
        @Override
1428
        public String toString() {
1429
            return this.value.toString();
1430
        }
1431
    }
1432
    
1433
    public class InsertBuilderBase implements InsertBuilder {
1434

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

    
1438
        public InsertBuilderBase() {
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
            for (InsertColumnBuilder column : columns) {
1451
                column.accept(visitor, filter);
1452
            }
1453
        }
1454

    
1455
        @Override
1456
        public TableNameBuilder table() {
1457
            if( table == null ) {
1458
                table = new TableNameBuilderBase();
1459
            }
1460
            return table;
1461
        }
1462

    
1463
        @Override
1464
        public InsertColumnBuilder column() {
1465
            InsertColumnBuilder column = createInsertColumnBuilder();
1466
            this.columns.add(column);
1467
            return column;
1468
        }
1469

    
1470
        @Override
1471
        public String toString() {
1472
            /*
1473
             * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
1474
             * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
1475
             * output_expression [ AS output_name ] [, ...] ]
1476
             */
1477
            StringBuilder builderColumns = new StringBuilder();
1478
            StringBuilder builderValues = new StringBuilder();
1479
            
1480
            boolean first = true;
1481
            for (InsertColumnBuilder column : columns) {
1482
                if (first) {
1483
                    first = false;
1484
                } else {
1485
                    builderColumns.append(", ");
1486
                }
1487
                builderColumns.append(identifier(column.getName()));
1488
            }
1489
            first = true;
1490
            for (InsertColumnBuilder column : columns) {
1491
                if (first) {
1492
                    first = false;
1493
                } else {
1494
                    builderValues.append(", ");
1495
                }
1496
                builderValues.append(column.toString());
1497
            }
1498
            
1499
            String sql = MessageFormat.format(
1500
                    config.getString(SQLConfig.INSERT_INTO_table_columns_VALUES_values),
1501
                    this.table.toString(),
1502
                    builderColumns.toString(),
1503
                    builderValues.toString()
1504
            );
1505
            return sql;
1506

    
1507
        }
1508
    }
1509

    
1510
    public class UpdateTableStatisticsBuilderBase implements UpdateTableStatisticsBuilder {
1511

    
1512
        protected TableNameBuilder table;
1513

    
1514
        @Override
1515
        public void accept(Visitor visitor, VisitorFilter filter) {
1516
            if( filter.accept(this) ) {
1517
                visitor.visit(this);
1518
            }
1519
            if( this.table != null ) {
1520
                this.table.accept(visitor, filter);
1521
            }
1522
        }
1523

    
1524
        @Override
1525
        public TableNameBuilder table() {
1526
            if( table == null ) {
1527
                table = new TableNameBuilderBase();
1528
            }
1529
            return table;
1530
        }
1531

    
1532
        @Override
1533
        public String toString() {
1534
            StringBuilder builder = new StringBuilder();
1535
            boolean first = true;
1536
            for (String sql : toStrings()) {
1537
                if( StringUtils.isEmpty(sql) ) {
1538
                    continue;
1539
                }
1540
                if (first) {
1541
                    first = false;
1542
                } else {
1543
                    builder.append("; ");
1544
                }
1545
                builder.append(sql);
1546
            }
1547
            return builder.toString();
1548
        }
1549

    
1550
        @Override
1551
        public List<String> toStrings() {
1552
            List<String> sqls = new ArrayList<>();
1553
            
1554
            if( config.has_functionality(SQLConfig.UPDATE_TABLE_STATISTICS_table) ) {
1555
                String sql = MessageFormat.format(
1556
                        config.getString(SQLConfig.UPDATE_TABLE_STATISTICS_table),
1557
                        table.toString()
1558
                    );
1559
                if( !StringUtils.isEmpty(sql) ) {
1560
                    sqls.add(sql);
1561
                }
1562
            }
1563
            return sqls;
1564
        }
1565
    }
1566
    
1567
    public SQLBuilderBase() {
1568
        super();
1569
        config.set(SQLConfig.default_schema, "public");
1570
        config.set(SQLConfig.allowAutomaticValues, true);
1571
        
1572
        config.set(SQLConfig.ST_ExtentAggregate, "ST_Extent({0})");
1573
        config.set(SQLConfig.ST_UnionAggregate, "ST_Union({0})");
1574
        config.set(SQLConfig.count, "COUNT({0})");
1575
        config.set(SQLConfig.count_distinct, "COUNT(DISTINCT {0})");
1576

    
1577
        config.set(SQLConfig.type_boolean, "BOOLEAN");
1578
        config.set(SQLConfig.type_byte, "TINYINT");
1579
        config.set(SQLConfig.type_bytearray, "BYTEA");
1580
        config.set(SQLConfig.type_geometry, "TEXT");
1581
        config.set(SQLConfig.type_char, "CHARACTER(1)");
1582
        config.set(SQLConfig.type_date, "DATE");
1583
        config.set(SQLConfig.type_double, "DOUBLE PRECISION"); //float con 53 bits de mantisa, float(54)
1584
        config.set(SQLConfig.type_numeric_p, "NUMERIC({0})");
1585
        config.set(SQLConfig.type_numeric_ps, "NUMERIC({0},{1})");
1586
        config.set(SQLConfig.type_bigdecimal, "NUMERIC({0},{1})");
1587
        config.set(SQLConfig.type_float, "REAL"); //float con 24 bits de mantisa, float(24)
1588
        config.set(SQLConfig.type_int, "INT");
1589
        config.set(SQLConfig.type_long, "BIGINT");
1590
        config.set(SQLConfig.type_string, "TEXT");
1591
        config.set(SQLConfig.type_string_p, "VARCHAR({0})");
1592
        config.set(SQLConfig.type_time, "TIME");
1593
        config.set(SQLConfig.type_timestamp, "TIMESTAMP");
1594
        config.set(SQLConfig.type_version, "VARCHAR(30)");
1595
        config.set(SQLConfig.type_URI, "TEXT");
1596
        config.set(SQLConfig.type_URL, "TEXT");
1597
        config.set(SQLConfig.type_FILE, "TEXT");
1598
        config.set(SQLConfig.type_FOLDER, "TEXT");
1599

    
1600
        config.set(SQLConfig.DELETE_FROM_table_WHERE_expresion, "DELETE FROM {0} WHERE {1}");
1601
        config.set(SQLConfig.DELETE_FROM_table, "DELETE FROM {0}");
1602
        config.set(SQLConfig.INSERT_INTO_table_columns_VALUES_values, "INSERT INTO {0} ( {1} ) VALUES ( {2} )");
1603
        config.set(SQLConfig.UPDATE_TABLE_STATISTICS_table, "VACUUM ANALYZE {0}");
1604
        config.set(SQLConfig.DROP_TABLE_table, "DROP TABLE {0}");
1605
        config.set(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table, "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_schema = {0} AND f_table_name = {1}");
1606
        config.set(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table, "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_name, {0}");
1607
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues_WHERE_expresion, "UPDATE {0} SET {1} WHERE {2}");
1608
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues, "UPDATE {0} SET {1}");
1609
        config.set(SQLConfig.GRANT_privileges_ON_table_TO_role, "GRANT {0} ON {1} TO {2}");
1610
    }
1611
    
1612
    @Override
1613
    public String default_schema() {
1614
        return config.getString(SQLConfig.default_schema);
1615
    }
1616
    
1617
    @Override
1618
    public String sqltype(int type, int p, int s) {
1619
        switch (type) {
1620
            case DataTypes.BOOLEAN:
1621
                return config.getString(SQLConfig.type_boolean);
1622
            case DataTypes.BYTE:
1623
                return config.getString(SQLConfig.type_byte);
1624
            case DataTypes.BYTEARRAY:
1625
                return config.getString(SQLConfig.type_bytearray);
1626
            case DataTypes.GEOMETRY:
1627
                return config.getString(SQLConfig.type_geometry);
1628
            case DataTypes.CHAR:
1629
                return config.getString(SQLConfig.type_char);
1630
            case DataTypes.DATE:
1631
                return config.getString(SQLConfig.type_date);
1632
            case DataTypes.DOUBLE:
1633
                  // FIXME: Si cargamos la capa "country" al exportarla a
1634
                  // SQLServer falla por:
1635
                  //  Error de desbordamiento aritm?tico al convertir float al tipo de datos numeric.
1636
                  // Al parecer la capa declara la columna sqkm_ctry como Numeric(12,6) y para 
1637
                  // Algeria intenta asignarle un valor de 2320972.0 y falla.
1638
                  // Habria que repasar el proveedor de shape.
1639
                
1640
//                if (p > 1) {
1641
//                    if (s < 0) {
1642
//                        return MessageFormat.format(config.getString(SQLConfig.type_numeric_p), p);
1643
//                    }
1644
//                    return MessageFormat.format(config.getString(SQLConfig.type_numeric_ps), p,s);
1645
//                }
1646
                return MessageFormat.format(config.getString(SQLConfig.type_double),p,s);
1647
            case DataTypes.BIGDECIMAL:
1648
                if (p < 1) {
1649
                    p = 20;
1650
                }
1651
                if (s < 0) {
1652
                    s = 10;
1653
                }
1654
                return MessageFormat.format(config.getString(SQLConfig.type_bigdecimal), p,s);
1655
            case DataTypes.FLOAT:
1656
                return MessageFormat.format(config.getString(SQLConfig.type_float), p,s);
1657
            case DataTypes.INT:
1658
                return MessageFormat.format(config.getString(SQLConfig.type_int), p,s);
1659
            case DataTypes.LONG:
1660
                return MessageFormat.format(config.getString(SQLConfig.type_long), p,s);
1661
            case DataTypes.STRING:
1662
                if (p < 0) {
1663
                    return config.getString(SQLConfig.type_string);
1664
                } else if (p < 4096) {
1665
                    return MessageFormat.format(config.getString(SQLConfig.type_string_p),p);
1666
                }
1667
                return config.getString(SQLConfig.type_string);
1668
            case DataTypes.TIME:
1669
                return config.getString(SQLConfig.type_time);
1670
            case DataTypes.TIMESTAMP:
1671
                return config.getString(SQLConfig.type_timestamp);
1672
            case DataTypes.VERSION:
1673
                return config.getString(SQLConfig.type_version);
1674
            case DataTypes.URI:
1675
                return config.getString(SQLConfig.type_URI);
1676
            case DataTypes.URL:
1677
                return config.getString(SQLConfig.type_URL);
1678
            case DataTypes.FILE:
1679
                return config.getString(SQLConfig.type_FILE);
1680
            case DataTypes.FOLDER:
1681
                return config.getString(SQLConfig.type_FOLDER);
1682
            default:
1683
                return null;
1684
        }
1685
    }
1686

    
1687
    protected SelectColumnBuilder createSelectColumnBuilder() {
1688
        return new SelectColumnBuilderBase();
1689
    }
1690
    
1691
    protected UpdateColumnBuilder createUpdateColumnBuilder() {
1692
        return new UpdateColumnBuilderBase();
1693
    }
1694
    
1695
    protected InsertColumnBuilder createInsertColumnBuilder() {
1696
        return new InsertColumnBuilderBase();
1697
    }
1698
    
1699
    protected OrderByBuilder createOrderByBuilder() {
1700
        return new OrderByBuilderBase();
1701
    }
1702

    
1703
    protected FromBuilder createFromBuilder() {
1704
        return new FromBuilderBase();
1705
    }
1706

    
1707
    protected SelectBuilder createSelectBuilder() {
1708
        return new SelectBuilderBase();
1709
    }
1710

    
1711
    protected UpdateBuilder createUpdateBuilder() {
1712
        return new UpdateBuilderBase();
1713
    }
1714

    
1715
    protected DeleteBuilder createDeleteBuilder() {
1716
        return new DeleteBuilderBase();
1717
    }
1718

    
1719
    protected GrantBuilder createGrantBuilder() {
1720
        return new GrantBuilderBase();
1721
    }
1722

    
1723
    protected GrantRoleBuilder createGrantRoleBuilder(TableNameBuilder table, String role) {
1724
        return new GrantRoleBuilderBase(table, role);
1725
    }
1726
    
1727
    protected DropTableBuilder createDropTableBuilder() {
1728
        return new DropTableBuilderBase();
1729
    }
1730

    
1731
    protected CreateTableBuilder createCreateTableBuilder() {
1732
        return new CreateTableBuilderBase();
1733
    }
1734

    
1735
    protected AlterTableBuilder createAlterTableBuilder() {
1736
        return new AlterTableBuilderBase();
1737
    }
1738

    
1739
    protected InsertBuilder createInsertBuilder() {
1740
        return new InsertBuilderBase();
1741
    }
1742

    
1743
    protected UpdateTableStatisticsBuilder createUpdateTableStatisticsBuilder() {
1744
        return new UpdateTableStatisticsBuilderBase();
1745
    }
1746

    
1747
    @Override
1748
    public SelectBuilder select() {
1749
        if (this.select == null) {
1750
            this.select = this.createSelectBuilder();
1751
        }
1752
        return this.select;
1753
    }
1754

    
1755
    @Override
1756
    public UpdateBuilder update() {
1757
        if (this.update == null) {
1758
            this.update = this.createUpdateBuilder();
1759
        }
1760
        return this.update;
1761
    }
1762

    
1763
    @Override
1764
    public UpdateTableStatisticsBuilder update_table_statistics() {
1765
        if (this.update_table_statistics == null) {
1766
            this.update_table_statistics = this.createUpdateTableStatisticsBuilder();
1767
        }
1768
        return this.update_table_statistics;
1769
    }
1770

    
1771
    @Override
1772
    public DropTableBuilder drop_table() {
1773
        if (this.drop_table == null) {
1774
            this.drop_table = this.createDropTableBuilder();
1775
        }
1776
        return this.drop_table;
1777
    }
1778

    
1779
    @Override
1780
    public DeleteBuilder delete() {
1781
        if (this.delete == null) {
1782
            this.delete = this.createDeleteBuilder();
1783
        }
1784
        return this.delete;
1785
    }
1786

    
1787
    @Override
1788
    public InsertBuilder insert() {
1789
        if (this.insert == null) {
1790
            this.insert = this.createInsertBuilder();
1791
        }
1792
        return this.insert;
1793
    }
1794

    
1795
    @Override
1796
    public AlterTableBuilder alter_table() {
1797
        if (this.alter_table == null) {
1798
            this.alter_table = this.createAlterTableBuilder();
1799
        }
1800
        return this.alter_table;
1801
    }
1802

    
1803
    @Override
1804
    public CreateTableBuilder create_table() {
1805
        if (this.create_table == null) {
1806
            this.create_table = this.createCreateTableBuilder();
1807
        }
1808
        return this.create_table;
1809
    }
1810

    
1811
    @Override
1812
    public GrantBuilder grant() {
1813
        if (this.grant == null) {
1814
            this.grant = this.createGrantBuilder();
1815
        }
1816
        return this.grant;
1817
    }
1818

    
1819
    @Override
1820
    public void accept(Visitor visitor, VisitorFilter filter) {
1821
        if (this.select != null) {
1822
            this.select.accept(visitor, filter);
1823
        }
1824
        if (this.update != null) {
1825
            this.update.accept(visitor, filter);
1826
        }
1827
        if (this.insert != null) {
1828
            this.insert.accept(visitor, filter);
1829
        }
1830
        if (this.delete != null) {
1831
            this.delete.accept(visitor, filter);
1832
        }
1833
        if (this.alter_table != null) {
1834
            this.alter_table.accept(visitor, filter);
1835
        }
1836
        if (this.create_table != null) {
1837
            this.create_table.accept(visitor, filter);
1838
        }
1839
        if (this.drop_table != null) {
1840
            this.drop_table.accept(visitor, filter);
1841
        }
1842
    }
1843

    
1844
    
1845
    @Override
1846
    public String toString() {
1847
        if (this.select != null) {
1848
            return this.select.toString();
1849
        }
1850
        if (this.update != null) {
1851
            return this.update.toString();
1852
        }
1853
        if (this.insert != null) {
1854
            return this.insert.toString();
1855
        }
1856
        if (this.delete != null) {
1857
            return this.delete.toString();
1858
        }
1859
        if (this.alter_table != null) {
1860
            return this.alter_table.toString();
1861
        }
1862
        if (this.create_table != null) {
1863
            return this.create_table.toString();
1864
        }
1865
        if (this.drop_table != null) {
1866
            return this.drop_table.toString();
1867
        }
1868
        if (this.update_table_statistics != null) {
1869
            return this.update_table_statistics.toString();
1870
        }
1871
        return "";
1872
    }
1873

    
1874
    @Override
1875
    public Function ST_UnionAggregate(Value geom) {
1876
        return function("ST_UnionAggregate", config.getString(SQLConfig.ST_UnionAggregate), geom);
1877
    }
1878

    
1879
    @Override
1880
    public Function ST_ExtentAggregate(Value geom) {
1881
        return function("ST_ExtentAggregate", config.getString(SQLConfig.ST_ExtentAggregate), geom);
1882
    }
1883

    
1884
    @Override
1885
    public CountBuilder count() {
1886
        return new CountBuilderBase();
1887
    }
1888

    
1889
}