001package gudusoft.gsqlparser.stmt;
002
003
004import gudusoft.gsqlparser.*;
005import gudusoft.gsqlparser.nodes.*;
006
007import java.util.EnumSet;
008
009/**
010 * Create trigger statement.
011 *
012 * supported databases:
013 * <ul>
014 *     <li>DB2</li>
015 *     <li>Hana</li>
016 *     <li>Greenplum, represented by {@link gudusoft.gsqlparser.stmt.oracle.TPlsqlCreateTrigger}</li>
017 *     <li>Informix</li>
018 *     <li>MySQL</li>
019 *     <li>Openedge</li>
020 *     <li>Oracle, represented by {@link gudusoft.gsqlparser.stmt.oracle.TPlsqlCreateTrigger}
021 *     support dml, non-dml and database trigger.
022 *     </li>
023 *     <li>PostgreSQL</li>
024 *     <li>SQL Server,
025 *     support dml, ddl trigger
026 *     </li>
027 *     <li>Sybase</li>
028 *     <li>Teradata</li>
029 * </ul>
030 *
031 * @see TTriggeringClause
032 */
033public class TCreateTriggerStmt extends TStoredProcedureSqlStatement {
034    public void setTriggeringClause(TTriggeringClause triggeringClause) {
035        this.triggeringClause = triggeringClause;
036    }
037
038    public TCreateTriggerStmt (EDbVendor dbvendor){
039        super(dbvendor);
040        sqlstatementtype = ESqlStatementType.sstcreatetrigger ;
041    }
042
043
044    void buildsql() {
045    }
046
047    void clear() {
048    }
049
050    String getasprettytext() {
051        return "";
052    }
053
054    void iterate(TVisitorAbs pvisitor) {
055    }
056
057    private TExpression whenCondition = null;
058
059    /**
060     * When condition
061     * @return when condition
062     */
063    public TExpression getWhenCondition() {
064        return whenCondition;
065    }
066
067    private boolean alterTrigger;
068
069    public void setAlterTrigger(boolean alterTrigger) {
070        this.alterTrigger = alterTrigger;
071    }
072
073    public boolean isAlterTrigger() {
074
075        return alterTrigger;
076    }
077    @Override
078    public TObjectName getStoredProcedureName(){
079        return triggerName;
080    }
081
082    private TTable onTable = null;
083
084    /**
085     * @deprecated As of v2.0.1.0,  use {@link #getTriggeringClause()} instead
086     *
087     * @return onTable
088     */
089    public TTable getOnTable() {
090        return onTable;
091    }
092
093
094    public TObjectName getTriggerName() {
095        return triggerName;
096    }
097
098    private TObjectName triggerName = null;
099
100    public void setTimingPoint(ETriggerTimingPoint timingPoint) {
101        this.timingPoint = timingPoint;
102    }
103
104    public void setDmlTypes(EnumSet<ETriggerDmlType> dmlTypes) {
105        this.dmlTypes = dmlTypes;
106    }
107
108    /**
109     * @deprecated As of v2.0.1.0, replaced by {@link #getTriggeringClause()}
110     * @return timing point
111     */
112    public ETriggerTimingPoint getTimingPoint() {
113
114        return timingPoint;
115    }
116
117    /**
118     * @deprecated As of v2.0.1.0, replaced by {@link #getTriggeringClause()}
119     * @return dml
120     */
121    public EnumSet<ETriggerDmlType> getDmlTypes() {
122        return dmlTypes;
123    }
124
125    private TFunctionCall functionCall;//postgresql
126
127    public void setFunctionCall(TFunctionCall functionCall) {
128        this.functionCall = functionCall;
129    }
130
131    /**
132     * Greenplum,postgresql executed function
133     *
134     * @return function call
135     */
136    public TFunctionCall getFunctionCall() {
137
138        return functionCall;
139    }
140
141    public int doParseStatement(TCustomSqlStatement psql) {
142        if (rootNode == null) return -1;
143        if(!(rootNode instanceof TCreateTriggerSqlNode)) return -1;
144        TCreateTriggerSqlNode createTriggerNode = (TCreateTriggerSqlNode)rootNode;
145
146        super.doParseStatement(psql);
147        this.triggerName = createTriggerNode.getTriggerName();
148        if (getSqlEnv().getDefaultCatalogName() != null){
149            if (triggerName.getDatabaseToken() == null){
150                triggerName.setDatabaseToken(new TSourceToken(getSqlEnv().getDefaultCatalogName()));
151            }
152        }
153        alterTrigger = createTriggerNode.isAlterTrigger();
154        this.fireMode = createTriggerNode.getFireMode();
155        timingPoint = createTriggerNode.getTimingPoint();
156        triggeringClause = createTriggerNode.getTriggeringClause();
157        triggeringClause.doParse(this,ESqlClause.unknown);
158        functionCall = createTriggerNode.getFunctionCall();
159
160        onTable = tables.getTable(0);
161
162        switch (dbvendor){
163            case dbvdb2:
164                TTriggerAction triggerAction = createTriggerNode.getTriggerAction();
165                this.whenCondition = triggerAction.getWhenExpr();
166
167                if (triggerAction.getStmtNode() != null){
168                    triggerAction.getStmtNode().doParse(this,ESqlClause.unknown);
169                    this.getBodyStatements().add(triggerAction.getStmtNode().getStmt());
170                }else if (triggerAction.getCompoundSqlNode() != null){
171                    TCompoundSqlNode compoundSqlNode = triggerAction.getCompoundSqlNode();
172                    if (compoundSqlNode.getDeclareStmts() != null){
173                        compoundSqlNode.getDeclareStmts().doParse(this,ESqlClause.unknown);
174
175                        // push variable declare into symbolTable, and add to declareStatements
176                        for(int i=0;i<compoundSqlNode.getDeclareStmts().size();i++){
177                            this.getTopStatement().getSymbolTable().push( new TSymbolTableItem(TObjectName.ttobjVariable,this,compoundSqlNode.getDeclareStmts().getStatementSqlNode(i).getStmt() ));
178                            this.getDeclareStatements().add(compoundSqlNode.getDeclareStmts().getStatementSqlNode(i).getStmt());
179                        }
180                    }
181
182                    if (compoundSqlNode.getStmts() != null){
183                        compoundSqlNode.getStmts().doParse(this,ESqlClause.unknown);
184
185                        for(int i= 0; i<compoundSqlNode.getStmts().size();i++){
186                            this.getBodyStatements().add(compoundSqlNode.getStmts().getStatementSqlNode(i).getStmt());
187                        }
188                    }
189
190                    if (compoundSqlNode.getDeclareStmts() != null){
191                        // pop variable declare from symbolTable
192                        for(int i=0;i<compoundSqlNode.getDeclareStmts().size();i++){
193                            this.getTopStatement().getSymbolTable().pop();
194                        }
195                    }
196                }
197                break;
198            case dbvmysql:
199                parseMySqlTriggerBody(createTriggerNode);
200                break;
201            case dbvoceanbase:
202                // MySQL/system tenant: the MySQL trigger body, one statement or a BEGIN ... END block
203                // (Mantis 4813, Codex review); Oracle tenant keeps the generic reading
204                if (isMySQLDialect()){
205                    parseMySqlTriggerBody(createTriggerNode);
206                }else{
207                    parseGenericTriggerBody(createTriggerNode);
208                }
209                break;
210            case dbvsqlite:
211                if (createTriggerNode.getWhenCondition() != null){
212                    this.whenCondition = createTriggerNode.getWhenCondition();
213                }
214                if (createTriggerNode.getStmts() != null){
215                    createTriggerNode.getStmts().doParse(this,ESqlClause.unknown);
216                    for(int i=0;i<createTriggerNode.getStmts().size();i++){
217                        this.getBodyStatements().add(createTriggerNode.getStmts().getStatementSqlNode(i).getStmt());
218                    }
219                }
220                break;
221            default:
222                parseGenericTriggerBody(createTriggerNode);
223                break;
224        }
225
226
227        return 0;
228    }
229
230    /** A MySQL trigger body: one statement, or the statements of a BEGIN ... END block. */
231    private void parseMySqlTriggerBody(TCreateTriggerSqlNode createTriggerNode){
232        if (createTriggerNode.getStmt() != null){
233            createTriggerNode.getStmt().doParse(this,ESqlClause.unknown);
234            this.getBodyStatements().add(createTriggerNode.getStmt().getStmt());
235        }
236        else if (createTriggerNode.getBlcok() != null){
237            if (createTriggerNode.getBlcok().getStmts() != null){
238                createTriggerNode.getBlcok().getStmts().doParse(this,ESqlClause.unknown);
239
240                for(int i=0;i<createTriggerNode.getBlcok().getStmts().size();i++){
241                    this.getBodyStatements().add(createTriggerNode.getBlcok().getStmts().getStatementSqlNode(i).getStmt());
242                }
243            }
244        }
245    }
246
247    /** The trigger body of the other dialects: the node's statement list. */
248    private void parseGenericTriggerBody(TCreateTriggerSqlNode createTriggerNode){
249        if (createTriggerNode.getStmts() != null){
250            createTriggerNode.getStmts().doParse(this,ESqlClause.unknown);
251            for(int i=0;i<createTriggerNode.getStmts().size();i++){
252                this.getBodyStatements().add(createTriggerNode.getStmts().getStatementSqlNode(i).getStmt());
253            }
254        }
255    }
256
257    private TTriggeringClause triggeringClause;
258
259    public TTriggeringClause getTriggeringClause() {
260        return triggeringClause;
261    }
262
263    private int fireMode = TBaseType.tfmFor;
264    private ETriggerTimingPoint timingPoint = ETriggerTimingPoint.ttpAfter;
265    private EnumSet <ETriggerDmlType> dmlTypes = EnumSet.noneOf(ETriggerDmlType.class);
266
267    /**
268     * @deprecated As of v1.7.2.5, replaced by {@link gudusoft.gsqlparser.ETriggerDmlType}
269     * @return insert/delete/update action
270     */
271    public TSourceTokenList getDmlTpyes() {
272        if (this.dmlTpyes == null){
273            this.dmlTpyes = new TSourceTokenList();
274        }
275        return this.dmlTpyes;
276    }
277
278    private TSourceTokenList dmlTpyes = null;
279
280    /**
281     * @deprecated As of v1.7.2.5, replaced by {@link gudusoft.gsqlparser.ETriggerTimingPoint}
282     * @return trigger timing point
283     */
284    public int getFireMode() {
285        return fireMode;
286    }
287
288    public void accept(TParseTreeVisitor v){
289        v.preVisit(this);
290
291        v.postVisit(this);
292    }
293    public void acceptChildren(TParseTreeVisitor v){
294        v.preVisit(this);
295        if (getBodyStatements().size() > 0) getBodyStatements().acceptChildren(v);
296        v.postVisit(this);
297    }
298
299    public void setOnTable(TTable onTable) {
300        this.onTable = onTable;
301    }
302
303    public void setTriggerName(TObjectName triggerName) {
304        this.triggerName = triggerName;
305    }
306
307    public void setFireMode(int fireMode) {
308        this.fireMode = fireMode;
309    }
310}