Hi Oleg,

That's terrific - thanks very much for your response.

First off, the point you raised about setting many values at once; yes, I was aware of this, but a lot of the things we seem to want to do are more like we have a dict with strings for keys and associated values, and we want to write them into the db in one go, where the strings are the column names - is there's some way to do a myObject.set(), and pass in a dictionary? (or some python semantic that yields the same result?.. I'm not sure).

Okay, I completely understand the distinction between SQLObject and SQLBuilder now, and it makes perfect sense - thanks! Just by the way, is there any way to do transactions with SQLObject's?

Thanks again,
-Aaron.


On Fri, Jul 24, 2009 at 7:59 PM, Oleg Broytmann <phd@phd.pp.ru> wrote:
On Fri, Jul 24, 2009 at 12:31:02PM +1200, Aaron Robinson wrote:
> if I set the value of a blob column by setting a
> varialbe on my object, it gets written to the db just fine, but when I do it
> inside a transaction using sqlbuilder I have the error. Please see the code
> below.
>
> Test Code:
>
> from sqlobject import *
> from array import *
>
> sqlhub.processConnection = connectionForURI('postgres://user:pass@localhost
> /mydb')
>
> class MyObject(SQLObject):
>     myInt =  IntCol(default=42)
>     myBlob = BLOBCol(default=None)
>
> MyObject.createTable()
>
> #This works:
> myObject = MyObject()
> myObject.myInt = 43
> myObject.myBlob = array('H',range(256)).tostring()

  I hope you know you can set many values at once:
myObject.set(myInt=43, myBlob=array('H',range(256)).tostring())
  (That's offtopic, just a reminder.)

> #This doesn't work:
> record = {'my_int':44, 'my_blob':array('H',range(256)).tostring()}
> conn = sqlhub.getConnection()
> tx = conn.transaction()
> tx.query(conn.sqlrepr(sqlbuilder.Insert(MyObject, [record])))
> tx.commit()
>
> #psycopg2.DataError: invalid byte sequence for encoding "UTF8": 0x80
> #HINT:  This error can also happen if the byte sequence does not match the
> encoding expected by the server, which is controlled by "client_encoding".

  First, this has nothing with transactions. You can do conn.query() here.
Second, SQLBuilder... SQLObject is a high-level object that does a lot of
things internally, but SQLBuilder is a low-level interface that knows
nothing about classes, columns, column types, conversion; the first
parameters should be string (table name), the values must be converted to
the DB format; for a BLOB it means you have to use psycopg.Binary wrapper.
  This code works for my in Postgres and SQLite:

record = {'my_int':44, 'my_blob':conn.createBinary(array('H',range(256)).tostring())}
conn.query(conn.sqlrepr(sqlbuilder.Insert(MyObject.sqlmeta.table, [record])))

Oleg.
--
    Oleg Broytmann            http://phd.pp.ru/            phd@phd.pp.ru
          Programmers don't die, they just GOSUB without RETURN.