libtabula

Check-in [3f91a82d13]
Login

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:3f91a82d135d525cedc1ea547c7ea5a0fc55554d
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
Hide Diffs Unified Diffs Ignore Whitespace Patch

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.