~mapopa/flamerobin/master

« back to all changes in this revision

Viewing changes to src/metadata/domain.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
 
 
16
  Portions created by the original developer
 
17
  are Copyright (C) 2004 Milan Babuskov.
 
18
 
 
19
  All Rights Reserved.
 
20
 
 
21
  Contributor(s): Nando Dessena
 
22
*/
 
23
 
 
24
//------------------------------------------------------------------------------
 
25
// For compilers that support precompilation, includes "wx/wx.h".
 
26
#include "wx/wxprec.h"
 
27
#ifdef __BORLANDC__
 
28
    #pragma hdrstop
 
29
#endif
 
30
 
 
31
// for all others, include the necessary headers (this file is usually all you
 
32
// need because it includes almost all "standard" wxWindows headers
 
33
#ifndef WX_PRECOMP
 
34
    #include "wx/wx.h"
 
35
#endif
 
36
 
 
37
#include <sstream>
 
38
#include <string>
 
39
#include <ibpp.h>
 
40
#include "dberror.h"
 
41
#include "database.h"
 
42
#include "domain.h"
 
43
//------------------------------------------------------------------------------
 
44
YDomain::YDomain():
 
45
        YxMetadataItem()
 
46
{
 
47
        typeM = ntDomain;
 
48
        infoLoadedM = false;    // I had a 2 hour session with debugger to found out that this was missing
 
49
}
 
50
//------------------------------------------------------------------------------
 
51
bool YDomain::loadInfo()
 
52
{
 
53
        IBPP::Database& db = getDatabase()->getDatabase();
 
54
 
 
55
        try
 
56
        {
 
57
                IBPP::Transaction tr1 = IBPP::TransactionFactory(db, IBPP::amRead);
 
58
                tr1->Start();
 
59
                IBPP::Statement st1 = IBPP::StatementFactory(db, tr1);
 
60
                st1->Prepare(
 
61
                        "select t.rdb$type, f.rdb$field_sub_type, f.rdb$field_length,"
 
62
                        " f.rdb$field_precision, f.rdb$field_scale, c.rdb$character_set_name"
 
63
                        " from rdb$fields f"
 
64
                        " join rdb$types t on f.rdb$field_type=t.rdb$type"
 
65
                        " left outer join rdb$character_sets c on c.rdb$character_set_id = f.rdb$character_set_id"
 
66
                        " where f.rdb$field_name = ?"
 
67
                        " and t.rdb$field_name='RDB$FIELD_TYPE'"
 
68
                );
 
69
 
 
70
                st1->Set(1, getName());
 
71
                st1->Execute();
 
72
                st1->Fetch();
 
73
                st1->Get(1, &datatypeM);
 
74
                if (st1->IsNull(2))
 
75
                        subtypeM = 0;
 
76
                else
 
77
                        st1->Get(2, &subtypeM);
 
78
                st1->Get(3, &lengthM);
 
79
                if (st1->IsNull(4))
 
80
                        precisionM = 0;
 
81
                else
 
82
                        st1->Get(4, &precisionM);
 
83
                if (st1->IsNull(5))
 
84
                        scaleM = 0;
 
85
                else
 
86
                        st1->Get(5, &scaleM);
 
87
                if (st1->IsNull(6))
 
88
                        charsetM = "";
 
89
                else
 
90
                {
 
91
                        st1->Get(6, charsetM);
 
92
                        charsetM.erase(charsetM.find_last_not_of(" ")+1);
 
93
                }
 
94
 
 
95
                tr1->Commit();
 
96
                notify();
 
97
                infoLoadedM = true;
 
98
                return true;
 
99
        }
 
100
        catch (IBPP::Exception &e)
 
101
        {
 
102
                lastError().setMessage(e.ErrorMessage());
 
103
        }
 
104
        catch (...)
 
105
        {
 
106
                lastError().setMessage("System error.");
 
107
        }
 
108
        return false;
 
109
}
 
110
//------------------------------------------------------------------------------
 
111
//! returns column's datatype as human readable string. It can also be used to construct DDL for tables
 
112
std::string YDomain::getDatatypeAsString()
 
