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}