1 | #pragma once |
2 | |
3 | #include <mysqlxx/Types.h> |
4 | #include <mysqlxx/Value.h> |
5 | #include <mysqlxx/ResultBase.h> |
6 | #include <mysqlxx/Exception.h> |
7 | |
8 | |
9 | namespace mysqlxx |
10 | { |
11 | |
12 | class ResultBase; |
13 | |
14 | |
15 | /** Строка результата. |
16 | * В отличие от mysql++, |
17 | * представляет собой обёртку над MYSQL_ROW (char**), ссылается на ResultBase, не владеет сам никакими данными. |
18 | * Это значит, что если будет уничтожен объект результата или соединение, |
19 | * или будет задан следующий запрос, то Row станет некорректным. |
20 | * При использовании UseQueryResult, в памяти хранится только одна строка результата, |
21 | * это значит, что после чтения следующей строки, предыдущая становится некорректной. |
22 | */ |
23 | class Row |
24 | { |
25 | private: |
26 | /** @brief Pointer to bool data member, for use by safe bool conversion operator. |
27 | * @see http://www.artima.com/cppsource/safebool.html |
28 | * Взято из mysql++. |
29 | */ |
30 | typedef MYSQL_ROW Row::*private_bool_type; |
31 | |
32 | public: |
33 | /** Для возможности отложенной инициализации. */ |
34 | Row() |
35 | { |
36 | } |
37 | |
38 | /** Для того, чтобы создать Row, используйте соответствующие методы UseQueryResult или StoreQueryResult. */ |
39 | Row(MYSQL_ROW row_, ResultBase * res_, MYSQL_LENGTHS lengths_) |
40 | : row(row_), res(res_), lengths(lengths_) |
41 | { |
42 | } |
43 | |
44 | /** Получить значение по индексу. |
45 | * Здесь используется int, а не unsigned, чтобы не было неоднозначности с тем же методом, принимающим const char *. |
46 | */ |
47 | Value operator[] (int n) const |
48 | { |
49 | if (unlikely(static_cast<size_t>(n) >= res->getNumFields())) |
50 | throw Exception("Index of column is out of range." ); |
51 | return Value(row[n], lengths[n], res); |
52 | } |
53 | |
54 | /** Get value by column name. Less efficient. */ |
55 | Value operator[] (const char * name) const; |
56 | |
57 | Value operator[] (const std::string & name) const |
58 | { |
59 | return operator[](name.c_str()); |
60 | } |
61 | |
62 | /** Получить значение по индексу. */ |
63 | Value at(size_t n) const |
64 | { |
65 | return operator[](n); |
66 | } |
67 | |
68 | /** Количество столбцов. */ |
69 | size_t size() const { return res->getNumFields(); } |
70 | |
71 | /** Является ли пустым? Такой объект используется, чтобы обозначить конец результата |
72 | * при использовании UseQueryResult. Или это значит, что объект не инициализирован. |
73 | * Вы можете использовать вместо этого преобразование в bool. |
74 | */ |
75 | bool empty() const { return row == nullptr; } |
76 | |
77 | /** Преобразование в bool. |
78 | * (Точнее - в тип, который преобразуется в bool, и с которым больше почти ничего нельзя сделать.) |
79 | */ |
80 | operator private_bool_type() const { return row == nullptr ? nullptr : &Row::row; } |
81 | |
82 | private: |
83 | MYSQL_ROW row{}; |
84 | ResultBase * res{}; |
85 | MYSQL_LENGTHS lengths{}; |
86 | }; |
87 | |
88 | } |
89 | |