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

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 SelectBuilder limit(Long limit) {
1317
            if( limit == null ) {
1318
                this.limit = 0;
1319
            } else {
1320
                this.limit = limit;
1321
            }
1322
            return this;
1323
        }
1324

    
1325
        @Override
1326
        public boolean has_limit() {
1327
            return this.limit > 0;
1328
        }
1329

    
1330
        @Override
1331
        public SelectBuilder offset(long offset) {
1332
            this.offset = offset;
1333
            return this;
1334
        }
1335

    
1336
        @Override
1337
        public boolean has_offset() {
1338
            return this.offset > 0;
1339
        }
1340

    
1341
        @Override
1342
        public OrderByBuilder order_by() {
1343
            if( this.order_by == null ) {
1344
                this.order_by = new ArrayList<>();
1345
            }
1346
            OrderByBuilder order = createOrderByBuilder();
1347
            this.order_by.add(order);
1348
            return order;
1349
        }
1350

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

    
1394
            if ( this.has_from() ) {
1395
                builder.append(" FROM ");
1396
                builder.append(this.from.toString());
1397
            }
1398
            if ( this.has_where() ) {
1399
                builder.append(" WHERE ");
1400
                builder.append(this.where.toString());
1401
            }
1402
            
1403
            if( this.has_order_by() ) {
1404
                builder.append(" ORDER BY ");
1405
                first = true;
1406
                for (OrderByBuilder item : this.order_by) {
1407
                    if (first) {
1408
                        first = false;
1409
                    } else {
1410
                        builder.append(", ");
1411
                    }
1412
                    builder.append(item.toString());                    
1413
                }   
1414
            }
1415
            
1416
            if ( this.has_limit() ) {
1417
                builder.append(" LIMIT ");
1418
                builder.append(this.limit);
1419
            }
1420
            if ( this.has_offset() ) {
1421
                builder.append(" OFFSET ");
1422
                builder.append(this.offset);
1423
            }
1424
            return builder.toString();
1425

    
1426
        }
1427
    }
1428

    
1429
    public class DropTableBuilderBase implements DropTableBuilder {
1430

    
1431
        protected TableNameBuilder table;
1432

    
1433
        @Override
1434
        public TableNameBuilder table() {
1435
            if( table == null ) {
1436
                table = createTableNameBuilder();
1437
            }
1438
            return table;
1439
        }
1440

    
1441
        @Override
1442
        public void accept(Visitor visitor, VisitorFilter filter) {
1443
            if( filter.accept(this) ) {
1444
                visitor.visit(this);
1445
            }
1446
            this.table.accept(visitor,filter);
1447
        }
1448
        
1449
        @Override
1450
        public String toString() {
1451
            StringBuilder builder = new StringBuilder();
1452
            boolean first = true;
1453
            for (String sql : toStrings()) {
1454
                if( StringUtils.isEmpty(sql) ) {
1455
                    continue;
1456
                }
1457
                if (first) {
1458
                    first = false;
1459
                } else {
1460
                    builder.append("; ");
1461
                }
1462
                builder.append(sql);
1463
            }
1464
            return builder.toString();
1465
        }
1466

    
1467
        @Override
1468
        public List<String> toStrings() {
1469
            List<String> sqls = new ArrayList<>();
1470

    
1471
            sqls.add(
1472
                    MessageFormat.format(
1473
                            config.getString(SQLConfig.DROP_TABLE_table),
1474
                            this.table.toString()
1475
                    )
1476
            );
1477
            String sql;
1478
            if( config.has_functionality(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table) ) {
1479
                if (this.table.has_schema()) {
1480
                    sql = MessageFormat.format(
1481
                            config.getString(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table),
1482
                            string(this.table.getSchema()),
1483
                            string(this.table.getName())
1484
                    );
1485
                } else {
1486
                    sql = MessageFormat.format(
1487
                            config.getString(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table),
1488
                            identifier(this.table.getName())
1489
                    );
1490
                }
1491
                if( !StringUtils.isEmpty(sql) ) {
1492
                    sqls.add(sql);
1493
                }
1494
            }
1495
            return sqls;
1496
        }
1497
    }
1498

    
1499
    public class GrantRoleBuilderBase implements GrantRoleBuilder {
1500
        protected TableNameBuilder table;
1501
        protected String role;
1502
        protected Set<Privilege> privileges;
1503

    
1504
        public GrantRoleBuilderBase(TableNameBuilder table, String role) {
1505
            this.table = table;
1506
            this.role = role;
1507
            this.privileges = new HashSet<>();
1508
        }
1509

    
1510
        @Override
1511
        public GrantRoleBuilder privilege(Privilege privilege) {
1512
            privileges.add(privilege);
1513
            return this;
1514
        }
1515
        
1516
        @Override
1517
        public GrantRoleBuilder select() {
1518
             privileges.add(Privilege.SELECT);
1519
            return this;
1520
        }
1521

    
1522
        @Override
1523
        public GrantRoleBuilder update() {
1524
             privileges.add(Privilege.UPDATE);
1525
            return this;
1526
        }
1527

    
1528
        @Override
1529
        public GrantRoleBuilder insert() {
1530
            privileges.add(Privilege.INSERT);
1531
            return this;
1532
        }
1533

    
1534
        @Override
1535
        public GrantRoleBuilder delete() {
1536
            privileges.add(Privilege.DELETE);
1537
            return this;
1538
        }
1539

    
1540
        @Override
1541
        public GrantRoleBuilder truncate() {
1542
            privileges.add(Privilege.TRUNCATE);
1543
            return this;
1544
        }
1545

    
1546
        @Override
1547
        public GrantRoleBuilder reference() {
1548
            privileges.add(Privilege.REFERENCE);
1549
            return this;
1550
        }
1551

    
1552
        @Override
1553
        public GrantRoleBuilder trigger() {
1554
            privileges.add(Privilege.TRIGGER);
1555
            return this;
1556
        }
1557

    
1558
        @Override
1559
        public GrantRoleBuilder all() {
1560
            privileges.add(Privilege.ALL);
1561
            return this;
1562
        }
1563

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

    
1610
        protected TableNameBuilder table;
1611
        protected Map<String, GrantRoleBuilder> roles;
1612

    
1613
        public GrantBuilderBase() {
1614
            this.roles = new HashMap<>();
1615
        }
1616
        
1617
        @Override
1618
        public TableNameBuilder table() {
1619
            if( table == null ) {
1620
                table = createTableNameBuilder();
1621
            }
1622
            return table;
1623
        }
1624

    
1625
        @Override
1626
        public void accept(Visitor visitor, VisitorFilter filter) {
1627
            if( filter.accept(this) ) {
1628
                visitor.visit(this);
1629
            }
1630
            if( this.table!= null ) {
1631
                this.table.accept(visitor,filter);
1632
            }
1633
        }
1634
        
1635
        @Override
1636
        public GrantRoleBuilder role(String role) {
1637
            GrantRoleBuilder roleBuilder = this.roles.get(role);
1638
            if( roleBuilder == null ) {
1639
                roleBuilder = createGrantRoleBuilder(this.table(), role);
1640
                this.roles.put(role, roleBuilder);
1641
            }
1642
            return roleBuilder;
1643
        }
1644

    
1645
        @Override
1646
        public String toString() {
1647
            StringBuilder builder = new StringBuilder();
1648
            boolean first = true;
1649
            for (String sql : toStrings()) {
1650
                if( StringUtils.isEmpty(sql) ) {
1651
                    continue;
1652
                }
1653
                if (first) {
1654
                    first = false;
1655
                } else {
1656
                    builder.append("; ");
1657
                }
1658
                builder.append(sql);
1659
            }
1660
            return builder.toString();
1661
        }
1662

    
1663
        @Override
1664
        public List<String> toStrings() {
1665
            List<String> sqls = new ArrayList<>();
1666
            for (GrantRoleBuilder role : roles.values()) {
1667
                sqls.add(role.toString());
1668
            }
1669
            return sqls;
1670
        }
1671
    }
