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

History | View | Annotate | Download (124 KB)

1
package org.gvsig.fmap.dal.feature.spi;
2

    
3
import java.text.MessageFormat;
4
import java.util.ArrayList;
5
import java.util.Collection;
6
import java.util.Collections;
7
import java.util.HashMap;
8
import java.util.HashSet;
9
import java.util.List;
10
import java.util.Map;
11
import java.util.Objects;
12
import java.util.Set;
13
import org.apache.commons.lang3.ObjectUtils;
14
import org.apache.commons.lang3.StringUtils;
15
import org.apache.commons.lang3.tuple.ImmutablePair;
16
import org.apache.commons.lang3.tuple.Pair;
17
import org.cresques.cts.IProjection;
18
import org.gvsig.expressionevaluator.ExpressionBuilder;
19
import static org.gvsig.expressionevaluator.ExpressionBuilder.Config.geometry_type_support;
20
import static org.gvsig.expressionevaluator.ExpressionBuilder.Config.has_spatial_functions;
21
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
22
import org.gvsig.fmap.dal.DataStoreParameters;
23
import org.gvsig.fmap.dal.DataTypes;
24
import org.gvsig.fmap.dal.SQLBuilder;
25
import org.gvsig.fmap.dal.SQLBuilder.AlterTableBuilder;
26
import org.gvsig.fmap.dal.SQLBuilder.CreateTableBuilder;
27
import org.gvsig.fmap.dal.SQLBuilder.DeleteBuilder;
28
import org.gvsig.fmap.dal.SQLBuilder.DropTableBuilder;
29
import org.gvsig.fmap.dal.SQLBuilder.FromBuilder;
30
import org.gvsig.fmap.dal.SQLBuilder.GrantBuilder;
31
import org.gvsig.fmap.dal.SQLBuilder.InsertBuilder;
32
import org.gvsig.fmap.dal.SQLBuilder.InsertColumnBuilder;
33
import org.gvsig.fmap.dal.SQLBuilder.OrderByBuilder;
34
import org.gvsig.fmap.dal.SQLBuilder.Privilege;
35
import org.gvsig.fmap.dal.SQLBuilder.SQLConfig;
36
import org.gvsig.fmap.dal.SQLBuilder.SelectBuilder;
37
import org.gvsig.fmap.dal.SQLBuilder.SelectColumnBuilder;
38
import org.gvsig.fmap.dal.SQLBuilder.TableNameBuilder;
39
import org.gvsig.fmap.dal.SQLBuilder.UpdateBuilder;
40
import org.gvsig.fmap.dal.SQLBuilder.UpdateColumnBuilder;
41
import org.gvsig.fmap.dal.SQLBuilder.UpdateTableStatisticsBuilder;
42
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
43
import org.gvsig.fmap.dal.feature.FeatureStore;
44
import org.gvsig.fmap.geom.Geometry;
45
import org.gvsig.fmap.geom.primitive.Envelope;
46
import org.slf4j.Logger;
47
import org.slf4j.LoggerFactory;
48

    
49
public class SQLBuilderBase implements SQLBuilder {
50
    
51
    protected static final Logger logger = LoggerFactory.getLogger(SQLBuilderBase.class);
52
    
53
    protected SelectBuilder select;
54
    protected UpdateBuilder update;
55
    protected InsertBuilder insert;
56
    protected DeleteBuilder delete;
57
    protected AlterTableBuilder alter_table;
58
    protected CreateTableBuilder create_table;
59
    protected GrantBuilder grant;
60
    protected DropTableBuilder drop_table;
61
    protected UpdateTableStatisticsBuilder update_table_statistics;
62
    protected CreateIndexBuilder create_index;
63
    protected List<Parameter> parameters;
64

    
65
    public class ConfigBase implements Config {
66

    
67
        protected Map<String, Object> values;
68

    
69
        public ConfigBase() {
70
            this.values = new HashMap<>();
71

    
72
        }
73

    
74
        @Override
75
        public boolean has_functionality(String functionality) {
76
            Object x = this.values.get(functionality);
77
            if (x == null) {
78
                return false;
79
            }
80
            if (x instanceof CharSequence && StringUtils.isEmpty((CharSequence) x)) {
81
                return false;
82
            }
83
            return true;
84
        }
85

    
86
        @Override
87
        public void remove_functionality(String functionality) {
88
            this.values.remove(functionality);
89
        }
90

    
91
        @Override
92
        public boolean has_spatial_functions() {
93
            return this.getBoolean(has_spatial_functions);
94
        }
95

    
96
        @Override
97
        public GeometrySupportType getGeometryTypeSupport() {
98
            return (GeometrySupportType) this.get(geometry_type_support);
99
        }
100

    
101
        @Override
102
        public boolean getBoolean(String name) {
103
            return (boolean) this.values.get(name);
104
        }
105

    
106
        @Override
107
        public String getString(String name) {
108
            return (String) this.values.get(name);
109
        }
110

    
111
        @Override
112
        public Object get(String name) {
113
            return this.values.get(name);
114
        }
115

    
116
        @Override
117
        public void set(String name, Object value) {
118
            this.values.put(name, value);
119
        }
120
    }
121

    
122
    public abstract class AbstractValue implements Value {
123

    
124
        @Override
125
        public void accept(Visitor visitor, VisitorFilter filter) {
126
            if (filter == null || filter.accept(this)) {
127
                visitor.visit(this);
128
            }
129
        }
130

    
131
    }
132

    
133
    public class ClassVisitorFilter implements VisitorFilter {
134

    
135
        private final Class classFilter;
136

    
137
        public ClassVisitorFilter(Class classFilter) {
138
            this.classFilter = classFilter;
139
        }
140

    
141
        @Override
142
        public boolean accept(Visitable visitable) {
143
            return classFilter.isInstance(visitable);
144
        }
145

    
146
    }
147

    
148
    public class GroupBase extends AbstractValue implements Group {
149

    
150
        protected Value value;
151

    
152
        public GroupBase(Value value) {
153
            this.value = value;
154
        }
155

    
156
        @Override
157
        public Value getValue() {
158
            return value;
159
        }
160

    
161
        @Override
162
        public void accept(Visitor visitor, VisitorFilter filter) {
163
            super.accept(visitor, filter);
164
            this.value.accept(visitor, filter);
165
        }
166

    
167
        @Override
168
        public String toString() {
169
            return MessageFormat.format(config.getString(Config.group), this.value.toString());
170
        }
171
    }
172
    
173
    protected class ColumnDescriptorBase implements ColumnDescriptor {
174

    
175
        private String name;
176
        private int type;
177
        private int type_p;
178
        private int type_s;
179
        private boolean isPk;
180
        private boolean _allowNulls;
181
        private boolean _isAutomatic;
182
        private Object defaultValue;
183
        private int geom_type;
184
        private int geom_subtype;
185
        private Object geom_srsdbcode;
186
        private boolean _isIndexed;
187
        private DataStoreParameters parameters = null;
188

    
189
        public ColumnDescriptorBase(String name, int type, Object defaultValue) {
190
            this.name = name;
191
            this.type = type;
192
            this.type_p = -1;
193
            this.type_s = -1;
194
            this.isPk = false;
195
            this._allowNulls = true;
196
            this._isAutomatic = false;
197
            this.defaultValue = defaultValue;
198
            this.geom_type = Geometry.TYPES.GEOMETRY;
199
            this.geom_subtype = Geometry.SUBTYPES.GEOM2D;
200
            this.geom_srsdbcode = null;
201
            this._isIndexed = false;
202
        }
203

    
204
        public ColumnDescriptorBase(String name, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
205
            this.name = name;
206
            this.type = type;
207
            this.type_p = type_p;
208
            this.type_s = type_s;
209
            this.isPk = isPk;
210
            this._allowNulls = allowNulls;
211
            this._isAutomatic = isAutomatic;
212
            this.defaultValue = defaultValue;
213
            this.geom_type = Geometry.TYPES.GEOMETRY;
214
            this.geom_subtype = Geometry.SUBTYPES.GEOM2D;
215
            this.geom_srsdbcode = null;
216
            this._isIndexed = isIndexed;
217
        }
218
        
219
        public ColumnDescriptorBase(String name, int geom_type, int geom_subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
220
            this.name = name;
221
            this.type = DataTypes.GEOMETRY;
222
            this.type_p = 0;
223
            this.type_s = 0;
224
            this.isPk = false;
225
            this._allowNulls = allowNulls;
226
            this._isAutomatic = false;
227
            this.defaultValue = null;
228
            this.geom_type = geom_type;
229
            this.geom_subtype = geom_subtype;
230
            this.geom_srsdbcode = getSRSId(proj);
231
            this._isIndexed = isIndexed;
232
        }
233
        
234
        public ColumnDescriptorBase(String name, int geom_type, int geom_subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
235
            this.name = name;
236
            this.type = DataTypes.GEOMETRY;
237
            this.type_p = 0;
238
            this.type_s = 0;
239
            this.isPk = false;
240
            this._allowNulls = allowNulls;
241
            this._isAutomatic = false;
242
            this.defaultValue = null;
243
            this.geom_type = geom_type;
244
            this.geom_subtype = geom_subtype;
245
            this.geom_srsdbcode = srsdbcode;
246
            this._isIndexed = isIndexed;
247
        }
248
        
249
        @Override
250
        public String getName() {
251
            return this.name;
252
        }
253
        
254
        @Override
255
        public void setName(String name) {
256
            this.name = name;
257
        }
258

    
259
        @Override
260
        public int getType() {
261
            return this.type;
262
        }
263

    
264
        @Override
265
        public void setType(int type) {
266
            this.type = type;
267
        }
268

    
269
        @Override
270
        public int getPrecision() {
271
            return type_p;
272
        }
273

    
274
        @Override
275
        public void setPrecision(int precision) {
276
            this.type_p = precision;
277
        }
278

    
279
        @Override
280
        public int getSize() {
281
            return type_s;
282
        }
283

    
284
        @Override
285
        public void setSize(int size) {
286
            this.type_s = size;
287
        }
288

    
289
        @Override
290
        public boolean isPrimaryKey() {
291
            return isPk;
292
        }
293

    
294
        @Override
295
        public void setIsPrimaryKey(boolean isPk) {
296
            this.isPk = isPk;
297
        }
298

    
299
        @Override
300
        public boolean allowNulls() {
301
            return _allowNulls;
302
        }
303

    
304
        @Override
305
        public void setAllowNulls(boolean allowNulls) {
306
            this._allowNulls = allowNulls;
307
        }
308

    
309
        @Override
310
        public boolean isAutomatic() {
311
            return _isAutomatic;
312
        }
313

    
314
        @Override
315
        public boolean isIndexed() {
316
            return _isIndexed;
317
        }
318

    
319
        @Override
320
        public void setIsAutomatic(boolean isAutomatic) {
321
            this._isAutomatic = isAutomatic;
322
        }
323

    
324
        @Override
325
        public Object getDefaultValue() {
326
            return defaultValue;
327
        }
328

    
329
        @Override
330
        public void setDefaultValue(Object defaultValue) {
331
            this.defaultValue = defaultValue;
332
        }
333

    
334
        @Override
335
        public int getGeometryType() {
336
            return geom_type;
337
        }
338

    
339
        @Override
340
        public void setGeometryType(int geom_type) {
341
            this.geom_type = geom_type;
342
        }
343

    
344
        @Override
345
        public int getGeometrySubtype() {
346
            return geom_subtype;
347
        }
348

    
349
        @Override
350
        public void setGeometrySubtype(int geom_subtype) {
351
            this.geom_subtype = geom_subtype;
352
        }
353

    
354
        @Override
355
        public Object getGeometrySRSId() {
356
            return geom_srsdbcode;
357
        }
358

    
359
        @Override
360
        public void setGeometrySRSId(Object geom_srsid) {
361
            this.geom_srsdbcode = geom_srsid;
362
        }        
363

    
364
        @Override
365
        public boolean isGeometry() {
366
            return this.type == DataTypes.GEOMETRY;
367
        }
368

    
369
        private void setStoreParameters(DataStoreParameters parameters) {
370
            this.parameters = parameters;
371
        }
372

    
373
        @Override
374
        public DataStoreParameters getStoreParameters() {
375
            return this.parameters;
376
        }
377
    }
378

    
379
    public class VariableBase extends AbstractValue implements Column {
380

    
381
        protected ColumnDescriptor descriptor;
382
        protected String name;
383

    
384

    
385
        public VariableBase(ColumnDescriptor descriptor) {
386
            this.name = descriptor.getName();
387
            this.descriptor = descriptor;
388
        }
389

    
390
        public VariableBase(String name) {
391
            this.name = name;
392
            this.descriptor = null;
393
        }
394

    
395
        @Override
396
        public ColumnDescriptor getDescriptor() {
397
            return descriptor;
398
        }
399

    
400
        @Override
401
        public String getName() {
402
            return this.name;
403
        }
404

    
405
        @Override
406
        public String toString() {
407
            return identifier(this.name);
408
        }
409

    
410
        @Override
411
        public int compareTo(ExpressionBuilder.Variable o) {
412
            return this.name.compareTo(o.getName());
413
        }
414

    
415
        @Override
416
        public boolean equals(Object obj) {
417
            if (!(obj instanceof ExpressionBuilder.Variable)) {
418
                return false;
419
            }
420
            return this.name.equals(((ExpressionBuilder.Variable) obj).getName());
421
        }
422

    
423
        @Override
424
        public int hashCode() {
425
            int hash = 7;
426
            hash = 37 * hash + Objects.hashCode(this.name);
427
            return hash;
428
        }
429

    
430
    }
431

    
432
    
433
    public class ParameterBase extends AbstractValue implements Parameter {
434

    
435
        protected String name;
436
        protected Object value;
437
        protected ParameterType type;
438
        protected Value srs;
439

    
440
        public ParameterBase() {
441
            this.type = ParameterType.Constant;
442
            this.name = null;
443
            this.value = null;
444
        }
445

    
446
        @Override
447
        public void accept(Visitor visitor, VisitorFilter filter) {
448
            super.accept(visitor, filter);
449
            if (this.srs != null) {
450
                this.srs.accept(visitor, filter);
451
            }
452
        }
453

    
454
        @Override
455
        public Parameter as_geometry_variable() {
456
            this.type = ParameterType.Geometry;
457
            if (this.value == null && this.name != null) {
458
                this.value = this.name;
459
            }
460
            return this;
461
        }
462

    
463
        @Override
464
        public Parameter as_constant() {
465
            this.type = ParameterType.Constant;
466
            if (this.value == null && this.name != null) {
467
                this.value = this.name;
468
            }
469
            return this;
470
        }
471

    
472
        @Override
473
        public Parameter as_variable() {
474
            this.type = ParameterType.Variable;
475
            if (this.value != null && this.name == null) {
476
                this.name = (String) this.value;
477
            }
478
            return this;
479
        }
480

    
481
        @Override
482
        public Parameter srs(Value srs) {
483
            this.srs = srs;
484
            if( this.type == ParameterType.Variable ) {
485
                this.type = ParameterType.Geometry;
486
            }
487
            return this;
488
        }
489

    
490
        @Override
491
        public Parameter srs(IProjection srs) {
492
            this.srs = constant(getSRSId(srs));
493
            if( this.type == ParameterType.Variable ) {
494
                this.type = ParameterType.Geometry;
495
            }
496
            return this;
497
        }
498

    
499
        @Override
500
        public String getName() {
501
            switch (this.type) {
502
                case Variable:
503
                case Geometry:
504
                    return this.name;
505
                case Constant:
506
                    if (this.value == null) {
507
                        return null;
508
                    }
509
                    return this.value.toString();
510
                default:
511
                    if (this.name != null) {
512
                        return this.name;
513
                    }
514
                    if (this.value != null) {
515
                        return this.value.toString();
516
                    }
517
                    return null;
518
            }
519
        }
520

    
521
        @Override
522
        public boolean is_constant() {
523
            return this.type == ParameterType.Constant;
524
        }
525

    
526
        @Override
527
        public boolean is_geometry_variable() {
528
            return this.type == ParameterType.Geometry;
529
        }
530

    
531
        @Override
532
        public boolean is_variable() {
533
            return this.type == ParameterType.Variable;
534
        }
535

    
536
        @Override
537
        public Parameter value(Object value) {
538
            this.value = value;
539
            return this;
540
        }
541

    
542
        @Override
543
        public Parameter name(String name) {
544
            this.type = ParameterType.Variable;
545
            this.name = name;
546
            return this;
547
        }
548

    
549
        @Override
550
        public Object getValue() {
551
            try {
552
                switch (this.type) {
553
                    case Constant:
554
                        if (this.value instanceof Geometry) {
555
                            switch (config.getGeometryTypeSupport()) {
556
                                case EWKB:
557
                                    return bytearray(((Geometry) this.value).convertToEWKB());
558
                                case NATIVE:
559
                                case WKB:
560
                                    return bytearray(((Geometry) this.value).convertToWKB());
561
                                case WKT:
562
                                default:
563
                                    return ((Geometry) this.value).convertToWKT();
564
                            }
565
                        } else if (this.value instanceof IProjection) {
566
                            return getSRSId((IProjection) this.value);
567
                        }
568
                        return this.value;
569
                    case Variable:
570
                    case Geometry:
571
                    default:
572
                        return this.value;
573
                }
574
            } catch (Exception ex) {
575
                throw new RuntimeException("Can't get value from parameter.", ex);
576
            }
577
        }
578

    
579
        @Override
580
        public ParameterType getType() {
581
            return this.type;
582
        }
583

    
584
        @Override
585
        public Value getSRS() {
586
            return this.srs;
587
        }
588

    
589
        @Override
590
        public String toString() {
591
            switch (this.type) {
592
                case Constant:
593
                case Variable:
594
                default:
595
                    return "?";
596
                case Geometry:
597
                    switch (config.getGeometryTypeSupport()) {
598
                        case EWKB:
599
                            return MessageFormat.format(
600
                                    config.getString(Config.ST_GeomFromEWKB),
601
                                    "?",
602
                                    String.valueOf(this.srs.toString())
603
                            );
604
                        case WKB:
605
                            return MessageFormat.format(
606
                                    config.getString(Config.ST_GeomFromWKB),
607
                                    "?",
608
                                    String.valueOf(this.srs.toString())
609
                            );
610
                        case WKT:
611
                        default:
612
                            return MessageFormat.format(
613
                                    config.getString(Config.ST_GeomFromText),
614
                                    "?",
615
                                    String.valueOf(this.srs.toString())
616
                            );
617
                    }
618
            }
619
        }
620
    }
621

    
622
    public class ConstantBase extends AbstractValue implements Constant {
623

    
624
        protected Object value;
625

    
626
        public ConstantBase(Object value) {
627
            this.value = value;
628
        }
629

    
630
        @Override
631
        public Object getValue() {
632
            return this.value;
633
        }
634

    
635
        @Override
636
        public String toString() {
637
            if (this.value instanceof String) {
638
                return string((String) this.value);
639
            }
640
            if (this.value instanceof Boolean) {
641
                if (((Boolean) this.value)) {
642
                    return config.getString(Config.constant_true);
643
                } else {
644
                    return config.getString(Config.constant_false);
645
                }
646
            }
647
            return ObjectUtils.toString(this.value, "");
648
        }
649
    }
650

    
651
    public class CustomBase extends AbstractValue implements Custom {
652

    
653
        protected Object value;
654

    
655
        // Esto es para permitir declarar parametros y columnas en una seccion
656
        // custom.
657
        protected List<Value> values;
658

    
659
        public CustomBase(Object value) {
660
            this.value = value;
661
        }
662

    
663
        @Override
664
        public void accept(Visitor visitor, VisitorFilter filter) {
665
            super.accept(visitor, filter);
666
            if (this.values != null) {
667
                for (Value value : values) {
668
                    value.accept(visitor, filter);
669
                }
670
            }
671
        }
672

    
673
        @Override
674
        public Object getValue() {
675
            return this.value;
676
        }
677

    
678
        @Override
679
        public Custom add(Variable variable) {
680
            if (this.values == null) {
681
                this.values = new ArrayList<>();
682
            }
683
            this.values.add(variable);
684
            return this;
685
        }
686

    
687
        @Override
688
        public Custom add(Parameter parameter) {
689
            if (this.values == null) {
690
                this.values = new ArrayList<>();
691
            }
692
            this.values.add(parameter);
693
            return this;
694
        }
695

    
696
        @Override
697
        public String toString() {
698
            return ObjectUtils.toString(this.value, "");
699
        }
700
    }
701

    
702
    public class GeometryValueBase extends AbstractValue implements GeometryValue {
703

    
704
        protected Geometry geometry;
705
        protected IProjection projection;
706

    
707
        public GeometryValueBase(Geometry geometry, IProjection projection) {
708
            this.geometry = geometry;
709
            this.projection = projection;
710
        }
711

    
712
        @Override
713
        public Geometry getGeometry() {
714
            return this.geometry;
715
        }
716

    
717
        @Override
718
        public IProjection getSRS() {
719
            return this.projection;
720
        }
721

    
722
        @Override
723
        public String toString() {
724
            try {
725
                switch (config.getGeometryTypeSupport()) {
726
                    case EWKB:
727
                        return MessageFormat.format(
728
                                config.getString(Config.ST_GeomFromEWKB),
729
                                bytearray(this.geometry.convertToEWKB()),
730
                                String.valueOf(getSRSId(this.projection))
731
                        );
732
                    case WKB:
733
                        return MessageFormat.format(
734
                                config.getString(Config.ST_GeomFromWKB),
735
                                bytearray(this.geometry.convertToWKB()),
736
                                String.valueOf(getSRSId(this.projection))
737
                        );
738
                    case WKT:
739
                    default:
740
                        return MessageFormat.format(
741
                                config.getString(Config.ST_GeomFromText),
742
                                string(this.geometry.convertToWKT()),
743
                                String.valueOf(getSRSId(this.projection))
744
                        );
745
                }
746
            } catch (Exception ex) {
747
                throw new RuntimeException("Can't convert geometry to string.", ex);
748
            }
749
        }
750
    }
751

    
752
    public class FunctionBase extends AbstractValue implements Function {
753

    
754
        protected String name;
755
        protected String format;
756
        protected List<Value> parameters;
757

    
758
        public FunctionBase(String name, String format) {
759
            this.name = name;
760
            this.format = format;
761
        }
762

    
763
        public FunctionBase(String name) {
764
            this(name,null);
765
        }
766
        
767
        @Override
768
        public List<Value> parameters() {
769
            if (this.parameters == null) {
770
                this.parameters = new ArrayList<>();
771
            }
772
            return this.parameters;
773
        }
774

    
775
        @Override
776
        public Function parameter(Value parameter) {
777
            this.parameters().add(parameter);
778
            return this;
779
        }
780

    
781
        @Override
782
        public String getName() {
783
            return this.name;
784
        }
785

    
786
        @Override
787
        public void accept(Visitor visitor, VisitorFilter filter) {
788
            super.accept(visitor, filter);
789
            for (Value value : this.parameters) {
790
                value.accept(visitor, filter);
791
            }
792
        }
793

    
794
        @Override
795
        public String toString() {
796
            if( this.format==null ) {
797
                StringBuilder builder = new StringBuilder();
798
                builder.append(name);
799
                builder.append("(");
800
                if (this.parameters != null && !this.parameters.isEmpty()) {
801
                    boolean first = true;
802
                    for (Value value : this.parameters) {
803
                        if( first ) {
804
                            first=false;
805
                            builder.append(value.toString());
806
                        } else {
807
                            builder.append(", ");
808
                            builder.append(value.toString());
809
                        }
810
                    }
811
                }
812
                builder.append(")");
813
                return builder.toString();
814
            }
815
            if (this.parameters != null && !this.parameters.isEmpty()) {
816
                List<String> values = new ArrayList<>();
817
                for (Value value : this.parameters) {
818
                    values.add(value.toString());
819
                }
820
                return MessageFormat.format(format, values.toArray());
821
            } else {
822
                return this.format;
823
            }
824
        }
825
    }
826

    
827
    public class BinaryOperatorBase extends AbstractValue implements BinaryOperator {
828

    
829
        protected String name;
830
        protected String format;
831
        protected Value left;
832
        protected Value right;
833

    
834
        public BinaryOperatorBase(String name, String format) {
835
            this.name = name;
836
            this.format = format;
837
        }
838

    
839
        @Override
840
        public String getName() {
841
            return this.name;
842
        }
843

    
844
        @Override
845
        public void accept(Visitor visitor, VisitorFilter filter) {
846
            super.accept(visitor, filter);
847
            this.left.accept(visitor, filter);
848
            this.right.accept(visitor, filter);
849
        }
850

    
851
        @Override
852
        public BinaryOperator setLeft(Value operand) {
853
            this.left = operand;
854
            return this;
855
        }
856

    
857
        @Override
858
        public BinaryOperator setRight(Value operand) {
859
            this.right = operand;
860
            return this;
861
        }
862

    
863
        @Override
864
        public Value getLeft() {
865
            return this.left;
866
        }
867

    
868
        @Override
869
        public Value getRight() {
870
            return this.right;
871
        }
872

    
873
        @Override
874
        public String toString() {
875
            return MessageFormat.format(
876
                    format,
877
                    this.left.toString(),
878
                    this.right.toString()
879
            );
880
        }
881
    }
882
    
883
    public class TableNameBuilderBase implements TableNameBuilder {
884

    
885
        public String tableName;
886
        public String schemaName;
887
        private String databaseName;
888

    
889
        public TableNameBuilderBase() {
890
        }
891

    
892
        @Override
893
        public void accept(Visitor visitor, VisitorFilter filter) {
894
            if( filter.accept(this) ) {
895
                visitor.visit(this);
896
            }
897
        }
898

    
899
        @Override
900
        public TableNameBuilder database(String name) {
901
            this.databaseName = name;
902
            return this;
903
        }
904

    
905
        @Override
906
        public TableNameBuilder schema(String name) {
907
            if( supportSchemas() ) {
908
                this.schemaName = name;
909
            }
910
            return this;
911
        }
912

    
913
        @Override
914
        public TableNameBuilder name(String name) {
915
            this.tableName = name;
916
            return this;
917
        }
918

    
919
        @Override
920
        public String getDatabase() {
921
            return this.databaseName;
922
        }
923

    
924
        @Override
925
        public String getSchema() {
926
            return this.schemaName;
927
        }
928

    
929
        @Override
930
        public String getName() {
931
            return this.tableName;
932
        }
933
        
934
        @Override
935
        public boolean has_schema() {
936
            if( !supportSchemas() ) {
937
                return false;
938
            }
939
            return !StringUtils.isEmpty(this.schemaName);
940
        }
941

    
942
        @Override
943
        public boolean has_database() {
944
            return !StringUtils.isEmpty(this.databaseName);
945
        }
946
        
947
        @Override
948
        public String toString() {
949
            if( this.has_database()) {
950
                if( this.has_schema()) {
951
                    return identifier(this.databaseName) + "." + 
952
                           identifier(this.schemaName) + "." + 
953
                           identifier(this.tableName);
954
                }
955
            } else {
956
                if( this.has_schema()) {
957
                    return identifier(this.schemaName) + "." + 
958
                           identifier(this.tableName);
959
                }                
960
            }
961
            return identifier(this.tableName);
962
        }
963

    
964
    }
965

    
966
    public class CountBuilderBase extends AbstractValue implements CountBuilder {
967

    
968
        protected Value value;
969
        protected boolean distinct;
970
        protected boolean all ;
971
        
972
        public CountBuilderBase() {
973
            this.value = null;
974
            this.distinct = false;
975
            this.all = false;
976
        }
977
        
978
        @Override
979
        public CountBuilder all() {
980
            this.all = true;
981
            return this;
982
        }
983

    
984
        @Override
985
        public CountBuilder column(Value value) {
986
            this.value = value;
987
            return this;
988
        }
989

    
990
        @Override
991
        public CountBuilder distinct() {
992
            this.distinct = true;
993
            return this;
994
        }
995

    
996
        @Override
997
        public String toString() {
998
            if( this.all ) {
999
                return MessageFormat.format(
1000
                    config.getString(SQLConfig.count),
1001
                    "*"
1002
                );
1003
            }
1004
            if( this.distinct ) {
1005
                return MessageFormat.format(
1006
                    config.getString(SQLConfig.count_distinct),
1007
                    value.toString()
1008
                );
1009
            }
1010
            return MessageFormat.format(
1011
                config.getString(SQLConfig.count),
1012
                value.toString()
1013
            );
1014
        }
1015
        
1016
        
1017
    }
1018
    
1019
    public class FromBuilderBase implements FromBuilder {
1020

    
1021
        protected TableNameBuilder tableName= null;
1022
        private String subquery = null;
1023
        private String passthrough = null;
1024

    
1025
        @Override
1026
        public TableNameBuilder table() {
1027
            if( tableName == null ) {
1028
                this.tableName = createTableNameBuilder();
1029
            }
1030
            return this.tableName;
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.tableName != null ) {
1039
                this.tableName.accept(visitor, filter);
1040
            }
1041
        }
1042

    
1043
        @Override
1044
        public FromBuilder custom(String passthrough) {
1045
            this.passthrough = passthrough;
1046
            return this;
1047
        }
1048

    
1049
        @Override
1050
        public FromBuilder subquery(String subquery) {
1051
            this.subquery = subquery;
1052
            return this;
1053
        }
1054
        
1055
        @Override
1056
        public String toString() {
1057
            if( ! StringUtils.isEmpty(passthrough) ) {
1058
                return passthrough;
1059
            }
1060
            if( ! StringUtils.isEmpty(subquery) ) {
1061
                return "( " + this.subquery + ") as _subquery_alias_ ";
1062
            }
1063
            return this.tableName.toString();
1064
        }
1065

    
1066
    }
