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

History | View | Annotate | Download (62.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 ExpressionEvaluatorBase 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
            if( this.order_by == null ) {
531
                this.order_by = new ArrayList<>();
532
            }
533
            OrderByBuilder order = createOrderByBuilder();
534
            this.order_by.add(order);
535
            return order;
536
        }
537

    
538
        @Override
539
        public boolean has_order_by() {
540
            if( this.order_by == null ) {
541
                return false;
542
            }
543
            return !this.order_by.isEmpty();
544
        }
545
        
546
        protected boolean isValid(StringBuilder message) {
547
            if( message == null ) {
548
                message = new StringBuilder();
549
            }
550
            if( this.has_offset() && !this.has_order_by() ) {
551
                // Algunos gestores de BBDD requieren que se especifique un
552
                // orden para poder usar OFFSET. Como eso parece buena idea para
553
                // asegurar que siempre tengamos los mismo resultados, lo exijimos
554
                // siempre.
555
                message.append("Can't use OFFSET without an ORDER BY.");
556
                return false;
557
            }
558
            return true;
559
        }
560
        
561
        @Override
562
        public String toString() {
563
            StringBuilder builder = new StringBuilder();
564
            if( !this.isValid(builder) ) {
565
                throw new IllegalStateException(builder.toString());
566
            }
567
            builder.append("SELECT ");
568
            if( this.distinct ) {
569
                builder.append("DISTINCT ");
570
            }
571
            boolean first = true;
572
            for (SelectColumnBuilder column : columns) {
573
                if (first) {
574
                    first = false;
575
                } else {
576
                    builder.append(", ");
577
                }
578
                builder.append(column.toString());
579
            }
580

    
581
            if ( this.has_from() ) {
582
                builder.append(" FROM ");
583
                builder.append(this.from.toString());
584
            }
585
            if ( this.has_where() ) {
586
                builder.append(" WHERE ");
587
                builder.append(this.where.toString());
588
            }
589
            
590
            if( this.has_order_by() ) {
591
                builder.append(" ORDER BY ");
592
                first = true;
593
                for (OrderByBuilder item : this.order_by) {
594
                    if (first) {
595
                        first = false;
596
                    } else {
597
                        builder.append(", ");
598
                    }
599
                    builder.append(item.toString());                    
600
                }   
601
            }
602
            
603
            if ( this.has_limit() ) {
604
                builder.append(" LIMIT ");
605
                builder.append(this.limit);
606
            }
607
            if ( this.has_offset() ) {
608
                builder.append(" OFFSET ");
609
                builder.append(this.offset);
610
            }
611
            return builder.toString();
612

    
613
        }
614
    }
615

    
616
    public class DropTableBuilderBase implements DropTableBuilder {
617

    
618
        protected TableNameBuilder table;
619

    
620
        @Override
621
        public TableNameBuilder table() {
622
            if( table == null ) {
623
                table = new TableNameBuilderBase();
624
            }
625
            return table;
626
        }
627

    
628
        @Override
629
        public void accept(Visitor visitor, VisitorFilter filter) {
630
            if( filter.accept(this) ) {
631
                visitor.visit(this);
632
            }
633
            this.table.accept(visitor,filter);
634
        }
635
        
636
        @Override
637
        public String toString() {
638
            StringBuilder builder = new StringBuilder();
639
            boolean first = true;
640
            for (String sql : toStrings()) {
641
                if( StringUtils.isEmpty(sql) ) {
642
                    continue;
643
                }
644
                if (first) {
645
                    first = false;
646
                } else {
647
                    builder.append("; ");
648
                }
649
                builder.append(sql);
650
            }
651
            return builder.toString();
652
        }
653

    
654
        @Override
655
        public List<String> toStrings() {
656
            List<String> sqls = new ArrayList<>();
657

    
658
            sqls.add(
659
                    MessageFormat.format(
660
                            config.getString(SQLConfig.DROP_TABLE_table),
661
                            this.table.toString()
662
                    )
663
            );
664
            String sql;
665
            if( config.has_functionality(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table) ) {
666
                if (this.table.has_schema()) {
667
                    sql = MessageFormat.format(
668
                            config.getString(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table),
669
                            string(this.table.getSchema()),
670
                            string(this.table.getName())
671
                    );
672
                } else {
673
                    sql = MessageFormat.format(
674
                            config.getString(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table),
675
                            identifier(this.table.getName())
676
                    );
677
                }
678
                if( !StringUtils.isEmpty(sql) ) {
679
                    sqls.add(sql);
680
                }
681
            }
682
            return sqls;
683
        }
684
    }