1672

    
1673
    public class UpdateColumnBuilderBase extends InsertColumnBuilderBase implements UpdateColumnBuilder {
1674
        
1675
        public UpdateColumnBuilderBase() {
1676
            super();
1677
        }
1678

    
1679
        @Override
1680
        public UpdateColumnBuilder name(String name) {
1681
            return (UpdateColumnBuilder) super.name(name);
1682
        }
1683

    
1684
        @Override
1685
        public UpdateColumnBuilder with_value(Value value) {
1686
            return (UpdateColumnBuilder) super.with_value(value);
1687
        }
1688
        
1689
    }
1690
    
1691
    public class UpdateBuilderBase implements UpdateBuilder {
1692

    
1693
        protected ExpressionBuilder where;
1694
        protected List<UpdateColumnBuilder> columns;
1695
        protected TableNameBuilder table;
1696

    
1697
        public UpdateBuilderBase() {
1698
            this.columns = new ArrayList<>();
1699
        }
1700

    
1701
        @Override
1702
        public void accept(Visitor visitor, VisitorFilter filter) {
1703
            if( filter.accept(this) ) {
1704
                visitor.visit(this);
1705
            }
1706
            if( this.table != null ) {
1707
                this.table.accept(visitor, filter);
1708
            }
1709
            for (UpdateColumnBuilder column : columns) {
1710
                column.accept(visitor, filter);
1711
            }
1712
            if( this.has_where() ) {
1713
                this.where.accept(visitor, filter);
1714
            }
1715
        }
1716

    
1717
        @Override
1718
        public ExpressionBuilder where() {
1719
            if (this.where == null) {
1720
                this.where = createExpressionBuilder();
1721
            }
1722
            return this.where;
1723
        }
1724

    
1725
        @Override
1726
        public TableNameBuilder table() {
1727
            if( table == null ) {
1728
                table = createTableNameBuilder();
1729
            }
1730
            return table;
1731
        }
1732

    
1733
        @Override
1734
        public UpdateColumnBuilder column() {
1735
            UpdateColumnBuilder column = createUpdateColumnBuilder();
1736
            this.columns.add(column);
1737
            return column;
1738
        }
1739
        
1740
        @Override
1741
        public boolean has_where() {
1742
            return this.where != null;
1743
        }
1744

    
1745
        @Override
1746
        public String toString() {
1747
            /*
1748
             * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
1749
             * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
1750
             * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
1751
             * output_expression [ AS output_name ] [, ...] ]
1752
             */
1753
            StringBuilder columnsAndValues = new StringBuilder();
1754

    
1755
            boolean first = true;
1756
            for (UpdateColumnBuilder column : columns) {
1757
                if (first) {
1758
                    first = false;
1759
                } else {
1760
                    columnsAndValues.append(", ");
1761
                }
1762
                columnsAndValues.append(identifier(column.getName()));
1763
                columnsAndValues.append(" = ");
1764
                columnsAndValues.append(column.getValue().toString());
1765
            }
1766
            
1767
            String sql;
1768
            if ( this.has_where() ) {
1769
                sql = MessageFormat.format(
1770
                        config.getString(SQLConfig.UPDATE_table_SET_columnsAndValues_WHERE_expresion),
1771
                        this.table.toString(),
1772
                        columnsAndValues.toString(),
1773
                        this.where.toString()
1774
                );
1775
            } else {
1776
                sql = MessageFormat.format(
1777
                        config.getString(SQLConfig.UPDATE_table_SET_columnsAndValues),
1778
                        this.table.toString(),
1779
                        columnsAndValues.toString()
1780
                );
1781
            }
1782
            return sql;
1783
        }
1784
    }
1785

    
1786
    public class DeleteBuilderBase implements DeleteBuilder {
1787

    
1788
        protected ExpressionBuilder where;
1789
        protected TableNameBuilder table;
1790

    
1791
        public DeleteBuilderBase() {
1792
        }
1793

    
1794
        @Override
1795
        public void accept(Visitor visitor, VisitorFilter filter) {
1796
            if( filter.accept(this) ) {
1797
                visitor.visit(this);
1798
            }
1799
            if( this.table != null ) {
1800
                this.table.accept(visitor, filter);
1801
            }
1802
            if( this.has_where() ) {
1803
                this.where.accept(visitor, filter);
1804
            }
1805
        }
1806

    
1807
        @Override
1808
        public ExpressionBuilder where() {
1809
            if (this.where == null) {
1810
                this.where = createExpressionBuilder();
1811
            }
1812
            return this.where;
1813
        }
1814

    
1815
        @Override
1816
        public TableNameBuilder table() {
1817
            if( table == null ) {
1818
                table = createTableNameBuilder();
1819
            }
1820
            return table;
1821
        }
1822

    
1823
        @Override
1824
        public boolean has_where() {
1825
            return this.where != null;
1826
        }
1827

    
1828
        @Override
1829
        public String toString() {
1830
            /*
1831
             * DELETE FROM table_name
1832
             * WHERE some_column=some_value; 
1833
             */
1834
            String sql;
1835
            if( this.has_where() ) {
1836
                sql = MessageFormat.format(
1837
                        config.getString(SQLConfig.DELETE_FROM_table_WHERE_expresion),
1838
                        this.table.toString(),
1839
                        this.where.toString()
1840
                );
1841
            } else {
1842
                sql = MessageFormat.format(
1843
                        config.getString(SQLConfig.DELETE_FROM_table),
1844
                        this.table.toString()
1845
                );
1846
            }
1847
            return sql;
1848
        }
1849
    }