1067

    
1068
    public class SelectColumnBuilderBase implements SelectColumnBuilder {
1069

    
1070
        private Variable name = null;
1071
        private String alias = null;
1072
        private Value value = null;
1073
        private boolean asGeometry = false;
1074
        
1075
        @Override
1076
        public void accept(Visitor visitor, VisitorFilter filter) {
1077
            if( filter.accept(this) ) {
1078
                visitor.visit(this);
1079
            }
1080
            if( this.name != null ) {
1081
                this.name.accept(visitor, filter);
1082
            }
1083
            if( this.value != null ) {
1084
                this.value.accept(visitor, filter);
1085
            }
1086
        }
1087

    
1088
        @Override
1089
        public SelectColumnBuilder name(String name) {
1090
            String quote = config.getString(Config.quote_for_identifiers);
1091
            if (name.startsWith(quote)) {
1092
                // Remove quotes
1093
                name = name.substring(1, name.length() - 1);
1094
            }
1095
            this.name = variable(name);
1096
            this.value = null;
1097
            this.asGeometry = false;
1098
            return this;
1099
        }
1100

    
1101
        @Override
1102
        public SelectColumnBuilder all() {
1103
            this.name = null;
1104
            this.value = custom("*");
1105
            this.asGeometry = false;
1106
            return this;
1107
        }
1108
        
1109
        @Override
1110
        public SelectColumnBuilder as_geometry() {
1111
            this.asGeometry = true;
1112
            return this;
1113
        }
1114
       
1115
        @Override
1116
        public SelectColumnBuilder value(Value value) {
1117
            this.value = value;
1118
            this.name = null;
1119
            return this;
1120
        }
1121

    
1122
        @Override
1123
        public SelectColumnBuilder as(String alias) {
1124
            this.alias = alias;
1125
            return this;
1126
        }
1127

    
1128
        @Override
1129
        public String getName() {
1130
            return this.name.getName();
1131
        }
1132
        
1133
        @Override
1134
        public String getAlias() {
1135
            return this.alias;
1136
        }
1137
        
1138
        @Override
1139
        public String getValue() {
1140
            return this.alias;
1141
        }
1142

    
1143
        @Override
1144
        public String toString() {
1145
            StringBuilder builder = new StringBuilder();
1146
            if( this.asGeometry ) {
1147
                builder.append(getAsGeometry(this.name).toString());
1148
            } else {
1149
                if( this.name != null ) {
1150
                    builder.append(this.name.toString());
1151
                } else {
1152
                    builder.append(this.value.toString());
1153
                }
1154
            }
1155
            if( this.alias != null ) {
1156
                builder.append(" AS ");
1157
                builder.append(identifier(this.alias));
1158
            }
1159
            return builder.toString();
1160
        }
1161
    }
