From 0f04eb5bc2069a63c86489258da06f007d8ac3c7 Mon Sep 17 00:00:00 2001 From: Constantin Michael Date: Tue, 5 Jul 2011 13:04:34 +0200 Subject: Implement PostgreSQL specific query --- odb/pgsql/query.cxx | 94 ++++++++++++++++++++++++++++++++++++++--------------- odb/pgsql/query.hxx | 83 ++++++++++++++++++++++------------------------ 2 files changed, 107 insertions(+), 70 deletions(-) diff --git a/odb/pgsql/query.cxx b/odb/pgsql/query.cxx index ba39564..5bf1f52 100644 --- a/odb/pgsql/query.cxx +++ b/odb/pgsql/query.cxx @@ -9,6 +9,7 @@ #include #include +#include using namespace std; @@ -27,6 +28,7 @@ namespace odb query (const query& q) : clause_ (q.clause_), parameters_ (q.parameters_), + parameter_offsets_ (q.parameter_offsets_), bind_ (q.bind_), binding_ (0, 0), values_ (q.values_), @@ -56,6 +58,8 @@ namespace odb assert (lengths_.size () == n); assert (formats_.size () == n); assert (types_.size () == n); + + statement::bind_param (native_binding_, binding_); } } @@ -66,6 +70,7 @@ namespace odb { clause_ = q.clause_; parameters_ = q.parameters_; + parameter_offsets_ = q.parameter_offsets_; bind_ = q.bind_; size_t n (bind_.size ()); @@ -92,6 +97,8 @@ namespace odb native_binding_.values = &values_[0]; native_binding_.lengths = &lengths_[0]; native_binding_.formats = &formats_[0]; + + statement::bind_param (native_binding_, binding_); } } @@ -101,33 +108,58 @@ namespace odb query& query:: operator+= (const query& q) { - size_t n (clause_.size ()); + size_t cur_pos (0); - if (n != 0 && clause_[n - 1] != ' ' && - !q.clause_.empty () && q.clause_[0] != ' ') - clause_ += ' '; + // Append the argument clause to the clause of this instance. + // + for (size_t i (0), + p (parameters_.size () + 1), + e (q.parameter_offsets_.size ()); + i < e; + ++i, ++p) + { + size_t n (clause_.size ()); + + if (n != 0 && clause_[n - 1] != ' ' && q.clause_[cur_pos] != ' ') + clause_ += ' '; + + parameter_offset o (q.parameter_offsets_[i]); - clause_ += q.clause_; + // Append all characters up to the start of the current + // parameter specifier, including the '$'. + // + clause_.append (q.clause_, cur_pos, o.first - cur_pos + 1); + + // Advance current position in source clause to 1 element past + // the current parameter specifier. + // + cur_pos = o.second; + + // Insert the correct parameter number and update the parameter + // offset to describe its offset in the new clause. + // + o.first = clause_.size () - 1; + ostringstream os; + os << p; + clause_.append (os.str ()); + o.second = clause_.size (); + + parameter_offsets_.push_back (o); + } - // Reset parameter indexes. + // Copy any remaining characters in q.clause_. // - bool unquoted (true); - for (std::size_t i (0), e (clause_.size ()), p(1); i < e; ++i) + if (cur_pos < q.clause_.length ()) { - // $'s are legal in identifiers in PostgreSQL. - // - if (clause_[i] == '"') - unquoted = !unquoted; + size_t n (clause_.size ()); - if (unquoted && clause_[i] == '$') - { - ostringstream ss; - ss << p++; - clause_[++i] = ss.str()[0]; - } + if (n != 0 && clause_[n - 1] != ' ' && q.clause_[cur_pos] != ' ') + clause_ += ' '; + + clause_.append (q.clause_, cur_pos, string::npos); } - n = bind_.size (); + size_t n = bind_.size (); parameters_.insert ( parameters_.end (), q.parameters_.begin (), q.parameters_.end ()); @@ -164,6 +196,8 @@ namespace odb native_binding_.lengths = &lengths_[0]; native_binding_.formats = &formats_[0]; native_binding_.count = n; + + statement::bind_param (native_binding_, binding_); } return *this; @@ -177,11 +211,16 @@ namespace odb if (n != 0 && clause_[n - 1] != ' ') clause_ += ' '; + parameter_offset o; + o.first = clause_.length (); + ostringstream ss; ss << parameters_.size () + 1; - clause_ += '$' + ss.str (); + o.second = clause_.length (); + parameter_offsets_.push_back (o); + parameters_.push_back (p); bind_.push_back (bind ()); binding_.bind = &bind_[0]; @@ -199,25 +238,27 @@ namespace odb native_binding_.lengths = &lengths_[0]; native_binding_.formats = &formats_[0]; - types_.push_back (p->oid ()); - // native_binding_.count should always equal binding_.count. // At this point, we know that we have added one element to // each array, so there is no need to check. // native_binding_.count = binding_.count; + + types_.push_back (p->oid ()); + + statement::bind_param (native_binding_, binding_); } - binding& query:: + native_binding& query:: parameters_binding () const { size_t n (parameters_.size ()); - binding& r (binding_); if (n == 0) - return r; + return native_binding_; bool inc_ver (false); + binding& r (binding_); bind* b (&bind_[0]); for (size_t i (0); i < n; ++i) @@ -237,7 +278,8 @@ namespace odb if (inc_ver) r.version++; - return r; + statement::bind_param (native_binding_, binding_); + return native_binding_; } std::string query:: diff --git a/odb/pgsql/query.hxx b/odb/pgsql/query.hxx index 632fde5..1d34545 100644 --- a/odb/pgsql/query.hxx +++ b/odb/pgsql/query.hxx @@ -126,14 +126,8 @@ namespace odb std::string clause () const; - binding& - parameters_binding () const; - native_binding& - native_parameters_binding () const - { - return native_binding_; - } + parameters_binding () const; const unsigned int* parameter_types () const @@ -213,6 +207,9 @@ namespace odb std::string clause_; parameters_type parameters_; + typedef std::pair parameter_offset; + std::vector parameter_offsets_; + mutable std::vector bind_; mutable binding binding_; @@ -1501,47 +1498,45 @@ namespace odb std::size_t size_; }; - // @@ BIT + // BIT // - // template - // struct query_param_impl: query_param - // { - // query_param_impl (ref_bind r) : query_param (&r.ref) {} - // query_param_impl (val_bind v) : query_param (0) {init (v.val);} + template + struct query_param_impl: query_param + { + query_param_impl (ref_bind r) : query_param (&r.ref) {} + query_param_impl (val_bind v) : query_param (0) {init (v.val);} - // virtual bool - // init () - // { - // init (*static_cast (value_)); - // return false; - // } + virtual bool + init () + { + return init (*static_cast (value_)); + } - // virtual void - // bind (pgsql::bind* b) - // { - // b->type = bind::bit; - // b->buffer = buffer_; - // b->capacity = sizeof (buffer_); - // b->size = &size_; - // } + virtual void + bind (pgsql::bind* b) + { + b->type = bind::bit; + b->buffer = buffer_.data (); + b->capacity = buffer_.capacity (); + b->size = &size_; + } - // private: - // void - // init (const T& v) - // { - // bool dummy; - // std::size_t size; - // value_traits::set_image ( - // buffer_, sizeof (buffer_), size, dummy, v); - // size_ = static_cast (size); - // } + private: + bool + init (const T& v) + { + bool dummy; + std::size_t size, cap (buffer_.capacity ()); + value_traits::set_image (buffer_, size, dummy, v); + size_ = size; - // private: - // // Max 64 bit. - // // - // unsigned char buffer_[8]; - // unsigned long size_; - // }; + return cap != buffer_.capacity (); + } + + private: + details::ubuffer buffer_; + std::size_t size_; + }; // VARBIT // @@ -1584,7 +1579,7 @@ namespace odb } private: - details::buffer buffer_; + details::ubuffer buffer_; std::size_t size_; }; -- cgit v1.1