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