Revision 47779 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

View differences:

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

  
3
import java.text.MessageFormat;
4
import java.util.ArrayList;
5
import java.util.Collections;
6
import java.util.HashMap;
7
import java.util.HashSet;
8
import java.util.List;
9
import java.util.Map;
10
import java.util.Objects;
11
import java.util.Set;
12
import org.apache.commons.lang3.StringUtils;
13
import org.apache.commons.lang3.tuple.ImmutablePair;
14
import org.apache.commons.lang3.tuple.Pair;
15
import org.cresques.cts.IProjection;
16
import org.gvsig.expressionevaluator.ExpressionBuilder;
17
import org.gvsig.expressionevaluator.ExpressionBuilder.AbstractValue;
18
import org.gvsig.expressionevaluator.ExpressionBuilder.ClassVisitorFilter;
19
import static org.gvsig.expressionevaluator.ExpressionBuilder.PARAMETER_TYPE_CONSTANT;
20
import static org.gvsig.expressionevaluator.ExpressionBuilder.PARAMETER_TYPE_VARIABLE;
21
import org.gvsig.expressionevaluator.ExpressionBuilder.Parameter;
22
import static org.gvsig.expressionevaluator.ExpressionBuilder.VALUE_NULL;
23
import org.gvsig.expressionevaluator.ExpressionBuilder.Value;
24
import org.gvsig.expressionevaluator.ExpressionBuilder.Variable;
25
import org.gvsig.expressionevaluator.ExpressionBuilder.Visitable;
26
import org.gvsig.expressionevaluator.ExpressionBuilder.Visitor;
27
import org.gvsig.expressionevaluator.ExpressionBuilder.VisitorFilter;
28
import org.gvsig.expressionevaluator.Formatter;
29
import org.gvsig.expressionevaluator.GeometryExpressionBuilder;
30
import org.gvsig.expressionevaluator.GeometryExpressionBuilderHelper.GeometrySupportType;
31
import org.gvsig.expressionevaluator.GeometryExpressionEvaluatorLocator;
32
import org.gvsig.fmap.dal.DataManager;
33
import org.gvsig.fmap.dal.DataStoreParameters;
34
import org.gvsig.fmap.dal.DataTypes;
35
import org.gvsig.fmap.dal.SQLBuilder;
36
import org.gvsig.fmap.dal.SQLBuilder.AlterTableBuilder;
37
import org.gvsig.fmap.dal.SQLBuilder.CreateTableBuilder;
38
import org.gvsig.fmap.dal.SQLBuilder.DeleteBuilder;
39
import org.gvsig.fmap.dal.SQLBuilder.DropTableBuilder;
40
import org.gvsig.fmap.dal.SQLBuilder.FromBuilder;
41
import org.gvsig.fmap.dal.SQLBuilder.GrantBuilder;
42
import org.gvsig.fmap.dal.SQLBuilder.InsertBuilder;
43
import org.gvsig.fmap.dal.SQLBuilder.InsertColumnBuilder;
44
import org.gvsig.fmap.dal.SQLBuilder.OrderByBuilder;
45
import org.gvsig.fmap.dal.SQLBuilder.Privilege;
46
import org.gvsig.fmap.dal.SQLBuilder.SelectBuilder;
47
import org.gvsig.fmap.dal.SQLBuilder.SelectColumnBuilder;
48
import org.gvsig.fmap.dal.SQLBuilder.TableNameBuilder;
49
import org.gvsig.fmap.dal.SQLBuilder.UpdateBuilder;
50
import org.gvsig.fmap.dal.SQLBuilder.UpdateColumnBuilder;
51
import org.gvsig.fmap.dal.SQLBuilder.UpdateTableStatisticsBuilder;
52
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
53
import org.gvsig.fmap.dal.feature.FeatureType;
54
import org.gvsig.fmap.geom.Geometry;
55
import org.gvsig.fmap.geom.GeometryUtils;
56
import org.gvsig.fmap.geom.primitive.Envelope;
57
import org.gvsig.tools.dataTypes.DataType;
58
import org.gvsig.tools.dynobject.Tags;
59
import org.gvsig.tools.lang.CloneableUtils;
60
import org.gvsig.tools.util.Bitmask;
61
import org.gvsig.tools.util.PropertiesSupport;
62
import org.slf4j.Logger;
63
import org.slf4j.LoggerFactory;
64

  
65
@SuppressWarnings("UseSpecificCatch")
66
public class SQLBuilderBase implements SQLBuilder {
67

  
68
    protected static final Logger LOGGER = LoggerFactory.getLogger(SQLBuilderBase.class);
69

  
70
    protected SelectBuilder select;
71
    protected UpdateBuilder update;
72
    protected InsertBuilder insert;
73
    protected DeleteBuilder delete;
74
    protected AlterTableBuilder alter_table;
75
    protected CreateTableBuilder create_table;
76
    protected GrantBuilder grant;
77
    protected DropTableBuilder drop_table;
78
    protected UpdateTableStatisticsBuilder update_table_statistics;
79
    protected CreateIndexBuilder create_index;
80
    protected DropIndexBuilder drop_index;
81
    protected TableNameBuilder table_name;
82

  
83
    protected abstract class AbstractStatementPart extends AbstractValue {
84
        
85
    }
86

  
87
    protected abstract class AbstractStatement extends AbstractStatementPart {
88
        @Override
89
        public Value clone() throws CloneNotSupportedException {
90
            throw new CloneNotSupportedException();
91
        }
92
    }
93

  
94
    protected class ColumnDescriptorBase implements ColumnDescriptor {
95

  
96
        private String name;
97
        private int type;
98
        private int size;
99
        private int precision;
100
        private int scale;
101
        private boolean isPk;
102
        private boolean _allowNulls;
103
        private boolean _allowIndexDuplicateds;
104
        private boolean _isAutomatic;
105
        private Object defaultValue;
106
        private int geom_type;
107
        private int geom_subtype;
108
        private Object geom_srsdbcode;
109
        private Envelope tablebbox;
110
        private boolean _isIndexed;
111
        private DataStoreParameters parameters = null;
112

  
113
        public ColumnDescriptorBase(String name, int type, Object defaultValue) {
114
            this.name = name;
115
            this.type = type;
116
            this.size = -1;
117
            this.precision = -1;
118
            this.scale = -1;
119
            this.isPk = false;
120
            this._allowNulls = true;
121
            this._isAutomatic = false;
122
            this.defaultValue = defaultValue;
123
            this.geom_type = Geometry.TYPES.GEOMETRY;
124
            this.geom_subtype = Geometry.SUBTYPES.GEOM2D;
125
            this.geom_srsdbcode = null;
126
            this.tablebbox = null;
127
            this._isIndexed = false;
128
            this._allowIndexDuplicateds = true;
129
        }
130

  
131
        public ColumnDescriptorBase(String name, int type, int size, int precision, int scale, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue) {
132
            this(name, type, size, precision, scale, isPk, isIndexed, allowNulls, isAutomatic, defaultValue, true);
133
        }
134
        
135
        public ColumnDescriptorBase(String name, int type, int size, int precision, int scale, boolean isPk, boolean isIndexed, boolean allowNulls, boolean isAutomatic, Object defaultValue, boolean allowIndexDuplicateds) {
136
            this.name = name;
137
            this.type = type;
138
            this.size = size;
139
            this.precision = precision;
140
            this.scale = scale;
141
            this.isPk = isPk;
142
            this._allowNulls = allowNulls;
143
            this._isAutomatic = isAutomatic;
144
            this.defaultValue = defaultValue;
145
            this.geom_type = Geometry.TYPES.GEOMETRY;
146
            this.geom_subtype = Geometry.SUBTYPES.GEOM2D;
147
            this.geom_srsdbcode = null;
148
            this.tablebbox = null;
149
            this._isIndexed = isIndexed;
150
            this._allowIndexDuplicateds = allowIndexDuplicateds;
151
        }
152

  
153
        public ColumnDescriptorBase(String name, int geom_type, int geom_subtype, IProjection proj, boolean isIndexed, boolean allowNulls) {
154
            this.name = name;
155
            this.type = DataTypes.GEOMETRY;
156
            this.size = 0;
157
            this.precision = 0;
158
            this.scale = 0;
159
            this.isPk = false;
160
            this._allowNulls = allowNulls;
161
            this._isAutomatic = false;
162
            this.defaultValue = null;
163
            this.geom_type = geom_type;
164
            this.geom_subtype = geom_subtype;
165
            this.geom_srsdbcode = srs_id(proj);
166
            this.tablebbox = null;
167
            this._isIndexed = isIndexed;
168
            this._allowIndexDuplicateds = true;
169
        }
170

  
171
        public ColumnDescriptorBase(String name, int geom_type, int geom_subtype, Object srsdbcode, boolean isIndexed, boolean allowNulls) {
172
            this.name = name;
173
            this.type = DataTypes.GEOMETRY;
174
            this.size = 0;
175
            this.precision = 0;
176
            this.scale = 0;
177
            this.isPk = false;
178
            this._allowNulls = allowNulls;
179
            this._isAutomatic = false;
180
            this.defaultValue = null;
181
            this.geom_type = geom_type;
182
            this.geom_subtype = geom_subtype;
183
            this.geom_srsdbcode = srsdbcode;
184
            this.tablebbox = null;
185
            this._isIndexed = isIndexed;
186
            this._allowIndexDuplicateds = true;
187
        }
188

  
189
        private ColumnDescriptorBase(FeatureAttributeDescriptor fad) {
190
            this(fad.getName(), fad.getType(), fad.getDefaultValue());
191
            this.precision = fad.getPrecision();
192
            this.size = fad.getSize();
193
            this.scale = fad.getScale();
194
            this.isPk = fad.isPrimaryKey();
195
            this._allowNulls = fad.allowNull();
196
            this._isAutomatic = fad.isAutomatic();
197
            this._isIndexed = fad.isIndexed();
198
            this._allowIndexDuplicateds = fad.allowIndexDuplicateds();
199

  
200
            if (fad.getType() == org.gvsig.fmap.geom.DataTypes.GEOMETRY) {
201
                this.geom_type = fad.getGeomType().getType();
202
                this.geom_subtype = fad.getGeomType().getSubType();
203
                this.geom_srsdbcode =  srs_id(fad.getSRS());
204
                this.tablebbox = null;
205
                Tags tags = fad.getTags();
206
                String s = tags.getString("tablebbox", null);
207
                if( StringUtils.isNotBlank(s) ) {
208
                    try {
209
                        Geometry g = GeometryUtils.createFrom(s);
210
                        if( g!=null ) {
211
                            this.tablebbox = g.getEnvelope();
212
                        }
213
                    } catch(Exception ex) {
214
                        LOGGER.warn("Can't parse tablebbox for column '"+s+"'.",ex);
215
                    }
216
                }
217
            }
218
        }
219
    
220

  
221
        @Override
222
        public String getName() {
223
            return this.name;
224
        }
225

  
226
        @Override
227
        public void setName(String name) {
228
            this.name = name;
229
        }
230

  
231
        @Override
232
        public int getType() {
233
            return this.type;
234
        }
235

  
236
        @Override
237
        public void setType(int type) {
238
            this.type = type;
239
        }
240

  
241
        @Override
242
        public int getPrecision() {
243
            return precision;
244
        }
245

  
246
        @Override
247
        public void setPrecision(int precision) {
248
            this.precision = precision;
249
        }
250

  
251
        @Override
252
        public int getScale() {
253
            return scale;
254
        }
255

  
256
        @Override
257
        public void setScale(int scale) {
258
            this.scale = scale;
259
        }
260

  
261
        @Override
262
        public int getSize() {
263
            return size;
264
        }
265

  
266
        @Override
267
        public void setSize(int size) {
268
            this.size = size;
269
        }
270

  
271
        @Override
272
        public boolean isPrimaryKey() {
273
            return isPk;
274
        }
275

  
276
        @Override
277
        public void setIsPrimaryKey(boolean isPk) {
278
            this.isPk = isPk;
279
        }
280

  
281
        @Override
282
        public boolean allowNulls() {
283
            return _allowNulls;
284
        }
285

  
286
        @Override
287
        public void setAllowNulls(boolean allowNulls) {
288
            this._allowNulls = allowNulls;
289
        }
290

  
291
        @Override
292
        public boolean isAutomatic() {
293
            return _isAutomatic;
294
        }
295

  
296
        @Override
297
        public boolean isIndexed() {
298
            return _isIndexed;
299
        }
300

  
301
        @Override
302
        public void setIsAutomatic(boolean isAutomatic) {
303
            this._isAutomatic = isAutomatic;
304
        }
305

  
306
        @Override
307
        public Object getDefaultValue() {
308
            return defaultValue;
309
        }
310

  
311
        @Override
312
        public void setDefaultValue(Object defaultValue) {
313
            this.defaultValue = defaultValue;
314
        }
315

  
316
        @Override
317
        public int getGeometryType() {
318
            return geom_type;
319
        }
320

  
321
        @Override
322
        public void setGeometryType(int geom_type) {
323
            this.geom_type = geom_type;
324
        }
325

  
326
        @Override
327
        public int getGeometrySubtype() {
328
            return geom_subtype;
329
        }
330

  
331
        @Override
332
        public void setGeometrySubtype(int geom_subtype) {
333
            this.geom_subtype = geom_subtype;
334
        }
335

  
336
        @Override
337
        public Object getGeometrySRSId() {
338
            return geom_srsdbcode;
339
        }
340

  
341
        @Override
342
        public void setGeometrySRSId(Object geom_srsid) {
343
            this.geom_srsdbcode = geom_srsid;
344
        }
345

  
346
        @Override
347
        public boolean isGeometry() {
348
            return this.type == DataTypes.GEOMETRY;
349
        }
350

  
351
        private void setStoreParameters(DataStoreParameters parameters) {
352
            this.parameters = parameters;
353
        }
354

  
355
        @Override
356
        public DataStoreParameters getStoreParameters() {
357
            return this.parameters;
358
        }
359
        
360
        public Envelope getTableBBox() {
361
            return this.tablebbox;
362
        }
363
        
364
        public void setTableBBox(Envelope bbox) {
365
            this.tablebbox = bbox;
366
        }
367

  
368
        @Override
369
        public boolean allowIndexDuplicateds() {
370
            return this._allowIndexDuplicateds;
371
        }
372

  
373
        @Override
374
        public void setAllowIndexDuplicateds(boolean allowIndexDuplicateds) {
375
            this._allowIndexDuplicateds = allowIndexDuplicateds;
376
        }
377
        
378
    }
379

  
380
    public class ColumnBase extends AbstractValue implements Column {
381

  
382
        private final String name;
383
        private TableNameBuilder table;
384

  
385
        public ColumnBase(TableNameBuilder table, String name) {
386
            this.name = name;
387
            this.table = table;
388
        }
389
        
390
        @Override
391
        public ColumnBase clone() throws CloneNotSupportedException {
392
            ColumnBase other = (ColumnBase) super.clone();
393
            other.table = (TableNameBuilder) org.gvsig.tools.lang.Cloneable.cloneQuietly(table);
394
            return other;
395
        }
396

  
397

  
398
        @Override
399
        public String name() {
400
            return this.name;
401
        }
402

  
403
        @Override
404
        public TableNameBuilder table() {
405
            return this.table;
406
        }
407

  
408
        @Override
409
        public TableNameBuilder table(TableNameBuilder table) {
410
            this.table = table;
411
            return this.table;
412
        }
413

  
414
        @Override
415
        public String toString() {
416
            return this.toString(formatter());
417
        }
418
        
419
        @Override
420
        public String toString(Formatter<Value> formatter) {
421
            if( formatter!=null && formatter.canApply(this) ) {
422
                return formatter.format(this);
423
            }
424
            if( this.table==null ) {
425
                return as_identifier(this.name);
426
            }
427
            return this.table.toString(formatter) + "." + as_identifier(this.name);
428
        }
429

  
430
        @Override
431
        public int compareTo(Variable o) {
432
            return this.name.compareTo(o.name());
433
        }
434

  
435
        @Override
436
        public boolean equals(Object obj) {
437
            if (!(obj instanceof Variable)) {
438
                return false;
439
            }
440
            return StringUtils.equals(this.toString(), ((Variable) obj).toString());
441
        }
442

  
443
        @Override
444
        public int hashCode() {
445
            int hash = 7;
446
            hash = 37 * hash + Objects.hashCode(this.toString());
447
            return hash;
448
        }
449

  
450
        @Override
451
        public void setProperty(String name, Object value) {
452
            super.setProperty(name, value);
453
            if(this.table != null){
454
                this.table.setProperty(name, value);
455
            }
456
        }
457
        
458
        
459
    }
460

  
461
    public class TableNameBuilderBase
462
            extends AbstractStatementPart
463
            implements TableNameBuilder {
464

  
465
        public String tableName;
466
        public String schemaName;
467
        private String databaseName;
468

  
469
        public TableNameBuilderBase() {
470
        }
471
        
472
        @Override
473
        public void accept(Visitor visitor, VisitorFilter filter) {
474
            if (filter==null || filter.accept(this)) {
475
                visitor.visit(this);
476
            }
477
        }
478

  
479
        @Override
480
        public TableNameBuilder database(String name) {
481
            this.databaseName = name;
482
            return this;
483
        }
484

  
485
        @Override
486
        public TableNameBuilder schema(String name) {
487
            if (support_schemas()) {
488
                this.schemaName = name;
489
            }
490
            return this;
491
        }
492

  
493
        @Override
494
        public TableNameBuilder name(String name) {
495
            this.tableName = name;
496
            return this;
497
        }
498

  
499
        @Override
500
        public String getDatabase() {
501
            return this.databaseName;
502
        }
503

  
504
        @Override
505
        public String getSchema() {
506
            return this.schemaName;
507
        }
508

  
509
        @Override
510
        public String getName() {
511
            return this.tableName;
512
        }
513

  
514
        @Override
515
        public boolean has_schema() {
516
            if (!support_schemas()) {
517
                return false;
518
            }
519
            return StringUtils.isNotBlank(this.schemaName);
520
        }
521

  
522
        @Override
523
        public boolean has_name() {
524
            return StringUtils.isNotBlank(this.tableName);
525
        }
526

  
527
        @Override
528
        public boolean has_database() {
529
            return StringUtils.isNotBlank(this.databaseName);
530
        }
531

  
532
        @Override
533
        public boolean isEmpty() {
534
            return !this.has_database() && !this.has_schema() && !this.has_name();
535
        }
536

  
537
        @Override
538
        public String toString() {
539
            return this.toString(formatter());
540
        }
541

  
542
        @Override
543
        public String toString(Formatter<Value> formatter) {
544
            if (formatter!=null && formatter.canApply(this)) {
545
                return formatter.format(this);
546
            }
547
            if (this.has_database()) {
548
                if (this.has_schema()) {
549
                    return as_identifier(this.databaseName) + "."
550
                            + as_identifier(this.schemaName) + "."
551
                            + as_identifier(this.tableName);
552
                }
553
//                return as_identifier(this.databaseName) + "."
554
//                        + as_identifier(this.tableName);
555
            } else {
556
                if (this.has_schema()) {
557
                    return as_identifier(this.schemaName) + "."
558
                            + as_identifier(this.tableName);
559
                }
560
            }
561
            return as_identifier(this.tableName);
562
        }
563

  
564
        @Override
565
        public boolean equals(Object obj) {
566
            if( obj==null || !(obj instanceof TableNameBuilder) ) {
567
                return false;
568
            }
569
            TableNameBuilder other = (TableNameBuilder) obj;
570
            
571
            if (this.has_database() != other.has_database()) {
572
                return false;
573
            }
574
            String thisSchema = null;
575
            String otherSchema = null;
576
            if(support_schemas()) {
577
                thisSchema = this.schemaName;
578
                if (StringUtils.isBlank(thisSchema)) {
579
                    thisSchema = default_schema();
580
                }
581
                otherSchema = other.getSchema();
582
                if (StringUtils.isBlank(otherSchema)) {
583
                    otherSchema = default_schema();
584
                }
585
            }
586
            if (this.has_database()) {
587
                    return StringUtils.equals(this.databaseName,other.getDatabase()) &&
588
                           StringUtils.equals(thisSchema, otherSchema) &&
589
                           StringUtils.equals(this.tableName,other.getName());
590
            } else {
591
                    return StringUtils.equals(thisSchema, otherSchema) &&
592
                           StringUtils.equals(this.tableName,other.getName());
593
            }
594
        }
595

  
596
        @Override
597
        public int hashCode() {
598
            int hash = 7;
599
            hash = 37 * hash + Objects.hashCode(this.toString());
600
            return hash;
601
        }
602

  
603
    }
604

  
605
    public class CountBuilderBase
606
            extends AbstractStatementPart
607
            implements CountBuilder {
608

  
609
        protected Value value;
610
        protected boolean distinct;
611
        protected boolean all;
612

  
613
        public CountBuilderBase() {
614
            this.value = null;
615
            this.distinct = false;
616
            this.all = false;
617
        }
618
        
619
        @Override
620
        public CountBuilderBase clone() throws CloneNotSupportedException {
621
            CountBuilderBase other = (CountBuilderBase) super.clone();
622
            other.value = (Value) org.gvsig.tools.lang.Cloneable.cloneQuietly(value);
623
            return other;
624
        }
625
        
626
        @Override
627
        public CountBuilder all() {
628
            this.all = true;
629
            return this;
630
        }
631

  
632
        @Override
633
        public CountBuilder column(Value value) {
634
            this.value = value;
635
            return this;
636
        }
637

  
638
        @Override
639
        public CountBuilder distinct() {
640
            this.distinct = true;
641
            return this;
642
        }
643

  
644
        @Override
645
        public String toString() {
646
            return this.toString(formatter());
647
        }
648

  
649
        @Override
650
        public String toString(Formatter formatter) {
651
            if (formatter!=null && formatter.canApply(this)) {
652
                return formatter.format(this);
653
            }
654
            if (this.all) {
655
                return "COUNT(*)";
656
            }
657
            if (this.distinct) {
658
                return MessageFormat.format(
659
                        "COUNT(DISTINCT {0})",
660
                        value.toString(formatter)
661
                );
662
            }
663
            return MessageFormat.format(
664
                    "COUNT({0})",
665
                    value.toString(formatter)
666
            );
667
        }
668

  
669
    }
670

  
671
    protected class JoinBase 
672
            extends AbstractStatementPart
673
            implements JoinBuilder 
674
        {
675
        protected String type;
676
        protected TableNameBuilder table;
677
        protected Value expression;
678
        
679
        public JoinBase(String type, TableNameBuilder table, Value expression) {
680
            this.type = type;
681
            this.table = table;
682
            this.expression = expression;
683
        }
684
        
685
        @Override
686
        public JoinBase clone() throws CloneNotSupportedException {
687
            JoinBase other = (JoinBase) super.clone();
688
            other.table = (TableNameBuilder) org.gvsig.tools.lang.Cloneable.cloneQuietly(table);
689
            other.expression = (Value) org.gvsig.tools.lang.Cloneable.cloneQuietly(expression);
690
            return other;
691
        }
692

  
693
        @Override
694
        public String toString() {
695
            return this.toString(formatter());
696
        }
697

  
698
        @Override
699
        public String toString(Formatter<Value> formatter) {
700
            if (formatter!=null && formatter.canApply(this)) {
701
                return formatter.format(this);
702
            }
703
            StringBuilder builder = new StringBuilder();
704
            // INNER JOIN Customers ON Orders.CustomerID = Customers.CustomerID
705
            builder.append(this.type.toUpperCase());
706
            builder.append(" JOIN ");
707
            builder.append(this.table.toString(formatter));
708
            builder.append(" ON ");
709
            builder.append(this.expression.toString(formatter));
710
            return builder.toString();
711
        }
712
        
713
        @Override
714
        public TableNameBuilder getTable() {
715
            return this.table;
716
        }
717
        
718
        @Override
719
        public String getType() {
720
            return this.type;
721
        }
722

  
723
        @Override
724
        public Value getCondition() {
725
            return this.expression;
726
        }
727
        
728
        @Override
729
        public void accept(Visitor visitor, VisitorFilter filter) {
730
            boolean visitChildren = true;
731
            if (filter==null || filter.accept(this)) {
732
                visitor.visit(this);
733
            } else {
734
                visitChildren = !filter.skipChildren();
735
            }
736
            if(visitChildren){
737
                if (this.expression != null) {
738
                    this.expression.accept(visitor, filter);
739
                }
740
            }
741
        }
742

  
743
    }
744
    
745
    public class FromBuilderBase
746
            extends AbstractStatementPart
747
            implements FromBuilder {
748

  
749
        protected TableNameBuilder tableName;
750
        protected String subquery;
751
        protected String passthrough;
752
        protected List<JoinBuilder> joins;
753

  
754
        public FromBuilderBase() {
755
            this.tableName = null;
756
            this.subquery = null;
757
            this.passthrough = null;
758
            this.joins = null;
759
        }
760
        
761
        @Override
762
        public FromBuilderBase clone() throws CloneNotSupportedException {
763
            FromBuilderBase other = (FromBuilderBase) super.clone();
764
            other.tableName = (TableNameBuilder) org.gvsig.tools.lang.Cloneable.cloneQuietly(tableName);
765
            if (joins!=null) {
766
                for (int i = 0; i < joins.size(); i++) {
767
                    other.joins.set(i, (JoinBase) joins.get(i).clone());
768
                }
769
            }
770
            return other;
771
        }
772

  
773
        @Override
774
        public FromBuilder left_join(TableNameBuilder table, Value expression) {
775
            JoinBase join = createJoin("LEFT", table, expression);
776
            if( this.joins==null ) {
777
                this.joins = new ArrayList<>();
778
            }
779
            this.joins.add(join);
780
            return this;
781
        }
782
        
783
        @Override
784
        public TableNameBuilder table() {
785
            if (tableName == null) {
786
                this.tableName = createTableNameBuilder();
787
            }
788
            return this.tableName;
789
        }
790

  
791
        @Override
792
        public void accept(Visitor visitor, VisitorFilter filter) {
793
            boolean visitChildren = true;
794
            if (filter==null || filter.accept(this)) {
795
                visitor.visit(this);
796
            } else {
797
                visitChildren = !filter.skipChildren();
798
            }
799
            if(visitChildren){
800
                if (this.tableName != null) {
801
                    this.tableName.accept(visitor, filter);
802
                }
803
                if(this.joins != null) {
804
                    for (JoinBuilder join : joins) {
805
                        join.accept(visitor, filter);
806
                    }
807
                }
808
            }
809
        }
810

  
811
        @Override
812
        public FromBuilder custom(String passthrough) {
813
            this.passthrough = passthrough;
814
            return this;
815
        }
816

  
817
        @Override
818
        public FromBuilder subquery(String subquery) {
819
            this.subquery = subquery;
820
            return this;
821
        }
822

  
823
        @Override
824
        public String toString() {
825
            return this.toString(formatter());
826
        }
827

  
828
        @Override
829
        public String toString(Formatter<Value> formatter) {
830
            if (formatter!=null && formatter.canApply(this)) {
831
                return formatter.format(this);
832
            }
833
            if (!StringUtils.isEmpty(passthrough)) {
834
                return passthrough;
835
            }
836
            if (!StringUtils.isEmpty(subquery)) {
837
                return "( " + this.subquery + ") AS _subquery_alias_ ";
838
            }
839
            if( this.joins==null || this.joins.isEmpty() ) {
840
                return this.tableName.toString(formatter);
841
            }
842
            StringBuilder builder = new StringBuilder();
843
            builder.append(this.tableName.toString(formatter));
844
            for (JoinBuilder join : this.joins) {
845
                builder.append(" ");
846
                builder.append(join.toString(formatter));
847
            }
848
            return builder.toString();
849
        }
850

  
851
        @Override
852
        public List<JoinBuilder> getJoins() {
853
            return this.joins;
854
        }
855

  
856
    }
857

  
858
    public class SelectColumnBuilderBase
859
            extends AbstractStatementPart
860
            implements SelectColumnBuilder {
861

  
862
        protected Column name = null;
863
        protected String alias = null;
864
        protected Value value = null;
865
        protected boolean asGeometry = false;
866
        protected TableNameBuilder table;
867
        protected SQLBuilder sqlbuilder;
868
        
869
        public SelectColumnBuilderBase(SQLBuilder sqlbuilder) {
870
            this.sqlbuilder = sqlbuilder;
871
        }
872
        
873
        @Override
874
        public SelectColumnBuilderBase clone() throws CloneNotSupportedException {
875
            SelectColumnBuilderBase other = (SelectColumnBuilderBase) super.clone();
876
            other.value = (Value) org.gvsig.tools.lang.Cloneable.cloneQuietly(value);
877
            other.name = (Column) org.gvsig.tools.lang.Cloneable.cloneQuietly(name);
878
            other.table = (TableNameBuilder) org.gvsig.tools.lang.Cloneable.cloneQuietly(table);
879
            return other;
880
        }
881

  
882
        @Override
883
        public void accept(Visitor visitor, VisitorFilter filter) {
884
            boolean visitChildren = true;
885
            if (filter==null || filter.accept(this)) {
886
                visitor.visit(this);
887
            } else {
888
                visitChildren = !filter.skipChildren();
889
            }
890
            if(visitChildren){
891
                if (this.value != null) {
892
                    this.value.accept(visitor, filter);
893
                } else if (this.name != null) {
894
                    this.name.accept(visitor, filter);
895
                }
896
            }
897
        }
898

  
899
        @Override
900
        public void replace(Value target, Value replacement) {
901
            if (this.name!=null ) {
902
                if( this.name == target) {
903
                    if(replacement == null){
904
                        this.name = null;
905
                    } else if(replacement instanceof Column){
906
                        this.name = (Column) replacement;
907
                    } else if(replacement instanceof Variable){
908
                        this.name = new ColumnBase(this.table, ((Variable) replacement).name());
909
                    } else {
910
                        this.value = replacement;
911
                    }
912
                }
913
            }
914
            if( this.value!=null ) {
915
                if (this.value == target) {
916
                    this.value = replacement;
917
                } else {
918
                    this.value.replace(target, replacement);
919
                }
920
            }
921
        }
922

  
923
        @Override
924
        public SelectColumnBuilder name(String name) {
925
            return this.name(this.table, name);
926
        }
927

  
928
        @Override
929
        public SelectColumnBuilder name(TableNameBuilder table, String name) {
930
            String quote = quote_for_identifiers();
931
            if (name.startsWith(quote)) {
932
                // Remove quotes
933
                name = name.substring(1, name.length() - 1);
934
            }
935
            this.table = table;
936
            this.name = new ColumnBase(this.table, name);
937
            this.value = null;
938
            this.asGeometry = false;
939
            return this;
940
        }
941
        
942
        public SelectColumnBuilder table(TableNameBuilder table) {
943
            this.table = table;
944
            if(this.name != null){
945
                this.name.table(table);
946
            }
947
            return this;
948
        }
949
        
950
        @Override
951
        public SelectColumnBuilder all() {
952
            this.name = null;
953
            this.value = expression().custom("*");
954
            this.asGeometry = false;
955
            return this;
956
        }
957

  
958
        @Override
959
        public SelectColumnBuilder as_geometry() {
960
            this.asGeometry = true;
961
            return this;
962
        }
963

  
964
        @Override
965
        public SelectColumnBuilder value(Value value) {
966
            this.value = value;
967
            return this;
968
        }
969

  
970
        @Override
971
        public SelectColumnBuilder as(String alias) {
972
            this.alias = alias;
973
            return this;
974
        }
975

  
976
        @Override
977
        public String getName() {
978
            if (this.name==null) {
979
                return null;
980
            }
981
            return this.name.name();
982
        }
983

  
984
        @Override
985
        public String getAlias() {
986
            return this.alias;
987
        }
988

  
989
        @Override
990
        public Value getValue() {
991
            return this.value;
992
        }
993

  
994
        @Override
995
        public String toString() {
996
            return this.toString(formatter());
997
        }
998

  
999
        @Override
1000
        public String toString(Formatter<Value> formatter) {
1001
            if (formatter!=null && formatter.canApply(this)) {
1002
                return formatter.format(this);
1003
            }
1004
            StringBuilder builder = new StringBuilder();
1005
            if (this.asGeometry) {
1006
                if(this.value == VALUE_NULL){
1007
                    builder.append(this.value.toString(formatter));
1008
                } else {
1009
                    switch(expression().geometry_support_type()) {
1010
                        case WKB:
1011
                            builder.append(expression().ST_AsBinary(this.name).toString(formatter));
1012
                            break;
1013
                        case EWKB:
1014
                            builder.append(expression().ST_AsEWKB(this.name).toString(formatter));
1015
                            break;
1016
                        case WKT:
1017
                            builder.append(expression().ST_AsText(this.name).toString(formatter));
1018
                            break;
1019
                        case NATIVE:
1020
                            builder.append(as_identifier(this.name.toString(formatter)));
1021
                            break;
1022
                    }
1023
                }
1024
            } else {
1025
                if (this.value == null) {
1026
                    builder.append(this.name.toString(formatter));
1027
                } else {
1028
                    builder.append(this.value.toString(formatter));
1029
                }
1030
            }
1031
            if (this.alias != null) {
1032
                builder.append(" AS ");
1033
                builder.append(as_identifier(this.alias));
1034
            }
1035
            return builder.toString();
1036
        }
1037
        
1038
        @Override
1039
        public boolean isGeometry() {
1040
            return this.asGeometry;
1041
        }
1042
        
1043
        @Override
1044
        public TableNameBuilder getTable() {
1045
            return this.table;
1046
        }
1047
        
1048
        @Override
1049
        public boolean isAggregateFunction() {
1050
            if( this.value == null ) {
1051
                return false;
1052
            }
1053
            if( !(this.value instanceof ExpressionBuilder.Function) ) {
1054
                return false;
1055
            }
1056
            String funcname = ((ExpressionBuilder.Function)this.value).name();
1057
            return this.sqlbuilder.isAggregateFunction(funcname);
1058
        }
1059
    }
1060

  
1061
    public class OrderByBuilderBase
1062
            extends AbstractStatementPart
1063
            implements OrderByBuilder {
1064

  
1065
        protected Value value;
1066
        protected String custom;
1067
        protected boolean ascending;
1068
        protected int nullsMode;
1069

  
1070
        public OrderByBuilderBase() {
1071
            this.ascending = true;
1072
            this.nullsMode = MODE_NULLS_LAST;
1073
        }
1074
        
1075
        @Override
1076
        public OrderByBuilderBase clone() throws CloneNotSupportedException {
1077
            OrderByBuilderBase other = (OrderByBuilderBase) super.clone();
1078
            other.value = (Value) org.gvsig.tools.lang.Cloneable.cloneQuietly(value);
1079
            return other;
1080
        }
1081
        
1082
        @Override
1083
        public void accept(Visitor visitor, VisitorFilter filter) {
1084
            boolean visitChildren = true;
1085
            if (filter==null || filter.accept(this)) {
1086
                visitor.visit(this);
1087
            } else {
1088
                visitChildren = !filter.skipChildren();
1089
            }
1090
            if(visitChildren){
1091
                if (this.value!=null) {
1092
                    this.value.accept(visitor, filter);
1093
                }
1094
            }
1095
        }
1096

  
1097
        @Override
1098
        public OrderByBuilder column(String name) {
1099
            this.value = expression().variable(name);
1100
            return this;
1101
        }
1102
        
1103
        @Override
1104
        public boolean isColumn(String name) {
1105
            if(this.value instanceof ExpressionBuilder.Variable){
1106
                return StringUtils.equalsIgnoreCase(((ExpressionBuilder.Variable)this.value).name(), name);
1107
            }
1108
            return false;
1109
        }
1110
        
1111
        @Override
1112
        public boolean isColumn(Value value) {
1113
            if(value instanceof ExpressionBuilder.Variable){
1114
                return isColumn(((ExpressionBuilder.Variable)value).name());
1115
            }
1116
            return this.value == value;
1117
        }
1118
        
1119
        @Override
1120
        public OrderByBuilder value(Value expression) {
1121
            this.value = expression;
1122
            return this;
1123
        }
1124
        
1125
        @Override
1126
        public OrderByBuilder custom(String order) {
1127
            this.custom = order;
1128
            return this;
1129
        }
1130

  
1131
        @Override
1132
        public OrderByBuilder ascending() {
1133
            this.ascending = true;
1134
            return this;
1135
        }
1136

  
1137
        @Override
1138
        public OrderByBuilder ascending(boolean asc) {
1139
            this.ascending = asc;
1140
            return this;
1141
        }
1142

  
1143
        @Override
1144
        public OrderByBuilder descending() {
1145
            this.ascending = false;
1146
            return this;
1147
        }
1148

  
1149
        @Override
1150
        public OrderByBuilder nulls(int mode) {
1151
            this.nullsMode = mode;
1152
            return this;
1153
        }
1154

  
1155
        @Override
1156
        public int getNullsMode() {
1157
            return this.nullsMode;
1158
        }
1159

  
1160
        @Override
1161
        public String toString() {
1162
            return this.toString(formatter());
1163
        }
1164

  
1165
        @Override
1166
        public String toString(Formatter<Value> formatter) {
1167
            if (formatter!=null && formatter.canApply(this)) {
1168
                return formatter.format(this);
1169
            }
1170
            if (!StringUtils.isEmpty(this.custom)) {
1171
                return this.custom;
1172
            }
1173
            String order_s = this.value.toString(formatter);
1174
            if (this.ascending) {
1175
                order_s += " ASC";
1176
            } else {
1177
                order_s += " DESC";
1178
            }
1179
            switch(this.nullsMode) {
1180
                case MODE_NULLS_NOT_SPECIFIED:
1181
                    break;
1182
                case MODE_NULLS_FIRST:
1183
                    order_s += " NULLS FIRST";
1184
                    break;
1185
                case MODE_NULLS_LAST:
1186
                default:
1187
                    order_s += " NULLS LAST";
1188
                    break;
1189
            }
1190
            return order_s;
1191
        }
1192

  
1193
        @Override
1194
        public void replace(Value target, Value replacement) {
1195
            super.replace(target, replacement);
1196
            if(target == this.value){
1197
                this.value = replacement;
1198
                return;
1199
            }
1200
            if(this.value == null){
1201
                return;
1202
            }
1203
            this.value.replace(target, replacement);
1204
        }
1205
        
1206
        
1207
    }
1208

  
1209
    public class SelectBuilderBase
1210
            extends AbstractStatement
1211
            implements SelectBuilder {
1212

  
1213
        protected FromBuilder from;
1214
        protected GeometryExpressionBuilder where;
1215
        protected long limit = -1;
1216
        protected long offset = -1;
1217
        protected List<SelectColumnBuilder> columns;
1218
        protected List<OrderByBuilder> order_by;
1219
        protected boolean distinct;
1220
        protected List<Value> groupColumn;
1221
        protected boolean check_order_and_offset = true;
1222

  
1223
        public SelectBuilderBase() {
1224
            this.columns = new ArrayList<>();
1225
            this.distinct = false;
1226
        }
1227
        @Override
1228
        public List<Value> getGroups() {
1229
            return this.groupColumn;
1230
        }
1231
        
1232
        @Override
1233
        public List<SelectColumnBuilder> getColumns() {
1234
            return Collections.unmodifiableList(this.columns);
1235
    }
1236
        
1237
        @Override
1238
        public void remove_column(String columnName) {
1239
            SelectColumnBuilder found = null;
1240
            for (SelectColumnBuilder column : columns) {
1241
                if(column.getAlias().equalsIgnoreCase(columnName)) {
1242
                    found = column;
1243
                    break;
1244
                }
1245
                    
1246
            }
1247
            if(found!=null) {
1248
                columns.remove(found);
1249
            }
1250
        }
1251

  
1252
        @Override
1253
        public SelectBuilder group_by(Value... columns) {
1254
            if( this.groupColumn==null ) {
1255
                this.groupColumn = new ArrayList<>();
1256
            }
1257
            for (Value column : columns) {
1258
                this.groupColumn.add(column);
1259
            }
1260
            return this;
1261
        }
1262

  
1263
        @Override
1264
        public void accept(Visitor visitor, VisitorFilter filter) {
1265
            boolean visitChildren = true;
1266
            if (filter==null || filter.accept(this)) {
1267
                visitor.visit(this);
1268
            } else {
1269
                visitChildren = !filter.skipChildren();
1270
            }
1271
            if(visitChildren){
1272
                for (SelectColumnBuilder column : columns) {
1273
                    column.accept(visitor, filter);
1274
                }
1275
                if (this.has_from()) {
1276
                    this.from.accept(visitor, filter);
1277
                }
1278
                if (this.has_where()) {
1279
                    this.where.accept(visitor, filter);
1280
                }
1281
                if (this.has_order_by()) {
1282
                    for (OrderByBuilder order : order_by) {
1283
                        order.accept(visitor, filter);
1284
                    }
1285
                }
1286
                if (this.has_group_by()) {
1287
                    for (Value group : groupColumn) {
1288
                        group.accept(visitor, filter);
1289
                    }
1290
                }
1291
            }
1292
        }
1293

  
1294
        @Override
1295
        public void replace(Value target, Value replacement) {
1296
            if( this.columns!=null ) {
1297
                for (int i = 0; i < columns.size(); i++) {
1298
                    SelectColumnBuilder column = columns.get(i);
1299
                    if( column == target ) {
1300
                        columns.set(i, (SelectColumnBuilder) replacement);
1301
                    } else {
1302
                        column.replace(target, replacement);
1303
                    }
1304
                }
1305
            }
1306
            if (this.has_from()) {
1307
                if( this.from == target ) {
1308
                    this.from = (FromBuilder) replacement;
1309
                } else {
1310
                    this.from.replace(target, replacement);
1311
                }
1312
            }
1313
            if (this.has_where()) {
1314
                if( this.where == target ) {
1315
                    this.where = (GeometryExpressionBuilder) replacement;
1316
                } else if( this.where.value() == target ) {
1317
                    this.where.value(replacement);
1318
                } else {
1319
                    this.where.value().replace(target, replacement);
1320
                }
1321
            }
1322
            if (this.has_order_by()) {
1323
                for (int i = 0; i < order_by.size(); i++) {
1324
                    OrderByBuilder order = order_by.get(i);
1325
                    if( order == target ) {
1326
                        order_by.set(i, (OrderByBuilder) replacement);
1327
                    } else {
1328
                        order.replace(target, replacement);
1329
                    }
1330
                }
1331
            }
1332
            if (this.has_group_by()) {
1333
                for (int i = 0; i < groupColumn.size(); i++) {
1334
                    Value group = groupColumn.get(i);
1335
                    if( group == target ) {
1336
                        groupColumn.set(i, replacement);
1337
                    } else {
1338
                        group.replace(target, replacement);
1339
                    }
1340
                }
1341
            }
1342
        }
1343

  
1344
        @Override
1345
        public SelectBuilder distinct() {
1346
            this.distinct = true;
1347
            return this;
1348
        }
1349

  
1350
        @Override
1351
        public SelectColumnBuilder column() {
1352
            return column(createSelectColumnBuilder());
1353
        }
1354

  
1355
        @Override
1356
        public SelectColumnBuilder column(SelectColumnBuilder columnBuilder) {
1357
            this.columns.add(columnBuilder);
1358
            if( this.has_from() && !this.from().table().isEmpty() ) {
1359
                TableNameBuilder table = (TableNameBuilder) CloneableUtils.cloneQuietly(this.from().table());
1360
                columnBuilder.table(table);
1361
            }
1362
            return columnBuilder;
1363
        }
1364

  
1365
        @Override
1366
        public SelectColumnBuilder column(String name) {
1367
            for (SelectColumnBuilder column : columns) {
1368
                if (StringUtils.equals(name, column.getName())) {
1369
                    return column;
1370
                }
1371
            }
1372
            return column(createSelectColumnBuilder()).name(name);
1373
        }
1374

  
1375
        @Override
1376
        public SelectColumnBuilder getColumn(String name) {
1377
            for (SelectColumnBuilder column : columns) {
1378
                if (StringUtils.equals(name, column.getName())) {
1379
                    return column;
1380
                }
1381
            }
1382
            return null;
1383
        }
1384
        
1385
        @Override
1386
        public SelectBuilder remove_all_columns() {
1387
            this.columns = new ArrayList<>();
1388
            return this;
1389
        }
1390
        
1391
        @Override
1392
        public boolean has_column(String name) {
1393
            for (SelectColumnBuilder column : columns) {
1394
                if (StringUtils.equals(name, column.getName())) {
1395
                    return true;
1396
                }
1397
                if (StringUtils.equals(name, column.getAlias())) {
1398
                    return true;
1399
                }
1400
            }
1401
            return false;
1402
        }
1403

  
1404
        @Override
1405
        public FromBuilder from() {
1406
            if (this.from == null) {
1407
                this.from = createFromBuilder();
1408
            }
1409
            return this.from;
1410
        }
1411

  
1412
        @Override
1413
        public boolean has_from() {
1414
            return this.from != null;
1415
        }
1416

  
1417
        @Override
1418
        public GeometryExpressionBuilder where() {
1419
            if (this.where == null) {
1420
                this.where = createExpressionBuilder();
1421
            }
1422
            return this.where;
1423
        }
1424

  
1425
        @Override
1426
        public boolean has_where() {
1427
            if (this.where == null) {
1428
                return false;
1429
            }
1430
            return this.where.value() != null;
1431
        }
1432

  
1433
        @Override
1434
        public SelectBuilder limit(long limit) {
1435
            this.limit = limit;
1436
            return this;
1437
        }
1438

  
1439
        @Override
1440
        public SelectBuilder limit(Long limit) {
1441
            if (limit == null) {
1442
                this.limit = -1;
1443
            } else {
1444
                this.limit = limit;
1445
            }
1446
            return this;
1447
        }
1448

  
1449
        @Override
1450
        public boolean has_limit() {
1451
            return this.limit >= 0;
1452
        }
1453

  
1454
        @Override
1455
        public SelectBuilder offset(long offset) {
1456
            this.offset = offset;
1457
            return this;
1458
        }
1459

  
1460
        @Override
1461
        public boolean has_offset() {
1462
            return this.offset > 0;
1463
        }
1464

  
1465
        @Override
1466
        public OrderByBuilder order_by() {
1467
            if (this.order_by == null) {
1468
                this.order_by = new ArrayList<>();
1469
            }
1470
            OrderByBuilder order = createOrderByBuilder();
1471
            this.order_by.add(order);
1472
            return order;
1473
        }
1474
        
1475
        @Override
1476
        public OrderByBuilder getOrderBy(Value column) {
1477
            if(this.order_by == null){
1478
                return null;
1479
            }
1480
            for (OrderByBuilder orderByBuilder : this.order_by) {
1481
                if(orderByBuilder.isColumn(column)){
1482
                    return orderByBuilder;
1483
                }
1484
            }
1485
            return null;
1486
        }
1487
        
1488
        @Override
1489
        public OrderByBuilder getOrderBy(String column) {
1490
            if(this.order_by == null){
1491
                return null;
1492
            }
1493
            for (OrderByBuilder orderByBuilder : this.order_by) {
1494
                if(orderByBuilder.isColumn(column)){
1495
                    return orderByBuilder;
1496
                }
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff