Hi.

In extending the Dbo build in types to custom types, I've found
it convenient to add a building block void * blob type, to
make it straightforward to implement fixed sized elements,
rather than using the std::vector<unsigned char> which
I found a bit clumsy for this purpose.

Attached is a patch for the added void * type. (Note that
the size parameter is needed set the blob size correctly in
statement->bind().)

Graeme Gill.

*** orig_319/src/Wt/Dbo/SqlConnection   Sun Oct 17 01:54:31 2010
--- 319/src/Wt/Dbo/SqlConnection        Mon Nov 28 18:19:33 2011
***************
*** 150,155 ****
--- 150,156 ----
    /*! \brief Returns the blob type.
     *
     * \sa SqlStatement::bind(int, const std::vector<unsigned char>&)
+    * \sa SqlStatement::bind(int, const void *)
     */
    virtual const char *blobType() const = 0;
    //@}
*** orig_319/src/Wt/Dbo/SqlStatement    Tue Oct 19 20:21:24 2010
--- 319/src/Wt/Dbo/SqlStatement Mon Nov 28 18:17:10 2011
***************
*** 95,100 ****
--- 95,104 ----
     */
    virtual void bind(int column, const std::vector<unsigned char>& value) = 0;
  
+   /*! \brief Binds a value to a column.
+    */
+   virtual void bind(int column, const void *value, int size) = 0;
+ 
    /*! \brief Binds \c null to a column.
     */
    virtual void bindNull(int column) = 0;
***************
*** 177,182 ****
--- 181,192 ----
    virtual bool getResult(int column, std::vector<unsigned char> *value,
                         int size) = 0;
  
+   /*! \brief Fetches a result value.
+    *
+    * Returns \c true when the value was not \c null.
+    */
+   virtual bool getResult(int column, void *value, int size) = 0;
+ 
    /*! \brief Returns the prepared SQL string.
     */
    virtual std::string sql() const = 0;
*** orig_319/src/Wt/Dbo/SqlTraits       Fri Jan 28 21:58:27 2011
--- 319/src/Wt/Dbo/SqlTraits    Mon Nov 28 18:20:01 2011
***************
*** 37,42 ****
--- 37,43 ----
   *  - enum types
   *  - <tt>bool</tt>
   *  - <tt>std::vector<unsigned char></tt> (binary data)
+  *  - <tt>void *</tt> (binary data)
   *  - <tt>boost::optional<T></tt>: to make the type optional
   *    (allowing an SQL <tt>null</tt> value)
   *
*** orig_319/src/Wt/Dbo/StdSqlTraits    Thu Jan 13 19:45:18 2011
--- 319/src/Wt/Dbo/StdSqlTraits Mon Nov 28 18:17:23 2011
***************
*** 128,133 ****
--- 128,143 ----
                   int column, int size);
  };
  
+ template<>
+ struct WTDBO_API sql_value_traits<void *, void>
+ {
+   static const bool specialized = true;
+ 
+   static const char *type(SqlConnection *conn, int size);
+   static void bind(const void *v, SqlStatement *statement, int column, int 
size);
+   static bool read(void *v, SqlStatement *statement, int column, int size);
+ };
+ 
  template<typename T>
  struct sql_value_traits<boost::optional<T>, void>
  {
*** orig_319/src/Wt/Dbo/StdSqlTraits.C  Thu Jan 13 19:45:18 2011
--- 319/src/Wt/Dbo/StdSqlTraits.C       Mon Nov 28 18:17:32 2011
***************
*** 241,246 ****
--- 241,266 ----
    return statement->getResult(column, &v, size);
  }
  
+   /*
+    * void * 
+    */
+ 
+ const char *sql_value_traits<void *>
+ ::type(SqlConnection *conn, int size)
+ {
+   return conn->blobType();
+ }
+ 
+ void sql_value_traits<void *>::bind(const void *v, SqlStatement *statement, 
int column, int size)
+ {
+   statement->bind(column, v, size);
+ }
+ 
+ bool sql_value_traits<void *>::read(void *v, SqlStatement *statement, int 
column, int size)
+ {
+   return statement->getResult(column, v, size);
+ }
+ 
    }
  }
  
