firebird/common.cpp
Go to the documentation of this file.
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 #include "common.h"
9 #include <soci-backend.h>
10 #include <ibase.h> // FireBird
11 #include <cstddef>
12 #include <cstring>
13 #include <cstdio>
14 #include <sstream>
15 #include <iostream>
16 #include <string>
17 
18 namespace soci
19 {
20 
21 namespace details
22 {
23 
24 namespace firebird
25 {
26 
27 char * allocBuffer(XSQLVAR* var)
28 {
29  std::size_t size;
30  int type = var->sqltype & ~1;
31  if (type == SQL_VARYING)
32  {
33  size = var->sqllen + sizeof(short);
34  }
35  else if (type == SQL_TIMESTAMP || type == SQL_TYPE_TIME
36  || type == SQL_TYPE_DATE)
37  {
38  size = sizeof(std::tm);
39  }
40  else
41  {
42  size = var->sqllen;
43  }
44 
45  return new char[size];
46 }
47 
48 void tmEncode(short type, std::tm * src, void * dst)
49 {
50  switch (type & ~1)
51  {
52  // In Interbase v6 DATE represents a date-only data type,
53  // in InterBase v5 DATE represents a date+time data type.
54  case SQL_TIMESTAMP:
55  isc_encode_timestamp(src, static_cast<ISC_TIMESTAMP*>(dst));
56  break;
57  case SQL_TYPE_TIME:
58  isc_encode_sql_time(src, static_cast<ISC_TIME*>(dst));
59  break;
60  case SQL_TYPE_DATE:
61  isc_encode_sql_date(src, static_cast<ISC_DATE*>(dst));
62  break;
63  default:
64  std::ostringstream msg;
65  msg << "Unexpected type of date/time field (" << type << ")";
66  throw soci_error(msg.str());
67  }
68 }
69 
70 void tmDecode(short type, void * src, std::tm * dst)
71 {
72  switch (type & ~1)
73  {
74  case SQL_TIMESTAMP:
75  isc_decode_timestamp(static_cast<ISC_TIMESTAMP*>(src), dst);
76  break;
77  case SQL_TYPE_TIME:
78  isc_decode_sql_time(static_cast<ISC_TIME*>(src), dst);
79  break;
80  case SQL_TYPE_DATE:
81  isc_decode_sql_date(static_cast<ISC_DATE*>(src), dst);
82  break;
83  default:
84  std::ostringstream msg;
85  msg << "Unexpected type of date/time field (" << type << ")";
86  throw soci_error(msg.str());
87  }
88 }
89 
90 void setTextParam(char const * s, std::size_t size, char * buf_,
91  XSQLVAR * var)
92 {
93  //std::cerr << "setTextParam: var->sqltype=" << var->sqltype << std::endl;
94  short sz = 0;
95  if (size < static_cast<std::size_t>(var->sqllen))
96  {
97  sz = static_cast<short>(size);
98  }
99  else
100  {
101  sz = var->sqllen;
102  }
103 
104  if ((var->sqltype & ~1) == SQL_VARYING)
105  {
106  std::memcpy(buf_, &sz, sizeof(short));
107  std::memcpy(buf_ + sizeof(short), s, sz);
108  }
109  else if ((var->sqltype & ~1) == SQL_TEXT)
110  {
111  std::memcpy(buf_, s, sz);
112  if (sz < var->sqllen)
113  {
114  std::memset(buf_+sz, ' ', var->sqllen - sz);
115  }
116  }
117  else if ((var->sqltype & ~1) == SQL_SHORT)
118  {
119  parse_decimal<short, unsigned short>(buf_, var, s);
120  }
121  else if ((var->sqltype & ~1) == SQL_LONG)
122  {
123  parse_decimal<int, unsigned int>(buf_, var, s);
124  }
125  else if ((var->sqltype & ~1) == SQL_INT64)
126  {
127  parse_decimal<long long, unsigned long long>(buf_, var, s);
128  }
129  else if ((var->sqltype & ~1) == SQL_TIMESTAMP
130  || (var->sqltype & ~1) == SQL_TYPE_DATE)
131  {
132  unsigned short year, month, day, hour, min, sec;
133  if (std::sscanf(s, "%hu-%hu-%hu %hu:%hu:%hu",
134  &year, &month, &day, &hour, &min, &sec) != 6)
135  {
136  if (std::sscanf(s, "%hu-%hu-%huT%hu:%hu:%hu",
137  &year, &month, &day, &hour, &min, &sec) != 6)
138  {
139  hour = min = sec = 0;
140  if (std::sscanf(s, "%hu-%hu-%hu", &year, &month, &day) != 3)
141  {
142  throw soci_error("Could not parse timestamp value.");
143  }
144  }
145  }
146  std::tm t;
147  std::memset(&t, 0, sizeof(t));
148  t.tm_year = year - 1900;
149  t.tm_mon = month - 1;
150  t.tm_mday = day;
151  t.tm_hour = hour;
152  t.tm_min = min;
153  t.tm_sec = sec;
154  std::memcpy(buf_, &t, sizeof(t));
155  tmEncode(var->sqltype, &t, buf_);
156  }
157  else if ((var->sqltype & ~1) == SQL_TYPE_TIME)
158  {
159  unsigned short hour, min, sec;
160  if (std::sscanf(s, "%hu:%hu:%hu", &hour, &min, &sec) != 3)
161  {
162  throw soci_error("Could not parse timestamp value.");
163  }
164  std::tm t;
165  std::memset(&t, 0, sizeof(t));
166  t.tm_hour = hour;
167  t.tm_min = min;
168  t.tm_sec = sec;
169  std::memcpy(buf_, &t, sizeof(t));
170  tmEncode(var->sqltype, &t, buf_);
171  }
172  else
173  {
174  throw soci_error("Unexpected string type.");
175  }
176 }
177 
178 std::string getTextParam(XSQLVAR const *var)
179 {
180  //std::cerr << "getTextParam: var->sqltype=" << var->sqltype << std::endl;
181  short size;
182  std::size_t offset = 0;
183 
184  if ((var->sqltype & ~1) == SQL_VARYING)
185  {
186  size = *reinterpret_cast<short*>(var->sqldata);
187  offset = sizeof(short);
188  }
189  else if ((var->sqltype & ~1) == SQL_TEXT)
190  {
191  size = var->sqllen;
192  }
193  else if ((var->sqltype & ~1) == SQL_SHORT)
194  {
195  return format_decimal<short>(var->sqldata, var->sqlscale);
196  }
197  else if ((var->sqltype & ~1) == SQL_LONG)
198  {
199  return format_decimal<int>(var->sqldata, var->sqlscale);
200  }
201  else if ((var->sqltype & ~1) == SQL_INT64)
202  {
203  return format_decimal<long long>(var->sqldata, var->sqlscale);
204  }
205  else
206  throw soci_error("Unexpected string type");
207 
208  return std::string(var->sqldata + offset, size);
209 }
210 
211 } // namespace firebird
212 
213 } // namespace details
214 
215 } // namespace soci
void tmEncode(short type, std::tm *src, void *dst)
void setTextParam(char const *s, std::size_t size, char *buf_, XSQLVAR *var)
char * allocBuffer(XSQLVAR *var)
SOCI_FIREBIRD_DECL firebird_backend_factory const firebird
void tmDecode(short type, void *src, std::tm *dst)
std::string getTextParam(XSQLVAR const *var)


asr_lib_ism
Author(s): Hanselmann Fabian, Heller Florian, Heizmann Heinrich, Kübler Marcel, Mehlhaus Jonas, Meißner Pascal, Qattan Mohamad, Reckling Reno, Stroh Daniel
autogenerated on Wed Jan 8 2020 04:02:40