685

    
686
    public class GrantRoleBuilderBase implements GrantRoleBuilder {
687
        protected TableNameBuilder table;
688
        protected String role;
689
        protected Set<Privilege> privileges;
690

    
691
        public GrantRoleBuilderBase(TableNameBuilder table, String role) {
692
            this.table = table;
693
            this.role = role;
694
            this.privileges = new HashSet<>();
695
        }
696

    
697
        @Override
698
        public GrantRoleBuilder privilege(Privilege privilege) {
699
            privileges.add(privilege);
700
            return this;
701
        }
702
        
703
        @Override
704
        public GrantRoleBuilder select() {
705
             privileges.add(Privilege.SELECT);
706
            return this;
707
        }
708

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

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

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

    
727
        @Override
728
        public GrantRoleBuilder truncate() {
729
            privileges.add(Privilege.TRUNCATE);
730
            return this;
731
        }
732

    
733
        @Override
734
        public GrantRoleBuilder reference() {
735
            privileges.add(Privilege.REFERENCE);
736
            return this;
737
        }
738

    
739
        @Override
740
        public GrantRoleBuilder trigger() {
741
            privileges.add(Privilege.TRIGGER);
742
            return this;
743
        }
744

    
745
        @Override
746
        public GrantRoleBuilder all() {
747
            privileges.add(Privilege.ALL);
748
            return this;
749
        }
750

    
751
        protected String getPrivilegeName(Privilege privilege) {
752
            switch(privilege) {
753
                case DELETE:
754
                    return "DELETE";
755
                case INSERT:
756
                    return "INSERT";
757
                case REFERENCE:
758
                    return "REFERENCE";
759
                case SELECT:
760
                    return "SELECT";
761
                case TRIGGER:
762
                    return "TRIGGER";
763
                case TRUNCATE:
764
                    return "TRUNCATE";
765
                case UPDATE:
766
                    return "UPDATE";
767
                case ALL:
768
                default:
769
                    return "ALL";
770
            }
771
        }
772
        
773
        @Override
774
        public String toString() {
775
            StringBuilder builder = new StringBuilder();
776
            boolean first = true;
777
            for (Privilege privilege : privileges) {
778
                if (first) {
779
                    first = false;
780
                } else {
781
                    builder.append(", ");
782
                }
783
                builder.append( this.getPrivilegeName(privilege));
784
            }
785
            String sql = MessageFormat.format(
786
                    config.getString(SQLConfig.GRANT_privileges_ON_table_TO_role),
787
                    builder.toString(),
788
                    table.toString(),
789
                    role
790
            );
791
            return sql;
792
        }
793
    }
794
    
795
    public class GrantBuilderBase implements GrantBuilder {
796

    
797
        protected TableNameBuilder table;
798
        protected Map<String, GrantRoleBuilder> roles;
799

    
800
        public GrantBuilderBase() {
801
            this.roles = new HashMap<>();
802
        }
803
        
804
        @Override
805
        public TableNameBuilder table() {
806
            if( table == null ) {
807
                table = new TableNameBuilderBase();
808
            }
809
            return table;
810
        }
811

    
812
        @Override
813
        public void accept(Visitor visitor, VisitorFilter filter) {
814
            if( filter.accept(this) ) {
815
                visitor.visit(this);
816
            }
817
            if( this.table!= null ) {
818
                this.table.accept(visitor,filter);
819
            }
820
        }
821
        
822
        @Override
823
        public GrantRoleBuilder role(String role) {
824
            GrantRoleBuilder roleBuilder = this.roles.get(role);
825
            if( roleBuilder == null ) {
826
                roleBuilder = createGrantRoleBuilder(this.table(), role);
827
                this.roles.put(role, roleBuilder);
828
            }
829
            return roleBuilder;
830
        }
831

    
832
        @Override
833
        public String toString() {
834
            StringBuilder builder = new StringBuilder();
835
            boolean first = true;
836
            for (String sql : toStrings()) {
837
                if( StringUtils.isEmpty(sql) ) {
838
                    continue;
839
                }
840
                if (first) {
841
                    first = false;
842
                } else {
843
                    builder.append("; ");
844
                }
845
                builder.append(sql);
846
            }
847
            return builder.toString();
848
        }
849

    
850
        @Override
851
        public List<String> toStrings() {
852
            List<String> sqls = new ArrayList<>();
853
            for (GrantRoleBuilder role : roles.values()) {
854
                sqls.add(role.toString());
855
            }
856
            return sqls;
857
        }
858
    }
859

    
860
    public class UpdateColumnBuilderBase extends InsertColumnBuilderBase implements UpdateColumnBuilder {
861
        
862
        public UpdateColumnBuilderBase() {
863
            super();
864
        }
865

    
866
        @Override
867
        public UpdateColumnBuilder name(String name) {
868
            return (UpdateColumnBuilder) super.name(name);
869
        }
870

    
871
        @Override
872
        public UpdateColumnBuilder with_value(Value value) {
873
            return (UpdateColumnBuilder) super.with_value(value);
874
        }
875
        
876
    }
877
    
878
    public class UpdateBuilderBase implements UpdateBuilder {
879

    
880
        protected ExpressionBuilder where;
881
        protected List<UpdateColumnBuilder> columns;
882
        protected TableNameBuilder table;
883

    
884
        public UpdateBuilderBase() {
885
            this.columns = new ArrayList<>();
886
        }
887

    
888
        @Override
889
        public void accept(Visitor visitor, VisitorFilter filter) {
890
            if( filter.accept(this) ) {
891
                visitor.visit(this);
892
            }
893
            if( this.table != null ) {
894
                this.table.accept(visitor, filter);
895
            }
896
            for (UpdateColumnBuilder column : columns) {
897
                column.accept(visitor, filter);
898
            }
899
            if( this.has_where() ) {
900
                this.where.accept(visitor, filter);
901
            }
902
        }
903

    
904
        @Override
905
        public ExpressionBuilder where() {
906
            if (this.where == null) {
907
                this.where = createExpressionBuilder();
908
            }
909
            return this.where;
910
        }
911

    
912
        @Override
913
        public TableNameBuilder table() {
914
            if( table == null ) {
915
                table = new TableNameBuilderBase();
916
            }
917
            return table;
918
        }
919

    
920
        @Override
921
        public UpdateColumnBuilder column() {
922
            UpdateColumnBuilder column = createUpdateColumnBuilder();
923
            this.columns.add(column);
924
            return column;
925
        }
926
        
927
        @Override
928
        public boolean has_where() {
929
            return this.where != null;
930
        }
931

    
932
        @Override
933
        public String toString() {
934
            /*
935
             * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
936
             * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
937
             * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
938
             * output_expression [ AS output_name ] [, ...] ]
939
             */
940
            StringBuilder columnsAndValues = new StringBuilder();
941

    
942
            boolean first = true;
943
            for (UpdateColumnBuilder column : columns) {
944
                if (first) {
945
                    first = false;
946
                } else {
947
                    columnsAndValues.append(", ");
948
                }
949
                columnsAndValues.append(identifier(column.getName()));
950
                columnsAndValues.append(" = ");
951
                columnsAndValues.append(column.getValue().toString());
952
            }
953
            
954
            String sql;
955
            if ( this.has_where() ) {
956
                sql = MessageFormat.format(
957
                        config.getString(SQLConfig.UPDATE_table_SET_columnsAndValues_WHERE_expresion),
958
                        this.table.toString(),
959
                        columnsAndValues.toString(),
960
                        this.where.toString()
961
                );
962
            } else {
963
                sql = MessageFormat.format(
964
                        config.getString(SQLConfig.UPDATE_table_SET_columnsAndValues),
965
                        this.table.toString(),
966
                        columnsAndValues.toString()
967
                );
968
            }
969
            return sql;
970
        }
971
    }
972

    
973
    public class DeleteBuilderBase implements DeleteBuilder {
974

    
975
        protected ExpressionBuilder where;
976
        protected TableNameBuilder table;
977

    
978
        public DeleteBuilderBase() {
979
        }
980

    
981
        @Override
982
        public void accept(Visitor visitor, VisitorFilter filter) {
983
            if( filter.accept(this) ) {
984
                visitor.visit(this);
985
            }
986
            if( this.table != null ) {
987
                this.table.accept(visitor, filter);
988
            }
989
            if( this.has_where() ) {
990
                this.where.accept(visitor, filter);
991
            }
992
        }
993

    
994
        @Override
995
        public ExpressionBuilder where() {
996
            if (this.where == null) {
997
                this.where = createExpressionBuilder();
998
            }
999
            return this.where;
1000
        }
1001

    
1002
        @Override
1003
        public TableNameBuilder table() {
1004
            if( table == null ) {
1005
                table = new TableNameBuilderBase();
1006
            }
1007
            return table;
1008
        }
1009

    
1010
        @Override
1011
        public boolean has_where() {
1012
            return this.where != null;
1013
        }
1014

    
1015
        @Override
1016
        public String toString() {
1017
            /*
1018
             * DELETE FROM table_name
1019
             * WHERE some_column=some_value; 
1020
             */
1021
            String sql;
1022
            if( this.has_where() ) {
1023
                sql = MessageFormat.format(
1024
                        config.getString(SQLConfig.DELETE_FROM_table_WHERE_expresion),
1025
                        this.table.toString(),
1026
                        this.where.toString()
1027
                );
1028
            } else {
1029
                sql = MessageFormat.format(
1030
                        config.getString(SQLConfig.DELETE_FROM_table),
1031
                        this.table.toString()
1032
                );
1033
            }
1034
            return sql;
1035
        }
1036
    }
1037

    
1038
    public class AlterTableBuilderBase implements AlterTableBuilder {
1039

    
1040
        protected TableNameBuilder table;
1041
        protected List<String> drops;
1042
        protected List<ColumnInfo> adds;
1043
        protected List<ColumnInfo> alters;
1044
        protected List<Pair> renames;
1045

    
1046
        public AlterTableBuilderBase() {
1047
            this.drops = new ArrayList<>();
1048
            this.adds = new ArrayList<>();
1049
            this.alters = new ArrayList<>();
1050
            this.renames = new ArrayList<>();
1051
        }
1052

    
1053
        @Override
1054
        public void accept(Visitor visitor, VisitorFilter filter) {
1055
            if( filter.accept(this) ) {
1056
                visitor.visit(this);
1057
            }
1058
            if( this.table != null ) {
1059
                this.table.accept(visitor, filter);
1060
            }
1061
        }
1062

    
1063
        @Override
1064
        public TableNameBuilder table() {
1065
            if( table == null ) {
1066
                table = new TableNameBuilderBase();
1067
            }
1068
            return table;
1069
        }
1070

    
1071
        @Override
1072
        public AlterTableBuilder drop_column(String columnName) {
1073
            this.drops.add(columnName);
1074
            return this;
1075
        }
1076

    
1077
        @Override
1078
        public AlterTableBuilder add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1079
            if (isPk || isAutomatic) {
1080
                allowNulls = false;
1081
            }
1082
            this.adds.add(new ColumnInfo(columnName, type, type_p, type_s, isPk, allowNulls, isAutomatic, defaultValue));
1083
            return this;
1084
        }
1085

    
1086
        @Override
1087
        public AlterTableBuilder alter_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1088
            if (isPk || isAutomatic) {
1089
                allowNulls = false;
1090
            }
