001package gudusoft.gsqlparser.nodes;
002
003import gudusoft.gsqlparser.*;
004
005import java.util.ArrayList;
006
007
008/**
009 * SQL constant (sometimes called a literal) specifies a value.
010 * Constants are classified as:
011 * <ul>
012 * <li>string(text) constants</li>
013 * <li>numeric constants,Numeric constants are further classified as integer, floating-point, or decimal</li>
014 * <li>datetime constants</li>
015 * <li>interval constants</li>
016 * <li>boolean constants</li>
017 * </ul>
018 * {@link #getLiteralType()} returns the type of this constant, {@link #getValueToken()} returns the value of this constant.
019 * {@link #toString} returns the text of this constant.
020 *
021 *
022 */
023public class TConstant extends TParseTreeNode {
024
025    public Integer getIntegerValue(){
026        Integer result = null;
027
028        switch (getLiteralType()){
029            case integer_et:
030            case numeric_et:
031            case etNumber:
032                try {
033                    result = Integer.parseInt(valueToken.toString());
034
035                } catch (NumberFormatException e) {
036                }
037                break;
038        }
039
040        return result;
041    }
042    private ArrayList<TKeyValueSqlNode> keyValues;
043
044    public ArrayList<TKeyValueSqlNode> getKeyValues() {
045        return keyValues;
046    }
047
048    /**
049     * Set the explicit type of this constant
050     *
051     * @param castType explicit type
052     * @see #getCastType
053     */
054    public void setCastType(TTypeName castType) {
055        this.castType = castType;
056        switch (castType.getDataType()){
057            case time_t:
058                this.literalType = ELiteralType.etTime;
059                break;
060            case timestamp_t:
061                this.literalType = ELiteralType.etTimestamp;
062                break;
063            case interval_t:
064                this.literalType = ELiteralType.etInterval;
065                break;
066        }
067    }
068
069    public void setLiteralType(TSourceToken st){
070        if (st == null) return;
071        for(ELiteralType et:ELiteralType.values()){
072            if (et.getText().equalsIgnoreCase(st.toString())){
073                this.literalType = et;
074                break;
075            }
076        }
077    }
078
079    /**
080     * Constants can be specified with explicit types. This method returns the explicit type.
081     * In PostgreSQL, a constant of an arbitrary type can be entered using any one of the following notations:
082     * <pre>
083     *     type 'string'
084     *     'string'::type
085     *     CAST 'string' AS type
086     * </pre>
087     *
088     * @return explicit type for this constant
089     */
090    public TTypeName getCastType() {
091
092        return castType;
093    }
094
095    private TTypeName castType;
096    private TSourceToken valueToken;
097    private TSourceToken signToken; // +,-
098
099    public void setSignToken(TSourceToken signToken) {
100        this.signToken = signToken;
101    }
102
103    public TSourceToken getSignToken() {
104        return signToken;
105    }
106
107    private TSourceToken charSetName;
108    private TSourceToken char_String_SetLiteral;
109    private TSourceTokenList stringLiteralSequence;
110    private ELiteralType literalType = ELiteralType.unknownType;
111    private TSourceToken leadingPrecision;
112    private EIntervalType intervalType;
113
114    /**
115     * Set the sub-type of interval constant
116     *
117     * @param intervalType sub-type of interval constant
118     * @see #getIntervalType
119     */
120    public void setIntervalType(EIntervalType intervalType) {
121        this.intervalType = intervalType;
122    }
123
124    /**
125     * Oracle interval year to month and interval day to second constant.
126     * This method return sub-type of interval constant such as year to month, minute to second.
127     *
128     * @return sub-type of interval constant
129     */
130    public EIntervalType getIntervalType() {
131
132        return intervalType;
133    }
134
135    /**
136     * set value of this constant
137     * <pre>
138     *     INTERVAL '30.12345' SECOND(2,4)
139     * </pre>
140     * '30.12345' in the above SQL in the valueToken
141     *
142     * @param valueToken value of this constant
143     */
144    public void setValueToken(TSourceToken valueToken) {
145        this.valueToken = valueToken;
146        stringValue = valueToken.toString();
147    }
148
149    /**
150     * set the precision which is the maximum number of digits in the leading field of a interval constant.
151     * <pre>
152     *     INTERVAL '400 5' DAY(3) TO HOUR
153     * </pre>
154     * 3 in the above SQL is the <code>leadingPrecision</code>
155     *
156     *
157     * @param leadingPrecision the precision of the leading field
158     */
159    public void setLeadingPrecision(TSourceToken leadingPrecision) {
160
161        this.leadingPrecision = leadingPrecision;
162    }
163
164    /**
165     * set the fractional precision which is the number of digits in the fractional part of the SECOND datetime field
166     * in a interval day to second constant.
167     * <pre>
168     *     INTERVAL '30.12345' SECOND(2,4)
169     * </pre>
170     * 4 in the above SQL is the <code>fractionalSecondsPrecision</code>, 2 is the <code>leadingPrecision</code>
171     *
172     * @param fractionalSecondsPrecision
173     */
174    public void setFractionalSecondsPrecision(TSourceToken fractionalSecondsPrecision) {
175        this.fractionalSecondsPrecision = fractionalSecondsPrecision;
176    }
177
178    /**
179     * the maximum number of digits in the leading field of a interval constant.
180     * <pre>
181     *     INTERVAL '400 5' DAY(3) TO HOUR
182     * </pre>
183     * 3 in the above SQL is the <code>leadingPrecision</code>
184     *
185     * @return the leading precision
186     */
187    public TSourceToken getLeadingPrecision() {
188
189        return leadingPrecision;
190    }
191
192    /**
193     * the number of digits in the fractional part of the SECOND datetime field in a interval day to second constant.
194     *
195     * <pre>
196     *     INTERVAL '30.12345' SECOND(2,4)
197     * </pre>
198     * 4 in the above SQL is the <code>fractionalSecondsPrecision</code>, 2 is the <code>leadingPrecision</code>
199     *
200     * @return the fractional seconds precision
201     */
202    public TSourceToken getFractionalSecondsPrecision() {
203        return fractionalSecondsPrecision;
204    }
205
206    private TSourceToken fractionalSecondsPrecision;
207
208    public TConstant(){}
209
210    /**
211     * Class constructor, set the type of this constant while creating a new instance of the constant
212     *
213     * @param pLiteralType type of this constant
214     *
215     */
216    public TConstant(ELiteralType pLiteralType){
217        this.literalType = pLiteralType;
218    }
219
220    /**
221     * Class constructor, set the type and value of this constant when creating a new instance of the constant
222     *
223     * @param literalType type of this constant
224     * @param valueToken  value of this constant
225     */
226    public TConstant (ELiteralType literalType, TSourceToken valueToken){
227        this(literalType);
228        this.valueToken = valueToken;
229        this.stringValue = valueToken.toString();
230        this.setStartToken(valueToken);
231        this.setEndToken(valueToken);
232    }
233
234    /**
235     * Class constructor, set the type and value of this constant when creating a new instance of the constant.
236     * set the sub-type of an interval constant.
237     *
238     * @param literalType   type of this constant, must be etInterval
239     * @param valueToken    value of this constant
240     * @param intervalType  sub-type of an interval constant
241     */
242    public TConstant (ELiteralType literalType, TSourceToken valueToken,EIntervalType intervalType){
243        this(literalType, valueToken);
244        this.intervalType = intervalType;
245    }
246
247    /**
248     * @deprecated use {@link #getValueToken} instead
249     *
250     * @param stringValue text value of this constant
251     */
252//    public void setStringValue(String stringValue) {
253//        this.stringValue = stringValue;
254//    }
255
256    /**
257     *
258     * @return text value of this constant without quote characters
259     */
260    public String getValue(){
261        //return getStringValue();
262        String ret;
263        switch (literalType){
264            case etString:
265            case etNumber:
266            case etFloat:
267                if (valueToken != null){
268                    ret = TBaseType.removeQuoteChar(valueToken.toString());
269                }else{
270                    ret =  TBaseType.removeQuoteChar(toString());
271                }
272
273                break;
274            default:
275                ret = toString();
276                break;
277        }
278
279        return ret;
280    }
281
282    /**
283     * @deprecated since 1.8.2.4, use {@link #getValue()} instead.
284     *
285     * @return text value of this constant
286     */
287    public String getStringValue() {
288        return getValue();
289    }
290
291    private String stringValue;
292
293    /**
294     * get type of this constant, can be strings, integers, and floating point numbers and more.
295     * Please check {@link gudusoft.gsqlparser.ELiteralType} for more type of constant
296     *
297     * @return type of this constant
298     */
299    public ELiteralType getLiteralType() {
300        return literalType;
301    }
302
303    public void setStringLiteralSequence(TSourceTokenList stringLiteralSequence) {
304        this.stringLiteralSequence = stringLiteralSequence;
305    }
306
307    /**
308     * String list constant in Hive.
309     *
310     * @return a sequence of source token
311     */
312    public TSourceTokenList getStringLiteralSequence() {
313
314        return stringLiteralSequence;
315    }
316
317    /**
318     * The '+' or '-' before this constant. Valid only when {@link #getLiteralType} is {@link ELiteralType#etNumber}
319     *
320     * @param sign the '+' or '-' token
321     */
322    public void setSign(TSourceToken sign) {
323        this.sign = sign;
324    }
325
326    private TSourceToken sign;
327
328    /**
329     * The '+' or '-' before this constant. Valid only when {@link #getLiteralType} is {@link ELiteralType#etNumber}
330     *
331     * @return the '+' or '-' token
332     */
333    public TSourceToken getSign() {
334        return sign;
335    }
336
337    /**
338     * The value of this constant represented by a source token.
339     *
340     * @return the value of this constant
341     */
342    public TSourceToken getValueToken(){
343        return valueToken;
344    }
345
346    public void accept(TParseTreeVisitor v){
347        v.preVisit(this);
348        v.postVisit(this);
349    }
350
351    public void acceptChildren(TParseTreeVisitor v){
352        v.preVisit(this);
353        // the expression of a BigQuery INTERVAL literal can read columns: INTERVAL SAFE_CAST(c AS INT64) DAY
354        if (int64_expression != null) {
355            int64_expression.acceptChildren(v);
356        }
357        v.postVisit(this);
358    }
359
360    public void init(Object arg1){
361        literalType = (ELiteralType)arg1;
362    }
363
364    /**
365     * The type of this constant.
366     * <p>
367     * The most used type are: etNumber,etFloat,etString,etTimestamp,etDate,etInterval
368     * @param literalType the type of this constant
369     */
370    public void setLiteralType(ELiteralType literalType) {
371        this.literalType = literalType;
372    }
373
374    public static TConstant createConstant(ELiteralType literalType, String valueStr){
375        TConstant constant = new TConstant(literalType);
376        constant.setValueToken(new TSourceToken(valueStr));
377        return constant;
378    }
379
380    public void init(Object arg1, Object arg2){
381        init(arg1);
382        switch (literalType){
383            case integer_et:
384                valueToken = (TSourceToken)arg2;
385                break;
386            case etNumber:
387                valueToken = (TSourceToken)arg2;
388                break;
389            case etFloat:
390                valueToken = (TSourceToken)arg2;
391                break;
392            case etString:
393                valueToken = (TSourceToken)arg2;
394                break;
395            case etTimestamp:
396                valueToken = (TSourceToken)arg2;
397                break;
398            case etDate:
399                valueToken = (TSourceToken)arg2;
400                break;
401            case etInterval:
402                valueToken = (TSourceToken)arg2;
403                break;
404            case etStringLiteralSequence:
405                stringLiteralSequence  = (TSourceTokenList)arg2;
406                break;
407            case etStar:
408                valueToken = (TSourceToken)arg2;
409                break;
410            case interval:
411                int64_expression = (TExpression)arg2;
412                break;
413            case etJson:
414                keyValues = (ArrayList<TKeyValueSqlNode>)arg2;
415                break;
416            default:
417                break;
418        }
419
420        if (arg2 instanceof TSourceToken){
421            this.setStartToken((TSourceToken)arg2);
422            this.setEndToken((TSourceToken)arg2);
423        }
424
425    }
426
427    private TSourceToken bind1;
428    private TSourceToken bind2;
429    private TSourceToken indicator;
430
431    public void setBind1(TSourceToken bind1) {
432        this.bind1 = bind1;
433    }
434
435    public void setBind2(TSourceToken bind2) {
436        this.bind2 = bind2;
437    }
438
439    public void setIndicator(TSourceToken indicator) {
440        this.indicator = indicator;
441    }
442
443    public TSourceToken getBind1() {
444
445        return bind1;
446    }
447
448    public TSourceToken getBind2() {
449        return bind2;
450    }
451
452    public TSourceToken getIndicator() {
453        return indicator;
454    }
455
456    EIntervalType getIntervalTypeByDummy(TDummy dummy){
457        EIntervalType rtn = EIntervalType.itUnknown;
458        for(EIntervalType t : EIntervalType.values()){
459            if (t.getValue() == dummy.int1){
460                rtn = t;
461                break;
462            }
463        }
464        return rtn;
465    }
466
467    private ArrayList<TSourceToken> intervalValueTokens;
468
469    public ArrayList<TSourceToken> getIntervalValueTokens() {
470        if (intervalValueTokens == null) {
471            intervalValueTokens = new ArrayList<>();
472        }
473        return intervalValueTokens;
474    }
475
476    public ArrayList<EIntervalType> getIntervalTypes() {
477        if (intervalTypes == null) {
478            intervalTypes = new ArrayList<>();
479        }
480        return intervalTypes;
481    }
482
483    private ArrayList<EIntervalType> intervalTypes;
484
485    public void addIntervalTypeByDummy(TDummy dummy){
486        if (intervalTypes == null) {
487            intervalTypes = new ArrayList<>();
488        }
489        intervalTypes.add( getIntervalTypeByDummy(dummy) );
490    }
491
492    public void init(Object arg1, Object arg2,Object arg3){
493        init(arg1);
494        switch (literalType){
495            case etInterval:
496                valueToken = (TSourceToken)arg2;
497                if (arg3 instanceof TDummy){ // databricks
498                    intervalType = getIntervalTypeByDummy((TDummy) arg3);
499                    getIntervalValueTokens().add(valueToken);
500                    getIntervalTypes().add(intervalType);
501                }else{
502                    intervalType = (EIntervalType)arg3;
503                }
504                break;
505            case etBindVar:
506                bind1 = (TSourceToken)arg2;
507                bind2 = (TSourceToken)arg3;
508                break;
509            default:
510                break;
511        }
512    }
513
514
515    public void init(Object arg1, Object arg2,Object arg3,Object arg4){
516        init(arg1);
517        switch (literalType){
518            case etBindVar:
519                bind1 = (TSourceToken)arg2;
520                bind2 = (TSourceToken)arg3;
521                indicator = (TSourceToken)arg4;
522                break;
523            default:
524                break;
525        }
526    }
527
528    private TExpression int64_expression;
529
530    /**
531     * BigQuery interval literal int64_expression
532     *
533     * @return BigQuery interval literal int64_expression
534     */
535    public TExpression getInt64_expression() {
536        return int64_expression;
537    }
538}