OCILIB (C and C++ Driver for Oracle)  4.7.6
Open source and cross platform Oracle Driver delivering efficient access to Oracle databases.
BindArray.hpp
1 /*
2  * OCILIB - C Driver for Oracle (C Wrapper for Oracle OCI)
3  *
4  * Website: http://www.ocilib.net
5  *
6  * Copyright (c) 2007-2023 Vincent ROGIER <vince.rogier@ocilib.net>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #pragma once
22 
23 #include "ocilibcpp/support.hpp"
24 
25 // ReSharper disable CppClangTidyModernizePassByValue
26 
27 namespace ocilib
28 {
29  namespace support
30  {
31  inline BindArray::BindArray(const ocilib::Statement& statement, const ostring& name, unsigned int mode) : BindObject(statement, name, mode), _object(nullptr)
32  {
33 
34  }
35 
36  template<class T>
37  void BindArray::SetVector(std::vector<T>& vector, bool isPlSqlTable, unsigned int elemSize)
38  {
39  _object = core::OnAllocate(new BindArrayObject<T>(_statement, GetName(), vector, isPlSqlTable, GetMode(), elemSize));
40  }
41 
42  inline BindArray::~BindArray() noexcept
43  {
44  delete core::OnDeallocate(_object);
45  }
46 
47  template<class T>
48  typename BindResolver<T>::OutputType* BindArray::GetData() const
49  {
50  return static_cast<typename BindResolver<T>::OutputType*>(*(dynamic_cast<BindArrayObject<T>*> (_object)));
51  }
52 
53  inline void BindArray::SetInData()
54  {
55 
56  if (GetMode() & OCI_BDM_IN || _object->IsHandleObject())
57  {
58  _object->SetInData();
59  }
60  }
61 
62  inline void BindArray::SetOutData()
63  {
64  if (GetMode() & OCI_BDM_OUT)
65  {
66  _object->SetOutData();
67  }
68  }
69 
70  inline unsigned int BindArray::GetSize() const
71  {
72  return _object ? _object->GetSize() : _statement.GetBindArraySize();
73  }
74 
75  inline unsigned int BindArray::GetSizeForBindCall() const
76  {
77  return _object ? _object->GetSizeForBindCall() : 0;
78  }
79 
80 
81  template<class T>
82  BindArray::BindArrayObject<T>::BindArrayObject(const ocilib::Statement& statement, const ostring& name, ObjectVector& vector, bool isPlSqlTable, unsigned int mode, unsigned int elemSize)
83  : _statement(statement), _name(name), _vector(vector), _data(nullptr), _isPlSqlTable(isPlSqlTable), _mode(mode), _elemCount(BindArrayObject<T>::GetSize()), _elemSize(elemSize)
84  {
85  AllocData();
86  }
87 
88  template<class T>
89  BindArray::BindArrayObject<T>::~BindArrayObject() noexcept
90  {
91  FreeData();
92  }
93 
94  template<class T>
95  void BindArray::BindArrayObject<T>::AllocData()
96  {
97  _data = core::OnAllocate(new NativeType[_elemCount], _elemCount);
98 
99  memset(_data, 0, sizeof(NativeType) * _elemCount);
100  }
101 
102  template<>
103  inline void BindArray::BindArrayObject<ocilib::ostring>::AllocData()
104  {
105  const size_t count = _elemSize * _elemCount;
106 
107  _data = core::OnAllocate(new otext[count], count);
108 
109  memset(_data, 0, count * sizeof(otext));
110  }
111 
112  template<>
113  inline void BindArray::BindArrayObject<ocilib::Raw> ::AllocData()
114  {
115  const size_t count = _elemSize * _elemCount;
116 
117  _data = core::OnAllocate(new unsigned char[count], count);
118 
119  memset(_data, 0, count * sizeof(unsigned char));
120  }
121 
122  template<class T>
123  void BindArray::BindArrayObject<T>::FreeData() const
124  {
125  delete[] core::OnDeallocate(_data);
126  }
127 
128  template<class T>
129  void BindArray::BindArrayObject<T>::SetInData()
130  {
131  typename ObjectVector::iterator it, it_end;
132 
133  unsigned int index = 0;
134  const unsigned int currElemCount = GetSize();
135 
136  for (it = _vector.begin(), it_end = _vector.end(); it != it_end && index < _elemCount && index < currElemCount; ++it, ++index)
137  {
138  _data[index] = static_cast<NativeType>(*it);
139  }
140  }
141 
142  template<>
143  inline void BindArray::BindArrayObject<ocilib::ostring>::SetInData()
144  {
145  std::vector<ostring>::iterator it, it_end;
146 
147  unsigned int index = 0;
148  const unsigned int currElemCount = GetSize();
149 
150  for (it = _vector.begin(), it_end = _vector.end(); it != it_end && index < _elemCount && index < currElemCount; ++it, ++index)
151  {
152  const ostring& value = *it;
153 
154  memcpy(_data + (_elemSize * index), value.c_str(), (value.size() + 1) * sizeof(otext));
155  }
156  }
157 
158  template<>
159  inline void BindArray::BindArrayObject<ocilib::Raw>::SetInData()
160  {
161  std::vector<Raw>::iterator it, it_end;
162 
163  unsigned int index = 0;
164  const unsigned int currElemCount = GetSize();
165 
166  for (it = _vector.begin(), it_end = _vector.end(); it != it_end && index < _elemCount && index < currElemCount; ++it, ++index)
167  {
168  Raw& value = *it;
169 
170  if (!value.empty())
171  {
172  memcpy(_data + (_elemSize * index), &value[0], value.size());
173  }
174 
175  OCI_BindSetDataSizeAtPos(OCI_GetBind2(_statement, GetName().c_str()), index + 1, static_cast<unsigned int>(value.size()));
176  }
177  }
178 
179  template<class T>
180  void BindArray::BindArrayObject<T>::SetOutData()
181  {
182  typename ObjectVector::iterator it, it_end;
183 
184  unsigned int index = 0;
185  const unsigned int currElemCount = GetSize();
186 
187  for (it = _vector.begin(), it_end = _vector.end(); it != it_end && index < _elemCount && index < currElemCount; ++it, ++index)
188  {
189  *it = static_cast<NativeType&>(_data[index]);
190  }
191  }
192 
193  template<>
194  inline void BindArray::BindArrayObject<ocilib::ostring>::SetOutData()
195  {
196  std::vector<ostring>::iterator it, it_end;
197 
198  OCI_Bind* pBind = core::Check(OCI_GetBind2(_statement, GetName().c_str()));
199 
200  unsigned int index = 0;
201  const unsigned int currElemCount = GetSize();
202 
203  for (it = _vector.begin(), it_end = _vector.end(); it != it_end && index < _elemCount && index < currElemCount; ++it, ++index)
204  {
205  otext* currData = _data + (_elemSize * sizeof(otext) * index);
206 
207  (*it).assign(currData, currData + core::Check(OCI_BindGetDataSizeAtPos(pBind, index + 1)));
208  }
209  }
210 
211  template<>
212  inline void BindArray::BindArrayObject<ocilib::Raw>::SetOutData()
213  {
214  std::vector<Raw>::iterator it, it_end;
215 
216  OCI_Bind* pBind = core::Check(OCI_GetBind2(_statement, GetName().c_str()));
217 
218  unsigned int index = 0;
219  const unsigned int currElemCount = GetSize();
220 
221  for (it = _vector.begin(), it_end = _vector.end(); it != it_end && index < _elemCount && index < currElemCount; ++it, ++index)
222  {
223  unsigned char* currData = _data + (_elemSize * index);
224 
225  (*it).assign(currData, currData + core::Check(OCI_BindGetDataSizeAtPos(pBind, index + 1)));
226  }
227  }
228 
229  template<class T>
230  ostring BindArray::BindArrayObject<T>::GetName() const
231  {
232  return _name;
233  }
234 
235  template<class T>
236  bool BindArray::BindArrayObject<T>::IsHandleObject() const
237  {
238  return BindResolver<T>::IsHandle;
239  }
240 
241  template<class T>
242  unsigned int BindArray::BindArrayObject<T>::GetSize() const
243  {
244  return _isPlSqlTable ? static_cast<unsigned int>(_vector.size()) : _statement.GetBindArraySize();
245  }
246 
247  template<class T>
248  unsigned int BindArray::BindArrayObject<T>::GetSizeForBindCall() const
249  {
250  return _isPlSqlTable ? static_cast<unsigned int>(_vector.size()) : 0;
251  }
252 
253  template<class T>
254  BindArray::BindArrayObject<T>::operator ObjectVector& () const
255  {
256  return _vector;
257  }
258 
259  template<class T>
260  BindArray::BindArrayObject<T>::operator NativeType* () const
261  {
262  return _data;
263  }
264  }
265 }
Object used for executing SQL or PL/SQL statement and returning the produced results.
Definition: types.hpp:5559
OCI_SYM_PUBLIC boolean OCI_API OCI_BindSetDataSizeAtPos(OCI_Bind *bnd, unsigned int position, unsigned int size)
Set the size of the element at the given position in the bind input array.
OCI_SYM_PUBLIC OCI_Bind *OCI_API OCI_GetBind2(OCI_Statement *stmt, const otext *name)
Return a bind handle from its name.
OCI_SYM_PUBLIC unsigned int OCI_API OCI_BindGetDataSizeAtPos(OCI_Bind *bnd, unsigned int position)
Return the actual size of the element at the given position in the bind input array.
struct OCI_Bind OCI_Bind
Internal bind representation.
Definition: types.h:148
OCILIB ++ Namespace.
std::basic_string< otext, std::char_traits< otext >, std::allocator< otext > > ostring
string class wrapping the OCILIB otext * type and OTEXT() macros ( see Character sets )
Definition: config.hpp:120
std::vector< unsigned char > Raw
C++ counterpart of SQL RAW data type.
Definition: config.hpp:138