aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odb/pgsql/query.cxx94
-rw-r--r--odb/pgsql/query.hxx83
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 <sstream>
#include <odb/pgsql/query.hxx>
+#include <odb/pgsql/statement.hxx>
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<std::size_t, std::size_t> parameter_offset;
+ std::vector<parameter_offset> parameter_offsets_;
+
mutable std::vector<bind> bind_;
mutable binding binding_;
@@ -1501,47 +1498,45 @@ namespace odb
std::size_t size_;
};
- // @@ BIT
+ // BIT
//
- // template <typename T>
- // struct query_param_impl<T, id_bit>: query_param
- // {
- // query_param_impl (ref_bind<T> r) : query_param (&r.ref) {}
- // query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);}
+ template <typename T>
+ struct query_param_impl<T, id_bit>: query_param
+ {
+ query_param_impl (ref_bind<T> r) : query_param (&r.ref) {}
+ query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);}
- // virtual bool
- // init ()
- // {
- // init (*static_cast<const T*> (value_));
- // return false;
- // }
+ virtual bool
+ init ()
+ {
+ return init (*static_cast<const T*> (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<T, id_bit>::set_image (
- // buffer_, sizeof (buffer_), size, dummy, v);
- // size_ = static_cast<unsigned long> (size);
- // }
+ private:
+ bool
+ init (const T& v)
+ {
+ bool dummy;
+ std::size_t size, cap (buffer_.capacity ());
+ value_traits<T, id_bit>::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_;
};