1 //
2 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //
7
8 #define SOCI_FIREBIRD_SOURCE
9 #include "soci/firebird/soci-firebird.h"
10 #include "firebird/common.h"
11
12 using namespace soci;
13 using namespace soci::details;
14 using namespace soci::details::firebird;
15
bind_by_pos(int & position,void * data,exchange_type type)16 void firebird_vector_use_type_backend::bind_by_pos(int & position,
17 void * data, exchange_type type)
18 {
19 if (statement_.boundByName_)
20 {
21 throw soci_error(
22 "Binding for use elements must be either by position or by name.");
23 }
24
25 position_ = position-1;
26 data_ = data;
27 type_ = type;
28
29 ++position;
30
31 statement_.useType_ = eVector;
32 statement_.uses_.push_back(static_cast<void*>(this));
33
34 XSQLVAR *var = statement_.sqlda2p_->sqlvar+position_;
35
36 buf_ = allocBuffer(var);
37 var->sqldata = buf_;
38 var->sqlind = &indISCHolder_;
39
40 statement_.boundByPos_ = true;
41 }
42
bind_by_name(std::string const & name,void * data,exchange_type type)43 void firebird_vector_use_type_backend::bind_by_name(
44 std::string const & name, void * data, exchange_type type)
45 {
46 if (statement_.boundByPos_)
47 {
48 throw soci_error(
49 "Binding for use elements must be either by position or by name.");
50 }
51
52 std::map <std::string, int> :: iterator idx =
53 statement_.names_.find(name);
54
55 if (idx == statement_.names_.end())
56 {
57 throw soci_error("Missing use element for bind by name (" + name + ")");
58 }
59
60 position_ = idx->second;
61 data_ = data;
62 type_ = type;
63
64 statement_.useType_ = eVector;
65 statement_.uses_.push_back(static_cast<void*>(this));
66
67 XSQLVAR *var = statement_.sqlda2p_->sqlvar+position_;
68
69 buf_ = allocBuffer(var);
70 var->sqldata = buf_;
71 var->sqlind = &indISCHolder_;
72
73 statement_.boundByName_ = true;
74 }
75
pre_use(indicator const * ind)76 void firebird_vector_use_type_backend::pre_use(indicator const * ind)
77 {
78 inds_ = ind;
79 }
80
81 namespace
82 {
83 template <typename T>
getUseVectorValue(void * v,std::size_t index)84 T* getUseVectorValue(void *v, std::size_t index)
85 {
86 std::vector<T> *src =
87 static_cast<std::vector<T> *>(v);
88
89 std::vector<T> &v_ = *src;
90 return &(v_[index]);
91 }
92 }
93
exchangeData(std::size_t row)94 void firebird_vector_use_type_backend::exchangeData(std::size_t row)
95 {
96 // first prepare indicators
97 if (inds_ != NULL)
98 {
99 switch (inds_[row])
100 {
101 case i_null:
102 indISCHolder_ = -1;
103 break;
104 case i_ok:
105 indISCHolder_ = 0;
106 break;
107 default:
108 throw soci_error("Use element used with non-supported indicator type.");
109 }
110 }
111
112 XSQLVAR * var = statement_.sqlda2p_->sqlvar+position_;
113
114 // then set parameters for query execution
115 switch (type_)
116 {
117 // simple cases
118 case x_char:
119 setTextParam(getUseVectorValue<char>(data_, row), 1, buf_, var);
120 break;
121 case x_short:
122 to_isc<short>(
123 static_cast<void*>(getUseVectorValue<short>(data_, row)),
124 var);
125 break;
126 case x_integer:
127 to_isc<int>(
128 static_cast<void*>(getUseVectorValue<int>(data_, row)),
129 var);
130 break;
131 case x_long_long:
132 to_isc<long long>(
133 static_cast<void*>(getUseVectorValue<long long>(data_, row)),
134 var);
135 break;
136 case x_double:
137 to_isc<double>(
138 static_cast<void*>(getUseVectorValue<double>(data_, row)),
139 var);
140 break;
141
142 // cases that require adjustments and buffer management
143 case x_stdstring:
144 {
145 std::string *tmp = getUseVectorValue<std::string>(data_, row);
146 setTextParam(tmp->c_str(), tmp->size(), buf_, var);
147 }
148 break;
149 case x_stdtm:
150 tmEncode(var->sqltype,
151 getUseVectorValue<std::tm>(data_, row), buf_);
152 break;
153 // Not supported
154 // case x_cstring:
155 // case x_blob:
156 default:
157 throw soci_error("Use element used with non-supported type.");
158 } // switch
159 }
160
size()161 std::size_t firebird_vector_use_type_backend::size()
162 {
163 std::size_t sz = 0; // dummy initialization to please the compiler
164 switch (type_)
165 {
166 // simple cases
167 case x_char:
168 sz = getVectorSize<char> (data_);
169 break;
170 case x_short:
171 sz = getVectorSize<short> (data_);
172 break;
173 case x_integer:
174 sz = getVectorSize<int> (data_);
175 break;
176 case x_long_long:
177 sz = getVectorSize<long long> (data_);
178 break;
179 case x_double:
180 sz = getVectorSize<double> (data_);
181 break;
182 case x_stdstring:
183 sz = getVectorSize<std::string> (data_);
184 break;
185 case x_stdtm:
186 sz = getVectorSize<std::tm> (data_);
187 break;
188
189 default:
190 throw soci_error("Use vector element used with non-supported type.");
191 }
192
193 return sz;
194 }
195
clean_up()196 void firebird_vector_use_type_backend::clean_up()
197 {
198 if (buf_ != NULL)
199 {
200 delete [] buf_;
201 buf_ = NULL;
202 }
203 std::vector<void*>::iterator it =
204 std::find(statement_.uses_.begin(), statement_.uses_.end(), this);
205 if (it != statement_.uses_.end())
206 statement_.uses_.erase(it);
207 }
208