1162

    
1163
    public class OrderByBuilderBase implements OrderByBuilder {
1164
        protected String value;
1165
        protected String custom;
1166
        protected boolean ascending;
1167
        
1168
        public OrderByBuilderBase() {
1169
            this.ascending = true;
1170
        }
1171

    
1172
        @Override
1173
        public void accept(Visitor visitor, VisitorFilter filter) {
1174
            if( filter.accept(this) ) {
1175
                visitor.visit(this);
1176
            }
1177
        }
1178

    
1179
        @Override
1180
        public OrderByBuilder column(String name) {
1181
            this.value = name;
1182
            return this;
1183
        }
1184

    
1185
        @Override
1186
        public OrderByBuilder custom(String order) {
1187
            this.custom = order;
1188
            return this;
1189
        }
1190

    
1191
        @Override
1192
        public OrderByBuilder ascending() {
1193
            this.ascending = true;
1194
            return this;
1195
        }
1196

    
1197
        @Override
1198
        public OrderByBuilder ascending(boolean asc) {
1199
            this.ascending = asc;
1200
            return this;
1201
        }
1202

    
1203
        @Override
1204
        public OrderByBuilder descending() {
1205
            this.ascending = false;
1206
            return this;
1207
        }
1208

    
1209
        @Override
1210
        public String toString() {
1211
            if( !StringUtils.isEmpty(this.custom) ) {
1212
                return this.custom;
1213
            }
1214
            if( this.ascending ) {
1215
                return identifier(this.value) + " ASC";
1216
            }
1217
            return identifier(this.value) + " DESC";
1218
        }
1219
    }
1220
    
1221
    public class SelectBuilderBase implements SelectBuilder {
1222

    
1223
        protected FromBuilder from;
1224
        protected ExpressionBuilder where;
1225
        protected long limit = -1;
1226
        protected long offset = -1;
1227
        protected List<SelectColumnBuilder> columns;
1228
        protected List<OrderByBuilder> order_by;
1229
        protected boolean distinct;
1230

    
1231
        public SelectBuilderBase() {
1232
            this.columns = new ArrayList<>();
1233
            this.distinct = false;
1234
        }
1235

    
1236
        @Override
1237
        public void accept(Visitor visitor, VisitorFilter filter) {
1238
            if( filter.accept(this) ) {
1239
                visitor.visit(this);
1240
            }
1241
            for (SelectColumnBuilder column : columns) {
1242
                column.accept(visitor,filter);
1243
            }
1244
            if( this.has_from() ) {
1245
                this.from.accept(visitor,filter);
1246
            }
1247
            if( this.has_where() ) {
1248
                this.where.accept(visitor,filter);
1249
            }
1250
            if( this.has_order_by() ) {
1251
                for (OrderByBuilder order : order_by) {
1252
                    order.accept(visitor,filter);
1253
                }
1254
            }
1255
        }
1256

    
1257
        @Override
1258
        public SelectBuilder distinct() {
1259
            this.distinct = true;
1260
            return this;
1261
        }
1262
        
1263
        @Override
1264
        public SelectColumnBuilder column() {
1265
            SelectColumnBuilder builder = createSelectColumnBuilder();
1266
            this.columns.add(builder);
1267
            return builder;
1268
        }
1269

    
1270
        @Override
1271
        public boolean has_column(String name) {
1272
            for (SelectColumnBuilder column : columns) {
1273
                if( name.equals(column.getName()) ) {
1274
                    return true;
1275
                }
1276
            }
1277
            return false;
1278
        }
1279

    
1280
        @Override
1281
        public FromBuilder from() {
1282
            if (this.from == null) {
1283
                this.from = createFromBuilder();
1284
            }
1285
            return this.from;
1286
        }
1287

    
1288
        @Override
1289
        public boolean has_from() {
1290
            return this.from != null;
1291
        }
1292
        
1293
        @Override
1294
        public ExpressionBuilder where() {
1295
            if (this.where == null) {
1296
                this.where = createExpressionBuilder();
1297
            }
1298
            return this.where;
1299
        }
1300

    
1301
        @Override
1302
        public boolean has_where() {
1303
            if( this.where == null ) {
1304
                return false;
1305
            }
1306
            return this.where.getValue() != null;
1307
        }
1308
        
1309
        @Override
1310
        public SelectBuilder limit(long limit) {
1311
            this.limit = limit;
1312
            return this;
1313
        }
1314

    
1315
        @Override
1316
        public boolean has_limit() {
1317
            return this.limit > 0;
1318
        }
1319

    
1320
        @Override
1321
        public SelectBuilder offset(long offset) {
1322
            this.offset = offset;
1323
            return this;
1324
        }
1325

    
1326
        @Override
1327
        public boolean has_offset() {
1328
            return this.offset > 0;
1329
        }
1330

    
1331
        @Override
1332
        public OrderByBuilder order_by() {
1333
            if( this.order_by == null ) {
1334
                this.order_by = new ArrayList<>();
1335
            }
1336
            OrderByBuilder order = createOrderByBuilder();
1337
            this.order_by.add(order);
1338
            return order;
1339
        }
1340

    
1341
        @Override
1342
        public boolean has_order_by() {
1343
            if( this.order_by == null ) {
1344
                return false;
1345
            }
1346
            return !this.order_by.isEmpty();
1347
        }
1348
        
1349
        protected boolean isValid(StringBuilder message) {
1350
            if( message == null ) {
1351
                message = new StringBuilder();
1352
            }
1353
            if( this.has_offset() && !this.has_order_by() ) {
1354
                // Algunos gestores de BBDD requieren que se especifique un
1355
                // orden para poder usar OFFSET. Como eso parece buena idea para
1356
                // asegurar que siempre tengamos los mismo resultados, lo exijimos
1357
                // siempre.
1358
                message.append("Can't use OFFSET without an ORDER BY.");
1359
                return false;
1360
            }
1361
            return true;
1362
        }
1363
        
1364
        @Override
1365
        public String toString() {
1366
            StringBuilder builder = new StringBuilder();
1367
            if( !this.isValid(builder) ) {
1368
                throw new IllegalStateException(builder.toString());
1369
            }
1370
            builder.append("SELECT ");
1371
            if( this.distinct ) {
1372
                builder.append("DISTINCT ");
1373
            }
1374
            boolean first = true;
1375
            for (SelectColumnBuilder column : columns) {
1376
                if (first) {
1377
                    first = false;
1378
                } else {
1379
                    builder.append(", ");
1380
                }
1381
                builder.append(column.toString());
1382
            }
1383

    
1384
            if ( this.has_from() ) {
1385
                builder.append(" FROM ");
1386
                builder.append(this.from.toString());
1387
            }
1388
            if ( this.has_where() ) {
1389
                builder.append(" WHERE ");
1390
                builder.append(this.where.toString());
1391
            }
1392
            
1393
            if( this.has_order_by() ) {
1394
                builder.append(" ORDER BY ");
1395
                first = true;
1396
                for (OrderByBuilder item : this.order_by) {
1397
                    if (first) {
1398
                        first = false;
1399
                    } else {
1400
                        builder.append(", ");
1401
                    }
1402
                    builder.append(item.toString());                    
1403
                }   
1404
            }
1405
            
1406
            if ( this.has_limit() ) {
1407
                builder.append(" LIMIT ");
1408
                builder.append(this.limit);
1409
            }
1410
            if ( this.has_offset() ) {
1411
                builder.append(" OFFSET ");
1412
                builder.append(this.offset);
1413
            }
1414
            return builder.toString();
1415

    
1416
        }
1417
    }
1418

    
1419
    public class DropTableBuilderBase implements DropTableBuilder {
1420

    
1421
        protected TableNameBuilder table;
1422

    
1423
        @Override
1424
        public TableNameBuilder table() {
1425
            if( table == null ) {
1426
                table = createTableNameBuilder();
1427
            }
1428
            return table;
1429
        }
1430

    
1431
        @Override
1432
        public void accept(Visitor visitor, VisitorFilter filter) {
1433
            if( filter.accept(this) ) {
1434
                visitor.visit(this);
1435
            }
1436
            this.table.accept(visitor,filter);
1437
        }
1438
        
1439
        @Override
1440
        public String toString() {
1441
            StringBuilder builder = new StringBuilder();
1442
            boolean first = true;
1443
            for (String sql : toStrings()) {
1444
                if( StringUtils.isEmpty(sql) ) {
1445
                    continue;
1446
                }
1447
                if (first) {
1448
                    first = false;
1449
                } else {
1450
                    builder.append("; ");
1451
                }
1452
                builder.append(sql);
1453
            }
1454
            return builder.toString();
1455
        }
1456

    
1457
        @Override
1458
        public List<String> toStrings() {
1459
            List<String> sqls = new ArrayList<>();
1460

    
1461
            sqls.add(
1462
                    MessageFormat.format(
1463
                            config.getString(SQLConfig.DROP_TABLE_table),
1464
                            this.table.toString()
1465
                    )
1466
            );
1467
            String sql;
1468
            if( config.has_functionality(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table) ) {
1469
                if (this.table.has_schema()) {
1470
                    sql = MessageFormat.format(
1471
                            config.getString(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table),
1472
                            string(this.table.getSchema()),
1473
                            string(this.table.getName())
1474
                    );
1475
                } else {
1476
                    sql = MessageFormat.format(
1477
                            config.getString(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table),
1478
                            identifier(this.table.getName())
1479
                    );
1480
                }
1481
                if( !StringUtils.isEmpty(sql) ) {
1482
                    sqls.add(sql);
1483
                }
1484
            }
1485
            return sqls;
1486
        }
1487
    }
1488

    
1489
    public class GrantRoleBuilderBase implements GrantRoleBuilder {
1490
        protected TableNameBuilder table;
1491
        protected String role;
1492
        protected Set<Privilege> privileges;
1493

    
1494
        public GrantRoleBuilderBase(TableNameBuilder table, String role) {
1495
            this.table = table;
1496
            this.role = role;
1497
            this.privileges = new HashSet<>();
1498
        }
1499

    
1500
        @Override
1501
        public GrantRoleBuilder privilege(Privilege privilege) {
1502
            privileges.add(privilege);
1503
            return this;
1504
        }
1505
        
1506
        @Override
1507
        public GrantRoleBuilder select() {
1508
             privileges.add(Privilege.SELECT);
1509
            return this;
1510
        }
1511

    
1512
        @Override
1513
        public GrantRoleBuilder update() {
1514
             privileges.add(Privilege.UPDATE);
1515
            return this;
1516
        }
1517

    
1518
        @Override
1519
        public GrantRoleBuilder insert() {
1520
            privileges.add(Privilege.INSERT);
1521
            return this;
1522
        }
1523

    
1524
        @Override
1525
        public GrantRoleBuilder delete() {
1526
            privileges.add(Privilege.DELETE);
1527
            return this;
1528
        }
1529

    
1530
        @Override
1531
        public GrantRoleBuilder truncate() {
1532
            privileges.add(Privilege.TRUNCATE);
1533
            return this;
1534
        }
1535

    
1536
        @Override
1537
        public GrantRoleBuilder reference() {
1538
            privileges.add(Privilege.REFERENCE);
1539
            return this;
1540
        }
1541

    
1542
        @Override
1543
        public GrantRoleBuilder trigger() {
1544
            privileges.add(Privilege.TRIGGER);
1545
            return this;
1546
        }
1547

    
1548
        @Override
1549
        public GrantRoleBuilder all() {
1550
            privileges.add(Privilege.ALL);
1551
            return this;
1552
        }
1553

    
1554
        protected String getPrivilegeName(Privilege privilege) {
1555
            switch(privilege) {
1556
                case DELETE:
1557
                    return "DELETE";
1558
                case INSERT:
1559
                    return "INSERT";
1560
                case REFERENCE:
1561
                    return "REFERENCE";
1562
                case SELECT:
1563
                    return "SELECT";
1564
                case TRIGGER:
1565
                    return "TRIGGER";
1566
                case TRUNCATE:
1567
                    return "TRUNCATE";
1568
                case UPDATE:
1569
                    return "UPDATE";
1570
                case ALL:
1571
                default:
1572
                    return "ALL";
1573
            }
1574
        }
1575
        
1576
        @Override
1577
        public String toString() {
1578
            StringBuilder builder = new StringBuilder();
1579
            boolean first = true;
1580
            for (Privilege privilege : privileges) {
1581
                if (first) {
1582
                    first = false;
1583
                } else {
1584
                    builder.append(", ");
1585
                }
1586
                builder.append( this.getPrivilegeName(privilege));
1587
            }
1588
            String sql = MessageFormat.format(
1589
                    config.getString(SQLConfig.GRANT_privileges_ON_table_TO_role),
1590
                    builder.toString(),
1591
                    table.toString(),
1592
                    role
1593
            );
1594
            return sql;
1595
        }
1596
    }
1597
    