1850

    
1851
    public class CreateIndexBuilderBase implements CreateIndexBuilder {
1852

    
1853
        protected boolean ifNotExist = false;
1854
        protected boolean isUnique = false;
1855
        protected String indexName;
1856
        protected boolean isSpatial = false;
1857
        protected TableNameBuilder table;
1858
        protected final List<String> columns;
1859
        
1860
        public CreateIndexBuilderBase() {
1861
            this.columns = new ArrayList<>();
1862
        }
1863
        
1864
        @Override
1865
        public CreateIndexBuilder unique() {
1866
            this.isUnique = true;
1867
            return this;
1868
        }
1869

    
1870
        @Override
1871
        public CreateIndexBuilder if_not_exist() {
1872
            this.ifNotExist = true;
1873
            return this;
1874
        }
1875

    
1876
        @Override
1877
        public CreateIndexBuilder name(String name) {
1878
            this.indexName = name;
1879
            return this;
1880
        }
1881

    
1882
        @Override
1883
        public CreateIndexBuilder spatial() {
1884
            this.isSpatial = true;
1885
            return this;
1886
        }
1887

    
1888
        @Override
1889
        public CreateIndexBuilder column(String name) {
1890
            this.columns.add(name);
1891
            return this;
1892
        }
1893

    
1894
        @Override
1895
        public TableNameBuilder table() {
1896
            if( table == null ) {
1897
                table = createTableNameBuilder();
1898
            }
1899
            return table;
1900
        }
1901

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

    
1946
    }
1947
    
1948
    public class AlterTableBuilderBase implements AlterTableBuilder {
1949

    
1950
        protected TableNameBuilder table;
1951
        protected List<String> drops;
1952
        protected List<ColumnDescriptor> adds;
1953
        protected List<ColumnDescriptor> alters;
1954
        protected List<Pair<String,String>> renames;
1955

    
1956
        public AlterTableBuilderBase() {
1957
            this.drops = new ArrayList<>();
1958
            this.adds = new ArrayList<>();
1959
            this.alters = new ArrayList<>();
1960
            this.renames = new ArrayList<>();
1961
        }
1962

    
1963
        @Override
1964
        public boolean isEmpty() {
1965
            return this.drops.isEmpty() && 
1966
                this.adds.isEmpty() && 
1967
                this.alters.isEmpty() && 
1968
                this.renames.isEmpty();
1969
        }
1970
        
1971
        @Override
1972
        public void accept(Visitor visitor, VisitorFilter filter) {
1973
            if( filter.accept(this) ) {
1974
                visitor.visit(this);
1975
            }
1976
            if( this.table != null ) {
1977
                this.table.accept(visitor, filter);
1978
            }
1979
        }
1980

    
1981
        @Override
1982
        public TableNameBuilder table() {
1983
            if( table == null ) {
1984
                table = createTableNameBuilder();
1985
            }
1986
            return table;
1987
        }
1988

    
1989
        @Override
1990
        public AlterTableBuilder drop_column(String columnName) {
1991
            this.drops.add(columnName);
1992
            return this;
1993
        }
1994
        
1995
        @Override
1996
        public AlterTableBuilder add_column(FeatureAttributeDescriptor fad) {
1997
            this.adds.add(column(fad).getDescriptor());
1998
            return this;            
1999
        }
2000

    
2001
        @Override
2002
        public AlterTableBuilder add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
2003
            if (isPk || isAutomatic) {
2004
                allowNulls = false;
2005
            }
2006
            this.adds.add(new ColumnDescriptorBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
2007
            return this;
2008
        }
2009

    
2010
        @Override
2011
        public AlterTableBuilder add_geometry_column(String columnName, int type, int subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
2012
            if( StringUtils.isEmpty(columnName) ) {
2013
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2014
            }
2015
            this.adds.add(new ColumnDescriptorBase(columnName, type, subtype, proj, isIndexed, allowNulls));
2016
            return this;
2017
        }
2018

    
2019
        @Override
2020
        public AlterTableBuilder add_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
2021
            if( StringUtils.isEmpty(columnName) ) {
2022
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2023
            }
2024
            this.adds.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
2025
            return this;
2026
        }
2027
        
2028
        @Override
2029
        public AlterTableBuilder alter_column(FeatureAttributeDescriptor fad) {
2030
            this.alters.add(column(fad).getDescriptor());
2031
            return this;            
2032
        }
2033
        
2034
        @Override
2035
        public AlterTableBuilder alter_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
2036
            if (isPk || isAutomatic) {
2037
                allowNulls = false;
2038
            }
2039
            this.alters.add(new ColumnDescriptorBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
2040
            return this;
2041
        }
2042

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

    
2052
        @Override
2053
        public AlterTableBuilder alter_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
2054
            if( StringUtils.isEmpty(columnName) ) {
2055
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2056
            }
2057
            this.alters.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
2058
            return this;
2059
        }
2060

    
2061
        @Override
2062
        public AlterTableBuilder rename_column(String source, String target) {
2063
            this.renames.add(new ImmutablePair(source, target));
2064
            return this;
2065
        }
2066

    
2067
        @Override
2068
        public String toString() {
2069
            StringBuilder builder = new StringBuilder();
2070
            boolean first = true;
2071
            for (String sql : toStrings()) {
2072
                if( StringUtils.isEmpty(sql) ) {
2073
                    continue;
2074
                }
2075
                if (first) {
2076
                    first = false;
2077
                } else {
2078
                    builder.append("; ");
2079
                }
2080
                builder.append(sql);
2081
            }
2082
            return builder.toString();
2083
        }
2084

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

    
2184
    }
2185

    
2186
    public class CreateTableBuilderBase implements CreateTableBuilder {
2187

    
2188
        protected TableNameBuilder table;
2189
        protected List<ColumnDescriptor> columns;
2190

    
2191
        public CreateTableBuilderBase() {
2192
            this.columns = new ArrayList<>();
2193
        }
2194

    
2195
        @Override
2196
        public void accept(Visitor visitor, VisitorFilter filter) {
2197
            if( filter.accept(this) ) {
2198
                visitor.visit(this);
2199
            }
2200
            if( this.table != null ) {
2201
                this.table.accept(visitor, filter);
2202
            }
2203
        }
2204

    
2205
        @Override
2206
        public TableNameBuilder table() {
2207
            if( table == null ) {
2208
                table = createTableNameBuilder();
2209
            }
2210
            return table;
2211
        }
2212

    
2213
        @Override
2214
        public CreateTableBuilderBase add_column(FeatureAttributeDescriptor fad) {
2215
            this.columns.add(column(fad).getDescriptor());
2216
            return this;            
2217
        }
2218

    
2219
        @Override
2220
        public CreateTableBuilderBase add_column(String columnName, int type, int type_p, int type_s, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
2221
            if( StringUtils.isEmpty(columnName) ) {
2222
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2223
            }
2224
            if (isPk || isAutomatic) {
2225
                allowNulls = false;
2226
            }
2227
            this.columns.add(new ColumnDescriptorBase(columnName, type, type_p, type_s, isPk, isIndexed, allowNulls, isAutomatic, defaultValue));
2228
            return this;
2229
        }
2230

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

    
2240
        @Override
2241
        public CreateTableBuilder add_geometry_column(String columnName, int type, int subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
2242
            if( StringUtils.isEmpty(columnName) ) {
2243
                throw new IllegalArgumentException("Argument 'columnName' can't be empty.");
2244
            }
2245
            this.columns.add(new ColumnDescriptorBase(columnName, type, subtype, srsdbcode, isIndexed, allowNulls));
2246
            return this;
2247
        }
2248

    
2249
        @Override
2250
        public ColumnDescriptor getColumnDescriptor(String columnName) {
2251
            if( StringUtils.isEmpty(columnName) ) {
2252
                return null;
2253
            }
2254
            for (ColumnDescriptor column : columns) {
2255
                if( columnName.equals(column.getName()) ) {
2256
                    return column;
2257
                }
2258
            }
2259
            return null;
2260
        }
2261
                
2262
        @Override
2263
        public String toString() {
2264
            StringBuilder builder = new StringBuilder();
2265
            boolean first = true;
2266
            for (String sql : toStrings()) {
2267
                if( StringUtils.isEmpty(sql) ) {
2268
                    continue;
2269
                }
2270
                if (first) {
2271
                    first = false;
2272
                } else {
2273
                    builder.append("; ");
2274
                }
2275
                builder.append(sql);
2276
            }
2277
            return builder.toString();
2278
        }
2279

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

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

    
2353
    public class InsertColumnBuilderBase implements InsertColumnBuilder {
2354
        protected Variable name;
2355
        protected Value value;
2356
        
2357
        public InsertColumnBuilderBase() {
2358
        }
2359

    
2360
        @Override
2361
        public void accept(Visitor visitor, VisitorFilter filter) {
2362
            if( filter.accept(this) ) {
2363
                visitor.visit(this);
2364
            }
2365
            if( this.name != null ) {
2366
                this.name.accept(visitor, filter);
2367
            }
2368
            if( this.value != null ) {
2369
                this.value.accept(visitor, filter);
2370
            }
2371
        }
2372

    
2373
        @Override
2374
        public InsertColumnBuilder name(String name) {
2375
            this.name = variable(name);
2376
            return this;
2377
        }
2378

    
2379
        @Override
2380
        public InsertColumnBuilder with_value(Value value) {
2381
            this.value = value;
2382
            return this;
2383
        }
2384
        
2385
        @Override
2386
        public String getName() {
2387
            return this.name.getName();
2388
        }
2389
        
2390
        @Override
2391
        public Value getValue() {
2392
            return this.value;
2393
        }
2394
        
2395
        @Override
2396
        public String toString() {
2397
            return this.value.toString();
2398
        }
2399
    }
2400
    
2401
    public class InsertBuilderBase implements InsertBuilder {
2402

    
2403
        protected List<InsertColumnBuilder> columns;
2404
        protected TableNameBuilder table;
2405

    
2406
        public InsertBuilderBase() {
2407
            this.columns = new ArrayList<>();
2408
        }
2409

    
2410
        @Override
2411
        public void accept(Visitor visitor, VisitorFilter filter) {
2412
            if( filter.accept(this) ) {
2413
                visitor.visit(this);
2414
            }
2415
            if( this.table != null ) {
2416
                this.table.accept(visitor, filter);
2417
            }
2418
            for (InsertColumnBuilder column : columns) {
2419
                column.accept(visitor, filter);
2420
            }
2421
        }
2422

    
2423
        @Override
2424
        public TableNameBuilder table() {
2425
            if( table == null ) {
2426
                table = createTableNameBuilder();
2427
            }
2428
            return table;
2429
        }
2430

    
2431
        @Override
2432
        public InsertColumnBuilder column() {
2433
            InsertColumnBuilder column = createInsertColumnBuilder();
2434
            this.columns.add(column);
2435
            return column;
2436
        }
2437

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

    
2475
        }
2476
    }
2477

    
2478
    public class UpdateTableStatisticsBuilderBase implements UpdateTableStatisticsBuilder {
2479

    
2480
        protected TableNameBuilder table;
2481

    
2482
        @Override
2483
        public void accept(Visitor visitor, VisitorFilter filter) {
2484
            if( filter.accept(this) ) {
2485
                visitor.visit(this);
2486
            }
2487
            if( this.table != null ) {
2488
                this.table.accept(visitor, filter);
2489
            }
2490
        }
2491

    
2492
        @Override
2493
        public TableNameBuilder table() {
2494
            if( table == null ) {
2495
                table = createTableNameBuilder();
2496
            }
2497
            return table;
2498
        }
2499

    
2500
        @Override
2501
        public String toString() {
2502
            StringBuilder builder = new StringBuilder();
2503
            boolean first = true;
2504
            for (String sql : toStrings()) {
2505
                if( StringUtils.isEmpty(sql) ) {
2506
                    continue;
2507
                }
2508
                if (first) {
2509
                    first = false;
2510
                } else {
2511
                    builder.append("; ");
2512
                }
2513
                builder.append(sql);
2514
            }
2515
            return builder.toString();
2516
        }
2517

    
2518
        @Override
2519
        public List<String> toStrings() {
2520
            List<String> sqls = new ArrayList<>();
2521
            
2522
            if( config.has_functionality(SQLConfig.UPDATE_TABLE_STATISTICS_table) ) {
2523
                String sql = MessageFormat.format(
2524
                        config.getString(SQLConfig.UPDATE_TABLE_STATISTICS_table),
2525
                        table.toString()
2526
                    );
2527
                if( !StringUtils.isEmpty(sql) ) {
2528
                    sqls.add(sql);
2529
                }
2530
            }
2531
            return sqls;
2532
        }
2533
    }
2534

    
2535

    
2536
    private static class ParametersBase extends ArrayList<Parameter> implements Parameters {
2537

    
2538
        private static final long serialVersionUID = -2188534574151780470L;
2539

    
2540
        public ParametersBase() {
2541
            super();
2542
        }
2543

    
2544
        public ParametersBase(Collection parameters) {
2545
            super(parameters);
2546
        }
2547

    
2548
        @Override
2549
        public Parameter get(String name) {
2550
            if( name == null ) {
2551
                return null;
2552
            }
2553
            for (Parameter param : this) {
2554
                if( param.is_variable() || param.is_geometry_variable() ) {
2555
                    if( name.equalsIgnoreCase(param.getName()) ) {
2556
                        return param;
2557
                    }
2558
                }
2559
            }
2560
            return null;
2561
        }
2562

    
2563
        
2564
        @Override
2565
        public String toString() {
2566
            boolean first = true;
2567
            StringBuilder builder = new StringBuilder();
2568
            builder.append("{ ");
2569
            for (Parameter param : this) {
2570
                if (!first) {
2571
                    builder.append(", ");
2572
                } else {
2573
                    first = false;
2574
                }
2575
                String s;
2576
                Object value = param.getValue();
2577
                if (value == null) {
2578
                    s = "null";
2579
                } else if (value instanceof String) {
2580
                    s = "'" + (String) value + "'";
2581
                } else {
2582
                    s = value.toString();
2583
                }
2584
                switch (param.getType()) {
2585
                    case Constant:
2586
                        builder.append(s);
2587
                        break;
2588
                    case Geometry:
2589
                        builder.append("(Geometry)");
2590
                    case Variable:
2591
                    default:
2592
                        builder.append(param.getName());
2593
                        builder.append(": ");
2594
                        builder.append(s);
2595
                }
2596
            }
2597
            builder.append(" }");
2598
            return builder.toString();
2599
        }
2600
    }
2601

    
2602
    protected Value value;
2603
    protected Config config;
2604
  