1091
            this.alters.add(new ColumnInfo(columnName, type, type_p, type_s, isPk, allowNulls, isAutomatic, defaultValue));
1092
            return this;
1093
        }
1094

    
1095
        @Override
1096
        public AlterTableBuilder rename_column(String source, String target) {
1097
            this.renames.add(new ImmutablePair(source, target));
1098
            return this;
1099
        }
1100

    
1101
        @Override
1102
        public String toString() {
1103
            StringBuilder builder = new StringBuilder();
1104
            boolean first = true;
1105
            for (String sql : toStrings()) {
1106
                if( StringUtils.isEmpty(sql) ) {
1107
                    continue;
1108
                }
1109
                if (first) {
1110
                    first = false;
1111
                } else {
1112
                    builder.append("; ");
1113
                }
1114
                builder.append(sql);
1115
            }
1116
            return builder.toString();
1117
        }
1118

    
1119
        @Override
1120
        public List<String> toStrings() {
1121
            List<String> sqls = new ArrayList<>();
1122
            /*
1123
             ALTER TABLE [ ONLY ] name [ * ]
1124
             action [, ... ]
1125
             ALTER TABLE [ ONLY ] name [ * ]
1126
             RENAME [ COLUMN ] column TO new_column
1127
             ALTER TABLE name
1128
             RENAME TO new_name
1129
             ALTER TABLE name
1130
             SET SCHEMA new_schema
1131

1132
             where action is one of:
1133

1134
             ADD [ COLUMN ] column data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
1135
             DROP [ COLUMN ] [ IF EXISTS ] column [ RESTRICT | CASCADE ]
1136
             ALTER [ COLUMN ] column [ SET DATA ] TYPE data_type [ COLLATE collation ] [ USING expression ]
1137
             ALTER [ COLUMN ] column SET DEFAULT expression
1138
             ALTER [ COLUMN ] column DROP DEFAULT
1139
             ALTER [ COLUMN ] column { SET | DROP } NOT NULL
1140
             ALTER [ COLUMN ] column SET STATISTICS integer
1141
             ALTER [ COLUMN ] column SET ( attribute_option = value [, ... ] )
1142
             ALTER [ COLUMN ] column RESET ( attribute_option [, ... ] )
1143
             ALTER [ COLUMN ] column SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
1144
             ADD table_constraint [ NOT VALID ]
1145
             ADD table_constraint_using_index
1146
             VALIDATE CONSTRAINT constraint_name
1147
             DROP CONSTRAINT [ IF EXISTS ]  constraint_name [ RESTRICT | CASCADE ]
1148
             DISABLE TRIGGER [ trigger_name | ALL | USER ]
1149
             ENABLE TRIGGER [ trigger_name | ALL | USER ]
1150
             ENABLE REPLICA TRIGGER trigger_name
1151
             ENABLE ALWAYS TRIGGER trigger_name
1152
             DISABLE RULE rewrite_rule_name
1153
             ENABLE RULE rewrite_rule_name
1154
             ENABLE REPLICA RULE rewrite_rule_name
1155
             ENABLE ALWAYS RULE rewrite_rule_name
1156
             CLUSTER ON index_name
1157
             SET WITHOUT CLUSTER
1158
             SET WITH OIDS
1159
             SET WITHOUT OIDS
1160
             SET ( storage_parameter = value [, ... ] )
1161
             RESET ( storage_parameter [, ... ] )
1162
             INHERIT parent_table
1163
             NO INHERIT parent_table
1164
             OF type_name
1165
             NOT OF
1166
             OWNER TO new_owner
1167
             SET TABLESPACE new_tablespace
1168

1169
             and table_constraint_using_index is:
1170

1171
             [ CONSTRAINT constraint_name ]
1172
             { UNIQUE | PRIMARY KEY } USING INDEX index_name
1173
             [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1174

1175
             */
1176
            StringBuilder builder = new StringBuilder();
1177

    
1178
            builder.append("ALTER TABLE");
1179
            builder.append(this.table.toString());
1180
            builder.append(" ");
1181
            boolean first = true;
1182
            for (String column : drops) {
1183
                if (first) {
1184
                    first = false;
1185
                } else {
1186
                    builder.append(", ");
1187
                }
1188
                builder.append("DROP COLUMN IF EXISTS ");
1189
                builder.append(column);
1190
            }
1191
            first = drops.isEmpty();
1192
            for (ColumnInfo column : adds) {
1193
                if (first) {
1194
                    first = false;
1195
                } else {
1196
                    builder.append(", ");
1197
                }
1198
                builder.append("ADD COLUMN ");
1199
                builder.append(column.name);
1200
                builder.append(" ");
1201
                if( column.type == DataTypes.INT && column.isAutomatic ) {
1202
                    builder.append(" SERIAL");
1203
                } else {
1204
                    builder.append(sqltype(column.type, column.type_p, column.type_s));
1205
                }
1206
                if (column.defaultValue == null) {
1207
                    if (column.allowNulls) {
1208
                        builder.append(" DEFAULT NULL");
1209
                    }
1210
                } else {
1211
                    builder.append(" DEFAULT '");
1212
                    builder.append(column.defaultValue.toString());
1213
                    builder.append("'");
1214
                }
1215
                if (column.allowNulls) {
1216
                    builder.append(" NULL");
1217
                } else {
1218
                    builder.append(" NOT NULL");
1219
                }
1220
                if (column.isPk) {
1221
                    builder.append(" PRIMARY KEY");
1222
                }
1223
            }
1224
            first = drops.isEmpty() && adds.isEmpty();
1225
            for (ColumnInfo column : alters) {
1226
                if (first) {
1227
                    first = false;
1228
                } else {
1229
                    builder.append(", ");
1230
                }
1231
                builder.append("ALTER COLUMN ");
1232
                builder.append(column.name);
1233
                builder.append("SET DATA TYPE ");
1234
                if( column.type == DataTypes.INT && column.isAutomatic ) {
1235
                    builder.append(" SERIAL");
1236
                } else {
1237
                    builder.append(sqltype(column.type, column.type_p, column.type_s));
1238
                }
1239
                builder.append(", ");
1240
                if (column.defaultValue == null) {
1241
                    if (column.allowNulls) {
1242
                        builder.append("ALTER COLUMN ");
1243
                        builder.append(column.name);
1244
                        builder.append(" SET DEFAULT NULL");
1245
                    } else {
1246
                        builder.append("ALTER COLUMN ");
1247
                        builder.append(column.name);
1248
                        builder.append(" DROP DEFAULT");
1249
                    }
1250
                } else {
1251
                    builder.append("ALTER COLUMN ");
1252
                    builder.append(column.name);
1253
                    builder.append(" SET DEFAULT '");
1254
                    builder.append(column.defaultValue.toString());
1255
                    builder.append("'");
1256
                }
1257
            }
1258
            first = drops.isEmpty() && adds.isEmpty() && alters.isEmpty();
1259
            for (Pair pair : renames) {
1260
                if (first) {
1261
                    first = false;
1262
                } else {
1263
                    builder.append(", ");
1264
                }
1265
                builder.append("RENAME COLUMN ");
1266
                builder.append(pair.getLeft());
1267
                builder.append(" TO ");
1268
                builder.append(pair.getRight());
1269
            }
1270
            sqls.add(builder.toString());
1271

    
1272
            return sqls;
1273
        }