1598
    public class GrantBuilderBase implements GrantBuilder {
1599

    
1600
        protected TableNameBuilder table;
1601
        protected Map<String, GrantRoleBuilder> roles;
1602

    
1603
        public GrantBuilderBase() {
1604
            this.roles = new HashMap<>();
1605
        }
1606
        
1607
        @Override
1608
        public TableNameBuilder table() {
1609
            if( table == null ) {
1610
                table = createTableNameBuilder();
1611
            }
1612
            return table;
1613
        }
1614

    
1615
        @Override
1616
        public void accept(Visitor visitor, VisitorFilter filter) {
1617
            if( filter.accept(this) ) {
1618
                visitor.visit(this);
1619
            }
1620
            if( this.table!= null ) {
1621
                this.table.accept(visitor,filter);
1622
            }
1623
        }
1624
        
1625
        @Override
1626
        public GrantRoleBuilder role(String role) {
1627
            GrantRoleBuilder roleBuilder = this.roles.get(role);
1628
            if( roleBuilder == null ) {
1629
                roleBuilder = createGrantRoleBuilder(this.table(), role);
1630
                this.roles.put(role, roleBuilder);
1631
            }
1632
            return roleBuilder;
1633
        }
1634

    
1635
        @Override
1636
        public String toString() {
1637
            StringBuilder builder = new StringBuilder();
1638
            boolean first = true;
1639
            for (String sql : toStrings()) {
1640
                if( StringUtils.isEmpty(sql) ) {
1641
                    continue;
1642
                }
1643
                if (first) {
1644
                    first = false;
1645
                } else {
1646
                    builder.append("; ");
1647
                }
1648
                builder.append(sql);
1649
            }
1650
            return builder.toString();
1651
        }
1652

    
1653
        @Override
1654
        public List<String> toStrings() {
1655
            List<String> sqls = new ArrayList<>();
1656
            for (GrantRoleBuilder role : roles.values()) {
1657
                sqls.add(role.toString());
1658
            }
1659
            return sqls;
1660
        }
1661
    }
1662

    
1663
    public class UpdateColumnBuilderBase extends InsertColumnBuilderBase implements UpdateColumnBuilder {
1664
        
1665
        public UpdateColumnBuilderBase() {
1666
            super();
1667
        }
1668

    
1669
        @Override
1670
        public UpdateColumnBuilder name(String name) {
1671
            return (UpdateColumnBuilder) super.name(name);
1672
        }
1673

    
1674
        @Override
1675
        public UpdateColumnBuilder with_value(Value value) {
1676
            return (UpdateColumnBuilder) super.with_value(value);
1677
        }
1678
        
1679
    }
1680
    
1681
    public class UpdateBuilderBase implements UpdateBuilder {
1682

    
1683
        protected ExpressionBuilder where;
1684
        protected List<UpdateColumnBuilder> columns;
1685
        protected TableNameBuilder table;
1686

    
1687
        public UpdateBuilderBase() {
1688
            this.columns = new ArrayList<>();
1689
        }
1690

    
1691
        @Override
1692
        public void accept(Visitor visitor, VisitorFilter filter) {
1693
            if( filter.accept(this) ) {
1694
                visitor.visit(this);
1695
            }
1696
            if( this.table != null ) {
1697
                this.table.accept(visitor, filter);
1698
            }
1699
            for (UpdateColumnBuilder column : columns) {
1700
                column.accept(visitor, filter);
1701
            }
1702
            if( this.has_where() ) {
1703
                this.where.accept(visitor, filter);
1704
            }
1705
        }
1706

    
1707
        @Override
1708
        public ExpressionBuilder where() {
1709
            if (this.where == null) {
1710
                this.where = createExpressionBuilder();
1711
            }
1712
            return this.where;
1713
        }
1714

    
1715
        @Override
1716
        public TableNameBuilder table() {
1717
            if( table == null ) {
1718
                table = createTableNameBuilder();
1719
            }
1720
            return table;
1721
        }
1722

    
1723
        @Override
1724
        public UpdateColumnBuilder column() {
1725
            UpdateColumnBuilder column = createUpdateColumnBuilder();
1726
            this.columns.add(column);
1727
            return column;
1728
        }
1729
        
1730
        @Override
1731
        public boolean has_where() {
1732
            return this.where != null;
1733
        }
1734

    
1735
        @Override
1736
        public String toString() {
1737
            /*
1738
             * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
1739
             * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
1740
             * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
1741
             * output_expression [ AS output_name ] [, ...] ]
1742
             */
1743
            StringBuilder columnsAndValues = new StringBuilder();
1744

    
1745
            boolean first = true;
1746
            for (UpdateColumnBuilder column : columns) {
1747
                if (first) {
1748
                    first = false;
1749
                } else {
1750
                    columnsAndValues.append(", ");
1751
                }
1752
                columnsAndValues.append(identifier(column.getName()));
1753
                columnsAndValues.append(" = ");
1754
                columnsAndValues.append(column.getValue().toString());
1755
            }
1756
            
1757
            String sql;
1758
            if ( this.has_where() ) {
1759
                sql = MessageFormat.format(
1760
                        config.getString(SQLConfig.UPDATE_table_SET_columnsAndValues_WHERE_expresion),
1761
                        this.table.toString(),
1762
                        columnsAndValues.toString(),
1763
                        this.where.toString()
1764
                );
1765
            } else {
1766
                sql = MessageFormat.format(
1767
                        config.getString(SQLConfig.UPDATE_table_SET_columnsAndValues),
1768
                        this.table.toString(),
1769
                        columnsAndValues.toString()
1770
                );
1771
            }
1772
            return sql;
1773
        }
1774
    }
1775

    
1776
    public class DeleteBuilderBase implements DeleteBuilder {
1777

    
1778
        protected ExpressionBuilder where;
1779
        protected TableNameBuilder table;
1780

    
1781
        public DeleteBuilderBase() {
1782
        }
1783

    
1784
        @Override
1785
        public void accept(Visitor visitor, VisitorFilter filter) {
1786
            if( filter.accept(this) ) {
1787
                visitor.visit(this);
1788
            }
1789
            if( this.table != null ) {
1790
                this.table.accept(visitor, filter);
1791
            }
1792
            if( this.has_where() ) {
1793
                this.where.accept(visitor, filter);
1794
            }
1795
        }
1796

    
1797
        @Override
1798
        public ExpressionBuilder where() {
1799
            if (this.where == null) {
1800
                this.where = createExpressionBuilder();
1801
            }
1802
            return this.where;
1803
        }
1804

    
1805
        @Override
1806
        public TableNameBuilder table() {
1807
            if( table == null ) {
1808
                table = createTableNameBuilder();
1809
            }
1810
            return table;
1811
        }
1812

    
1813
        @Override
1814
        public boolean has_where() {
1815
            return this.where != null;
1816
        }
1817

    
1818
        @Override
1819
        public String toString() {
1820
            /*
1821
             * DELETE FROM table_name
1822
             * WHERE some_column=some_value; 
1823
             */
1824
            String sql;
1825
            if( this.has_where() ) {
1826
                sql = MessageFormat.format(
1827
                        config.getString(SQLConfig.DELETE_FROM_table_WHERE_expresion),
1828
                        this.table.toString(),
1829
                        this.where.toString()
1830
                );
1831
            } else {
1832
                sql = MessageFormat.format(
1833
                        config.getString(SQLConfig.DELETE_FROM_table),
1834
                        this.table.toString()
1835
                );
1836
            }
1837
            return sql;
1838
        }
1839
    }
1840

    
1841
    public class CreateIndexBuilderBase implements CreateIndexBuilder {
1842

    
1843
        protected boolean ifNotExist = false;
1844
        protected boolean isUnique = false;
1845
        protected String indexName;
1846
        protected boolean isSpatial = false;
1847
        protected TableNameBuilder table;
1848
        protected final List<String> columns;
1849
        
1850
        public CreateIndexBuilderBase() {
1851
            this.columns = new ArrayList<>();
1852
        }
1853
        
1854
        @Override
1855
        public CreateIndexBuilder unique() {
1856
            this.isUnique = true;
1857
            return this;
1858
        }
1859

    
1860
        @Override
1861
        public CreateIndexBuilder if_not_exist() {
1862
            this.ifNotExist = true;
1863
            return this;
1864
        }
1865

    
1866
        @Override
1867
        public CreateIndexBuilder name(String name) {
1868
            this.indexName = name;
1869
            return this;
1870
        }
1871

    
1872
        @Override
1873
        public CreateIndexBuilder spatial() {
1874
            this.isSpatial = true;
1875
            return this;
1876
        }
1877

    
1878
        @Override
1879
        public CreateIndexBuilder column(String name) {
1880
            this.columns.add(name);
1881
            return this;
1882
        }
1883

    
1884
        @Override
1885
        public TableNameBuilder table() {
1886
            if( table == null ) {
1887
                table = createTableNameBuilder();
1888
            }
1889
            return table;
1890
        }
1891

    
1892
        @Override
1893
        public void accept(Visitor visitor, VisitorFilter filter) {
1894
            if( filter.accept(this) ) {
1895
                visitor.visit(this);
1896
            }
1897
            if( this.table != null ) {
1898
                this.table.accept(visitor, filter);
1899
            }
1900
        }
1901
        
1902
        @Override
1903
        public List<String> toStrings() {
1904
            StringBuilder builder = new StringBuilder();
1905
            builder.append("CREATE ");
1906
            if( this.isUnique ) {
1907
                builder.append("UNIQUE ");
1908
            }
1909
            builder.append("INDEX ");
1910
            if( this.ifNotExist ) {
1911
                builder.append("IF NOT EXISTS ");
1912
            }
1913
            builder.append(identifier(this.indexName));
1914
            builder.append(" ON ");
1915
            builder.append(this.table.toString());
1916
            if( this.isSpatial ) {
1917
                builder.append(" USING GIST ");
1918
            }
1919
            builder.append(" ( ");
1920
            boolean is_first_column = true;
1921
            for( String column : this.columns) {
1922
                if( is_first_column ) {
1923
                    is_first_column = false;
1924
                } else {
1925
                    builder.append(", ");
1926
                }
1927
                builder.append(column);
1928
            }
1929
            builder.append(" )");
1930
            
1931
            List<String> sqls = new ArrayList<>();
1932
            sqls.add(builder.toString());
1933
            return sqls;
1934
        }
1935

    
1936
    }
1937
    
1938
    public class AlterTableBuilderBase implements AlterTableBuilder {
1939

    
1940
        protected TableNameBuilder table;
1941
        protected List<String> drops;
1942
        protected List<ColumnDescriptor> adds;
1943
        protected List<ColumnDescriptor> alters;
1944
        protected List<Pair<String,String>> renames;
1945

    
1946
        public AlterTableBuilderBase() {
1947
            this.drops = new ArrayList<>();
1948
            this.adds = new ArrayList<>();
1949
            this.alters = new ArrayList<>();
1950
            this.renames = new ArrayList<>();
1951
        }
1952

    
1953
        @Override
1954
        public boolean isEmpty() {
1955
            return this.drops.isEmpty() && 
1956
                this.adds.isEmpty() && 
1957
                this.alters.isEmpty() && 
1958
                this.renames.isEmpty();
1959
        }
1960
        
1961
        @Override
1962
        public void accept(Visitor visitor, VisitorFilter filter) {
1963
            if( filter.accept(this) ) {
1964
                visitor.visit(this);
1965
            }
1966
            if( this.table != null ) {
1967
                this.table.accept(visitor, filter);
1968
            }
1969
        }
1970

    
1971
        @Override
1972
        public TableNameBuilder table() {
1973
            if( table == null ) {
1974
                table = createTableNameBuilder();
1975
            }
1976
            return table;
1977
        }
1978

    
1979
        @Override
1980
        public AlterTableBuilder drop_column(String columnName) {
1981
            this.drops.add(columnName);
1982
            return this;
1983
        }
1984
        
1985
        @Override
1986
        public AlterTableBuilder add_column(FeatureAttributeDescriptor fad) {
1987
            this.adds.add(column(fad).getDescriptor());
1988
            return this;            
1989
        }
1990

    
1991
        @Override
1992
        public AlterTableBuilder add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
1993
            if (isPk || isAutomatic) {
1994
                allowNulls = false;
1995
            }
1996
            this.adds.add(new ColumnDescriptorBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
1997
            return this;
1998
        }
1999

    
2000
        @Override
2001
        public AlterTableBuilder add_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
2002
            if( StringUtils.isEmpty(columnName) ) {
2003
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2004
            }
2005
            this.adds.add(new ColumnDescriptorBase(columnName, type, subtype, proj, isIndexed, allowNulls));
2006
            return this;
2007
        }
2008

    
2009
        @Override
2010
        public AlterTableBuilder add_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
2011
            if( StringUtils.isEmpty(columnName) ) {
2012
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2013
            }
2014
            this.adds.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
2015
            return this;
2016
        }
2017
        
2018
        @Override
2019
        public AlterTableBuilder alter_column(FeatureAttributeDescriptor fad) {
2020
            this.alters.add(column(fad).getDescriptor());
2021
            return this;            
2022
        }
2023
        
2024
        @Override
2025
        public AlterTableBuilder alter_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
2026
            if (isPk || isAutomatic) {
2027
                allowNulls = false;
2028
            }
2029
            this.alters.add(new ColumnDescriptorBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
2030
            return this;
2031
        }
2032

    
2033
        @Override
2034
        public AlterTableBuilder alter_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
2035
            if( StringUtils.isEmpty(columnName) ) {
2036
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2037
            }
2038
            this.alters.add(new ColumnDescriptorBase(columnName, type, subtype, proj, isIndexed, allowNulls));
2039
            return this;
2040
        }
2041

    
2042
        @Override
2043
        public AlterTableBuilder alter_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
2044
            if( StringUtils.isEmpty(columnName) ) {
2045
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2046
            }
2047
            this.alters.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
2048
            return this;
2049
        }
2050

    
2051
        @Override
2052
        public AlterTableBuilder rename_column(String source, String target) {
2053
            this.renames.add(new ImmutablePair(source, target));
2054
            return this;
2055
        }
2056

    
2057
        @Override
2058
        public String toString() {
2059
            StringBuilder builder = new StringBuilder();
2060
            boolean first = true;
2061
            for (String sql : toStrings()) {
2062
                if( StringUtils.isEmpty(sql) ) {
2063
                    continue;
2064
                }
2065
                if (first) {
2066
                    first = false;
2067
                } else {
2068
                    builder.append("; ");
2069
                }
2070
                builder.append(sql);
2071
            }
2072
            return builder.toString();
2073
        }
2074

    
2075
        @Override