2605
    public SQLBuilderBase() {
2606
        
2607
        this.config = new ConfigBase();
2608
        this.value = null;
2609
        
2610
        config.set(SQLConfig.has_spatial_functions, false);
2611
        config.set(SQLConfig.support_schemas, true);
2612
        config.set(SQLConfig.constant_true, "(1=1)");
2613
        config.set(SQLConfig.constant_false, "(1=2)");
2614
        config.set(SQLConfig.quote_for_identifiers, "\"");
2615
        config.set(SQLConfig.quote_for_strings, "'");
2616
        config.set(SQLConfig.geometry_type_support, GeometrySupportType.WKT);
2617
        config.set(SQLConfig.group, "( {0} )");
2618

    
2619
        config.set(SQLConfig.ST_SRID, "ST_SRID({0})");
2620
        config.set(SQLConfig.ST_AsText, "ST_AsText({0})");
2621
        config.set(SQLConfig.ST_AsBinary, "ST_AsBinary({0})");
2622
        config.set(SQLConfig.ST_AsEWKB, "ST_AsEWKB({0})");
2623
        config.set(SQLConfig.ST_Contains, "ST_Contains(({0}), ({1}))");
2624
        config.set(SQLConfig.ST_Crosses, "ST_Crosses(({0}), ({1}))");
2625
        config.set(SQLConfig.ST_Disjoint, "ST_Disjoint(({0}), ({1}))");
2626
        config.set(SQLConfig.ST_Equals, "ST_Equals(({0}), ({1}))");
2627
        config.set(SQLConfig.ST_IsClosed, "ST_IsClosed({0})");
2628
        config.set(SQLConfig.ST_Overlaps, "ST_Overlaps(({0}), ({1}))");
2629
        config.set(SQLConfig.ST_Touches, "ST_Touches(({0}), ({1}))");
2630
        config.set(SQLConfig.ST_Within, "ST_Within(({0}), ({1}))");
2631
        config.set(SQLConfig.ST_Envelope, "ST_Envelope({0})");
2632
        config.set(SQLConfig.ST_Intersects, "ST_Intersects(({0}), ({1}))");
2633
        config.set(SQLConfig.ST_GeomFromText, "ST_GeomFromText({0}, ({1}))");
2634
        config.set(SQLConfig.ST_GeomFromWKB, "ST_GeomFromWKB(({0}), ({1}))");
2635
        config.set(SQLConfig.ST_GeomFromEWKB, "ST_GeomFromEWKB(({0}), ({1}))");
2636

    
2637
        // Por defecto no esta disponible la funcion ST_Simplify
2638
        // El proveedor que la soporte que la defina.
2639
        // config.set(SQLConfig.ST_Simplify, "ST_Simplify(({0}), ({1}))");
2640
        config.remove_functionality(SQLConfig.ST_Simplify);
2641

    
2642
        config.set(SQLConfig.lcase, "LCASE({0})");
2643
        config.set(SQLConfig.ucase, "UCASE({0})");
2644
        config.set(SQLConfig.isNull, "( ({0}) IS NULL )");
2645
        config.set(SQLConfig.notIsNull, "( ({0}) NOT IS NULL )");
2646
        config.set(SQLConfig.operator_not, "( NOT ({0}) )");
2647

    
2648
        config.set(SQLConfig.operator_AND, "{0} AND {1}");
2649
        config.set(SQLConfig.operator_OR, "{0} OR {1}");
2650
        config.set(SQLConfig.operator_EQ, "( ({0}) = ({1}) )");
2651
        config.set(SQLConfig.operator_NE, "( ({0}) <> ({1}) )");
2652
        config.set(SQLConfig.operator_GT, "( ({0}) > ({1}) )");
2653
        config.set(SQLConfig.operator_GE, "( ({0}) >= ({1}) )");
2654
        config.set(SQLConfig.operator_LT, "( ({0}) < ({1}) )");
2655
        config.set(SQLConfig.operator_LE, "( ({0}) <= ({1}) )");
2656
        config.set(SQLConfig.operator_LIKE, "( ({0}) LIKE ({1}) )");
2657
        config.set(SQLConfig.operator_ILIKE, "( ({0}) ILIKE ({1}) )");
2658

    
2659
        config.set(SQLConfig.operator_add, "{0} + {1}");
2660
        config.set(SQLConfig.operator_subst, "{0} - {1}");
2661
        config.set(SQLConfig.operator_mult, "{0} * {1}");
2662
        config.set(SQLConfig.operator_div, "{0} / {1}");
2663
        config.set(SQLConfig.operator_concat, "{0} || {1}");
2664

    
2665

    
2666
        config.set(SQLConfig.default_schema, "public");
2667
        config.set(SQLConfig.allowAutomaticValues, true);
2668
        
2669
        config.set(SQLConfig.ST_ExtentAggregate, "ST_Extent({0})");
2670
        config.set(SQLConfig.ST_UnionAggregate, "ST_Union({0})");
2671
        config.set(SQLConfig.count, "COUNT({0})");
2672
        config.set(SQLConfig.count_distinct, "COUNT(DISTINCT {0})");
2673

    
2674
        config.set(SQLConfig.type_boolean, "BOOLEAN");
2675
        config.set(SQLConfig.type_byte, "TINYINT");
2676
        config.set(SQLConfig.type_bytearray, "BYTEA");
2677
        config.set(SQLConfig.type_geometry, "TEXT");
2678
        config.set(SQLConfig.type_char, "CHARACTER(1)");
2679
        config.set(SQLConfig.type_date, "DATE");
2680
        config.set(SQLConfig.type_double, "DOUBLE PRECISION"); //float con 53 bits de mantisa, float(54)
2681
        config.set(SQLConfig.type_numeric_p, "NUMERIC({0})");
2682
        config.set(SQLConfig.type_numeric_ps, "NUMERIC({0},{1})");
2683
        config.set(SQLConfig.type_bigdecimal, "NUMERIC({0},{1})");
2684
        config.set(SQLConfig.type_float, "REAL"); //float con 24 bits de mantisa, float(24)
2685
        config.set(SQLConfig.type_int, "INT");
2686
        config.set(SQLConfig.type_long, "BIGINT");
2687
        config.set(SQLConfig.type_string, "TEXT");
2688
        config.set(SQLConfig.type_string_p, "VARCHAR({0})");
2689
        config.set(SQLConfig.type_time, "TIME");
2690
        config.set(SQLConfig.type_timestamp, "TIMESTAMP");
2691
        config.set(SQLConfig.type_version, "VARCHAR(30)");
2692
        config.set(SQLConfig.type_URI, "TEXT");
2693
        config.set(SQLConfig.type_URL, "TEXT");
2694
        config.set(SQLConfig.type_FILE, "TEXT");
2695
        config.set(SQLConfig.type_FOLDER, "TEXT");
2696

    
2697
        config.set(SQLConfig.DELETE_FROM_table_WHERE_expresion, "DELETE FROM {0} WHERE {1}");
2698
        config.set(SQLConfig.DELETE_FROM_table, "DELETE FROM {0}");
2699
        config.set(SQLConfig.INSERT_INTO_table_columns_VALUES_values, "INSERT INTO {0} ( {1} ) VALUES ( {2} )");
2700
        config.set(SQLConfig.UPDATE_TABLE_STATISTICS_table, "VACUUM ANALYZE {0}");
2701
        config.set(SQLConfig.DROP_TABLE_table, "DROP TABLE {0}");
2702
        config.set(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table, "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_schema = {0} AND f_table_name = {1}");
2703
        config.set(SQLConfig.DELETE_GEOMETRY_COLUMN_FROM_TABLE_table, "DELETE FROM GEOMETRY_COLUMNS WHERE f_table_name = {0}");
2704
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues_WHERE_expresion, "UPDATE {0} SET {1} WHERE {2}");
2705
        config.set(SQLConfig.UPDATE_table_SET_columnsAndValues, "UPDATE {0} SET {1}");
