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 Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/dbdriver.h.

   191    191   	virtual void fetch_fields(Fields& fl, ResultBase::Impl& impl) const = 0;
   192    192   	
   193    193   	/// \brief Returns the lengths of the fields in the current row
   194    194   	virtual const unsigned long* fetch_lengths(
   195    195   			ResultBase::Impl& impl) const = 0;
   196    196   
   197    197   	/// \brief Returns the next row from the given "use" query result set.
   198         -	virtual Row fetch_row(ResultBase& res, ResultBase::Impl& impl) = 0;
          198  +	virtual Row fetch_row(ResultBase& res) = 0;
   199    199   
   200    200   	/// \brief Releases memory used by a result set
   201    201   	virtual void free_result(ResultBase::Impl& impl) const = 0;
   202    202   
   203    203   	/// \brief Get the ID last generated for an INSERT by the DBMS.
   204    204   	///
   205    205   	/// The semantic meaning of this call varies among DBMSes because

Changes to src/mysql/driver.cpp.

   139    139   	}
   140    140   
   141    141   	mysql_field_seek(pres, 0);	// semantics break otherwise!
   142    142   }
   143    143   
   144    144   
   145    145   Row
   146         -MySQLDriver::fetch_row(ResultBase& res, ResultBase::Impl& impl)
   147         -// FIXME: Why do we need the impl param?  Can't we get that from res?
          146  +MySQLDriver::fetch_row(ResultBase& res)
   148    147   {
   149         -	if (MYSQL_ROW raw = mysql_fetch_row(MYSQL_RES_FROM_IMPL(impl))) {
          148  +	if (MYSQL_ROW raw = mysql_fetch_row(MYSQL_RES_FROM_IMPL(res.impl()))) {
   150    149   		Row::size_type size = res.num_fields();
   151    150   		Row::Impl* pd = new Row::Impl;
   152    151   		pd->reserve(size);
   153         -		const unsigned long* lengths = fetch_lengths(impl);
          152  +		const unsigned long* lengths = fetch_lengths(res.impl());
   154    153   		for (Row::size_type i = 0; i < size; ++i) {
   155    154   			bool is_null = raw[i] == 0;
   156    155   			pd->push_back(Row::value_type(
   157    156   					is_null ? "NULL" : raw[i],
   158    157   					is_null ? 4 : lengths[i],
   159    158   					res.field_type(int(i)).base_type(),
   160    159   					is_null));

Changes to src/mysql/driver.h.

   194    194   		return !mysql_real_query(&mysql_, qstr,
   195    195   				static_cast<unsigned long>(length));
   196    196   	}
   197    197   
   198    198   	/// \brief Returns the next DB row from the given result set.
   199    199   	///
   200    200   	/// Wraps \c mysql_fetch_row() in MySQL C API.
   201         -	Row fetch_row(ResultBase& res, ResultBase::Impl& impl);
          201  +	Row fetch_row(ResultBase& res);
   202    202   
   203    203   	/// \brief Returns the lengths of the fields in the current row
   204    204   	///
   205    205   	/// Wraps \c mysql_fetch_lengths() in MySQL C API.
   206    206   	const unsigned long* fetch_lengths(ResultBase::Impl& impl) const
   207    207   	{
   208    208   		return mysql_fetch_lengths(MYSQL_RES_FROM_IMPL(impl));

Changes to src/result.cpp.

    89     89   }
    90     90   
    91     91   
    92     92   StoreQueryResult::StoreQueryResult(Impl* res, size_t rows,
    93     93   		DBDriver* dbd, bool te) :
    94     94   ResultBase(res, dbd, te),
    95     95   list_type(rows),
           96  +pimpl_(res),
    96     97   copacetic_(true)
    97     98   {
    98     99   	if (copacetic_) {
    99    100   		iterator it = begin();
   100         -		while (Row row = dbd->fetch_row(*this, *res)) *it++ = row;
          101  +		while (Row row = dbd->fetch_row(*this)) *it++ = row;
   101    102   	}
   102    103   }
   103    104   
   104    105   
   105    106   StoreQueryResult&
   106    107   StoreQueryResult::copy(const StoreQueryResult& other)
   107    108   {
................................................................................
   154    155   			throw UseQueryError("Results not fetched");
   155    156   		}
   156    157   		else {
   157    158   			return Row();
   158    159   		}
   159    160   	}
   160    161   
   161         -	if (Row row = driver_->fetch_row(*this, impl())) {
          162  +	if (Row row = driver_->fetch_row(*this)) {
   162    163   		const unsigned long* lengths = fetch_lengths();
   163    164   		if (lengths) {
   164    165   			return row;
   165    166   		}
   166    167   		else {
   167    168   			if (throw_exceptions()) {
   168    169   				throw UseQueryError("Failed to get field lengths");

Changes to src/result.h.

   146    146   	const FieldTypes::value_type& field_type(int i) const
   147    147   			{ return types_->at(i); }
   148    148   
   149    149   	/// \brief Get a list of the types of the fields within this
   150    150   	/// result set.
   151    151   	const RefCountedPointer<FieldTypes>& field_types() const
   152    152   			{ return types_; }
          153  +
          154  +	/// \brief Access the driver-level implementation result set info
          155  +	///
          156  +	/// This is primarily for the benefit of the DBDriver subclass,
          157  +	/// not end-user code.
          158  +	virtual Impl& impl() const = 0;
   153    159   
   154    160   	/// \brief Returns a pointer to the DBDriver subclass that created
   155    161   	/// this object.
   156    162   	DBDriver* driver() const { return driver_; }
   157    163   
   158    164   	/// \brief Returns the number of fields in this result set
   159    165   	size_t num_fields() const { return fields_.size(); }
................................................................................
   245    251   	}
   246    252   	
   247    253   	/// \brief Fully initialize object
   248    254   	StoreQueryResult(Impl* pri, size_t rows, DBDriver* dbd, bool te);
   249    255   
   250    256   	/// \brief Destroy result set
   251    257   	~StoreQueryResult() { }
          258  +
          259  +	/// \brief Access the driver-level implementation result set info
          260  +	///
          261  +	/// This is primarily for the benefit of the DBDriver subclass,
          262  +	/// not end-user code.
          263  +	Impl& impl() const { return *pimpl_; }
   252    264   
   253    265   	/// \brief Returns the number of rows in this result set
   254    266   	list_type::size_type num_rows() const { return size(); }
   255    267   
   256    268   	/// \brief Copy another StoreQueryResult object's data into this
   257    269   	/// object
   258    270   	StoreQueryResult& operator =(const StoreQueryResult& rhs)
................................................................................
   270    282   	}
   271    283   
   272    284   private:
   273    285   	/// \brief Copy another StoreQueryResult object's contents into this
   274    286   	/// one.
   275    287   	StoreQueryResult& copy(const StoreQueryResult& other);
   276    288   
   277         -	bool copacetic_;	///< true if initialized from a good result set
          289  +	RefCountedPointer<Impl> pimpl_;	///< Driver-level result set info
          290  +	bool copacetic_;				///< true if initialized from good result
   278    291   };
   279    292   
   280    293   
   281    294   /// \brief Result set type for "use" queries
   282    295   ///
   283    296   /// See the user manual for the reason you might want to use this even
   284    297   /// though its interface is less friendly than StoreQueryResult's.