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        v.postVisit(this);
354    }
355
356    public void init(Object arg1){
357        literalType = (ELiteralType)arg1;
358    }
359
360    /**
361     * The type of this constant.
362     * <p>
363     * The most used type are: etNumber,etFloat,etString,etTimestamp,etDate,etInterval
364     * @param literalType the type of this constant
365     */
366    public void setLiteralType(ELiteralType literalType) {
367        this.literalType = literalType;
368    }
369
370    public static TConstant createConstant(ELiteralType literalType, String valueStr){
371        TConstant constant = new TConstant(literalType);
372        constant.setValueToken(new TSourceToken(valueStr));
373        return constant;
374    }
375
376    public void init(Object arg1, Object arg2){
377        init(arg1);
378        switch (literalType){
379            case integer_et:
380                valueToken = (TSourceToken)arg2;
381                break;
382            case etNumber:
383                valueToken = (TSourceToken)arg2;
384                break;
385            case etFloat:
386                valueToken = (TSourceToken)arg2;
387                break;
388            case etString:
389                valueToken = (TSourceToken)arg2;
390                break;
391            case etTimestamp:
392                valueToken = (TSourceToken)arg2;
393                break;
394            case etDate:
395                valueToken = (TSourceToken)arg2;
396                break;
397            case etInterval:
398                valueToken = (TSourceToken)arg2;
399                break;
400            case etStringLiteralSequence:
401                stringLiteralSequence  = (TSourceTokenList)arg2;
402                break;
403            case etStar:
404                valueToken = (TSourceToken)arg2;
405                break;
406            case interval:
407                int64_expression = (TExpression)arg2;
408                break;
409            case etJson:
410                keyValues = (ArrayList<TKeyValueSqlNode>)arg2;
411                break;
412            default:
413                break;
414        }
415
416        if (arg2 instanceof TSourceToken){
417            this.setStartToken((TSourceToken)arg2);
418            this.setEndToken((TSourceToken)arg2);
419        }
420
421    }
422
423    private TSourceToken bind1;
424    private TSourceToken bind2;
425    private TSourceToken indicator;
426
427    public void setBind1(TSourceToken bind1) {
428        this.bind1 = bind1;
429    }
430
431    public void setBind2(TSourceToken bind2) {
432        this.bind2 = bind2;
433    }
434
435    public void setIndicator(TSourceToken indicator) {
436        this.indicator = indicator;
437    }
438
439    public TSourceToken getBind1() {
440
441        return bind1;
442    }
443
444    public TSourceToken getBind2() {
445        return bind2;
446    }
447
448    public TSourceToken getIndicator() {
449        return indicator;
450    }
451
452    EIntervalType getIntervalTypeByDummy(TDummy dummy){
453        EIntervalType rtn = EIntervalType.itUnknown;
454        for(EIntervalType t : EIntervalType.values()){
455            if (t.getValue() == dummy.int1){
456                rtn = t;
457                break;
458            }
459        }
460        return rtn;
461    }
462
463    private ArrayList<TSourceToken> intervalValueTokens = new ArrayList<>();
464
465    public ArrayList<TSourceToken> getIntervalValueTokens() {
466        return intervalValueTokens;
467    }
468
469    public ArrayList<EIntervalType> getIntervalTypes() {
470        return intervalTypes;
471    }
472
473    private ArrayList<EIntervalType> intervalTypes = new ArrayList<>();
474
475    public void addIntervalTypeByDummy(TDummy dummy){
476        intervalTypes.add( getIntervalTypeByDummy(dummy) );
477    }
478
479    public void init(Object arg1, Object arg2,Object arg3){
480        init(arg1);
481        switch (literalType){
482            case etInterval:
483                valueToken = (TSourceToken)arg2;
484                if (arg3 instanceof TDummy){ // databricks
485                    intervalType = getIntervalTypeByDummy((TDummy) arg3);
486                    intervalValueTokens.add(valueToken);
487                    intervalTypes.add(intervalType);
488                }else{
489                    intervalType = (EIntervalType)arg3;
490                }
491                break;
492            case etBindVar:
493                bind1 = (TSourceToken)arg2;
494                bind2 = (TSourceToken)arg3;
495                break;
496            default:
497                break;
498        }
499    }
500
501
502    public void init(Object arg1, Object arg2,Object arg3,Object arg4){
503        init(arg1);
504        switch (literalType){
505            case etBindVar:
506                bind1 = (TSourceToken)arg2;
507                bind2 = (TSourceToken)arg3;
508                indicator = (TSourceToken)arg4;
509                break;
510            default:
511                break;
512        }
513    }
514
515    private TExpression int64_expression;
516
517    /**
518     * BigQuery interval literal int64_expression
519     *
520     * @return BigQuery interval literal int64_expression
521     */
522    public TExpression getInt64_expression() {
523        return int64_expression;
524    }
525}