| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- //
- // MySQLException.cpp
- //
- // $Id: //poco/1.4/Data/MySQL/src/ResultMetadata.cpp#1 $
- //
- // Library: Data
- // Package: MySQL
- // Module: ResultMetadata
- //
- // Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
- // and Contributors.
- //
- // Permission is hereby granted, free of charge, to any person or organization
- // obtaining a copy of the software and accompanying documentation covered by
- // this license (the "Software") to use, reproduce, display, distribute,
- // execute, and transmit the Software, and to prepare derivative works of the
- // Software, and to permit third-parties to whom the Software is furnished to
- // do so, all subject to the following:
- //
- // The copyright notices in the Software and this entire statement, including
- // the above license grant, this restriction and the following disclaimer,
- // must be included in all copies of the Software, in whole or in part, and
- // all derivative works of the Software, unless such copies or derivative
- // works are solely in the form of machine-executable object code generated by
- // a source language processor.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
- // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
- // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
- // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- // DEALINGS IN THE SOFTWARE.
- //
- #include "Poco/Data/MySQL/ResultMetadata.h"
- #include "Poco/Data/MySQL/MySQLException.h"
- #include <cstring>
- namespace
- {
- class ResultMetadataHandle
- /// Simple exception-safe wrapper
- {
- public:
- explicit ResultMetadataHandle(MYSQL_STMT* stmt)
- {
- h = mysql_stmt_result_metadata(stmt);
- }
- ~ResultMetadataHandle()
- {
- if (h)
- {
- mysql_free_result(h);
- }
- }
- operator MYSQL_RES* ()
- {
- return h;
- }
- private:
- MYSQL_RES* h;
- };
- std::size_t fieldSize(const MYSQL_FIELD& field)
- /// Convert field MySQL-type and field MySQL-length to actual field length
- {
- switch (field.type)
- {
- case MYSQL_TYPE_TINY: return sizeof(char);
- case MYSQL_TYPE_SHORT: return sizeof(short);
- case MYSQL_TYPE_INT24:
- case MYSQL_TYPE_LONG: return sizeof(Poco::Int32);
- case MYSQL_TYPE_FLOAT: return sizeof(float);
- case MYSQL_TYPE_DOUBLE: return sizeof(double);
- case MYSQL_TYPE_LONGLONG: return sizeof(Poco::Int64);
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_TIME:
- case MYSQL_TYPE_DATETIME:
- return sizeof(MYSQL_TIME);
- case MYSQL_TYPE_DECIMAL:
- case MYSQL_TYPE_NEWDECIMAL:
- case MYSQL_TYPE_STRING:
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- return field.length;
- default:
- throw Poco::Data::MySQL::StatementException("unknown field type");
- }
- }
- Poco::Data::MetaColumn::ColumnDataType fieldType(const MYSQL_FIELD& field)
- /// Convert field MySQL-type to Poco-type
- {
- bool unsig = ((field.flags & UNSIGNED_FLAG) == UNSIGNED_FLAG);
- switch (field.type)
- {
- case MYSQL_TYPE_TINY:
- if (unsig) return Poco::Data::MetaColumn::FDT_UINT8;
- return Poco::Data::MetaColumn::FDT_INT8;
- case MYSQL_TYPE_SHORT:
- if (unsig) return Poco::Data::MetaColumn::FDT_UINT16;
- return Poco::Data::MetaColumn::FDT_INT16;
- case MYSQL_TYPE_INT24:
- case MYSQL_TYPE_LONG:
- if (unsig) return Poco::Data::MetaColumn::FDT_UINT32;
- return Poco::Data::MetaColumn::FDT_INT32;
- case MYSQL_TYPE_FLOAT:
- return Poco::Data::MetaColumn::FDT_FLOAT;
- case MYSQL_TYPE_DOUBLE:
- return Poco::Data::MetaColumn::FDT_DOUBLE;
- case MYSQL_TYPE_LONGLONG:
- if (unsig) return Poco::Data::MetaColumn::FDT_UINT64;
- return Poco::Data::MetaColumn::FDT_INT64;
- case MYSQL_TYPE_STRING:
- case MYSQL_TYPE_VAR_STRING:
- return Poco::Data::MetaColumn::FDT_STRING;
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- return Poco::Data::MetaColumn::FDT_BLOB;
- default:
- return Poco::Data::MetaColumn::FDT_UNKNOWN;
- }
- }
- } // namespace
- namespace Poco {
- namespace Data {
- namespace MySQL {
- void ResultMetadata::reset()
- {
- _columns.resize(0);
- _row.resize(0);
- _buffer.resize(0);
- _lengths.resize(0);
- _isNull.resize(0);
- }
- void ResultMetadata::init(MYSQL_STMT* stmt)
- {
- ResultMetadataHandle h(stmt);
- if (!h)
- {
- // all right, it is normal
- // querys such an "INSERT INTO" just does not have result at all
- reset();
- return;
- }
- std::size_t count = mysql_num_fields(h);
- MYSQL_FIELD* fields = mysql_fetch_fields(h);
- std::size_t commonSize = 0;
- _columns.reserve(count);
- {for (std::size_t i = 0; i < count; i++)
- {
- _columns.push_back(MetaColumn(
- i, // position
- fields[i].name, // name
- fieldType(fields[i]), // type
- fieldSize(fields[i]), // length
- 0, // TODO: precision
- !IS_NOT_NULL(fields[i].flags) // nullable
- ));
- commonSize += _columns[i].length();
- }}
- _buffer.resize(commonSize);
- _row.resize(count);
- _lengths.resize(count);
- _isNull.resize(count);
- std::size_t offset = 0;
- {for (std::size_t i = 0; i < count; i++)
- {
- std::memset(&_row[i], 0, sizeof(MYSQL_BIND));
- _row[i].buffer_type = fields[i].type;
- _row[i].buffer_length = static_cast<unsigned int>(_columns[i].length());
- _row[i].buffer = &_buffer[0] + offset;
- _row[i].length = &_lengths[i];
- _row[i].is_null = &_isNull[i];
-
- offset += _row[i].buffer_length;
- }}
- }
- std::size_t ResultMetadata::columnsReturned() const
- {
- return static_cast<std::size_t>(_columns.size());
- }
- const MetaColumn& ResultMetadata::metaColumn(std::size_t pos) const
- {
- return _columns[pos];
- }
- MYSQL_BIND* ResultMetadata::row()
- {
- return &_row[0];
- }
- std::size_t ResultMetadata::length(std::size_t pos) const
- {
- return _lengths[pos];
- }
- const unsigned char* ResultMetadata::rawData(std::size_t pos) const
- {
- return reinterpret_cast<const unsigned char*>(_row[pos].buffer);
- }
- bool ResultMetadata::isNull(std::size_t pos) const
- {
- return (_isNull[pos] != 0);
- }
- }}} // namespace Poco::Data::MySQL
|