113
{
 
114
        if (!infoLoadedM)
 
115
                loadInfo();
 
116
 
 
117
        std::ostringstream retval;              // this will be returned
 
118
 
 
119
        // special case (mess that some tools (ex. IBExpert) make by only setting scale and not changing type)
 
120
        if (datatypeM == 27 && scaleM < 0)
 
121
        {
 
122
                retval << "Numeric(15," << -scaleM << ")";
 
123
                return retval.str();
 
124
        }
 
125
 
 
126
        // LONG&INT64: INT/SMALLINT (prec=0), DECIMAL(sub_type=2), NUMERIC(sub_type=1)
 
127
        if (datatypeM == 7 || datatypeM == 8 || datatypeM == 16)
 
128
        {
 
129
                if (scaleM == 0)
 
130
                {
 
131
                        if (datatypeM == 7)
 
132
                                return "Smallint";
 
133
                        else if (datatypeM == 8)
 
134
                                return "Integer";
 
135
                        else
 
136
                                return "Numeric(18,0)";
 
137
                }
 
138
                else
 
139
                {
 
140
                        retval << (subtypeM == 2 ? "Decimal(" : "Numeric(");
 
141
                        if (precisionM <= 0 || precisionM > 18)
 
142
                                retval << 18;
 
143
                        else
 
144
                                retval << precisionM;
 
145
                        retval << "," << -scaleM << ")";
 
146
                        return retval.str();
 
147
                }
 
148
        }
 
149
 
 
150
        std::string names[] = {
 
151
                "Char",
 
152
                "Float",
 
153
                "Double precision",
 
154
                "Timestamp",
 
155
                "Varchar",
 
156
                "Blob",
 
157
                "Date",
 
158
                "Time"
 
159
        };
 
160
        short mapper[8] = { 14, 10, 27, 35, 37, 261, 12, 13 };
 
161
 
 
162
        for (int i=0; i<8; ++i)
 
163
        {
 
164
                if (mapper[i] == datatypeM)
 
165
                {
 
166
                        retval << names[i];
 
167
                        break;
 
168
                }
 
169
        }
 
170
 
 
171
        if (datatypeM == 14 || datatypeM == 37) // char & varchar, add (length)
 
172
                retval << "(" << lengthM << ")";
 
173
 
 
174
        if (datatypeM == 261)   // blob
 
175
                retval << " sub_type " << subtypeM;
 
176
 
 
177
        return retval.str();
 
178
}
 
179
//------------------------------------------------------------------------------
 
180
void YDomain::getDatatypeParts(std::string& type, std::string& size, std::string& scale)
 
181
{
 
182
        using namespace std;
 
183
        string datatype = getDatatypeAsString();
 
184
        string::size_type p1 = datatype.find("(");
 
185
        if (p1 != string::npos)
 
186
        {
 
187
                type = datatype.substr(0, p1);
 
188
                string::size_type p2 = datatype.find(",");
 
189
                if (p2 == string::npos)
 
190
                        p2 = datatype.find(")");
 
191
                else
 
192
                {
 
193
                        string::size_type p3 = datatype.find(")");
 
194
                        scale = datatype.substr(p2+1, p3-p2-1);
 
195
                }
 
196
                size = datatype.substr(p1+1, p2-p1-1);
 
197
        }
 
198
        else
 
199
                type = datatype;
 
200
}
 
201
//------------------------------------------------------------------------------
 
202
std::string YDomain::getCharset()
 
203
{
 
204
        if (!infoLoadedM)
 
205
                loadInfo();
 
206
 
 
207
        return charsetM;
 
208
}
 
209
//------------------------------------------------------------------------------
 
210
std::string YDomain::getCreateSqlTemplate() const
 
211
{
 
212
        return  "CREATE DOMAIN domain_name\n"
 
213
            "AS datatype\n"
 
214
            "DEFAULT {literal | NULL | USER}\n"
 
215
            "[NOT NULL]\n"
 
216
            "[CHECK (dom_search_condition)]\n"
 
217
            "COLLATE collation;\n";
 
218
}
 
219
//------------------------------------------------------------------------------
 
220
const std::string YDomain::getTypeName() const
 
221
{
 
222
        return "DOMAIN";
 
223
}
 
224
//------------------------------------------------------------------------------
 
225