2706
        config.set(SQLConfig.GRANT_privileges_ON_table_TO_role, "GRANT {0} ON {1} TO {2}");        
2707
    }
2708
   
2709
    @Override
2710
    public ExpressionBuilder createExpressionBuilder() {
2711
        return ExpressionEvaluatorLocator.getManager().createExpressionBuilder();
2712
    }
2713

    
2714
    @Override
2715
    public Config getConfig() {
2716
        return this.config;
2717
    }
2718

    
2719
    @Override
2720
    public Value getValue() {
2721
        return this.value;
2722
    }
2723

    
2724
    @Override
2725
    public ExpressionBuilder setValue(Value value) {
2726
        this.value = value;
2727
        return this;
2728
    }
2729

    
2730
    @Override
2731
    public boolean has_spatial_functions() {
2732
        return this.config.getBoolean(Config.has_spatial_functions);
2733
    }
2734

    
2735
    @Override
2736
    public GeometrySupportType geometry_support_type() {
2737
        return (GeometrySupportType) this.config.get(Config.geometry_type_support);
2738
    }
2739

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

    
2751
    @Override
2752
    public String identifier(String id) {
2753
        String quote = this.config.getString(Config.quote_for_identifiers);
2754
//        No se porque no esta disponible wrapIfMissing
2755
//        return StringUtils.wrapIfMissing(id,quote);
2756
        if (id.startsWith(quote)) {
2757
            return id;
2758
        }
2759
        return quote + id + quote;
2760
    }
2761

    
2762
    @Override
2763
    public String bytearray(byte[] data) {
2764
        return bytearray_0x(data);
2765
    }
2766
    
2767
    public String bytearray_hex(byte[] data) {
2768
        StringBuilder builder = new StringBuilder();
2769
        for (byte abyte : data) {
2770
            int v = abyte & 0xff;
2771
            builder.append(String.format("%02x", v));
2772
        }
2773
        return builder.toString();
2774
    }
2775

    
2776
    public String bytearray_0x(byte[] data) {
2777
        return "0x" + bytearray_hex(data);
2778
    }
2779

    
2780
    public String bytearray_x(byte[] data) {
2781
        return "x'" + bytearray_hex(data) + "'";
2782
    }
2783
    
2784
    @Override
2785
    public Object getSRSId(IProjection projection) {
2786
        String abrev = projection.getAbrev();
2787
        return abrev.split(":")[1].trim();
2788
    }
2789

    
2790
    @Override
2791
    public Constant srs(IProjection projection) {
2792
        return constant(getSRSId(projection));
2793
    }
2794

    
2795
    @Override
2796
    public Variable variable(String name) {
2797
        return new VariableBase(name);
2798
    }
2799

    
2800
    @Override
2801
    public Column column(String name) {
2802
        return new VariableBase(name);
2803
    }
2804
    
2805
    @Override
2806
    public Parameter parameter(String name) {
2807
        Parameters parameters = this.getParameters();
2808
        Parameter parameter = parameters.get(name);
2809
        if( parameter != null ) {
2810
            return parameter;
2811
        }
2812
        parameter = this.parameter();
2813
        parameter.name(name);
2814
        return parameter;
2815
    }
2816
    
2817
    @Override
2818
    public Parameter parameter() {
2819
        return new ParameterBase();
2820
    }
2821
    
2822
    @Override
2823
    public Constant constant(Object value) {
2824
        return new ConstantBase(value);
2825
    }
2826

    
2827
    @Override
2828
    public Group group(Value value) {
2829
        return new GroupBase(value);
2830
    }
2831

    
2832
    @Override
2833
    public GeometryValue geometry(Geometry geom, IProjection projection) {
2834
        return new GeometryValueBase(geom, projection);
2835
    }
2836

    
2837
    @Override
2838
    public GeometryValue geometry(Geometry geom) {
2839
        if( geom.getProjection()==null ) {
2840
            throw new IllegalArgumentException("The geometry does not have an associated projection. Use 'geometry(Geometry, IProjection)'.");
2841
        }
2842
        return new GeometryValueBase(geom, geom.getProjection());
2843
    }
2844

    
2845
    @Override
2846
    public GeometryValue envelope(Envelope envelope, IProjection projection) {
2847
        return new GeometryValueBase(envelope.getGeometry(), projection);
2848
    }
2849

    
2850
    @Override
2851
    public GeometryValue envelope(Envelope envelope) {
2852
        if( envelope.getProjection()==null ) {
2853
            throw new IllegalArgumentException("The envelope does not have an associated projection. Use 'envelope(Geometry, IProjection)'.");
2854
        }
2855
        return new GeometryValueBase(envelope.getGeometry(), envelope.getProjection());
2856
    }
2857

    
2858
    @Override
2859
    public Custom custom(Object value) {
2860
        return new CustomBase(value);
2861
    }
2862

    
2863
    public Function builtin_function(String name, String format, Value... values) {
2864
        FunctionBase func = new FunctionBase(name, format);
2865
        for (Value value : values) {
2866
            func.parameter(value);
2867
        }
2868
        return func;
2869
    }
2870

    
2871
    public Function function(String name, Value... values) {
2872
        FunctionBase func = new FunctionBase(name);
2873
        for (Value theValue : values) {
2874
            func.parameter(theValue);
2875
        }
2876
        return func;
2877
    }    
2878
    
2879
    public BinaryOperator binaryOperator(String name, String format, Value leftOperand, Value rightOperand) {
2880
        BinaryOperator operator = new BinaryOperatorBase(name, format);
2881
        operator.setLeft(leftOperand);
2882
        operator.setRight(rightOperand);
2883
        return operator;
2884
    }
2885

    
2886
    @Override
2887
    public List<Variable> getVariables() {
2888
        final Set<Variable> vars = new HashSet<>();
2889
        this.accept(new Visitor() {
2890
            @Override
2891
            public void visit(Visitable value) {
2892
                vars.add((Variable) value);
2893
            }
2894
        }, new ClassVisitorFilter(Variable.class));
2895
        List<Variable> lvars = new ArrayList<>(vars);
2896
        Collections.sort(lvars);
2897
        return lvars;
2898
    }
2899

    
2900
    @Override
2901
    public Parameters getParameters() {
2902
        final Parameters params = new ParametersBase();
2903
        this.accept(new Visitor() {
2904
            @Override
2905
            public void visit(Visitable value) {
2906
                params.add((Parameter) value);
2907
            }
2908
        }, new ClassVisitorFilter(Parameter.class));
2909
        return params;
2910
    }
