001package gudusoft.gsqlparser.nodes.mssql;
002
003import gudusoft.gsqlparser.TSourceToken;
004import gudusoft.gsqlparser.nodes.TParseTreeNode;
005import gudusoft.gsqlparser.nodes.TParseTreeVisitor;
006
007/**
008 * One option of {@code BULK INSERT ... WITH (...)}: {@code NAME = value} ({@code DATA_SOURCE = 'MyAzureBlob'},
009 * {@code FIRSTROW = 2}), a flag ({@code TABLOCK}) or {@code ORDER (column [ASC|DESC], ...)}, whose value is not
010 * kept. The option names are SQL Server keywords, so they are compared ignoring case.
011 */
012public class TMssqlBulkInsertOption extends TParseTreeNode {
013
014    private final TSourceToken nameToken;
015    private final TSourceToken valueToken;
016
017    /**
018     * @param nameToken  the option name
019     * @param valueToken the value after {@code =}, or null for a flag or {@code ORDER (...)}
020     * @param endToken   the last token of the option
021     */
022    public TMssqlBulkInsertOption(TSourceToken nameToken, TSourceToken valueToken, TSourceToken endToken) {
023        this.nameToken = nameToken;
024        this.valueToken = valueToken;
025        setStartToken(nameToken);
026        setEndToken(endToken == null ? nameToken : endToken);
027    }
028
029    public TSourceToken getNameToken() {
030        return nameToken;
031    }
032
033    /** The option name as written. */
034    public String getName() {
035        return nameToken == null ? null : nameToken.toString();
036    }
037
038    /** True when the option is {@code optionName}, ignoring case. */
039    public boolean isNamed(String optionName) {
040        return nameToken != null && nameToken.toString().equalsIgnoreCase(optionName); // non-identifier-compare: SQL Server option keyword
041    }
042
043    public TSourceToken getValueToken() {
044        return valueToken;
045    }
046
047    /** The value token as written ({@code 'MyAzureBlob'}, {@code 2}); null for a flag or {@code ORDER (...)}. */
048    public String getValueText() {
049        return valueToken == null ? null : valueToken.toString();
050    }
051
052    /**
053     * The value: a string literal without its quotes ({@code N'..'} and doubled quotes decoded), any other token as
054     * written; null for a flag or {@code ORDER (...)}.
055     */
056    public String getValue() {
057        String text = getValueText();
058        if (text == null) {
059            return null;
060        }
061        String t = text;
062        if (t.length() >= 2 && (t.charAt(0) == 'N' || t.charAt(0) == 'n') && t.charAt(1) == '\'') {
063            t = t.substring(1);
064        }
065        if (t.length() >= 2 && t.charAt(0) == '\'' && t.charAt(t.length() - 1) == '\'') {
066            return t.substring(1, t.length() - 1).replace("''", "'");
067        }
068        return text;
069    }
070
071    public void accept(TParseTreeVisitor v) {
072        v.preVisit(this);
073        v.postVisit(this);
074    }
075
076    public void acceptChildren(TParseTreeVisitor v) {
077        v.preVisit(this);
078        v.postVisit(this);
079    }
080}