~mapopa/flamerobin/master

« back to all changes in this revision

Viewing changes to src/metadata/trigger.cpp

  • Committer: Michael Hieke
  • Date: 2004-11-22 11:34:42 UTC
  • Revision ID: git-v1:8153b493d66ee7aae55e7b34e0d7bddacf4999ef
Initial revision

svn path=/trunk/flamerobin/; revision=13

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  The contents of this file are subject to the Initial Developer's Public
 
3
  License Version 1.0 (the "License"); you may not use this file except in
 
4
  compliance with the License. You may obtain a copy of the License here:
 
5
  http://www.flamerobin.org/license.html.
 
6
 
 
7
  Software distributed under the License is distributed on an "AS IS"
 
8
  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 
9
  License for the specific language governing rights and limitations under
 
10
  the License.
 
11
 
 
12
  The Original Code is FlameRobin (TM).
 
13
 
 
14
  The Initial Developer of the Original Code is Milan Babuskov.
 
15
  The function getTriggerType is adapted from Firebird projects isql code
 
16
 
 
17
  Portions created by the original developer
 
18
  are Copyright (C) 2004 Milan Babuskov.
 
19
 
 
20
  All Rights Reserved.
 
21
 
 
22
  Contributor(s):
 
23
*/
 
24
 
 
25
// For compilers that support precompilation, includes "wx/wx.h".
 
26
#include "wx/wxprec.h"
 
27
 
 
28
#ifdef __BORLANDC__
 
29
    #pragma hdrstop
 
30
#endif
 
31
 
 
32
// for all others, include the necessary headers (this file is usually all you
 
33
// need because it includes almost all "standard" wxWindows headers
 
34
#ifndef WX_PRECOMP
 
35
    #include "wx/wx.h"
 
36
#endif
 
37
//------------------------------------------------------------------------------
 
38
#include <sstream>
 
39
#include <ibpp.h>
 
40
#include "metadataitem.h"
 
41
#include "dberror.h"
 
42
#include "database.h"
 
43
#include "trigger.h"
 
44
//------------------------------------------------------------------------------
 
45
YTrigger::YTrigger():
 
46
        YxMetadataItem()
 
47
{
 
48
        typeM = ntTrigger;
 
49
        infoIsLoadedM = false;
 
50
}
 
51
//------------------------------------------------------------------------------
 
52
bool YTrigger::getTriggerInfo(std::string& object, bool& active, int& position, std::string& type)
 
53
{
 
54
        if (!infoIsLoadedM && !loadInfo())
 
55
                return false;
 
56
        object = objectM;
 
57
        active = activeM;
 
58
        position = positionM;
 
59
        type = triggerTypeM;
 
60
        return true;
 
61
}
 
62
//------------------------------------------------------------------------------
 
63
bool YTrigger::loadInfo(bool force)
 
64
{
 
65
        infoIsLoadedM = false;
 
66
        YDatabase *d = getDatabase();
 
67
        if (!d)
 
68
        {
 
69
                lastError().setMessage("database not set");
 
70
                return false;
 
71
        }
 
72
 
 
73
        IBPP::Database& db = d->getDatabase();
 
74
 
 
75
        try
 
76
        {
 
77
                IBPP::Transaction tr1 = IBPP::TransactionFactory(db, IBPP::amRead);
 
78
                tr1->Start();
 
79
                IBPP::Statement st1 = IBPP::StatementFactory(db, tr1);
 
80
                st1->Prepare(
 
81
                        "select t.rdb$relation_name, t.rdb$trigger_sequence, t.rdb$trigger_inactive, t.rdb$trigger_type "
 
82
                        "from rdb$triggers t where rdb$trigger_name = ? "
 
83
                );
 
84
 
 
85
                st1->Set(1, getName());
 
86
                st1->Execute();
 
87
                st1->Fetch();
 
88
                st1->Get(1, objectM);
 
89
                st1->Get(2, &positionM);
 
90
 
 
91
                short temp;
 
92
                if (st1->IsNull(3))
 
93
                        temp = 0;
 
94
                else
 
95
                        st1->Get(3, &temp);
 
96
                activeM = (temp == 0);
 
97
 
 
98
                int ttype;
 
99
                st1->Get(4, &ttype);
 
100
                triggerTypeM = getTriggerType(ttype);
 
101
                tr1->Commit();
 
102
                infoIsLoadedM = true;
 
103
                if (force)
 
104
                        notify();
 
105
                return true;
 
106
        }
 
107
        catch (IBPP::Exception &e)
 
108
        {
 
109
                lastError().setMessage(e.ErrorMessage());
 
110
        }
 
111
        catch (...)
 
112
        {
 
113
                lastError().setMessage("System error.");
 
114
        }
 
115
 
 
116
        return false;
 
117
}
 
118
//------------------------------------------------------------------------------
 
119
bool YTrigger::getSource(std::string& source) const
 