*** orig_319/src/Wt/Dbo/backend/Sqlite3.C       Tue Mar 22 02:09:57 2011
--- 319/src/Wt/Dbo/backend/Sqlite3.C    Mon Nov 28 18:23:53 2011
***************
*** 175,180 ****
--- 175,195 ----
      handleErr(err);
    }
  
+   virtual void bind(int column, const void *value, int size)
+   {
+     DEBUG(std::cerr << this << " bind " << column << " (blob, size=" <<
+         size << ")" << std::endl);
+ 
+     int err;
+ 
+     if (size == 0)
+       err = sqlite3_bind_blob(st_, column + 1, "", 0, SQLITE_TRANSIENT);
+     else 
+       err = sqlite3_bind_blob(st_, column + 1, value, size, SQLITE_STATIC);
+ 
+     handleErr(err);
+   }
+ 
    virtual void bindNull(int column)
    {
      DEBUG(std::cerr << this << " bind " << column << " null" << std::endl);
***************
*** 417,422 ****
--- 432,456 ----
      return true;
    }
  
+   virtual bool getResult(int column, void *value, int size)
+   {
+     if (sqlite3_column_type(st_, column) == SQLITE_NULL)
+       return false;
+ 
+     int s = sqlite3_column_bytes(st_, column);
+     unsigned char *v = (unsigned char *)sqlite3_column_blob(st_, column);
+ 
+     if (s < size)             // Or should we error ?
+       size = s;
+     memmove(value, v, s);
+ 
+     DEBUG(std::cerr << this 
+         << " result blob " << column << " (blob, size = " << s << ")"
+         << std::endl);
+ 
+     return true;
+   }
+ 
   
    virtual std::string sql() const {
      return sql_;
*** orig_319/src/Wt/Dbo/backend/Postgres.C      Fri Apr  1 21:35:50 2011
--- 319/src/Wt/Dbo/backend/Postgres.C   Mon Nov 28 18:23:39 2011
***************
*** 158,163 ****
--- 158,182 ----
      // statement if necessary because the type changes
    }
  
+   virtual void bind(int column, const void *value, int size)
+   {
+     DEBUG(std::cerr << this << " bind " << column << " (blob, size=" <<
+         size << ")" << std::endl);
+ 
+     for (int i = (int)params_.size(); i <= column; ++i)
+       params_.push_back(Param());
+ 
+     Param& p = params_[column];
+     p.value.resize(size);
+     if (size > 0)
+       memcpy(const_cast<char *>(p.value.data()), value, size);
+     p.isbinary = true;
+     p.isnull = false;
+ 
+     // FIXME if first null was bound, check here and invalidate the prepared
+     // statement if necessary because the type changes
+   }
+ 
    virtual void bindNull(int column)
    {
      DEBUG(std::cerr << this << " bind " << column << " null" << std::endl);
***************
*** 420,425 ****
--- 439,466 ----
      return true;
    }
  
+   virtual bool getResult(int column, *value, int size)
+   {
+     if (PQgetisnull(result_, row_, column))
+       return false;
+ 
+     const char *escaped = PQgetvalue(result_, row_, column);
+ 
+     std::size_t vlength;
+     unsigned char *v = PQunescapeBytea((unsigned char *)escaped, &vlength);
+ 
+     if (vlength < size)               // Or should this error ?
+       size = vlength;
+     memcpy(value, v, size);
+     PQfreemem(v);
+ 
+     DEBUG(std::cerr << this 
+         << " result blob " << column << " (blob, size = " << vlength << ")"
+         << std::endl);
+ 
+     return true;
+   }
+ 
    virtual std::string sql() const {
      return sql_;
    }

------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure 
contains a definitive record of customers, application performance, 
security threats, fraudulent activity, and more. Splunk takes this 
data and makes sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-novd2d
_______________________________________________
witty-interest mailing list
witty-interest@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/witty-interest

Reply via email to