2076
        public List<String> toStrings() {
2077
            List<String> sqls = new ArrayList<>();
2078
            if( this.isEmpty() ) {
2079
                return sqls;
2080
            }
2081
            for (String column : drops) {
2082
                StringBuilder builder = new StringBuilder();
2083
                builder.append("ALTER TABLE ");
2084
                builder.append(this.table.toString());
2085
                builder.append(" DROP COLUMN IF EXISTS ");
2086
                builder.append(identifier(column)); 
2087
                sqls.add(builder.toString());
2088
            }
2089
            for (ColumnDescriptor column : adds) {
2090
                StringBuilder builder = new StringBuilder();
2091
                builder.append("ALTER TABLE ");
2092
                builder.append(this.table.toString());
2093
                builder.append(" ADD COLUMN ");
2094
                builder.append(identifier(column.getName())); 
2095
                builder.append(" ");
2096
                if( column.getType() == DataTypes.INT && column.isAutomatic() ) {
2097
                    builder.append(" SERIAL");
2098
                } else {
2099
                    builder.append(
2100
                        sqltype(
2101
                            column.getType(), 
2102
                            column.getPrecision(), 
2103
                            column.getSize(),
2104
                            column.getGeometryType(),
2105
                            column.getGeometrySubtype()
2106
                        )
2107
                    );
2108
                }
2109
                if (column.getDefaultValue() == null) {
2110
                    if (column.allowNulls()) {
2111
                        builder.append(" DEFAULT NULL");
2112
                    }
2113
                } else {
2114
                    builder.append(" DEFAULT '");
2115
                    builder.append(column.getDefaultValue().toString());
2116
                    builder.append("'");
2117
                }
2118
                if (column.allowNulls()) {
2119
                    builder.append(" NULL");
2120
                } else {
2121
                    builder.append(" NOT NULL");
2122
                }
2123
                if (column.isPrimaryKey()) {
2124
                    builder.append(" PRIMARY KEY");
2125
                }
2126
                sqls.add(builder.toString());
2127
            }
2128
            for (ColumnDescriptor column : alters) {
2129
                StringBuilder builder = new StringBuilder();
2130
                builder.append("ALTER TABLE ");
2131
                builder.append(this.table.toString());
2132
                builder.append(" ALTER COLUMN ");
2133
                builder.append(identifier(column.getName())); 
2134
                builder.append(" SET DATA TYPE ");
2135
                if( column.getType() == DataTypes.INT && column.isAutomatic() ) {
2136
                    builder.append(" SERIAL");
2137
                } else {
2138
                    builder.append(
2139
                        sqltype(
2140
                            column.getType(), 
2141
                            column.getPrecision(), 
2142
                            column.getSize(),
2143
                            column.getGeometryType(),
2144
                            column.getGeometrySubtype()
2145
                        )
2146
                    );
2147
                }
2148
                if (column.getDefaultValue() == null) {
2149
                    if (column.allowNulls()) {
2150
                        builder.append(" DEFAULT NULL");
2151
                    } else {
2152
                        builder.append(" DROP DEFAULT");
2153
                    }
2154
                } else {
2155
                    builder.append(" DEFAULT '");
2156
                    builder.append(column.getDefaultValue().toString());
2157
                    builder.append("'");
2158
                }
2159
                sqls.add(builder.toString());
2160
            }
2161
            for (Pair<String,String> pair : renames) {
2162
                StringBuilder builder = new StringBuilder();
2163
                builder.append("ALTER TABLE ");
2164
                builder.append(this.table.toString());
2165
                builder.append(" RENAME COLUMN ");
2166
                builder.append(identifier(pair.getLeft())); 
2167
                builder.append(" TO ");
2168
                builder.append(identifier(pair.getRight())); 
2169
                sqls.add(builder.toString());
2170
            }
2171
            return sqls;
2172
        }
2173

    
2174
    }
2175

    
2176
    public class CreateTableBuilderBase implements CreateTableBuilder {
2177

    
2178
        protected TableNameBuilder table;
2179
        protected List<ColumnDescriptor> columns;
2180

    
2181
        public CreateTableBuilderBase() {
2182
            this.columns = new ArrayList<>();
2183
        }
2184

    
2185
        @Override
2186
        public void accept(Visitor visitor, VisitorFilter filter) {
2187
            if( filter.accept(this) ) {
2188
                visitor.visit(this);
2189
            }
2190
            if( this.table != null ) {
2191
                this.table.accept(visitor, filter);
2192
            }
2193
        }
2194

    
2195
        @Override
2196
        public TableNameBuilder table() {
2197
            if( table == null ) {
2198
                table = createTableNameBuilder();
2199
            }
2200
            return table;
2201
        }
2202

    
2203
        @Override
2204
        public CreateTableBuilderBase add_column(FeatureAttributeDescriptor fad) {
2205
            this.columns.add(column(fad).getDescriptor());
2206
            return this;            
2207
        }
2208

    
2209
        @Override
2210
        public CreateTableBuilderBase add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
2211
            if( StringUtils.isEmpty(columnName) ) {
2212
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2213
            }
2214
            if (isPk || isAutomatic) {
2215
                allowNulls = false;
2216
            }
2217
            this.columns.add(new ColumnDescriptorBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
2218
            return this;
2219
        }
2220

    
2221
        @Override
2222
        public CreateTableBuilder add_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
2223
            if( StringUtils.isEmpty(columnName) ) {
2224
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2225
            }
2226
            this.columns.add(new ColumnDescriptorBase(columnName, type, subtype, proj, isIndexed, allowNulls));
2227
            return this;
2228
        }
2229

    
2230
        @Override
2231
        public CreateTableBuilder add_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
2232
            if( StringUtils.isEmpty(columnName) ) {
2233
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2234
            }
2235
            this.columns.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
2236
            return this;
2237
        }
2238

    
2239
        @Override
2240
        public ColumnDescriptor getColumnDescriptor(String columnName) {
2241
            if( StringUtils.isEmpty(columnName) ) {
2242
                return null;
2243
            }
2244
            for (ColumnDescriptor column : columns) {
2245
                if( columnName.equals(column.getName()) ) {
2246
                    return column;
2247
                }
2248
            }
2249
            return null;
2250
        }
2251
                
2252
        @Override
2253
        public String toString() {
2254
            StringBuilder builder = new StringBuilder();
2255
            boolean first = true;
2256
            for (String sql : toStrings()) {
2257
                if( StringUtils.isEmpty(sql) ) {
2258
                    continue;
2259
                }
2260
                if (first) {
2261
                    first = false;
2262
                } else {
2263
                    builder.append("; ");
2264
                }
2265
                builder.append(sql);
2266
            }
2267
            return builder.toString();
2268
        }
2269

    
2270
        @Override
2271
        public List<String> toStrings() {
2272
            List<String> sqls = new ArrayList<>();
2273
            /**
2274
             * CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE
2275
             * table_name ( { column_name data_type [ DEFAULT default_expr ] [
2276
             * column_constraint [ ... ] ] | table_constraint | LIKE
2277
             * parent_table [ { INCLUDING | EXCLUDING } DEFAULTS ] } [, ... ] )
2278
             * [ INHERITS ( parent_table [, ... ] ) ] [ WITH OIDS | WITHOUT OIDS
2279
             * ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
2280
             *
2281
             * where column_constraint is:
2282
             *
2283
             * [ CONSTRAINT constraint_name ] { NOT NULL | NULL | UNIQUE |
2284
             * PRIMARY KEY | CHECK (expression) | REFERENCES reftable [ (
2285
             * refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON
2286
             * DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE | NOT
2287
             * DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
2288
             *
2289
             * and table_constraint is:
2290
             *
2291
             * [ CONSTRAINT constraint_name ] { UNIQUE ( column_name [, ... ] )
2292
             * | PRIMARY KEY ( column_name [, ... ] ) | CHECK ( expression ) |
2293
             * FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ (
2294
             * refcolumn [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH
2295
             * SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE
2296
             * | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
2297
             */
2298
            StringBuilder builder = new StringBuilder();
2299

    
2300
            builder.append("CREATE TABLE ");
2301
            builder.append(this.table.toString());
2302
            builder.append(" (");
2303
            boolean first = true;
2304
            for (ColumnDescriptor column : columns) {
2305
                if (first) {
2306
                    first = false;
2307
                } else {
2308
                    builder.append(", ");
2309
                }
2310
                builder.append(identifier(column.getName()));
2311
                builder.append(" ");
2312
                if( column.isAutomatic() && column.getType() == DataTypes.INT ) {
2313
                    builder.append("SERIAL");
2314
                } else if( column.isAutomatic() && column.getType() == DataTypes.LONG ) {
2315
                    builder.append("BIGSERIAL");
2316
                } else {
2317
                    builder.append(sqltype(column.getType(), column.getPrecision(), column.getSize()));
2318
                }
2319
                if (column.getDefaultValue() == null) {
2320
                    if (column.allowNulls()) {
2321
                        builder.append(" DEFAULT NULL");
2322
                    }
2323
                } else {
2324
                    builder.append(" DEFAULT '");
2325
                    builder.append(column.getDefaultValue().toString());
2326
                    builder.append("'");
2327
                }
2328
                if (column.allowNulls()) {
2329
                    builder.append(" NULL");
2330
                } else {
2331
                    builder.append(" NOT NULL");
2332
                }
2333
                if (column.isPrimaryKey()) {
2334
                    builder.append(" PRIMARY KEY");
2335
                }
2336
            }
2337
            builder.append(" )");
2338
            sqls.add(builder.toString());
2339
            return sqls;
2340
        }
2341
    }
2342

    
2343
    public class InsertColumnBuilderBase implements InsertColumnBuilder {
2344
        protected Variable name;
2345
        protected Value value;
2346
        
2347
        public InsertColumnBuilderBase() {
2348
        }
2349

    
2350
        @Override
2351
        public void accept(Visitor visitor, VisitorFilter filter) {
2352
            if( filter.accept(this) ) {
2353
                visitor.visit(this);
2354
            }
2355
            if( this.name != null ) {
2356
                this.name.accept(visitor, filter);
2357
            }
2358
            if( this.value != null ) {
2359
                this.value.accept(visitor, filter);
2360
            }
2361
        }
2362

    
2363
        @Override
2364
        public InsertColumnBuilder name(String name) {
2365
            this.name = variable(name);
2366
            return this;
2367
        }
2368

    
2369
        @Override
2370
        public InsertColumnBuilder with_value(Value value) {
2371
            this.value = value;
2372
            return this;
2373
        }
2374
        
2375
        @Override
2376
        public String getName() {
2377
            return this.name.getName();
2378
        }
2379
        
2380
        @Override
2381
        public Value getValue() {
2382
            return this.value;
2383
        }
2384
        
2385
        @Override
2386
        public String toString() {
2387
            return this.value.toString();
2388
        }
2389
    }
2390
    
2391
    public class InsertBuilderBase implements InsertBuilder {
2392

    
2393
        protected List<InsertColumnBuilder> columns;
2394
        protected TableNameBuilder table;
2395

    
2396
        public InsertBuilderBase() {
2397
            this.columns = new ArrayList<>();
2398
        }
2399

    
2400
        @Override
2401
        public void accept(Visitor visitor, VisitorFilter filter) {
2402
            if( filter.accept(this) ) {
2403
                visitor.visit(this);
2404
            }
2405
            if( this.table != null ) {
2406
                this.table.accept(visitor, filter);
2407
            }
2408
            for (InsertColumnBuilder column : columns) {
2409
                column.accept(visitor, filter);
2410
            }
2411
        }
2412

    
2413
        @Override
2414
        public TableNameBuilder table() {
2415
            if( table == null ) {
2416
                table = createTableNameBuilder();
2417
            }
2418
            return table;
2419
        }
2420

    
2421
        @Override
2422
        public InsertColumnBuilder column() {
2423
            InsertColumnBuilder column = createInsertColumnBuilder();
2424
            this.columns.add(column);
2425
            return column;
2426
        }
2427

    
2428
        @Override
2429
        public String toString() {
2430
            /*
2431
             * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
2432
             * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
2433
             * output_expression [ AS output_name ] [, ...] ]
2434
             */
2435
            StringBuilder builderColumns = new StringBuilder();
2436
            StringBuilder builderValues = new StringBuilder();
2437
            
2438
            boolean first = true;
2439
            for (InsertColumnBuilder column : columns) {
2440
                if (first) {
2441
                    first = false;
2442
                } else {
2443
                    builderColumns.append(", ");
2444
                }
2445
                builderColumns.append(identifier(column.getName()));
2446
            }
2447
            first = true;
2448
            for (InsertColumnBuilder column : columns) {
2449
                if (first) {
2450
                    first = false;
2451
                } else {
2452
                    builderValues.append(", ");
2453
                }
2454
                builderValues.append(column.toString());
2455
            }
2456
            
2457
            String sql = MessageFormat.format(
2458
                    config.getString(SQLConfig.INSERT_INTO_table_columns_VALUES_values),
2459
                    this.table.toString(),
2460
                    builderColumns.toString(),
2461
                    builderValues.toString()
2462
            );
2463
            return sql;
2464

    
2465
        }
2466
    }
2467

    
2468
    public class UpdateTableStatisticsBuilderBase implements UpdateTableStatisticsBuilder {
2469

    
2470
        protected TableNameBuilder table;
2471

    
2472
        @Override
2473
        public void accept(Visitor visitor, VisitorFilter filter) {
2474
            if( filter.accept(this) ) {
2475
                visitor.visit(this);
2476
            }
2477
            if( this.table != null ) {
2478
                this.table.accept(visitor, filter);
2479
            }
2480
        }
2481

    
2482
        @Override
2483
        public TableNameBuilder table() {
2484
            if( table == null ) {
2485
                table = createTableNameBuilder();
2486
            }
2487
            return table;
2488
        }
2489

    
2490
        @Override
2491
        public String toString() {
2492
            StringBuilder builder = new StringBuilder();
2493
            boolean first = true;
2494
            for (String sql : toStrings()) {
2495
                if( StringUtils.isEmpty(sql) ) {
2496
                    continue;
2497
                }
2498
                if (first) {
2499
                    first = false;
2500
                } else {
2501
                    builder.append("; ");
2502
                }
2503
                builder.append(sql);
2504
            }
2505
            return builder.toString();
2506
        }
2507

    
2508
        @Override
2509
        public List<String> toStrings() {
2510
            List<String> sqls = new ArrayList<>();
2511
            
2512
            if( config.has_functionality(SQLConfig.UPDATE_TABLE_STATISTICS_table) ) {
2513
                String sql = MessageFormat.format(
2514
                        config.getString(SQLConfig.UPDATE_TABLE_STATISTICS_table),
2515
                        table.toString()
2516
                    );
2517
                if( !StringUtils.isEmpty(sql) ) {
2518
                    sqls.add(sql);
2519
                }
2520
            }
2521
            return sqls;
2522
        }
2523
    }
2524

    
2525

    
2526
    private static class ParametersBase extends ArrayList<Parameter> implements Parameters {
2527

    
2528
        private static final long serialVersionUID = -2188534574151780470L;
2529

    
2530
        public ParametersBase() {
2531
            super();
2532
        }
2533

    
2534
        public ParametersBase(Collection parameters) {
2535
            super(parameters);
2536
        }
2537

    
2538
        @Override
2539
        public Parameter get(String name) {
2540
            if( name == null ) {
2541
                return null;
2542
            }
2543
            for (Parameter param : this) {
2544
                if( param.is_variable() || param.is_geometry_variable() ) {
2545
                    if( name.equalsIgnoreCase(param.getName()) ) {
2546
                        return param;
2547
                    }
2548
                }
2549
            }
2550
            return null;
2551
        }
2552

    
2553
        
2554
        @Override
2555
        public String toString() {
2556
            boolean first = true;
2557
            StringBuilder builder = new StringBuilder();
2558
            builder.append("{ ");
2559
            for (Parameter param : this) {
2560
                if (!first) {
2561
                    builder.append(", ");
2562
                } else {
2563
                    first = false;
2564
                }
2565
                String s;
2566
                Object value = param.getValue();
2567
                if (value == null) {
2568
                    s = "null";
2569
                } else if (value instanceof String) {
2570
                    s = "'" + (String) value + "'";
2571
                } else {
2572
                    s = value.toString();
2573
                }
2574
                switch (param.getType()) {
2575
                    case Constant:
2576
                        builder.append(s);
2577
                        break;
2578
                    case Geometry:
2579
                        builder.append("(Geometry)");
2580
                    case Variable:
2581
                    default:
2582
                        builder.append(param.getName());
2583
                        builder.append(": ");
2584
                        builder.append(s);
2585
                }
2586
            }
2587
            builder.append(" }");
2588
            return builder.toString();
2589
        }
2590
    }