120
{
 
121
        YDatabase *d = getDatabase();
 
122
        if (!d)
 
123
        {
 
124
                lastError().setMessage("database not set");
 
125
                return false;
 
126
        }
 
127
 
 
128
        IBPP::Database& db = d->getDatabase();
 
129
 
 
130
        try
 
131
        {
 
132
                IBPP::Transaction tr1 = IBPP::TransactionFactory(db, IBPP::amRead);
 
133
                tr1->Start();
 
134
                IBPP::Statement st1 = IBPP::StatementFactory(db, tr1);
 
135
                st1->Prepare("select rdb$trigger_source from rdb$triggers where rdb$trigger_name = ?");
 
136
                st1->Set(1, getName());
 
137
                st1->Execute();
 
138
                st1->Fetch();
 
139
                IBPP::Blob b = IBPP::BlobFactory(st1->Database(), st1->Transaction());
 
140
                st1->Get(1, b);
 
141
 
 
142
                try                             // if blob is empty the exception is thrown
 
143
                {                               // I tried to check st1->IsNull(1) but it doesn't work
 
144
                        b->Open();      // to this hack is the only way (for the time being)
 
145
                }
 
146
                catch (...)
 
147
                {
 
148
                        source = "";
 
149
                        return true;
 
150
                }
 
151
 
 
152
                std::string desc;
 
153
                char buffer[8192];              // 8K block
 
154
                while (true)
 
155
                {
 
156
                        int size = b->Read(buffer, 8192);
 
157
                        if (size <= 0)
 
158
                                break;
 
159
                        buffer[size] = 0;
 
160
                        source += buffer;
 
161
                }
 
162
                b->Close();
 
163
                tr1->Commit();
 
164
                return true;
 
165
        }
 
166
        catch (IBPP::Exception &e)
 
167
        {
 
168
                lastError().setMessage(e.ErrorMessage());
 
169
        }
 
170
        catch (...)
 
171
        {
 
172
                lastError().setMessage("System error.");
 
173
        }
 
174
 
 
175
        return false;
 
176
}
 
177
//------------------------------------------------------------------------------
 
178
std::string YTrigger::getTriggerType(int type)
 
179
{
 
180
        std::string res;
 
181
 
 
182
        std::vector<std::string> prefix_types, suffix_types;
 
183
        prefix_types.push_back("BEFORE");
 
184
        prefix_types.push_back("AFTER");
 
185
 
 
186
        suffix_types.push_back("");
 
187
        suffix_types.push_back("INSERT");
 
188
        suffix_types.push_back("UPDATE");
 
189
        suffix_types.push_back("DELETE");
 
190
 
 
191
        #define TRIGGER_ACTION_PREFIX(value) ((value + 1) & 1)
 
192
        #define TRIGGER_ACTION_SUFFIX(value, slot) (((value + 1) >> (slot * 2 - 1)) & 3)
 
193
 
 
194
        std::string result;
 
195
        int prefix = TRIGGER_ACTION_PREFIX(type);
 
196
        result = prefix_types[prefix];
 
197
 
 
198
        int suffix = TRIGGER_ACTION_SUFFIX(type, 1);
 
199
        result += " " + suffix_types[suffix];
 
200
        suffix = TRIGGER_ACTION_SUFFIX(type, 2);
 
201
        if (suffix)
 
202
                result += " OR " + suffix_types[suffix];
 
203
        suffix = TRIGGER_ACTION_SUFFIX(type, 3);
 
204
        if (suffix)
 
205
                result += " OR " + suffix_types[suffix];
 
206
        return result;
 
207
}
 
208
//------------------------------------------------------------------------------
 
209
YTrigger::firingTimeType YTrigger::getFiringTime()
 
210
{
 
211
        if (!infoIsLoadedM)
 
212
                loadInfo();
 
213
        if (triggerTypeM.substr(0, 6) == "BEFORE")
 
214
                return beforeTrigger;
 
215
        else
 
216
                return afterTrigger;
 
217
}
 
218
//------------------------------------------------------------------------------
 
219
std::string YTrigger::getAlterSql()
 
220
{
 
221
        std::string object, source, type;
 
222
        bool active;
 
223
        int position;
 
224
 
 
225
        if (!getTriggerInfo(object, active, position, type) || !getSource(source))
 
226
                return lastError().getMessage();
 
227
 
 
228
        std::ostringstream sql;
 
229
        sql << "SET TERM ^ ;\nALTER TRIGGER " << nameM;
 
230
        if (active)
 
231
                sql << " ACTIVE\n";
 
232
        else
 
233
                sql << " INACTIVE\n";
 
234
        sql << type;
 
235
        sql << " POSITION ";
 
236
        sql << position << "\n";
 
237
        //sql << " AS ";
 
238
        sql << source;
 
239
        sql << "^\nSET TERM ; ^";
 
240
        return sql.str();
 
241
}
 
242
//------------------------------------------------------------------------------
 
243
std::string YTrigger::getCreateSqlTemplate() const
 
244
{
 
245
        return  "SET TERM ^ ;\n\n"
 
246
                        "CREATE TRIGGER name FOR table/view \n"
 
247
                        " [IN]ACTIVE \n"
 
248
                        " {BEFORE | AFTER} INSERT OR UPDATE OR DELETE \n"
 
249
                        " POSITION number \n"
 
250
                        "AS \n"
 
251
                        "BEGIN \n"
 
252
                        "    /* enter trigger code here */ \n"
 
253
                        "END^\n\n"
 
254
                        "SET TERM ; ^\n";
 
255
}
 
256
//------------------------------------------------------------------------------
 
257
const std::string YTrigger::getTypeName() const
 
258
{
 
259
        return "TRIGGER";
 
260
}
 
261
//------------------------------------------------------------------------------
 
262