1274

    
1275
    }
1276

    
1277
    public class CreateTableBuilderBase implements CreateTableBuilder {
1278

    
1279
        protected TableNameBuilder table;
1280
        protected List<ColumnInfo> columns;
1281

    
1282
        public CreateTableBuilderBase() {
1283
            this.columns = new ArrayList<>();
1284
        }
1285

    
1286
        @Override
1287
        public void accept(Visitor visitor, VisitorFilter filter) {
1288
            if( filter.accept(this) ) {
1289
                visitor.visit(this);
1290
            }
1291
            if( this.table != null ) {
1292
                this.table.accept(visitor, filter);
1293
            }
1294
        }
1295

    
1296
        @Override
1297
        public TableNameBuilder table() {
1298
            if( table == null ) {
1299
                table = new TableNameBuilderBase();
1300
            }
1301
            return table;
1302
        }
1303

    
1304
        @Override
1305
        public CreateTableBuilderBase add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1306
            if (isPk || isAutomatic) {
1307
                allowNulls = false;
1308
            }
1309
            this.columns.add(new ColumnInfo(columnName, type, type_p, type_s, isPk, allowNulls, isAutomatic, defaultValue));
1310
            return this;
1311
        }
1312

    
1313
        @Override
1314
        public String toString() {
1315
            StringBuilder builder = new StringBuilder();
1316
            boolean first = true;
1317
            for (String sql : toStrings()) {
1318
                if( StringUtils.isEmpty(sql) ) {
1319
                    continue;
1320
                }
1321
                if (first) {
1322
                    first = false;
1323
                } else {
1324
                    builder.append("; ");
1325
                }
1326
                builder.append(sql);
1327
            }
1328
            return builder.toString();
1329
        }
1330

    
1331
        @Override
1332
        public List<String> toStrings() {
1333
            List<String> sqls = new ArrayList<>();
1334
            /**
1335
             * CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE
1336
             * table_name ( { column_name data_type [ DEFAULT default_expr ] [
1337
             * column_constraint [ ... ] ] | table_constraint | LIKE
1338
             * parent_table [ { INCLUDING | EXCLUDING } DEFAULTS ] } [, ... ] )
1339
             * [ INHERITS ( parent_table [, ... ] ) ] [ WITH OIDS | WITHOUT OIDS
1340
             * ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
1341
             *
1342
             * where column_constraint is:
1343
             *
1344
             * [ CONSTRAINT constraint_name ] { NOT NULL | NULL | UNIQUE |
1345
             * PRIMARY KEY | CHECK (expression) | REFERENCES reftable [ (
1346
             * refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON
1347
             * DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE | NOT
1348
             * DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1349
             *
1350
             * and table_constraint is:
1351
             *
1352
             * [ CONSTRAINT constraint_name ] { UNIQUE ( column_name [, ... ] )
1353
             * | PRIMARY KEY ( column_name [, ... ] ) | CHECK ( expression ) |
1354
             * FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ (
1355
             * refcolumn [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH
1356
             * SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE
1357
             * | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
1358
             */
1359
            StringBuilder builder = new StringBuilder();
1360

    
1361
            builder.append("CREATE TABLE ");
1362
            builder.append(this.table.toString());
1363
            builder.append(" (");
1364
            boolean first = true;
1365
            for (ColumnInfo column : columns) {
1366
                if (first) {
1367
                    first = false;
1368
                } else {
1369
                    builder.append(", ");
1370
                }
1371
                builder.append(identifier(column.name));
1372
                builder.append(" ");
1373
                if( column.isAutomatic && column.type == DataTypes.INT ) {
1374
                    builder.append("SERIAL");
1375
                } else if( column.isAutomatic && column.type == DataTypes.LONG ) {
1376
                    builder.append("BIGSERIAL");
1377
                } else {
1378
                    builder.append(sqltype(column.type, column.type_p, column.type_s));
1379
                }
1380
                if (column.defaultValue == null) {
1381
                    if (column.allowNulls) {
1382
                        builder.append(" DEFAULT NULL");
1383
                    }
1384
                } else {
1385
                    builder.append(" DEFAULT '");
1386
                    builder.append(column.defaultValue.toString());
1387
                    builder.append("'");
1388
                }
1389
                if (column.allowNulls) {
1390
                    builder.append(" NULL");
1391
                } else {
1392
                    builder.append(" NOT NULL");
1393
                }
1394
                if (column.isPk) {
1395
                    builder.append(" PRIMARY KEY");
1396
                }
1397
            }
1398
            builder.append(" )");
1399
            sqls.add(builder.toString());
1400

    
1401
            return sqls;
1402
        }