2591

    
2592
    protected Value value;
2593
    protected Config config;
2594
  
2595
    public SQLBuilderBase() {
2596
        
2597
        this.config = new ConfigBase();
2598
        this.value = null;
2599
        
2600
        config.set(SQLConfig.has_spatial_functions, false);
2601
        config.set(SQLConfig.support_schemas, true);
2602
        config.set(SQLConfig.constant_true, "(1=1)");
2603
        config.set(SQLConfig.constant_false, "(1=2)");
2604
        config.set(SQLConfig.quote_for_identifiers, "\"");
2605
        config.set(SQLConfig.quote_for_strings, "'");
2606
        config.set(SQLConfig.geometry_type_support, GeometrySupportType.WKT);
2607
        config.set(SQLConfig.group, "( {0} )");
2608

    
2609
        config.set(SQLConfig.ST_SRID, "ST_SRID({0})");
2610
        config.set(SQLConfig.ST_AsText, "ST_AsText({0})");
2611
        config.set(SQLConfig.ST_AsBinary, "ST_AsBinary({0})");
2612
        config.set(SQLConfig.ST_AsEWKB, "ST_AsEWKB({0})");
2613
        config.set(SQLConfig.ST_Contains, "ST_Contains(({0}), ({1}))");
2614
        config.set(SQLConfig.ST_Crosses, "ST_Crosses(({0}), ({1}))");
2615
        config.set(SQLConfig.ST_Disjoint, "ST_Disjoint(({0}), ({1}))");
2616
        config.set(SQLConfig.ST_Equals, "ST_Equals(({0}), ({1}))");
2617
        config.set(SQLConfig.ST_IsClosed, "ST_IsClosed({0})");
2618
        config.set(SQLConfig.ST_Overlaps, "ST_Overlaps(({0}), ({1}))");
2619
        config.set(SQLConfig.ST_Touches, "ST_Touches(({0}), ({1}))");
2620
        config.set(SQLConfig.ST_Within, "ST_Within(({0}), ({1}))");
2621
        config.set(SQLConfig.ST_Envelope, "ST_Envelope({0})");
2622
        config.set(SQLConfig.ST_Intersects, "ST_Intersects(({0}), ({1}))");
2623
        config.set(SQLConfig.ST_GeomFromText, "ST_GeomFromText({0}, ({1}))");
2624
        config.set(SQLConfig.ST_GeomFromWKB, "ST_GeomFromWKB(({0}), ({1}))");
2625
        config.set(SQLConfig.ST_GeomFromEWKB, "ST_GeomFromEWKB(({0}), ({1}))");
2626

    
2627
        // Por defecto no esta disponible la funcion ST_Simplify
2628
        // El proveedor que la soporte que la defina.
2629
        // config.set(SQLConfig.ST_Simplify, "ST_Simplify(({0}), ({1}))");
2630
        config.remove_functionality(SQLConfig.ST_Simplify);
2631

    
2632
        config.set(SQLConfig.lcase, "LCASE({0})");
2633
        config.set(SQLConfig.ucase, "UCASE({0})");
2634
        config.set(SQLConfig.isNull, "( ({0}) IS NULL )");
2635
        config.set(SQLConfig.notIsNull, "( ({0}) NOT IS NULL )");
2636
        config.set(SQLConfig.operator_not, "( NOT ({0}) )");
2637

    
2638
        config.set(SQLConfig.operator_AND, "{0} AND {1}");
2639
        config.set(SQLConfig.operator_OR, "{0} OR {1}");
2640
        config.set(SQLConfig.operator_EQ, "( ({0}) = ({1}) )");
2641
        config.set(SQLConfig.operator_NE, "( ({0}) <> ({1}) )");
2642
        config.set(SQLConfig.operator_GT, "( ({0}) > ({1}) )");
2643
        config.set(SQLConfig.operator_GE, "( ({0}) >= ({1}) )");
2644
        config.set(SQLConfig.operator_LT, "( ({0}) < ({1}) )");
2645
        config.set(SQLConfig.operator_LE, "( ({0}) <= ({1}) )");
2646
        config.set(SQLConfig.operator_LIKE, "( ({0}) LIKE ({1}) )");
2647
        config.set(SQLConfig.operator_ILIKE, "( ({0}) ILIKE ({1}) )");
2648

    
2649
        config.set(SQLConfig.operator_add, "{0} + {1}");
2650
        config.set(SQLConfig.operator_subst, "{0} - {1}");
2651
        config.set(SQLConfig.operator_mult, "{0} * {1}");
2652
        config.set(SQLConfig.operator_div, "{0} / {1}");
2653
        config.set(SQLConfig.operator_concat, "{0} || {1}");
2654

    
2655

    
2656
        config.set(SQLConfig.default_schema, "public");
2657
        config.set(SQLConfig.allowAutomaticValues, true);
2658
        
2659
        config.set(SQLConfig.ST_ExtentAggregate, "ST_Extent({0})");
2660
        config.set(SQLConfig.ST_UnionAggregate, "ST_Union({0})");
2661
        config.set(SQLConfig.count, "COUNT({0})");
2662
        config.set(SQLConfig.count_distinct, "COUNT(DISTINCT {0})");
2663

    
2664
        config.set(SQLConfig.type_boolean, "BOOLEAN");
2665
        config.set(SQLConfig.type_byte, "TINYINT");
2666
        config.set(SQLConfig.type_bytearray, "BYTEA");
2667
        config.set(SQLConfig.type_geometry, "TEXT");
2668
        config.set(SQLConfig.type_char, "CHARACTER(1)");
2669
        config.set(SQLConfig.type_date, "DATE");
2670
        config.set(SQLConfig.type_double, "DOUBLE PRECISION"); //float con 53 bits de mantisa, float(54)
2671
        config.set(SQLConfig.type_numeric_p, "NUMERIC({0})");
2672
        config.set(SQLConfig.type_numeric_ps, "NUMERIC({0},{1})");
2673
        config.set(SQLConfig.type_bigdecimal, "NUMERIC({0},{1})");
2674
        config.set(SQLConfig.type_float, "REAL"); //float con 24 bits de mantisa, float(24)
2675
        config.set(SQLConfig.type_int, "INT");
2676
        config.set(SQLConfig.type_long, "BIGINT");
2677
        config.set(SQLConfig.type_string, "TEXT");
2678
        config.set(SQLConfig.type_string_p, "VARCHAR({0})");
2679
        config.set(SQLConfig.type_time, "TIME");
2680
        config.set(SQLConfig.type_timestamp, "TIMESTAMP");
2681
        config.set(SQLConfig.type_version, "VARCHAR(30)");
2682
        config.set(SQLConfig.type_URI, "TEXT");
2683
        config.set(SQLConfig.type_URL, "TEXT");
2684
        config.set(SQLConfig.type_FILE, "TEXT");
2685
        config.set(SQLConfig.type_FOLDER, "TEXT");
2686

    
2687
        config.set(SQLConfig.DELETE_FROM_table_WHERE_expresion, "DELETE FROM {0} WHERE {1}");
2688
        config.set(SQLConfig.DELETE_FROM_table, "DELETE FROM {0}");
2689
        config.set(SQLConfig.INSERT_INTO_table_columns_VALUES_values, "INSERT INTO {0} ( {1} ) VALUES ( {2} )");
2690
        config.set(SQLConfig.UPDATE_TABLE_STATISTICS_table, "VACUUM ANALYZE {0}");
2691
        config.set(SQLConfig.DROP_TABLE_table, "DROP TABLE {0}");
2692
        config.set(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table, "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_schema = {0} AND f_table_name = {1}");
2693
        config.set(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table, "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_name = {0}");
2694
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues_WHERE_expresion, "UPDATE {0} SET {1} WHERE {2}");
2695
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues, "UPDATE {0} SET {1}");
2696
        config.set(SQLConfig.GRANT_privileges_ON_table_TO_role, "GRANT {0} ON {1} TO {2}");        
2697
    }
2698
   
2699
    @Override
2700
    public ExpressionBuilder createExpressionBuilder() {
2701
        return ExpressionEvaluatorLocator.getManager().createExpressionBuilder();
2702
    }
2703

    
2704
    @Override
2705
    public Config getConfig() {
2706
        return this.config;
2707
    }
2708

    
2709
    @Override
2710
    public Value getValue() {
2711
        return this.value;
2712
    }
2713

    
2714
    @Override
2715
    public ExpressionBuilder setValue(Value value) {
2716
        this.value = value;
2717
        return this;
2718
    }
2719

    
2720
    @Override
2721
    public boolean has_spatial_functions() {
2722
        return this.config.getBoolean(Config.has_spatial_functions);
2723
    }
2724

    
2725
    @Override
2726
    public GeometrySupportType geometry_support_type() {
2727
        return (GeometrySupportType) this.config.get(Config.geometry_type_support);
2728
    }
2729

    
2730
    @Override
2731
    public String string(String s) {
2732
        String quote = this.config.getString(Config.quote_for_strings);
2733
//        No se porque no esta disponible wrapIfMissing
2734
//        return StringUtils.wrapIfMissing(s,quote);
2735
        if (s.startsWith(quote)) {
2736
            return s;
2737
        }
2738
        return quote + s + quote;
2739
    }
2740

    
2741
    @Override
2742
    public String identifier(String id) {
2743
        String quote = this.config.getString(Config.quote_for_identifiers);
2744
//        No se porque no esta disponible wrapIfMissing
2745
//        return StringUtils.wrapIfMissing(id,quote);
2746
        if (id.startsWith(quote)) {
2747
            return id;
2748
        }
2749
        return quote + id + quote;
2750
    }
2751

    
2752
    @Override
2753
    public String bytearray(byte[] data) {
2754
        return bytearray_0x(data);
2755
    }
2756
    
2757
    public String bytearray_hex(byte[] data) {
2758
        StringBuilder builder = new StringBuilder();
2759
        for (byte abyte : data) {
2760
            int v = abyte & 0xff;
2761
            builder.append(String.format("%02x", v));
2762
        }
2763
        return builder.toString();
2764
    }
2765

    
2766
    public String bytearray_0x(byte[] data) {
2767
        return "0x" + bytearray_hex(data);
2768
    }
2769

    
2770
    public String bytearray_x(byte[] data) {
2771
        return "x'" + bytearray_hex(data) + "'";
2772
    }
2773
    
2774
    @Override
2775
    public Object getSRSId(IProjection projection) {
2776
        String abrev = projection.getAbrev();
2777
        return abrev.split(":")[1].trim();
2778
    }
2779

    
2780
    @Override
2781
    public Constant srs(IProjection projection) {
2782
        return constant(getSRSId(projection));
2783
    }
2784

    
2785
    @Override
2786
    public Variable variable(String name) {
2787
        return new VariableBase(name);
2788
    }
2789

    
2790
    @Override
2791
    public Column column(String name) {
2792
        return new VariableBase(name);
2793
    }
2794
    
2795
    @Override
2796
    public Parameter parameter(String name) {
2797
        Parameters parameters = this.getParameters();
2798
        Parameter parameter = parameters.get(name);
2799
        if( parameter != null ) {
2800
            return parameter;
2801
        }
2802
        parameter = this.parameter();
2803
        parameter.name(name);
2804
        return parameter;
2805
    }
2806
    
2807
    @Override
2808
    public Parameter parameter() {
2809
        return new ParameterBase();
2810
    }
2811
    
2812
    @Override
2813
    public Constant constant(Object value) {
2814
        return new ConstantBase(value);
2815
    }
2816

    
2817
    @Override
2818
    public Group group(Value value) {
2819
        return new GroupBase(value);
2820
    }
2821

    
2822
    @Override
2823
    public GeometryValue geometry(Geometry geom, IProjection projection) {
2824
        return new GeometryValueBase(geom, projection);
2825
    }
2826

    
2827
    @Override
2828
    public GeometryValue geometry(Geometry geom) {
2829
        if( geom.getProjection()==null ) {
2830
            throw new IllegalArgumentException("The geometry does not have an associated projection. Use 'geometry(Geometry, IProjection)'.");
2831
        }
2832
        return new GeometryValueBase(geom, geom.getProjection());
2833
    }
2834

    
2835
    @Override
2836
    public GeometryValue envelope(Envelope envelope, IProjection projection) {
2837
        return new GeometryValueBase(envelope.getGeometry(), projection);
2838
    }
2839

    
2840
    @Override
2841
    public GeometryValue envelope(Envelope envelope) {
2842
        if( envelope.getProjection()==null ) {
2843
            throw new IllegalArgumentException("The envelope does not have an associated projection. Use 'envelope(Geometry, IProjection)'.");
2844
        }
2845
        return new GeometryValueBase(envelope.getGeometry(), envelope.getProjection());
2846
    }
2847

    
2848
    @Override
2849
    public Custom custom(Object value) {
2850
        return new CustomBase(value);
2851
    }
2852

    
2853
    public Function builtin_function(String name, String format, Value... values) {
2854
        FunctionBase func = new FunctionBase(name, format);
2855
        for (Value value : values) {
2856
            func.parameter(value);
2857
        }
2858
        return func;
2859
    }
2860

    
2861
    public Function function(String name, Value... values) {
2862
        FunctionBase func = new FunctionBase(name);
2863
        for (Value theValue : values) {
2864
            func.parameter(theValue);
2865
        }
2866
        return func;
2867
    }    
2868
    
2869
    public BinaryOperator binaryOperator(String name, String format, Value leftOperand, Value rightOperand) {
2870
        BinaryOperator operator = new BinaryOperatorBase(name, format);
2871
        operator.setLeft(leftOperand);
2872
        operator.setRight(rightOperand);
2873
        return operator;
2874
    }
2875

    
2876
    @Override
2877
    public List<Variable> getVariables() {
2878
        final Set<Variable> vars = new HashSet<>();
2879
        this.accept(new Visitor() {
2880
            @Override
2881
            public void visit(Visitable value) {
2882
                vars.add((Variable) value);
2883
            }
2884
        }, new ClassVisitorFilter(Variable.class));
2885
        List<Variable> lvars = new ArrayList<>(vars);
2886
        Collections.sort(lvars);
2887
        return lvars;
2888
    }
2889

    
2890
    @Override
2891
    public Parameters getParameters() {
2892
        final Parameters params = new ParametersBase();
2893
        this.accept(new Visitor() {
2894
            @Override
2895
            public void visit(Visitable value) {
2896
                params.add((Parameter) value);
2897
            }
2898
        }, new ClassVisitorFilter(Parameter.class));
2899
        return params;
2900
    }
2901

    
2902
    @Override
2903
    public Function getAsGeometry(Value value) {
2904
        return builtin_function("ST_AsBinary", config.getString(Config.ST_AsBinary), value);
2905
    }
2906

    
2907
    @Override
2908
    public ExpressionBuilder set(Value value) {
2909
        this.value = value;
2910
        return this;
2911
    }
2912

    
2913
    @Override