2911

    
2912
    @Override
2913
    public Function getAsGeometry(Value value) {
2914
        return builtin_function("ST_AsBinary", config.getString(Config.ST_AsBinary), value);
2915
    }
2916

    
2917
    @Override
2918
    public ExpressionBuilder set(Value value) {
2919
        this.value = value;
2920
        return this;
2921
    }
2922

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

    
2933
    @Override
2934
    public ExpressionBuilder or(Value value) {
2935
        if (this.value == null) {
2936
            return this.set(value);
2937
        }
2938
        BinaryOperator operator = binaryOperator("OR", config.getString(Config.operator_OR), this.value, value);
2939
        this.value = operator;
2940
        return this;
2941
    }
2942

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

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

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

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

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

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

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

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

    
2983
    @Override
2984
    public Function ST_GeomFromEWKB(Value geom, Value crs) {
2985
        return builtin_function("ST_GeomFromEWKB", config.getString(Config.ST_GeomFromEWKB), geom, crs);
2986
    }
2987

    
2988
    @Override
2989
    public Function ST_Simplify(Value geom, Value tolerance) {
2990
        return builtin_function("ST_Simplify", config.getString(Config.ST_Simplify), tolerance);
2991
    }
2992

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

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

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

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

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

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

    
3023
    @Override
3024
    public Function ST_Touches(Value geom1, Value geom2) {
3025
        return builtin_function("ST_Touches", config.getString(Config.ST_Touches), geom1, geom2);
3026
    }
3027

    
3028
    @Override
3029
    public Function ST_Within(Value geom1, Value geom2) {
3030
        return builtin_function("ST_Within", config.getString(Config.ST_Within), geom1, geom2);
3031
    }
3032

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

    
3038
    @Override
3039
    public Function notIsNull(Value value) {
3040
        return builtin_function("NOT IS NULL", config.getString(Config.notIsNull), value);
3041
    }
3042

    
3043
    @Override
3044
    public Function not(Value value) {
3045
        return builtin_function("NOT", config.getString(Config.operator_not), value);
3046
    }
3047

    
3048
    @Override
3049
    public Function lcase(Value s) {
3050
        return builtin_function("LCASE", config.getString(Config.lcase), s);
3051
    }
3052

    
3053
    @Override
3054
    public Function ucase(Value s) {
3055
        return builtin_function("UCASE", config.getString(Config.ucase), s);
3056
    }
3057

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

    
3063
    @Override
3064
    public BinaryOperator or(Value leftOperand, Value rightOperand) {
3065
        return binaryOperator("OR", config.getString(Config.operator_OR), leftOperand, rightOperand);
3066
    }
3067

    
3068
    @Override
3069
    public BinaryOperator eq(Value leftOperand, Value rightOperand) {
3070
        return binaryOperator("=", config.getString(Config.operator_EQ), leftOperand, rightOperand);
3071
    }
3072

    
3073
    @Override
3074
    public BinaryOperator ne(Value leftOperand, Value rightOperand) {
3075
        return binaryOperator("<>", config.getString(Config.operator_NE), leftOperand, rightOperand);
3076
    }
3077

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

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

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

    
3093
    @Override
3094
    public BinaryOperator le(Value op1, Value op2) {
3095
        return binaryOperator("<=", config.getString(Config.operator_LE), op1, op2);
3096
    }
3097

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

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

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

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

    
3118
    @Override
3119
    public BinaryOperator mult(Value op1, Value op2) {
3120
        return binaryOperator("MULT", config.getString(Config.operator_mult), op1, op2);
3121
    }
3122

    
3123
    @Override
3124
    public BinaryOperator div(Value op1, Value op2) {
3125
        return binaryOperator("DIV", config.getString(Config.operator_div), op1, op2);
3126
    }
3127

    
3128
    @Override
3129
    public BinaryOperator concat(Value op1, Value op2) {
3130
        return binaryOperator("CONCAT", config.getString(Config.operator_concat), op1, op2);
3131
    }
3132
 
3133
    @Override
3134
    public String default_schema() {
3135
        return config.getString(SQLConfig.default_schema);
3136
    }
3137

    
3138
    @Override
3139
    public boolean supportSchemas() {
3140
        return config.getBoolean(Config.support_schemas);
3141
    }
3142
    
3143
    @Override
3144
    @Deprecated
3145
    public String sqltype(int type, int p, int s) {
3146
        return this.sqltype(type, p, s, Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.UNKNOWN);
3147
    }
3148

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

    
3219
    private static Map<Pair<Integer,Integer>,String> sqlgeometrytypes = null;
3220
    
3221
    @Override
3222
    public Object sqlgeometrytype(int type, int subtype) {
3223
        // Devuelve un Object por que algunos gestores de BBDD utilizan
3224
        // identificadores numericos para el tipo y otros strings.
3225
        // Por defecto vamos a devolver strings.
3226
        if( sqlgeometrytypes==null ) {
3227
            sqlgeometrytypes = new HashMap<>();
3228
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM2D), "POINT");
3229
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM3D), "POINTZ");
3230
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM2DM), "POINTM");
3231
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM3DM), "POINTZM");
3232

    
3233
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM2D), "LINESTRING");
3234
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM3D), "LINESTRINGZ");
3235
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM2DM), "LINESTRINGM");
3236
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM3DM), "LINESTRINGZM");
3237

    
3238
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM2D), "POLYGON");
3239
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM3D), "POLYGONZ");
3240
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM2DM), "POLYGONM");
3241
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM3DM), "POLYGONZM");
3242

    
3243
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM2D), "MULTIPOINT");
3244
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM3D), "MULTIPOINTZ");
3245
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM2DM), "MULTIPOINTM");
3246
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM3DM), "MULTIPOINTZM");
3247

    
3248
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM2D), "MULTILINESTRING");
3249
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM3D), "MULTILINESTRINGZ");
3250
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM2DM), "MULTILINESTRINGM");
3251
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM3DM), "MULTILINESTRINGZM");
3252

    
3253
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM2D), "MULTILINESTRING");
3254
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM3D), "MULTILINESTRINGZ");
3255
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM2DM), "MULTILINESTRINGM");
3256
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTICURVE,Geometry.SUBTYPES.GEOM3DM), "MULTILINESTRINGZM");
3257

    
3258
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM2D), "MULTIPOLYGON");
3259
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM3D), "MULTIPOLYGONZ");
3260
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM2DM), "MULTIPOLYGONM");
3261
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM3DM), "MULTIPOLYGONZM");
3262

    
3263
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM2D), "MULTIPOLYGON");
3264
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM3D), "MULTIPOLYGONZ");
3265
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM2DM), "MULTIPOLYGONM");
3266
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.MULTISURFACE,Geometry.SUBTYPES.GEOM3DM), "MULTIPOLYGONZM");
3267

    
3268
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2D), "GEOMETRY");
3269
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3D), "GEOMETRYZ");
3270
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2DM), "GEOMETRYM");
3271
            sqlgeometrytypes.put( new ImmutablePair<>(Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3DM), "GEOMETRYZM");
