Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Removed need for Impl parameter to ResultBase::fetch_row() and its derivatives. ResultBase can provide the implementation object to the DBDriver layer, which is the only code that needed this. |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
3f91a82d135d525cedc1ea547c7ea5a0 |
User & Date: | tangent 2015-12-18 22:42:06 |
Context
2015-12-18
| ||
23:29 | Copying the refcounted pointer to the FieldNames object in Row::operator =() instead of copying the field names. We can share the object. check-in: 1e03cb233c user: tangent tags: trunk | |
22:42 | Removed need for Impl parameter to ResultBase::fetch_row() and its derivatives. ResultBase can provide the implementation object to the DBDriver layer, which is the only code that needed this. check-in: 3f91a82d13 user: tangent tags: trunk | |
22:24 | STL on OS X can't cope with vector::at() assignments when the space has only been set aside with vector::reserve(). It wants either a resize() call to set the space aside definitely, or push_back() to extend the vector into the reserved space. (This is probably a sanity check like the old SafeSTL, rather than an actual memory bug, but it has the same effect as a crash.) check-in: 24d069b506 user: tangent tags: trunk | |
Changes
Changes to src/dbdriver.h.
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
virtual void fetch_fields(Fields& fl, ResultBase::Impl& impl) const = 0;
/// \brief Returns the lengths of the fields in the current row
virtual const unsigned long* fetch_lengths(
ResultBase::Impl& impl) const = 0;
/// \brief Returns the next row from the given "use" query result set.
virtual Row fetch_row(ResultBase& res, ResultBase::Impl& impl) = 0;
/// \brief Releases memory used by a result set
virtual void free_result(ResultBase::Impl& impl) const = 0;
/// \brief Get the ID last generated for an INSERT by the DBMS.
///
/// The semantic meaning of this call varies among DBMSes because
|
| |
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
virtual void fetch_fields(Fields& fl, ResultBase::Impl& impl) const = 0; /// \brief Returns the lengths of the fields in the current row virtual const unsigned long* fetch_lengths( ResultBase::Impl& impl) const = 0; /// \brief Returns the next row from the given "use" query result set. virtual Row fetch_row(ResultBase& res) = 0; /// \brief Releases memory used by a result set virtual void free_result(ResultBase::Impl& impl) const = 0; /// \brief Get the ID last generated for an INSERT by the DBMS. /// /// The semantic meaning of this call varies among DBMSes because |
Changes to src/mysql/driver.cpp.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
} mysql_field_seek(pres, 0); // semantics break otherwise! } Row MySQLDriver::fetch_row(ResultBase& res, ResultBase::Impl& impl) // FIXME: Why do we need the impl param? Can't we get that from res? { if (MYSQL_ROW raw = mysql_fetch_row(MYSQL_RES_FROM_IMPL(impl))) { Row::size_type size = res.num_fields(); Row::Impl* pd = new Row::Impl; pd->reserve(size); const unsigned long* lengths = fetch_lengths(impl); for (Row::size_type i = 0; i < size; ++i) { bool is_null = raw[i] == 0; pd->push_back(Row::value_type( is_null ? "NULL" : raw[i], is_null ? 4 : lengths[i], res.field_type(int(i)).base_type(), is_null)); |
| < | | |
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
} mysql_field_seek(pres, 0); // semantics break otherwise! } Row MySQLDriver::fetch_row(ResultBase& res) { if (MYSQL_ROW raw = mysql_fetch_row(MYSQL_RES_FROM_IMPL(res.impl()))) { Row::size_type size = res.num_fields(); Row::Impl* pd = new Row::Impl; pd->reserve(size); const unsigned long* lengths = fetch_lengths(res.impl()); for (Row::size_type i = 0; i < size; ++i) { bool is_null = raw[i] == 0; pd->push_back(Row::value_type( is_null ? "NULL" : raw[i], is_null ? 4 : lengths[i], res.field_type(int(i)).base_type(), is_null)); |
Changes to src/mysql/driver.h.
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
return !mysql_real_query(&mysql_, qstr,
static_cast<unsigned long>(length));
}
/// \brief Returns the next DB row from the given result set.
///
/// Wraps \c mysql_fetch_row() in MySQL C API.
Row fetch_row(ResultBase& res, ResultBase::Impl& impl);
/// \brief Returns the lengths of the fields in the current row
///
/// Wraps \c mysql_fetch_lengths() in MySQL C API.
const unsigned long* fetch_lengths(ResultBase::Impl& impl) const
{
return mysql_fetch_lengths(MYSQL_RES_FROM_IMPL(impl));
|
| |
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
return !mysql_real_query(&mysql_, qstr, static_cast<unsigned long>(length)); } /// \brief Returns the next DB row from the given result set. /// /// Wraps \c mysql_fetch_row() in MySQL C API. Row fetch_row(ResultBase& res); /// \brief Returns the lengths of the fields in the current row /// /// Wraps \c mysql_fetch_lengths() in MySQL C API. const unsigned long* fetch_lengths(ResultBase::Impl& impl) const { return mysql_fetch_lengths(MYSQL_RES_FROM_IMPL(impl)); |
Changes to src/result.cpp.
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
} StoreQueryResult::StoreQueryResult(Impl* res, size_t rows, DBDriver* dbd, bool te) : ResultBase(res, dbd, te), list_type(rows), copacetic_(true) { if (copacetic_) { iterator it = begin(); while (Row row = dbd->fetch_row(*this, *res)) *it++ = row; } } StoreQueryResult& StoreQueryResult::copy(const StoreQueryResult& other) { ................................................................................ throw UseQueryError("Results not fetched"); } else { return Row(); } } if (Row row = driver_->fetch_row(*this, impl())) { const unsigned long* lengths = fetch_lengths(); if (lengths) { return row; } else { if (throw_exceptions()) { throw UseQueryError("Failed to get field lengths"); |
>
|
|
|
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
...
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
} StoreQueryResult::StoreQueryResult(Impl* res, size_t rows, DBDriver* dbd, bool te) : ResultBase(res, dbd, te), list_type(rows), pimpl_(res), copacetic_(true) { if (copacetic_) { iterator it = begin(); while (Row row = dbd->fetch_row(*this)) *it++ = row; } } StoreQueryResult& StoreQueryResult::copy(const StoreQueryResult& other) { ................................................................................ throw UseQueryError("Results not fetched"); } else { return Row(); } } if (Row row = driver_->fetch_row(*this)) { const unsigned long* lengths = fetch_lengths(); if (lengths) { return row; } else { if (throw_exceptions()) { throw UseQueryError("Failed to get field lengths"); |
Changes to src/result.h.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 ... 245 246 247 248 249 250 251 252 253 254 255 256 257 258 ... 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
const FieldTypes::value_type& field_type(int i) const { return types_->at(i); } /// \brief Get a list of the types of the fields within this /// result set. const RefCountedPointer<FieldTypes>& field_types() const { return types_; } /// \brief Returns a pointer to the DBDriver subclass that created /// this object. DBDriver* driver() const { return driver_; } /// \brief Returns the number of fields in this result set size_t num_fields() const { return fields_.size(); } ................................................................................ } /// \brief Fully initialize object StoreQueryResult(Impl* pri, size_t rows, DBDriver* dbd, bool te); /// \brief Destroy result set ~StoreQueryResult() { } /// \brief Returns the number of rows in this result set list_type::size_type num_rows() const { return size(); } /// \brief Copy another StoreQueryResult object's data into this /// object StoreQueryResult& operator =(const StoreQueryResult& rhs) ................................................................................ } private: /// \brief Copy another StoreQueryResult object's contents into this /// one. StoreQueryResult& copy(const StoreQueryResult& other); bool copacetic_; ///< true if initialized from a good result set }; /// \brief Result set type for "use" queries /// /// See the user manual for the reason you might want to use this even /// though its interface is less friendly than StoreQueryResult's. |
> > > > > > > > > > > > > | |
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 ... 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 ... 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
const FieldTypes::value_type& field_type(int i) const { return types_->at(i); } /// \brief Get a list of the types of the fields within this /// result set. const RefCountedPointer<FieldTypes>& field_types() const { return types_; } /// \brief Access the driver-level implementation result set info /// /// This is primarily for the benefit of the DBDriver subclass, /// not end-user code. virtual Impl& impl() const = 0; /// \brief Returns a pointer to the DBDriver subclass that created /// this object. DBDriver* driver() const { return driver_; } /// \brief Returns the number of fields in this result set size_t num_fields() const { return fields_.size(); } ................................................................................ } /// \brief Fully initialize object StoreQueryResult(Impl* pri, size_t rows, DBDriver* dbd, bool te); /// \brief Destroy result set ~StoreQueryResult() { } /// \brief Access the driver-level implementation result set info /// /// This is primarily for the benefit of the DBDriver subclass, /// not end-user code. Impl& impl() const { return *pimpl_; } /// \brief Returns the number of rows in this result set list_type::size_type num_rows() const { return size(); } /// \brief Copy another StoreQueryResult object's data into this /// object StoreQueryResult& operator =(const StoreQueryResult& rhs) ................................................................................ } private: /// \brief Copy another StoreQueryResult object's contents into this /// one. StoreQueryResult& copy(const StoreQueryResult& other); RefCountedPointer<Impl> pimpl_; ///< Driver-level result set info bool copacetic_; ///< true if initialized from good result }; /// \brief Result set type for "use" queries /// /// See the user manual for the reason you might want to use this even /// though its interface is less friendly than StoreQueryResult's. |