001package gudusoft.gsqlparser.stmt;
002
003import gudusoft.gsqlparser.EDbVendor;
004import gudusoft.gsqlparser.ESqlStatementType;
005import gudusoft.gsqlparser.TCustomSqlStatement;
006import gudusoft.gsqlparser.TSourceToken;
007import gudusoft.gsqlparser.nodes.TObjectName;
008import gudusoft.gsqlparser.nodes.TParseTreeVisitor;
009
010/**
011 * Vertica CREATE PROJECTION statement.
012 * <p>
013 * Syntax:
014 * <pre>
015 * CREATE PROJECTION [schema.]projection_name (column_list)
016 * AS SELECT ...
017 * [ORDER BY ...]
018 * [SEGMENTED BY expression ALL NODES [KSAFE [k]]]
019 * [UNSEGMENTED ALL NODES]
020 * </pre>
021 *
022 * @since 4.0.0.7
023 */
024public class TCreateProjectionStmt extends TCustomSqlStatement {
025
026    private TObjectName projectionName = null;
027
028    public TCreateProjectionStmt(EDbVendor dbvendor) {
029        super(dbvendor);
030        sqlstatementtype = ESqlStatementType.sstCreateProjection;
031    }
032
033    /**
034     * @return the projection name (may include schema prefix)
035     */
036    public TObjectName getProjectionName() {
037        return projectionName;
038    }
039
040    /**
041     * Skip grammar-based syntax checking since there's no grammar rule
042     * for CREATE PROJECTION. We do token-based parsing instead.
043     */
044    protected int dochecksyntax(TCustomSqlStatement psql) {
045        isparsed = true;
046        return 0;
047    }
048
049    /**
050     * Parse the CREATE PROJECTION statement from tokens.
051     * <p>
052     * Since there's no grammar-produced AST node for CREATE PROJECTION,
053     * this method extracts key information from the token stream.
054     */
055    public int doParseStatement(TCustomSqlStatement psql) {
056        if (sourcetokenlist == null || sourcetokenlist.size() == 0) {
057            return -1;
058        }
059
060        // Find projection name after CREATE PROJECTION keywords
061        int projectionIndex = -1;
062        for (int i = 0; i < sourcetokenlist.size() - 1; i++) {
063            TSourceToken token = sourcetokenlist.get(i);
064            if (token.toString().equalsIgnoreCase("PROJECTION")) {
065                projectionIndex = i;
066                break;
067            }
068        }
069
070        if (projectionIndex >= 0) {
071            // Find the next solid token after PROJECTION keyword (schema or name)
072            TSourceToken firstToken = sourcetokenlist.nextsolidtoken(projectionIndex, 1, false);
073            if (firstToken != null) {
074                // Check if next solid token is a dot (schema.name format)
075                TSourceToken afterFirst = sourcetokenlist.nextsolidtoken(firstToken.posinlist, 1, false);
076                if (afterFirst != null && afterFirst.toString().equals(".")) {
077                    // schema.name format
078                    TSourceToken nameToken = sourcetokenlist.nextsolidtoken(afterFirst.posinlist, 1, false);
079                    if (nameToken != null) {
080                        projectionName = new TObjectName();
081                        projectionName.setSchemaToken(firstToken);
082                        projectionName.setObjectToken(nameToken);
083                    }
084                } else {
085                    // Simple name format
086                    projectionName = new TObjectName();
087                    projectionName.setObjectToken(firstToken);
088                }
089            }
090        }
091
092        return 0;
093    }
094
095    public void accept(TParseTreeVisitor v) {
096        v.preVisit(this);
097        v.postVisit(this);
098    }
099
100    public void acceptChildren(TParseTreeVisitor v) {
101        v.preVisit(this);
102        v.postVisit(this);
103    }
104}