2914
    public ExpressionBuilder and(Value value) {
2915
        if (this.value == null) {
2916
            return this.set(value);
2917
        }
2918
        BinaryOperator operator = binaryOperator("AND", config.getString(Config.operator_AND), this.value, value);
2919
        this.value = operator;
2920
        return this;
2921
    }
2922

    
2923
    @Override
2924
    public ExpressionBuilder or(Value value) {
2925
        if (this.value == null) {
2926
            return this.set(value);
2927
        }
2928
        BinaryOperator operator = binaryOperator("OR", config.getString(Config.operator_OR), this.value, value);
2929
        this.value = operator;
2930
        return this;
2931
    }
2932

    
2933
    @Override
2934
    public Function ST_Intersects(Value geom1, Value geom2) {
2935
        return builtin_function("ST_Intersects", config.getString(Config.ST_Intersects), geom1, geom2);
2936
    }
2937

    
2938
    @Override
2939
    public Function ST_SRID(Value geom) {
2940
        return builtin_function("ST_SRID", config.getString(Config.ST_SRID), geom);
2941
    }
2942

    
2943
    @Override
2944
    public Function ST_Envelope(Value geom) {
2945
        return builtin_function("ST_Envelope", config.getString(Config.ST_Envelope), geom);
2946
    }
2947

    
2948
    @Override
2949
    public Function ST_AsText(Value geom) {
2950
        return builtin_function("ST_AsText", config.getString(Config.ST_AsText), geom);
2951
    }
2952

    
2953
    @Override
2954
    public Function ST_AsBinary(Value geom) {
2955
        return builtin_function("ST_AsBinary", config.getString(Config.ST_AsBinary), geom);
2956
    }
2957

    
2958
    @Override
2959
    public Function ST_AsEWKB(Value geom) {
2960
        return builtin_function("ST_AsEWKB", config.getString(Config.ST_AsEWKB), geom);
2961
    }
2962

    
2963
    @Override
2964
    public Function ST_GeomFromText(Value geom, Value crs) {
2965
        return builtin_function("ST_GeomFromText", config.getString(Config.ST_GeomFromText), geom, crs);
2966
    }
2967

    
2968
    @Override
2969
    public Function ST_GeomFromWKB(Value geom, Value crs) {
2970
        return builtin_function("ST_GeomFromWKB", config.getString(Config.ST_GeomFromWKB), geom, crs);
2971
    }
2972

    
2973
    @Override
2974
    public Function ST_GeomFromEWKB(Value geom, Value crs) {
2975
        return builtin_function("ST_GeomFromEWKB", config.getString(Config.ST_GeomFromEWKB), geom, crs);
2976
    }
2977

    
2978
    @Override
2979
    public Function ST_Simplify(Value geom, Value tolerance) {
2980
        return builtin_function("ST_Simplify", config.getString(Config.ST_Simplify), tolerance);
2981
    }
2982

    
2983
    @Override
2984
    public Function ST_Disjoint(Value geom1, Value geom2) {
2985
        return builtin_function("ST_Disjoint", config.getString(Config.ST_Disjoint), geom1, geom2);
2986
    }
2987

    
2988
    @Override
2989
    public Function ST_Contains(Value geom1, Value geom2) {
2990
        return builtin_function("ST_Contains", config.getString(Config.ST_Contains), geom1, geom2);
2991
    }
2992

    
2993
    @Override
2994
    public Function ST_Equals(Value geom1, Value geom2) {
2995
        return builtin_function("ST_Equals", config.getString(Config.ST_Equals), geom1, geom2);
2996
    }
2997

    
2998
    @Override
2999
    public Function ST_Crosses(Value geom1, Value geom2) {
3000
        return builtin_function("ST_Crosses", config.getString(Config.ST_Crosses), geom1, geom2);
3001
    }
3002

    
3003
    @Override
3004
    public Function ST_IsClosed(Value geom) {
3005
        return builtin_function("ST_IsClosed", config.getString(Config.ST_IsClosed), geom);
3006
    }
3007

    
3008
    @Override
3009
    public Function ST_Overlaps(Value geom1, Value geom2) {
3010
        return builtin_function("ST_Overlaps", config.getString(Config.ST_Overlaps), geom1, geom2);
3011
    }
3012

    
3013
    @Override
3014
    public Function ST_Touches(Value geom1, Value geom2) {
3015
        return builtin_function("ST_Touches", config.getString(Config.ST_Touches), geom1, geom2);
3016
    }
3017

    
3018
    @Override
3019
    public Function ST_Within(Value geom1, Value geom2) {
3020
        return builtin_function("ST_Within", config.getString(Config.ST_Within), geom1, geom2);
3021
    }
3022

    
3023
    @Override
3024
    public Function isNull(Value value) {
3025
        return builtin_function("IS NULL", config.getString(Config.isNull), value);
3026
    }
3027

    
3028
    @Override
3029
    public Function notIsNull(Value value) {
3030
        return builtin_function("NOT IS NULL", config.getString(Config.notIsNull), value);
3031
    }
3032

    
3033
    @Override
3034
    public Function not(Value value) {
3035
        return builtin_function("NOT", config.getString(Config.operator_not), value);
3036
    }
3037

    
3038
    @Override
3039
    public Function lcase(Value s) {
3040
        return builtin_function("LCASE", config.getString(Config.lcase), s);
3041
    }
3042

    
3043
    @Override
3044
    public Function ucase(Value s) {
3045
        return builtin_function("UCASE", config.getString(Config.ucase), s);
3046
    }
3047

    
3048
    @Override
3049
    public BinaryOperator and(Value leftOperand, Value rightOperand) {
3050
        return binaryOperator("AND", config.getString(Config.operator_AND), leftOperand, rightOperand);
3051
    }
3052

    
3053
    @Override
3054
    public BinaryOperator or(Value leftOperand, Value rightOperand) {
3055
        return binaryOperator("OR", config.getString(Config.operator_OR), leftOperand, rightOperand);
3056
    }
3057

    
3058
    @Override
3059
    public BinaryOperator eq(Value leftOperand, Value rightOperand) {
3060
        return binaryOperator("=", config.getString(Config.operator_EQ), leftOperand, rightOperand);
3061
    }
3062

    
3063
    @Override
3064
    public BinaryOperator ne(Value leftOperand, Value rightOperand) {
3065
        return binaryOperator("<>", config.getString(Config.operator_NE), leftOperand, rightOperand);
3066
    }
3067

    
3068
    @Override
3069
    public BinaryOperator gt(Value op1, Value op2) {
3070
        return binaryOperator(">", config.getString(Config.operator_GT), op1, op2);
3071
    }
3072

    
3073
    @Override
3074
    public BinaryOperator ge(Value op1, Value op2) {
3075
        return binaryOperator(">=", config.getString(Config.operator_GE), op1, op2);
3076
    }
3077

    
3078
    @Override
3079
    public BinaryOperator lt(Value op1, Value op2) {
3080
        return binaryOperator("<", config.getString(Config.operator_LT), op1, op2);
3081
    }
3082

    
3083
    @Override
3084
    public BinaryOperator le(Value op1, Value op2) {
3085
        return binaryOperator("<=", config.getString(Config.operator_LE), op1, op2);
3086
    }
3087

    
3088
    @Override
3089
    public BinaryOperator like(Value op1, Value op2) {
3090
        return binaryOperator("LIKE", config.getString(Config.operator_LIKE), op1, op2);
3091
    }
3092

    
3093
    @Override
3094
    public BinaryOperator ilike(Value op1, Value op2) {
3095
        return binaryOperator("ILIKE", config.getString(Config.operator_ILIKE), op1, op2);
3096
    }
3097

    
3098
    @Override
3099
    public BinaryOperator add(Value op1, Value op2) {
3100
        return binaryOperator("ADD", config.getString(Config.operator_add), op1, op2);
3101
    }
3102

    
3103
    @Override
3104
    public BinaryOperator subst(Value op1, Value op2) {
3105
        return binaryOperator("SUBST", config.getString(Config.operator_subst), op1, op2);
3106
    }
3107

    
3108
    @Override
3109
    public BinaryOperator mult(Value op1, Value op2) {
3110
        return binaryOperator("MULT", config.getString(Config.operator_mult), op1, op2);
3111
    }
3112

    
3113
    @Override
3114
    public BinaryOperator div(Value op1, Value op2) {
3115
        return binaryOperator("DIV", config.getString(Config.operator_div), op1, op2);
3116
    }
3117

    
3118
    @Override
3119
    public BinaryOperator concat(Value op1, Value op2) {
3120
        return binaryOperator("CONCAT", config.getString(Config.operator_concat), op1, op2);
3121
    }
3122
 
3123
    @Override
3124
    public String default_schema() {
3125
        return config.getString(SQLConfig.default_schema);
3126
    }
3127

    
3128
    @Override
3129
    public boolean supportSchemas() {
3130
        return config.getBoolean(Config.support_schemas);
3131
    }
3132
    
3133
    @Override
3134
    @Deprecated
3135
    public String sqltype(int type, int p, int s) {
3136
        return this.sqltype(type, p, s, Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.UNKNOWN);
3137
    }
3138

    
3139
    @Override
3140
    public String sqltype(int type, int p, int s, int geomType, int geomSubtype) {
3141
        switch (type) {
3142
            case DataTypes.BOOLEAN:
3143
                return config.getString(SQLConfig.type_boolean);
3144
            case DataTypes.BYTE:
3145
                return config.getString(SQLConfig.type_byte);
3146
            case DataTypes.BYTEARRAY:
3147
                return config.getString(SQLConfig.type_bytearray);
3148
            case DataTypes.GEOMETRY:
3149
                return config.getString(SQLConfig.type_geometry);
3150
            case DataTypes.CHAR:
3151
                return config.getString(SQLConfig.type_char);
3152
            case DataTypes.DATE:
3153
                return config.getString(SQLConfig.type_date);
3154
            case DataTypes.DOUBLE:
3155
                  // FIXME: Si cargamos la capa "country" al exportarla a
3156
                  // SQLServer falla por:
3157
                  //  Error de desbordamiento aritm?tico al convertir float al tipo de datos numeric.
3158
                  // Al parecer la capa declara la columna sqkm_ctry como Numeric(12,6) y para 
3159
                  // Algeria intenta asignarle un valor de 2320972.0 y falla.
3160
                  // Habria que repasar el proveedor de shape.
3161
                
3162
//                if (p > 1) {
3163
//                    if (s < 0) {
3164
//                        return MessageFormat.format(config.getString(SQLConfig.type_numeric_p), p);
3165
//                    }
3166
//                    return MessageFormat.format(config.getString(SQLConfig.type_numeric_ps), p,s);
3167
//                }
3168
                return MessageFormat.format(config.getString(SQLConfig.type_double),p,s);
3169
            case DataTypes.BIGDECIMAL:
3170
                if (p < 1) {
3171
                    p = 20;
3172
                }
3173
                if (s < 0) {
3174
                    s = 10;
3175
                }
3176
                return MessageFormat.format(config.getString(SQLConfig.type_bigdecimal), p,s);
3177
            case DataTypes.FLOAT:
3178
                return MessageFormat.format(config.getString(SQLConfig.type_float), p,s);
3179
            case DataTypes.INT:
3180
                return MessageFormat.format(config.getString(SQLConfig.type_int), p,s);
3181
            case DataTypes.LONG:
3182
                return MessageFormat.format(config.getString(SQLConfig.type_long), p,s);
3183
            case DataTypes.STRING:
3184
                if (p < 0) {
3185
                    return config.getString(SQLConfig.type_string);
3186
                } else if (p < 4096) {
3187
                    return MessageFormat.format(config.getString(SQLConfig.type_string_p),p);
3188
                }
3189
                return config.getString(SQLConfig.type_string);
3190
            case DataTypes.TIME:
3191
                return config.getString(SQLConfig.type_time);
3192
            case DataTypes.TIMESTAMP:
3193
                return config.getString(SQLConfig.type_timestamp);
3194
            case DataTypes.VERSION:
3195
                return config.getString(SQLConfig.type_version);
3196
            case DataTypes.URI:
3197
                return config.getString(SQLConfig.type_URI);
3198
            case DataTypes.URL:
3199
                return config.getString(SQLConfig.type_URL);
3200
            case DataTypes.FILE:
3201
                return config.getString(SQLConfig.type_FILE);
3202
            case DataTypes.FOLDER:
3203
                return config.getString(SQLConfig.type_FOLDER);
3204
            default:
3205
                return null;
3206
        }
3207
    }
3208

    
3209
    private static Map<Pair<Integer,Integer>,String> sqlgeometrytypes = null;
3210
    
3211
    @Override
3212
    public Object sqlgeometrytype(int type, int subtype) {
3213
        // Devuelve un Object por que algunos gestores de BBDD utilizan
3214
        // identificadores numericos para el tipo y otros strings.
3215
        // Por defecto vamos a devolver strings.
3216
        if( sqlgeometrytypes==null ) {
3217
            sqlgeometrytypes = new HashMap<>();
3218
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM2D), "POINT");
3219
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM3D), "POINTZ");
3220
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM2DM), "POINTM");
3221
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM3DM), "POINTZM");
3222

    
3223
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM2D), "LINESTRING");
3224
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM3D), "LINESTRINGZ");
3225
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM2DM), "LINESTRINGM");
3226
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM3DM), "LINESTRINGZM");
3227

    
3228
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM2D), "POLYGON");
3229
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM3D), "POLYGONZ");
3230
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM2DM), "POLYGONM");
3231
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM3DM), "POLYGONZM");
3232

    
3233
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM2D), "MULTIPOINT");
3234
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM3D), "MULTIPOINTZ");
3235
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM2DM), "MULTIPOINTM");
3236
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM3DM), "MULTIPOINTZM");
3237

    
3238
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM2D), "MULTILINESTRING");
3239
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM3D), "MULTILINESTRINGZ");
3240
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM2DM), "MULTILINESTRINGM");
3241
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM3DM), "MULTILINESTRINGZM");
3242

    
3243
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM2D), "MULTILINESTRING");
3244
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM3D), "MULTILINESTRINGZ");
3245
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM2DM), "MULTILINESTRINGM");
3246
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM3DM), "MULTILINESTRINGZM");
3247

    
3248
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM2D), "MULTIPOLYGON");
3249
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM3D), "MULTIPOLYGONZ");
3250
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM2DM), "MULTIPOLYGONM");
3251
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM3DM), "MULTIPOLYGONZM");
3252

    
3253
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM2D), "MULTIPOLYGON");
3254
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM3D), "MULTIPOLYGONZ");
3255
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM2DM), "MULTIPOLYGONM");
3256
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM3DM), "MULTIPOLYGONZM");
3257

    
3258
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2D), "GEOMETRY");
3259
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3D), "GEOMETRYZ");
3260
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2DM), "GEOMETRYM");
3261
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3DM), "GEOMETRYZM");
3262
        }
3263
        return sqlgeometrytypes.get(new ImmutablePair<>(type,subtype));
3264
    }
3265

    
3266
    @Override
3267
    public Object sqlgeometrydimension(int type, int subtype) {
3268
        // Devuelve un Object por que algunos gestortes de BBDD utilizan
3269
        // identificadores numericos para las dimensiones y otros strings.
3270
        // Por defecto vamos a devolver enteros.
3271
        switch(subtype) {
3272
            case Geometry.SUBTYPES.GEOM3D:
3273
                return 3;
3274
            case Geometry.SUBTYPES.GEOM2DM:
3275
                return 3;
3276
            case Geometry.SUBTYPES.GEOM3DM:
3277
                return 4;
3278
            case Geometry.SUBTYPES.GEOM2D:
3279
            default:
3280
                return 2;
3281
        }
3282
    }
