std::string getTextParam(XSQLVAR const *var) { //std::cerr << "getTextParam: var->sqltype=" << var->sqltype << std::endl; short size; std::size_t offset = 0; if ((var->sqltype & ~1) == SQL_VARYING) { size = *reinterpret_cast<short*>(var->sqldata); offset = sizeof(short); } else if ((var->sqltype & ~1) == SQL_TEXT) { size = var->sqllen; } else if ((var->sqltype & ~1) == SQL_SHORT) { return format_decimal<short>(var->sqldata, var->sqlscale); } else if ((var->sqltype & ~1) == SQL_LONG) { return format_decimal<int>(var->sqldata, var->sqlscale); } else if ((var->sqltype & ~1) == SQL_INT64) { return format_decimal<long long>(var->sqldata, var->sqlscale); } else throw soci_error("Unexpected string type"); return std::string(var->sqldata + offset, size); }
void statement_impl::describe() { row_->clean_up(); int numcols = backEnd_->prepare_for_describe(); for (int i = 1; i <= numcols; ++i) { data_type dtype; std::string columnName; backEnd_->describe_column(i, dtype, columnName); column_properties props; props.set_name(columnName); props.set_data_type(dtype); switch (dtype) { case dt_string: bind_into<dt_string>(); break; case dt_double: bind_into<dt_double>(); break; case dt_integer: bind_into<dt_integer>(); break; case dt_unsigned_long: bind_into<dt_unsigned_long>(); break; case dt_long_long: bind_into<dt_long_long>(); break; case dt_date: bind_into<dt_date>(); break; default: std::ostringstream msg; msg << "db column type " << dtype <<" not supported for dynamic selects"<<std::endl; throw soci_error(msg.str()); } row_->add_properties(props); } alreadyDescribed_ = true; }
double soci::details::postgresql::string_to_double(char const * buf) { double t; int n; int const converted = sscanf(buf, "%lf%n", &t, &n); if (converted == 1 && static_cast<std::size_t>(n) == strlen(buf)) { // successfully converted to double // and no other characters were found in the buffer return t; } else { throw soci_error("Cannot convert data."); } }
void tmDecode(short type, void * src, std::tm * dst) { switch (type & ~1) { case SQL_TIMESTAMP: isc_decode_timestamp(static_cast<ISC_TIMESTAMP*>(src), dst); break; case SQL_TYPE_TIME: isc_decode_sql_time(static_cast<ISC_TIME*>(src), dst); break; case SQL_TYPE_DATE: isc_decode_sql_date(static_cast<ISC_DATE*>(src), dst); break; default: std::ostringstream msg; msg << "Unexpected type of date/time field (" << type << ")"; throw soci_error(msg.str()); } }
void tmEncode(short type, std::tm * src, void * dst) { switch (type & ~1) { // In Interbase v6 DATE represents a date-only data type, // in InterBase v5 DATE represents a date+time data type. case SQL_TIMESTAMP: isc_encode_timestamp(src, static_cast<ISC_TIMESTAMP*>(dst)); break; case SQL_TYPE_TIME: isc_encode_sql_time(src, static_cast<ISC_TIME*>(dst)); break; case SQL_TYPE_DATE: isc_encode_sql_date(src, static_cast<ISC_DATE*>(dst)); break; default: std::ostringstream msg; msg << "Unexpected type of date/time field (" << type << ")"; throw soci_error(msg.str()); } }
void setTextParam(char const * s, std::size_t size, char * buf_, XSQLVAR * var) { //std::cerr << "setTextParam: var->sqltype=" << var->sqltype << std::endl; short sz = 0; if (size < static_cast<std::size_t>(var->sqllen)) { sz = static_cast<short>(size); } else { sz = var->sqllen; } if ((var->sqltype & ~1) == SQL_VARYING) { std::memcpy(buf_, &sz, sizeof(short)); std::memcpy(buf_ + sizeof(short), s, sz); } else if ((var->sqltype & ~1) == SQL_TEXT) { std::memcpy(buf_, s, sz); if (sz < var->sqllen) { std::memset(buf_+sz, ' ', var->sqllen - sz); } } else if ((var->sqltype & ~1) == SQL_SHORT) { parse_decimal<short, unsigned short>(buf_, var, s); } else if ((var->sqltype & ~1) == SQL_LONG) { parse_decimal<int, unsigned int>(buf_, var, s); } else if ((var->sqltype & ~1) == SQL_INT64) { parse_decimal<long long, unsigned long long>(buf_, var, s); } else if ((var->sqltype & ~1) == SQL_TIMESTAMP || (var->sqltype & ~1) == SQL_TYPE_DATE) { unsigned short year, month, day, hour, min, sec; if (std::sscanf(s, "%hu-%hu-%hu %hu:%hu:%hu", &year, &month, &day, &hour, &min, &sec) != 6) { if (std::sscanf(s, "%hu-%hu-%huT%hu:%hu:%hu", &year, &month, &day, &hour, &min, &sec) != 6) { hour = min = sec = 0; if (std::sscanf(s, "%hu-%hu-%hu", &year, &month, &day) != 3) { throw soci_error("Could not parse timestamp value."); } } } std::tm t; std::memset(&t, 0, sizeof(t)); t.tm_year = year - 1900; t.tm_mon = month - 1; t.tm_mday = day; t.tm_hour = hour; t.tm_min = min; t.tm_sec = sec; std::memcpy(buf_, &t, sizeof(t)); tmEncode(var->sqltype, &t, buf_); } else if ((var->sqltype & ~1) == SQL_TYPE_TIME) { unsigned short hour, min, sec; if (std::sscanf(s, "%hu:%hu:%hu", &hour, &min, &sec) != 3) { throw soci_error("Could not parse timestamp value."); } std::tm t; std::memset(&t, 0, sizeof(t)); t.tm_hour = hour; t.tm_min = min; t.tm_sec = sec; std::memcpy(buf_, &t, sizeof(t)); tmEncode(var->sqltype, &t, buf_); } else { throw soci_error("Unexpected string type."); } }
void setTextParam(char const * s, std::size_t size, char * buf_, XSQLVAR * var) { int const sqltype = var->sqltype & ~1; if (sqltype == SQL_VARYING || sqltype == SQL_TEXT) { if (size > static_cast<std::size_t>(var->sqllen)) { std::ostringstream msg; msg << "Value \"" << s << "\" is too long (" << size << " bytes) to be stored in column of size " << var->sqllen << " bytes"; throw soci_error(msg.str()); } short const sz = static_cast<short>(size); if (sqltype == SQL_VARYING) { std::memcpy(buf_, &sz, sizeof(short)); std::memcpy(buf_ + sizeof(short), s, sz); } else // sqltype == SQL_TEXT { std::memcpy(buf_, s, sz); if (sz < var->sqllen) { std::memset(buf_+sz, ' ', var->sqllen - sz); } } } else if (sqltype == SQL_SHORT) { parse_decimal<short, unsigned short>(buf_, var, s); } else if (sqltype == SQL_LONG) { parse_decimal<int, unsigned int>(buf_, var, s); } else if (sqltype == SQL_INT64) { parse_decimal<long long, unsigned long long>(buf_, var, s); } else if (sqltype == SQL_TIMESTAMP || sqltype == SQL_TYPE_DATE) { unsigned short year, month, day, hour, min, sec; if (std::sscanf(s, "%hu-%hu-%hu %hu:%hu:%hu", &year, &month, &day, &hour, &min, &sec) != 6) { if (std::sscanf(s, "%hu-%hu-%huT%hu:%hu:%hu", &year, &month, &day, &hour, &min, &sec) != 6) { hour = min = sec = 0; if (std::sscanf(s, "%hu-%hu-%hu", &year, &month, &day) != 3) { throw soci_error("Could not parse timestamp value."); } } } std::tm t; std::memset(&t, 0, sizeof(t)); t.tm_year = year - 1900; t.tm_mon = month - 1; t.tm_mday = day; t.tm_hour = hour; t.tm_min = min; t.tm_sec = sec; std::memcpy(buf_, &t, sizeof(t)); tmEncode(var->sqltype, &t, buf_); } else if (sqltype == SQL_TYPE_TIME) { unsigned short hour, min, sec; if (std::sscanf(s, "%hu:%hu:%hu", &hour, &min, &sec) != 3) { throw soci_error("Could not parse timestamp value."); } std::tm t; std::memset(&t, 0, sizeof(t)); t.tm_hour = hour; t.tm_min = min; t.tm_sec = sec; std::memcpy(buf_, &t, sizeof(t)); tmEncode(var->sqltype, &t, buf_); } else { throw soci_error("Unexpected string type."); } }