1403
    }
1404

    
1405
    public class InsertColumnBuilderBase implements InsertColumnBuilder {
1406
        protected Variable name;
1407
        protected Value value;
1408
        
1409
        public InsertColumnBuilderBase() {
1410
        }
1411

    
1412
        @Override
1413
        public void accept(Visitor visitor, VisitorFilter filter) {
1414
            if( filter.accept(this) ) {
1415
                visitor.visit(this);
1416
            }
1417
            if( this.name != null ) {
1418
                this.name.accept(visitor, filter);
1419
            }
1420
            if( this.value != null ) {
1421
                this.value.accept(visitor, filter);
1422
            }
1423
        }
1424

    
1425
        @Override
1426
        public InsertColumnBuilder name(String name) {
1427
            this.name = variable(name);
1428
            return this;
1429
        }
1430

    
1431
        @Override
1432
        public InsertColumnBuilder with_value(Value value) {
1433
            this.value = value;
1434
            return this;
1435
        }
1436
        
1437
        @Override
1438
        public String getName() {
1439
            return this.name.getName();
1440
        }
1441
        
1442
        @Override
1443
        public Value getValue() {
1444
            return this.value;
1445
        }
1446
        
1447
        @Override
1448
        public String toString() {
1449
            return this.value.toString();
1450
        }
1451
    }
1452
    
1453
    public class InsertBuilderBase implements InsertBuilder {
1454

    
1455
        protected List<InsertColumnBuilder> columns;
1456
        protected TableNameBuilder table;
1457

    
1458
        public InsertBuilderBase() {
1459
            this.columns = new ArrayList<>();
1460
        }
1461

    
1462
        @Override
1463
        public void accept(Visitor visitor, VisitorFilter filter) {
1464
            if( filter.accept(this) ) {
1465
                visitor.visit(this);
1466
            }
1467
            if( this.table != null ) {
1468
                this.table.accept(visitor, filter);
1469
            }
1470
            for (InsertColumnBuilder column : columns) {
1471
                column.accept(visitor, filter);
1472
            }
1473
        }
1474

    
1475
        @Override
1476
        public TableNameBuilder table() {
1477
            if( table == null ) {
1478
                table = new TableNameBuilderBase();
1479
            }
1480
            return table;
1481
        }
1482

    
1483
        @Override
1484
        public InsertColumnBuilder column() {
1485
            InsertColumnBuilder column = createInsertColumnBuilder();
1486
            this.columns.add(column);
1487
            return column;
1488
        }
1489

    
1490
        @Override
1491
        public String toString() {
1492
            /*
1493
             * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
1494
             * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
1495
             * output_expression [ AS output_name ] [, ...] ]
1496
             */
1497
            StringBuilder builderColumns = new StringBuilder();
1498
            StringBuilder builderValues = new StringBuilder();
1499
            
1500
            boolean first = true;
1501
            for (InsertColumnBuilder column : columns) {
1502
                if (first) {
1503
                    first = false;
1504
                } else {
1505
                    builderColumns.append(", ");
1506
                }
1507
                builderColumns.append(identifier(column.getName()));
1508
            }
1509
            first = true;
1510
            for (InsertColumnBuilder column : columns) {
1511
                if (first) {
1512
                    first = false;
1513
                } else {
1514
                    builderValues.append(", ");
1515
                }
1516
                builderValues.append(column.toString());
1517
            }
1518
            
1519
            String sql = MessageFormat.format(
1520
                    config.getString(SQLConfig.INSERT_INTO_table_columns_VALUES_values),
1521
                    this.table.toString(),
1522
                    builderColumns.toString(),
1523
                    builderValues.toString()
1524
            );
1525
            return sql;
1526

    
1527
        }
1528
    }
