001package gudusoft.gsqlparser.stmt;
002
003
004import gudusoft.gsqlparser.*;
005import gudusoft.gsqlparser.nodes.TObjectName;
006import gudusoft.gsqlparser.nodes.TParseTreeVisitor;
007import gudusoft.gsqlparser.nodes.TPrepareSqlNode;
008import gudusoft.gsqlparser.nodes.TStatementSqlNode;
009import gudusoft.gsqlparser.nodes.TTypeNameList;
010
011/**
012 * A PREPARE statement: a named statement that is planned now and run later with EXECUTE.
013 * <p>
014 * MySQL and others prepare a statement given as a string ({@link #getPreparableStmtStr()}), which is parsed
015 * separately. PostgreSQL ({@code PREPARE name [ ( data_type [, ...] ) ] AS statement}) gives the statement in
016 * the SQL itself: {@link #getPreparableStmt()} is that SELECT, INSERT, UPDATE, DELETE or MERGE, parsed with this
017 * statement as its parent, and {@link #getDatatypeList()} the parameter types. A PostgreSQL PREPARE keeps the
018 * statement type {@link ESqlStatementType#sstpostgresqlPrepare} (Mantis 4868).
019 */
020public class TPrepareStmt extends TCustomSqlStatement {
021
022    public TPrepareStmt(EDbVendor dbvendor) {
023        super(dbvendor);
024        sqlstatementtype = ESqlStatementType.sstprepare;
025    }
026
027
028    private TCustomSqlStatement preparableStmt;
029
030    public TCustomSqlStatement getPreparableStmt() {
031        return preparableStmt;
032    }
033
034    private TObjectName stmtName;
035    private String  preparableStmtStr = "";
036
037    public String getPreparableStmtStr() {
038        return preparableStmtStr;
039    }
040
041    public TObjectName getStmtName() {
042        return stmtName;
043    }
044
045    private TTypeNameList datatypeList;
046
047    /**
048     * @return the parameter data types of a PostgreSQL PREPARE, or null when it has none
049     */
050    public TTypeNameList getDatatypeList() {
051        return datatypeList;
052    }
053
054    TGSqlParser parser;
055
056
057    public int doParseStatement(TCustomSqlStatement psql) {
058        if (rootNode == null) return -1;
059        super.doParseStatement(psql);
060
061        if ((dbvendor == EDbVendor.dbvpresto)||(dbvendor == EDbVendor.dbvathena)){
062            TStatementSqlNode sqlNode = new TStatementSqlNode();
063            sqlNode.init(rootNode);
064            sqlNode.doParse(this, ESqlClause.unknown);
065            preparableStmt = sqlNode.getStmt();
066
067        }else if ((rootNode instanceof TPrepareSqlNode) && (((TPrepareSqlNode)rootNode).getStatementNode() != null)){
068            // PostgreSQL: PREPARE name [ ( data_type [, ...] ) ] AS statement (Mantis 4868)
069            TPrepareSqlNode prepareNode = (TPrepareSqlNode)rootNode;
070            stmtName = prepareNode.getStmtName();
071            datatypeList = prepareNode.getDatatypeList();
072            preparableStmtStr = prepareNode.getStatementNode().toString();
073            TStatementSqlNode sqlNode = new TStatementSqlNode();
074            sqlNode.init(prepareNode.getStatementNode());
075            sqlNode.doParse(this, ESqlClause.unknown);
076            preparableStmt = sqlNode.getStmt();
077        }else{
078            TPrepareSqlNode sqlNode = (TPrepareSqlNode)rootNode;
079
080            stmtName = sqlNode.getStmtName();
081            preparableStmtStr = sqlNode.getPreparableStmt();
082            if (preparableStmtStr.startsWith("'")) {
083                preparableStmtStr = preparableStmtStr.replace("'", "");
084            }else if (sqlNode.getPreparableStmt().startsWith("\"")) {
085                preparableStmtStr = preparableStmtStr.replace("\"", "");
086            }
087
088            if (preparableStmtStr.length() > 0){
089                parser = new TGSqlParser(this.dbvendor);
090                parser.sqltext = preparableStmtStr;
091                //A whitespace-only or comment-only prepared string parses with
092                //rc 0 and ZERO statements (mantis 4681) — guard before get(0).
093                if ((parser.parse() == 0) && (parser.sqlstatements.size() > 0)){
094                    preparableStmt = parser.sqlstatements.get(0);
095                }
096            }
097        }
098
099        return 0;
100    }
101
102    public void accept(TParseTreeVisitor v){
103        v.preVisit(this);
104        v.postVisit(this);
105    }
106
107    public void acceptChildren(TParseTreeVisitor v){
108        v.preVisit(this);
109        if (preparableStmt != null) preparableStmt.accept(v);
110        v.postVisit(this);
111    }
112
113    public void setPreparableStmt(TCustomSqlStatement preparableStmt) {
114        this.preparableStmt = preparableStmt;
115    }
116
117    public void setStmtName(TObjectName stmtName) {
118        this.stmtName = stmtName;
119    }
120
121    public void setPreparableStmtStr(String preparableStmtStr) {
122        this.preparableStmtStr = preparableStmtStr;
123    }
124
125    public void setDatatypeList(TTypeNameList datatypeList) {
126        this.datatypeList = datatypeList;
127    }
128}