3283
    
3284
    protected TableNameBuilder createTableNameBuilder() {
3285
        return new TableNameBuilderBase();
3286
    }
3287
    
3288
    protected SelectColumnBuilder createSelectColumnBuilder() {
3289
        return new SelectColumnBuilderBase();
3290
    }
3291
    
3292
    protected UpdateColumnBuilder createUpdateColumnBuilder() {
3293
        return new UpdateColumnBuilderBase();
3294
    }
3295
    
3296
    protected InsertColumnBuilder createInsertColumnBuilder() {
3297
        return new InsertColumnBuilderBase();
3298
    }
3299
    
3300
    protected OrderByBuilder createOrderByBuilder() {
3301
        return new OrderByBuilderBase();
3302
    }
3303

    
3304
    protected FromBuilder createFromBuilder() {
3305
        return new FromBuilderBase();
3306
    }
3307

    
3308
    protected SelectBuilder createSelectBuilder() {
3309
        return new SelectBuilderBase();
3310
    }
3311

    
3312
    protected UpdateBuilder createUpdateBuilder() {
3313
        return new UpdateBuilderBase();
3314
    }
3315

    
3316
    protected DeleteBuilder createDeleteBuilder() {
3317
        return new DeleteBuilderBase();
3318
    }
3319

    
3320
    protected GrantBuilder createGrantBuilder() {
3321
        return new GrantBuilderBase();
3322
    }
3323

    
3324
    protected GrantRoleBuilder createGrantRoleBuilder(TableNameBuilder table, String role) {
3325
        return new GrantRoleBuilderBase(table, role);
3326
    }
3327
    
3328
    protected DropTableBuilder createDropTableBuilder() {
3329
        return new DropTableBuilderBase();
3330
    }
3331

    
3332
    protected CreateTableBuilder createCreateTableBuilder() {
3333
        return new CreateTableBuilderBase();
3334
    }
3335

    
3336
    protected AlterTableBuilder createAlterTableBuilder() {
3337
        return new AlterTableBuilderBase();
3338
    }
3339

    
3340
    protected InsertBuilder createInsertBuilder() {
3341
        return new InsertBuilderBase();
3342
    }
3343

    
3344
    protected UpdateTableStatisticsBuilder createUpdateTableStatisticsBuilder() {
3345
        return new UpdateTableStatisticsBuilderBase();
3346
    }
3347

    
3348
    protected CreateIndexBuilder createCreateIndexBuilder() {
3349
        return new CreateIndexBuilderBase();
3350
    }
3351
    
3352
    @Override
3353
    public SelectBuilder select() {
3354
        if (this.select == null) {
3355
            this.select = this.createSelectBuilder();
3356
        }
3357
        return this.select;
3358
    }
3359

    
3360
    @Override
3361
    public UpdateBuilder update() {
3362
        if (this.update == null) {
3363
            this.update = this.createUpdateBuilder();
3364
        }
3365
        return this.update;
3366
    }
3367

    
3368
    @Override
3369
    public UpdateTableStatisticsBuilder update_table_statistics() {
3370
        if (this.update_table_statistics == null) {
3371
            this.update_table_statistics = this.createUpdateTableStatisticsBuilder();
3372
        }
3373
        return this.update_table_statistics;
3374
    }
3375

    
3376
    @Override
3377
    public DropTableBuilder drop_table() {
3378
        if (this.drop_table == null) {
3379
            this.drop_table = this.createDropTableBuilder();
3380
        }
3381
        return this.drop_table;
3382
    }
3383

    
3384
    @Override
3385
    public CreateIndexBuilder create_index() {
3386
        if (this.create_index == null) {
3387
            this.create_index = this.createCreateIndexBuilder();
3388
        }
3389
        return this.create_index;
3390
    }
3391

    
3392
    
3393
    @Override
3394
    public DeleteBuilder delete() {
3395
        if (this.delete == null) {
3396
            this.delete = this.createDeleteBuilder();
3397
        }
3398
        return this.delete;
3399
    }
3400

    
3401
    @Override
3402
    public InsertBuilder insert() {
3403
        if (this.insert == null) {
3404
            this.insert = this.createInsertBuilder();
3405
        }
3406
        return this.insert;
3407
    }
3408

    
3409
    @Override
3410
    public AlterTableBuilder alter_table() {
3411
        if (this.alter_table == null) {
3412
            this.alter_table = this.createAlterTableBuilder();
3413
        }
3414
        return this.alter_table;
3415
    }
3416

    
3417
    @Override
3418
    public CreateTableBuilder create_table() {
3419
        if (this.create_table == null) {
3420
            this.create_table = this.createCreateTableBuilder();
3421
        }
3422
        return this.create_table;
3423
    }
3424

    
3425
    @Override
3426
    public GrantBuilder grant() {
3427
        if (this.grant == null) {
3428
            this.grant = this.createGrantBuilder();
3429
        }
3430
        return this.grant;
3431
    }
3432

    
3433
    @Override
3434
    public void accept(Visitor visitor, VisitorFilter filter) {
3435
        if (this.select != null) {
3436
            this.select.accept(visitor, filter);
3437
        }
3438
        if (this.update != null) {
3439
            this.update.accept(visitor, filter);
3440
        }
3441
        if (this.insert != null) {
3442
            this.insert.accept(visitor, filter);
3443
        }
3444
        if (this.delete != null) {
3445
            this.delete.accept(visitor, filter);
3446
        }
3447
        if (this.alter_table != null) {
3448
            this.alter_table.accept(visitor, filter);
3449
        }
3450
        if (this.create_table != null) {
3451
            this.create_table.accept(visitor, filter);
3452
        }
3453
        if (this.drop_table != null) {
3454
            this.drop_table.accept(visitor, filter);
3455
        }
3456
//        if( this.value == null) {
3457
//            return;
3458
//        }
3459
//        this.value.accept(visitor, filter);
3460
    }
3461

    
3462
    
3463
    @Override
3464
    public String toString() {
3465
        if (this.select != null) {
3466
            return this.select.toString();
3467
        }
3468
        if (this.update != null) {
3469
            return this.update.toString();
3470
        }
3471
        if (this.insert != null) {
3472
            return this.insert.toString();
3473
        }
3474
        if (this.delete != null) {
3475
            return this.delete.toString();
3476
        }
3477
        if (this.alter_table != null) {
3478
            return this.alter_table.toString();
3479
        }
3480
        if (this.create_table != null) {
3481
            return this.create_table.toString();
3482
        }
3483
        if (this.drop_table != null) {
3484
            return this.drop_table.toString();
3485
        }
3486
        if (this.update_table_statistics != null) {
3487
            return this.update_table_statistics.toString();
3488
        }
3489
        if ( this.value != null ) {
3490
            return this.value.toString();
3491
        }
3492
        return ""; 
3493
    }
3494

    
3495
    @Override
3496
    public Function ST_UnionAggregate(Value geom) {
3497
        return builtin_function("ST_UnionAggregate", config.getString(SQLConfig.ST_UnionAggregate), geom);
3498
    }
3499

    
3500
    @Override
3501
    public Function ST_ExtentAggregate(Value geom) {
3502
        return builtin_function("ST_ExtentAggregate", config.getString(SQLConfig.ST_ExtentAggregate), geom);
3503
    }
3504

    
3505
    @Override
3506
    public CountBuilder count() {
3507
        return new CountBuilderBase();
3508
    }
3509

    
3510
    @Override
3511
    public Column column(FeatureAttributeDescriptor fad) {
3512
        ColumnDescriptorBase descriptor;
3513
        if( fad.getType()==org.gvsig.fmap.geom.DataTypes.GEOMETRY ) {
3514
            descriptor = new ColumnDescriptorBase(
3515
                    fad.getName(),
3516
                    fad.getGeomType().getType(),
3517
                    fad.getGeomType().getSubType(),
3518
                    fad.getSRS(),
3519
                    fad.isIndexed(),
3520
                    fad.allowNull()
3521
            );
3522
        } else {
3523
            descriptor = new ColumnDescriptorBase(
3524
                    fad.getName(),
3525
                    fad.getType(),
3526
                    fad.getSize(),
3527
                    fad.getPrecision(),
3528
                    fad.isPrimaryKey(),
3529
                    fad.isIndexed(),
3530
                    fad.allowNull(),
3531
                    fad.isAutomatic(),
3532
                    fad.getDefaultValue()
3533
            );
3534
        }
3535
        FeatureStore store = fad.getStore();
3536
        if( store!=null ) {
3537
            descriptor.setStoreParameters(store.getParameters());
3538
        }
3539
        return new VariableBase(descriptor);
3540
    }
3541
    
3542
    @Override
3543
    public Function Find_SRID(Value schema, Value table, Value column) {
3544
        return builtin_function("Find_SRID", config.getString(SQLConfig.Find_SRID), schema, table, column);
3545
    }
3546

    
3547

    
3548
    public Function iif(Value condition, Value iftrue, Value iffalse) {
3549
        return builtin_function("IIF", config.getString(Config.iif), condition, iftrue, iffalse);
3550
    }
3551

    
3552
    public Function ifnull(Value value, Value iftrue, Value iffalse) {
3553
        return builtin_function("IFNULL", config.getString(Config.ifnull), value, iftrue, iffalse);
3554
    }
3555
    
3556
    
3557
    @Override
3558
    public Function left(Value str, Value size) {
3559
       return function("left", str, size);
3560
       // return builtin_function("left", "left({1})",str,size);
3561
    }
3562
    
3563
    @Override
3564
    public Function right(Value str, Value len) {
3565
       return function("right", str, len);
3566
    }
3567
    
3568
    @Override
3569
    public Function locate(Value search, Value str, Value start) {
3570
       return function("locate", search, str, start);
3571
    }
3572
    
3573
    @Override
3574
    public Function position(Value search, Value str) {
3575
       return function("position", search, str);
3576
    }
3577
    
3578
    @Override
3579
    public Function lpad(Value str, Value len, Value padstr) {
3580
       return function("lpad", str, len, padstr);
3581
    }
3582
    
3583
    @Override
3584
    public Function rpad(Value str, Value len, Value padstr) {
3585
       return function("rpad", str, len, padstr);
3586
    }
3587
    
3588
    @Override
3589
    public Function ltrim(Value str) {
3590
       return function("ltrim", str);
3591
    }
3592
    
3593
    @Override
3594
    public Function rtrim(Value str) {
3595
       return function("rtrim", str);
3596
    }
3597
    
3598
    @Override
3599
    public Function trim(Value str) {
3600
       return function("trim", str);
3601
    }
3602
    
3603
    @Override
3604
    public Function repeat(Value str, Value size) {
3605
       return function("repeat", str, size);
3606
    }
3607
    
3608
    @Override
3609
    public Function replace(Value str, Value search, Value replstr) {
3610
       return function("replace", str, search, replstr);
3611
    }
3612
    
3613
    @Override
3614
    public Function ascii(Value str) {
3615
       return function("ascii", str);
3616
    }
3617
    
3618
    @Override
3619
    public Function lenght(Value str) {
3620
       return function("lenght", str);
3621
    }
3622

    
3623
    @Override
3624
    public Function instr(Value str, Value search, Value start) {
3625
       return function("instr", str, search, start);
3626
    }
3627
    
3628
    @Override
3629
    public Function lower(Value str) {
3630
       return function("lower", str);
3631
    }
3632
    
3633
    @Override
3634
    public Function upper(Value str) {
3635
       return function("upper", str);
3636
    }
3637
    
3638
    @Override
3639
    public Function space(Value size) {
3640
       return function("space", size);
3641
    }
3642
    
3643
    @Override
3644
    public Function substring(Value str, Value start, Value len) {
3645
       return function("substring", str, start, len);
3646
    }
3647
    
3648
    @Override
3649
    public Function acos(Value num) {
3650
       return function("acos", num);
3651
    } 
3652
    
3653
    @Override
3654
    public Function asin(Value num) {
3655
       return function("asin", num);
3656
    }
3657
    
3658
    @Override
3659
    public Function atan(Value num) {
3660
       return function("atan", num);
3661
    }
3662
    
3663
    @Override
3664
    public Function cos(Value num) {
3665
       return function("cos", num);
3666
    }
3667
    
3668
    @Override
3669
    public Function cosh(Value num) {
3670
       return function("cosh", num);
3671
    }
3672
    
3673
    @Override
3674
    public Function cot(Value num) {
3675
       return function("cot", num);
3676
    }  
3677
    
3678
    @Override
3679
    public Function bitand(Value num1, Value num2) {
3680
       return function("bitand", num1, num2);
3681
    } 
3682
    
3683
    @Override
3684
    public Function bitor(Value num1, Value num2) {
3685
       return function("bitor", num1, num2);
3686
    }
3687
    
3688
    @Override
3689
    public Function bitxor(Value num1, Value num2) {
3690
       return function("bitxor", num1, num2);
3691
    }
3692
    
3693
    @Override
3694
    public Function ceil(Value num) {
3695
       return function("ceil", num);
3696
    }
3697
    
3698
    @Override
3699
    public Function degrees(Value num) {
3700
       return function("degrees", num);
3701
    }  
3702
    
3703
    @Override
3704
    public Function exp(Value num) {
3705
       return function("exp", num);
3706
    }  
3707
    
3708
    @Override
3709
    public Function floor(Value num) {
3710
       return function("floor", num);
3711
    }  
3712
    
3713
    @Override
3714
    public Function log(Value num) {
3715
       return function("log", num);
3716
    }  
3717
    
3718
    @Override
3719
    public Function log10(Value num) {
3720
       return function("log10", num);
3721
    }  
3722
    
3723
    @Override
3724
    public Function pi(Value num) {
3725
       return function("pi", num);
3726
    }
3727
    
3728
    @Override
3729
    public Function power(Value num) {
3730
       return function("power", num);
3731
    }
3732
    
3733
    @Override
3734
    public Function radians(Value num) {
3735
       return function("radians", num);
3736
    }
3737
    
3738
    @Override
3739
    public Function rand(Value num) {
3740
       return function("rand", num);
3741
    }
3742
    
3743
    @Override
3744
    public Function round(Value num) {
3745
       return function("round", num);
3746
    }
3747
    
3748
    @Override
3749
    public Function sqrt(Value num) {
3750
       return function("sqrt", num);
3751
    }
3752
    
3753
    @Override
3754
    public Function sign(Value num) {
3755
       return function("sign", num);
3756
    }
3757
    
3758
    @Override
3759
    public Function sin(Value num) {
3760
       return function("sin", num);
3761
    }
3762
    
3763
    @Override
3764
    public Function sinh(Value num) {
3765
       return function("sinh", num);
3766
    }
3767
    
3768
    @Override
3769
    public Function tan(Value num) {
3770
       return function("tan", num);
3771
    }
3772
    @Override
3773
    public Function tanh(Value num) {
3774
       return function("cosh", num);
3775
    }  
3776
    
3777
    @Override
3778
    public Function zero() {
3779
       return function("zero");
3780
    }
3781
    
3782
    @Override
3783
    public Function chr(Value num) {
3784
       return function("chr", num);
3785
    }
3786
}