1529

    
1530
    public class UpdateTableStatisticsBuilderBase implements UpdateTableStatisticsBuilder {
1531

    
1532
        protected TableNameBuilder table;
1533

    
1534
        @Override
1535
        public void accept(Visitor visitor, VisitorFilter filter) {
1536
            if( filter.accept(this) ) {
1537
                visitor.visit(this);
1538
            }
1539
            if( this.table != null ) {
1540
                this.table.accept(visitor, filter);
1541
            }
1542
        }
1543

    
1544
        @Override
1545
        public TableNameBuilder table() {
1546
            if( table == null ) {
1547
                table = new TableNameBuilderBase();
1548
            }
1549
            return table;
1550
        }
1551

    
1552
        @Override
1553
        public String toString() {
1554
            StringBuilder builder = new StringBuilder();
1555
            boolean first = true;
1556
            for (String sql : toStrings()) {
1557
                if( StringUtils.isEmpty(sql) ) {
1558
                    continue;
1559
                }
1560
                if (first) {
1561
                    first = false;
1562
                } else {
1563
                    builder.append("; ");
1564
                }
1565
                builder.append(sql);
1566
            }
1567
            return builder.toString();
1568
        }
1569

    
1570
        @Override
1571
        public List<String> toStrings() {
1572
            List<String> sqls = new ArrayList<>();
1573
            
1574
            if( config.has_functionality(SQLConfig.UPDATE_TABLE_STATISTICS_table) ) {
1575
                String sql = MessageFormat.format(
1576
                        config.getString(SQLConfig.UPDATE_TABLE_STATISTICS_table),
1577
                        table.toString()
1578
                    );
1579
                if( !StringUtils.isEmpty(sql) ) {
1580
                    sqls.add(sql);
1581
                }
1582
            }
1583
            return sqls;
1584
        }
1585
    }
1586
    