3272
        }
3273
        return sqlgeometrytypes.get(new ImmutablePair<>(type,subtype));
3274
    }
3275

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

    
3314
    protected FromBuilder createFromBuilder() {
3315
        return new FromBuilderBase();
3316
    }
3317

    
3318
    protected SelectBuilder createSelectBuilder() {
3319
        return new SelectBuilderBase();
3320
    }
3321

    
3322
    protected UpdateBuilder createUpdateBuilder() {
3323
        return new UpdateBuilderBase();
3324
    }
3325

    
3326
    protected DeleteBuilder createDeleteBuilder() {
3327
        return new DeleteBuilderBase();
3328
    }
3329

    
3330
    protected GrantBuilder createGrantBuilder() {
3331
        return new GrantBuilderBase();
3332
    }
3333

    
3334
    protected GrantRoleBuilder createGrantRoleBuilder(TableNameBuilder table, String role) {
3335
        return new GrantRoleBuilderBase(table, role);
3336
    }
3337
    
3338
    protected DropTableBuilder createDropTableBuilder() {
3339
        return new DropTableBuilderBase();
3340
    }
3341

    
3342
    protected CreateTableBuilder createCreateTableBuilder() {
3343
        return new CreateTableBuilderBase();
3344
    }
3345

    
3346
    protected AlterTableBuilder createAlterTableBuilder() {
3347
        return new AlterTableBuilderBase();
3348
    }
3349

    
3350
    protected InsertBuilder createInsertBuilder() {
3351
        return new InsertBuilderBase();
3352
    }
3353

    
3354
    protected UpdateTableStatisticsBuilder createUpdateTableStatisticsBuilder() {
3355
        return new UpdateTableStatisticsBuilderBase();
3356
    }
3357

    
3358
    protected CreateIndexBuilder createCreateIndexBuilder() {
3359
        return new CreateIndexBuilderBase();
3360
    }
3361
    
3362
    @Override
3363
    public SelectBuilder select() {
3364
        if (this.select == null) {
3365
            this.select = this.createSelectBuilder();
3366
        }
3367
        return this.select;
3368
    }
3369

    
3370
    @Override
3371
    public UpdateBuilder update() {
3372
        if (this.update == null) {
3373
            this.update = this.createUpdateBuilder();
3374
        }
3375
        return this.update;
3376
    }
3377

    
3378
    @Override
3379
    public UpdateTableStatisticsBuilder update_table_statistics() {
3380
        if (this.update_table_statistics == null) {
3381
            this.update_table_statistics = this.createUpdateTableStatisticsBuilder();
3382
        }
3383
        return this.update_table_statistics;
3384
    }
3385

    
3386
    @Override
3387
    public DropTableBuilder drop_table() {
3388
        if (this.drop_table == null) {
3389
            this.drop_table = this.createDropTableBuilder();
3390
        }
3391
        return this.drop_table;
3392
    }
3393

    
3394
    @Override
3395
    public CreateIndexBuilder create_index() {
3396
        if (this.create_index == null) {
3397
            this.create_index = this.createCreateIndexBuilder();
3398
        }
3399
        return this.create_index;
3400
    }
3401

    
3402
    
3403
    @Override
3404
    public DeleteBuilder delete() {
3405
        if (this.delete == null) {
3406
            this.delete = this.createDeleteBuilder();
3407
        }
3408
        return this.delete;
3409
    }
3410

    
3411
    @Override
3412
    public InsertBuilder insert() {
3413
        if (this.insert == null) {
3414
            this.insert = this.createInsertBuilder();
3415
        }
3416
        return this.insert;
3417
    }
3418

    
3419
    @Override
3420
    public AlterTableBuilder alter_table() {
3421
        if (this.alter_table == null) {
3422
            this.alter_table = this.createAlterTableBuilder();
3423
        }
3424
        return this.alter_table;
3425
    }
3426

    
3427
    @Override
3428
    public CreateTableBuilder create_table() {
3429
        if (this.create_table == null) {
3430
            this.create_table = this.createCreateTableBuilder();
3431
        }
3432
        return this.create_table;
3433
    }
3434

    
3435
    @Override
3436
    public GrantBuilder grant() {
3437
        if (this.grant == null) {
3438
            this.grant = this.createGrantBuilder();
3439
        }
3440
        return this.grant;
3441
    }
3442

    
3443
    @Override
3444
    public void accept(Visitor visitor, VisitorFilter filter) {
3445
        if (this.select != null) {
3446
            this.select.accept(visitor, filter);
3447
        }
3448
        if (this.update != null) {
3449
            this.update.accept(visitor, filter);
3450
        }
3451
        if (this.insert != null) {
3452
            this.insert.accept(visitor, filter);
3453
        }
3454
        if (this.delete != null) {
3455
            this.delete.accept(visitor, filter);
3456
        }
3457
        if (this.alter_table != null) {
3458
            this.alter_table.accept(visitor, filter);
3459
        }
3460
        if (this.create_table != null) {
3461
            this.create_table.accept(visitor, filter);
3462
        }
3463
        if (this.drop_table != null) {
3464
            this.drop_table.accept(visitor, filter);
3465
        }
3466
//        if( this.value == null) {
3467
//            return;
3468
//        }
3469
//        this.value.accept(visitor, filter);
3470
    }
3471

    
3472
    
3473
    @Override
3474
    public String toString() {
3475
        if (this.select != null) {
3476
            return this.select.toString();
3477
        }
3478
        if (this.update != null) {
3479
            return this.update.toString();
3480
        }
3481
        if (this.insert != null) {
3482
            return this.insert.toString();
3483
        }
3484
        if (this.delete != null) {
3485
            return this.delete.toString();
3486
        }
3487
        if (this.alter_table != null) {
3488
            return this.alter_table.toString();
3489
        }
3490
        if (this.create_table != null) {
3491
            return this.create_table.toString();
3492
        }
3493
        if (this.drop_table != null) {
3494
            return this.drop_table.toString();
3495
        }
3496
        if (this.update_table_statistics != null) {
3497
            return this.update_table_statistics.toString();
3498
        }
3499
        if ( this.value != null ) {
3500
            return this.value.toString();
3501
        }
3502
        return ""; 
3503
    }
3504

    
3505
    @Override
3506
    public Function ST_UnionAggregate(Value geom) {
3507
        return builtin_function("ST_UnionAggregate", config.getString(SQLConfig.ST_UnionAggregate), geom);
3508
    }
3509

    
3510
    @Override
3511
    public Function ST_ExtentAggregate(Value geom) {
3512
        return builtin_function("ST_ExtentAggregate", config.getString(SQLConfig.ST_ExtentAggregate), geom);
3513
    }
3514

    
3515
    @Override
3516
    public CountBuilder count() {
3517
        return new CountBuilderBase();
3518
    }
3519

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

    
3557

    
3558
    public Function iif(Value condition, Value iftrue, Value iffalse) {
3559
        return builtin_function("IIF", config.getString(Config.iif), condition, iftrue, iffalse);
3560
    }
3561

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

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