ClickHouse/libs/libmysqlxx/include/mysqlxx/Row.h

114 lines
4.0 KiB
C
Raw Normal View History

2011-03-03 19:57:34 +00:00
#ifndef MYSQLXX_ROW_H
#define MYSQLXX_ROW_H
#include <mysqlxx/Types.h>
#include <mysqlxx/String.h>
#include <mysqlxx/ResultBase.h>
namespace mysqlxx
{
class ResultBase;
2011-03-18 20:26:54 +00:00
/** Строка результата.
* В отличие от mysql++,
* представляет собой обёртку над MYSQL_ROW (char**), ссылается на ResultBase, не владеет сам никакими данными.
* Это значит, что если будет уничтожен объект результата или соединение,
* или будет задан следующий запрос, то Row станет некорректным.
* При использовании UseQueryResult, в памяти хранится только одна строка результата,
* это значит, что после чтения следующей строки, предыдущая становится некорректной.
*/
2011-03-03 19:57:34 +00:00
class Row
{
2011-03-05 16:56:30 +00:00
private:
/** @brief Pointer to bool data member, for use by safe bool conversion operator.
* @see http://www.artima.com/cppsource/safebool.html
* Взято из mysql++.
*/
typedef MYSQL_ROW Row::*private_bool_type;
2011-03-15 20:56:42 +00:00
void this_type_does_not_support_comparisons() const {}
2011-03-03 19:57:34 +00:00
public:
2011-03-18 20:26:54 +00:00
/** Для возможности отложенной инициализации. */
2011-03-03 19:57:34 +00:00
Row() : row(NULL), res(NULL)
{
}
2011-03-18 20:26:54 +00:00
/** Для того, чтобы создать Row, используйте соответствующие методы UseQueryResult или StoreQueryResult. */
Row(MYSQL_ROW row_, ResultBase * res_, MYSQL_LENGTHS lengths_)
: row(row_), res(res_), lengths(lengths_)
2011-03-03 19:57:34 +00:00
{
}
2011-03-18 20:26:54 +00:00
/** Получить значение по индексу.
* Здесь используется int, а не unsigned, чтобы не было неоднозначности с тем же методом, принимающим const char *.
*/
2011-03-04 20:58:19 +00:00
String operator[] (int n) const
2011-03-03 19:57:34 +00:00
{
2011-03-18 20:26:54 +00:00
if (unlikely(static_cast<size_t>(n) >= res->getNumFields()))
throw Exception("Index of column is out of range.");
return String(row[n], lengths[n], res);
2011-03-03 19:57:34 +00:00
}
2011-03-18 20:26:54 +00:00
/** Получить значение по имени. Слегка менее эффективно. */
2011-03-04 20:58:19 +00:00
String operator[] (const char * name) const
2011-03-03 19:57:34 +00:00
{
unsigned n = res->getNumFields();
MYSQL_FIELDS fields = res->getFields();
for (unsigned i = 0; i < n; ++i)
if (!strcmp(name, fields[i].name))
return operator[](i);
throw Exception(std::string("Unknown column ") + name);
}
2011-03-18 20:26:54 +00:00
/** Получить значение по индексу. */
2011-03-04 20:58:19 +00:00
String at(size_t n) const
2011-03-03 19:57:34 +00:00
{
return operator[](n);
}
2011-03-18 20:26:54 +00:00
/** Количество столбцов. */
2011-03-09 20:11:29 +00:00
size_t size() const { return res->getNumFields(); }
2011-03-18 20:26:54 +00:00
/** Является ли пустым? Такой объект используется, чтобы обозначить конец результата
* при использовании UseQueryResult. Или это значит, что объект не инициализирован.
* Вы можете использовать вместо этого преобразование в bool.
*/
2011-03-09 20:11:29 +00:00
bool empty() const { return row == NULL; }
2011-03-18 20:26:54 +00:00
/** Преобразование в bool.
* (Точнее - в тип, который преобразуется в bool, и с которым больше почти ничего нельзя сделать.)
*/
2011-03-05 16:56:30 +00:00
operator private_bool_type() const { return row == NULL ? NULL : &Row::row; }
2011-03-03 19:57:34 +00:00
private:
MYSQL_ROW row;
ResultBase * res;
MYSQL_LENGTHS lengths;
2011-03-03 19:57:34 +00:00
};
2011-03-15 20:56:42 +00:00
2011-03-18 20:26:54 +00:00
/** Следующие две функции генерируют ошибку компиляции при попытке использовать операторы == или !=.
*/
2011-03-15 20:56:42 +00:00
template <typename T>
bool operator!=(const Row & lhs, const T & rhs)
{
lhs.this_type_does_not_support_comparisons();
return false;
}
template <typename T>
bool operator==(const Row & lhs, const T & rhs)
{
lhs.this_type_does_not_support_comparisons();
return false;
}
2011-03-03 19:57:34 +00:00
}
#endif