1587
    public SQLBuilderBase() {
1588
        super();
1589
        config.set(SQLConfig.default_schema, "public");
1590
        config.set(SQLConfig.allowAutomaticValues, true);
1591
        
1592
        config.set(SQLConfig.ST_ExtentAggregate, "ST_Extent({0})");
1593
        config.set(SQLConfig.ST_UnionAggregate, "ST_Union({0})");
1594
        config.set(SQLConfig.count, "COUNT({0})");
1595
        config.set(SQLConfig.count_distinct, "COUNT(DISTINCT {0})");
1596

    
1597
        config.set(SQLConfig.type_boolean, "BOOLEAN");
1598
        config.set(SQLConfig.type_byte, "TINYINT");
1599
        config.set(SQLConfig.type_bytearray, "BYTEA");
1600
        config.set(SQLConfig.type_geometry, "TEXT");
1601
        config.set(SQLConfig.type_char, "CHARACTER(1)");
1602
        config.set(SQLConfig.type_date, "DATE");
1603
        config.set(SQLConfig.type_double, "DOUBLE PRECISION"); //float con 53 bits de mantisa, float(54)
1604
        config.set(SQLConfig.type_numeric_p, "NUMERIC({0})");
1605
        config.set(SQLConfig.type_numeric_ps, "NUMERIC({0},{1})");
1606
        config.set(SQLConfig.type_bigdecimal, "NUMERIC({0},{1})");
1607
        config.set(SQLConfig.type_float, "REAL"); //float con 24 bits de mantisa, float(24)
1608
        config.set(SQLConfig.type_int, "INT");
1609
        config.set(SQLConfig.type_long, "BIGINT");
1610
        config.set(SQLConfig.type_string, "TEXT");
1611
        config.set(SQLConfig.type_string_p, "VARCHAR({0})");
1612
        config.set(SQLConfig.type_time, "TIME");
1613
        config.set(SQLConfig.type_timestamp, "TIMESTAMP");
1614
        config.set(SQLConfig.type_version, "VARCHAR(30)");
1615
        config.set(SQLConfig.type_URI, "TEXT");
1616
        config.set(SQLConfig.type_URL, "TEXT");
1617
        config.set(SQLConfig.type_FILE, "TEXT");
1618
        config.set(SQLConfig.type_FOLDER, "TEXT");
1619

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

    
1707
    protected SelectColumnBuilder createSelectColumnBuilder() {
1708
        return new SelectColumnBuilderBase();
1709
    }
1710
    
1711
    protected UpdateColumnBuilder createUpdateColumnBuilder() {
1712
        return new UpdateColumnBuilderBase();
1713
    }
1714
    
1715
    protected InsertColumnBuilder createInsertColumnBuilder() {
1716
        return new InsertColumnBuilderBase();
1717
    }
1718
    
1719
    protected OrderByBuilder createOrderByBuilder() {
1720
        return new OrderByBuilderBase();
1721
    }
1722

    
1723
    protected FromBuilder createFromBuilder() {
1724
        return new FromBuilderBase();
1725
    }
1726

    
1727
    protected SelectBuilder createSelectBuilder() {
1728
        return new SelectBuilderBase();
1729
    }
1730

    
1731
    protected UpdateBuilder createUpdateBuilder() {
1732
        return new UpdateBuilderBase();
1733
    }
1734

    
1735
    protected DeleteBuilder createDeleteBuilder() {
1736
        return new DeleteBuilderBase();
1737
    }
1738

    
1739
    protected GrantBuilder createGrantBuilder() {
1740
        return new GrantBuilderBase();
1741
    }
1742

    
1743
    protected GrantRoleBuilder createGrantRoleBuilder(TableNameBuilder table, String role) {
1744
        return new GrantRoleBuilderBase(table, role);
1745
    }
1746
    
1747
    protected DropTableBuilder createDropTableBuilder() {
1748
        return new DropTableBuilderBase();
1749
    }
1750

    
1751
    protected CreateTableBuilder createCreateTableBuilder() {
1752
        return new CreateTableBuilderBase();
1753
    }
1754

    
1755
    protected AlterTableBuilder createAlterTableBuilder() {
1756
        return new AlterTableBuilderBase();
1757
    }
1758

    
1759
    protected InsertBuilder createInsertBuilder() {
1760
        return new InsertBuilderBase();
1761
    }
1762

    
1763
    protected UpdateTableStatisticsBuilder createUpdateTableStatisticsBuilder() {
1764
        return new UpdateTableStatisticsBuilderBase();
1765
    }
1766

    
1767
    @Override
1768
    public SelectBuilder select() {
1769
        if (this.select == null) {
1770
            this.select = this.createSelectBuilder();
1771
        }
1772
        return this.select;
1773
    }
1774

    
1775
    @Override
1776
    public UpdateBuilder update() {
1777
        if (this.update == null) {
1778
            this.update = this.createUpdateBuilder();
1779
        }
1780
        return this.update;
1781
    }
1782

    
1783
    @Override
1784
    public UpdateTableStatisticsBuilder update_table_statistics() {
1785
        if (this.update_table_statistics == null) {
1786
            this.update_table_statistics = this.createUpdateTableStatisticsBuilder();
1787
        }
1788
        return this.update_table_statistics;
1789
    }
1790

    
1791
    @Override
1792
    public DropTableBuilder drop_table() {
1793
        if (this.drop_table == null) {
1794
            this.drop_table = this.createDropTableBuilder();
1795
        }
1796
        return this.drop_table;
1797
    }
1798

    
1799
    @Override
1800
    public DeleteBuilder delete() {
1801
        if (this.delete == null) {
1802
            this.delete = this.createDeleteBuilder();
1803
        }
1804
        return this.delete;
1805
    }
1806

    
1807
    @Override
1808
    public InsertBuilder insert() {
1809
        if (this.insert == null) {
1810
            this.insert = this.createInsertBuilder();
1811
        }
1812
        return this.insert;
1813
    }
1814

    
1815
    @Override
1816
    public AlterTableBuilder alter_table() {
1817
        if (this.alter_table == null) {
1818
            this.alter_table = this.createAlterTableBuilder();
1819
        }
1820
        return this.alter_table;
1821
    }
1822

    
1823
    @Override
1824
    public CreateTableBuilder create_table() {
1825
        if (this.create_table == null) {
1826
            this.create_table = this.createCreateTableBuilder();
1827
        }
1828
        return this.create_table;
1829
    }
1830

    
1831
    @Override
1832
    public GrantBuilder grant() {
1833
        if (this.grant == null) {
1834
            this.grant = this.createGrantBuilder();
1835
        }
1836
        return this.grant;
1837
    }
1838

    
1839
    @Override
1840
    public void accept(Visitor visitor, VisitorFilter filter) {
1841
        if (this.select != null) {
1842
            this.select.accept(visitor, filter);
1843
        }
1844
        if (this.update != null) {
1845
            this.update.accept(visitor, filter);
1846
        }
1847
        if (this.insert != null) {
1848
            this.insert.accept(visitor, filter);
1849
        }
1850
        if (this.delete != null) {
1851
            this.delete.accept(visitor, filter);
1852
        }
1853
        if (this.alter_table != null) {
1854
            this.alter_table.accept(visitor, filter);
1855
        }
1856
        if (this.create_table != null) {
1857
            this.create_table.accept(visitor, filter);
1858
        }
1859
        if (this.drop_table != null) {
1860
            this.drop_table.accept(visitor, filter);
1861
        }
1862
    }
1863

    
1864
    
1865
    @Override
1866
    public String toString() {
1867
        if (this.select != null) {
1868
            return this.select.toString();
1869
        }
1870
        if (this.update != null) {
1871
            return this.update.toString();
1872
        }
1873
        if (this.insert != null) {
1874
            return this.insert.toString();
1875
        }
1876
        if (this.delete != null) {
1877
            return this.delete.toString();
1878
        }
1879
        if (this.alter_table != null) {
1880
            return this.alter_table.toString();
1881
        }
1882
        if (this.create_table != null) {
1883
            return this.create_table.toString();
1884
        }
1885
        if (this.drop_table != null) {
1886
            return this.drop_table.toString();
1887
        }
1888
        if (this.update_table_statistics != null) {
1889
            return this.update_table_statistics.toString();
1890
        }
1891
        if ( this.value != null ) {
1892
            return this.value.toString();
1893
        }
1894
        return ""; 
1895
    }
1896

    
1897
    @Override
1898
    public Function ST_UnionAggregate(Value geom) {
1899
        return function("ST_UnionAggregate", config.getString(SQLConfig.ST_UnionAggregate), geom);
1900
    }
1901

    
1902
    @Override
1903
    public Function ST_ExtentAggregate(Value geom) {
1904
        return function("ST_ExtentAggregate", config.getString(SQLConfig.ST_ExtentAggregate), geom);
1905
    }
1906

    
1907
    @Override
1908
    public CountBuilder count() {
1909
        return new CountBuilderBase();
1910
    }
1911

    
1912
}